:wc: relfile 00-WikiIndex ---3 A Simple Dynamic DNS for Home Networks %abs= This article explains how to provide a simple dynamic DNS for home networks, so that all Linux machines in the network can be addressed by name instead of by their IP addresses. 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. %= ---4 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__". . ---4 Overview of what we will do - We will run [[http://www.thekelleys.org.uk/dnsmasq/doc.html] 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). . ---4 The 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/hosts== but instead read a bunch of hosts-file-like configuration from a specified directory, say, ==/tmp/hosts==. A file whose content looks like this: ---== 192.168.201.15 my-machine ---= will then be read and used by dnsmasq to perform IP address/name mapping. When that file is present, a DNS resolution request to dnsmasq for "my-machine" will be resolved as "192.168.201.15". Dnsmasq also provides reverse-lookup as well (192.168.201.15 will be mapped back to "my-machine"). We can put as many files like this in that ==/tmp/hosts==, one for each IP address/host. - example dnsmasq.conf file based on the above points (using OpenDNS as upstream DNS servers) ---==example domain-needed bogus-priv no-resolv server=208.67.222.222 server=208.67.220.220 no-hosts addn-hosts=/tmp/hosts ---= # Create a few init script to start dnsmasq at boot time, using the correct config file (or parameters). # Create a simple "server" to allow other machines to deposit or update a file into the server's ==/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. # Dnsmasq doesn't automatically reload the files in the ==/tmp/hosts== if 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). . ---4 The Client 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 ==nc== here - you can send the command just by ==echo==-ing to bash's virtual ==/dev/tcp/host/port==. 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. ---4 The Modem/Router 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 updates ==/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. %wikiseq= As a precaution, ensure that you put two nameserver entries in ==/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. %= ---4 Download 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 [[/wiki/main/files/local-dyndns.tar.bz2] 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 changes to ==/tmp/hosts== are automatically applied (this requires busybox' ==inotifyd==). ---4 Comparison with other methods # [[http://en.wikipedia.org/wiki/Multicast_DNS] mDNS] (multicast DNS/nss-mdns/Bonjour/Avahi) 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. # http://smorgasbord.gavagai.nl/2011/08/homemade-dynamic-dns-service/ 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 [[http://threading.2038bug.com/sheerdns/] 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). . ---4 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. %notice= ---* Security Notes 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. %=