I've tried to write a basic TCP hole puncher for a firewall in Python 3 using the principles outlined in this article. I'm having trouble getting anything to connect, though. Here is the code:
#!/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()
I decided to try the puncher on my local machine, so that I could capture all the traffic sent by both instances. I first set up a loopback firewall:
iptables -A INPUT -i lo -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i lo -j DROP
Then I launched two copies of the script:
left$ ./tcphole.py localhost 20012 20011
and
right$ ./tcphole.py localhost 20011 20012
I can see according to Wireshark that the SYN packets are being transmitted both ways:
But nothing ever prints "connected!" What am I doing wrong?
One of the most effective methods of establishing peer-to-peer communication between hosts on different private networks is known as “hole punching.” This technique is widely used already in UDP-based applications, but essentially the same technique also works for TCP.
Skype uses the UDP hole punching technique to allow communication between users who are behind NAT.
The basic story of a NAT Hole Punch is that, when both the Nodes who want to connect to each other send a message to the server. Server responds to both nodes with each other's IP address and Ports (Endpoints).
Hole punching (or sometimes punch-through) is a technique in computer networking for establishing a direct connection between two parties in which one or both are behind firewalls or behind routers that use network address translation (NAT).
The answer turned out to be quite simple: packets aren't considered RELATED
if they aren't coming to the same IP address!
Changing the bind
lines to
c.bind('', int(sys.argv[3])))
(the ''
binds to the loopback address) fixes the problem entirely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With