Esempio n. 1
0
class ArcTestResolver(object):
    def __init__(self, records, port=8053, verbose=False):
        self.records = records
        self.port = port
        self.verbose = verbose

    def __enter__(self):
        zones = []
        for (domain, txt) in self.records.items():
            n = 255
            frags = [("'" + txt[i:i+n] + "'") for i in range(0, len(txt), n)]
            zones.append(domain + " IN TXT " + " ".join(frags))

        resolver = ZoneResolver("\n".join(zones))
        
        if self.verbose:
            logger = DNSLogger()
        else:
            logger = NullLogger()

        self.server = DNSServer(resolver, port=self.port, logger=logger)
        self.server.start_thread()

    def __exit__(self, type, value, traceback):
        self.server.stop()
Esempio n. 2
0
class MyDNSServer:

    server = None

    @classmethod
    def start(self, address):

        my_resolver = MyResolver(address)

        logger = DNSLogger(prefix=False)

        self.server = DNSServer(my_resolver,
                                port=10053,
                                address=str(address),
                                logger=logger)

        self.server.start_thread()
        print("DNS server is UP")
        # while server.isAlive():
        #   time.sleep(1)

    @classmethod
    def shut_down(self):
        print("shutting down the DNS server..\n")
        self.server.stop()
Esempio n. 3
0
    def http_01_challenge(self):
        self.logger.info("Performing http-01 challenge")
        for challenge in self.acme_challenges:
            token = challenge["token"]
            chall_url = challenge["url"]
            key_auth = crypto.get_key_authorization(token, self.jwk)

            zone = ". 60 IN A " + self.record_addr
            resolver = DnsResolver(zone)
            dns_server = DNSServer(resolver,
                                   address=self.record_addr,
                                   port=10053)
            dns_server.start_thread()

            challenge_server = ChallengeServer(token, key_auth,
                                               self.record_addr)
            challenge_server.start()

            r_dict = util.acme_server_request(self, chall_url, {}).json()
            self.logger.debug(r_dict)

            _dict = util.poll_acme_server(self, challenge['auth_url'], "",
                                          "valid")
            self.logger.debug(r_dict)

            challenge_server.terminate()
            challenge_server.join()
            dns_server.stop()
        return
Esempio n. 4
0
    def dns_01_challenge(self):
        self.logger.info("Performing dns-01 challenge")
        for challenge in self.acme_challenges:
            token = challenge["token"]
            chall_url = challenge["url"]
            key_auth = crypto.get_key_authorization(token, self.jwk)
            hashed_key_auth = hashlib.sha256(key_auth.encode('utf-8')).digest()
            hashed_key_auth = util.to_base64(hashed_key_auth)

            zone = ". 300 IN TXT " + hashed_key_auth
            resolver = DnsResolver(zone)
            dns_server = DNSServer(resolver,
                                   address=self.record_addr,
                                   port=10053)
            dns_server.start_thread()

            r_dict = util.acme_server_request(self, chall_url, {}).json()
            self.logger.debug(r_dict)

            r_dict = util.poll_acme_server(self, challenge['auth_url'], "",
                                           "valid")
            self.logger.debug(r_dict)

            dns_server.stop()
        return
Esempio n. 5
0
class CatlogResolver(BaseResolver):
    def __init__(self):
        self.txtMap = {}
        self.udp_server = None

    def setTxt(self, domain: str, value: str) -> None:
        self.txtMap[domain.lower()] = value

    def clearTxt(self, domain: str) -> None:
        del self.txtMap[domain.lower()]

    def resolve(self, request, handler):
        """
            Respond to DNS request - parameters are request packet & handler.
            Method is expected to return DNS response
        """
        reply = request.reply()
        qname = request.q.qname.idna()[:-1].lower()
        qtype = QTYPE[request.q.qtype]
        if qtype == 'TXT' and qname in self.txtMap:
            reply.add_answer(*RR.fromZone('{} IN TXT "{}"'.format(
                qname, self.txtMap[qname])))
        else:
            reply.header.rcode = RCODE.NXDOMAIN
        return reply

    def start(self):
        self.udp_server = DNSServer(self, port=53, logger=SilentLogger())
        self.udp_server.start_thread()

    def stop(self):
        self.udp_server.stop()
Esempio n. 6
0
class DnsSrvDiscoveryTest(TestCase):

    num_nodes = 3

    def setUp(self):
        zone_file = '''
crate.internal.               600   IN   SOA   localhost localhost ( 2007120710 1d 2h 4w 1h )
crate.internal.               400   IN   NS    localhost
crate.internal.               600   IN   A     127.0.0.1'''

        transport_ports = [bind_port() for _ in range(self.num_nodes)]
        for port in transport_ports:
            zone_file += '''
_test._srv.crate.internal.    600   IN   SRV   1 10 {port} 127.0.0.1.'''.format(
                port=port)

        dns_port = bind_port()
        self.dns_server = DNSServer(ZoneResolver(zone_file), port=dns_port)
        self.dns_server.start_thread()

        self.nodes = nodes = []
        for i in range(self.num_nodes):
            settings = {
                'node.name': f'node-{i}',
                'cluster.name': 'crate-dns-discovery',
                'psql.port': 0,
                'transport.tcp.port': transport_ports[i],
                "discovery.seed_providers": "srv",
                "discovery.srv.query": "_test._srv.crate.internal.",
                "discovery.srv.resolver": "127.0.0.1:" + str(dns_port)
            }
            if i == 0:
                settings['cluster.initial_master_nodes'] = f'node-{i}'
            node = CrateNode(crate_dir=crate_path(),
                             version=(4, 0, 0),
                             settings=settings,
                             env={
                                 'CRATE_HEAP_SIZE':
                                 '256M',
                                 'CRATE_JAVA_OPTS':
                                 '-Dio.netty.leakDetection.level=paranoid',
                             })
            node.start()
            nodes.append(node)

    def tearDown(self):
        for node in self.nodes:
            node.stop()
        self.dns_server.server.server_close()
        self.dns_server.stop()

    def test_nodes_discover_each_other(self):
        with connect(self.nodes[0].http_url) as conn:
            c = conn.cursor()
            c.execute('''select count(*) from sys.nodes''')
            result = c.fetchone()
        self.assertEqual(result[0], self.num_nodes,
                         'Nodes must be able to join')
