Site-to-site networking
You can use Tailscale subnet routers to connect two or more subnets (such as different physical locations or cloud environments) within a single, secure network mesh. This type of configuration is called site-to-site (L3) networking.
Requirements and limitations
The subnets and subnet router devices within a Tailscale network (known as a tailnet) must meet the following requirements for site-to-site networking to work:
- The subnets must not have overlapping CIDR ranges or use 4via6 subnet routing.
- Both subnet routers must use a Linux-based operating system.
Create a site-to-site connection
To connect two or more subnets within your tailnet (creating a site-to-site connection), you must do the following for each subnet:
- Make sure each subnet meets the minimum requirements.
- Select a device within the subnet to act as the subnet router.
- Configure the device as a subnet router.
- Approve the subnet router.
- Update the tailnet access control policies to allow communication between the subnets.
- Configure the other devices in the subnet.
Select a subnet router
The first step is to select a device within the subnet to act as the designated subnet router. This device must use a Linux-based operating system.
Configure the subnet router
After selecting a device in the subnet to function as the subnet router, you must configure it to act as a subnet router. Configuring the subnet router involves installing the Tailscale client, enabling IP address forwarding, starting the Tailscale client with the correct configuration options, and configuring the device's iptables
settings.
IP address forwarding
If your Linux system has a /etc/sysctl.d
directory, use:
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf
Otherwise, use:
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p /etc/sysctl.conf
Subnet router configuration options
Configuring a device as a subnet router involves specifying the subnet routes to advertise, disabling source network address translation (SNAT), and enabling the device to accept routes. You can use the tailscale up
or tailscale set
CLI commands to set these configuration options.
Configuration option | CLI flag | Description |
---|---|---|
Advertise subnet routes | --advertise-routes=<CIDR> | The --advertise-routes flag specifies a CIDR range of the IP addresses to be exposed to the tailnet. Access to those addresses is controlled by Tailscale access control policies. |
Disable source network address translation (SNAT) | --snat-subnet-routes=false | The --snat-subnet-routes=false flag disables source NAT (SNAT). By default, a device behind a subnet router sees traffic as originating from the subnet router. This simplifies routing but prevents traversing multiple networks. By disabling source NAT, the end device sees the IP address of the originating device as the source, which might be a Tailscale IP address or an address behind another subnet router. |
Accept routes | --accept-routes | The --accept-routes flag accepts the advertised routes of all other subnet routers in the tailnet. |
Clamp the MSS to the MTU
You should also clamp the maximum segment size (MSS) to the maximum transmission unit (MTU). You can do this using iptables
. The following command updates the Tailscale network interface (tailscale0
) to clamp MSS to MTU.
iptables -t mangle -A FORWARD -o tailscale0 -p tcp -m tcp \
--tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
Approve the subnet router
After selecting and configuring the subnet router, you must approve it from the Machines page of the admin console. If you used an auto approver policy in the tailnet policy file for the device, you don’t need to approve the subnet router manually.
- Open the Machines page of the admin console.
- Locate the subnet router devices by locating the Subnets badge or using the
property:subnet
filter. - For each subnet router:
- Select the menu > Edit route settings.
- Approve the device.
You might prefer to disable key expiry on your subnet routers to avoid having to periodically reauthenticate. If you are using tags, key expiry is disabled by default.
Update tailnet access control policies
You must update the access control policies for your tailnet to allow communication between the subnets. You can do this by updating the tailnet policy file with the appropriate ACLs or grants.
For example, the following tailnet policy file allows all traffic between the subnets using ACLs:
{
"acls": [
{
"action": "accept",
"src": [ <CIDR-range-of-Subnet-A> ],
"dst": [ <CIDR-range-of-Subnet-B> ]
},
{
"action": "accept",
"src": [ <CIDR-range-of-Subnet-B> ],
"dst": [ <CIDR-range-of-Subnet-A> ]
}
]
}
Configure the other subnet devices
After configuring and approving the subnet router, make sure the devices in the subnet use the designated subnet router for the correct routes. The best way to configure the devices in the subnet depends on your infrastructure. For example, if the subnet devices already use the subnet router as the default gateway, you don't need to configure them because they will automatically use the subnet router for all traffic (unless a more specific route applies). If the subnet devices don't use the subnet router as the default gateway, you must configure them to use the subnet router for the correct routes.
For example, on Linux devices, you can use the ip route
command. You don't need to configure the subnet devices if the subnet router you selected for the subnet is already the default gateway for the subnet.
ip route add <first-subnet-CIDR> via <first-subnet-router-IP-address>
ip route add <second-subnet-CIDR> via <second-subnet-router-IP-address>
The ip route
commands do not persist after rebooting. You must run them again after each reboot. Depending on your setup, you can make the route settings persistent by adding them to your network manager or netplan
configuration. Alternatively, you can manage route settings with a DHCP server on your network.
If the subnet is in a cloud environment, such as AWS, you can usually update the cloud provider's routing tables instead of configuring each device directly.
Example scenario
The following sections demonstrate using two subnet routers to connect two subnets within a tailnet. The example subnets and subnet routers are documented in the table below.
Subnet name | Subnet CIDR range | Subnet router IP address |
---|---|---|
Subnet A | 192.0.2.0/24 | 192.0.2.2 (subnet router A) |
Subnet B | 198.51.100.0/24 | 198.51.100.2 (subnet router A) |
To create a site-to-site connection between Subnet A and Subnet B, follow these steps:
-
Configure both subnet routers (Subnet A at
192.0.2.2
and Subnet B at198.51.100.2
):-
Install the Tailscale client on each subnet router.
-
Configure the Tailscale client.
Make sure to replace
<CIDR>
with the correct subnet routes. For the192.0.2.2
subnet router, use192.0.2.0/24
. For the198.51.100.2
subnet router, use198.51.100.0/24
.tailscale up --advertise-routes=<CIDR> --snat-subnet-routes=false --accept-routes
-
Configure
iptables
to clamp the MSS to the MTU.
-
-
Configure the subnet devices by running the following commands on each device in the subnet (except the subnet router):
-
For each device in the
192.0.2.0/24
subnet (except the subnet router), run the following commands:ip route add 100.64.0.0/10 via 192.0.2.2 ip route add 198.51.100.0/24 via 192.0.2.2
-
For each device in the
198.51.100.0/24
subnet (except the subnet router), run the following commands:ip route add 100.64.0.0/10 via 198.51.100.2 ip route add 192.0.2.0/24 via 198.51.100.2
-
-
Update the tailnet access control policies to allow communication between the subnets. In the following example, the tailnet policy file allows all traffic between the subnets using ACLs:
{ "acls": [ { "action": "accept", "src": [ 100.64.0.0/10 ], // CIDR range of Subnet A "dst": [ 192.0.2.0/24 ], // CIDR range of Subnet B }, { "action": "accept", "src": [ 192.0.2.0/24 ], // CIDR range of Subnet B "dst": [ 100.64.0.0/10 ], // CIDR range of Subnet A } ] }
-
Test the connectivity between Subnet A and Subnet B:
Now a device in Subnet A can connect to a device in Subnet B (and vice versa) without either needing to install the Tailscale client. You can test the connection by running the
ping
command from a Subnet A device to a Subnet B device. For example, ping198.51.100.3
from198.0.2.3
:ping 198.51.100.3 PING 198.51.100.3 (198.51.100.3) 56(84) bytes of data. 64 bytes from 198.51.100.3: icmp_seq=1 ttl=64 time=9.34 ms 64 bytes from 198.51.100.3: icmp_seq=2 ttl=64 time=3.85 ms