TCP Hole Punching
Solution 1
A start 2 threads:
One thread tries connecting to B's router with the info sent by S
The other thread is waiting for an incoming connection on the same port used to connect to its router when it connected to S
You can't do this with two threads, since it's just one operation. Every TCP connection that is making an outbound connection is also waiting for an incoming connection. You simply call 'connect', and you are both sending outbound SYNs to make a connection and waiting for inbound SYNs to make a connection.
You may, however, need to close your connection to the server. Your platform likely doesn't permit you to make a TCP connection from a port when you already have an established connection from that same port. So just as you start TCP hole punching, close the connection to the server. Bind a new TCP socket to that same port, and call connect
.
Solution 2
A simple solution to traverse into NAT routers is to make your traffic follow a protocol that your NAT already has an algorithm for forwarding, such as FTP.
Related videos on Youtube
Comments
-
Giann almost 2 years
I'm trying to implement TCP hole punching with windows socket using mingw toolchain. I think the process is right but the hole doesn't seems to take. I used this as reference.
- A and B connect to the server S
- S sends to A, B's router IP + the port it used to connect to S
- S does the same for B
-
A start 2 threads:
- One thread tries connecting to B's router with the info sent by S
- The other thread is waiting for an incoming connection on the same port used to connect to its router when it connected to S
- B does the same
I have no issue in the code I think since:
- A and B does get each other ip and port to use
- They are both listening on the port they used to connect to their router when they contacted the server
- They are both connecting to the right ip and port but get timed out (code error
10060
)
I am missing something ?
EDIT: With the help of process explorer, I see that one of the client managed to establish a connection to the peer. But the peer doesn't seems to consider the connection to be made.
Here is what I captured with Wireshark. For the sake of the example, the server S and the client A are on the same PC. The server S listens on a specific port (
8060
) redirected to that PC. B still tries to connect on the right IP because it sees that the public address of A sent by S islocalhost
and therefore uses the public IP of S instead. (I have replaced the public IPs by placeholders)EDIT 2: I think the confusion is due to the fact that both incoming and outcoming connection request data are transfered on the same port. Which seems to mess up the connection state because we don't know which socket will get the data from the port. If I quote msdn:
The
SO_REUSEADDR
socket option allows a socket to forcibly bind to a port in use by another socket. The second socket calls setsockopt with the optname parameter set toSO_REUSEADDR
and the optval parameter set to a boolean value ofTRUE
before calling bind on the same port as the original socket. Once the second socket has successfully bound, the behavior for all sockets bound to that port is indeterminate.But talking on the same port is required by the TCP Hole Punching technique to open up the holes !
-
George Hilliard about 10 years@Giann ah shame. I wrote one and it seems to work fairly well.
-
Giann over 12 yearsI don't understand why I have to use sets for the sockets. What does it change ?
-
Vikram Ranabhatt over 12 yearsIt will notify if something is available on that socket.We have to repeatedly check if something is available on particular socket.
-
Vikram Ranabhatt over 12 yearsWSAETIMEDOUT ....Ensure your In the NAT setting Out going TCP traffic is allowed for all port.
-
Allen over 12 yearscould you add a network layout for your S, A and B and router, I suspect that since you have S and A on the same machine, so your NAT router did not even have a NAT translation in the router for B to reach A since A do not have a connection to S through router(they are on the same machine!). for proper testing, you should place your S not at the same LAN as A or B.
-
Giann over 12 yearsThat worked, but only if both
SYN
do not reach either peer before they both passes theire respective NAT/Router. So there is a little timing issue. That's Simultaneous TCP Open. But bford.info/pub/net/p2pnat/index.html talks about a simultaneous listening socket in the event of one failing connection request. I never saw that work. -
David Schwartz over 12 yearsIf it fails, you might (cross fingers) be able to retry immediately and still have it work. But you cannot rely on TCP hole punching working.
-
Giann over 12 yearsDo you know of an other reliable way of establishing peer to peer connection behind different NATs/Routers ?
-
Giann over 12 yearsUnfortunately TCP is a requirement for me.
-
David Schwartz over 12 years@Giann Then use a TCP connection to the endpoint of your UDP hole.
TCP <-> UDP <-> NAT <-> Internet <-> NAT <-> UDP <-> TCP
-
Summer_More_More_Tea about 11 yearsI'm new to the TCP hole punching topic and not quite clear at this point
just as you start TCP hole punching, close the connection to the server. Bind a new TCP socket to that same port
. Must I bind a new TCP socket to the port connecting to server? Isn't an unbound socket allocated another NAT address? So I think it's not necessary to bind the socket used to connect server B. Am I right or any misunderstanding? Thanks. -
David Schwartz about 11 yearsIf the socket gets another NAT address, it won't be able to take advantage of the hole you punched.