+class OutgoingProtobufWithECSMappingTest(TestRecursorProtobuf):
+ """
+ This test makes sure that we correctly export outgoing queries over protobuf.
+ It must be improved and setup env so we can check for incoming responses, but makes sure for now
+ that the recursor at least connects to the protobuf server.
+ """
+
+ _confdir = 'OutgoingProtobuffWithECSMapping'
+ _config_template = """
+ # Switch off QName Minimization, it generates much more protobuf messages
+ # (or make the test much more smart!)
+ qname-minimization=no
+ edns-subnet-allow-list=example
+ allow-from=1.2.3.4/32
+ # this is to not let . queries interfere
+ max-cache-ttl=600
+ loglevel=9
+"""
+ _lua_config_file = """
+ outgoingProtobufServer({"127.0.0.1:%d", "127.0.0.1:%d"})
+ addProxyMapping("127.0.0.0/8", "1.2.3.4", { "host1.secure.example." })
+ """ % (protobufServersParameters[0].port, protobufServersParameters[1].port)
+
+ def testA(self):
+ # There is a race in priming (having the . DNSKEY in cache in particular) and this code.
+ # So make sure we have the . DNSKEY in cache
+ query = dns.message.make_query('.', 'A', want_dnssec=True)
+ query.flags |= dns.flags.RD
+ res = self.sendUDPQuery(query)
+ time.sleep(1)
+ self.emptyProtoBufQueue()
+
+ name = 'host1.secure.example.'
+ expected = list()
+
+ for qname, qtype, proto, responseSize, ecs in [
+ ('host1.secure.example.', dns.rdatatype.A, dnsmessage_pb2.PBDNSMessage.UDP, 248, "1.2.3.0"),
+ ('host1.secure.example.', dns.rdatatype.A, dnsmessage_pb2.PBDNSMessage.UDP, 221, "1.2.3.0"),
+ ('example.', dns.rdatatype.DNSKEY, dnsmessage_pb2.PBDNSMessage.UDP, 219, "1.2.3.0"),
+ ('host1.secure.example.', dns.rdatatype.A, dnsmessage_pb2.PBDNSMessage.UDP, 175, "1.2.3.0"),
+ ('secure.example.', dns.rdatatype.DNSKEY, dnsmessage_pb2.PBDNSMessage.UDP, 233, "1.2.3.0"),
+ ]:
+ if not qname:
+ expected.append((None, None, None, None, None, None, None))
+ continue
+ ecso = clientsubnetoption.ClientSubnetOption('9.10.11.12', 24)
+ query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True, options=[ecso], payload=512)
+ resp = dns.message.make_response(query)
+ expected.append((
+ qname, qtype, query, resp, proto, responseSize, ecs
+ ))
+
+ query = dns.message.make_query(name, 'A', want_dnssec=True)
+ query.flags |= dns.flags.RD
+ res = self.sendUDPQuery(query)
+
+ for qname, qtype, qry, ans, proto, responseSize, ecs in expected:
+ if not qname:
+ self.getFirstProtobufMessage()
+ self.getFirstProtobufMessage()
+ continue
+
+ msg = self.getFirstProtobufMessage()
+ self.checkProtobufOutgoingQuery(msg, proto, qry, dns.rdataclass.IN, qtype, qname, "127.0.0.1", None, ecs)
+ # Check the answer
+ msg = self.getFirstProtobufMessage()
+ self.checkProtobufIncomingResponse(msg, proto, ans, length=responseSize)
+
+ self.checkNoRemainingMessage()
+
+ # this query should use the unmapped ECS
+ name = 'mx1.secure.example.'
+ expected = list()
+
+ for qname, qtype, proto, responseSize, ecs in [
+ ('mx1.secure.example.', dns.rdatatype.A, dnsmessage_pb2.PBDNSMessage.UDP, 173, "127.0.0.1"),
+ ]:
+ if not qname:
+ expected.append((None, None, None, None, None, None, None))
+ continue
+ ecso = clientsubnetoption.ClientSubnetOption('127.0.0.1', 32)
+ query = dns.message.make_query(qname, qtype, use_edns=True, want_dnssec=True, options=[ecso], payload=512)
+ resp = dns.message.make_response(query)
+ expected.append((
+ qname, qtype, query, resp, proto, responseSize, ecs
+ ))
+
+ query = dns.message.make_query(name, 'A', want_dnssec=True)
+ query.flags |= dns.flags.RD
+ res = self.sendUDPQuery(query)
+
+ for qname, qtype, qry, ans, proto, responseSize, ecs in expected:
+ if not qname:
+ self.getFirstProtobufMessage()
+ self.getFirstProtobufMessage()
+ continue
+
+ msg = self.getFirstProtobufMessage()
+ self.checkProtobufOutgoingQuery(msg, proto, qry, dns.rdataclass.IN, qtype, qname, "127.0.0.1", None, ecs)
+ # Check the answer
+ msg = self.getFirstProtobufMessage()
+ self.checkProtobufIncomingResponse(msg, proto, ans, length=responseSize)
+
+ self.checkNoRemainingMessage()
+