Esempio n. 7
0
class DnsServer:
    def __init__(self, host: str, record: str, url: str):
        resolver = FixedResolver(record, url)
        self._server = DNSServer(resolver, port=10053, address=host)

    def start(self):
        self._server.start_thread()

    def shutDown(self):
        self._server.stop()
Esempio n. 8
0
 def start(self):
     server = DNSServer(resolver=HTTPResolver(query=import_query(),
                                              cache=SimpleCache()),
                        address=ConfigParse.listen,
                        port=ConfigParse.port,
                        logger=DNSLogger())
     server.start_thread()
     while self.running:
         time.sleep(5)
     server.stop()
Esempio n. 9
0
class DnsSrvDiscoveryTest(TestCase):

    num_nodes = 3

    def setUp(self):
        zone_file = '''
crate.internal.               600   IN   SOA   localhost localhost ( 2007120710 1d 2h 4w 1h )
crate.internal.               400   IN   NS    localhost
crate.internal.               600   IN   A     127.0.0.1'''

        transport_ports = [bind_port() for _ in range(self.num_nodes)]
        for port in transport_ports:
            zone_file += '''
_test._srv.crate.internal.    600   IN   SRV   1 10 {port} 127.0.0.1.'''.format(port=port)

        dns_port = bind_port()
        self.dns_server = DNSServer(ZoneResolver(zone_file), port=dns_port)
        self.dns_server.start_thread()

        self.nodes = nodes = []
        for i in range(self.num_nodes):
            settings = {
                         'node.name': f'node-{i}',
                         'cluster.name': 'crate-dns-discovery',
                         'psql.port': 0,
                         'transport.tcp.port': transport_ports[i],
                         "discovery.seed_providers": "srv",
                         "discovery.srv.query": "_test._srv.crate.internal.",
                         "discovery.srv.resolver": "127.0.0.1:" + str(dns_port)
                     }
            if i is 0:
                settings['cluster.initial_master_nodes'] = f'node-{i}'
            node = CrateNode(
                crate_dir=crate_path(),
                version=(4, 0, 0),
                settings=settings,
                env={
                    'CRATE_HEAP_SIZE': '256M'
                }
            )
            node.start()
            nodes.append(node)

    def tearDown(self):
        for node in self.nodes:
            node.stop()
        self.dns_server.server.server_close()
        self.dns_server.stop()

    def test_nodes_discover_each_other(self):
        with connect(self.nodes[0].http_url) as conn:
            c = conn.cursor()
            c.execute('''select count(*) from sys.nodes''')
            result = c.fetchone()
        self.assertEqual(result[0], self.num_nodes, 'Nodes must be able to join')
Esempio n. 10
0
File: dnsd.py Progetto: lmyzzu/etc
def main():
    resolver = SocksResolver(REAL_SERVER, 53)
    logger = DNSLogger("request,reply,truncated,error", False)

    server = DNSServer(
        resolver, port=53, address=LISTEN_ADDR, logger=logger,
    )
    try:
        server.start()
    except KeyboardInterrupt:
        server.stop()
Esempio n. 11
0
class DNS(object):
    def __init__(self):
        self.default_ip = get_default_ip()
        self.resolver = None
        self.server = None
        self.base_zone_data = None
        self.reset()

    def wait_for_query(self, record_type, record_name, timeout):
        self.resolver.wait_for_query(record_type, record_name, timeout)

    def load_zone(self, api_version, api_protocol, zone_name, port_base):
        zone_file = open(zone_name).read()
        template = Template(zone_file)
        zone_data = template.render(ip_address=self.default_ip,
                                    api_ver=api_version,
                                    api_proto=api_protocol,
                                    domain=CONFIG.DNS_DOMAIN,
                                    port_base=port_base)
        self.resolver = WatchingResolver(self.base_zone_data + zone_data)
        self.stop()
        print(" * Loading DNS zone file '{}' with api_ver={}".format(
            zone_name, api_version))
        self.start()

    def reset(self):
        zone_file = open("test_data/core/dns_base.zone").read()
        template = Template(zone_file)
        self.base_zone_data = template.render(ip_address=self.default_ip,
                                              domain=CONFIG.DNS_DOMAIN)
        self.resolver = WatchingResolver(self.base_zone_data)
        self.stop()
        print(" * Loading DNS zone base file")
        self.start()

    def start(self):
        if not self.server:
            print(" * Starting DNS server on {}:53".format(self.default_ip))
            try:
                self.server = DNSServer(self.resolver,
                                        port=53,
                                        address=self.default_ip)
                self.server.start_thread()
            except Exception as e:
                print(
                    " * ERROR: Unable to bind to port 53. DNS server could not start: {}"
                    .format(e))

    def stop(self):
        if self.server:
            print(" * Stopping DNS server on {}:53".format(self.default_ip))
            self.server.stop()
            self.server = None
