mbdnsSunday, Sep 9, 2018 · 1200 words · approx 6 mins to read
I run a bunch of online services, from this blog to Beyond3D and a host (sorry) of other things in between. Letting folks easily connect to them means I need DNS, and because I run my own infrastructure as much as I can it made sense to get DNS service from a single provider, so I can manage everything in one place and learn one control panel system and API. For as long as I can remember that’s been at Dyn (searching my email says mid 2007), but recently I’ve been looking elsewhere.
A combination of them trying to up-sell me without understanding that my business is tiny and can’t afford the next tier up, plus their acquisition by Oracle, means I’ve been idly wondering about moving elsewhere in the last half a year or so. Their service is actually really good so I haven’t been in a hurry, but another round of them trying to convince me to move to a new product that’s well outside my budget had me looking for options again in mid-July.
I tried Cloudflare — well, not really because their control panel was broken and wouldn’t do anything — had a look at Route 53 but couldn’t figure out their completely inscrutable pricing, and then someone mentioned Mythic Beasts, a small ISP in Cambridge here in the UK. A quick look at their website showed that they did provide DNS service, and they had a good looking API and support for dynamic DNS which I need (which is conceptually just a specific manipulation of their Primary DNS system), but that I needed to host the domains with them to get that.
While I would like to switch registrar too at some point, I wasn’t prepared or ready to do both at the same time. So I tweeted that it wasn’t what I was looking for and continued looking. Then they replied! I did as asked and they explained how to get around the need to host the domain with them to get DNS service for it.
Turns out you just need to host 1 domain with them — and by host I mean they’re the registrar and provide the glue services for it to the rest of the Internet. So I spent a tiny amount registering a single domain to get a paid account there and then added the rest of my fleet of domains, including those of my customers, as what they call a 3rd party domain.
You prove you have control of the domain by setting a named
TXT record somewhere in the zone and then that’s it, you can setup the domain in full inside their DNS system. Faced with setting up 19 domains from scratch, I emailed them to see if they could do it for me: I maintain up-to-date BIND zonefiles for everything as a matter of course, so I just emailed them over and they imported them en masse. Thanks for the excellent support on that, if you’re reading!
I have 3 zones that need dynamic services, 1 of my own and 2 belonging to customers, so after checking that Mythic Beasts' zonefile import looked good and all the records were intact and correct (they weren’t but they warned me up-front what would get lost, and those CAA records weren’t critical), I flipped the switch on the other 16 zones at my registrar which meant that Mythic Beasts were providing DNS resolution for them all. Nobody noticed, which is exactly as it should be for that kind of infrastructure change!
So what about the 3 zones that need dynamic services? Mythic Beasts support dynamic record updates, but their API is completely different to Dyn’s. There’s no standard for things like that and therefore each DNS vendor invents their own system. I spoke to my 2 customers about their needs to see if there was a solution to put in place that uses Mythic Beasts' system. Both customers get direct API access to Dyn’s system via their own sub accounts, but they access it via ddclient, which unfortunately has no support for Mythic Beasts (despite Mythic Beasts themselves writing a patch back in 2014).
At this point there was a decision to make: take Mythic Beasts' patch for ddclient, rebase it against ddclient 3.9.0, and then get it released such that my customer’s devices would then get it, or write a separate client entirely against Mythic Beast’s API that runs everywhere my customers need it. Patching ddclient is the good internet citizen thing to do, and I might still do that, but it’s much less fun than writing something yourself.
So after canvassing where my customers ran their Dyn-using updaters — an ARM-based QNAP and basic amd64 Linux — and my own requirements (FreeNAS on amd64 and my EdgeRouter X), I started typing. The end result is mbdns.
mbdns is an MIT-licensed dynamic DNS updater for Mythic Beasts' API, written in golang. It consumes a JSON configuration file which describes which records you want to update, and the API token that Mythic Beasts need to authenticate the request, and then calls the correct API endpoint at Mythic Beasts to make it happen.
There are prebuilt binaries for
linux-amd64 (that’s for you, Tim!),
linux-arm (Mark’s QNAP),
linux-mipsle (my ER-X and all the other Octeon-based EdgeRouter products Ubiquiti sell most likely),
freebsd-amd64 (my FreeNAS) and
darwin-amd64 (macOS, because that’s what I wrote the client on).
It’s all (hopefully!) documented well in the repo on GitHub, and comes with helper scripts to help you build binaries and package them just as I did.
Really there’s not much in there that couldn’t be done with shell scripts and curl, but because of golang’s very strong cross-compiler support and the fact that golang binaries are statically compiled with no runtime dependencies, it’s a good fit for small, focused utilities like this and less brittle than shell scripts.
And because the standard library is very much batteries included (I use no outside libraries in mbdns), it was easy to put together. The documentation in
docs/ARCHITECTURE.md describes what I wanted it to do, and was written first before any of the golang code.
Then I wrote the minimum viable client to (mostly) satisfy it, polishing a little afterwards to get to the very basic 1.0 that I released earlier. golang’s great JSON support, http library, plus built-in support for parsing command line flags, made it all come together quickly.
I might never need to touch the code again if Mythic Beasts keep the API stable, so who knows what a 2.0 (or even a 1.1) would contain, but the source code is there just in case you get any ideas of your own. Pull requests are most welcome.
It was a fun little project to work on, even if it’s quite over engineered, but it was a good excuse to write some code in a language I’ve never really used before and provide a missing piece of infrastructure to my customers as I switched their DNS service over to my new provider.