コード例 #1
0
    def checkMessageProxyProtocol(self,
                                  receivedProxyPayload,
                                  source,
                                  destination,
                                  isTCP,
                                  values=[]):
        proxy = ProxyProtocol()
        self.assertTrue(proxy.parseHeader(receivedProxyPayload))
        self.assertEquals(proxy.version, 0x02)
        self.assertEquals(proxy.command, 0x01)
        self.assertEquals(proxy.family, 0x01)
        if not isTCP:
            self.assertEquals(proxy.protocol, 0x02)
        else:
            self.assertEquals(proxy.protocol, 0x01)
        self.assertGreater(proxy.contentLen, 0)

        self.assertTrue(proxy.parseAddressesAndPorts(receivedProxyPayload))
        self.assertEquals(proxy.source, source)
        self.assertEquals(proxy.destination, destination)
        #self.assertEquals(proxy.sourcePort, sourcePort)
        self.assertEquals(proxy.destinationPort, self._dnsDistPort)

        self.assertTrue(proxy.parseAdditionalValues(receivedProxyPayload))
        proxy.values.sort()
        values.sort()
        self.assertEquals(proxy.values, values)
コード例 #2
0
def ProxyProtocolUDPResponder(port, fromQueue, toQueue):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
    try:
        sock.bind(("127.0.0.1", port))
    except socket.error as e:
        print("Error binding in the Proxy Protocol UDP responder: %s" % str(e))
        sys.exit(1)

    while True:
        data, addr = sock.recvfrom(4096)

        proxy = ProxyProtocol()
        if len(data) < proxy.HEADER_SIZE:
            continue

        if not proxy.parseHeader(data):
            continue

        if proxy.local:
            # likely a healthcheck
            data = data[proxy.HEADER_SIZE:]
            request = dns.message.from_wire(data)
            response = dns.message.make_response(request)
            wire = response.to_wire()
            sock.settimeout(2.0)
            sock.sendto(wire, addr)
            sock.settimeout(None)

            continue

        payload = data[:(proxy.HEADER_SIZE + proxy.contentLen)]
        dnsData = data[(proxy.HEADER_SIZE + proxy.contentLen):]
        toQueue.put([payload, dnsData], True, 2.0)
        # computing the correct ID for the response
        request = dns.message.from_wire(dnsData)
        response = fromQueue.get(True, 2.0)
        response.id = request.id

        sock.settimeout(2.0)
        sock.sendto(response.to_wire(), addr)
        sock.settimeout(None)

    sock.close()
コード例 #3
0
def ProxyProtocolTCPResponder(port, fromQueue, toQueue):
    # be aware that this responder will not accept a new connection
    # until the last one has been closed. This is done on purpose to
    # to check for connection reuse, making sure that a lot of connections
    # are not opened in parallel.
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
    try:
        sock.bind(("127.0.0.1", port))
    except socket.error as e:
        print("Error binding in the TCP responder: %s" % str(e))
        sys.exit(1)

    sock.listen(100)
    while True:
        (conn, _) = sock.accept()
        conn.settimeout(5.0)
        # try to read the entire Proxy Protocol header
        proxy = ProxyProtocol()
        header = conn.recv(proxy.HEADER_SIZE)
        if not header:
            conn.close()
            continue

        if not proxy.parseHeader(header):
            conn.close()
            continue

        proxyContent = conn.recv(proxy.contentLen)
        if not proxyContent:
            conn.close()
            continue

        payload = header + proxyContent
        while True:
          try:
            data = conn.recv(2)
          except socket.timeout:
            data = None

          if not data:
            conn.close()
            break

          (datalen,) = struct.unpack("!H", data)
          data = conn.recv(datalen)

          toQueue.put([payload, data], True, 2.0)

          response = copy.deepcopy(fromQueue.get(True, 2.0))
          if not response:
            conn.close()
            break

          # computing the correct ID for the response
          request = dns.message.from_wire(data)
          response.id = request.id

          wire = response.to_wire()
          conn.send(struct.pack("!H", len(wire)))
          conn.send(wire)

        conn.close()

    sock.close()
