Exemplo n.º 1
0
    def _recv_handler(self):
        recv_buffer = []
        while True:
            try:
                data_from_server = self._relay_conn.sock.recv(1024)
            except (socket.timeout, OSError) as e:
                Log.p(f'RECV HANDLER: {e}')
                break

            else:
                self._reset_fail_detection()
                if (not data_from_server):
                    Log.p('RECV HANDLER: PIPELINE CLOSED BY REMOTE SERVER!')
                    break

                recv_buffer.append(data_from_server)
                while recv_buffer:
                    current_data = b''.join(recv_buffer)[2:]
                    data_len = short_unpackf(recv_buffer[0])[0]
                    if (len(current_data) == data_len):
                        recv_buffer = []

                    elif (len(current_data) > data_len):
                        recv_buffer = [current_data[data_len:]]

                    else:
                        break

                    if not self.is_keepalive(current_data):
                        self.DNSRelay.responder.add(current_data[:data_len])

        self._relay_conn.sock.close()
Exemplo n.º 2
0
    def __fail_detection(self):
        if (fast_time() - self._last_sent >= FIVE_SEC
                and self._send_cnt >= HEARTBEAT_FAIL_LIMIT):

            self.mark_server_down()

        Log.p(
            f'NOTICE: fail detection | now={fast_time()}, last_sent={self._last_sent}, send_count={self._send_cnt}'
        )
Exemplo n.º 3
0
    def _register_new_socket(self, client_query=None):
        for secure_server in self.DNSRelay.dns_servers:
            if (not secure_server[self._protocol]): continue

            if self._tls_connect(secure_server['ip']): return True

            self.mark_server_down()
        else:
            Log.p('NO SECURE SERVERS AVAILABLE!')
            self.DNSRelay.tls_up = False
Exemplo n.º 4
0
    def mark_server_down(self):
        if (self.socket_available):
            self._relay_conn.sock.close()
            Log.p(
                f'NOTICE: {self._relay_conn.remote_ip} failed to respond to 3 messages. marking as down.'
            )

            for server in self.DNSRelay.dns_servers:
                if (server['ip'] == self._relay_conn.remote_ip):
                    server[self._protocol] = False
Exemplo n.º 5
0
    def __send_query(self, client_query):
        for attempt in range(2):
            try:
                self._relay_conn.sock.send(client_query.send_data)
                Log.console(f'SENT SECURE[{attempt}]: {client_query.request}')
            except OSError:
                if not self._register_new_socket(): break

                threading.Thread(target=self._recv_handler).start()
            else:
                self._increment_fail_detection()
                break
Exemplo n.º 6
0
    def _register(self, listener):
        '''will register interface with listener. requires subclass property for listener_sock returning valid socket object.
        once registration is complete the thread will exit.'''

        Log.console(f'REGISTERING: {self._l_ip}.')

        l_sock = self.listener_sock

        listener._registered_socks[l_sock.fileno()] = l_sock
        listener._epoll.register(l_sock.fileno(), select.EPOLLIN)

        Log.console(f'COMPLETE: {self._l_ip}.')
Exemplo n.º 7
0
    def _tls_connect(self, secure_server):
        Log.p(f'Opening Secure socket to {secure_server}: 853')

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        dns_sock = self._tls_context.wrap_socket(sock,
                                                 server_hostname=secure_server)
        try:
            dns_sock.connect((secure_server, PROTO.DNS_TLS))
        except OSError:
            return None
        else:
            return True
        finally:
            self._relay_conn = RELAY_CONN(secure_server, dns_sock)
Exemplo n.º 8
0
    def tls(self):
        if (not self.is_enabled): return TEN_SEC

        for secure_server in self.DNSRelay.dns_servers:
            if (secure_server[self._protocol]):
                continue  # not checking if server/proto is known up

            if self._tls_reachable(secure_server['ip']):
                secure_server[self._protocol] = True
                self.DNSRelay.tls_up = True

                Log.p('NOTICE: TLS server {} has recovered.'.format(
                    secure_server['ip']))

        return THIRTY_SEC
Exemplo n.º 9
0
    def __init__(self, DNSRelay):
        '''general constructor. can only be reached through subclass.

        May be expanded.

        '''
        if (self.__run is False):
            raise TypeError(
                f'{self.__class__.__name__} must be started through run class method.'
            )

        Log.console(f'INITIALIZING: {self.__class__.__name__}')

        self.DNSRelay = DNSRelay
        self._relay_conn = RELAY_CONN(None, socket.socket())

        self._send_cnt = 0
        self._last_sent = 0

        threading.Thread(target=self.__fail_detection).start()
        threading.Thread(target=self.relay).start()
Exemplo n.º 10
0
    def run(cls, listening_addresses):
        Log.console('INITIALIZING: Primary service.')

        # initializing dns cache/ sending in reference to needed methods for top domains
        cls._records_cache = DNSCache(
            packet=ClientRequest.generate_local_query,
            request_handler=cls._handle_query)

        # defining main epoll/ socket loop prior for register methods reference.
        service_loop = cls(None)

        # starting a registration thread for all available interfaces
        # upon registration the threads will exit
        for ip in listening_addresses:
            self = cls(ip)
            threading.Thread(target=self._register,
                             args=(service_loop, )).start()

        TLSRelay.run(cls)

        # engaging epoll listener. local traffic processing starts here.
        service_loop._listener()
Exemplo n.º 11
0
    parser.add_argument('-v',
                        '--verbose',
                        help='prints output to screen',
                        action='store_true')

    args = parser.parse_args(argv[1:])

    l_addrs = args.ip_addrs
    servers = args.servers
    VERBOSE = args.verbose

    if (servers):
        SERVERS = tuple(servers.split(','))

    if (l_addrs):
        LISTENING_ADDRESSES = tuple(l_addrs.split(','))

    try:
        argument_validation()
    except ValueError as E:
        sys.stdout.err(E)
        os._exit(1)

    if (os.getuid() or DISABLED):
        sys.stdout.err('DNS over TLS Relay must be ran as root.')
        os._exit(1)

    display_banner()

    Log.setup(verbose=VERBOSE)
    DNSRelay.run(LISTENING_ADDRESSES)
Exemplo n.º 12
0
    def add(self, request, data_to_cache):
        '''add query to cache after calculating expiration time.'''
        self[request] = data_to_cache

        Log.p(f'CACHE ADD | NAME: {request} TTL: {data_to_cache.ttl}')