Esempio n. 12
0
def main():
    try:
        resolver = ZoneResolver(ZONE, True)
        logger = RedisLogger()
        _dns_logger.info(ZONE)
        _dns_logger.info("Starting Dns Server (*:53) [UDP]")

        dns_server = DNSServer(resolver, port=53, address='', logger=logger)
        dns_server.start()
    except KeyboardInterrupt:
        _dns_logger.info("Shutting Down Dns Server (*:53) [UDP]")
        dns_server.stop()
Esempio n. 13
0
class DNSServerThread(QThread):
    """ Simple DNS server UDP resolver """

    sendRequests = pyqtSignal(object)  # I'll use this object in future feature

    def __init__(self, conf):
        super(DNSServerThread, self).__init__(parent=None)
        self.resolver = None
        self.conf = conf

    def run(self):

        port = int(os.getenv("PORT", 53))
        upstream = os.getenv("UPSTREAM", "8.8.8.8")
        zone_file = Path(C.DNSHOSTS)
        self.logger_dns = LocalDNSLogger(self.sendRequests)
        self.resolver = Resolver(upstream, zone_file, self.sendRequests)
        self.udp_server = DNSServer(self.resolver,
                                    port=port,
                                    logger=self.logger_dns)
        self.tcp_server = DNSServer(self.resolver,
                                    port=port,
                                    logger=self.logger_dns,
                                    tcp=True)
        print(
            display_messages("starting {}".format(self.objectName()),
                             info=True))

        # logger.info('starting DNS server on port %d, upstream DNS server "%s"', port, upstream)
        self.udp_server.start_thread()
        self.tcp_server.start_thread()

        try:
            while self.udp_server.isAlive():
                sleep(1)
        except KeyboardInterrupt:
            pass

    def getpid(self):
        """ return the pid of current process in background"""
        return "thread"

    def getID(self):
        """ return the name of process in background"""
        return self.objectName()

    def stop(self):
        self.udp_server.stop()
        self.tcp_server.stop()
        print(
            display_messages("thread {} successfully stopped".format(
                self.objectName()),
                             info=True))
Esempio n. 14
0
def main():
    num_nodes = 3

    node0_http_port = bind_port()
    dns_port = bind_port()
    transport_ports = []
    zone_file = '''
crate.internal.               600   IN   SOA   localhost localhost ( 2007120710 1d 2h 4w 1h )
crate.internal.               400   IN   NS    localhost
crate.internal.               600   IN   A     127.0.0.1'''

    for i in range(0, num_nodes):
        port = bind_port()
        transport_ports.append(port)
        zone_file += '''
_test._srv.crate.internal.    600   IN   SRV   1 10 {port} 127.0.0.1.'''.format(
            port=port)

    dns_server = DNSServer(ZoneResolver(zone_file), port=dns_port)
    dns_server.start_thread()

    crate_layers = []
    for i in range(0, num_nodes):
        crate_layer = CrateLayer(
            'node-' + str(i),
            cluster_name='crate-dns-discovery',
            crate_home=crate_path(),
            port=node0_http_port if i == 0 else bind_port(),
            transport_port=transport_ports[i],
            settings={
                'psql.port': bind_port(),
                "discovery.zen.hosts_provider": "srv",
                "discovery.srv.query": "_test._srv.crate.internal.",
                "discovery.srv.resolver": "127.0.0.1:" + str(dns_port)
            })
        crate_layers.append(crate_layer)
        crate_layer.start()

    try:
        conn = connect('localhost:{}'.format(node0_http_port))
        c = conn.cursor()
        c.execute('''select count() from sys.nodes''')
        result = c.fetchone()
        if result[0] != num_nodes:
            raise AssertionError(
                "Nodes could not join, expected number of nodes: " +
                str(num_nodes) + ", found: " + str(result[0]))

    finally:
        for crate_layer in crate_layers:
            crate_layer.stop()
        dns_server.stop()
    def run_dns_proxy(self):
        resolver = HTTPSResolver()
        logger = DNSLogger()

        server = DNSServer(resolver,
                           port=DNS_PORT,
                           address='localhost',
                           logger=logger)

        server.start_thread()
        while self.is_running:
            # this just keeps the thing alive...
            time.sleep(5)
        server.stop()
Esempio n. 16
0
class DNS(object):
    def __init__(self):
        self.default_ip = get_default_ip()
        self.resolver = None
        self.server = None
        self.base_zone_data = None
        self.reset()

    def load_zone(self, api_version, api_protocol):
        zone_file = open("test_data/IS0401/dns_records.zone").read()
        template = Template(zone_file)
        zone_data = template.render(ip_address=self.default_ip,
                                    api_ver=api_version,
                                    api_proto=api_protocol,
                                    domain=DNS_DOMAIN)
        self.resolver = ZoneResolver(self.base_zone_data + zone_data)
        self.stop()
        print(" * Loading DNS zone file with api_ver={}".format(api_version))
        self.start()

    def reset(self):
        zone_file = open("test_data/IS0401/dns_base.zone").read()
        template = Template(zone_file)
        self.base_zone_data = template.render(ip_address=self.default_ip,
                                              domain=DNS_DOMAIN)
        self.resolver = ZoneResolver(self.base_zone_data)
        self.stop()
        print(" * Loading DNS zone base file")
        self.start()

    def start(self):
        if not self.server:
            print(" * Starting DNS server on {}:53".format(self.default_ip))
            try:
                self.server = DNSServer(self.resolver,
                                        port=53,
                                        address=self.default_ip)
                self.server.start_thread()
            except Exception as e:
                print(
                    " * ERROR: Unable to bind to port 53. DNS server could not start: {}"
                    .format(e))

    def stop(self):
        if self.server:
            print(" * Stopping DNS server on {}:53".format(self.default_ip))
            self.server.stop()
            self.server = None
