Dynamic DNS: Part Two
This post is a follow-up to Dynamic DNS
When last I left you, we had basic updateable DNS running and could update it from OS X. I've been a bit busy since then, but thanks to some prodding from @Loredo, I got back in and started looking at. What follows is the exciting story of how I got things up and running -- by the end of this post, you'll have access to a working copy of dnsextd for linux, and a client application that updates SRV and IP (A/AAAA) leases. Woo.
If you remember from Part 1, we'd gotten DNS UPDATE running on a Linux machine, but didn't yet have support for Apple's DNS extensions which make wide-area Bonjour so cool, because dnsextd is a pain in the ass and doesn't really work except on Linux. Well, now it does.
So, we'll be basing our adventure on mDNSResponder-215, which is the latest copy. I initially wrote against -214, but don't worry, my code also works against -215 (and trunk, for that matter). You have a couple of options here. If you'd like to check out my actual code that I'm working on, I have a git tree that I work in. It's based off of mDNSResponder-214 because it's a pita to switch over to -215 or -trunk and there are no (0) changes to mDNSPosix or dnsextd.c in -215. You should be able to clone my get repo with the following code:
git clone http://files.roguelazer.com/projects/mDNSResponder-214.git mDNSResponder-214 cd mDNSResponder-214
Alternatively, if you would prefer to work off of -215:
svn co http://svn.macosforge.org/repository/mDNSResponder/tags/mDNSResponder-215 cd mDNSResponder-215 wget http://files.roguelazer.com/projects/dnsextd_posix-215.patch patch -p1 < dnsextd_posix-215.patch
Some notes about this code: Apple seems to have tried pretty hard to "do the right thing" on a lot of platforms. To that end, they wrote a big network abstraction library. Except they only implemented it for OS X and Windows. So I implemented parts of it for Posix. I did not implement the stuff I didn't need, including the callback system for TCP events, or any TLS support. I don't think anything in mDNSResponder other than dnsextd will work with this code. But who cares about that stuff? If you want a real mDNS responder on Linux, I suggest looking at Avahi.
Also, the usual disclaimer applies: I am not responsible if using this code causes your computer to explode or God to kill a kitten. Liek, for reals. I'm going to see what I can do about getting this code merged in, so maybe there'll be more good stuff in the future.
Oh, also, this probably won't do the right thing if your zone is private. But the existing code also wouldn't, so *shrug*.
Once you've downloaded the code, and cd'd into the root directory, the following sequence of code will build dnsextd
cd mDNSPosix make os=linux dnsextd sudo cp ../mDNSShared/dnsextd.conf /etc/dnsextd.conf
Now it's configuration time. First, you'll need to edit the dnsextd.conf file that you just installed (/etc/dnsextd.conf). Change the zone name to be your dynamic zone, but DO NOT CHANGE ANYTHING ELSE. Most of the configuration parsing is extremely brittle and has a tendency to mysteriously die if you specify an option slightly differently than it expects. In fact, just uncommenting the example code will make things break. Woo.
Also, I didn't yet fix the bug which causes dnsextd to segfault if the configuration file isn't found. So, uh, make sure it's in the right place.
You'll also have to edit your DNS configuration. I'm not going to explain BIND to you, because you really do need to know how BIND9 works before you can even have a hope of getting this to work. In short, you just need to configure BIND to listen on port 5030 and accept updates from 127.0.0.1 (and ::1, if you're doing the ipv6 thing). dnsext really wants to listen on port 53, so I would advise against trying to change that.
Once you've restarted BIND, you should be able to launch dnsextd with the following command (still in the mDNSPosix directory):
sudo ./build/prod/dnsextd -v -d
A small security note: dnsextd needs to open port 53 to do listening, but doesn't seem to be smart enough to drop privs after that, so it needs to be run as root the whole time, which is a giant security hole. Anybody who feels like writing up some cross-platform permission-dropping code should send me a message. :-)
Congratulations, you are now running dnsextd on Linux and can support long-lived queries and UPDATE-LEASE. You can't support DNS-over-TLS, but why would you want to?
The other thing that I worked on is what I'm tentatively calling [wamupd]. It will eventually be a daemon for updating wide-area mDNS information. Currently, it supports loading Avahi .service files and setting SRV/PTR/TXT records for them, as well as setting system A and AAAA records. I'd eventually like to support listening on Avahi's D-BUS interface so that this daemon could act like a wide-area Avahi and publish all services, but I haven't gotten that far. I also have to make the daemon automatically renew leases (right now, I have it in a cron job to run every few minutes and re-up my leases).
wamupd uses Dnsruby (rdoc), which is a really great DNS library for Ruby. Unfortunately, while it's great, it's not perfect, so I had to implement some patches to get it working properly. They let Dnsruby support OPT correctly and not die when receiving a non-signed response to a signed request (because dnsextd doesn't sign lease confirmations). Make sure that you apply them to your Dnsruby before trying to run wamupd.
wamupd is a pretty big hack, mostly done because the Avahi codebase is nasty and I didn't want to work on it. With any luck, somebody will finish the long-promised wide-area Bonjour update for Avahi, and it won't be necessary. Yup.