99% of companies want to ditch their VPN. See why in our 2025 Zero Trust ReportRead more
Get started - it's free!
Log in
WireGuard is a registered trademark of Jason A. Donenfeld.
© 2025 Tailscale Inc. All rights reserved. Tailscale is a registered trademark of Tailscale Inc.
Blog|insightsOctober 15, 2025

NAT traversal, and how we're improving it

Two diagram boxes, both labeled "Hard NAT," one blue and one green. Inside the blue box, and then a "Home" box is Laptop. A line moves through a blue hole and into the green box, where inside an "Office" box, it connects to a Workstation.
This is the first in a series of posts about how Tailscale makes secure connections between devices, and the challenges on the path between them. Read on to learn how we've made connections easier for both Tailscale and the global web—and look for future posts about cloud networking, and what we see in the future.

Tailscale’s architecture is built to favor direct peer-to-peer (P2P) connections whenever possible. In fact, the vast majority of Tailscale traffic flows directly between peers, with the cloud relay servers (called DERP servers) used to initiate connections and as a fallback relay​. This means that under normal conditions, almost all your data is sent P2P over an end-to-end encrypted WireGuard™ tunnel, not through any central server. And we’ve been working for years to make those normal conditions even more normal.

Direct connections generally offer much better throughput and lower latency than relayed connections, so Tailscale’s NAT traversal machinery works hard to punch through whatever obstacles stand in the way. That said, every connection technically begins via DERP, then upgrades to a direct link if possible​. When device A connects to device B, it first contacts B via the nearest DERP relay to exchange information (like observed IP addresses/ports and keys) and to begin sending data. In parallel, each side uses that information to attempt a direct UDP connection through any intervening NATs or firewalls.

If the NAT traversal succeeds, traffic seamlessly switches to the direct UDP path. If it never succeeds, the traffic continues flowing over DERP for as long as needed​. In practice, Tailscale succeeds in establishing direct connections nearly all of the time​. Internal metrics have indicated success rates for direct NAT traversal well north of 90% in typical conditions. In other words, more than nine out of 10 connections between Tailscale nodes end up being direct P2P links. DERP helps Tailscale create direct connections, and then typically steps away. DERP is also indispensable for those rare cases where direct UDP cannot get through at all, but it’s truly a last resort in normal operation.

What follows are a few cases where we can’t always get a P2P connection and have to fall back to a DERP relay—and some work we’ve been doing in public to improve on that.

Symmetric or “hard” NAT devices

The biggest culprit is a symmetric NAT, sometimes called a “hard NAT.” These NATs randomize the source port mapping for every outbound connection, meaning your device gets a different external port number for each remote destination​. This makes peer-to-peer negotiation virtually impossible—even if both sides coordinate using common traversal tools (i.e. STUN), they cannot predict or reuse a stable port to reach each other.

Enterprise-grade firewalls and carrier-grade NAT gateways (like those used by cellular providers or cloud providers) often behave this way for maximum connection isolation. The more layers of NAT in play, the lower the chances for direct connectivity​. Two devices, each behind “hard NAT,” will almost always need to use a relay, since neither can punch through the other’s dynamic mappings.

Multiple NAT layers (double NAT)

Even if individual NATs aren’t especially hard or symmetric, stacking multiple NAT layers complicates traversal. A laptop, on hotel Wi-Fi, reaching through that Wi-Fi router’s NAT, to a virtual machine, in a VPC, through a cloud NAT gateway—the more hops you add, the more coordination is required, and the more failure modes appear. Each device on a Tailscale network is told all the possible ways it might reach another, and they race through those options to see what works. With just one NAT layer, that often succeeds; with two or more, the odds rise that no direct path forms quickly enough, and DERP takes over.

Strict firewalls blocking UDP or P2P

In some environments, it’s not the NAT’s behavior preventing a P2P connection, but a firewall policy that outright blocks it. Certain corporate networks or security appliances might block all unsolicited UDP traffic. Some “intrusion prevention” systems even classify peer-to-peer connection attempts as suspicious. A notable example is UniFi’s security gateway, which by default can classify P2P traffic as a threat and block it unless you disable that rule​.

