Python TCP打孔(旁路监听插座)

Python TCP打孔(旁路监听插座),python,sockets,tcp,udp,hole-punching,Python,Sockets,Tcp,Udp,Hole Punching,我已经有几天没有在打孔了,为了有可靠的行为,但我现在已经走到了死胡同 UDP打孔非常有效:只需先向远程发送数据包,然后让远程发送数据包,因为它将通过源NAT到达。从我的尝试来看,它相当可靠 但是现在是TCP。。。我不明白 现在,我可以通过NAT建立连接,但是只能通过连接插座建立连接: A.connect(B)->在B的NAT上崩溃,但在A的NAT上打开一个洞。 连接(A)->进入A的NAT孔,到达A的连接插座。 但现在,发送SYN数据包进行连接的两个套接字已连接 你会认为我会这么做,通过2个N

我已经有几天没有在打孔了,为了有可靠的行为,但我现在已经走到了死胡同

UDP打孔非常有效:只需先向远程发送数据包,然后让远程发送数据包,因为它将通过源NAT到达。从我的尝试来看,它相当可靠

但是现在是TCP。。。我不明白

现在,我可以通过NAT建立连接,但是只能通过连接插座建立连接

A.connect(B)->在B的NAT上崩溃,但在A的NAT上打开一个洞。
连接(A)->进入A的NAT孔,到达A的连接插座。
但现在,发送SYN数据包进行连接的两个套接字已连接

你会认为我会这么做,通过2个NAT获得连接,万岁

但问题是,这不是一种正常的行为,鉴于本文:,我应该能够有一个与连接套接字并行的侦听套接字

所以我绑定了一个监听套接字,它接受入站连接

但是入站连接总是被连接套接字捕获,而不是被侦听套接字捕获…

e、 g:

#/usr/bin/env蟒蛇3
从套接字导入*
从线程导入线程
插座
#使用的端点:
本地='0.0.0.0',7000
远程='REMOTE',7000
#创建侦听套接字,将其绑定并使其侦听:
侦听=套接字(AF_INET、SOCK_STREAM)
Listening.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
正在侦听。绑定(本地)
听,听(5)
#只需在另一个线程中启动某种调试:
#打印任何连接客户端的地址:
def handle():
不在收听时。\u关闭:
client,addr=Listening.accept()
打印('已接受',地址)
线程(目标=句柄).start()
#现在创建连接套接字:
连接=插座(AF_INET,SOCK_STREAM)
Connecting.setsockopt(SOL_插座,SO_REUSEADDR,1)
连接.绑定(本地)
#现在我们可以尝试连接:
尝试:
连接。连接(远程)
打印('CONNECTED',Connecting.getpeername())
例外情况除外,如e:
打印('trued',键入(e),e)
现在使用此脚本,只需与朋友或其他人商定一个端口,并在一端执行它,
Connecting.connect(…)
应该运行一段时间(等待超时,因为SYN数据包撞到了远处的NAT,但幸运的是在自己的NAT上打开了一个洞),同时在另一端执行脚本,现在,
Connecting.connect(…)
将返回,因为它已连接

最奇怪的是:
监听
套接字从未触发过

为什么??如何让侦听套接字通过连接套接字捕获入站连接

注意:关闭连接插座确实会在网络上发送一些信息,这些信息会立即关闭该孔,至少在我的网络上是这样

第二个注意:我在windows上


编辑:主要问题是,在任何情况下,此脚本都会输出连接[…]的

我想答案就在这里。TCP连接由四个元素组成的元组定义:

  • 本地地址
  • 本地港口
  • 远程地址
  • 远程端口
当您建立TCP连接时,您将创建从此元组到本地主机上的连接套接字的绑定

通过NAT发送SYN时,会创建绑定: -本地地址/端口->公共地址/端口

当远程端将其SYN发送到公共地址/端口时,该地址将被转换为本地地址/端口并发送到本地计算机。在此计算机上,此连接与初始连接无法区分,并且已成功建立(使用SYN/ACK)

这意味着本地端没有接收到初始SYN

如何让侦听套接字通过连接套接字捕获入站连接?


使用源NAT是不可能的。要接受NAT背后的新连接,您需要目标NAT将一些公共IP/端口映射到您的私有IP/端口

因此,在进行了更多测试和阅读后,我得出以下结论:

事实上,可以将侦听套接字和在同一地址(ip、端口)上进行出站连接的套接字绑定在一起

但套接字的行为严重依赖于系统/TCP堆栈的实现,如§4.3所述:

客户端应用程序在TCP打孔过程中观察到的套接字情况取决于所涉及的时间和TCP实现。假设AB的公共端点的第一个出站SYN数据包被NATB丢弃,但是BA的公共端点的第一个后续SYN数据包在A的TCP重新传输其SYN之前到达A。根据所涉及的操作系统,可能会发生以下两种情况之一:

  • A的TCP实现注意到传入SYN的会话终结点与出站会话的会话终结点匹配A正在尝试启动<因此,strong>A的TCP堆栈将此新会话与A上的本地应用程序用于连接()到B的公共端点的套接字相关联。应用程序的异步connect()调用成功,应用程序的侦听套接字不会发生任何变化。
    由于接收到的SYN数据包不包括A先前出站SYN的ACK,A的TCP使用SYN-ACK数据包回复B的公共端点,SYN部分仅仅是A原始出站SYN的重播,使用相同的se