Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rec: correct appliedPolicyTrigger value for IP matches #10842

Merged
merged 5 commits into from Oct 18, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 14 additions & 9 deletions pdns/filterpo.cc
Expand Up @@ -53,27 +53,30 @@ bool DNSFilterEngine::Zone::findExactNSPolicy(const DNSName& qname, DNSFilterEng
return findExactNamedPolicy(d_propolName, qname, pol);
}

bool DNSFilterEngine::Zone::findNSIPPolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const
bool DNSFilterEngine::Zone::findNSIPPolicy(const ComboAddress& addr, Netmask& key, DNSFilterEngine::Policy& pol) const
{
if (const auto fnd = d_propolNSAddr.lookup(addr)) {
key = fnd->first;
pol = fnd->second;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to update the d_trigger field of the returned policy here, instead of exposing the internal key?

Suggested change
key = fnd->first;
pol = fnd->second;
const auto& key = fnd->first;
pol = fnd->second;
pol.d_trigger = Zone::maskToRPZ(key);

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that is a good idea.

return true;
}
return false;
}

bool DNSFilterEngine::Zone::findResponsePolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const
bool DNSFilterEngine::Zone::findResponsePolicy(const ComboAddress& addr, Netmask& key, DNSFilterEngine::Policy& pol) const
{
if (const auto fnd = d_postpolAddr.lookup(addr)) {
key = fnd->first;
pol = fnd->second;
return true;
}
return false;
}

