A little introduction to DNS
To understand the problems with free dynamic DNS providers and the solution we use for it, it’s necessary to understand the basic structure of DNS.
The tree structure
While the most structures in the internet look like a network of independent knots the domain name system has a tree structure. The root of this tree contains the TLDs (e.g. “de”, “com”, “net”, “org”, …). Each of those TLDs then has it’s own subtree. Let’s consider “org” to have the nodes “example” and “wikipedia”. Now “wikipedia” again is splitted into a few subdomains … So a subtree of the whole DNS might look like this:
- org
- example
- wikipedia
- en
- de
- fr
- com
When talking about the tree of the DNS, the word “zone” is used to refer to certain subtree of the DNS. For example the zone “wikipedia.org” contains the names “en”, “de” and “fr” in the given tree. The root zone is oftened refered with a single “.”, so that you might come across domains like “de.wikipedia.org.” when you investigate the domain name system.
The resource records
Now all this domain names are useless without pointing to addresses. So each zone needs something like a database containing information about the domain names. The entries in this database are called “resource records” and we will explain the types of records that are used quite often:
- SOA
SOA records are used to declare the authority for a certain domain. Beside various information on the intervals the information should be refreshed in other servers it contains the mail address of the zone administrator.
- NS
NS records are used to tell other DNS servers on the internet which nameserver handles requests for a certain zone
- A
A records are the most often used records in the DNS. They contain the information which (IPv4) address a domain points at. One domain name might also have multiple A records which will be replied in a cycling order, that way DNS can be used to do a simple load balancing.
- AAAA
AAAA is the IPv6 pendant to A.
- CNAME
CNAME records are used to make a certain domain an alias for another domain name. If a client recieves a CNAME record during a lookup it changes the domain name to the new domain name and performs another lookup.
- MX
MX records contain information about mailserver that are responsible for domains. When you send an email to “foo@example.com”, the mail transfer agents looks for an MX record for example.com and contacts the refered mailserver to deliver the email.
Now that you know the basics, let me explain something …
Why don’t you use DynDNS or No-IP?
If you don’t own a domain and just want to provide some name for you dynamic address to pass around to your friends, using those free services can make you happy. But as soon as you want to use your own domain the trouble begins. Of course one could use some sort of alias from your own domain to the subdomain provided by DynDNS, you would just put a CNAME resource record in your own zone pointing to the dynamic subdomain. Anyway, using a CNAME record forbids to use any other records on that domain name, because it really is just an alias domain. Okay, and what’s the problem with that? In our case the problem was that we have IPv6 addresses on our machines, so the domain name pointing to a host with a dynamic IPv4 and a static IPv6 address needs at least two records: An A record that will be changed when the IP address changes and an AAAA record for the IPv6 address. As far as we know there is no free service that allows you to add custom records to the domain you use for dynamic DNS. That’s just one of the reasons why we decided to leave those providers and try what we could achieve on our own.
Not using HTTP requests
Unlike all free dynamic DNS providers, we didn’t want to use updates based on HTTP requests. Why not? The first reason is that HTTP is really not the slave you should use for everything, it was invented to provide linked information for scientists and is now being violated by a lot applications that don’t use it for providing information but abusing it’s request mechanism. Beside that it is insecure, some man in the middle might capture your TCP stream and then redirect your domain to an arbitrary address.
To keep the mechanism itself independent of update-protocols, we decided to watch out for changes in the filesystem. So we use files like /home/user/.dynamicdns that contains the address the domain will point to and watch it for changes to update the database.
dns-updater: pyinotfiy at it’s best
Since version 2.6.13 the linux kernel provides a subsystem called inotify, that allows you to watch the filesystem for events like file creation, modification etc. and comes in quite handy for watching if the user changed his ~/.dynamicdns file.
Being happy with using tinydns as a nameserver, we developed a daemon that registers inotify watchers on the users .dynamicdns files and updates tinys database to match the desired ip addresses.
The daemon is written in Python and uses pyinotify to access the inotify subsystem. You can get a copy by cloning it from our git repository:
git clone git://git.eta-ori.net/dns-updater.git
The example configuration file should be self explaining, but i’ll provide a short description of the values:
- ttl
This is the time-to-live value, dns caches will not keep the records longer than this value (in seconds).
- pathpattern
The pattern to describe where the address files are stored, as you might not want to restrict your dynamic dns service to system users, you can change this to match your environment.
- makecommand
tinydns uses a Makefile to recreate its database, this is the command that is executed after dns-updater has changed the datafile.
- datafile
Here you can set the path of the datafile tinydns uses.
- log_tempfile
This file will contain the latest logmessage of the daemon, it’s content is piped to the logger binary to support syslog without opening a security hole.
- users
a list of the users and the domain names belonging to them, you can specify multiple domain names for a single user. All of them will be updated when the users address file is changed
After finishing the configuration, you might want to use an initscript in /etc/init.d to start dns-updater. If you use Gentoo, just copy the init.d/dns-updater and conf.d/dns-updater files to your etc directory and adjust the settings in /etc/conf.d/dns-updater. Non-Gentoo users might alter the shipped initscript to fit the expectations of the used distribution.
To finish the configuration, you will need to change your tinydns data file, so that dns-updater knows where to put its records. You should put this section at the very top of the file so that there are no wildcards that override this records, the section should look like this:
# start dynamic dns entries # end dynamic dns entries
Now before you start dns-updater, you will need to create the address files for the users you want to activate, because dns-updater registers watchers on the startup and can not register watchers on files that don’t exists! Make sure dns-updater has read permissions and the user who should alter the address has write permissions.
You can check your syslog if dns-updater was started. It should look like this:May 16 16:40:46 [dns-updater] started
To be sure it is running properly, do your first dynamic dns update:
# echo 1.2.3.4 > /home/john/.dynamicdns # tail -n 3 /var/log/everything/current May 16 16:46:27 [dns-updater] user john requested update to 1.2.3.4 May 16 16:46:27 [dns-updater] updating record for john.dyn.example.com to 1.2.3.4 May 16 16:46:27 [dns-updater] updating record for john.dyn.example.org to 1.2.3.4
You can now perform a lookup to check if it’s really working. It is? Great!
Remote updates
The easiest way to perform remote updates now is just:
ssh host 'echo 1.2.3.4 > .dynamicdns'
As many embedded routers only support HTTP requests for updating dynamic DNS records, we are working on a python script to catch HTTP requests from those routers and alter the address file.
We will tell you about it when it’s done, have fun with your dynamic DNS :)