class Authenticator(dns_common.DNSAuthenticator):
    """Standalone DNS Authenticator

    This Authenticator uses a standalone DNS server to fulfill a dns-01 challenge.
    """

    description = ('Obtain certificates using an integrated DNS server')

    def __init__(self, *args, **kwargs):
        super(Authenticator, self).__init__(*args, **kwargs)
        self.resolver = None
        self.udp_server = None

    @classmethod
    def add_parser_arguments(cls, add):  # pylint: disable=arguments-differ
        super(Authenticator,
              cls).add_parser_arguments(add, default_propagation_seconds=0)
        add('address', help='IP address to bind to.', default='0.0.0.0')

    def _setup_credentials(self):
        return

    def more_info(self):  # pylint: disable=missing-docstring,no-self-use
        return 'This plugin uses a standalone DNS server to respond to a dns-01 challenge.'

    def _perform(self, domain, validation_name, validation):
        if self.resolver is None:
            self.resolver = _AcmeResolver()

        self.resolver.addToken(validation)

        if self.udp_server is None:
            try:
                self.udp_server = DNSServer(self.resolver,
                                            port=53,
                                            address=self.conf('address'),
                                            logger=dnsLogger)
                self.udp_server.start_thread()
            except Exception as e:
                raise errors.PluginError(
                    'Error starting DNS server: {0}'.format(e))

    def _cleanup(self, domain, validation_name, validation):
        if self.udp_server:
            self.udp_server.stop()
Esempio n. 18
0
def main():
    """
    主函数
    :return:
    """
    zone = f"*.{DOMAIN}.       IN      A       {NS_SERVER}"

    resolver = ZoneResolver(zone, True)
    dns_logger = MyLogger()
    logger.info("启动域名解析 %s:%d" % ("0.0.0.0", 53))
    udp_server = DNSServer(resolver,
                           port=53,
                           address="0.0.0.0",
                           logger=dns_logger)

    try:
        udp_server.start()
    except KeyboardInterrupt:
        logger.info("正在关闭域名解析……")
        udp_server.stop()
        logger.info("关闭域名解析完成")
Esempio n. 19
0
    def runDNSProxy(self):
        resolver = CustomDNSResolver()
        logger = DNSLogger()
        server = DNSServer(resolver,
                           port=DNS_PORT,
                           address=DNS_SERVER_IPV4_ADDRESS,
                           logger=logger)
        server.start_thread()

        # Usage
        self.printUsage()

        while True:
            inputOption = input("[Input Number] ").strip()

            try:
                inputOption = inputOption.strip().lower()
            except ValueError:
                inputOption = 0

            if 'q' == inputOption:
                break
            elif '1' == inputOption:
                resolver.enableCustomDNS(True)
                print("Custom DNS Server turned on.")
            elif '2' == inputOption:
                resolver.enableCustomDNS(False)
                print("Custom DNS Server turned off.")
            elif 'p' == inputOption:
                # Print Custom DNS Status
                print("     Feature #1 - Custom DNS Server turned ", end='')
                if resolver.isCustomDNSEnabled:
                    print("on.")
                else:
                    print("off.")
                print("")
            else:
                self.printUsage()

        server.stop()
Esempio n. 20
0
class DNS(object):
    def __init__(self):
        default_gw_interface = netifaces.gateways()['default'][netifaces.AF_INET][1]
        default_ip = netifaces.ifaddresses(default_gw_interface)[netifaces.AF_INET][0]['addr']
        self.default_ip = default_ip
        self.resolver = None
        self.server = None
        self.base_zone_data = None
        self.reset()

    def load_zone(self, api_version):
        zone_file = open("test_data/IS0401/dns_records.zone").read()
        template = Template(zone_file)
        zone_data = template.render(ip_address=self.default_ip, api_ver=api_version)
        self.resolver = ZoneResolver(self.base_zone_data + zone_data)
        self.stop()
        self.start()

    def reset(self):
        zone_file = open("test_data/IS0401/dns_base.zone").read()
        template = Template(zone_file)
        self.base_zone_data = template.render(ip_address=self.default_ip)
        self.resolver = ZoneResolver(self.base_zone_data)
        self.stop()
        self.start()

    def start(self):
        if not self.server:
            print(" * Starting DNS server on {}:53".format(self.default_ip))
            try:
                self.server = DNSServer(self.resolver, port=53, address=self.default_ip)
                self.server.start_thread()
            except Exception as e:
                print(" * ERROR: Unable to bind to port 53. DNS server could not start: {}".format(e))

    def stop(self):
        if self.server:
            self.server.stop()
            self.server = None
Esempio n. 21
0
    def handle(self, *args, **options):
        # map django command verbosity to logging options
        logger = DNSLogger(log={
            '0': '-request,-reply,-truncated,-error',
            '1': '',
            '2': '+data',
            '3': '+recv,+send,+data'
        }[options['verbosity']])

        udp_server = DNSServer(
            resolver=InterceptingResolver(),
            address=options['address'],
            port=options['port'],
            logger=logger
        )
        udp_server.start_thread()

        try:
            while udp_server.isAlive():
                time.sleep(1)
        except KeyboardInterrupt:
            udp_server.stop()
