RubyDNS - asynchronous DNS client and server for Ruby

Hi,

I wanted to share a gem I made and I’ve got a fun demonstration.

I was always interested in DNS clients and servers and at one point I
had a
very specific setup with servers behind an ADSL NAT connection, which
meant
that locally resolved names pointed to servers inside the NAT while
externally resolved names should point at the ADSL modem which had
appropriate VHOST rules. Thus, was born RubyDNS.

RubyDNS is an infinitely flexible DNS server which includes an
asynchronous
DNS client to ensure non-blocking behaviour when forwarding requests
upstream. It is built on EventMachine which theoretically should provide
a
good asynchronous foundation for processing DNS requests and integration
with other asynchronous systems (e.g. em-http-request).

For fun, I made an example. WikipediaDNS allows you to query wikipedia
via
DNS, e.g.:

:slight_smile: > dig +tcp +short @ayako.oriontransfer.org computer.wikipedia TXT
“A computer is a general purpose device that can be programmed to carry
out
a finite set of arithmetic or logical operations. Since a sequence of
operations can be readily changed, the computer can solve more than one
kind of problem.”

I’m running it on my VPS (temporarily for this demonstration, don’t
expect
this to be a permanent home) and you can also run it locally, the code
is
available:
https://github.com/ioquatix/rubydns/blob/master/test/examples/wikipedia-dns.rb-
in this example, I’ve forced +tcp as udp seems to be blocked, at least
from my current location.

RubyDNS has been used in a number of interesting systems, including
Murakumo, a distributed peer-to-peer DNS system, and along side vagrant
to
provide dynamically registered DNS names for dynamically created virtual
hosts. Someone also contacted me recently about using it for full scale
network integration testing and also browser level testing of some sort.
It
was used in f***PSN, a tool for bypassing the PSN network, and has been
also used in SiriProxy (I’m sure you can guess what it does).

I’d love to share RubyDNS with the hope that I see more interesting
projects developed on top of it. I get really excited thinking about all
the possibilities. For example it would be really interesting to make a
client-server architecture for sending data via DNS, perhaps some kind
of
DNS port knocking security system, better integration of information
systems with DNS (e.g. mapping “document database” to DNS records).

Source code is available: GitHub - socketry/rubydns: A DSL for building fun, high-performance DNS servers.

Project home page with introduction video and documentation:
http://www.codeotaku.com/projects/rubydns/index.en

Kind regards,
Samuel

On Tue, May 21, 2013 at 9:05 PM, Samuel W. <
[email protected]> wrote:

Source code is available: GitHub - socketry/rubydns: A DSL for building fun, high-performance DNS servers.
Project home page with introduction video and documentation:
RubyDNS

Hi Samuel,
i was looking for hints/docs if it would be possible to create virtual
domains using rubydns. The dbs are stored in text (djbdns format) and db
(sqlite or postgres)…
thanks for rubydns gem.
kind regards -botp

Hi botp, you can create any configuration of DNS you like. RubyDNS
doesn’t
have a concept of zone files or anything like that, perhaps you can give
me
more details about what you mean exactly by virtual domains?

On Wed, May 22, 2013 at 7:02 AM, Samuel W. <
[email protected]> wrote:

Hi botp, you can create any configuration of DNS you like. RubyDNS doesn’t
have a concept of zone files or anything like that,…

Hi Samuel,
apologies in advance for any stupid question.
Maybe i should simplify my q:

say, I have a list of names w corresponding ip addresses in a text file.
now if a query comes in asking for an ip (among others) of a name, i’d
look
inside the text file for that name, and output the ip if any…

problem is, i’d like to get more info about the query… like what, where
is
it coming fr, etc…

thanks again,
-botp

On Wed, May 22, 2013 at 1:45 PM, Samuel W. <
[email protected]> wrote:

Hi, you can use geo-ip for finding the location, geographically speaking.
There is an example of how to do this:

https://github.com/ioquatix/rubydns/blob/master/test/examples/geoip-dns.rb#L40-L41You’ll
need to follow the instructions L40-41 to get a geo-ip database.

Does that answer your question?

sorry Samuel, i confused you again.
when i say IP, i just meant the ip address of the client querying my dns
server.

for now, i just want to get two things from the requesting client:
1 the ip of the client
2 the query object (and its attributes) issued by the client

https://github.com/ioquatix/rubydns/blob/master/test/examples/geoip-dns.rb#L57
2.
https://github.com/ioquatix/rubydns/blob/master/lib/rubydns/transaction.rb#L43-L51

Does that help?

Hello,

