So yesterday I wrote about my tests on bypassing an hostile NAT that left me with a public-accessible dynamic IPv6. This helps me a whole lot, but it ’s almost unusable for more than a couple of days as I cannot know the IP address (unless that is I mail it to myself each time it change). The idea of using Mobile IPv6 to get a stable address for the box left away because of the complexity, I came back on my steps to my original, possibly easy, option: dynamic hostnames.
Dynamic hostnames are a very old technology to work around the issue of dynamic IPs (which was much more common years ago), it seemed obvious to me that the solution was the easiest to implement: I get a stable address (in form of hostname) to the router, then I can get to the remaining hosts through a SSH jump (or some kind of limited-scope IPv6 routing).
Unfortunately the first obvious choice (DynDNS) is a failure: it does not support using IPv6 for dynamic hostnames as far as I can see, and that makes it useless for my aim here. The second option for me was using the OVH system for DynHOSTs — it’s a service I pay, so I was expecting it to have the needed features, unfortunately they also don’t allow using IPv6 for their hosts. There used to be a service that supported this kind of feature, called DNS6, but that seems to be now dead. Hurricane Electric is planning on supporting dynamic hosts at some point, but right now there is no support for it.
Then I started looking at some more complex solutions, including paid-for solutions and custom solutions. One of my first ideas was UltraDNS but no public pricing seems to be available and that is not something I’m very fond of; plus it’s based in the United States which gives me trouble with taxes and payments, an European solution would have been better for my requests.
After discarding this solution as well, I started down the most complex road for this kind of situations, at least that’s what I thought at that point: writing my own dynamic DNS system. Luckily, a job I took earlier this year gave me a bit of expertise with PowerDNS (the software) so I only had to write some CGI application in Ruby to modify a PostgreSQL database on this very server, and serve it from there. I started looking into the pieces of the puzzle for what concerned the CGI script, and found a number of other problems, mostly related to SSL and certificates (but that’s, again, something for another post), and then I looked at PowerDNS itself, starting from looking at the latest version available on the site.
When I looked at the homepage (which is the one I linked earlier), I noted two more interesting things: the first is that the developers offer a paid-for custom DNS service, the second that the company is in the Netherlands, so it’s within the European Union, which is good for my taxes. Also, the price for a single domain (which is what I’d be needing at first) is low enough that it looked acceptable ($2 per domain, $0.50 for the transaction, less than €1.90 total). Beside the usual user-friendly operation interface to set the DNS records, their service has the one thing that was important to me: API access based on the SOAP protocol (and a WSDL description), that allowed updating records via scripts.
While on paper the service is great – and cheap too! – there are way too many shortcomings in their approach:
- Authentication shautentication: the SOAP interface is only available in simple HTTP, there is no proper authentication, but it’s all left to the single API key that is provider per user; this means that if you deploy this on a non-trusted network (and, well, do you really trust the rest of the Internet?), and somebody is able to get your API key, not only they can mess with the records you’re messing at a given time, but they can mess with any of your zones and domains.
- API keys and WSDL: beside the fact that it’s the one and only authentication mechanism, the API key is not passed as part of the SOAP request; instead it is passed as a query parameter on the POST request, as part of the uri. Unfortunately, the WSDL that is reported by the interface is not fixed to use the API key. As their documentation only speaks about PHP and VB.NET, I assume that those two libraries ignore the endpoint URL provided by the WSDL response (as
soap:address); Ruby on the other hand respects what the response tells it to use, and it turns out it does not include the API key back, resulting in receiving “Invalid User” messages back at any request.
- No advanced editing: while the PowerDNS express user interface for assisted editing of zones is one of the best I’ve seen among various DNS services, including the ability to automatically add Google Mail records (which would have been nice given that I actually have them on a number of domains already), they don’t have an “advanced” mode, which would allow you to either edit the zone manually, or at least add any kind of records in a free-form way; the SOAP interface also doesn’t allow you to add all kind of records either, which is a bad thing. It gets even worse when you add the fact that you don’t have SSHFP as a record type that you can use to set the fingerprint of a SSH server — this was actually a half decent idea to provide some extra safety that the lack of real authentication didn’t give me.
I’m seriously disappointed by the bad quality of the service PowerDNS Express provides, even though their software (pdns) seems pretty good and their basic interface is one of the best, as I said. As it is, it’s definitely not an option.
Luckily, Robin (robbat2) saved me from writing and deploying my own custom solution, so I’ll be working on deploying that in the next few days, taking most definitely less time than it would require me to waste for writing all the code myself. In most recent Bind version, support for Dynamic DNS entries is supported via the
nsupdate tool; this means that if I set up a standard bind instance on my server (which might be harder to configure, but requires less than half the dependencies of pdns, most importantly it doesn’t need boost, and does not require a database behind it), then I can simply use that (which provides a strong authentication system, and a complete authorization system) to provide dynamic host names, exactly like I intended to originally.
For now, I’ll like the two reference pages that Robin gave me, if I’ll encounter problems implementing it that way, I might post again about it: