🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Question regarding UDP punchthrough.

Started by
4 comments, last by pindrought 5 years, 2 months ago

So I was thinking about setting up a basic UDP punchthrough system like so.

 

Server: Creates a socket and binds to a specific port that the clients will send messages to to either request to be a host or request host information.

Listens for client A to send packet requesting to host. Captures the port being used from the packet that was received. Stores this ip/port.

Listens for client B to send packet requesting host information. If the port/ip has been stored from client A, then the server will send the ip/port to client B.

 

Once client B receives the packet from the server about client A's ip and port combination being used, client B will begin transmitting packets to packet A and vice versa.

 

One thing I am confused about however - how can I make sure that the port will remain tied to client A on the router? (Same with client B - how do you ensure that the port will remain tied to that specific client on the LAN?) This part confuses me since bind is never called.

When a new socket is created using socket(), is a port at that point determined and somehow kept tied to that client on the LAN until the program ends?

 

Thanks

Advertisement
44 minutes ago, pindrought said:

Once client B receives the packet from the server about client A's ip and port combination being used, client B will begin transmitting packets to packet A and vice versa.

One thing I am confused about however - how can I make sure that the port will remain tied to client A on the router? (Same with client B - how do you ensure that the port will remain tied to that specific client on the LAN?) This part confuses me since bind is never called.

When a new socket is created using socket(), is a port at that point determined and somehow kept tied to that client on the LAN until the program ends?

Routers only see the actual packets sent, they don't know about `socket()` etc.

NAT works because the router remembers an outgoing packet for a while (TCP or UDP), so that when it gets an incoming packet it knows to forward it to the LAN client that sent the outbound one. If there is no traffic for a while, this mapping may be lost (can't recall the details, there is a timeout and maybe also a mapping count limit).

 

From memory:

  1. So say you have a client 10.1.1.2 on a LAN with public IP 1.2.3.4 and it wants to talk to a remote 5.6.7.8 port 5000.
  2. When the router sees a packet from 10.1.1.2:30000 being sent to 5.6.7.8:5000, it will record this in its local table.
  3. The router will change the packets source IP from 10.1.1.2 to 1.2.3.4
  4. The router may change the source port from 30000, say to 35000. This could happen if say 10.1.1.3 already sent a packet from 30000 to 5.6.7.8 port 5000, making 1.2.3.4:30000 not unique.
  5. The router then sends this modified packet onto the internet.
  6. The remote will get a packet from 1.2.3.4:35000 destined for 5.6.7.8:5000 and passes it to the application
  7. The application then knows it needs to send the reply (UDP, or next part of TCP connection) to 1.2.3.4:35000
  8. When the router gets a packet from 5.6.7.8:5000 destined to 1.2.3.4:35000, it remembers that in parts 2-5 that it previously sent that, and that the original address was 10.1.1.2:30000.
  9. The router sets the destination to 10.1.1.2:30000 then sends the packet on the LAN.

Part 8 has no way of magically knowing you called `socket()`, `bind()`, etc. on some LAN machine. It only knows that it previously sent a packet out to the internet.

Part 4 should be OK for TCP and UDP where the remote is either directly on a public IP or has a port forwarding rule (maybe using say UPnP). If not and it happens, I believe punch-through is impossible because the remote has no way to learn that it must send to 1.2.3.4:35000. You can timeout and try picking a different port to see if it was a conflict, if the router always re-maps the port, I believe you can't succeed with punch-through at both ends.

If the remote does not have such a rule, and 4 does not happen, you can punch-through by sending UDP packets in both directions, coordinated by a 3rd party server that is reachable. Because it is the act of sending a packet that added the NAT mapping, it makes receiving possible if the port number is known (30000 in this example).

3 minutes ago, SyncViews said:

NAT works because the router remembers an outgoing packet for a while (TCP or UDP), so that when it gets an incoming packet it knows to forward it to the LAN client that sent the outbound one. If there is no traffic for a while, this mapping may be lost (can't recall the details, there is a timeout and maybe also a mapping count limit).

Thanks for the reply. I was thinking this might be how it works.

Is there any trick to figuring out how often data must be transmitted to keep the port mapped with the lan client?

I am not sure if there is a documented standard for UDP. I saw some indications from Cisco that it is 5 minutes by default, but is user configurable (maybe not configurable on your average home router however). If with UDP your not naturally sending data very often, you can send a keepalive packet (that is, a normal UDP packet but with no actual data content) periodically just to keep it running.

TCP is much longer and the routers can track the connection state, IIRC Windows doesn't try to send a keepalive for a couple of hours and Cisco documents 24 hours since the last packet (between the handshake and a FIN "finish" packet).

 

1 minute ago, SyncViews said:

I am not sure if there is a documented standard for UDP. I saw some indications from Cisco that it is 5 minutes by default, but is user configurable (maybe not configurable on your average home router however). If with UDP your not naturally sending data very often, you can send a keepalive packet (that is, a normal UDP packet but with no actual data content) periodically just to keep it running.

TCP is much longer and the routers can track the connection state, IIRC Windows doesn't try to send a keepalive for a couple of hours and Cisco documents 24 hours since the last packet (between the handshake and a FIN "finish" packet).

 

Thanks a lot this is really helpful to me. I appreciate the info.

This topic is closed to new replies.

Advertisement