6 ms·
A most elegant TCP hole punching algorithm
- jcalvinowens 7mo agoIf you're asking "where is the listener", you don't need one: https://datatracker.ietf.org/doc/html/rfc9293#simul_connect https://datatracker.ietf.org/doc/html/rfc9293#simul_connect
- cperciva 7mo agoRFCs may say that simultaneous connect must be allowed, but that doesn't mean that firewalls can't block it. Plenty of setups block incoming SYN,!ACK packets, and if both sides do that, the connection is never getting established.
- jcalvinowens 7mo agoIn my experience most consumer routers are dumber than you're assuming they are, and will DNAT any inbound TCP packet that matches the 4-tuple after seeing the initial outbound SYN, including an inbound SYN. But yes, it doesn't work everywhere. I wrote little paper on this technique in school and did some practical tests, at the time I was actually unable to find an example of consumer grade router that it didn't work on! But my resources were rather limited, they certainly do exist.
- huhtenberg 7mo ago> Plenty of setups block incoming SYN,!ACK packets Even in the presence of a conntrack entry created by an earlier outbound SYN,!ACK ? Got a source?
- cperciva 7mo agoI've seen plenty of firewall rulesets over the past 25 years which only consult state after doing some initial stateless inspection. I don't have a convenient source though.
- deleted 7mo ago[deleted]
- huhtenberg 7mo agoSanity checks, sure, but SYN,!ACK packets cannot be rejected before the conntrack for obvious reasons. > Plenty of setups block incoming SYN,!ACK packets Nowhere close to being "plenty". It's doable, but this is extremely niche.
- cperciva 7mo agofor obvious reasons What are the obvious reasons? If you're protecting a client system, you don't want to allow in any bare SYNs. (And for that matter, if you're protecting a server, you probably want to discard ill-targeted bare SYNs without consulting conntrack anyway, just as a matter of avoiding extra CPU work.)
- gzread 7mo agoDoes this mean by establishing a new connection with a SYN,ACK bypasses some firewalls? I expect at least one OS out there ignores the extraneous ACK flag and proceeds to establish a new connection.
- huhtenberg 7mo agoWhy would it mean that? All inbound packets are matched against existing sessions. In this case none will turn up, so the packet will go through the "new session" flow and be subject to the same filtering as a bare SYN. Look up how connection tracking works, e.g. in the Linux kernel, it's rather simple and logical.
- jcalvinowens 7mo agoIt's not uncommon with routable internal networks to only drop inbound SYN,!ACK to disallow inbound connections while permitting outbound ones, since it doesn't require connection tracking (which can be resource intensive). I can't really imagine why you would do it for NAT'd v4 since you can't avoid the connection tracking overhead, but you certainly could, and I don't doubt OP has run into it in the wild. I've seen much weirder firewall rules :)
- EnigmaCurry 7mo ago> Many home routers try to preserve the source port in external mappings. This is a property called “equal delta mapping” – it won’t work on all routers but for our algorithm we’re sacrificing coverage for simplicity. It is precisely this point that has flummoxed me when connecting my p2p wireguard config[1] with a friend that uses a pfsense router, no matter what we tried, pfsense always chooses a random source port. But in the simple case this blog outlines, if both ends use the same source port, this method punches through 2 firewalls effortlessly: [1] https://blog.rymcg.tech/blog/linux/wireguard_p2p/ https://blog.rymcg.tech/blog/linux/wireguard_p2p/
- jonathanlydall 7mo agoDoes your friend setting up port forwarding on their pfSense not help in your scenario?
- EnigmaCurry 7mo agoYes, that solves it completely. But the exercise we were trying to do was to do it without that.
- hdgvhicv 7mo agoYou’re getting into birthday paradox territory, throw a few hundred packets in each direction and one will get through This hs a good diagram to understand the options https://rajsinghtech.github.io/claude-diagrams/diagrams/network/tailscale-nat-traversal-fallback/ https://rajsinghtech.github.io/claude-diagrams/diagrams/netw...
- patjensen 7mo agoThis is easily solved in your source NAT configuration on pfSense. It's a single checkbox to not randomize ports on outbound flows. This will enable full cone NAT. You can scope it to just your IPsec service, or whatever it is your hosting, or you can enable full cone for the whole subnet. It is not DNAT, nor is it port forwarding. If you host a SIP proxy, SBC or peer to peer gaming, it will enable these use cases as well. https://docs.netgate.com/pfsense/en/latest/nat/outbound.html https://docs.netgate.com/pfsense/en/latest/nat/outbound.html
- athrowaway3z 7mo ago- you know each others IP's (or have a way to signal it) - can't decide on a port in the same message - don't suffer from NAT port randomization I'm not saying it will never happen, but the Venn diagram of this being the minimum complexity solution just doesn't seem very large?
- Arch485 7mo agoI think many people know how to google "what is my IP" and send that to a friend, but don't necessarily know what a port is. NAT randomization, I don't know. Depends on your setup, I guess.
- sholladay 7mo agoThere are plenty of free public STUN servers and ways to share the information they return. The real problem is the port randomization if any client is behind a symmetric NAT. The search space for randomly trying port numbers is too large. There are some ways to reduce the search space, like port prediction. But ultimately, a large dose of port scanning is the only way I know of to make the connection reliably. And there’s only so much of that you can do before triggering IPS or overwhelming the NAT. IPv6 makes this way easier, of course!
- sholladay 7mo agoThis is a great algorithm! In this era where AI is eating away at how deterministic computers are, I really appreciate reading about an elegant solution to a real problem using deterministic logic.
- CamelCaseCondo 7mo agoWe still live in an age of deterministic computers. It’s the software that’s become fuzzy. (And since we’re on the subject: there’s no AI)
- sholladay 7mo agoYes, but a computer is just a paperweight without its software. Also, increasingly the hardware is being specifically designed and optimized for that non-deterministic software. The experience of using computers is changing and we’re still in the early days of that shift. Of course there’s still plenty of deterministic software you can run… for now.
- ufocia 7mo agoI can almost guarantee that all of AI runs on deterministic hardware and software. AI is just (near?) the top of the stack. There is no reason, and probably never will be to have a purely heuristic computer. Deterministic systems are way simpler and cheaper to handle very routine well defined tasks. Even AI authors code behind the scenes to process data files deterministically.
- wolttam 7mo ago> there’s no AI This is a theistic statement at this point, no?
- CharlesW 7mo agoMany people conflate "AI" and "AGI". It's disappointing to find people who don't know the difference on HN, though.
- Veserv 7mo agoNeeding to punch holes in NAT is one of the most idiotic own-goals in the entire field of networking. NAT is effectively your router doing DHCP with a 17-bit suffix (16-bit port + 1 bit for UDP vs TCP) to each of your applications and then not telling you the address it gave you or how long it is good for (which is what a regular DHCP lease does). This is in addition to it, most likely, already doing regular DHCP and allocating you a IP address that it does tell you about, but which is basically worthless since routing to just that prefix without the hidden suffix goes into a black hole. If you could just ask your router for a lease on a chunk of IP+NAT addresses that you could allocate to your applications and rotate them as they expire, you would not need this horrifying mess. The router would just need to maintain the last-leg routing table (what a concept, a router doing routing with routing tables) just like it already does DHCP. The applications would have short-term stable addresses that they could just tell their peers and just directly tell the router/firewall to block anybody except the desired peer short-term address.
- eptcyka 7mo agoWhy not use plain IPv6 instead?
- cbdevidal 7mo agoV6 adoption has reached 46.82%[1]. So it is increasingly viable for this. [1] https://www.google.com/intl/en/ipv6/statistics.html https://www.google.com/intl/en/ipv6/statistics.html
- TuxPowered 7mo agoEven with IPv6 you still might have stateful firewalls allowing only for outbound connection at both ends (e.g. a CPE a.k.a. “WiFi router”) and to establish communication you’d need to punch a hole in those firewalls.
- brewmarche 7mo agoThat’s true we won’t get rid of hole-punching with IPv6. But at least it will get rid of TURN.
- lxgr 7mo agoDoes 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.
- ignoramous 7mo ago> 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 https://datatracker.ietf.org/doc/html/rfc4787 NAT Behavioural Requirements for TCP, https://datatracker.ietf.org/doc/html/rfc5382 https://datatracker.ietf.org/doc/html/rfc5382
- lxgr 7mo ago> 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.
- aboardRat4 7mo agoThe standard way to do it is called ipv6. Implementing it is probably easier than any of those RFCs
- patrakov 7mo agoNo, 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.
- elophanto_agent 7mo ago[flagged]
- mudkipdev 7mo agoThis is an AI slop bot
- vntok 7mo agoThat's fine, it's pretty good slop and from the comments history even entertaining at times. > my grandmother had a cookie jar collection and I always thought it was weird until I realized she was basically running a primitive NFT gallery except the tokens were actually useful because they contained cookies
- ufocia 7mo agoMeh. "It is assumed another process will coordinate the running of this tool." Coordination is the crux of the problem for fast convergence. Otherwise you're stuck with an infinity cubed, hypercubed, or worse problem.
- ata-sesli 7mo agoThe timestamp bucket idea for generating shared port candidates is clever. Do you find this works reliably outside routers that preserve source ports? My understanding was that TCP punching tends to depend heavily on NAT behavior.
- enoint 7mo agoLooks like a typo in the degraded timestamp “bucket”. That “window” value should be based on the min threshold.
- sylware 7mo agoDudes: IPv6, please, come on, meh.
- majorchord 7mo agomaybe in another 20 years my local monopoly will consider IPv6 adoption, but I'm not holding my breath
- sylware 7mo agoYou live in one of those places... sad for you. In my country: only a few mobile ISPs are not yet native IPv6. The thing now would be to get a fixed IPv6 for mobile internet (which would remove the need of a name->IP "resolver"), but I wonder if the mobile ISPs can handle the quality of "security" this requires. (we all know about enshitific*tion).
- melson 7mo agoI made a udp Windows wintun based p2p vpn tunnel https://github.com/mascarenhasmelson/Windows-P2P-UDP https://github.com/mascarenhasmelson/Windows-P2P-UDP
- jder 7mo agoI don’t think the bucket-choosing algorithm works? The two hosts can be just on opposite sides of a bucket edge. For example if one host sees t=61 and another sees t=62, they will get different buckets despite being less than 20 seconds apart. You’ve got to check adjacent buckets within your error tolerance, not expand the bucket windows in size based on it.
- abcd_f 7mo agoClaimed elegance is based on a very bold assumption that the NAT device preserves the source port of outbound connection. Hardly the case in even half of typical deployment cases.
- taftster 7mo agoI like your comment, but it seems the author acknowledged this as a caveat to the algorithm. >Many home routers try to preserve the source port in external mappings. This is a property called “equal delta mapping” – it won’t work on all routers but for our algorithm we’re sacrificing coverage for simplicity. So to what percentage is this coverage sacrificed exactly? No idea. Not as useful if the percentage is high, as you are implying.
- killbot5000 7mo agoIt’s the same assumption is required for any hole punching handshake (including STUN). > This is a property called “equal delta mapping” FWIW I’ve worked in computer networking for 20 years and have never heard it called this. This blog is the only source that comes up when I search for that exact term. I wonder where the author got it from.
- ray_v 7mo agoI wonder how many new technical terms are going to be created by LLMs - not to say that this post was N necessarily written by an LLM (but, who knows!)
- abcd_f 7mo ago> It’s the same assumption is required for any hole punching handshake (including STUN). This is incorrect. Hole punching requires being able to predict external port. That's it. If the port remains the same, it certainly simplifies things, but ports going up (or down) by 1 (or 2, or 5) with each new mapping is quite common, trivial to detect and to punch through.
- 7mo ago
- andrewmcwatters 7mo ago[dead]
- ray_v 7mo agoOne thing about this get I just realized is that if the defect exists on some home networking equipment, then the defect can be leveraged in corporate network environments to disable this functionality. If the user of the algorithm (or, person using an app using it for userspace) isn't aware of the limitations, that would be super frustrating!
- kordlessagain 7mo agoThis perfectly eliminates the last centralized bottleneck for P2P agent networks. We are dropping this deterministic punch directly into the grubcrawler.dev edge binaries. Instead of relying on STUN/TURN servers to coordinate a swarm, millions of nodes trapped behind residential NATs will use the unix timestamp to mathematically predict a collision course, aggressively punch through their firewalls, and instantly hand the raw TCP socket over to rust-lightning (LDK). No DNS. No signaling servers. No legacy IP registries. Just a self-assembling Lightning mesh of autonomous agents spinning up encrypted channels and executing paid RPC calls entirely in the dark.
- stainlu 7mo ago[flagged]