commit 9b0dc3f61345b941d137cfe76b3f8585dfcd77b6 Author: J. Fernando Sánchez Date: Tue Oct 20 12:44:55 2015 +0200 diff --git a/dns.py b/dns.py new file mode 100644 index 0000000..a694787 --- /dev/null +++ b/dns.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- + +from __future__ import print_function + +try: + from subprocess import getoutput +except ImportError: + from commands import getoutput + +from dnslib import RR,QTYPE,RCODE,A,parse_time +from dnslib.label import DNSLabel +from dnslib.server import DNSServer,DNSHandler,BaseResolver,DNSLogger +from docker import Client, errors + +class DockerResolver(BaseResolver): + """ + + """ + def __init__(self, docker='unix://var/run/docker.sock', + origin='docker', ttl='60s'): + self.client = Client(base_url=docker) + self.origin = DNSLabel(origin) + self.ttl = parse_time(ttl) + + def resolve(self,request,handler): + reply = request.reply() + qname = request.q.qname + print("Queried: %s" % qname) + print("Label: %s" % self.origin) + found = False + if not qname.matchSuffix(self.origin): + print("Not the %s domain" % self.origin) + return reply + cname = "/" + str(qname.stripSuffix(self.origin))[:-1].replace("/", "_") + try: + for c in self.client.containers(): + if cname in c["Names"]: + container = self.client.inspect_container(c["Id"]) + ns = container.get("NetworkSettings", {}) + if ns: + address = ns.get("IPAddress", None) + print("Found %s [%s]" % (cname, address)) + if address: + reply.add_answer(RR(qname,QTYPE.A,ttl=self.ttl, + rdata=A(address))) + else: + print("Found %s - NO IP" % cname) + found = True + break + if not found: + print("Container not found: %s" % cname) + except Exception as ex: + print("Error occurred querying [%s]: %s" % (cname, ex)) + return reply + +if __name__ == '__main__': + + import argparse,sys,time + + p = argparse.ArgumentParser(description="Docker DNS Resolver") + p.add_argument("--docker","-d",default="unix://var/run/docker.sock", + metavar="", + help="Docker Socket/URL (default: unix://var/run/docker.sock)") + p.add_argument("--origin","-o",default="docker", + metavar="", + help="Origin domain label (default: .)") + p.add_argument("--ttl","-t",default="60s", + metavar="", + help="Response TTL (default: 60s)") + p.add_argument("--port","-p",type=int,default=53, + metavar="", + help="Server port (default:53)") + p.add_argument("--address","-a",default="", + metavar="
", + help="Listen address (default:all)") + p.add_argument("--udplen","-u",type=int,default=0, + metavar="", + help="Max UDP packet length (default:0)") + p.add_argument("--tcp",action='store_true',default=False, + help="TCP server (default: UDP only)") + p.add_argument("--log",default="request,reply,truncated,error", + help="Log hooks to enable (default: +request,+reply,+truncated,+error,-recv,-send,-data)") + p.add_argument("--log-prefix",action='store_true',default=False, + help="Log prefix (timestamp/handler/resolver) (default: False)") + args = p.parse_args() + + resolver = DockerResolver(docker=args.docker, origin=args.origin, ttl=args.ttl) + logger = DNSLogger(args.log,args.log_prefix) + + print("Starting Docker Resolver for %s (%s:%d) [%s]" % ( + args.docker, + args.address or "*", + args.port, + "UDP/TCP" if args.tcp else "UDP")) + + if args.udplen: + DNSHandler.udplen = args.udplen + + udp_server = DNSServer(resolver, + port=args.port, + address=args.address, + logger=logger) + udp_server.start_thread() + + if args.tcp: + tcp_server = DNSServer(resolver, + port=args.port, + address=args.address, + tcp=True, + logger=logger) + tcp_server.start_thread() + + while udp_server.isAlive(): + time.sleep(1)