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
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.
The most obvious solution is to stick some entries like this in
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.
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 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.
On glibc-based distros, hostnames will be resolved using a list of strategies listed in
/etc/nsswitch.conf. We’re interested in the
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.
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.
~/.config/hosts file contains what you would normally put in
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!