2

I've built a mini dns server with twisted that is avahi aware.

What it does is look for request that ends with .local; If it's the url of the host something like {{hostname}}.local the dns server let the os resolve the adress. If it's something like {{subdomain}}.{{hostname}}.local the server route it to {{hostname}}.local.

The feature that brings this program is not clear, it let you play with subdomains easly without having to add each and every subdomain you need to /etc/hosts, and the plus side it support also machine that are in the local network and have also avahi dnsconfd server running.

here is the code:

edit: now the server returns a A answer with the correct ip

import socket

from twisted.internet import reactor
from twisted.names import dns
from twisted.names import client, server

hostname = socket.gethostbyaddr(socket.gethostname())[0]
magic_number = + 5 + 1 + len(hostname)


class Resolver(client.Resolver):
    def lookupAddress(self, name, timeout = None):
        if name.endswith('.local'):
            local_name = name[-magic_number:]
            ip = reactor.resolve(local_name)
            if local_name == name:
                ip = reactor.resolve(local_name)
                def answer(adress):
                    a = dns.RRHeader(name=name, ttl=0)
                    payload = dns.Record_A(adress)
                    a.payload = payload
                    return ([a], [], [])
                d = ip.addCallback(answer)
                return d
            else:
                def answer(adress):
                    a = dns.RRHeader(name=name, type=dns.A, ttl=10)
                    payload = dns.Record_A(adress, ttl=10)
                    a.payload = payload

                    return ([a], [], [])
                d = ip.addCallback(answer)
                return d
        else:
            return self._lookup(name, dns.IN, dns.A, timeout)

resolver = Resolver(servers=[('212.27.40.241', 53)])
factory = server.DNSServerFactory(clients=[resolver])
protocol = dns.DNSDatagramProtocol(factory)

reactor.listenUDP(53, protocol)
reactor.listenTCP(53, factory)
reactor.run()

I have done some tests with dig and everything looks like good. My hostname is tachtev.

here is the output of dig www.tachtev.local

; <<>> DiG 9.7.3 <<>> www.tachtev.local
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12794
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.tachtev.local.             IN      A

;; ANSWER SECTION:
www.tachtev.local.      500     IN      CNAME   tachtev.local.

;; Query time: 2 msec
;; SERVER: 192.168.0.6#53(192.168.0.6)
;; WHEN: Sun Jun 26 15:51:41 2011
;; MSG SIZE  rcvd: 49

here is the output of nslookup

root@tachtev:~# nslookup -debug www.tachtev.local
Server:         127.0.0.1
Address:        127.0.0.1#53

------------
    QUESTIONS:
        www.tachtev.local, type = A, class = IN
    ANSWERS:
    ->  www.tachtev.local
        internet address = 192.168.0.4
        ttl = 10
    AUTHORITY RECORDS:
    ADDITIONAL RECORDS:
------------
Non-authoritative answer:
Name:   www.tachtev.local
Address: 192.168.0.4

Everything looks good when I dig the urls. But now when I try to curl www.tachtev.local I get a host not found error.

Where does the error come from ?

edit: dependencies : avahi + avahi-dnsconfd + twisted + twisted names (which can not be pip'ed) edit: I did not find solution, but there is a software that does what I want to achieve http://pow.cx/

amirouche
  • 7,682
  • 6
  • 40
  • 94
  • socket.gethostname usually isn't a very reliable way to learn your local hostname. When you run this, does `hostname` actually get set to "tachtev"? When I run it, I get "localhost.localdomain" instead. – Jean-Paul Calderone Jun 26 '11 at 15:23
  • @Jean-Paul Calderone, yes it's set to tachtev, it comes straight from python documentation http://docs.python.org/library/os.html#os.uname – amirouche Jun 26 '11 at 20:55
  • The Python documentation is not always correct. :) Each of these approaches will break in certain configurations. – Jean-Paul Calderone Jun 27 '11 at 01:59
  • Why dont you just run avahi? This sounds like a lots of trouble for you... – vidstige Jun 27 '11 at 08:37
  • 1
    @vidstige, avahi doesn't resolve subdomains to domains ip... – amirouche Jun 27 '11 at 14:01
  • @FMR um, I don't really know what your aiming at here. But it certainly resolves hostnames on "subdomains". Check out the command line program `avahi-resolve` for example. – vidstige Jun 27 '11 at 17:13
  • ˇ# avahi-resolve -n www.tachtev.local Failed to resolve host name 'www.tachtev.local': Timeout reached – amirouche Jun 28 '11 at 07:26

1 Answers1

1

Client OSes use something called a stub resolver. Stub resolvers expect that their DNS server will be a full-blown recursive resolver, and supply them a full-formed answer.

CNAME replies to a stub resolver must include the target of the CNAME; that is, you must include the A record in the DNS payload as well as the CNAME.

Realist
  • 509
  • 2
  • 13
  • I added a A record but it didn't work. I modified the program to answer directly an A record instead of CNAME + A. But it still doesn't work. – amirouche Jun 29 '11 at 23:33