Hacker News new | ask | show | jobs
by mjg59 1617 days ago
When you connect to a remote machine, you send traffic to a specific port on that remote machine but also from a specific port on your machine. The remote port would probably be well-known (eg, port 80 on TCP is the well known port for HTTP), but the local port would be chosen from a random range of available ports. As a result, every connection could be described based on a combination of parameters - the local IP, the remote IP, the local port and the remote port.

But these days most users don't connect to remote servers directly. Instead, they're on a local network that connects through a router that only has a single world-routable IPv4 address. That means that while the combination of local and remote IPs and ports is still nominally a unique identifier, the local IP could now refer to multiple different devices. NAT handles this by keeping track of which machine behind the NAT triggered a local connection, mapping its local port to a local port on the publicly routable IP, and then rewriting traffic and forwarding it appropriately so this is mostly invisible (eg, you send traffic to 142.250.189.174 on port 80, and your local port is 31337. Someone else on your network may also be using port 31337 to talk to port 80 on 142.250.189.174, so your NAT router rewrites your local port to 31338. When it sees incoming traffic on port 31338 from 142.250.189.174, it rewrites the packet to be sent to you and as far as you're concerned you're directly communicating with 142.250.189.174)

This basically works fine for TCP, because TCP requires you to explicitly make a connection. That means the NAT router can tie the combination of a remote host and a local port to a unique mapping to an internal machine. But UDP is, at the transport layer, stateless - when you send traffic to a remote machine over UDP, the expectation is that that remote machine can just send traffic back to the same UDP port at some arbitrary point in the future and, if the local client is still listening, that'll got through.

If you port-forward literally every UDP port to a specific device, when another local device tries to connect to an external service over UDP, your router will probably be confused - it can't just say "Ok, you connected to something over UDP, I rewrote your local port to 31337, traffic to 31337 will be sent to you", because 31337 is already configured to be forwarded to the Switch. You can potentially send traffic to a remote service, but the responses may be forwarded to the wrong device.

In theory you could say that because a machine with a specific internal IP sent traffic to a specific remote IP and you rewrote that to a specific port, any traffic from that remote IP to that port should be forwarded to that internal IP even if there's a general port forwarding rule that would instead forward it to the Switch. I have no idea whether that's how routers behave, and it's far too late for me to dig into the kernel source to check that (I've spent the evening fighting Linux's in-kernel ASN1 parser, I'm not inclined to do more)