Esempio n. 22
0
class FakeDNSServer:
    # pylint: disable=too-many-instance-attributes
    # pylint: disable=too-many-arguments
    def __init__(self,
                 listen_addr=const.DEFAULT_LISTEN_ADDR,
                 listen_port=const.DEFAULT_LISTEN_PORT,
                 *,
                 record_life=const.DEFAULT_CACHE_DURATION,
                 subnet=const.DEFAULT_SUBNET,
                 db_path=const.DEFAULT_DB_URI,
                 remove_records=False,
                 logger=None):
        self.logger = logger or DeliriumDNSLogger()
        self._addr = listen_addr
        self._port = listen_port
        self._resolver = DatabaseResolver(subnet,
                                          db_path=db_path,
                                          duration=record_life,
                                          remove=remove_records,
                                          logger=self.logger)
        self._dns_server = DNSServer(self._resolver,
                                     self._addr,
                                     self._port,
                                     logger=self.logger)

    @property
    def addr(self):
        return self._addr

    @property
    def port(self):
        return self._port

    @property
    def duration(self):
        return self._resolver.duration

    @duration.setter
    def duration(self, value):
        self.logger.debug('Setting cache duration to %s', value)
        self._resolver.duration = value

    @property
    def subnet(self):
        return self._resolver.subnet

    @subnet.setter
    def subnet(self, value):
        self.logger.debug('Setting cache subnet to %s', value)
        self._resolver.subnet = value

    def is_alive(self):
        return self._dns_server.isAlive()

    def start(self):
        self.logger.info('Starting Delirium DNS Server')
        self._dns_server.start()

    def start_thread(self):
        self._dns_server.start_thread()

    def stop(self):
        self.logger.info('Stopping Delerium DNS Server')
        self._resolver.close()
        self._dns_server.stop()
Esempio n. 23
0
def main():
    global OPTIONS, ARGS

    parser = OptionParser()

    parser.add_option("-b", "--bind", dest = "bind", \
                      type = "string", default = "127.0.0.7:53", \
                      help = "set bind address/port to IP[:PORT]. " \
                      "Default value is `127.0.0.7:53'.", \
                      metavar = "IP[:PORT]")
    parser.add_option("-t", "--timeout", dest = "timeout", \
                      type = "int", default = "5", \
                      help = "set DNS resolving timeout to SECONDS", \
                      metavar = "SECONDS")
    parser.add_option("-r", "--retry", dest = "retry", \
                      type = "int", default = "3", \
                      help = "set retry count to COUNT", metavar = "COUNT")
    parser.add_option("-i", "--invalid-resolve", dest = "invalid_resolve", \
                      type = "string", default = r"10\.10\.34\.\d+", \
                      help = "REGEX is a an IP address or a regular " \
                      "expression that will not be prefered on DNS " \
                      "resolving. Default value is `10.10.34.\\d+'.", \
                      metavar = "REGEX")
    parser.add_option("--request-bind", dest = "request_bind", \
                      type = "string", default = "", \
                      help = "bind to IP address before sending DNS " \
                      "requests.", metavar = "IP")
    parser.add_option("-q", "--quiet", dest = "quiet", \
                      action = "store_true", default = False, \
                      help = "do not print any log")
    
    parser.set_usage("%s [OPTION]... DNS_SERVER[:PORT]..." % \
                     sys.argv[0])
    parser.set_description(__doc__)

    OPTIONS, ARGS = parser.parse_args()

    if len(ARGS) < 1:
        parser.print_help()
        exit(1)

    def get_address_port(arg):
        address_port = arg if ":" in arg else "%s:53" % arg
        address_port = address_port.split(":")
        return address_port[0], int(address_port[1])

    bind_address, bind_port = get_address_port(OPTIONS.bind)
    dns_servers = [get_address_port(arg) for arg in ARGS]

    resolver = ProxyResolver(dns_servers, request_bind_address = \
                             (OPTIONS.request_bind or None))
    logger = DNSLogger("request,reply,truncated,error", False) \
             if not OPTIONS.quiet else \
             DNSLogger("-request,-reply,-truncated,-error,-log_recv," \
                       "-log_send,-log_data", False)
    udp_server = DNSServer(resolver,
                           port = bind_port,
                           address = bind_address,
                           logger = logger if not OPTIONS.quiet else None,
                           handler = DNSHandler,
                           server = UDPServer)

    udp_server.start_thread()

    try:
        while udp_server.isAlive():
            time.sleep(1)
    except KeyboardInterrupt:
        if not OPTIONS.quiet:
            print("Shutting down the server with user request...")
        udp_server.stop()
        exit(0)
