几天来,我一直在研究“洞穴打洞”,希望获得一些可靠的行为,但是现在我已经陷入了死胡同。
UDP洞穴打洞效果很好:首先向远程发送一个数据包,然后让远程发送数据包另一侧,因为它将通过源NAT传输。从我试过的情况来看,这相当可靠。
但是现在来了TCP……我不明白。
目前为止,我只能通过连接套接字与 NAT 建立联系。
但是现在,用于连接的两个发送SYN数据包的套接字已经连接成功。
你可能会认为我已经做到了,通过2个NAT获得了连接,太棒了。
但问题在于,这不是正常的行为,根据这篇论文:http://www.brynosaurus.com/pub/net/p2pnat/,我应该能够同时拥有一个监听套接字和一个连接套接字。
因此,我绑定了一个监听套接字,可以接受传入的连接。
但是传入的连接始终被连接套接字捕获,而不是监听套接字... 例如:
现在有了这个脚本,只需与朋友或其他人商定一个端口,并在一端执行它,
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 [...]
,根据某些讲座,这不应该发生。