SS-LT

SS-LT

执行摘要。

当我尝试通过 Python 中的套接字进行通信时,我收到“连接被拒绝 111”的错误信息。当连接被拒绝时,侦听器将停止侦听。使用 multiprocessing.connection、socket、zeromq 的导入时也会出现同样的问题。

我的感觉是 Python 和 OS/网络​​之间的链接不起作用。但是在 ubuntu 终端中发出的 NC 和套接字命令可以通过同一端口进行通信。

尽管这给我带来了不便,但如果无效的连接请求导致套接字停止监听,显然存在严重的安全风险。非常适合拒绝服务攻击。

证据:

我有两个程序:

t2.py

from multiprocessing.connection import Listener
def main():
    listener = Listener(('192.168.1.100', 16001), authkey=b'password')
    print ("listener ready", listener)
    running = True
    while running :
        print ("ready to connect")
        conn = listener.accept()
        print('connection accepted from', listener.last_accepted)
        
if __name__ == "__main__":
   main()

t1.py

from multiprocessing.connection import Client
def main():
   
    address = ('192.168.1.100', 16001)            
    conn = Client(address, authkey = b'password')        
if __name__ == "__main__":
   main()

当我启动监听器(IDLE 中按 f5)时,它似乎启动正常。

>>> 
==================== RESTART: /home/william/Midas/api/t2.py ====================
 listener ready <multiprocessing.connection.Listener object at 0x7fccdd472130> 

ready to connect

并且套接字开始监听:

SS-LT

状态 Recv-Q Send-Q 本地地址:端口 对等地址:端口 进程

收听 0 1 192.168.1.100:16001 0.0.0.0:*

但是,当我启动客户端(IDLE 中的 f5)时,我收到以下信息:

    Traceback (most recent call last):   File "/home/william/Midas/api/t1.py", line 25, in <module>
        main()   File "/home/william/Midas/api/t1.py", line 15, in main    
        conn = Client(address, authkey = b'password')   File "/usr/lib/python3.8/multiprocessing/connection.py", line 502, in Client    
c = SocketClient(address)   File "/usr/lib/python3.8/multiprocessing/connection.py", line 630, in SocketClient

s.connect(address) ConnectionRefusedError: [Errno 111] Connection refused

并且监听套接字消失。

SS-LT

状态 Recv-Q Send-Q 本地地址:端口 对等地址:端口 进程

侦听 0 5 127.0.0.1:ipp 0.0.0.0:* 侦听 0 1 127.0.0.1:36093
0.0.0.0:*
侦听 0 5 [::1]:ipp [::]:*

我尝试过更改端口号、设置 FW 规则、将 IP 地址从硬编码为“localhost”...远程客户端(在 Windows 上)等等。尽管症状各不相同,但都不起作用。

我尝试使用“套接字导入”对连接进行编程,并得到完全相同的结果。zeromq 也不起作用。

但是在终端中发出的 NC 和套接字命令可以通过同一个端口进行通信。

fwiw 我正在运行 Ubuntu 20.04.2 LTS。除了我在 Windows 上尝试的一个客户端外,所有测试都在单个 Ubuntu 系统上完成。这是一个相当新的安装,所以我不太可能破坏了某些东西。

请问有人能告诉我我做错了什么吗?

我的感觉是 Python 和操作系统/网络之间的链接不起作用。

尽管这给我带来了不便,但如果无效的连接请求导致套接字停止监听,显然存在严重的安全风险。非常适合拒绝服务攻击。

答案1

我无法重现您的问题,因此不确定问题是什么。但是,有一些评论。

我在你的代码中添加了一个简单的乒乓交换:

# t2.py

from multiprocessing.connection import Listener

listener = Listener(('127.0.5.1', 16001), authkey=b'password')
print ("listener ready", listener)
running = True
while running :
    print ("ready to connect")
    conn = listener.accept()
    print('connection accepted from', listener.last_accepted)
    msg = conn.recv()
    print(f"received: {msg}")
    conn.send(b"PONG")
# t1.py

from multiprocessing.connection import Client
address = ('127.0.5.1', 16001)            
conn = Client(address, authkey = b'password')        
conn.send(b"PING")
print(conn.recv())

并且将监听地址更改为来自链路本地子网的地址127.0.0.0/8

然后只需使用 2 个终端选项卡/窗口,运行t2.py3t1.py次:

$ python t2.py
listener ready <multiprocessing.connection.Listener object at 0x7fb115c18a00>
ready to connect
connection accepted from ('127.0.0.1', 36702)
received: b'PING'
ready to connect
connection accepted from ('127.0.0.1', 36704)
received: b'PING'
ready to connect
connection accepted from ('127.0.0.1', 36706)
received: b'PING'
ready to connect

服务器进程继续运行,正如预期的那样。客户端选项卡:

$ python t1.py
b'PONG'
$ python t1.py
b'PONG'
$ python t1.py
b'PONG'

请注意...您可能认为您提到的这些东西是相同的——但它们却有很大不同:

多处理.连接,套接字,zeromq。

python 内置进口插座模块是经典 BSD 套接字 API 的直接翻译。“套接字 API”定义了以下内容:端口、监听端口、连接端口、接受连接、、sendrecv其他close一些函数。一本关于网络编程的书可能会有所帮助(例如,这本书是随机示例— 我不赞同它。套接字 API 已经有近 40 年的历史了,所以你也可以很容易地在网上找到免费的学习资料。

下一个,导入多处理模块。这是一个完全不同的故事。它为多进程Python 程序。它们会创建多个 PID,并可在多个处理器核心上运行。几乎可以肯定的是,您会希望这些进程相互通信以完成有用的工作。这就是套接字派上用场的地方:由于进程彼此被操作系统隔离,因此网络提供了一种建立该通信的方法(即使它仅限于本地主机)。子模块多处理.连接为此提供了符合人体工程学的助手。

下一个,ØMQ完全是一个独立的项目(它不是 python 内置的;也不是 python 特有的)。它做了一些有趣的事情;它重新定义另一个“套接字 API”。ØMQ 套接字≠ BSD 套接字。Zeromq 套接字可以执行 BSD 套接字无法执行的操作(发布/订阅、扇出、应用程序级路由)。Zeromq 套接字构建于 BSD 套接字“之上”;如果您在使用较低级别的 API 时遇到麻烦,我建议您在熟悉基本套接字后再使用 ZMQ。

尽管症状各异,但都不起作用。

再次,您应该熟悉解释网络故障模式。出现的错误代码具有明确定义的含义。例如,经典的Connection refusederrno 111 表示初始SYN 数据包向主机connect()发送的响应是 RST 数据包,而不是正常的 SYN+ACK——这通常在没有程序监听给定端口时发生在远程计算机connect()

关于你的安全问题,还有一点需要说明。你应该始终假设网络是敌对的(敌意的),无论当时和空间上是否确实如此——甚至是本地主机网络。这就是为什么更高级别的多处理 API 具有该authkey参数的原因;它实际上总是需要的。password字节串是可以想象的最差值之一authkey,请尝试更好的值。理论上,活跃的网络对手可以解释您的问题;有一种称为“RST 注入攻击”的东西。您可能已经用尽了监听积压/SOMAXCONN。

最后,Wireshark 是一款很棒的工具。

相关内容