bool DNSFilterEngine::Zone::findClientPolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const
bool DNSFilterEngine::Zone::findClientPolicy(const ComboAddress& addr, Netmask& key, DNSFilterEngine::Policy& pol) const
{
if (const auto fnd = d_qpolAddr.lookup(addr)) {
key = fnd->first;
pol = fnd->second;
return true;
}
Expand Down Expand Up @@ -212,10 +215,10 @@ bool DNSFilterEngine::getProcessingPolicy(const ComboAddress& address, const std
continue;
}

if(z->findNSIPPolicy(address, pol)) {
Netmask key;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover?

if(z->findNSIPPolicy(address, key, pol)) {
// cerr<<"Had a hit on the nameserver ("<<address.toString()<<") used to process the query"<<endl;
// XXX should use ns RPZ
pol.d_trigger = Zone::maskToRPZ(address);
pol.d_trigger = Zone::maskToRPZ(key);
pol.d_trigger.appendRawLabel(rpzNSIPName);
pol.d_hit = address.toString();
return true;
Expand All @@ -236,7 +239,8 @@ bool DNSFilterEngine::getClientPolicy(const ComboAddress& ca, const std::unorder
continue;
}

if (z->findClientPolicy(ca, pol)) {
Netmask key;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover as well?

if (z->findClientPolicy(ca, key, pol)) {
// cerr<<"Had a hit on the IP address ("<<ca.toString()<<") of the client"<<endl;
rgacogne marked this conversation as resolved.
Show resolved Hide resolved
return true;
}
Expand Down Expand Up @@ -355,8 +359,9 @@ bool DNSFilterEngine::getPostPolicy(const DNSRecord& record, const std::unordere
return false;
}

if (z->findResponsePolicy(ca, pol)) {
pol.d_trigger = Zone::maskToRPZ(ca);
Netmask key;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover?

if (z->findResponsePolicy(ca, key, pol)) {
pol.d_trigger = Zone::maskToRPZ(key);
pol.d_trigger.appendRawLabel(rpzIPName);
pol.d_hit = ca.toString();
return true;
Expand Down
6 changes: 3 additions & 3 deletions pdns/filterpo.hh
Expand Up @@ -263,9 +263,9 @@ public:

bool findExactQNamePolicy(const DNSName& qname, DNSFilterEngine::Policy& pol) const;
bool findExactNSPolicy(const DNSName& qname, DNSFilterEngine::Policy& pol) const;
bool findNSIPPolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const;
bool findResponsePolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const;
bool findClientPolicy(const ComboAddress& addr, DNSFilterEngine::Policy& pol) const;
bool findNSIPPolicy(const ComboAddress& addr, Netmask& key, DNSFilterEngine::Policy& pol) const;
bool findResponsePolicy(const ComboAddress& addr, Netmask& key, DNSFilterEngine::Policy& pol) const;
bool findClientPolicy(const ComboAddress& addr, Netmask& key, DNSFilterEngine::Policy& pol) const;

bool hasClientPolicies() const
{
Expand Down
21 changes: 15 additions & 6 deletions pdns/recursordist/test-filterpo_cc.cc
Expand Up @@ -107,17 +107,20 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_basic)
const auto matchingPolicy = dfe.getProcessingPolicy(nsIP, std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::NSIP);
BOOST_CHECK(matchingPolicy.d_kind == DNSFilterEngine::PolicyKind::Drop);
Netmask key;
DNSFilterEngine::Policy zonePolicy;
BOOST_CHECK(zone->findNSIPPolicy(nsIP, zonePolicy));
BOOST_CHECK(zone->findNSIPPolicy(nsIP, key, zonePolicy));
BOOST_CHECK(key == nsIP);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like all our tests are using an exact match (/32), perhaps we should test with at least one different mask? I know we do in the regression tests, though.

Copy link
Member Author

@omoerbeek omoerbeek Oct 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extended the tests and found another case where the trigger value was not set properly: findExactNSPolicy.

Now I'm wondering if d_hit should be set in the find methods as well. Plus looking at the assignments to d_trigger in getQueryPolicy. They look redundant now.

BOOST_CHECK(zonePolicy == matchingPolicy);
}

{
/* allowed NS IP */
const auto matchingPolicy = dfe.getProcessingPolicy(ComboAddress("192.0.2.142"), std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::None);
Netmask key;
DNSFilterEngine::Policy zonePolicy;
BOOST_CHECK(zone->findNSIPPolicy(ComboAddress("192.0.2.142"), zonePolicy) == false);
BOOST_CHECK(zone->findNSIPPolicy(ComboAddress("192.0.2.142"), key, zonePolicy) == false);
}

{
Expand Down Expand Up @@ -158,17 +161,20 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_basic)
const auto matchingPolicy = dfe.getClientPolicy(clientIP, std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::ClientIP);
BOOST_CHECK(matchingPolicy.d_kind == DNSFilterEngine::PolicyKind::Drop);
Netmask key;
DNSFilterEngine::Policy zonePolicy;
BOOST_CHECK(zone->findClientPolicy(clientIP, zonePolicy));
BOOST_CHECK(zone->findClientPolicy(clientIP, key, zonePolicy));
BOOST_CHECK(key == clientIP);
BOOST_CHECK(zonePolicy == matchingPolicy);
}

{
/* not blocked */
const auto matchingPolicy = dfe.getClientPolicy(ComboAddress("192.0.2.142"), std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::None);
Netmask key;
DNSFilterEngine::Policy zonePolicy;
BOOST_CHECK(zone->findClientPolicy(ComboAddress("192.0.2.142"), zonePolicy) == false);
BOOST_CHECK(zone->findClientPolicy(ComboAddress("192.0.2.142"), key, zonePolicy) == false);
BOOST_CHECK(zone->findExactQNamePolicy(DNSName("totally.legit."), zonePolicy) == false);
}

Expand All @@ -180,8 +186,10 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_basic)
const auto matchingPolicy = dfe.getPostPolicy({dr}, std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::ResponseIP);
BOOST_CHECK(matchingPolicy.d_kind == DNSFilterEngine::PolicyKind::Drop);
Netmask key;
DNSFilterEngine::Policy zonePolicy;
BOOST_CHECK(zone->findResponsePolicy(responseIP, zonePolicy));
BOOST_CHECK(zone->findResponsePolicy(responseIP, key, zonePolicy));
BOOST_CHECK(key == responseIP);
BOOST_CHECK(zonePolicy == matchingPolicy);
}

Expand All @@ -192,8 +200,9 @@ BOOST_AUTO_TEST_CASE(test_filter_policies_basic)
dr.d_content = DNSRecordContent::mastermake(QType::A, QClass::IN, "192.0.2.142");
const auto matchingPolicy = dfe.getPostPolicy({dr}, std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::None);
Netmask key;
DNSFilterEngine::Policy zonePolicy;
BOOST_CHECK(zone->findResponsePolicy(ComboAddress("192.0.2.142"), zonePolicy) == false);
BOOST_CHECK(zone->findResponsePolicy(ComboAddress("192.0.2.142"), key, zonePolicy) == false);
}

BOOST_CHECK_EQUAL(zone->size(), 7U);
Expand Down
21 changes: 21 additions & 0 deletions regression-tests.recursor-dnssec/test_Protobuf.py
Expand Up @@ -939,13 +939,15 @@ def generateRecursorConfig(cls, confdir):
authzone.write("""$ORIGIN example.
@ 3600 IN SOA {soa}
sub.test 3600 IN A 192.0.2.42
ip 3600 IN A 33.22.11.99
""".format(soa=cls._SOA))

rpzFilePath = os.path.join(confdir, 'zone.rpz')
with open(rpzFilePath, 'w') as rpzZone:
rpzZone.write("""$ORIGIN zone.rpz.
@ 3600 IN SOA {soa}
*.test.example.zone.rpz. 60 IN CNAME rpz-passthru.
24.0.11.22.33.rpz-ip 60 IN A 1.2.3.4
""".format(soa=cls._SOA))

super(ProtobufRPZTest, cls).generateRecursorConfig(confdir)
Expand Down Expand Up @@ -973,6 +975,25 @@ def testA(self):
self.assertEqual(socket.inet_ntop(socket.AF_INET, rr.rdata), '192.0.2.42')
self.checkNoRemainingMessage()

def testB(self):
name = 'ip.example.'
expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '1.2.3.4')
query = dns.message.make_query(name, 'A', want_dnssec=True)
query.flags |= dns.flags.CD
res = self.sendUDPQuery(query)
self.assertRRsetInAnswer(res, expected)

# check the protobuf messages corresponding to the UDP query and answer
msg = self.getFirstProtobufMessage()
self.checkProtobufQuery(msg, dnsmessage_pb2.PBDNSMessage.UDP, query, dns.rdataclass.IN, dns.rdatatype.A, name)

# then the response
msg = self.getFirstProtobufMessage()
self.checkProtobufResponse(msg, dnsmessage_pb2.PBDNSMessage.UDP, res)
self.checkProtobufPolicy(msg, dnsmessage_pb2.PBDNSMessage.PolicyType.RESPONSEIP, 'zone.rpz.', '24.0.11.22.33.rpz-ip.', '33.22.11.99', dnsmessage_pb2.PBDNSMessage.PolicyKind.Custom)
self.assertEqual(len(msg.response.rrs), 1)
self.checkNoRemainingMessage()

class ProtobufRPZTagsTest(TestRecursorProtobuf):
"""
This test makes sure that we correctly export the RPZ tags in our protobuf messages
Expand Down