Half-Penny For Your Thoughts

rounded down to the nearest cent



Categories


Recent Articles




Computing

Simple Ruby DNS Server

Update 2009-09-10: If you’re interested in a DNS server written in Ruby, check out RubyDNS. Thanks to Samuel for his comment below announcing its release.

A few weeks ago, I started playing with Ruby’s Resolv library, which abstracts the DNS protocol. I’m playing with creating a DNS server in Ruby. It turns out to be pretty easy to get a very basic DNS server going in Ruby, And, for the curious, here it is.

require 'socket'
require 'resolv'

hosts = [
  {:name => "example.com", :type => "A", :data => "192.168.0.1"}
]

# Bind to UDP port 53 to receive requests
$port = 53
server = UDPSocket.open
server.bind(nil, $port)

while true
  # Receive and parse query
  data = server.recvfrom(10000)
  query = Resolv::DNS::Message::decode(data[0])

  # Setup answer
  answer = Resolv::DNS::Message::new(query.id)
  answer.qr = 1                 # 0 = Query, 1 = Response
  answer.opcode = query.opcode  # Type of Query; copy from query
  answer.aa = 1                 # Is this an authoritative response: 0 = No, 1 = Yes
  answer.rd = query.rd          # Is Recursion Desired, copied from query
  answer.ra = 0                 # Does name server support recursion: 0 = No, 1 = Yes
  answer.rcode = 0              # Response code: 0 = No errors

  query.each_question do |question, typeclass|    # There may be multiple questions per query
    name = question.to_s                          # The domain name looked for in the query.
    record_type = typeclass.name.split("::").last # For example "A", "MX"
    ttl = 16000
    record = hosts.find{|host| host[:name] == name && host[:type] == record_type }
    unless record.nil?
      # Setup answer to this question
      answer.add_answer(name + ".",ttl,typeclass.new(record[:data]))
      answer.encode
    end
  end

  # Send the response
  server.send(answer.encode, 0, data[1][2], data[1][1])
end

To try this out, run the above script (may require sudo, since it binds to port 53; I haven’t figured out a way to test this at a different port) and then, in irb:

require 'resolv'
d = Resolv::DNS::new(:nameserver => "localhost")
puts d.getaddress("example.com")

This would only respond to A record requests for example.com, and the array of hashes is not particularly scalable. One could, for example, use ActiveRecord to access the records from a database, which is something I’m currently working on.


Computing

DNS

Reading seenonslash the other day, which is a great shortcut, if you’re like me and read slashdot more for the funny or interesting comments than, say, the articles, I came upon this post regarding DNS. If you don’t want to read, the poster, Colin Smith, is suggesting that ICANN should have enforced a more managed heirarchy of the domain name system, e.g. “microsoft.vendors.software.com” rather than “microsoft.com”. I’ve pondered this a bit, partly because I get sick of trying to find a good domain for website clients. Obviously, they want something easy to remember, but inevitably name-of-their-company.com is taken. They shy away from .net and .org, which is oddly appropriate, considering few of my clients are network related or non-profits. And generally from the country TLDs as well.

A more heirarchical system suggested by Smith would, I think, help this a great deal: say smith.usedcars.ok.us vs. smithsoklahomausedcars.com. (or, more to my personal tastes, us.ok.usedcars.smith). Especially if there was an application, so that you don’t have company.#{every-tld-known-to-man}, but rather each organization has one-to-three domains that are actually descriptive. Then, perhaps, one could also get a flat domain, but for a higher price and definitely requiring an application process. Predictably, then, my second big beef with modern dns is half the names you can’t get are taking up by “search pages”.

So, I like Smith’s solution, but with two questions: 1. How do you keep from getting really long domains, e.g. wizardofoz.fans.filmadaptions.books.western.culture? Okay, with a little work that’s not a problem, but who wants to put in a little work? Maybe I’m being too pessimistic on that point. 2. How geographical should the heirarchies be. For example, when submitting a site to the Open Directory Project, I always wonder whether I should go under regional or not. Should there be rules about that? As an aside, it could be nice if I could just type local.X.Y.Z and it would automatically search country.state.city.X.Y.Z for my default location (or, maybe, to a location based on my IP).

Oh, another thing I like is the possibility of an automatic directory structure for searching. The web could have an easily maintainable category search because the heirarchical structure would already exist with the domain name system.