2

我有一个 python 套接字服务器,它侦听一个端口,并使用以下命令接受所有传入连接:

(conn, address) = socket.accept()

但是,我希望只接受来自特定 IP 地址的连接。

目前,如果地址未注册,我将关闭连接以完成此操作。

但是有没有更好的方法来做到这一点,直接拒绝来自未注册地址的连接,而不是接受连接然后关闭它们?

4

3 回答 3

7

无法指示拒绝来自某些 IP 地址的客户端的连接,也无法建立与来自其他 IP 地址的客户端的连接。这不是 Python 限制,而是较低级别的 BSD 套接字层限制。即使从 C 也无法做到这一点。

通常,您可以在 Python 中执行的最接近的行为是在连接被接受后快速关闭连接:

sock, addr = server_socket.accept()
if addr[0] != '12.34.56.78':
  sock.close()
  return
...

然后客户端会看到连接被接受,不久之后客户端会在读取它时看到 EOF,并且无法写入它。

但是,可以在绑定时通过接口(即网卡)进行限制,方法是使用以下之一:

server_socket.bind(('', 65432))  # Bind on any interface.
server_socket.bind(('127.0.0.1', 65432))  # Bind on loopback (localhost clients only).
server_socket.bind(('34.56.78.91', 65432))

因此,在127.0.0.1版本中,telnet 127.0.0.1 65432(作为客户端)可以工作,但telnet myhostname 65432会产生拒绝连接(并且server_socket.accept()调用不会获得此连接)。

于 2013-10-06T23:07:02.627 回答
1

如果您阅读文档,您可以找到BaseServer.verify_request(request, client_address)告诉您这一点的文档:

必须返回一个布尔值;如果值为 True,则处理请求,如果值为 False,则拒绝请求。可以重写此函数以实现对服务器的访问控制。默认实现总是返回 True。

于 2013-10-06T22:48:17.387 回答
0

Microsoft 似乎通过SO_CONDITIONAL_ACCEPT 套接字选项支持此功能

这似乎需要使用WSAAccept 来接受连接

这个常量没有出现在我的 windows 8 机器上的 pythons 套接字模块中。我认为没有通过 python 的内置套接字模块使用 WSAAccept 的选项。

如果我理解正确,这将允许您的服务器在配置为这样做时立即使用 RST 数据包响应 SYN 数据包,而不是完成握手和交换 FIN 数据包。请注意,使用此标志可以消除从操作系统处理连接的责任并将其放在应用程序上,因此有足够的空间发生错误和性能损失。如果提高性能是目标,那么它可能不值得追求

可以在 Windows 上的 C 级别进行。Python的ctypes模块允许与 C 代码进行交互,因此在技术上可以通过 python 接口来实现。但这可能需要不小的努力。如果你确定你需要这个特性,那么找到一个支持这个开箱即用的 C 套接字库可能会更省力,那么你可以为此制作一个 ctypes 包装器。

于 2015-06-13T23:19:52.787 回答