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.