def __init__(self, routes, origin, ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route, _, cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd
def __init__(self,zone,origin="",ttl=0): self.l = WordLexer(zone) self.l.commentchars = ';' self.l.nltok = ('NL',None) self.l.spacetok = ('SPACE',None) self.i = iter(self.l) if type(origin) is DNSLabel: self.origin = origin else: self.origin= DNSLabel(origin) self.ttl = ttl self.label = DNSLabel("") self.prev = None
def load_domain_rules(self): with open(self.domains_rules_filename, 'r') as fh: for line in fh.readlines(): line = line.strip() if len(line) > 6: domain, rule = line.split(',', 2) if rule in self.DOMAIN_STATES: self.domain_rules[DNSLabel(domain)] = rule #print("Added domain rule: %s %s" % (domain, rule)) if rule == self.DOMAIN_REQUESTED: request_label = self.add_request( domain, DNSLabel(domain)) print("To approve %s, please query %s" % (domain, str(request_label)))
def resolve(self, request, handler): reply = request.reply( ) # the object that this function will return in the end, with modifications qname = request.q.qname # the domain that was looked up burrow_log("Request for " + str(DNSLabel(qname.label[-5:])), 0) # First, we make sure the domain ends in burrow.tech. # If not, we return an NXDOMAIN result. if not qname.matchSuffix("burrow.tech"): reply.header.rcode = RCODE.NXDOMAIN return reply # Next, we try to look up the domain in our list of fixed test records. found_fixed_rr = False for rr in self.fixedrrs: a = copy.copy(rr) if (a.rname == qname): found_fixed_rr = True LOG("Found a fixed record for " + str(a.rname)) reply.add_answer(a) if found_fixed_rr: return reply # Alright, if we've gotten here it must be a Transmission API message! assert (not found_fixed_rr) response_dict = self.handle_transmission_api_message(qname) zone = generate_TXT_zone(str(qname), dict_to_attributes(response_dict)) rrs = RR.fromZone(zone) for rr in rrs: reply.add_answer(rr) return reply
class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) """ def __init__(self,routes,origin,ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route,_,cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self,request,handler): reply = request.reply() qname = request.q.qname cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer(RR(qname,QTYPE.TXT,ttl=self.ttl, rdata=TXT(output[:254]))) else: reply.header.rcode = RCODE.NXDOMAIN return reply
def resolve(self, request, handler): reply = request.reply() qname = request.q.qname if static_entries.get(str(qname)): # print("Got from static entries") for response in static_entries[str(qname)]: if request.q.qtype == response.rtype: reply.add_answer(response) return reply if any([str(qname).endswith(d) for d in mdns_domains]): # print("Querying mDNS") return self.resolve_mdns(request, handler) for f, repl in alternative_nonlocal_domains.items(): # print("Asking for {} v. {}".format(qname, f)) if qname.matchSuffix(f): print("Matched suffix. Rewriting query from {} to {}".format( f, repl)) request.q.qname = DNSLabel(repl).add(qname.stripSuffix(f)) print("Now querying for: {}".format(request.q.qname)) return self.resolve_mdns(request, handler, rewrite=qname) # print("Querying upstream DNS") return self.resolve_fwd(request, handler)
class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) Shell commands are passed in a a list in <label>:<cmd> format - eg: [ 'uptime.abc.com.:uptime', 'ls:ls' ] Would respond to requests to 'uptime.abc.com.' with the output of the 'uptime' command. For non-absolute labels the 'origin' parameter is prepended """ def __init__(self, routes, origin, ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route, _, cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self, request, handler): print("resolver:" + "-" * 40) reply = request.reply() qname = request.q.qname ia = ip_address(handler.client_address[0]) cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer( RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254]))) else: rqt = QTYPE.TXT rqd = TXT(f"{str(ia)}") if request.q.qtype in [QTYPE.A, QTYPE.AAAA, QTYPE.PTR]: QTR = {QTYPE.A: "A", QTYPE.AAAA: "AAAA", QTYPE.PTR: "PTR"} qt = QTR[request.q.qtype] if ia.version is 6 and request.q.qtype == QTYPE.AAAA: rqt = request.q.qtype rqd = AAAA(str(ia)) elif ia.version is 4 and request.q.qtype == QTYPE.A: rqt = request.q.qtype rqd = A(str(ia)) elif request.q.qtype == QTYPE.PTR: rqt = request.q.qtype rqd = PTR(str(ia.reverse_pointer)) else: rqt = QTYPE.TXT rqd = TXT( f"Your request for {qt} confuses me, but here is the IP as text {str(ia)}" ) reply.add_answer(RR(qname, rqt, ttl=self.ttl, rdata=rqd)) return reply
def __init__(self, origin, ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} self.keys = [""] self.files = dict() self.cmd = "true"
def parse(self): rr = [] paren = False try: while True: tok,val = next(self.i) if tok == 'NL': if not paren and rr: self.prev = tok yield self.parse_rr(rr) rr = [] elif tok == 'SPACE' and self.prev == 'NL' and not paren: rr.append('') elif tok == 'ATOM': if val == '(': paren = True elif val == ')': paren = False elif val == '$ORIGIN': self.expect('SPACE') origin = self.expect('ATOM') self.origin = self.label = DNSLabel(origin) elif val == '$TTL': self.expect('SPACE') ttl = self.expect('ATOM') self.ttl = parse_time(ttl) else: rr.append(val) self.prev = tok except StopIteration: if rr: yield self.parse_rr(rr)
class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) """ def __init__(self, routes, origin, ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route, _, cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self, request, handler): reply = request.reply() qname = request.q.qname cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer( RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254]))) else: reply.header.rcode = RCODE.NXDOMAIN return reply
def _generate_as_topo(self, topo_id, as_conf): dns_domain = DNSLabel(as_conf.get("dns_domain", DEFAULT_DNS_DOMAIN)) dns_domain = dns_domain.add("isd%s" % topo_id[0]).add("as%s" % topo_id[1]) mtu = as_conf.get('mtu', self.default_mtu) assert mtu >= SCION_MIN_MTU, mtu self.topo_dicts[topo_id] = { 'Core': as_conf.get('core', False), 'ISD_AS': str(topo_id), 'DnsDomain': str(dns_domain), 'Zookeepers': {}, 'MTU': mtu, } for i in SCION_SERVICE_NAMES: self.topo_dicts[topo_id][i] = {} self._gen_srv_entries(topo_id, as_conf, dns_domain) self._gen_er_entries(topo_id) self._gen_zk_entries(topo_id, as_conf)
def parse_label(self,label): if label.endswith("."): self.label = DNSLabel(label) elif label == "@": self.label = self.origin elif label == '': pass else: self.label = self.origin.add(label) return self.label
def __init__(self,covered,algorithm,labels,orig_ttl, sig_exp,sig_inc,key_tag,name,sig): self.covered = covered self.algorithm = algorithm self.labels = labels self.orig_ttl = orig_ttl self.sig_exp = sig_exp self.sig_inc = sig_inc self.key_tag = key_tag self.name = DNSLabel(name) self.sig = sig
def __init__(self,routes,origin,ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route,_,cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd
def __init__(self, zone, origin="", ttl=0): self.l = WordLexer(zone) self.l.commentchars = ";" self.l.nltok = ("NL", None) self.l.spacetok = ("SPACE", None) self.i = iter(self.l) if type(origin) is DNSLabel: self.origin = origin else: self.origin = DNSLabel(origin) self.ttl = ttl self.label = DNSLabel("") self.prev = None
async def set_domain(self, request): data = await request.post() if data.get('domain') and data.get('status') and data['status'] in [ 'allowed', 'blocked', 'requested' ]: self.resolver.domain_rules[DNSLabel( data['domain'])] = data['status'] return web.json_response({ 'status': 'OK', 'message': 'domain %s set to %s' % (data['domain'], data['status']) }) else: return web.json_response({ 'status': 'FAILURE', 'error': 'could not understand request' })
def __init__(self, config): self.running = True self.config = config #print(config) self.upstream_ip = config['upstream_recursive_dns_ip'] self.upstream_port = int(config['upstream_recursive_dns_port']) self.secret_hashkey = config['secret_hashkey'] self.clients_rules_filename = config['clients_rules_filename'] self.domains_rules_filename = config['domains_rules_filename'] self.origin = DNSLabel("control") self.timeout = int(config.get('timeout', 10)) self.command_channels = [] self.client_rules = {} self.domain_rules = {} self.rr_cache = {} self.requests = {} self.rrs = RR.fromZone(". 60 IN A 127.0.0.1") self.load_client_rules() self.load_domain_rules()
class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) Shell commands are passed in a a list in <label>:<cmd> format - eg: [ 'uptime.abc.com.:uptime', 'ls:ls' ] Would respond to requests to 'uptime.abc.com.' with the output of the 'uptime' command. For non-absolute labels the 'origin' parameter is prepended """ def __init__(self, routes, origin, ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route, _, cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self, request, handler): reply = request.reply() qname = request.q.qname cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer( RR(qname, QTYPE.TXT, ttl=self.ttl, rdata=TXT(output[:254]))) else: reply.header.rcode = RCODE.NXDOMAIN return reply
class ShellResolver(BaseResolver): """ Example dynamic resolver. Maps DNS labels to shell commands and returns result as TXT record (Note: No context is passed to the shell command) Shell commands are passed in a a list in <label>:<cmd> format - eg: [ 'uptime.abc.com.:uptime', 'ls:ls' ] Would respond to requests to 'uptime.abc.com.' with the output of the 'uptime' command. For non-absolute labels the 'origin' parameter is prepended """ def __init__(self,routes,origin,ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl) self.routes = {} for r in routes: route,_,cmd = r.partition(":") if route.endswith('.'): route = DNSLabel(route) else: route = self.origin.add(route) self.routes[route] = cmd def resolve(self,request,handler): reply = request.reply() qname = request.q.qname cmd = self.routes.get(qname) if cmd: output = getoutput(cmd).encode() reply.add_answer(RR(qname,QTYPE.TXT,ttl=self.ttl, rdata=TXT(output[:254]))) else: reply.header.rcode = RCODE.NXDOMAIN return reply
def set_target(self,target): if isinstance(target,DNSLabel): self._target = target else: self._target = DNSLabel(target)
SUPERVISOR_CONF = 'supervisord.conf' COMMON_DIR = 'endhost' ZOOKEEPER_HOST_TMPFS_DIR = "/run/shm/host-zk" ZOOKEEPER_TMPFS_DIR = "/run/shm/scion-zk" DEFAULT_LINK_BW = 1000 DEFAULT_BEACON_SERVERS = 1 DEFAULT_CERTIFICATE_SERVERS = 1 DEFAULT_PATH_SERVERS = 1 DEFAULT_DNS_SERVERS = 1 DEFAULT_SIBRA_SERVERS = 1 INITIAL_CERT_VERSION = 0 INITIAL_TRC_VERSION = 0 DEFAULT_DNS_DOMAIN = DNSLabel("scion") DEFAULT_NETWORK = "127.0.0.0/8" DEFAULT_MININET_NETWORK = "100.64.0.0/10" SCION_SERVICE_NAMES = ( "BeaconServers", "CertificateServers", "DNSServers", "EdgeRouters", "PathServers", "SibraServers", ) class ConfigGenerator(object):
def resolve(self, request, handler): reply = request.reply() qname = request.q.qname suffix = DNSLabel(self.origin) if str(qname.label[-len(suffix.label):]).lower() == str(suffix.label).lower(): rem = DNSLabel(qname.label[:-len(suffix.label)]) print(rem) found_rrs = [] found_glob = [] rrs = [] for extra in ZoneExtra.objects.all(): rrs += RR.fromZone(extra.entry) for dyn in DynamicEntry.objects.all(): rrs += RR.fromZone(dyn.combined) for rr in rrs: if rem.matchSuffix(rr.rname): rr.rname.label += self.origin.label found_rrs.append(rr) elif rem.matchGlob(rr.rname): rr.rname.label += self.origin.label found_glob.append(rr) if len(found_rrs): reply.add_auth(*RR.fromZone(f"{self.origin} 60 IN NS {settings.DNS_BASE_DOMAIN}")) reply.add_answer(*found_rrs) elif len(found_glob): reply.add_auth(*RR.fromZone(f"{self.origin} 60 IN NS {settings.DNS_BASE_DOMAIN}")) for g in found_glob: g.set_rname(qname) reply.add_answer(*found_glob) cts = Container.objects.filter(name=str(str(rem)[:-1]).lower()) if cts.exists(): ct = cts.first() reply.add_auth(*RR.fromZone(f"{self.origin} 60 IN NS {settings.DNS_BASE_DOMAIN}")) if request.q.qtype == QTYPE.A: for ip in ct.ip_set.all(): if ip.is_ipv4: reply.add_answer(RR(qname, QTYPE.A, ttl=self.ttl, rdata=A(ip.ip))) elif ip.siit_ip.exists(): reply.add_answer(RR(qname, QTYPE.A, ttl=self.ttl, rdata=A(ip.siit_ip.first().ip))) if request.q.qtype == QTYPE.AAAA: for ip in ct.ip_set.all(): if not ip.is_ipv4: reply.add_answer(RR(qname, QTYPE.AAAA, ttl=self.ttl, rdata=AAAA(ip.ip))) # try other server if len(reply.rr) == 0 and (settings.DNS_MIRROR_SERVER is not None): print("checking other server because no rr and env: .%s. "%settings.DNS_MIRROR_SERVER) connections.close_all() # might fail apk = request.send(settings.DNS_MIRROR_SERVER, 53, timeout=30) reply = DNSRecord.parse(apk) if len(reply.rr) == 0: reply.header.rcode = RCODE.NOERROR else: reply.header.rcode = RCODE.NXDOMAIN connections.close_all() return reply
class ZoneParser: """ Zone file parser >>> z = ZoneParser("www.example.com. 60 IN A 1.2.3.4") >>> list(z.parse()) [<DNS RR: 'www.example.com.' rtype=A rclass=IN ttl=60 rdata='1.2.3.4'>] """ def __init__(self, zone, origin="", ttl=0): self.l = WordLexer(zone) self.l.commentchars = ";" self.l.nltok = ("NL", None) self.l.spacetok = ("SPACE", None) self.i = iter(self.l) if type(origin) is DNSLabel: self.origin = origin else: self.origin = DNSLabel(origin) self.ttl = ttl self.label = DNSLabel("") self.prev = None def expect(self, expect): t, val = next(self.i) if t != expect: raise ValueError("Invalid Token: %s (expecting: %s)" % (t, expect)) return val def parse_label(self, label): if label.endswith("."): self.label = DNSLabel(label) elif label == "@": self.label = self.origin elif label == "": pass else: self.label = self.origin.add(label) return self.label def parse_rr(self, rr): label = self.parse_label(rr.pop(0)) ttl = int(rr.pop(0)) if rr[0].isdigit() else self.ttl rclass = rr.pop(0) if rr[0] in ("IN", "CH", "HS") else "IN" rtype = rr.pop(0) rdata = rr rd = RDMAP.get(rtype, RD) return RR( rname=label, ttl=ttl, rclass=getattr(CLASS, rclass), rtype=getattr(QTYPE, rtype), rdata=rd.fromZone(rdata, self.origin), ) def __iter__(self): return self.parse() def parse(self): rr = [] paren = False try: while True: tok, val = next(self.i) if tok == "NL": if not paren and rr: self.prev = tok yield self.parse_rr(rr) rr = [] elif tok == "SPACE" and self.prev == "NL" and not paren: rr.append("") elif tok == "ATOM": if val == "(": paren = True elif val == ")": paren = False elif val == "$ORIGIN": self.expect("SPACE") origin = self.expect("ATOM") self.origin = self.label = DNSLabel(origin) elif val == "$TTL": self.expect("SPACE") ttl = self.expect("ATOM") self.ttl = parse_time(ttl) else: rr.append(val) self.prev = tok except StopIteration: if rr: yield self.parse_rr(rr)
def prompt(self): resolver = self.resolver while self.running: sys.stdout.write('> ') sys.stdout.flush() line = sys.stdin.readline().strip() if line.startswith('requests'): msg = "" for req in resolver.requests.keys(): msg += "%s: %s\n" % (str(resolver.requests[req]), req) print(msg) elif line.startswith('request allow '): _, _, request_domain = line.split(' ', 3) request_label = DNSLabel(request_domain) domain = resolver.approve_request(request_domain) if domain: print("%s allowed" % domain) else: print("Request %s not found" % request_domain) elif line.startswith('request deny '): _, _, request_domain = line.split(' ', 2) request_label = DNSLabel(request_domain) domain = resolver.deny_request(request_domain) if domain: print("%s blocked" % domain) else: print("Request %s not found" % request_domain) elif line.startswith('domains'): rules = resolver.get_domainrules() col1width = max([len(x) for x in rules.keys()]) + 1 if col1width < 5: col1width = 5 print("%s Rule" % 'Domain'.ljust(col1width)) print("%s ==========" % ('=' * col1width)) filt = None lineparts = line.split(' ') if len(lineparts) > 1: filt = lineparts[1] for dom in sorted(rules.keys(), key=str): if filt and not filt in str(dom): continue print('%s %s' % (str(dom).ljust(col1width), rules[dom])) elif line.startswith('domain block'): _, _, domain = line.split(' ', 3) req = resolver.get_request(domain) if req: resolver.deny_request(req) else: resolver.block_domain(domain) resolver.save_domain_rules() print("%s denied" % domain) elif line.startswith('domain allow'): _, _, domain = line.split(' ', 3) req = resolver.get_request(domain) if req: resolver.approve_request(req) else: resolver.allow_domain(domain) resolver.save_domain_rules() print("%s allowed" % domain) elif line.startswith('clients'): print("Client Rule") print("================== ================") filt = None lineparts = line.split(' ') if len(lineparts) > 1: filt = lineparts[1] for client in sorted(resolver.get_clientrules().keys()): if filt and not filt in client: continue else: print( '%s %s' % (client.rjust(18), resolver.client_rules[client])) elif line.startswith('client block'): _, _, clientip = line.split(' ', 3) resolver.block_client(clientip) resolver.save_client_rules() elif line.startswith('client enforce'): _, _, clientip = line.split(' ', 3) resolver.enforce_client(clientip) resolver.save_client_rules() elif line.startswith('client except'): _, _, clientip = line.split(' ', 3) resolver.except_client(clientip) resolver.save_client_rules() elif line.startswith('client deny'): _, _, clientip = line.split(' ', 3) resolver.deny_client(clientip) resolver.save_client_rules() elif line == 'help': print("""-= Requests =- requests list all requests request approve <request_id> approve the request tied to a domain, (hash.control.) request deny <request_id> deny the domain and add it to the block list -= Domains =- domains [filter] list all domain rules domain allow <domain> allow a domain domain block <domain> block a domain -= Clients =- clients [filter] list all client rules client block <ip> do not reply at all to this IP client except <ip> resolve everytime for this IP, regardless of rules client enforce <ip> enforce the rules on this client client deny <ip> return NXDOMAIN to all requests from this IP -= Other =- quit stops the DNS server help this useful stuff""") elif line == 'quit': self.running = False self.resolver.running = False print("exiting...") else: print("unknown command")
def set_qname(self,qname): if isinstance(qname,DNSLabel): self._qname = qname else: self._qname = DNSLabel(qname)
def set_rname(self,rname): if isinstance(rname,DNSLabel): self._rname = rname else: self._rname = DNSLabel(rname)
def on_event(self, conv_event): if isinstance(conv_event, hangups.ChatMessageEvent): print('received chat message: {!r}'.format(conv_event.text)) resolver = self.resolver if conv_event.text.startswith('!'): line = conv_event.text[1:] if line == 'quit': self.running = False print("exiting...") elif line.startswith('approve'): approve, request_domain = line.split(' ', 2) request_label = DNSLabel(request_domain) if resolver.requests.get(request_label): domain = resolver.requests[request_label] resolver.domain_rules[domain] = 'allowed' resolver.save_domain_rules() print("%s allowed" % domain) else: print("Request %s not found" % request_domain) elif line.startswith('deny'): approve, request_domain = line.split(' ', 2) request_label = DNSLabel(request_domain) if resolver.requests.get(request_label): domain = resolver.requests[request_label] resolver.domain_rules[domain] = 'blocked' resolver.save_domain_rules() print("%s denied" % domain) else: print("Request %s not found" % request_domain) elif line.startswith('blocklist'): _, domain = message.content.split(' ', 2) resolver.domain_rules[domain] = 'blocked' resolver.save_domain_rules() print("%s denied" % domain) elif line.startswith('block'): _, clientip = line.split(' ', 2) resolver.client_rules[client] = 'denied' resolver.save_client_rules() elif line.startswith('enforce'): _, clientip = line.split(' ', 2) resolver.client_rules[client] = 'enforced' resolver.save_client_rules() elif line.startswith('except'): _, clientip = line.split(' ', 2) resolver.client_rules[client] = 'excepted' resolver.save_client_rules() elif line.startswith('requests'): msg = "" for req in resolver.requests.keys(): msg += "%s: %s\n" % (str(resolver.requests[req]), req) print(msg) elif line == 'help': print("""help this useful stuff approve <request_id> approve the request tied to a domain, (hash.control.) deny <request_id> deny the domain and add it to the block list blocklist <domain> block a domain (reguardless of a request) block <client ip> return NXDOMAIN to all requests from this IP except <client ip> do not enforce rules on this client IP enforce <client ip> enforce rules on this client IP requests list the pending requests quit stops the DNS server""")
def label(label,origin=None): if label.endswith("."): return DNSLabel(label) else: return (origin if isinstance(origin,DNSLabel) else DNSLabel(origin)).add(label)
async def on_message(message): # we do not want the bot to reply to itself if message.author == client.user: return if message.content.startswith('!quit'): await client.logout() await client.close() elif message.content.startswith('!approve'): approve, request_domain = message.content.split(' ', 2) request_label = DNSLabel(request_domain) if resolver.requests.get(request_label): domain = resolver.requests[request_label] resolver.domain_rules[domain] = 'allowed' resolver.save_domain_rules() await message.channel.send("%s allowed" % domain) else: await message.channel.send("Request %s not found" % request_domain) elif message.content.startswith('!deny'): approve, request_domain = message.content.split(' ', 2) request_label = DNSLabel(request_domain) if resolver.requests.get(request_label): domain = resolver.requests[request_label] resolver.domain_rules[domain] = 'blocked' resolver.save_domain_rules() await message.channel.send("%s blocked" % domain) else: await message.channel.send("Request %s not found" % request_domain) elif message.content.startswith('!blocklist'): _, domain = message.content.split(' ', 2) resolver.domain_rules[domain] = 'blocked' resolver.save_domain_rules() await message.channel.send("%s blocked" % domain) elif message.content.startswith('!block'): _, clientip = message.content.split(' ', 2) resolver.client_rules[client] = 'denied' resolver.save_client_rules() elif message.content.startswith('!enforce'): _, clientip = message.content.split(' ', 2) resolver.client_rules[client] = 'enforced' resolver.save_client_rules() elif message.content.startswith('!except'): _, clientip = message.content.split(' ', 2) resolver.client_rules[client] = 'excepted' resolver.save_client_rules() elif message.content.startswith('!requests'): msg = "" for req in resolver.requests.keys(): msg += "%s: %s\n" % (str(resolver.requests[req]), req) await message.channel.send(msg) elif message.content == '!help': await message.channel.send(""" !help this useful stuff !approve <request_id> approve the request tied to a domain, (hash.control.) !deny <request_id> deny the domain and add it to the block list !blocklist <domain> block a domain (reguardless of a request) !block <client ip> return NXDOMAIN to all requests from this IP !except <client ip> do not enforce rules on this client IP !enforce <client ip> enforce rules on this client IP !requests list the pending requests !quit stops the DNS server""")
def set_label(self,label): if isinstance(label,DNSLabel): self._label = label else: self._label = DNSLabel(label)
class ZoneParser: """ Zone file parser >>> z = ZoneParser("www.example.com. 60 IN A 1.2.3.4") >>> list(z.parse()) [<DNS RR: 'www.example.com.' rtype=A rclass=IN ttl=60 rdata='1.2.3.4'>] """ def __init__(self,zone,origin="",ttl=0): self.l = WordLexer(zone) self.l.commentchars = ';' self.l.nltok = ('NL',None) self.l.spacetok = ('SPACE',None) self.i = iter(self.l) if type(origin) is DNSLabel: self.origin = origin else: self.origin= DNSLabel(origin) self.ttl = ttl self.label = DNSLabel("") self.prev = None def expect(self,expect): t,val = next(self.i) if t != expect: raise ValueError("Invalid Token: %s (expecting: %s)" % (t,expect)) return val def parse_label(self,label): if label.endswith("."): self.label = DNSLabel(label) elif label == "@": self.label = self.origin elif label == '': pass else: self.label = self.origin.add(label) return self.label def parse_rr(self,rr): label = self.parse_label(rr.pop(0)) ttl = int(rr.pop(0)) if rr[0].isdigit() else self.ttl rclass = rr.pop(0) if rr[0] in ('IN','CH','HS') else 'IN' rtype = rr.pop(0) rdata = rr rd = RDMAP.get(rtype,RD) return RR(rname=label, ttl=ttl, rclass=getattr(CLASS,rclass), rtype=getattr(QTYPE,rtype), rdata=rd.fromZone(rdata,self.origin)) def __iter__(self): return self.parse() def parse(self): rr = [] paren = False try: while True: tok,val = next(self.i) if tok == 'NL': if not paren and rr: self.prev = tok yield self.parse_rr(rr) rr = [] elif tok == 'SPACE' and self.prev == 'NL' and not paren: rr.append('') elif tok == 'ATOM': if val == '(': paren = True elif val == ')': paren = False elif val == '$ORIGIN': self.expect('SPACE') origin = self.expect('ATOM') self.origin = self.label = DNSLabel(origin) elif val == '$TTL': self.expect('SPACE') ttl = self.expect('ATOM') self.ttl = parse_time(ttl) else: rr.append(val) self.prev = tok except StopIteration: if rr: yield self.parse_rr(rr)
def set_mname(self,mname): if isinstance(mname,DNSLabel): self._mname = mname else: self._mname = DNSLabel(mname)
def resolve(self, request, handler): reply = request.reply() qname = request.q.qname qtype = QTYPE[request.q.qtype] # Proxy to upstream if not reply.rr: # replace domain if configured if qname.matchSuffix(self.domain_external): domain_replaced = True qname_extern = copy.copy(qname) qname.label = qname.stripSuffix( self.domain_external).label + DNSLabel( self.domain_internal).label #request.q.qname = qname print("Domain replaced from:" + self.domain_external + " to:" + self.domain_internal) else: domain_replaced = False try: if handler.protocol == 'udp': proxy_r = request.send(self.address, self.port, timeout=self.timeout) else: proxy_r = request.send(self.address, self.port, tcp=True, timeout=self.timeout) reply = DNSRecord.parse(proxy_r) except socket.timeout: reply.header.rcode = getattr(RCODE, 'NXDOMAIN') if domain_replaced: # Revert the RR record to external domain for r in reply.rr: if r.rname.matchSuffix(self.domain_internal): r.rname.label = r.rname.stripSuffix( self.domain_internal).label + DNSLabel( self.domain_external).label if isinstance(r.rdata, CNAME): if r.rdata.label.matchSuffix(self.domain_internal): r.rdata.label.label = r.rdata.label.stripSuffix( self.domain_internal).label + DNSLabel( self.domain_external).label # Change the AUTH record to external domain for r in reply.auth: if r.rname.matchSuffix(self.domain_internal): r.rname.label = r.rname.stripSuffix( self.domain_internal).label + DNSLabel( self.domain_external).label if isinstance(r.rdata, SOA): if r.rdata.mname.matchSuffix(self.domain_internal): r.rdata.mname.label = r.rdata.mname.stripSuffix( self.domain_internal).label + DNSLabel( self.domain_external).label if r.rdata.rname.matchSuffix(self.domain_internal): r.rdata.rname.label = r.rdata.rname.stripSuffix( self.domain_internal).label + DNSLabel( self.domain_external).label reply.q.qname = qname_extern reply.header.aa = 1 # set AA flag if needed if qname.matchSuffix(self.set_aa_flag_domain): reply.header.aa = 1 #print(reply) return reply
def __init__(self,routes,origin,ttl): self.origin = DNSLabel(origin) self.ttl = parse_time(ttl)
def set_replacement(self,replacement): if isinstance(replacement,DNSLabel): self._replacement = replacement else: self._replacement = DNSLabel(replacement)