Exporting Libcloud DNS zone to BIND zone file format and migrating between DNS providers

Because of the reliability issues and pretty much non-existent and non-responsive customer service (if you don’t believe me, check Twitter which is full of complaints) I migrated some of my domains away from Zerigo to a different DNS provider. To do that, I wrote a simple Python script which allows you to export Libcloud DNS zone to a BIND zone file format.

Motivation & History

I have been Zerigo user for almost 4 years now. One of the primary reasons why I have migrated most of my domains to Zerigo back then was that they were one of the first DNS providers which offered a simple management REST API.

At the beginning things were working flawlessly, but after the acquisition by 8x8 things have started degrading. Things have became especially bad in the last year or so. During that time Zerigo has been a target of multiple DDoS attacks which took down majority or all of their DNS servers (1, 2). Those attacks caused a major disruptions for a lot of Zerigo DNS users.

Anycast provides better resilience against DDoS attacks

Recently Zerigo posted an announcement where they said that they have implemented multiple measures to improve their DNS servers reliability. Sadly, as displayed a couple of weeks ago when they were a target of another DDoS attack, those measurements didn’t help. The problem is that most of the measurements they have implemented are just small patches which don’t address a root cause. To improve the reliability of their service, the first step they would need to take is to move all of their DNS servers to Anycast. Anycast has long been used by many commercial DNS providers to increase performance and availability.

Exporting Libcloud DNS zone to BIND zone file format

Yesterday I have decided to migrate more of my domains to a different provider. To expedite the migration I wrote a simple Python script which can take a Libcloud DNS zone and create a BIND zone file for it.

Advantage of this approach over writing a script which uses Libcloud to directly re-create all the records under a different provider is that it’s more efficient and as an output you get a file which you can use with any DNS software or provider which supports BIND zone file format.

Keep in mind that a similar thing can be achieved by using a dig tool (dig +nocmd example.com any +multiline +noall +answer). The problem with dig approach is that unless zone transfers are enabled for your IP address, you won’t receive all the records back.

Aforementioned script can be found on Github.

Usage

To use this script and create a BIND zone file, follow the steps bellow:

  1. Install the Python package
$ pip install -e git+https://github.com/Kami/python-libcloud-dns-to-bind-zone@master#egg=libcloud_to_bind

The script is so simple I haven’t decided to publish it to PyPi yet. I plan to start a discussion on the Libcloud mailing list and if more people find it useful and are OK with that, I will include this functionality in the core.

  1. Take a look at example.py and modify it to suit your needs. For example:
from libcloud.dns.types import Provider
from libcloud.dns.providers import get_driver

from libcloud_to_bind import libcloud_zone_to_bind_zone_file


DOMAIN_TO_EXPORT = 'example.com'

Zerigo = get_driver(Provider.ZERIGO)
driver = Zerigo('email', 'api key')

zones = driver.list_zones()
zone = [z for z in zones if z.domain == DOMAIN_TO_EXPORT][0]

result = libcloud_zone_to_bind_zone_file(zone=zone)
print(result)

Keep in mind that you can replace Zerigo with any other provider supported by Libcloud.

  1. Run the code
$ pypy example.py

(yes, Libcloud works just fine under PyPy)

Here is an example output for one of my domains:

; Generated by Libcloud v0.13.0 on 2013-09-07 00:09:09
$ORIGIN tomaz.me.
$TTL 900

tomaz.me.	900	IN	TXT	"v=spf1 include:_spf.google.com ~all"
tomaz.me.	900	IN	A	207.97.227.245
tomaz.me.	900	IN	MX	30	aspmx5.googlemail.com.
testsrv.tomaz.me.	900	IN	SRV	10	10 333 google.com.
mail._domainkey.atlantis.tomaz.me.	900	IN	TXT	"v=DKIM1; k=rsa; t=y; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6HeU4PBI+JuEWAe03Bzye1Gs+U2vXhbSloSNbXr9JDWMygyQtCjxN7brHahqFambBtmdQ5VmbukM+HFlKUoaNz7Q97KaKRQg8mDvSmLJkHmAw5PzZJXfzrfkoLmXhN6K4XnwLWJ0BFWPyEPdpwCX8v9v3kB0INJU4hNjwdy/+6wIDAQAB"
www.tomaz.me.	900	IN	CNAME	kami.github.com.
tomaz.me.	900	IN	MX	30	aspmx3.googlemail.com.
google._domainkey.tomaz.me.	900	IN	TXT	"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNCHa8VeffMv+X/fRkPgHC9MN2Eh5vQqMkWy4e/YnFbWgF1JilL1Yn9nN54A5WV7lZpCTIvuOC2CrQrIcaBpfr+8SjYsjGO91dz8cwgqZkl7mAjKs7nz8U0PsstuI9i4V3LsHC4NVGOirAgnKA4HXVhxGRuyE94+tuNJ6XDLJoNQIDAQAB"
tomaz.me.	900	IN	MX	20	alt2.aspmx.l.google.com.
atlantis.tomaz.me.	900	IN	TXT	"v=spf1 ip4:178.63.79.14 ip4:178.63.79.48 ip4:178.63.79.49 ip4:178.63.79.50 ip6:2a01:4f8:121:3121::2"
atlantis.tomaz.me.	900	IN	PTR	atlantis.tomaz.me.
tomaz.me.	900	IN	TXT	google-site-verification=Rgex8ShgIRWUlb9j0Ivw5uHllb0p9skEdJqkSMqvX_o
test5.tomaz.me.	900	IN	AAAA	2620:0:1cfe:face:b00c::3
tomaz.me.	900	IN	SPF	"v=spf1 include:_spf.google.com ~all"
tomaz.me.	900	IN	MX	20	alt1.aspmx.l.google.com.
atlantis.tomaz.me.	900	IN	A	178.63.79.14
test5.tomaz.me.	900	IN	A	127.0.0.1
ponies.tomaz.me.	900	IN	A	86.58.76.208
tomaz.me.	900	IN	MX	30	aspmx2.googlemail.com.
atlantis.tomaz.me.	900	IN	AAAA	2a01:4f8:121:3121::2
secure.tomaz.me.	900	IN	A	86.58.76.208
tomaz.me.	900	IN	MX	10	aspmx.l.google.com.
tomaz.me.	900	IN	MX	30	aspmx4.googlemail.com.