Jump to content
  • Advertisement
pindrought

Question regarding UDP punchthrough.

Recommended Posts

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

Share this post


Link to post
Share on other sites
Advertisement
Posted (edited)
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).

Edited by SyncViews

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites

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).

 

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!