执行摘要。
当我尝试通过 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.py
3t1.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”定义了以下内容:端口、监听端口、连接端口、接受连接、、send
和recv
其他close
一些函数。一本关于网络编程的书可能会有所帮助(例如,这本书是随机示例— 我不赞同它。套接字 API 已经有近 40 年的历史了,所以你也可以很容易地在网上找到免费的学习资料。
下一个,导入多处理模块。这是一个完全不同的故事。它为多进程Python 程序。它们会创建多个 PID,并可在多个处理器核心上运行。几乎可以肯定的是,您会希望这些进程相互通信以完成有用的工作。这就是套接字派上用场的地方:由于进程彼此被操作系统隔离,因此网络提供了一种建立该通信的方法(即使它仅限于本地主机)。子模块多处理.连接为此提供了符合人体工程学的助手。
下一个,ØMQ完全是一个独立的项目(它不是 python 内置的;也不是 python 特有的)。它做了一些有趣的事情;它重新定义另一个“套接字 API”。ØMQ 套接字≠ BSD 套接字。Zeromq 套接字可以执行 BSD 套接字无法执行的操作(发布/订阅、扇出、应用程序级路由)。Zeromq 套接字构建于 BSD 套接字“之上”;如果您在使用较低级别的 API 时遇到麻烦,我建议您在熟悉基本套接字后再使用 ZMQ。
尽管症状各异,但都不起作用。
再次,您应该熟悉解释网络故障模式。出现的错误代码具有明确定义的含义。例如,经典的Connection refused
errno 111 表示初始SYN 数据包向主机connect()
发送的响应是 RST 数据包,而不是正常的 SYN+ACK——这通常在没有程序监听给定端口时发生在远程计算机connect()
上。
关于你的安全问题,还有一点需要说明。你应该始终假设网络是敌对的(敌意的),无论当时和空间上是否确实如此——甚至是本地主机网络。这就是为什么更高级别的多处理 API 具有该authkey
参数的原因;它实际上总是需要的。password
字节串是可以想象的最差值之一authkey
,请尝试更好的值。理论上,活跃的网络对手可以解释您的问题;有一种称为“RST 注入攻击”的东西。您可能已经用尽了监听积压/SOMAXCONN。
最后,Wireshark 是一款很棒的工具。