Geo*_*ard 7 python sockets tcp hole-punching
我试图使用本文中概述的原理为Python 3中的防火墙编写基本的TCP打孔器.但是我无法连接任何东西.这是代码:
#!/usr/bin/python3
import sys
import socket
import _thread as thread
def client():
c = socket.socket()
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
c.bind((socket.gethostbyname(socket.gethostname()), int(sys.argv[3])))
while(c.connect_ex((sys.argv[1], int(sys.argv[2])))):
pass
print("connected!")
thread.interrupt_main()
def server():
c = socket.socket()
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
c.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
c.bind((socket.gethostbyname(socket.gethostname()), int(sys.argv[3])))
c.listen(5)
c.accept()
print("connected!")
thread.interrupt_main()
def main():
thread.start_new_thread(client, ())
thread.start_new_thread(server, ())
while True:
pass
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
我决定在我的本地计算机上尝试打孔器,这样我就可以捕获两个实例发送的所有流量.我首先建立了一个环回防火墙:
iptables -A INPUT -i lo -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j DROP
Run Code Online (Sandbox Code Playgroud)
然后我发布了两个脚本副本:
left$ ./tcphole.py localhost 20012 20011
Run Code Online (Sandbox Code Playgroud)
和
right$ ./tcphole.py localhost 20011 20012
Run Code Online (Sandbox Code Playgroud)
根据Wireshark的说法,我可以看到SYN数据包是双向传输的:

但没有任何东西打印"连接!" 我究竟做错了什么?
结果证明答案非常简单:如果数据包RELATED没有到达相同的 IP 地址,则不会考虑这些数据包!
将bind行更改为
c.bind('', int(sys.argv[3])))
Run Code Online (Sandbox Code Playgroud)
(''绑定到环回地址)完全解决了这个问题。