Skip to main content
ertius.org

delegating Tailscale dns to Tailscale using Unbound

After getting annoyed at systemd-resolved for the last time, I decided to just "standardise" on most machines running a proper local caching resolver. That's fine and easy, but with just resolv.conf you're more or less routing all DNS traffic to one server, which could either be localhost or Tailscale DNS, but not both. unbound makes it pretty easy to just carve out that one domain, though:

server:
    # allow it to return private IP addresses
    private-domain: "{{ tailscale_domain }}"
    forward-zone:
        name: "{{ tailscale_domain }}"
        forward-addr: {{ tailscale_dns_server}}

Ansible-y templated, where tailscale_domain is something like example.ts.net and tailscale_dns_server is likely 100.100.100.100.

Empirically, I need the private-domain because otherwise unbound suppresses A records pointing at Tailscale's 100.64.0.0/10 IPs, but I cannot find that anywhere in the docs, or even in the code itself. I also can't find where it defaults to including 192.168.0.0/16, either.

Also! Since this only routes DNS requests for that domain up to the Tailscale DNS servers, you also need to duplicate the split-DNS config in unbound for any Split DNS zones in the Tailscale configuration.

Also also, it seems that Tailscale DNS has a slightly surprising feature - you can only resolve names for other nodes if you can actually access them in some way, ie there's an ACL that lets you do something with it. I've been quite strict about not letting servers talk to each other, so for a long time I just assumed I'd screwed something up, since dig some-other-host.example.ts.net @localhost kept returning nothing. Eventually I guessed this might be the problem, so I added an ACL permitting every host to ping every other host (you can edit it here):

"acls": [
+  // everyone can ping everyone - proto 1 = ICMP
+  {"action": "accept", "src": ["*"], "proto": "1", "dst": ["*:*"]},

by combining this Reddit post and Tailscale doc.

This also made all hosts show up in the output of tailscale status.