← Back to context

Comment by lxgr

14 hours ago

Does TCP hole punching actually work with common CPEs and CG-NATs?

I don’t think I’ve ever seen it done successfully and have often wondered if it’s for a lack of use cases or due to its bad success rate and complexity compared to UDP hole punching.

That said, I really wish there was a standardized way to do it. Some sort of explicit (or at least implicit but unambiguous) indicator to all firewalls that a connection from a given host/port pair is desired for the next few seconds. Basically a lightweight, in-band port mapping protocol.

It could have well been an official recommendation to facilitate TCP hole punching, but I guess it’s too late now, as firewall behaviors have had decades to evolve into different directions.

The standard way to do it is called ipv6. Implementing it is probably easier than any of those RFCs

  • No, it isn't. Many middleboxes (including OpenWrt by default) drop unsolicited inbound TCP connections even on IPv6, and therefore the same hole-punching algorithm is needed. The hole being punched is in the stateful firewall's connection tracker, not in the NAT. Basically, both parties need to convince their router that it is an outgoing connection initiated by them, not a prohibited-by-policy incoming connection.

    • There are two separate problems with IPv4 and only one applies to IPv6. Allowing incoming connections through a restrictive firewall is applicable to both. Address mangling via NAT applies only to one. Note also that in the IPv4 world you might be behind more than one layer of NAT which will make everything infinitely worse.

      Honestly ISPs really missed an opportunity to essentially provide IPv6-only as a service and add an IPv4 compatibility layer to that (IPv6 already has a mechanism built in for this but grandma’s old laptop might not fully support it so you might need a local router provided by the ISP to give you native local IPv4 that allows you to access the internet) instead of CGNAT. But they chose to go with duct tape, spit, paper clips, and hope instead of investing in the correct solution. Shame on them and too bad for us.

      2 replies →

    • All you should need is for both sides to connect to each other. Side A connecting to side B opens a hole in side A's firewall and is blocked by side B, then B connects to A, opening B's firewall and going through the already open hole in A's firewall.

      It might work better with UDP but I don't think those firewalls boxes tear down the mapping immediately on getting an RST - they wait until it times out.

> really wish there was a standardized way to do it. Some sort of explicit (or at least implicit but unambiguous) indicator to all firewalls that a connection from a given host/port pair is desired for the next few seconds

NAT Behavioural Requirements for Unicast UDP, https://datatracker.ietf.org/doc/html/rfc4787

NAT Behavioural Requirements for TCP, https://datatracker.ietf.org/doc/html/rfc5382

  • > NAT Behavioural Requirements for TCP

    TIL, thank you! I've been looking for this for quite a while after hearing it indirectly referenced recently, but only found host-side specifications for TCP simultaneous open.

    Do you happen to know if common firewalls and NATs support it? If they do, I really wonder why TCP hole punching isn't more common.