powerdyn - a dynamic DNS service for PowerDNS users

You may not know this, but I am a huge PowerDNS fan. This may be because it is so simple to use, supports different databases as backends or maybe just because I do not like BIND, pick one. I also happen to live in Germany where ISPs usually do not give static IP-addresses to private customers. Unless you pay extra or limit yourself to a bunch of providers that do good service but rely on old (DSL) technology, limiting you to some 16MBit/s down and 1MBit/s up. Luckily my ISP does not force the IP-address change, but it does happen from time to time (once in a couple of month usually). To access the machine(s) at home while on a non-IPv6-capable connection, I have been using my old (old, old, old) DynDNS.com account and pointing a CNAME from under die-welt.net to it. Some time ago, DynDNS.com started supporting AAAA records in their zones and I was happy: no need to type hostname.ipv6.kerker.die-welt.net to connect via v6 -- just let the application decide. Well, yes, almost. It's just DynDNS.com resets the AAAA record when you update the A record with ddclient and there is currently no IPv6 support in any of the DynDNS.com clients for Linux. So I end up with no AAAA record and am not as happy as I should be. Last Friday I got a mail from DynDNS:

Starting now, if you would like to maintain your free Dyn account, you must now log into your account once a month. Failure to do so will result in expiration and loss of your hostname. Note that using an update client will no longer suffice for this monthly login. You will still continue to get email alerts every 30 days if your email address is current. Yes, thank you very much...
Given that I have enough nameservers under my control and love hacking, I started writing an own dynamic DNS service. Actually you cannot call it a service. Or dynamic. But it's my own, and it does DNS: powerdyn. It is actually just a script, that can update DNS records in SQL (from which PowerDNS serves the zones). When you design such a "service", you first think about user authentication and proper information transport. The machine that runs my PowerDNS database is reachable via SSH, so let's use SSH for that. You do not only get user authentication, server authentication and properly crypted data transport, you also do not have to try hard to find out the IP-address you want to update the hostname to, just use $SSH_CLIENT from your environment. If you expected further explanation what has to be done next: sorry, we're done. We have the user (or hostname) by looking at the SSH credentials, and we have the IP-address to update it to if the data in the database is outdated. The only thing missing is some execution daemon or ... cron(8). :) The machine at home has the following cron entry now:
*/5 * * * * ssh -4 -T -i /home/evgeni/.ssh/powerdyn_rsa powerdyn@ssh.die-welt.net
This connects to the machine with the database via v4 (my IPv6 address does not change) and that's all. As an alternative, one can add the ssh call in /etc/network/if-up.d/, /etc/ppp/ip-up.d/ or /etc/ppp/ipv6-up.d (depending on your setup) to be executed every time the connection goes up. The machine with the database has the following authorized_keys entry for the powerdyn user:
no-agent-forwarding,no-port-forwarding,no-pty,no-X11-forwarding,no-user-rc,\ 
command="/home/powerdyn/powerdyn/powerdyn dorei.kerker.die-welt.net" ssh-rsa AAAA... evgeni@dorei
By forcing the command, the user has no way to get the database-credentials the script uses to write to the database and neither cannot update a different host. That seems secure enough for me. It won't scale for a setup as DynDNS.com and the user-management sucks (you even have to create the entries in the database first, the script can only update them), but it works fine for me and I bet it would for others too :) Update: included suggestions by XX and Helmut from the comments.

Comments

XX wrote on 2013-05-19 23:53:

To do it correctly, you need also disable port-forwarding etc. (if you have not done it via your sshd configuration)

by using:

no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command=”…” in authorized_keys.

Helmut Grohne wrote on 2013-05-20 08:17:

Consider also putting the ssh invocation in /etc/ppp/ip-up.d/. This is especially useful if your IP changes frequently, because you hook into the change event.

mirabilos wrote on 2013-05-20 15:31:

Pingback from a follow-up wlog entry: https://www.mirbsd.org/permalinks/wlog-10_e20130520-tg.htm

mic wrote on 2013-05-27 20:28:

IIRC the ssh client is still able to execute scp, for example to retrieve the script

evgeni wrote on 2013-06-19 19:49:

nope, it can’t. try it :)

Luca wrote on 2013-06-28 11:16:

Great script. Thank you very much.

Please note, for anybody facing “ImportError: No module named MySQLdb” (just like me) that you just have to execute “apt-get install python-mysqldb” (on Debian Wheezy).

Anyway, wouldn’t be possible to get the settings.domain (for updating SOA) directly from the authorized_keys command?

I have several second level domains to update, and with current behaviour I can’t succeed.

Thank you again.

Luca

evgeni wrote on 2013-07-16 06:50:

Hi,

yes this would be possible, in some setups at least. For me I have dorei.kerker.die-welt.net as my dynamic hostname, but the domain maintained with PowerDNS is die-welt.net directly, thus the stiff config. I’ll see if I can come up with some automatic behaviour as an alternative.

Greets

evgeni wrote on 2013-07-16 19:43:

https://github.com/evgeni/powerdyn/commit/a31421b3b770f6a8a064adc4fc149a6463508cda :)

Luca wrote on 2013-07-17 08:25:

Your recent commit suits well the given request; and now it works as expected: thanks!

Another little tip regards cron configuration. I suspect your instructions on README.md miss the username field.

This is what I’ve added to /etc/cron.d/powerdyn

# PowerDyn

# Connect every 15m to specified name server and update (a remotely configured) dynamic-ip DNS record

*/15 * * * * root ssh -4 -T -i /root/.ssh/id_rsa powerdyn@my.cool.powerdyn.server.tld

Cheers!

Luca

Send your comments to evgeni+blogcomments@golov.de and I will publish them here (if you want).