【发布时间】:2017-10-16 04:44:51
【问题描述】:
自从我为了获得某种可靠的行为而玩打孔以来已经有几天了,但我现在处于死胡同。
UDP 打孔效果很好:只需先向远程发送一个数据包,然后让远程发送一个数据包,因为它将通过源 NAT 登陆。从我的尝试来看,它相当可靠。
但现在是 TCP……我不明白。
现在,我可以通过 NAT 建立连接,但只能使用连接套接字:
A.connect(B) -> Crash agains't B's NAT, but open a hole in A's NAT.
B.connect(A) -> Get in A's NAT hole, reach A's connecting socket.
但是现在,发送 SYN 数据包进行连接的两个套接字已经连接了。
你会认为我会这样做,通过 2 个 NAT 建立连接,万岁。
但问题是这不是一种正常的行为,给这篇论文:http://www.brynosaurus.com/pub/net/p2pnat/,我应该能够有一个与连接套接字并行的监听套接字。
所以我确实绑定了一个监听套接字,它可以接受入站连接。
但是入站连接总是被连接的套接字捕获,而不是被监听的……
例如:
#!/usr/bin/env python3
from socket import *
from threading import Thread
Socket = socket
# The used endpoints:
LOCAL = '0.0.0.0', 7000
REMOTE = 'remote', 7000
# Create the listening socket, bind it and make it listen:
Listening = Socket(AF_INET, SOCK_STREAM)
Listening.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
Listening.bind(LOCAL)
Listening.listen(5)
# Just start in another thread some kind of debug:
# Print the addr of any connecting client:
def handle():
while not Listening._closed:
client, addr = Listening.accept()
print('ACCEPTED', addr)
Thread(target=handle).start()
# Now creating the connecting socket:
Connecting = Socket(AF_INET, SOCK_STREAM)
Connecting.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
Connecting.bind(LOCAL)
# Now we can attempt a connection:
try:
Connecting.connect(REMOTE)
print('CONNECTED', Connecting.getpeername())
except Exception as e:
print('TRIED', type(e), e)
现在有了这个脚本,只需与朋友或其他什么的端口达成一致,并在一端执行它,Connecting.connect(...) 应该运行一段时间(等待超时,因为 SYN 数据包崩溃到远程 NAT,但是幸好自己的NAT开了个洞),同时在另一端执行脚本,现在Connecting.connect(...)会返回,因为它已经连接了。
最奇怪的部分是:Listening 套接字从未被触发。
为什么?如何让监听套接字通过连接套接字捕获入站连接?
注意:关闭连接套接字确实会在网络上发送一些立即关闭漏洞的东西,至少在我的网络上是这样。
第二个注意:我在 windows 上。
编辑:主要问题是在任何情况下,这个脚本输出CONNECTED [...]而不是CLIENT [...],这不应该发生一些讲座。
【问题讨论】:
-
您是否尝试过在侦听端捕获数据包?您在那里看到来自远程端的 SYN 请求吗?
-
是的,正如我所说,两边(远程/本地)的两个套接字都建立了连接,但不是在
Listening套接字上...
标签: python sockets tcp udp hole-punching