class NegativeAndSOAAction: public DNSAction
{
public:
- NegativeAndSOAAction(bool nxd, const DNSName& zone, uint32_t ttl, const DNSName& mname, const DNSName& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum): d_zone(zone), d_mname(mname), d_rname(rname), d_ttl(ttl), d_serial(serial), d_refresh(refresh), d_retry(retry), d_expire(expire), d_minimum(minimum), d_nxd(nxd)
+ NegativeAndSOAAction(bool nxd, const DNSName& zone, uint32_t ttl, const DNSName& mname, const DNSName& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum, bool soaInAuthoritySection): d_zone(zone), d_mname(mname), d_rname(rname), d_ttl(ttl), d_serial(serial), d_refresh(refresh), d_retry(retry), d_expire(expire), d_minimum(minimum), d_nxd(nxd), d_soaInAuthoritySection(soaInAuthoritySection)
{
}
DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override
{
- if (!setNegativeAndAdditionalSOA(*dq, d_nxd, d_zone, d_ttl, d_mname, d_rname, d_serial, d_refresh, d_retry, d_expire, d_minimum)) {
+ if (!setNegativeAndAdditionalSOA(*dq, d_nxd, d_zone, d_ttl, d_mname, d_rname, d_serial, d_refresh, d_retry, d_expire, d_minimum, d_soaInAuthoritySection)) {
return Action::None;
}
uint32_t d_expire;
uint32_t d_minimum;
bool d_nxd;
+ bool d_soaInAuthoritySection;
};
class SetProxyProtocolValuesAction : public DNSAction
#endif /* defined(HAVE_LMDB) || defined(HAVE_CDB) */
luaCtx.writeFunction("NegativeAndSOAAction", [](bool nxd, const std::string& zone, uint32_t ttl, const std::string& mname, const std::string& rname, uint32_t serial, uint32_t refresh, uint32_t retry, uint32_t expire, uint32_t minimum, boost::optional<responseParams_t> vars) {
- auto ret = std::shared_ptr<DNSAction>(new NegativeAndSOAAction(nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum));
+ bool soaInAuthoritySection = false;
+ if (vars) {
+ if (vars->count("soaInAuthoritySection")) {
+ soaInAuthoritySection = boost::get<bool>((*vars)["soaInAuthoritySection"]);
+ }
+ }
+
+ auto ret = std::shared_ptr<DNSAction>(new NegativeAndSOAAction(nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum, soaInAuthoritySection));
auto action = std::dynamic_pointer_cast<NegativeAndSOAAction>(ret);
parseResponseConfig(vars, action->d_responseConfig);
return ret;
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, dnsdist::Protocol::DoUDP, &queryTime);
- BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5));
+ BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, false));
BOOST_CHECK(packet.size() > query.size());
MOADNSParser mdp(true, reinterpret_cast<const char*>(packet.data()), packet.size());
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, dnsdist::Protocol::DoUDP, &queryTime);
- BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5));
+ BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, false));
BOOST_CHECK(packet.size() > queryWithEDNS.size());
MOADNSParser mdp(true, reinterpret_cast<const char*>(packet.data()), packet.size());
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, dnsdist::Protocol::DoUDP, &queryTime);
- BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5));
+ BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, false));
BOOST_CHECK(packet.size() > query.size());
MOADNSParser mdp(true, reinterpret_cast<const char*>(packet.data()), packet.size());
DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, dnsdist::Protocol::DoUDP, &queryTime);
- BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5));
+ BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, false));
BOOST_CHECK(packet.size() > queryWithEDNS.size());
MOADNSParser mdp(true, reinterpret_cast<const char*>(packet.data()), packet.size());
BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_type, static_cast<uint16_t>(QType::OPT));
BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_name, g_rootdnsname);
}
+
+ /* SOA in the authority section*/
+
+ /* test NXD */
+ {
+ /* no incoming EDNS */
+ auto packet = query;
+
+ unsigned int consumed = 0;
+ uint16_t qtype;
+ DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, dnsdist::Protocol::DoUDP, &queryTime);
+
+ BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, true));
+ BOOST_CHECK(packet.size() > query.size());
+ MOADNSParser mdp(true, reinterpret_cast<const char*>(packet.data()), packet.size());
+
+ BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "www.powerdns.com.");
+ BOOST_CHECK_EQUAL(mdp.d_header.rcode, RCode::NXDomain);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0U);
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 1U);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast<uint16_t>(QType::SOA));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, DNSName("zone."));
+ }
+ {
+ /* now with incoming EDNS */
+ auto packet = queryWithEDNS;
+
+ unsigned int consumed = 0;
+ uint16_t qtype;
+ DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, dnsdist::Protocol::DoUDP, &queryTime);
+
+ BOOST_CHECK(setNegativeAndAdditionalSOA(dq, true, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, true));
+ BOOST_CHECK(packet.size() > queryWithEDNS.size());
+ MOADNSParser mdp(true, reinterpret_cast<const char*>(packet.data()), packet.size());
+
+ BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "www.powerdns.com.");
+ BOOST_CHECK_EQUAL(mdp.d_header.rcode, RCode::NXDomain);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 1U);
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 2U);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast<uint16_t>(QType::SOA));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, DNSName("zone."));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_type, static_cast<uint16_t>(QType::OPT));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_name, g_rootdnsname);
+ }
+
+ /* test No Data */
+ {
+ /* no incoming EDNS */
+ auto packet = query;
+
+ unsigned int consumed = 0;
+ uint16_t qtype;
+ DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, dnsdist::Protocol::DoUDP, &queryTime);
+
+ BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, true));
+ BOOST_CHECK(packet.size() > query.size());
+ MOADNSParser mdp(true, reinterpret_cast<const char*>(packet.data()), packet.size());
+
+ BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "www.powerdns.com.");
+ BOOST_CHECK_EQUAL(mdp.d_header.rcode, RCode::NoError);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0U);
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 1U);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast<uint16_t>(QType::SOA));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, DNSName("zone."));
+ }
+ {
+ /* now with incoming EDNS */
+ auto packet = queryWithEDNS;
+
+ unsigned int consumed = 0;
+ uint16_t qtype;
+ DNSName qname(reinterpret_cast<const char*>(packet.data()), packet.size(), sizeof(dnsheader), false, &qtype, nullptr, &consumed);
+ DNSQuestion dq(&qname, qtype, QClass::IN, &remote, &remote, packet, dnsdist::Protocol::DoUDP, &queryTime);
+
+ BOOST_CHECK(setNegativeAndAdditionalSOA(dq, false, DNSName("zone."), 42, DNSName("mname."), DNSName("rname."), 1, 2, 3, 4 , 5, true));
+ BOOST_CHECK(packet.size() > queryWithEDNS.size());
+ MOADNSParser mdp(true, reinterpret_cast<const char*>(packet.data()), packet.size());
+
+ BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "www.powerdns.com.");
+ BOOST_CHECK_EQUAL(mdp.d_header.rcode, RCode::NoError);
+ BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0U);
+ BOOST_CHECK_EQUAL(mdp.d_header.nscount, 1U);
+ BOOST_CHECK_EQUAL(mdp.d_header.arcount, 1U);
+ BOOST_REQUIRE_EQUAL(mdp.d_answers.size(), 2U);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast<uint16_t>(QType::SOA));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN);
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, DNSName("zone."));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_type, static_cast<uint16_t>(QType::OPT));
+ BOOST_CHECK_EQUAL(mdp.d_answers.at(1).first.d_name, g_rootdnsname);
+ }
}
BOOST_AUTO_TEST_CASE(getEDNSOptionsWithoutEDNS) {
(_, receivedResponse) = sender(query, response=None, useQueue=False)
self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
+
+class TestAdvancedNegativeAndSOAAuthSection(DNSDistTest):
+
+ _selfGeneratedPayloadSize = 1232
+ _config_template = """
+ addAction("nxd.negativeandsoa.advanced.tests.powerdns.com.", NegativeAndSOAAction(true, "auth.", 42, "mname", "rname", 5, 4, 3, 2, 1, { soaInAuthoritySection=true }))
+ addAction("nodata.negativeandsoa.advanced.tests.powerdns.com.", NegativeAndSOAAction(false, "another-auth.", 42, "mname", "rname", 1, 2, 3, 4, 5, { soaInAuthoritySection=true }))
+ setPayloadSizeOnSelfGeneratedAnswers(%d)
+ newServer{address="127.0.0.1:%s"}
+ """
+ _config_params = ['_selfGeneratedPayloadSize', '_testServerPort']
+
+
+ def testAdvancedNegativeAndSOANXD(self):
+ """
+ Advanced: NegativeAndSOAAction NXD
+ """
+ name = 'nxd.negativeandsoa.advanced.tests.powerdns.com.'
+ # no EDNS
+ query = dns.message.make_query(name, 'A', 'IN', use_edns=False)
+ query.flags &= ~dns.flags.RD
+ expectedResponse = dns.message.make_response(query)
+ expectedResponse.set_rcode(dns.rcode.NXDOMAIN)
+ soa = dns.rrset.from_text("auth.",
+ 42,
+ dns.rdataclass.IN,
+ dns.rdatatype.SOA,
+ 'mname. rname. 5 4 3 2 1')
+ expectedResponse.authority.append(soa)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ self.checkMessageNoEDNS(expectedResponse, receivedResponse)
+
+ # withEDNS
+ query = dns.message.make_query(name, 'A', 'IN', use_edns=True)
+ query.flags &= ~dns.flags.RD
+ expectedResponse = dns.message.make_response(query, our_payload=self._selfGeneratedPayloadSize)
+ expectedResponse.set_rcode(dns.rcode.NXDOMAIN)
+ soa = dns.rrset.from_text("auth.",
+ 42,
+ dns.rdataclass.IN,
+ dns.rdatatype.SOA,
+ 'mname. rname. 5 4 3 2 1')
+ expectedResponse.authority.append(soa)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
+
+ def testAdvancedNegativeAndSOANoData(self):
+ """
+ Advanced: NegativeAndSOAAction NoData
+ """
+ name = 'nodata.negativeandsoa.advanced.tests.powerdns.com.'
+ # no EDNS
+ query = dns.message.make_query(name, 'A', 'IN', use_edns=False)
+ query.flags &= ~dns.flags.RD
+ expectedResponse = dns.message.make_response(query)
+ expectedResponse.set_rcode(dns.rcode.NOERROR)
+ soa = dns.rrset.from_text("another-auth.",
+ 42,
+ dns.rdataclass.IN,
+ dns.rdatatype.SOA,
+ 'mname. rname. 1 2 3 4 5')
+ expectedResponse.authority.append(soa)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ self.checkMessageNoEDNS(expectedResponse, receivedResponse)
+
+ # with EDNS
+ query = dns.message.make_query(name, 'A', 'IN', use_edns=True)
+ query.flags &= ~dns.flags.RD
+ expectedResponse = dns.message.make_response(query, our_payload=self._selfGeneratedPayloadSize)
+ expectedResponse.set_rcode(dns.rcode.NOERROR)
+ soa = dns.rrset.from_text("another-auth.",
+ 42,
+ dns.rdataclass.IN,
+ dns.rdatatype.SOA,
+ 'mname. rname. 1 2 3 4 5')
+ expectedResponse.authority.append(soa)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ self.checkMessageEDNSWithoutOptions(expectedResponse, receivedResponse)
+
+
class TestAdvancedLuaRule(DNSDistTest):
_config_template = """