Posts for the month of August 2014

Implementing a self-hosted DD-WRT-compatible DDNS service using Linode

The free lunch that vanished

I long used dyndns.org for their free dynamic DNS service, but a while back, they decided to require periodic manual login to keep your account. I failed to do so, and they closed my account. When I created a new account, I discovered that the DNS domains I used to use were no longer offered to free accounts. (And apparently they have since stopped offering free accounts at all.) Since I use linode for retracile.net, I manually added a couple of entries to my own domain pointing to the IP addresses in question, and hoped for the best, knowing that eventually the IPs would change and the non-dynamic nature of the solution would bite me.

Recently, it did just that.

Cooking my own meal

So, when faced with a choice of spending 5 minutes to sign up for a free account with some dynamic DNS provider, and spending a chunk of my day coding up an independent solution, I naturally chose the harder path. This yielded ddns.py, a CGI script which provides a DDNS-compatible interface to Linode's Domain Manager that can be used by routers running DD-WRT.

When hosted on a server that all the clients can reliably reach, that script will update a set of hostnames in your domain based on the username with which the client authenticated. The configuration file, ddns.ini (saved in the directory with ddns.py) looks something like this:

[ddns]
key=authenticationtokenfromlinode

[someusername]
domains=host1.example.com, host2.example.com

[someotherusername]
domains=host3.example.com, host4.example.com

The key value in the ddns section is the Linode API authentication token you generate for this purpose. Then each section is a username, and in each of those sections, the domains key is a comma-separated list of hostnames to update to the IP of the client.

Use htpasswd to create an htpasswd file with a username matching each section in your configuration. Each client should have its own account.

Configure your webserver to run ddns.py as a particular URL on your site by adding a section like this example for Apache to your configuration:

<Location /myddnsservice>
    AuthType Basic
    AuthName "DDNS updater"
    AuthUserFile /path/to/htpasswd
    Require valid-user
</Location>

And configuring it to run ddns.py as a CGI script:

ScriptAlias /myddnsservice "/path/to/ddns.py"

Then configure your client. For routers running DD-WRT firmware, configure the DDNS client (under Setup -> DDNS).

  • Set "DDNS Service" to "Custom"
  • Set "DYNDNS Server" to the name of the server running ddns.py
  • Set "Username" to the username to match a section in ddns.ini
  • Set "Password" to the password for that user
  • Set some value in the Hostname field so that DD-WRT is happy, though ddns.py does not use it.
  • Set the URL to "/yourddnsurl?q=" so that the hostname it passes gets used as a parameter and is thus ignored by ddns.py

Ants at the picnic

There is just one problem.

Apparently DD-WRT's dynamic DNS updater client, INADYN, does not support SSL for communicating with the dynamic DNS provider, which means that any eavesdropper can see the username/password for authenticating to your little DDNS service, and then point your DDNS entries at his own IP address. There is, however, another INADYN project that specifically touts support for https.

Clearly, this is a critical issue that DD-WRT has promised to fix soon, right? Sadly, no. It was reported 5 years ago and the ticket closed as 'wontfix' 3 years ago. That leaves me wondering why I haven't heard of wide-spread dynamic DNS entry vandalism. I attempted to comment on their ticket to encourage them to reconsider their apparent priorities, but my account registration attempt yielded an internal error from their site, as did my attempt to login with the credentials I had attempted to register.

So, while this system is functional, it is not secure, and thus I cannot recommend anyone actually use it -- especially for anything important. But more than that, if you are relying on a DD-WRT router to update a DDNS entry for anything mission critical, perhaps you should reconsider due to the lack of meaningful security on those updates.