【问题标题】:Python socket server : Reject connection from addressPython套接字服务器:拒绝来自地址的连接
【发布时间】:2013-10-13 10:03:43
【问题描述】:

我有一个 python 套接字服务器,它监听一个端口,并接受所有传入的连接:

(conn, address) = socket.accept()

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

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

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

【问题讨论】:

    标签: python sockets networking


    【解决方案1】:

    无法向某些 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 会产生 Connection denied(以及 server_socket.accept()调用不会获得此连接)。

    【讨论】:

    • 使用 sock.close() 是有效的,但是当它被调用时它突然开始崩溃。出了什么问题?
    【解决方案2】:

    如果您阅读docs,您会发现BaseServer.verify_request(request, client_address) 告诉您:

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

    【讨论】:

    • 我需要一个比 socketserver 更原生的实现来进行分配。使用socket模块可以做到这一点吗?
    • 嗯,不,你必须接收传入的连接,但这并没有太多的开销。我认为您所做的符合直接拒绝传入连接的条件。您尚未开始发送或接收任何数据。而且我在文档中找不到任何支持您想要的东西。
    【解决方案3】:

    微软似乎通过SO_CONDITIONAL_ACCEPT socket option 支持此功能

    这似乎需要使用WSAAccept to accept connections

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-19
      • 2011-12-12
      • 2016-06-24
      • 2016-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      相关资源
      最近更新 更多