コード例 #4
0
ファイル: dnsdisttests.py プロジェクト: rgacogne/pdns
    def handleDoHConnection(cls, config, conn, fromQueue, toQueue,
                            trailingDataResponse, multipleResponses, callback,
                            tlsContext, useProxyProtocol):
        ignoreTrailing = trailingDataResponse is True
        try:
            h2conn = h2.connection.H2Connection(config=config)
            h2conn.initiate_connection()
            conn.sendall(h2conn.data_to_send())
        except ssl.SSLEOFError as e:
            print("Unexpected EOF: %s" % (e))
            return

        dnsData = {}

        if useProxyProtocol:
            # try to read the entire Proxy Protocol header
            proxy = ProxyProtocol()
            header = conn.recv(proxy.HEADER_SIZE)
            if not header:
                print('unable to get header')
                conn.close()
                return

            if not proxy.parseHeader(header):
                print('unable to parse header')
                print(header)
                conn.close()
                return

            proxyContent = conn.recv(proxy.contentLen)
            if not proxyContent:
                print('unable to get content')
                conn.close()
                return

            payload = header + proxyContent
            toQueue.put(payload, True, cls._queueTimeout)

        # be careful, HTTP/2 headers and data might be in different recv() results
        requestHeaders = None
        while True:
            data = conn.recv(65535)
            if not data:
                break

            events = h2conn.receive_data(data)
            for event in events:
                if isinstance(event, h2.events.RequestReceived):
                    requestHeaders = event.headers
                if isinstance(event, h2.events.DataReceived):
                    h2conn.acknowledge_received_data(
                        event.flow_controlled_length, event.stream_id)
                    if not event.stream_id in dnsData:
                        dnsData[event.stream_id] = b''
                    dnsData[event.stream_id] = dnsData[event.stream_id] + (
                        event.data)
                    if event.stream_ended:
                        forceRcode = None
                        status = 200
                        try:
                            request = dns.message.from_wire(
                                dnsData[event.stream_id],
                                ignore_trailing=ignoreTrailing)
                        except dns.message.TrailingJunk as e:
                            if trailingDataResponse is False or forceRcode is True:
                                raise
                            print(
                                "DOH query with trailing data, synthesizing response"
                            )
                            request = dns.message.from_wire(
                                dnsData[event.stream_id], ignore_trailing=True)
                            forceRcode = trailingDataResponse

                        if callback:
                            status, wire = callback(request, requestHeaders,
                                                    fromQueue, toQueue)
                        else:
                            response = cls._getResponse(request,
                                                        fromQueue,
                                                        toQueue,
                                                        synthesize=forceRcode)
                            if response:
                                wire = response.to_wire(max_size=65535)

                        if not wire:
                            conn.close()
                            conn = None
                            break

                        headers = [
                            (':status', str(status)),
                            ('content-length', str(len(wire))),
                            ('content-type', 'application/dns-message'),
                        ]
                        h2conn.send_headers(stream_id=event.stream_id,
                                            headers=headers)
                        h2conn.send_data(stream_id=event.stream_id,
                                         data=wire,
                                         end_stream=True)

                data_to_send = h2conn.data_to_send()
                if data_to_send:
                    conn.sendall(data_to_send)

            if conn is None:
                break

        if conn is not None:
            conn.close()
コード例 #5
0
def ProxyProtocolTCPResponder(port, fromQueue, toQueue):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
    try:
        sock.bind(("127.0.0.1", port))
    except socket.error as e:
        print("Error binding in the TCP responder: %s" % str(e))
        sys.exit(1)

    sock.listen(100)
    while True:
        (conn, _) = sock.accept()
        conn.settimeout(5.0)
        # try to read the entire Proxy Protocol header
        proxy = ProxyProtocol()
        header = conn.recv(proxy.HEADER_SIZE)
        if not header:
            conn.close()
            continue

        if not proxy.parseHeader(header):
            conn.close()
            continue

        proxyContent = conn.recv(proxy.contentLen)
        if not proxyContent:
            conn.close()
            continue

        payload = header + proxyContent
        while True:
            try:
                data = conn.recv(2)
            except socket.timeout:
                data = None

            if not data:
                conn.close()
                break

            (datalen, ) = struct.unpack("!H", data)
            data = conn.recv(datalen)

            toQueue.put([payload, data], True, 2.0)

            response = fromQueue.get(True, 2.0)
            if not response:
                conn.close()
                break

            # computing the correct ID for the response
            request = dns.message.from_wire(data)
            response.id = request.id

            wire = response.to_wire()
            conn.send(struct.pack("!H", len(wire)))
            conn.send(wire)

        conn.close()

    sock.close()
