Tailscale Subnet Router

If you’ve ever wanted to get secure remote access to something on the inside of your private network without the risk of exposing services to the public Internet, Tailscale is your friend and I recommend that you check it out.

Tailscale is a VPN that’s built on top of the WireGuard® protocol. It allows you to create a secure, private network (a “tailnet”) between your devices, no matter where they are in the world. Think of it as a virtual Ethernet cable that connects your laptop, phone, and home server as if they were plugged into the same switch. Once you install Tailscale on your devices, they’ll be able to communicate with each other and without poking holes in firewalls and port forwarding inbound traffic from the public Internet.

Its uses are endless but in this example we’re specifically looking at using Tailscale as a subnet router. Running in this configuration, it can expose inside systems and devices that don’t have Tailscale installed, much like how a traditional VPN works.

Not to cast shade on Windows, but we’re deploying Tailscale on Linux as it’s reportedly more performant. I’ve never installed it on Windows and this just works and so I don’t have an opinion. Just sharing what has worked for me.

Installation

On most modern Linux distributions, you can use the one-line installation script provided by Tailscale. This automatically handles the signing keys and repository setup for your specific version.

curl -fsSL https://tailscale.com/install.sh | sh

Enable IP Forwarding

If you are using this device as a Subnet Router, Linux requires IP forwarding to be enabled to pass traffic from the Tailscale network to your local network.

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

Route Advertisement

Connect the subnet router device and tell Tailscale which local subnet(s) you want to share. Replace the example IPs with your actual local network range.

sudo tailscale up --advertise-routes=172.16.21.0/23

Admin Panel

Log into the Tailscale Admin portal to Approve the Subnet Router and the Route

By default, access control, configured in the Tailscale Admin Panel, allows all traffic to flow in and out of your Tailnet. Although handy if that’s what you want, I like to deny all traffic by default and then only permit the traffic I want. For example, if I wanted to access 172.16.21.10 (note that there’s no Tailscale app installed on this host) using RDP on my phone, I could create an ACL in the Tailscale Admin Panel to permit my identity (user@example.com) to access host with IP 172.16.21.10 using tcp 3389. If you did everything right, the workflow would look like:

  1. Log into Tailscale app on your phone using your identity user@example.com
  2. Open your RDP client
  3. Connect to your inside host 172.16.21.10

Here’s what’s happening under the hood:

  1. Request: You type 172.16.21.10 into your client
  2. Routing: Tailscale sees that this IP matches the “Advertised Route” from your subnet router. It wraps that packet in WireGuard encryption and sends it to the router.
  3. Handoff: The subnet router unwraps the packet and drops it onto your local physical network.
  4. Response: The target host (172.16.21.10) sees the request and sends data back.
Scroll to Top