On 22 Μαϊ 2013, at 12:02 , botp [email protected] wrote:

On Wed, May 22, 2013 at 1:45 PM, Samuel W.
[email protected] wrote:
Hi, you can use geo-ip for finding the location, geographically speaking. There
is an example of how to do this:
https://github.com/ioquatix/rubydns/blob/master/test/examples/geoip-dns.rb#L40-L41
You’ll need to follow the instructions L40-41 to get a geo-ip database. Does that
answer your question?

sorry Samuel, i confused you again.
when i say IP, i just meant the ip address of the client querying my dns server.

for now, i just want to get two things from the requesting client:
1 the ip of the client
2 the query object (and its attributes) issued by the client

I’m a bit offtopic really but, I think the ‘correct’ way to do this
would be to monitor the DNS requests issued either by RubyDNS or any
other DNS server/client at port UDP:53 with a firewall (pf, iptables,
ipfw, etc) or tcpdump grab the values that are of interest from their
logs and then run a ruby (or pythong, or whatever) script that collects
the info you want.

Best Regards,

Panagiotis (atmosx) Atmatzidis

email: [email protected]
URL: http://www.convalesco.org
GnuPG ID: 0x1A7BFEC5
gpg --keyserver pgp.mit.edu --recv-keys 1A7BFEC5

On Thu, May 23, 2013 at 4:08 AM, Panagiotis A.
[email protected]wrote:

I’m a bit offtopic really but, I think the ‘correct’ way to do this would
be to monitor the DNS requests issued either by RubyDNS or any other DNS
server/client at port UDP:53 with a firewall (pf, iptables, ipfw, etc) or
tcpdump grab the values that are of interest from their logs and then run a
ruby (or pythong, or whatever) script that collects the info you want.

in a way, yes. But in this case i do it mainly for 2 reasons:
1 defense in-depth. protection at network level + protection at
application
level
2 split dns

now, as to why rubydns interest me:
1 rubydns would shine on environments w heterogeneous dns setup, some
have
bind, djbdns, etc… using ruby(dns), i wont have problems reading
their
differing databases…
2 adhoc dns… eg, i can just run a temp rubydns, while i fix their
problematic bind dns…
3 scale and economics. install ruby & deploy.
4 collaboration. my ruby/rails/sinatra apps can now communicate
seamlessly & natively with our dns servers…

kind regards
-botp

Hi, you can use geo-ip for finding the location, geographically
speaking.
There is an example of how to do this:
https://github.com/ioquatix/rubydns/blob/master/test/examples/geoip-dns.rb#L40-L41

You’ll need to follow the instructions L40-41 to get a geo-ip database.
Does that answer your question?

On Wed, May 22, 2013 at 10:40 PM, Samuel W. <
[email protected]> wrote:

https://github.com/ioquatix/rubydns/blob/master/test/examples/geoip-dns.rb#L57
2.

https://github.com/ioquatix/rubydns/blob/master/lib/rubydns/transaction.rb#L43-L51

Does that help?

ah, yes. funny i cannot seem to find those using ri. Got to fix my
ruby
setup here.
guess i’ll have to read the rubydns code then…

thanks again, Samuel
kind regards -botp

Weird - if there is a bug with the documentation please submit a patch
:smiley:
Thanks. Let me know if you have any further questions.

Now I’m kind of curious, what is your expertise and what are you doing
with
DNS?

On Sat, May 25, 2013 at 8:53 PM, Samuel W. <
[email protected]> wrote:

Now I’m kind of curious, what is your expertise and what are you doing
with DNS?

nothing new really, just honing basic skills (besides programming) as
sharpest possible…
kind regards -botp

I’m wondering if it’s possible to use rubydns to diagnose an issue on my
local network. I’m having an issue with a particular server and I
believe that it’s related to an extremely low TTL setting. I’d like to
try running my response time tests with custom TTL’s for those domains.
I’ve gone through the video on your site and the documentation provided
and didn’t see how I could pull this off.

I need to know how to:

  1. Override the TTL only when a specific DNS query is made.
  2. Ensure that the tests running from my local machine will use rubydns
    to resolve the domain instead of my main system DNS (I’m running OSX
    fwiw). Right now my only thought is to change my network settings to use
    127.0.0.1 as my DNS.

Any insight you could provide would be welcome. Thanks and great tool!

I answered my own question. The example on the github README and the
API docs illustrate how to do it. All I have to do to test anything else
from my local machine is set my local DNS to 127.0.0.1 with that
example.

Returning the TTL was as easy as adding ttl: 30 to the
transaction.response. Great piece of code you have here.