_dohWithH2OServerPort = pickAvailablePort()
_dohWithNGHTTP2BaseURL = ("https://%s:%d/" % (_serverName, _dohWithNGHTTP2ServerPort))
_dohWithH2OBaseURL = ("https://%s:%d/" % (_serverName, _dohWithH2OServerPort))
+ _doqServerPort = pickAvailablePort()
def testPass(self):
"""
'192.0.2.1')
response.answer.append(rrset)
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
(receivedQuery, receivedResponse) = sender(query, response)
receivedQuery.id = query.id
self.assertEqual(query, receivedQuery)
+ if method == 'sendDOQQueryWrapper':
+ # dnspython sets the ID to 0
+ receivedResponse.id = response.id
self.assertEqual(response, receivedResponse)
def testPassCached(self):
'192.0.2.1')
response.answer.append(rrset)
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
- if method != 'sendDOTQueryWrapper' and method != 'sendDOHWithH2OQueryWrapper':
+ if method != 'sendDOTQueryWrapper' and method != 'sendDOHWithH2OQueryWrapper' and method != 'sendDOQQueryWrapper':
# first time to fill the cache
# disabled for DoT since it was already filled via TCP
(receivedQuery, receivedResponse) = sender(query, response)
# second time from the cache
sender = getattr(self, method)
(_, receivedResponse) = sender(query, response=None, useQueue=False)
+ if method == 'sendDOQQueryWrapper':
+ # dnspython sets the ID to 0
+ receivedResponse.id = response.id
self.assertEqual(response, receivedResponse)
def testTimeoutThenAccept(self):
'192.0.2.1')
response.answer.append(rrset)
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
(receivedQuery, receivedResponse) = sender(query, response)
receivedQuery.id = query.id
self.assertEqual(query, receivedQuery)
+ if method == 'sendDOQQueryWrapper':
+ # dnspython sets the ID to 0
+ receivedResponse.id = response.id
self.assertEqual(response, receivedResponse)
def testAcceptThenTimeout(self):
'192.0.2.1')
response.answer.append(rrset)
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
(receivedQuery, receivedResponse) = sender(query, response)
receivedQuery.id = query.id
self.assertEqual(query, receivedQuery)
+ if method == 'sendDOQQueryWrapper':
+ # dnspython sets the ID to 0
+ receivedResponse.id = response.id
self.assertEqual(response, receivedResponse)
def testAcceptThenRefuse(self):
expectedResponse.flags |= dns.flags.RA
expectedResponse.set_rcode(dns.rcode.REFUSED)
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
(receivedQuery, receivedResponse) = sender(query, response)
receivedQuery.id = query.id
self.assertEqual(query, receivedQuery)
+ if method == 'sendDOQQueryWrapper':
+ # dnspython sets the ID to 0
+ receivedResponse.id = expectedResponse.id
self.assertEqual(expectedResponse, receivedResponse)
def testAcceptThenCustom(self):
'192.0.2.1')
response.answer.append(rrset)
- # easier to get the same custom response to everyone, sorry!
- expectedQuery = dns.message.make_query('custom.async.tests.powerdns.com.', 'A', 'IN')
+ expectedQuery = dns.message.make_query(name, 'A', 'IN')
expectedQuery.id = query.id
expectedResponse = dns.message.make_response(expectedQuery)
expectedResponse.flags |= dns.flags.RA
expectedResponse.set_rcode(dns.rcode.FORMERR)
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
(receivedQuery, receivedResponse) = sender(query, response)
receivedQuery.id = query.id
self.assertEqual(query, receivedQuery)
+ if method == 'sendDOQQueryWrapper':
+ # dnspython sets the ID to 0
+ receivedResponse.id = expectedResponse.id
self.assertEqual(expectedResponse, receivedResponse)
def testAcceptThenDrop(self):
'192.0.2.1')
response.answer.append(rrset)
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
- (receivedQuery, receivedResponse) = sender(query, response)
+ try:
+ (receivedQuery, receivedResponse) = sender(query, response)
+ except dns.exception.Timeout:
+ if not self._fromResponderQueue.empty():
+ receivedQuery = self._fromResponderQueue.get(True, 1.0)
+ receivedResponse = None
receivedQuery.id = query.id
self.assertEqual(query, receivedQuery)
self.assertEqual(receivedResponse, None)
expectedResponse.flags |= dns.flags.RA
expectedResponse.set_rcode(dns.rcode.REFUSED)
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
(_, receivedResponse) = sender(query, response=None, useQueue=False)
self.assertTrue(receivedResponse)
+ if method == 'sendDOQQueryWrapper':
+ # dnspython sets the ID to 0
+ receivedResponse.id = expectedResponse.id
self.assertEqual(expectedResponse, receivedResponse)
def testDrop(self):
name = 'drop.async.tests.powerdns.com.'
query = dns.message.make_query(name, 'A', 'IN')
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
- (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ try:
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ except dns.exception.Timeout:
+ receivedResponse = None
self.assertEqual(receivedResponse, None)
def testCustom(self):
expectedResponse.flags |= dns.flags.RA
expectedResponse.set_rcode(dns.rcode.FORMERR)
- for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper"):
+ for method in ("sendUDPQuery", "sendTCPQuery", "sendDOTQueryWrapper", "sendDOHWithNGHTTP2QueryWrapper", "sendDOHWithH2OQueryWrapper", "sendDOQQueryWrapper"):
sender = getattr(self, method)
(_, receivedResponse) = sender(query, response=None, useQueue=False)
self.assertTrue(receivedResponse)
+ if method == 'sendDOQQueryWrapper':
+ # dnspython sets the ID to 0
+ receivedResponse.id = expectedResponse.id
self.assertEqual(expectedResponse, receivedResponse)
def testTruncation(self):
addTLSLocal("127.0.0.1:%d", "%s", "%s", { provider="openssl" })
addDOHLocal("127.0.0.1:%d", "%s", "%s", {"/"}, {library="h2o"})
addDOHLocal("127.0.0.1:%d", "%s", "%s", {"/"}, {library="nghttp2"})
+ addDOQLocal("127.0.0.1:%d", "%s", "%s")
local ffi = require("ffi")
local C = ffi.C
pc = newPacketCache(100)
getPool('cache'):setCache(pc)
+ local asyncObjectsMap = {}
+
function gotAsyncResponse(endpointID, message, from)
print('Got async response '..message)
return
end
local queryID = tonumber(parts[1])
+ local qname = asyncObjectsMap[queryID]
if parts[2] == 'accept' then
print('accepting')
C.dnsdist_ffi_resume_from_async(asyncID, queryID, filteringTagName, #filteringTagName, filteringTagValue, #filteringTagValue, true)
end
if parts[2] == 'custom' then
print('sending a custom response')
- local raw = '\\000\\000\\128\\129\\000\\001\\000\\000\\000\\000\\000\\001\\006custom\\005async\\005tests\\008powerdns\\003com\\000\\000\\001\\000\\001\\000\\000\\041\\002\\000\\000\\000\\128\\000\\000\\000'
+ local raw = nil
+ if qname == string.char(6)..'custom'..string.char(5)..'async'..string.char(5)..'tests'..string.char(8)..'powerdns'..string.char(3)..'com' then
+ raw = '\\000\\000\\128\\129\\000\\001\\000\\000\\000\\000\\000\\001\\006custom\\005async\\005tests\\008powerdns\\003com\\000\\000\\001\\000\\001\\000\\000\\041\\002\\000\\000\\000\\128\\000\\000\\000'
+ elseif qname == string.char(18)..'accept-then-custom'..string.char(5)..'async'..string.char(5)..'tests'..string.char(8)..'powerdns'..string.char(3)..'com' then
+ raw = '\\000\\000\\128\\129\\000\\001\\000\\000\\000\\000\\000\\001\\018accept-then-custom\\005async\\005tests\\008powerdns\\003com\\000\\000\\001\\000\\001\\000\\000\\041\\002\\000\\000\\000\\128\\000\\000\\000'
+ elseif qname == string.char(18)..'accept-then-custom'..string.char(8)..'tcp-only'..string.char(5)..'async'..string.char(5)..'tests'..string.char(8)..'powerdns'..string.char(3)..'com' then
+ raw = '\\000\\000\\128\\129\\000\\001\\000\\000\\000\\000\\000\\001\\018accept-then-custom\\008tcp-only\\005async\\005tests\\008powerdns\\003com\\000\\000\\001\\000\\001\\000\\000\\041\\002\\000\\000\\000\\128\\000\\000\\000'
+ end
+
C.dnsdist_ffi_set_answer_from_async(asyncID, queryID, raw, #raw)
return
end
listener:addUnixListeningEndpoint('%s', 0, gotAsyncResponse)
listener:start()
+ function getQNameRaw(dq)
+ local ret_ptr = ffi.new("char *[1]")
+ local ret_ptr_param = ffi.cast("const char **", ret_ptr)
+ local ret_size = ffi.new("size_t[1]")
+ local ret_size_param = ffi.cast("size_t*", ret_size)
+ C.dnsdist_ffi_dnsquestion_get_qname_raw(dq, ret_ptr_param, ret_size_param)
+ return ffi.string(ret_ptr[0])
+ end
+
function passQueryToAsyncFilter(dq)
print('in passQueryToAsyncFilter')
local timeout = 500 -- 500 ms
-- we need to take a copy, as we can no longer touch that data after calling set_async
local buffer = ffi.string(queryPtr, querySize)
- print(C.dnsdist_ffi_dnsquestion_set_async(dq, asyncID, C.dnsdist_ffi_dnsquestion_get_id(dq), timeout))
+ asyncObjectsMap[C.dnsdist_ffi_dnsquestion_get_id(dq)] = getQNameRaw(dq)
+
+ C.dnsdist_ffi_dnsquestion_set_async(dq, asyncID, C.dnsdist_ffi_dnsquestion_get_id(dq), timeout)
asyncResponderEndpoint:send(buffer)
return DNSAction.Allow
-- we need to take a copy, as we can no longer touch that data after calling set_async
local buffer = ffi.string(responsePtr, responseSize)
- print(C.dnsdist_ffi_dnsresponse_set_async(dr, asyncID, C.dnsdist_ffi_dnsquestion_get_id(dr), timeout))
+ asyncObjectsMap[C.dnsdist_ffi_dnsquestion_get_id(dr)] = getQNameRaw(dr)
+
+ C.dnsdist_ffi_dnsresponse_set_async(dr, asyncID, C.dnsdist_ffi_dnsquestion_get_id(dr), timeout)
asyncResponderEndpoint:send(buffer)
return DNSResponseAction.Allow
"""
_asyncResponderSocketPath = asyncResponderSocketPath
_dnsdistSocketPath = dnsdistSocketPath
- _config_params = ['_testServerPort', '_testServerPort', '_tlsServerPort', '_serverCert', '_serverKey', '_dohWithH2OServerPort', '_serverCert', '_serverKey', '_dohWithNGHTTP2ServerPort', '_serverCert', '_serverKey', '_asyncResponderSocketPath', '_dnsdistSocketPath']
+ _config_params = ['_testServerPort', '_testServerPort', '_tlsServerPort', '_serverCert', '_serverKey', '_dohWithH2OServerPort', '_serverCert', '_serverKey', '_dohWithNGHTTP2ServerPort', '_serverCert', '_serverKey', '_doqServerPort', '_serverCert', '_serverKey', '_asyncResponderSocketPath', '_dnsdistSocketPath']
_verboseMode = True
@unittest.skipIf('SKIP_DOH_TESTS' in os.environ, 'DNS over HTTPS tests are disabled')
addTLSLocal("127.0.0.1:%d", "%s", "%s", { provider="openssl" })
addDOHLocal("127.0.0.1:%d", "%s", "%s", {"/"}, {library="h2o"})
addDOHLocal("127.0.0.1:%d", "%s", "%s", {"/"}, {library="nghttp2"})
+ addDOQLocal("127.0.0.1:%d", "%s", "%s")
local filteringTagName = 'filtering'
local filteringTagValue = 'pass'
end
if parts[2] == 'custom' then
print('sending a custom response')
- local raw = '\\000\\000\\128\\129\\000\\001\\000\\000\\000\\000\\000\\001\\006custom\\005async\\005tests\\008powerdns\\003com\\000\\000\\001\\000\\001\\000\\000\\041\\002\\000\\000\\000\\128\\000\\000\\000'
local dq = asyncObject:getDQ()
+ local raw
+ if tostring(dq.qname) == 'custom.async.tests.powerdns.com.' then
+ raw = '\\000\\000\\128\\129\\000\\001\\000\\000\\000\\000\\000\\001\\006custom\\005async\\005tests\\008powerdns\\003com\\000\\000\\001\\000\\001\\000\\000\\041\\002\\000\\000\\000\\128\\000\\000\\000'
+ elseif tostring(dq.qname) == 'accept-then-custom.async.tests.powerdns.com.' then
+ raw = '\\000\\000\\128\\129\\000\\001\\000\\000\\000\\000\\000\\001\\018accept-then-custom\\005async\\005tests\\008powerdns\\003com\\000\\000\\001\\000\\001\\000\\000\\041\\002\\000\\000\\000\\128\\000\\000\\000'
+ elseif tostring(dq.qname) == 'accept-then-custom.tcp-only.async.tests.powerdns.com.' then
+ raw = '\\000\\000\\128\\129\\000\\001\\000\\000\\000\\000\\000\\001\\018accept-then-custom\\008tcp-only\\005async\\005tests\\008powerdns\\003com\\000\\000\\001\\000\\001\\000\\000\\041\\002\\000\\000\\000\\128\\000\\000\\000'
+ end
dq:setContent(raw)
asyncObject:resume()
return
"""
_asyncResponderSocketPath = asyncResponderSocketPath
_dnsdistSocketPath = dnsdistSocketPath
- _config_params = ['_testServerPort', '_testServerPort', '_tlsServerPort', '_serverCert', '_serverKey', '_dohWithH2OServerPort', '_serverCert', '_serverKey', '_dohWithNGHTTP2ServerPort', '_serverCert', '_serverKey', '_asyncResponderSocketPath', '_dnsdistSocketPath']
+ _config_params = ['_testServerPort', '_testServerPort', '_tlsServerPort', '_serverCert', '_serverKey', '_dohWithH2OServerPort', '_serverCert', '_serverKey', '_dohWithNGHTTP2ServerPort', '_serverCert', '_serverKey', '_doqServerPort', '_serverCert', '_serverKey', '_asyncResponderSocketPath', '_dnsdistSocketPath']
_verboseMode = True
class TestDOQ(DNSDistTest):
_serverKey = 'server.key'
_serverCert = 'server.chain'
- _serverName = '127.0.0.1'
+ _serverName = 'tls.tests.dnsdist.org'
_caCert = 'ca.pem'
_doqServerPort = pickAvailablePort()
_config_template = """
dns.rdatatype.A,
'127.0.0.1')
response.answer.append(rrset)
- (receivedQuery, receivedResponse) = self.sendDOQQuery(self._doqServerPort, self._serverName, query, response=response, caFile=self._caCert)
+ (receivedQuery, receivedResponse) = self.sendDOQQuery(self._doqServerPort, query, response=response, caFile=self._caCert, serverName=self._serverName)
self.assertTrue(receivedQuery)
self.assertTrue(receivedResponse)
receivedQuery.id = expectedQuery.id
'127.0.0.1')
response.answer.append(rrset)
- connection = self.getDOQConnection(self._doqServerPort, self._serverName, self._caCert)
+ connection = self.getDOQConnection(self._doqServerPort, self._caCert)
- (receivedQuery, receivedResponse) = self.sendDOQQuery(self._doqServerPort, self._serverName, query, response=response, connection=connection)
+ (receivedQuery, receivedResponse) = self.sendDOQQuery(self._doqServerPort, query, response=response, caFile=self._caCert, serverName=self._serverName, connection=connection)
self.assertTrue(receivedQuery)
self.assertTrue(receivedResponse)
receivedQuery.id = expectedQuery.id
self.assertEqual(expectedQuery, receivedQuery)
- (receivedQuery, receivedResponse) = self.sendDOQQuery(self._doqServerPort, self._serverName, query, response=response, connection=connection)
+ (receivedQuery, receivedResponse) = self.sendDOQQuery(self._doqServerPort, query, response=response, caFile=self._caCert, serverName=self._serverName, connection=connection)
self.assertTrue(receivedQuery)
self.assertTrue(receivedResponse)
receivedQuery.id = expectedQuery.id
query = dns.message.make_query(name, 'A', 'IN')
dropped = False
try:
- (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, self._serverName, query, response=None, caFile=self._caCert, useQueue=False)
+ (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, query, response=None, caFile=self._caCert, useQueue=False, serverName=self._serverName)
# dns.quic doesn't seem to report correctly the quic error so the connection timeout
except dns.exception.Timeout :
dropped = True
expectedResponse = dns.message.make_response(query)
expectedResponse.set_rcode(dns.rcode.REFUSED)
- (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, self._serverName, query, response=None, caFile=self._caCert, useQueue=False)
+ (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, query, response=None, caFile=self._caCert, useQueue=False, serverName=self._serverName)
self.assertEqual(receivedResponse, expectedResponse)
def testSpoof(self):
'1.2.3.4')
expectedResponse.answer.append(rrset)
- (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, self._serverName, query, response=None, caFile=self._caCert, useQueue=False)
+ (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, query, response=None, caFile=self._caCert, useQueue=False, serverName=self._serverName)
self.assertEqual(receivedResponse, expectedResponse)
def testDOQNoBackend(self):
query = dns.message.make_query(name, 'A', 'IN', use_edns=False)
dropped = False
try:
- (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, self._serverName, query, response=None, caFile=self._caCert, useQueue=False)
+ (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, query, response=None, caFile=self._caCert, useQueue=False, serverName=self._serverName)
except dns.exception.Timeout :
dropped = True
self.assertTrue(dropped)
class TestDOQWithCache(DNSDistTest):
_serverKey = 'server.key'
_serverCert = 'server.chain'
- _serverName = '127.0.0.1'
+ _serverName = 'tls.tests.dnsdist.org'
_caCert = 'ca.pem'
_doqServerPort = 8853
_config_template = """
response.answer.append(rrset)
# first query to fill the cache
- (receivedQuery, receivedResponse) = self.sendDOQQuery(self._doqServerPort, self._serverName, query, response=response, caFile=self._caCert)
+ (receivedQuery, receivedResponse) = self.sendDOQQuery(self._doqServerPort, query, response=response, caFile=self._caCert, serverName=self._serverName)
self.assertTrue(receivedQuery)
self.assertTrue(receivedResponse)
receivedQuery.id = query.id
self.assertEqual(receivedResponse, response)
for _ in range(numberOfQueries):
- (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, self._serverName, query, response=None, caFile=self._caCert, useQueue=False)
+ (_, receivedResponse) = self.sendDOQQuery(self._doqServerPort, query, response=None, caFile=self._caCert, useQueue=False, serverName=self._serverName)
self.assertEqual(receivedResponse, response)
total = 0