DNS without a Server
A few days ago I’d decided to configure Raspberry PI as a weather station to check temperature,
humidity, and pressure. So I need to access it on the network with SSH and a web browser. The
easiest way of solving this problem is using a static IP address. In this case, I have to set static
IP for Raspberry PI and then use this address in a browser. For me, it’s more convenient to use a
human-readable hostname than remembering an IP address. I can modify /etc/hosts
to associate
Raspberry PI IP with custom hostname but I have to perform this action on all of my devices. It’s a
bit monotonous work if you have several computers and for some mobile devices, it’s impossible to
configure.
In the case of complicated enterprise networks, it’s common to configure a name server to perform
hostname resolution, but for a small home network with several computers, it can be a bit overkill
to configure and support a dedicated DNS server. Searching through the Internet I’d found
an article about connecting Raspberry PI to
an iPad with a USB cable. The author accessed a device with the address raspberrypi.local
without
any additional DNS configuration. So it should be a more lightweight alternative than a dedicated
DNS server for home networks.
A computer connected to a network has an address of the DNS server as a part of its network configuration. When a piece of software (e.g. web browser) tries to access a remote host using hostname it asks the DNS server to resolve a hostname into an IP address and then access a remote host using the received IP address.
But what if there is no DNS server? Is it possible to perform hostname resolution? There is a set of
technologies called zeroconf. It
allows to creates a usable computer network without any additional manual configuration. One part of
zeroconf is a Multicast DNS (mDNS) — a technology
that allows resolving some hostnames without a dedicated DNS server. When a mDNS client needs to
resolve a hostname, it sends a multicast message to 224.0.0.251
(or ff02::fb
for IPv6) that asks
the host having that name to identify itself. The target machine multicasts a response with its
address, so all computers in the network can use this information to update their mDNS caches.
Multicast DNS is supported by various operating systems like Linux, MacOS X, or Windows 10.
Usually, there is a file on Linux devices named /etc/nnswitch.conf
that allows different
applications to determine the sources from which to obtain name-service information and in what
order. On my Ubuntu 20.04 desktop the configuration looks like this:
hosts: files mdns4_minimal [NOTFOUND=return] dns mymachines
It describes such a chain of actions:
- check
/etc/hosts
for a requested address; - if
.local
domain was requested make a mDNS IPv4 request with avahi-daemon; - if mDNS lookup succeeded, but the requested entry was not found stop any further attempts;
- make a DNS request;
- try to resolve a hostname of container registered with systemd-machined.
There are two services on Ubuntu that provide mDNS support: Avahi and systemd-resolved. By default, Ubuntu 20.04 uses Avahi for mDNS requests and systemd-resolved for DNS requests.
One more useful service connected with mDNS is DNS Service Discovery. It’s a way of using standard DNS programming interfaces, servers, and packet formats to browse the network for services like printers, file-sharing, or chats.
It’s a pity but I haven’t found how to configure Android Chrome to support mDNS. Moreover by default
my Android phone ignores DNS server from the router and uses 8.8.8.8
that is why even
configuration with a dedicated DNS server will not work out of the box. So I need to access my
Raspberry PI with IP address from my Android devices.
After all, a just set a hostname weather
for the Raspberry PI, configured nginx to listen to port
80 and it made it possible to check the weather with http://weather.local
from my computers and
iOS devices.