Esempio n. 24
0
class ParentalControls(BaseResolver):

    """
        Intercepting resolver 
        
        Proxy requests to upstream server optionally intercepting requests
        matching local records
    """

    def __init__(self):
        self.log = logging.getLogger('dnspc.dnspc.ParentalControls')
        self.rules = []
        self.hosts = []
        self.LOCAL_IP = settings.DNS['LOCAL_IP']
        self.LOCAL_PORT = settings.DNS['LOCAL_PORT']
        self.UP_IP = settings.DNS['UP_IP']
        self.UP_PORT = settings.DNS['UP_PORT']
        self.TCP = settings.DNS['TCP']
        self.TTL = parse_time(settings.DNS['TTL'])
        self.store ={
            'rules': settings.DATA['RULES'],
            'hosts': settings.DATA['HOSTS']
        }
        self.load_rules()
        self.load_hosts()

    ## Rules
    def load_rules(self):
        stored_rules = self.store['rules'].loadRecords()
        uids = [r['_uid'] for r in self.rules]
        for sr in stored_rules:
            if sr['_uid'] in uids:
                continue
            rule = PCRule(**sr)
            self.rules.append(rule)
        self.log.debug("WTF:rules: {}".format(self.rules))
    def update_rule(self,rule):
        uid = rule._uid
        idxs = [i for i,c in enumerate(self.rules) if c._uid == uid]
        if len(idxs) == 0:
            self.rules.append(rule)
        else:
            self.rules[idxs[0]] = rule
        return rule

    def save_rule(self,d=None,**kwargs):
        #print "save_rule({})".format(kwargs)
        ## Remove angularjs artifacts:
        kwargs.pop('$$hashKey',None)
        saved_rule = self.store['rules'].editRecord(kwargs)
        self.log.debug("WTF: saved_rule: {}".format(saved_rule))
        rule = PCRule(**saved_rule)
        ## Not sure if I should update the rule, or just reload from disk.
        self.update_rule(rule)
        return rule

    def del_rule(self,uid):
        ''' del_rule(uid) returns:
             None: uid did not appear in list.
             True: success
            False: failure
        '''
        #print "del_rule({})".format(uid)
        #pp([x._serialize() for x in self.rules])
        self.store['rules'].deleteRecord({'_uid':uid})
        if uid not in [x._uid for x in self.rules]:
            return None
        self.rules = [x for x in self.rules if x._uid != uid]
        if uid in [x._uid for x in self.rules]:
            return False
        return True

    def get_rules(self):
        return self.rules

    def get_matching_rules(self,src_ip,dst_str):
        rs = [ r for r in self.rules if r.is_match(src_ip,dst_str) ]
        return rs

    ## Hosts
    def load_hosts(self):
        stored_hosts = self.store['hosts'].loadRecords()
        uids = [r['_uid'] for r in self.hosts]
        for sr in stored_hosts:
            if sr['_uid'] in uids:
                continue
            rule = PCHost(**sr)
            self.hosts.append(rule)
    def update_host(self,host):
        uid = host._uid
        idxs = [i for i,c in enumerate(self.hosts) if c._uid == uid]
        if len(idxs) == 0:
            self.hosts.append(host)
        else:
            self.hosts[idxs[0]] = host
        return host

    def save_host(self,d=None,**kwargs):
        #print "save_host({})".format(kwargs)
        ## Key generated by filestore.
        ## Can't risk overlap.
        #key = self._genkey(self.hosts)
        #print "WTF: Created key:",key
        kwargs.pop('$$hashKey',None)
        saved_host = self.store['hosts'].editRecord(kwargs)
        self.log.debug("WTF: saved_host: {}".format(saved_host))
        host = PCHost(**saved_host)
        self.update_host(host)
        #pp(self.hosts)
        return host

    def del_host(self,uid):
        ''' del_host(uid) returns:
             None: uid did not appear in list.
             True: success
            False: failure
        '''
        #print "del_host({})".format(uid)
        #pp([x._serialize() for x in self.hosts])
        self.store['hosts'].deleteRecord({'_uid':uid})
        if uid not in [x._uid for x in self.hosts]:
            return None
        self.hosts = [x for x in self.hosts if x._uid != uid]
        if uid in [x._uid for x in self.hosts]:
            return False
        return True

    def get_hosts(self):
        return self.hosts

    def _genkey(self,st):
        #print "WTF: _genkey()"
        key = int(time.strftime('%Y%U%w000'))
        #print "WTF: My key:",key
        keys = [r._uid for r in st]
        #print "WTF: keys:",keys
        #while len([1 for r in st if int(r['_uid']) == key]) > 0:
        while key in keys:
            key = key + 1
        return key

    ## DNS Server Methods
    def start(self):
        handler = DNSHandler
        # log options: "recv,send,request,reply,truncated,error,data"
        # log defaults: "request,reply,truncated,error"
        # It's just too much stuff!
        logger = DNSLogger("truncated,error",True)
        self.log.info("Starting UDP server")
        if 'udp_server' not in dir(self):
            self.udp_server = DNSServer(self,
                            port=self.LOCAL_PORT,
                            address=self.LOCAL_IP,
                            logger=logger,
                            handler=handler)
        self.udp_server.start_thread()
        if self.TCP:
            self.log.info("Starting TCP server")
            if 'tcp_server' not in dir(self):
                self.tcp_server = DNSServer(self,
                                port=self.LOCAL_PORT,
                                address=self.LOCAL_IP,
                                tcp=True,
                                logger=logger,
                                handler=handler)
            self.tcp_server.start_thread()

    def stop(self):
        self.log.debug( dir(self) )
        if 'udp_server' in dir(self):
            self.log.debug( "    Stopping UDP server." )
            self.udp_server.stop()
        if 'tcp_server' in dir(self) and self.TCP:
            self.log.debug( "    Stopping TCP server." )
            self.tcp_server.stop()

    def resolve(self,request,handler):
        client_ip = handler.client_address[0]
        #print "Request from IP: {}".format(client_ip)
        qname = request.q.qname
        qtype = QTYPE[request.q.qtype]
        reply = request.reply()
        self.log.debug("{} request for {} by {}".format(qtype,qname,client_ip))
        #print "query: {}".format(qname)
        #print "query: {}".format(qname.matchGlob("*.yahoo.com"))
        # Try to resolve locally unless on skip list
        rules = self.get_matching_rules(client_ip,qname)
        self.log.debug("Matched rules: {}".format(rules))
        if any(rules):
            ## Collecting info on match for logging
            match_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            match_name = client_ip
            match_hosts = [h.name for h in self.hosts if h.ip == client_ip]
            if any(match_hosts):
                match_name = ",".join(match_hosts)
            for rule in rules:
                if rule.action == 'monitor':
                    monitor.info({'time':match_time,'match_name':match_name,'client_ip':client_ip,'qname':str(qname)})
                if rule.action == 'redirect':
                    self.log.debug( "[{}] REDIRECT {}-->{} to {}".format(match_time,match_name,qname,rule.redirect) )
                    redir = rule.redirect
                    reply.add_answer(*RR.fromZone("{} 3600 IN A {}".format(qname,redir)))
                    return reply
                if rule.action == 'block':
                    self.log.debug( "[{}] BLOCKED {}({})-->{}".format(match_time,match_name,client_ip,qname) )
                    return reply
                if rule.action == 'allow':
                    self.log.debug( "[{}] ALLOWED {}({})-->{}".format(match_time,match_name,client_ip,qname) )
        ## If no match or action == 'allow', then proxy the request to IP_UP
        if handler.protocol == 'udp':
            proxy_r = request.send(self.UP_IP,self.UP_PORT)
        else:
            proxy_r = request.send(self.UP_IP,self.UP_PORT,tcp=True)
        reply = DNSRecord.parse(proxy_r)
        return reply