In these cases, Tailscale’s UDP hole-punching probes never get through at all. Because DERP traffic is carried over HTTPS (TCP port 443) by design, it will succeed even when direct UDP is filtered, at the cost of higher latency.

Carrier-grade NAT and large-scale networks

Laptop and phone devices from Network A and Network B, behind mobile hotspots, reaching through ISP networks and Carrier Grade NAT to reach the Internet.

Mobile networks and large Internet Service Providers (ISPs) often use carrier-grade NAT (CGNAT), where thousands of subscribers share a pool of public IP addresses. These systems tend to be very restrictive—they typically employ short port timeouts and symmetric mapping to cope with their sheer number of connections. If you have two mobile devices trying to connect peer-to-peer from different cellular networks, there’s a good chance they’ll have to use DERP. Similarly, cloud providers’ NAT services prioritize scalability and security over hole-punching friendliness (more on this in an upcoming post!). In all these cases, it’s not impossible to get a direct connection, but the odds are lower.

Unusually restrictive endpoint configurations

Sometimes a device’s own setup makes DERP unavoidable. A VM that can only reach the internet through a proxy, a firewall that blocks everything but web traffic, or a machine with no working UDP at all—in these cases, direct peer-to-peer just isn’t possible, so DERP (over TCP) is the only path.

An orange line from a laptop inside Network A, labeled 2.2.2.2, goes through its own blue firewall box, but is stopped on the way to a server at 7.7.7.7, inside a green firewall and Network B. "Rejected: No recent packets to 2.2.2.2" is shown below the green.
Device “Laptop (2.2.2.2)” sends a UDP packet to a peer “Server (7.7.7.7)” but the server’s firewall/NAT rejects it because it had no prior knowledge of that communication. In this one-sided attempt, the packet is blocked – the server’s NAT has “No recent packets to 2.2.2.2,” so it refuses the inbound packet​.

Other times, the trouble is two NATs that refuse to admit packets from a peer unless they’ve seen something outbound first. Picture a laptop at 2.2.2.2 sending a packet to a server at 7.7.7.7. The server’s NAT drops it: “no recent packets to that address.” From the laptop’s side, the same logic applies. Both firewalls sit there, arms crossed, waiting for the other to go first.

Packets from a Laptop at 2.2.2.2 inside Network A and blue firewall flow to a Server inside Network B and a green firewall, and then flow back to the laptop, due to a relay sending packets back to 2.2.2.2
After coordinated hole punching, both the Laptop’s and Server’s firewalls have seen outgoing traffic to each other’s address, so return traffic is now accepted on both sides. The two peers establish two-way communication through their respective NAT/firewall devices​.

Tailscale’s coordination layer normally breaks the deadlock by getting both devices to send packets at the same time, so each NAT sees outbound traffic and allows the return flow. When that trick works, DERP quietly steps aside. When it doesn’t, DERP stays in the loop, relaying traffic to keep the session alive—slower, but reliable.

Improving NAT traversal techniques

Even with a peer connection success rate above 90%, using DERP and other tools, we aren’t content to leave well enough alone. Over the past two years, we have made significant efforts to improve NAT traversal, especially for “hard cases” like symmetric NATs and complex corporate networks.

Some of these improvements involve enhancements to Tailscale’s own code (clients and coordination servers), while others have us working with the broader networking community, to improve the behavior of NAT devices themselves.

Sponsoring FreeBSD’s endpoint-independent NAT patch

One exciting development has been a change in the FreeBSD operating system’s firewall/NAT, which was directly sponsored by Tailscale.

FreeBSD’s PF firewall (used in systems like pfSense and OPNsense routers) historically implemented a symmetric NAT for UDP traffic by default. This meant that if a machine behind a FreeBSD PF router sent UDP traffic to two different external hosts, PF would allocate different source ports for each destination (a classic hard NAT behavior). From a NAT traversal perspective, that’s bad news—it prevents the device from having a single stable “hole” that a peer can target. Tailscale observed that users running behind pfSense/OPNsense often fell back to DERP because of this behavior​.