コード例 #6
0
    def DOHResponder(cls,
                     port,
                     fromQueue,
                     toQueue,
                     trailingDataResponse=False,
                     multipleResponses=False,
                     callback=None,
                     tlsContext=None,
                     useProxyProtocol=False):
        # trailingDataResponse=True means "ignore trailing data".
        # Other values are either False (meaning "raise an exception")
        # or are interpreted as a response RCODE for queries with trailing data.
        # callback is invoked for every -even healthcheck ones- query and should return a raw response
        ignoreTrailing = trailingDataResponse is True

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
        try:
            sock.bind(("127.0.0.1", port))
        except socket.error as e:
            print("Error binding in the TCP responder: %s" % str(e))
            sys.exit(1)

        sock.listen(100)
        if tlsContext:
            sock = tlsContext.wrap_socket(sock, server_side=True)

        config = h2.config.H2Configuration(client_side=False)

        while True:
            try:
                (conn, _) = sock.accept()
            except ssl.SSLError:
                continue
            except ConnectionResetError:
                continue

            conn.settimeout(5.0)
            h2conn = h2.connection.H2Connection(config=config)
            h2conn.initiate_connection()
            conn.sendall(h2conn.data_to_send())
            dnsData = {}

            if useProxyProtocol:
                # try to read the entire Proxy Protocol header
                proxy = ProxyProtocol()
                header = conn.recv(proxy.HEADER_SIZE)
                if not header:
                    print('unable to get header')
                    conn.close()
                    continue

                if not proxy.parseHeader(header):
                    print('unable to parse header')
                    print(header)
                    conn.close()
                    continue

                proxyContent = conn.recv(proxy.contentLen)
                if not proxyContent:
                    print('unable to get content')
                    conn.close()
                    continue

                payload = header + proxyContent
                toQueue.put(payload, True, cls._queueTimeout)

            while True:
                data = conn.recv(65535)
                if not data:
                    break

                events = h2conn.receive_data(data)
                for event in events:
                    if isinstance(event, h2.events.DataReceived):
                        h2conn.acknowledge_received_data(
                            event.flow_controlled_length, event.stream_id)
                        if not event.stream_id in dnsData:
                            dnsData[event.stream_id] = b''
                        dnsData[event.stream_id] = dnsData[event.stream_id] + (
                            event.data)
                        if event.stream_ended:
                            forceRcode = None
                            status = 200
                            try:
                                request = dns.message.from_wire(
                                    dnsData[event.stream_id],
                                    ignore_trailing=ignoreTrailing)
                            except dns.message.TrailingJunk as e:
                                if trailingDataResponse is False or forceRcode is True:
                                    raise
                                print(
                                    "DOH query with trailing data, synthesizing response"
                                )
                                request = dns.message.from_wire(
                                    dnsData[event.stream_id],
                                    ignore_trailing=True)
                                forceRcode = trailingDataResponse

                            if callback:
                                status, wire = callback(request)
                            else:
                                response = cls._getResponse(
                                    request,
                                    fromQueue,
                                    toQueue,
                                    synthesize=forceRcode)
                                if response:
                                    wire = response.to_wire(max_size=65535)

                            if not wire:
                                conn.close()
                                conn = None
                                break

                            headers = [
                                (':status', str(status)),
                                ('content-length', str(len(wire))),
                                ('content-type', 'application/dns-message'),
                            ]
                            h2conn.send_headers(stream_id=event.stream_id,
                                                headers=headers)
                            h2conn.send_data(stream_id=event.stream_id,
                                             data=wire,
                                             end_stream=True)

                    data_to_send = h2conn.data_to_send()
                    if data_to_send:
                        conn.sendall(data_to_send)

                if conn is None:
                    break

            if conn is not None:
                conn.close()

        sock.close()