6 ms·
It's not the NAT part on the easy side, it's the firewall on the easy side that needs to be open. Even if the easy side knows (through STUN) that its public ad
by fred256 6y ago
It's not the NAT part on the easy side, it's the firewall on the easy side that needs to be open.
Even if the easy side knows (through STUN) that its public address is 2.2.2.2:1234, that doesn't mean it'll accept any packets addressed to 2.2.2.2:1234.
For it to accept packets from e.g. 5.5.5.5:7890, it first needs to send a packet there, to create the connection table entry in the firewall.
But... it doesn't know what port 5.5.5.5 is going to be sending from (since that's the whole point of 5.5.5.5 having a "hard", i.e., destination-dependent-mapping, NAT), so it can't preemptively send a packet to open the firewall.
At least, this is my understanding.
- xg15 6y agoThat was my understanding as well. What I got was that "hard" NAT is hard because neither peer is able to obtain the hard NAT's public IP/Port pair: The peer behind the hard NAT can't ask a STUN server because that server would see a different pair while peer behind the easy NAT can't receive any packets. I think it's interesting that the peer behind the hard NAT could actually produce a packet that would contain all necessary information by sending something to the easy NAT's address - but neither peer could access this packet. You'd have to call the NSA to monitor the packet in-flight... I wonder if you could somehow fiddle with the max-hop header to have the packet be sent back to the hard NAT's peer though, sort of like traceroute works.
- dave_universetf 6y agoYou're on the right lines, yeah. On the wire, out on the internet, there is a packet with all the information we need to get through the easy/hard pair, but we can't access it. According to the author of dublin-traceroute, it used to be that you could use ICMP TTL Exceeded errors to your advantage, because buggy NATs didn't translate ICMP payload (which contains the IP+UDP header of the packet whose TTL hit zero). IOW, you could send a probe packet to the easy ip:port, with a TTL low enough that the packet expires somewhere between the two NATs, and listen for the returning ICMP error. Its payload would contain the public ip:port for your session on the hard NAT, which effectively gives you an accidental STUN server that gives you correct answers, even for a hard NAT. I _believe_ this trick no longer works reliably, because the "NAT Behavioral Requirements" family of RFCs started laying down rules for what well-behaved NATs should do, and afaict, inexplicably, vendors listened. REQ-4 of RFC 5508 says that NAT devices MUST translate the payload of ICMP errors according to the appropriate NAT mapping, to preserve the end device's illusion that no NAT exists. So, these days, the ICMP error you get back contains the unhelpful LAN source ip:port :( I still want to experiment with that some more, because if it's unusual but not unheard of... Well, it's another technique to grab a little bit more of the long tail :)
- iforgotpassword 6y ago> and afaict, inexplicably, vendors listened That got a good laugh out of me. That idea sounds really clever, but even if NATs wouldn't mangle the ICMP reply, don't you need elevated privileges to receive it in your application? And I wouldn't be too surprised if a bunch of devices would just drop it entirely. Another thing that just came to my mind: Do any of those hard NATs assign the outgoing port in a predictable pattern for some inexplicable reason? I'd guess no, since those already seem to be security focused and not randomizing the port sounds stupid, but you never know... Would be a cool last resort for hard/hard.
- dave_universetf 6y ago"it depends". There used to be NATs that did linear allocation or some other weird schemes (e.g. linear, but matching the lower bit of the WAN port to the LAN port, for reasons to do with SIP weirdness). These days, due to the misguided narrative that NATs are security devices, random port selection dominates. Certainly it does in linux (which accounts for most home routers), and all the commercial vendors (Juniper, Cisco, etc.). Some of the latter might let you configure it if you have esoteric needs, I haven't dug into that. Tailscale just assumes that port allocation is random.
- dave_universetf 6y agoAuthor here. You are correct, the challenge in an easy/hard pair is the stateful firewall built into the easy side. Even thought the _NAT_ is easy (we can discover our public ip:port), the firewall still wants to see transmissions to/from the correct ip:port on the hard side in order to let the traffic through. The hard side defeats that by not letting us discover what the correct ip:port should be, so we can't punch through the firewall component. So, we're left with two options: make one of the NATs vanish via the port-mapping protocols, or use the birthday paradox to find a usable ip:port in reasonable time.
- iforgotpassword 6y agoThanks to both of you. So it would only work the way I assumed if the easy one is that full cone type that doesn't have a firewall at all.
- dave_universetf 6y agoYup, exactly right. In the article, I tried to call those "trivial" NATs, because from a NAT traversal POV they might as well not exist. You do need to do a tiny bit of work to get them up and running, but once that's done, you effectively have an open port on the internet that anyone can connect to.