Skip to content

Instantly share code, notes, and snippets.

@kotnik
Created June 6, 2013 14:51
Show Gist options
  • Select an option

  • Save kotnik/5722085 to your computer and use it in GitHub Desktop.

Select an option

Save kotnik/5722085 to your computer and use it in GitHub Desktop.

Revisions

  1. kotnik created this gist Jun 6, 2013.
    76 changes: 76 additions & 0 deletions small-dns-server.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,76 @@
    from collections import Mapping

    from twisted.names import dns, server, client, cache
    from twisted.application import service, internet


    class MapResolver(client.Resolver):
    def __init__(self, mapping, servers):
    client.Resolver.__init__(self, servers=servers)

    self.mapping = mapping
    self.ttl = 10

    def lookupAddress(self, name, timeout = None):
    if name in self.mapping:
    # We know the answer.
    value = self.mapping[name]
    return [
    (
    dns.RRHeader(
    name, dns.A, dns.IN, self.ttl,
    dns.Record_A(value, self.ttl)
    ),
    ),
    (),
    ()
    ]
    else:
    # Ask our backend server.
    return self._lookup(name, dns.IN, dns.A, timeout)


    class CustomMapping(Mapping):
    def __init__(self, servers):
    self._servers = servers

    def __getitem__(self, key):
    return self._servers[key]

    def __iter__(self):
    return self._servers.iterkeys()

    def __len__(self):
    return len(self._servers)


    # Our custom resolver.
    custom_mapping = CustomMapping({"example.com": "33.33.33.33"})

    # Upstream DNS server.
    upstream_dns = "8.8.8.8"

    # Setup Twisted application.
    application = service.Application('dnsserver', 1, 1)
    simpledns = MapResolver(custom_mapping, servers=[(upstream_dns, 53)])

    # Create protocols.
    f = server.DNSServerFactory(caches=[cache.CacheResolver()], clients=[simpledns])
    p = dns.DNSDatagramProtocol(f)
    f.noisy = p.noisy = False

    # Register both TCP and UDP on port 53.
    ret = service.MultiService()
    PORT = 53

    # Attach services to the parent.
    for (klass, arg) in [(internet.TCPServer, f), (internet.UDPServer, p)]:
    s = klass(PORT, arg)
    s.setServiceParent(ret)

    # Run as a twistd application.
    ret.setServiceParent(service.IServiceCollection(application))

    if __name__ == '__main__':
    import sys
    print "Usage: twistd -ny %s" % sys.argv[0]