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:
- 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.
- 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.
- The router will change the packets source IP from 10.1.1.2 to 1.2.3.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.
- The router then sends this modified packet onto the internet.
- 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
- The application then knows it needs to send the reply (UDP, or next part of TCP connection) to 1.2.3.4:35000
- 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.
- 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).