To address this, developers contributed a patch to FreeBSD PF (and its counterpart iPFw) in late 2024 to support Endpoint-Independent Mapping for UDP. This gives FreeBSD-based NAT routers the option to behave like “Full Cone” NATs, rather than hard NATs. With endpoint-independent mapping, once an internal socket (say 10.0.0.5:12345) is mapped to an external port (1.2.3.4:54321), that same external port is reused for all destinations. From the perspective of remote peers, the device now has one stable, predictable endpoint—almost as if there were no NAT at all.

This drastically improves the ability of protocols like STUN and ICE (both of which Tailscale uses for NAT traversal) to establish direct connections. Concretely, the FreeBSD patch (by Damjan Jovanovic, Naman Sood, and others) added a new endpoint-independent option to PF’s NAT rules. When enabled for UDP, PF allocates one external port per internal socket and sticks to it. For example, if a packet to host A maps to 1.2.3.4:54321, a later packet from the same internal socket to host B will also use 1.2.3.4:54321. That means host B can reply to the same endpoint, even though it wasn’t part of the original mapping.

The impact on peer-to-peer connectivity is significant. With the patch, a FreeBSD/PF router can be configured to behave like a cone NAT, which means that if both sides of a Tailscale connection have such mappings, standard hole-punching will succeed. Even if only one side is behind an endpoint-independent NAT, that side can accept incoming UDP from any peer on the port it opened, after a single outbound packet. (In practice, the current FreeBSD implementation still applies “address-dependent filtering,” meaning the NAT won’t forward completely unsolicited packets from hosts the internal side never contacted, effectively making it a port-restricted cone. This is actually a good security balance.)

This vastly improves the connectivity of UDP applications using PF’s NATing. Not just Tailscale, but gaming, VoIP, WebRTC, and peer-to-peer applications.

Tailscale’s sponsorship of this work shows how improving the Internet’s plumbing can be a win-win. Not only do Tailscale users on FreeBSD-based routers get better connectivity (fewer DERP fallbacks when using OPNsense/pfSense), but any application or VPN running behind those routers benefits as well. Tailscale’s patch also avoids resorting to riskier or less portable workarounds. As router distributions adopt the changes, we expect to see a drop in Tailscale DERP usage for networks using those platforms.

Safer NAT traversal vs. UPnP and NAT-PMP

An astute reader might wonder: Instead of making NATs full-cone, why not just use UPnP or NAT-PMP to open ports? After all, many home routers support the UPnP IGD protocol, or its more secure successor, NAT-PMP/PCP (Port Control Protocol). Tailscale does attempt NAT-PMP/PCP on networks where it’s available—this can create an explicit port mapping on the router, effectively punching a hole that peers can use. However, relying on UPnP/NAT-PMP as the primary solution has downsides.

FreeBSD’s endpoint-independent NAT approach is actually safer and more elegant in many cases. First, enabling UPnP or NAT-PMP on a router can be a security risk if not managed carefully. These protocols allow devices on the inside to programmatically instruct the router to open a port to the outside world. If malware or a rogue app is present inside the network, it could potentially abuse this access to expose services that shouldn’t be public.

Many organizations disable UPnP for this reason. Even when enabled, UPnP/NAT-PMP tends to open a port fully to the outside (any host can hit it) unless paired with additional firewall rules. As our own docs warn, “By enabling NAT-PMP and UPnP, your network can allow in and forward all traffic.”​

By contrast, endpoint-independent NAT preserves a level of implicit security. The NAT only opens ports that were first used outbound by an internal host, and (in the current implementation) will still restrict which external hosts can send back (only those the internal host has sent to, if using address-dependent filtering).

So a random attacker on the internet can’t just probe your NAT and get through – they would have to know that your internal host at 10.0.0.x used port 12345, and approach from the exact IP your host recently contacted. The NAT is essentially performing a limited port forwarding, for just the duration of a conversation with a known peer, rather than blindly obeying any device’s request to open a hole.

