4 import clientsubnetoption
6 from dnsdisttests
import DNSDistTest
, Queue
, pickAvailablePort
7 from proxyprotocolutils
import ProxyProtocolUDPResponder
, ProxyProtocolTCPResponder
9 class TestTeeAction(DNSDistTest
):
11 _consoleKey
= DNSDistTest
.generateConsoleKey()
12 _consoleKeyB64
= base64
.b64encode(_consoleKey
).decode('ascii')
13 _teeServerPort
= pickAvailablePort()
14 _teeProxyServerPort
= pickAvailablePort()
16 _fromTeeQueue
= Queue()
17 _toTeeProxyQueue
= Queue()
18 _fromTeeProxyQueue
= Queue()
19 _config_template
= """
21 controlSocket("127.0.0.1:%s")
22 newServer{address="127.0.0.1:%d"}
23 addAction(QTypeRule(DNSQType.A), TeeAction("127.0.0.1:%d", true))
24 addAction(QTypeRule(DNSQType.AAAA), TeeAction("127.0.0.1:%d", false))
25 addAction(QTypeRule(DNSQType.ANY), TeeAction("127.0.0.1:%d", false, '127.0.0.1', true))
27 _config_params
= ['_consoleKeyB64', '_consolePort', '_testServerPort', '_teeServerPort', '_teeServerPort', '_teeProxyServerPort']
29 def startResponders(cls
):
30 print("Launching responders..")
32 cls
._UDPResponder
= threading
.Thread(name
='UDP Responder', target
=cls
.UDPResponder
, args
=[cls
._testServerPort
, cls
._toResponderQueue
, cls
._fromResponderQueue
])
33 cls
._UDPResponder
.daemon
= True
34 cls
._UDPResponder
.start()
36 cls
._TCPResponder
= threading
.Thread(name
='TCP Responder', target
=cls
.TCPResponder
, args
=[cls
._testServerPort
, cls
._toResponderQueue
, cls
._fromResponderQueue
, False, True])
37 cls
._TCPResponder
.daemon
= True
38 cls
._TCPResponder
.start()
40 cls
._TeeResponder
= threading
.Thread(name
='Tee Responder', target
=cls
.UDPResponder
, args
=[cls
._teeServerPort
, cls
._toTeeQueue
, cls
._fromTeeQueue
])
41 cls
._TeeResponder
.daemon
= True
42 cls
._TeeResponder
.start()
44 cls
._TeeProxyResponder
= threading
.Thread(name
='Proxy Protocol Tee Responder', target
=ProxyProtocolUDPResponder
, args
=[cls
._teeProxyServerPort
, cls
._toTeeProxyQueue
, cls
._fromTeeProxyQueue
])
45 cls
._TeeProxyResponder
.daemon
= True
46 cls
._TeeProxyResponder
.start()
48 def testTeeWithECS(self
):
52 name
= 'ecs.tee.tests.powerdns.com.'
53 query
= dns
.message
.make_query(name
, 'A', 'IN')
54 response
= dns
.message
.make_response(query
)
56 rrset
= dns
.rrset
.from_text(name
,
61 response
.answer
.append(rrset
)
64 for _
in range(numberOfQueries
):
65 # push the response to the Tee server
66 self
._toTeeQueue
.put(response
, True, 2.0)
68 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
69 self
.assertTrue(receivedQuery
)
70 self
.assertTrue(receivedResponse
)
71 receivedQuery
.id = query
.id
72 self
.assertEqual(query
, receivedQuery
)
73 self
.assertEqual(response
, receivedResponse
)
75 # retrieve the query from the Tee server
76 teedQuery
= self
._fromTeeQueue
.get(True, 2.0)
77 ecso
= clientsubnetoption
.ClientSubnetOption('127.0.0.1', 24)
78 expectedQuery
= dns
.message
.make_query(name
, 'A', 'IN', use_edns
=True, options
=[ecso
], payload
=512)
79 expectedQuery
.id = query
.id
80 self
.checkQueryEDNSWithECS(expectedQuery
, teedQuery
)
82 # check the TeeAction stats
83 stats
= self
.sendConsoleCommand("getAction(0):printStats()")
84 self
.assertEqual(stats
, """noerrors\t%d
94 """ % (numberOfQueries
, numberOfQueries
, numberOfQueries
))
96 def testTeeWithoutECS(self
):
100 name
= 'noecs.tee.tests.powerdns.com.'
101 query
= dns
.message
.make_query(name
, 'AAAA', 'IN')
102 response
= dns
.message
.make_response(query
)
104 rrset
= dns
.rrset
.from_text(name
,
109 response
.answer
.append(rrset
)
112 for _
in range(numberOfQueries
):
113 # push the response to the Tee server
114 self
._toTeeQueue
.put(response
, True, 2.0)
116 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
117 self
.assertTrue(receivedQuery
)
118 self
.assertTrue(receivedResponse
)
119 receivedQuery
.id = query
.id
120 self
.assertEqual(query
, receivedQuery
)
121 self
.assertEqual(response
, receivedResponse
)
123 # retrieve the query from the Tee server
124 teedQuery
= self
._fromTeeQueue
.get(True, 2.0)
125 ecso
= clientsubnetoption
.ClientSubnetOption('127.0.0.1', 24)
126 expectedQuery
= dns
.message
.make_query(name
, 'AAAA', 'IN', use_edns
=True, options
=[ecso
], payload
=512)
127 expectedQuery
.id = query
.id
128 self
.checkMessageNoEDNS(expectedQuery
, teedQuery
)
130 # check the TeeAction stats
131 stats
= self
.sendConsoleCommand("getAction(0):printStats()")
132 self
.assertEqual(stats
, """noerrors\t%d
142 """ % (numberOfQueries
, numberOfQueries
, numberOfQueries
))
144 def testTeeWithProxy(self
):
148 name
= 'proxy.tee.tests.powerdns.com.'
149 query
= dns
.message
.make_query(name
, 'ANY', 'IN')
150 response
= dns
.message
.make_response(query
)
152 rrset
= dns
.rrset
.from_text(name
,
157 response
.answer
.append(rrset
)
160 for _
in range(numberOfQueries
):
161 # push the response to the Tee Proxy server
162 self
._toTeeProxyQueue
.put(response
, True, 2.0)
164 (receivedQuery
, receivedResponse
) = self
.sendUDPQuery(query
, response
)
165 self
.assertTrue(receivedQuery
)
166 self
.assertTrue(receivedResponse
)
167 receivedQuery
.id = query
.id
168 self
.assertEqual(query
, receivedQuery
)
169 self
.assertEqual(response
, receivedResponse
)
171 # retrieve the query from the Tee Proxy server
172 [payload
, teedQuery
] = self
._fromTeeProxyQueue
.get(True, 2.0)
173 self
.checkMessageNoEDNS(query
, dns
.message
.from_wire(teedQuery
))
174 self
.checkMessageProxyProtocol(payload
, '127.0.0.1', '127.0.0.1', False)
176 # check the TeeAction stats
177 stats
= self
.sendConsoleCommand("getAction(0):printStats()")
178 self
.assertEqual(stats
, """noerrors\t%d
188 """ % (numberOfQueries
, numberOfQueries
, numberOfQueries
))