How to troubleshoot peer-to-peer connections

Solving issues with NAT traversal, in practice.

Twingate relies on two separate transport mechanisms for traffic between Clients and Connectors: Peer-to-peer and Relays.

Neither transport mechanism requires any ports to be opened through a firewall to the public internet to work.

It is relatively intuitive to understand why that is for Relay traffic - a Connector and Client each connect to a Relay in order to communicate with each other. The Relay is responsible for relaying all of those communications so there is no need for the Connector to receive packets directly from the Client (and vice versa).

For peer-to-peer traffic, it is a bit less intuitive. Peer-to-peer communications rely on a technique called NAT traversal (read our article on how NAT traversal works for a deep dive).

Some network conditions may prevent peer-to-peer connections from being made. If you are trying to troubleshoot a peer-to-peer connection, read on, as there are common configuration issues that can prevent NAT traversal from working.

At a high level, the main four reasons are the following:

  • UDP or QUIC are blocked (on either side)
  • Some IP addresses and/or ports are blocked for outbound communication (on either side)
  • The Client or Connector is behind two NAT devices (“double NAT”)
  • The Client or Connector is behind an incompatible NAT type

Let’s unpack it all, in order.

Verify that UDP & QUIC are not blocked

UDP is used as a protocol for NAT traversal. UDP is a great protocol for streaming and it performs well but lacks the integrity controls of TCP. Twingate uses QUIC, which is built on top of UDP but provides more reliability without compromising on performance.

In our experience, some overzealous firewalls block QUIC by default, which breaks NAT traversal. Our recommendation is to make sure that QUIC and UDP are not blocked on either side. (In practice, QUIC is almost never blocked on the Client side so we recommend starting by analyzing the Connector side.)

Verify outbound rules

As explained in how NAT traversal works, both the Client and Connector need to be able to send packets to each other’s public IP address and port. The Client’s public IP address is assigned by an internet service provider and cannot be known in advance (this is why Connectors need to be able to send UDP packets to all IP addresses). Additionally, NAT devices tend to map random ports to devices, which is why outbound traffic rules need to allow UDP packets to connect to any port.

This is all documented here and we highly recommend verifying that the prerequisites listed in that article are met in your environment.

Check for double NAT

Double NAT occasionally occurs on the Client side. A double NAT occurs if you have two distinct NAT devices on a single private network in front of your device on which a Client is installed (not uncommon if you add your own equipment on top of what your ISP provides).

A device behind two NAT devices will typically not be able to establish peer-to-peer connections because of specific aspects of UDP (it is a stateless protocol which means that no party acknowledges that packets are either received or sent). Introducing another layer of network address translation is likely to break peer-to-peer because all NAT devices end up having to maintain complex and brittle mappings between them.

Check NAT types in front of Clients and Connectors

In our how NAT traversal works article, we made the following assumption:

A NAT device (for instance, an ISP provided router) assigns a unique port to each device on its private network and uses it as a source port for all packets sent from the device, regardless of where it connects to on the internet.

This is referred to as ”endpoint-independent NAT” and is ideal for NAT traversal because since your Client needs to send packets to a Connector on its public IP address and port, your Client needs to rely on what the Relay sees as being the IP address and port from packets coming from the Connector.

If the public port of the Connector changes depending on whether it talks to the Relay or the Client, then the Client will never know the actual port it needs to send packets to for those packets to successfully reach the Connector.

Unfortunately, not all NAT devices are equal. Some implement ”endpoint-dependent NAT”, which breaks peer-to-peer because it assigns different ports to a single device for every different destination it connects to.

Connector side NAT type

Take a look at your Connectors in the Admin Console and make sure they all report STUN Discovery as Available:

Client side NAT type

Take a look at your Client logs and search for stun_nat_type:

[INFO] [libsdwan] stun_nat_type: endpoint-independent

What to do if your Connector is behind an incompatible NAT

Check for known incompatibilities

The following appliances are known to not be NAT traversal-friendly

  • AWS NAT gateways

Check your firewall configuration

Most enterprise-grade firewalls can be configured to change the NAT type for single endpoints (like Connectors, for instance).

Last updated 4 months ago