Another issue is that UPnP/NAT-PMP aren’t universally available. Enterprise firewalls and cloud NATs virtually never support these consumer-focused protocols. Even some ISP-supplied routers have them disabled by default. Tailscale’s goal is to work automatically on as many networks as possible without manual configuration. Techniques like UDP hole-punching and leveraging endpoint-independent mappings work transparently in the background, whereas something like UPnP requires the network admin to have enabled it beforehand.

The FreeBSD change brings a UPnP-like benefit (open inbound port to the peer) without requiring any additional protocol or setup. It’s just the NAT’s default behavior, once configured.

Lastly, there’s an elegance in solving the problem at the protocol or NAT level, rather than application level. If NATs simply behave in a more peer-to-peer friendly way (within reason), then every application benefits, not just those savvy enough to utilize NAT-PMP. We see this trend in some modern firewalls. Sophos gateways, by default, preserve the same UDP source port for all outbound flows from a given internal port. As noted in our docs, this “allows Tailscale at the other end to know what port it should use for sending traffic.” Sophos basically acts as an endpoint-independent NAT out of the box.

Similarly, Palo Alto Networks devices recently added a “Persistent NAT (Dynamic IP and Port)” option in PAN-OS 11.1 that achieves a similar effect​. All these are signs that the industry is moving away from the most strict NAT behaviors, in favor of approaches that maintain security and enable modern peer-to-peer connectivity.

Tailscale’s stance is that improving NATs and using smarter traversal tricks is preferable to requiring users to open ports manually. It’s better for the future of the Internet, and it just makes life easier for the user.

Other NAT traversal enhancements

Beyond the headline FreeBSD change, Tailscale’s team has been continuously tweaking their NAT traversal toolkit in the client software as well. For instance, recent versions of Tailscale have improved handling for certain corner cases, like when a router’s NAT mapping changes mid-connection, or when NAT-PMP mappings expire. In a recent update, we added functionality to have the client monitor the “epoch” of NAT-PMP/PCP mappings, automatically re-establishing a port mapping if the router reboots or resets its table, and avoiding a DERP fallback.

There have also been optimizations in the magicsock library (Tailscale’s NAT traversal engine) to more quickly switch to better paths. For example, if multiple potential paths are found (IPv4 vs IPv6, or multiple interface addresses), Tailscale will race them and stick to the one with lowest latency. This helps in scenarios like a device being on both Wi-Fi and Ethernet, or having both a NAT64 and NAT44 address—the best route is found dynamically.

We’ve also improved diagnostics and configuration guidance. Tailscale added the tailscale netcheck subcommand and improved its output, so power users can see exactly what NAT type they are behind (e.g. does the mapping vary by destination? Are the hairpin and IPv6 statuses good?). This transparency helps users identify if their network is one of the “difficult” ones.

It’s also worth noting that IPv6 can sometimes circumvent NAT issues entirely—if both peers have native IPv6 connectivity, Tailscale will prefer that for direct connections (since IPv6 requires no NAT). As IPv6 deployment grows, this inherently reduces NAT traversal complexity.

However, many IPv6 deployments are partial (e.g. one side behind IPv6, another not, or only ULAs available, etc.), so IPv4/UDP hole punching remains the critical path for most connections, even in 2025. Tailscale continues to support IPv6 where available, and in the best case, two IPv6-enabled nodes will talk directly, with no DERP or NAT in the way at all.


This is the first of a few posts you’ll see this month, exploring the ways Tailscale is upgrading the connections between both people and machines. We'll follow up with thoughts about cloud NATs, where we think connectivity is headed, and perhaps a little something else.


Share

Authors

Image of Will MooreWill Moore
Headshot of Kevin PurdyKevin Purdy
Kabir SikandKabir Sikand

Contributors

Avery Pennarun
Jordan Whited
James Tucker
Loading...

Try Tailscale for free

Schedule a demo
Contact sales
cta phone
mercury
instacrt
Retool
duolingo
Hugging Face