{"id":459,"date":"2009-08-10T17:54:34","date_gmt":"2009-08-10T16:54:34","guid":{"rendered":"http:\/\/wp.devco.net\/?p=459"},"modified":"2009-10-09T17:54:05","modified_gmt":"2009-10-09T16:54:05","slug":"ruby_powerdns_framework","status":"publish","type":"post","link":"https:\/\/www.devco.net\/archives\/2009\/08\/10\/ruby_powerdns_framework.php","title":{"rendered":"Ruby PowerDNS Framework"},"content":{"rendered":"
Regular readers here will know I patch bind with GeoIP extensions<\/a>, this has served me well but my needs have now outgrown simply doing geo related replies.<\/p>\n I’ve for a long time had an itch to be able to do completely custom DNS, maybe respond to monitoring, or time of day, geographical location or even to work around some unbelievably annoying bugs in windows that breaks all round robin dns<\/a>, this has not been possible with Bind.<\/p>\n PowerDNS has a backend that simply speaks via STDIN and STDOUT to any script, the documentation though is pretty shoddy but I quickly realized this is the way to go. Once I figured out all the various weird things about PDNS and the Pipe backend I set about writing a framework to host many records in a single PDNS server – in a way that hides and abstracts all the PowerDNS details from the code<\/i>. <\/p>\n The end goal is that I would dump some Ruby code into a file on the server and it should just be served, when I get new code I just want to overwrite the old code, no restarts or anything it must just serve it.<\/p>\n I wanted the code to be trivially simple, something like this:<\/p>\n module Pdns when “ZA”, “ZW” else should be all that is needed to do GeoIP based serving, and really complex things like weighted random round robins that effectively work around the bugs in client resolvers like the windows one above:<\/p>\n ips = [“1.x.x.x”, “2.x.x.x”, “3.x.x.x”, “4.x.x.x”, “5.x.x.x”]<\/p>\n ips = ips.randomize([1,5,3,3,3])<\/p>\n answer.shuffle false This code will take 5 ip addresses, shuffle them giving the first one least weight, the 2nd one most weight and return only 3 out of the 5 results, this would be impossible in Bind but trivial to imagine coding if only you could hook into the nameserver.<\/p>\n Anyway, so I wrote a framework that enables exactly this, the code snippets above are actual working snippets. The code is hosted on Google Code as ruby-pdns<\/a> and is at version 0.3 at present.<\/p>\n I’ve release tarball and RPM versions<\/a> of the code, the code is publicly browsable<\/a> and licensed under the GPLv2. <\/p>\n
newrecord(“www.your.net”) do |query, answer|
case country(query[:remoteip])
when “US”, “CA”
answer.content “64.xx.xx.245”<\/p>\n
answer.content “196.xx.xx.10”<\/p>\n
answer.content “78.xx.xx.140”
end
end
end<\/p><\/blockquote>\n
answer.ttl 300
answer.content ips[0]
answer.content ips[1]
answer.content ips[2]<\/p><\/blockquote>\n