
User-Friendly Hostnames with Yggdrasil
Yggdrasil allows you to easily set up a private virtual network based on IPv6.
Your machines will then receive an IPv6 address such as 201:2af6:fcc4:30e7:b22d:15d6:a55d:10bb
. However, that’s not
very fun to have to type, and it would be nicer to be able to refer to your machines by their hostnames, e.g. by doing
ping apples
and ping pears
.
I tried to do this in an intelligent way and failed, which led me to resort to setting up a local dnsmasq server to solve the problem. Still, I thought I’d write about my reasoning, since it could lead to a better solution in the future.
Hosts file
The most obvious solution is to stick some entries like this in /etc/hosts
:
201:2af6:fcc4:30e7:b22d:15d6:a55d:10bb apples
202:a024:caff:1010:b501:14e2:ee1e:4400 pears
However, I don’t like this solution, because this file needs to be in a system-wide location, which means it’s difficult to version, which in turn means you have to update it separately on each machine. Let’s look for something else.
mDNS
Usually, you might accomplish this using something based on multicast DNS (mDNS), such as Avahi. These solutions send out a multicast packet to all machines on some local network, asking for information about themselves. This means that all machines on the local network are automatically discovered with zero configuration and can be referred to by their hostnames out of the box:
vladh usu ~:main $ avahi-browse -a
+ wlp0s20f3 IPv6 usu [d8:3b:bf:b3:c7:2a] Workstation local
+ wlp0s20f3 IPv6 Music Player @ usu[443] Music Player Daemon local
+ wlp0s20f3 IPv4 RouterA [00:11:32:ab:55:bf] Workstation local
+ wlp0s20f3 IPv4 RouterB [00:11:32:b1:87:4d] Workstation local
+ wlp0s20f3 IPv6 RouterB [00:11:32:b1:87:4d] Workstation local
+ wlp0s20f3 IPv4 EPSON WF-7710 Series UNIX Printer local
+ wlp0s20f3 IPv4 XXXXX___s iPhone _rdlink._tcp local
Unfortunately, Yggdrasil doesn’t support multicast networking, so this won’t work. Still, perhaps we can get some hints if we look at how mDNS is integrated into the Linux networking stack.
nsswitch
On glibc-based distros, hostnames will be resolved using a list of strategies listed in
/etc/nsswitch.conf
. We’re interested in the hosts
entry, and here’s what that might look like:
hosts: mdns_minimal [NOTFOUND=return] files dns
This is saying that, first of all, the mdns_minimal
plugin should be tried, which is the plugin that calls out to
Avahi to make that multicast request. If that doesn’t work, we can try using the files
plugin, which just looks the
hostname up in /etc/hosts
. If our hostname is not in there either, we fall back to the dns
plugin, which looks up
the nameserver we’re using in /etc/resolv.conf
and makes a DNS request.
The ideal solution would probably involve adding some kind of yggdrasil
plugin, which asks Yggdrasil for the list of
peers we can connect to and attempts to resolve hostnames that way.
Unfortunately, this plugin doesn’t exist (perhaps you want to write it?). Additionally, nsswitch
is only supported in
glibc-based distros, so musl-based distros such as Alpine Linux would not support this approach at all, just like they
don’t support any kind of mDNS.
dnsmasq
None of the things we’ve tried so far ended up working, so let’s just set up the most obvious solution. We could run our DNS requests through a local instance of lightweight DNS server dnsmasq. Then, we can tell dnsmasq to return a specific IP when queried for the address of a certain host.
I use NetworkManager, so I set up dnsmasq with it as described on
ArchWiki. Then, I created a dnsmasq.conf
file in
/etc/NetworkManager/dnsmasq.d
with the following contents:
addn-hosts=/home/vladh/.config/hosts
The ~/.config/hosts
file contains what you would normally put in /etc/hosts
:
201:2af6:fcc4:30e7:b22d:15d6:a55d:10bb apples
202:a024:caff:1010:b501:14e2:ee1e:4400 pears
However, this file is inside my home folder, so it’s very easy to version. Also, running dnsmasq has some other benefits, such as the performance boost gained from having a local caching DNS server. I will also use this file to define custom hosts for other purposes than Yggdrasil, for example to make up for the lack of mDNS support on Alpine Linux.
The downside is that hosts are not automatically detected, so you still have to update a file when you add a new machine.
Overall, I think this solution is good enough. Let me know if you know of a better approach!