Esempio n. 25
0
class DnsServer(BaseCommand):
    name = "dns-server"
    aliases = ["dns"]
    description = "run dns server"
    add_log_level = True
    add_debug = True

    def __init__(self, *args, **kwargs):
        self.api_client = None
        self.resolver = None
        self.udp_server = None
        self.tcp_server = None
        super().__init__(*args, **kwargs)

    @classmethod
    def parser(cls, parser):
        parser.add_argument(
            "-a",
            "--api-url",
            default="http://127.0.0.1:8080",
            action="store",
            help="api url",
        )
        parser.add_argument("-t",
                            "--api-token",
                            action="store",
                            help="api token")
        parser.add_argument("-p",
                            "--port",
                            action="store",
                            type=int,
                            default=53,
                            help="listen port")
        parser.add_argument("-l",
                            "--listen",
                            action="store",
                            default="127.0.0.1",
                            help="bind address")
        parser.add_argument("--no-sync",
                            action="store_true",
                            help="sync api token back to database")

        parser.add_argument(
            "--no-ssl-verify",
            action="store_true",
            help="skip ssl verify in the dns server's api client",
        )

        parser.add_argument(
            "-r",
            "--refresh-ttl",
            type=int,
            default=3600,
            action="store",
            help="time to wait before polling for new records",
        )
        return parser

    async def run(self):

        # TODO: thread issues?
        verify_ssl = True
        if bool(self.option("no_ssl_verify")):
            verify_ssl = False

        self.api_client = ApiClient(self.get_api_url(),
                                    self.get_api_token(),
                                    verify_ssl=verify_ssl)

        if not self.api_client.wait_for_up():
            logger.critical(
                "run@dns_server.py - Could not connect to api. quitting")
            self.exit(1)

        if self.option("no_sync"):
            logger.info("run@dns_server.py - Skipping syncing api token")
        else:
            self.api_client.sync()

        self.boot()

        self.start_servers()

        try:
            count = 0
            while self.udp_server.isAlive():
                if count > 0 and count % self.option("refresh_ttl") == 0:
                    if self.api_client.refresh_zones_if_needed():
                        logger.critical(
                            "run@dns_server.py - API Client found new or changed zones. Stopping servers..."
                        )
                        # TODO: figure out why "stop" does not release the address
                        self.stop_servers()

                        sleep(1)

                        stop_count = 0
                        logger.critical(
                            "run@dns_server.py - Waiting for UDP Server to stop..."
                        )
                        while self.udp_server.thread and self.udp_server.isAlive(
                        ):
                            if stop_count > 30:
                                logger.critical(
                                    "run@dns_server.py - UDP Server did not stop while reloading zones"
                                )
                                raise Exception(
                                    "run@dns_server.py - UDP Server threads went rogue during zone reload"
                                )
                            logger.info(
                                "run@dns_server.py - Waiting for DNS Server to stop before reloading zones"
                            )
                            stop_count = stop_count + 1
                            sleep(1)
                        stop_count = 0
                        logger.critical(
                            "run@dns_server.py - Waiting for TCP Server to stop..."
                        )
                        while self.tcp_server.thread and self.tcp_server.isAlive(
                        ):
                            if stop_count > 30:
                                logger.critical(
                                    "run@dns_server.py - TCP Server did not stop while reloading zones"
                                )
                                raise Exception(
                                    "run@dns_server.py - TCP Server threads went rogue during zone reload"
                                )
                            logger.info(
                                "run@dns_server.py - Waiting for DNS Server to stop before reloading zones"
                            )
                            stop_count = stop_count + 1
                            sleep(1)
                        logger.critical(
                            "run@dns_server.py - Rebooting server with fresh zones..."
                        )
                        self.boot()
                        self.start_servers()

                count = count + 1
                sleep(1)
        except KeyboardInterrupt:
            pass

    def get_api_url(self):
        if os.environ.get("API_URL", None):
            return os.environ.get("API_URL")
        return self.option("api_url")

    def get_api_token(self):
        if os.environ.get("API_TOKEN", None):
            return os.environ.get("API_TOKEN")
        if self.option("api_token", None):
            return self.option("api_token")
        logger.critical("api token required")
        self.exit(1)

    def get_port(self):
        return self.option("port")

    def get_listen(self):
        return self.option("listen")

    def boot(self):
        port = self.get_port()
        listen = self.get_listen()

        self.resolver = Resolver(self.api_client)
        self.udp_server = DNSServer(
            self.resolver,
            address=listen,
            port=port,
            handler=DNSHandler,
            logger=DNSLogger(self.api_client),
        )
        self.tcp_server = DNSServer(
            self.resolver,
            address=listen,
            port=port,
            tcp=True,
            handler=DNSHandler,
            logger=DNSLogger(self.api_client),
        )

        logger.info("starting DNS server on port %d", port)

    def start_servers(self):
        self.udp_server.start_thread()
        self.tcp_server.start_thread()

    def stop_servers(self):
        self.udp_server.stop()
        self.udp_server.server.socket.close()
        self.udp_server.server.server_close()
        self.tcp_server.stop()
        self.tcp_server.server.socket.close()
        self.tcp_server.server.server_close()
