Direct vs relayed connections

Tailscale uses both direct and relayed connections, opting for direct connections where possible. When diagnosing unexpected performance issues, the most common cause is using a relayed connection where a direct connection is possible.

Tailscale operates a fleet of DERP relay servers around the world. Any device which can open an HTTPS connection to an arbitrary host will be able to build a tunnel using these DERP relays. They are very reliable, but have some Quality of Service (QoS) characteristics, so they are not as fast as a direct connection.

In order to establish a direct connection, Tailscale will need to be able to build a UDP tunnel, and negotiate a pair of ports via NAT traversal logic. Tailscale’s NAT traversal logic is very robust and successful in establishing direct connections, but not for every configuration.

Determining your connection type

To determine if your connection is direct, you can check the Tailscale status after trying to communicate between nodes.

On Linux or Windows, you can do this by running tailscale status on the command line. On macOS, you will need to run /Applications/ status.

A direct connection will look like:  testmy  tagged-devices linux    active; offers exit node; direct

A relayed connection will report something like the following:   localhost-0          jay@         android active; relay "tor"

You can also use tailscale ping to see if the connection can be direct. This will look like this:

    > ubuntu@living-razorfish:~$ tailscale ping testmy
    pong from testmy ( via DERP(nyc) in 130ms
    pong from testmy ( via DERP(nyc) in 37ms
    pong from testmy ( via DERP(nyc) in 50ms
    pong from testmy ( via DERP(nyc) in 38ms
    pong from testmy ( via in 35ms

The first few packets go via the nearest DERP server while the direct connection is being negotiated, then it goes direct after it’s negotiated that connection.

If a connection can’t be established, by default tailscale ping will give up after 10 attempts.

    > ubuntu@living-razorfish:~$ tailscale ping localhost-0
    pong from localhost-0 ( via DERP(tor) in 53ms
    pong from localhost-0 ( via DERP(tor) in 196ms
    pong from localhost-0 ( via DERP(tor) in 50ms
    pong from localhost-0 ( via DERP(tor) in 214ms
    pong from localhost-0 ( via DERP(tor) in 273ms
    pong from localhost-0 ( via DERP(tor) in 274ms
    pong from localhost-0 ( via DERP(tor) in 282ms
    pong from localhost-0 ( via DERP(tor) in 273ms
    pong from localhost-0 ( via DERP(tor) in 76ms
    pong from localhost-0 ( via DERP(tor) in 152ms
    direct connection not established

When using relayed connections, there is some extra latency added by the relay, and the DERP servers have varied QoS characteristics which will often limit maximum throughput as compared to a direct connection. Wherever possible, it is encouraged to establish a direct connection.


Some network and configuration settings can prevent direct connections:

  • Blocked UDP—If you can only use TCP connections, then all links will be relayed. We encapsulate the WireGuard frames in a TLS stream over TCP for the DERP links.
  • “Hard NAT” as described in How NAT Traversal Works—If both ends are Hard NAT, we won’t be able to establish a direct connection.
Blocked UDP

If something on the network is blocking direct UDP connections, then a DERP relay is going to be the best connectivity available. The only remediation is to ask your provider if they have IPV6 available, which is likely not going to be behind the restrictive NAT. Tailscale will build our dual stack (IPV4 and IPV6) tunnel over an IPV6-only underlying connection.

Hard NAT

If you’re running into Hard NAT, there are a few things we can do to improve the odds of getting a direct connection. Using NAT-PMP or uPnP portmapping on your router will often facilitate a direct connection.

Some firewall specific mechanisms can improving direct connections. In general, look for something named ‘static port mapping’ or similar configuration settings, which will provide predictable (static) port numbers. Having a predictable port number allows Tailscale to reliably get direct connections through a firewall.

Many cloud platforms like AWS have a NAT gateway solution. In many cases, seeing relayed connections on these services is due to a Hard NAT. You can expose a public IP address for your Tailscale nodes to ensure a direct connection. These can be dynamic, you don’t need to use an Elastic or Static IP. If you ensure that port UDP/41641 is not blocked, and that outgoing UDP and TCP/443 is permitted, Tailscale will be able to reliably serve direct connections.

Opening incoming UDP/41641 (by default) on a device’s public IP address will guarantee a direct connection from any peer where it is possible. This port is configurable by passing a value to tailscaled. On Linux machines, you can set it in /etc/defaults/tailscaled. This is useful if there is more than one endpoint behind a Hard NAT public IP address, and you want to ensure direct connections to each. Set the port to a unique value and forward that port through to the correct endpoint.

For devices such as exit nodes where you are intentionally egressing through a NAT gateway and want to improve performance, we have some terraform templates to set up routing incoming traffic through the public interface, and egressing through the NAT gateway. Contact our Solutions Engineering team at for assistance deploying this. This will allow the egress traffic to have a predictable public IP address, but the ingress traffic to establish a direct connection to the exit node.

Last updated