]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/proxyprotocolutils.py
Merge pull request #13906 from rgacogne/ddist-fix-ipv6-console
[thirdparty/pdns.git] / regression-tests.dnsdist / proxyprotocolutils.py
CommitLineData
8d22a19d
RG
1#!/usr/bin/env python
2import copy
3import dns
4import socket
5import struct
6import sys
7
8from proxyprotocol import ProxyProtocol
9
10def ProxyProtocolUDPResponder(port, fromQueue, toQueue):
11 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
12 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
13 try:
14 sock.bind(("127.0.0.1", port))
15 except socket.error as e:
16 print("Error binding in the Proxy Protocol UDP responder: %s" % str(e))
17 sys.exit(1)
18
19 while True:
20 data, addr = sock.recvfrom(4096)
21
22 proxy = ProxyProtocol()
23 if len(data) < proxy.HEADER_SIZE:
24 continue
25
26 if not proxy.parseHeader(data):
27 continue
28
29 if proxy.local:
30 # likely a healthcheck
31 data = data[proxy.HEADER_SIZE:]
32 request = dns.message.from_wire(data)
33 response = dns.message.make_response(request)
34 wire = response.to_wire()
35 sock.settimeout(2.0)
36 sock.sendto(wire, addr)
37 sock.settimeout(None)
38
39 continue
40
41 payload = data[:(proxy.HEADER_SIZE + proxy.contentLen)]
42 dnsData = data[(proxy.HEADER_SIZE + proxy.contentLen):]
43 toQueue.put([payload, dnsData], True, 2.0)
44 # computing the correct ID for the response
45 request = dns.message.from_wire(dnsData)
46 response = fromQueue.get(True, 2.0)
47 response.id = request.id
48
49 sock.settimeout(2.0)
50 sock.sendto(response.to_wire(), addr)
51 sock.settimeout(None)
52
53 sock.close()
54
55def ProxyProtocolTCPResponder(port, fromQueue, toQueue):
56 # be aware that this responder will not accept a new connection
57 # until the last one has been closed. This is done on purpose to
58 # to check for connection reuse, making sure that a lot of connections
59 # are not opened in parallel.
60 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
61 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
62 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
63 try:
64 sock.bind(("127.0.0.1", port))
65 except socket.error as e:
66 print("Error binding in the TCP responder: %s" % str(e))
67 sys.exit(1)
68
69 sock.listen(100)
70 while True:
71 (conn, _) = sock.accept()
72 conn.settimeout(5.0)
73 # try to read the entire Proxy Protocol header
74 proxy = ProxyProtocol()
75 header = conn.recv(proxy.HEADER_SIZE)
76 if not header:
77 conn.close()
78 continue
79
80 if not proxy.parseHeader(header):
81 conn.close()
82 continue
83
84 proxyContent = conn.recv(proxy.contentLen)
85 if not proxyContent:
86 conn.close()
87 continue
88
89 payload = header + proxyContent
90 while True:
91 try:
92 data = conn.recv(2)
93 except socket.timeout:
94 data = None
95
96 if not data:
97 conn.close()
98 break
99
100 (datalen,) = struct.unpack("!H", data)
101 data = conn.recv(datalen)
102
103 toQueue.put([payload, data], True, 2.0)
104
105 response = copy.deepcopy(fromQueue.get(True, 2.0))
106 if not response:
107 conn.close()
108 break
109
110 # computing the correct ID for the response
111 request = dns.message.from_wire(data)
112 response.id = request.id
113
114 wire = response.to_wire()
115 conn.send(struct.pack("!H", len(wire)))
116 conn.send(wire)
117
118 conn.close()
119
120 sock.close()