Esempio n. 26
0
    DNSHandler.log = {
        'log_request',      # DNS Request
        'log_reply',        # DNS Response
        'log_truncated',    # Truncated
        'log_error',        # Decoding error
    }

    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()

    try:
        while udp_server.isAlive():
            time.sleep(1)
    except KeyboardInterrupt:
        pass
    finally:
        udp_server.stop()
        if args.tcp:
            tcp_server.stop()
Esempio n. 27
0
class DNS(object):
    def __init__(self):
        self.default_ip = get_default_ip()
        self.resolver = None
        self.server = None
        self.base_zone_data = None
        self.reset()

    def wait_for_query(self, record_type, record_name, timeout):
        self.resolver.wait_for_query(record_type, record_name, timeout)

    def load_zone(self, api_version, api_protocol, api_authorization,
                  zone_name, port_base):
        zone_file = open(zone_name).read()
        template = Template(zone_file)
        zone_data = template.render(ip_address=self.default_ip,
                                    api_ver=api_version,
                                    api_proto=api_protocol,
                                    api_auth=str(api_authorization).lower(),
                                    domain=CONFIG.DNS_DOMAIN,
                                    port_base=port_base)
        self.resolver = WatchingResolver(self.base_zone_data + zone_data)
        self.stop()
        print(" * Loading DNS zone file '{}' with api_ver={}".format(
            zone_name, api_version))
        self.start()

    def reset(self):
        zone_file = open("test_data/core/dns_base.zone").read()
        template = Template(zone_file)

        extra_services = {}
        if CONFIG.ENABLE_AUTH:
            auth_proto = "https" if CONFIG.ENABLE_HTTPS else "http"
            extra_services["auth"] = {
                "host": CONFIG.AUTH_SERVER_HOSTNAME,
                "ip": CONFIG.AUTH_SERVER_IP,
                "port": CONFIG.AUTH_SERVER_PORT,
                "txt":
                ["api_ver=v1.0", "api_proto={}".format(auth_proto), "pri=0"]
            }
        if CONFIG.ENABLE_MQTT_BROKER:
            extra_services["mqtt"] = {
                "host": CONFIG.MQTT_BROKER_HOSTNAME,
                "ip": CONFIG.MQTT_BROKER_IP,
                "port": CONFIG.MQTT_BROKER_PORT,
                "txt": ["api_proto=mqtt", "api_auth=false"]
            }

        self.base_zone_data = template.render(ip_address=self.default_ip,
                                              domain=CONFIG.DNS_DOMAIN,
                                              extra_services=extra_services)
        self.resolver = WatchingResolver(self.base_zone_data)
        self.stop()
        print(" * Loading DNS zone base file")
        self.start()

    def start(self):
        if not self.server:
            print(" * Starting DNS server on {}:53".format(self.default_ip))
            try:
                self.server = DNSServer(self.resolver,
                                        port=53,
                                        address=self.default_ip)
                self.server.start_thread()
            except Exception as e:
                print(
                    " * ERROR: Unable to bind to port 53. DNS server could not start: {}"
                    .format(e))

    def stop(self):
        if self.server:
            print(" * Stopping DNS server on {}:53".format(self.default_ip))
            self.server.stop()
            self.server = None
Esempio n. 28
0
    except Exception as e:
        # Needs sudo for 53
        if "Permission denied" in e:
            print("Permission denied: use sudo for privileged ports such as 53")
        else:
            print("Error: {}".format(e))
        exit()

    print("{} Server listening for {} on port {}, CTRL+C to shut down".format(
        strftime("%Y-%m-%d %H:%M:%S"),
        args.host,
        args.port))
    sys.stdout.flush()

    # Server will maintain open connection until interrupted by Ctrl-C or SIGTERM
    try:
        server.start()
        while server.isAlive():
            sleep(1)
    # Shut down on keyboard interrupt
    except KeyboardInterrupt:
        server.stop()
        print("{} Server exiting...".format(strftime("%Y-%m-%d %H:%M:%S")))
    except Exception as e:
        print("Error: {}".format(e))
        server.stop()
        exit()

    print("{} Exited successfully.".format(strftime("%Y-%m-%d %H:%M:%S")))
    sys.stdout.flush()