Setting up Tailscale with Magic DNS on an OpenWrt Router
Recently I picked up a compact travel router that had an easy way of flashing OpenWrt. I had fun tinkering with it and I wanted to add it to my Headscale network (self-hosted Tailscale).
Following the initial setup in OpenWrt's Tailscale guide was straightforward. With forwarding set up I could connect to my other Tailscale machines by IP address, even without Tailscale installed on the router's clients, but conneting using just the machine name with Magic DNS doesn't work.
Either ways, you should follow the Initial Setup section of the guide there.
If you log in through SSH and have a look at /etc/resolv.conf
you'll find Tailscale overwrites it with something like so:
# resolv.conf(5) file generated by tailscale
# For more info, see https://tailscale.com/s/resolvconf-overwrite
# DO NOT EDIT THIS FILE BY HAND -- CHANGES WILL BE OVERWRITTEN
nameserver 100.100.100.100
search xxxxxx.ts.net
The search xxxxxx.ts.net
line sets the search domain, which behind the scenes adds it as a suffix when your query doesn't have a top level domain.
So when you try and connect to your machine via something like machine
, it actually looks up machine.xxxxxx.ts.net
on your Tailscale service's DNS nameserver at 100.100.100.100
and you get back the machine's Tailscale IP address.
While neat, I don't really like how Tailscale configures this by overwriting the /etc/resolv.conf
file, so I tend to disable this with
tailscale set --accept-dns=false
Thankfully this still keeps the nameserver running, allowing us to replicate the rest manually or through OpenWrt's built-in tools.
To do this, we push the search domain to the router's clients by going to Network > Interfaces > lan > Edit > DHCP Server > Advanced Settings and adding an entry for DHCP-Options with option:domain-name,lan xxxxxx.ts.net
.
Placing lan
first lets us prioritise machine.lan
over machine.xxxxxx.ts.net
for speed, but if you were relying on Tailscale to bypass the target machine's local firewall, you can place it second or remove it.
Next up, under Network > DHCP and DNS > Forwards we add an entry for DNS Forwards /*.xxxxxx.ts.net/100.100.100.100
. Tailscale's DNS returns anything outside its purview with "not found" so we need to restrict it to just your Tailscale domain.
This is also where you can add other upstream DNS servers like Cloudflare's 1.1.1.1
.
If you'd rather do all this through command line you could use something like:
uci add_list dhcp.lan.dhcp_option='option:domain-name,lan xxxxxx.ts.net'
uci add_list dhcp.@dnsmasq[0].server='/*.xxxxxx.ts.net/100.100.100.100'
As a final touch my travel router has a switch on the side that OpenWrt can listen to and run commands. I wanted this switch to toggle on/off routing all traffic through one of my Tailscale exit nodes, making it a VPN switch.
So I wrote a script you can save to /etc/rc.button/BTN_0
, or adapt it to your router's buttons if its different. (Don't forget to add it to your list of files to preserve when upgrading, under System > Backup / Flash Firmware > Configurations).
#!/bin/sh
[ "${BUTTON}" = "BTN_0" ] || exit 0
EXIT_NODE="nodename"
remove_wan_forwarding() {
uci show firewall |\
awk -F. '{print $2}' |\
awk -F= '{print $1}' |\
grep @forwarding |\
sort -u |\
while read i; do
src=`uci get "firewall.$i.src"`
dest=`uci get "firewall.$i.dest"`
[[ "$src" = "lan" ]] && [[ "$dest" = "wan" ]] || continue
uci delete "firewall.$i"
done
}
if [ "${ACTION}" = "pressed" ]; then
logger "tailscale tunnel on"
tailscale set --exit-node="$EXIT_NODE" --exit-node-allow-lan-access=true
remove_wan_forwarding
uci commit firewall
service firewall restart
elif [ "${ACTION}" = "released" ]; then
logger "tailscale tunnel off"
tailscale set --exit-node= --exit-node-allow-lan-access=false
remove_wan_forwarding
uci add firewall forwarding
uci set firewall.@forwarding[-1]=forwarding
uci set firewall.@forwarding[-1].src=lan
uci set firewall.@forwarding[-1].dest=wan
uci commit firewall
service firewall restart
fi
This whole thing took a couple of days of trial and error to figure out, but I hope it has been useful! For good measure I also added a script from OpenWrt's guide that simplifies reinstalling the Tailscale packages on upgrade.