Setup Split DNS and Reverse Proxy for Tailscale

Tailscale is super easy to use and configure. It’s based on WireGuard. You can read about it here.

By default, all devices inside your tailnet will receive a domain name via MagicDNS. Here’s my list of active machines:

MacBook-Pro:~ kavish$ tailscale status --peers
100.124.220.115 macbook              kavishgr@    macOS   -
100.79.20.48    ubuntu               kavishgr@    linux   -

Only devices on which tailscale is installed, will receive DNS. To be able to access devices on which tailscale can’t be installed(or you don’t want to for some reason), you need to deploy a subnet router. You can read about subnet routers here.

Connect as a Subnet Router

I’ll be using my Ubuntu machine as a tailscale subnet router. It will route traffics to my docker containers on the 192.168.200.0/24 subnet(custom bridge docker network).

Connecting ubuntu to Tailscale as a subnet router and advertising the route:

sudo tailscale up --advertise-routes=192.168.200.0/24 --auth-key="file:tskey" --accept-routes

Enable IP Forwarding

Enable IP Forwarding:

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p /etc/sysctl.conf

Go to the Tailscale admin console in your browser, and activate the route.

Setup Split DNS and Reverse Proxy

Next I’ll be setting up AdGuard as my split DNS server for *.home.local, and Nginx Reverse Proxy Manager(NPM) as my reverse proxy in Docker Compose:

version: '3.9'
services:
  tsapache:
    image: httpd:alpine3.16  
    volumes:
      - ./tsapache:/usr/local/apache2/htdocs
    networks:
      tailscale:
        ipv4_address: 192.168.200.5
  tsnginx:
    image: nginx:stable-alpine
    volumes:
      - ./tsnginx:/usr/share/nginx/html
    networks:
      tailscale:
        ipv4_address: 192.168.200.4
  nginx-proxy-manager:
    image: jc21/nginx-proxy-manager
    volumes:
      - ./nginx-proxy-manager/data:/data
    networks:
      tailscale:
        ipv4_address: 192.168.200.3
  adguardhome:
    image: adguard/adguardhome
    volumes:
      - ./adguard/work:/opt/adguardhome/work
      - ./adguard/conf:/opt/adguardhome/conf
    networks:
      tailscale:
        ipv4_address: 192.168.200.2

networks:
  tailscale:
    external: true

Browse to 192.168.200.2(AdGuard) and write a DNS rule that will point all *.home.local to 192.168.200.3(NPM). tsapache and tsnginx are dummy web servers.

Add NPM host rules

In NPM, I wrote 4 Proxy Hosts rules:

adguard.home.local -> http://192.168.200.2:80
apacheweb.home.local -> http://192.168.200.5:80
nginxweb.home.local -> http://192.168.200.4:80
nginxproxy.home.local -> http://192.168.200.3:81

In Tailscale’s admin console, go the DNS page, and add the IP of Adguard 192.168.200.2 as split DNS for home.local.

Access my containers vis DNS

Now I can access my containers via DNS:

MacBook-Pro:~ kavish$ curl apacheweb.home.local
<h1>TSAPACHE</h1>
MacBook-Pro:~ kavish$ 
MacBook-Pro:~ kavish$ curl nginxweb.home.local
<h1>TSNGINX</h1>

To access Adguard and NPM, I can simply browse to adguard.home.local or nginxproxy.home.local. That’s pretty cool. Tailscale took care of everything. I didn’t have to modify my firewall or network ports.

"Start children off on the way they should go, and even when they are old they will not turn from it." - Proverbs 22:6