A Simple Dynamic DNS for Home Networks
It's similar to http://smorgasbord.gavagai.nl/2011/08/homemade-dynamic-dns-service/ except that it works only for home networks without the need for external domain name.
Typical setup addressed by this article
A home network of computers, connected by one wired/wireless home router (perhaps also acting as a modem for Internet access), which also acts as DHCP server for all computers in the network.
What you will need:
- An always-on machine to act as a DNS cache (running dnsmasq). This machine will be referred as "the server".
Overview of what we will do
- We will run dnsmasq as
a DNS cache for our home network. Instead of going direct to modem's or
ISP's DNS server, we will tell all our home computers to resolve their
DNS through our dnsmasq. Dnsmasq will then forward our request to
upstream DNS server for Internet names, but will resolve the names for
our local machines directly.
- We will setup a simple mechanism to dynamically update dnsmasq's
knowledge of the home network's IP addresses and names when they change.
- We will create a simple program to use this mechanism to update dnsmasq with our new IP address/hostname each time they change (e.g. getting a new IP address from the DHCP server).
- Get a working dnsmasq package for the server.
- Preferably use a fixed (internal) IP address of the server, in the same
subnet as the rest of the home network.
- Using either configuration file or command line parameter (config file is preferred), tell dnsmasq to:
- provide DNS caching service only (no DHCP - DHCP service is already
provided by the home router).
- tell dnsmasq to use upstream (router's or ISP's or Google's or OpenDNS's
DNS server addresses) for forwarding DNS requests
- tell dnsmasq to ignore the system's
/etc/hostsbut instead read a bunch of hosts-file-like configuration from a specified directory, say,
/tmp/hosts. A file whose content looks like this:
/tmp/hosts, one for each IP address/host.
- example dnsmasq.conf file based on the above points (using OpenDNS as
upstream DNS servers)
domain-needed bogus-priv no-resolv server=184.108.40.206 server=220.127.116.11 no-hosts addn-hosts=/tmp/hosts
/tmp/hosts. This can be anything; if you wish you can run a samba server (an overkill, but works); or run ssh/dropbear server, ftp server, web server with php/ruby/python/generic CGI, etc.
For this article, however, I will just use busybox' version of netcat
nc) to do the job - it will listen to a specified port and execute
a shell script when something connects to that port (=a poor man's inetd).
The script reads a line that contains an action, password, hostname and
IP address. If the password matches, the script will create/update/delete
a hostfile entry in
/tmp/hosts depending on the action.
/tmp/hostsif they change. You have to send SIGHUP to dnsmasq to tell it to re-load its configuration files including re-reading
/tmp/hosts. But that's not a problem, we can either setup a inotify watch on the directory and sends SIGHUP to dnsmasq when it changes; or you can immediately send SIGHUP from the script that nc executes after it updates
/tmp/hosts(this is what I do).
All that the clients (ie the other computers) need to do is to watch for changes in its IP address (and hostname too, but hostname rarely changes so I don't even bother here); usually because it gets a new lease, but may be for other reasons too. As soon as it detects that the IP address has changed, contact the server to tell it of its new address.
For this article - matching the simple server - to do the update is very
simple as well: just use
nc again to contact the server's
nc to push
the details. In fact, if
bash is your shell, you don't even need
here - you can send the command just by
echo-ing to bash's virtual
To detect the IP address change, the easiest to use "
ip monitor" command,
available from iproute2 package (unfortunately busybox'
ip command has
not yet supported the "monitor" sub-command). But this package isn't included
in Fatdog64 or Puppy, so instead I've adapted a simple C client (ipmon.c)
that uses netlink to detect the changes and output the new IP address to
stdout. It should be straightforward to change the script to use
ip monitor instead, if you wish.
To glue all these together, we need to instruct the DHCP server on the home router to hand out our dnsmasq server as the DNS IP address, instead of the original modem/router/ISP DNS IP address (that's the reason why the dnsmasq server IP address should be fixed). This can usually be done through the modem/router's configuration page.
If this is not possible, then we'll just have to modify the dhcp script which
/etc/resolv.conf on the client machines to use our dnsmasq server
IP address instead of using one obtained from DHCP server.
If this is still too difficult, then one can use inotify to watch
/etc/resolv.conf and as soon as the file is changed
(by DHCP client presumably), override it again with our dnsmasq server address.
/etc/resolv.conf- the first one (which will have priority) is the dnsmasq server; and the second one is a upstream DNS server (your modem's, your ISP's, Google's, OpenDNS's, etc) which will be used if the first nameserver can't be contacted.
This ensures that your network can still access the Internet even when your dnsmasq server is down for whatever reason.
The tarball contains dnsmasq configuration and scripts for server setup, scripts for client setup, ipmon.c, statically-compiled ipmon for x86-64 (Fatdog64) and ARMv6 (FatdogArm).
Get it here.
Note: If you choose not to use
nc as the update mechanism,
you can uncomment watch_hostdir in the server's init script so that
/tmp/hosts are automatically applied (this requires
Comparison with other methods
Works, and works better than the method outlined here, but it requires a special DNS resolver (nss-mdns) and a daemon to respond to the mdns requests. The typical daemons are Bonjour and Avahi; both of these have larger scope and just doing DNS resolution (they also do for service advertisement and discovery). All machines must run one of these to participate.
With the method of the article, a machine which doesn't run the "client" setup can still participate - it can still contacts other machines by normal DNS resolution (this is especially true if the modem/router can be configured to hand out dnsmasq server IP address during DHCP negotiation); although it itself isn't contactable.
The idea is the same (in fact, the above site is where I get the inspiration from), only the implementation is different. The above site uses sheerdns as the DNS server (instead of dnsmasq), and uses Apache/Python/PHP for the 'client' setup to update the name server.
Sheerdns is an authoritative server, not a caching nameserver; so to run it you need a fully-qualified domain over which you have been delegated as its authority. It's good if the scope is the Internet (you can use it just like a proper dynamic DNS service like no-ip.org, dyndns.org, etc).
The idea of contacting an URL managed with a wildcard CNAME is clever (contacting the URL http://kitten.reg-a-record.tld/reg.php will create a DNS entry for "kitten" with the caller's IP address - no form filling is necessary), but it requires a heavier infrastructure (at least a web server with CGI). The benefit is, since it uses HTTP, it works with all sorts of clients, not only desktops (it also works smartphones, etc).
Concluding remarks and notes
You can achieve the same thing with even less work if you disable your router's DHCP server altogether, and instead run dnsmasq as both your DHCP (and caching DNS) server.
Dnsmasq can provide DNS resolution to hostnames it receives through DHCP requests - so as soon as a machine in the network is started and it asks for an IP address (and declare its preferred hostname); dnsmasq will allocate the IP address for that machine and automagically map that hostname to this IP address for later DNS resolution requests. No other server/clients are necessary: dnsmasq is your server and your DHCP client is your client.
This, by its very mechanism, is not secure. The hostname is provided by the 'client' machine, the IP address is also provided by the 'client' machine, it is easy for a client machine to create multiple entries and spoof names of other client machines to point them to itself.
Use this only in a closed network where the participating machines are not hostile.