[DNSfirewalls] rpz firewall + whitelisting

Paul Vixie paul at redbarn.org
Wed Aug 28 14:31:49 UTC 2019


On Wednesday, 28 August 2019 07:00:35 UTC Lee wrote:
> On 8/27/19, Paul Vixie <paul at redbarn.org> wrote:
> > it's tricky stuff. i hope you have at least read the draft (-04) though.
> 
> I looked at draft-vixie-dnsop-dns-rpz-00, but I doubt I understood
> even half of it.
> 
> Could you point out where in either draft it documents the
> non-intuitive behavior one gets by configuring an rpz zone with
> *.2o7.net CNAME .
> bcbsks.com.102.112.2o7.net CNAME rpz-passthru.

since the wildcard applies to nonexistent names, the existing names with no 
content (empty non terminals) are implicitly passed through above. these are:

2o7.net
112.2o7.net
102.112.2o7.net
com.102.112.2o7.net

this means they exist but have no records. a DNS query for those names would 
produce RCODE=0 ANCOUNT=0 (name exists but has no records.) RPZ will only move 
to the next policy zone in the subscription list if the name does not exist -- 
that is, if the response to a query about it would be RCODE=3 (NXDOMAIN).

this in turn means that an empty name (which in DNS can only be nonterminal) 
has the same meaning as CNAME rpz-passthru., because it stops the search for 
this names in subsequent policy zones (if any) but is a trigger w/o an action. 
it is merely coincidental that your CNAME rpz-passthru. action produces the 
same result (stops the search of policy zones with no RPZ action) as empty 
nodes would produce. the wildcard is only important to your story because the 
action it describes is not being triggered for the interstitial (empty 
nonterminal) names.

so if your above-quoted construct is present in RPZ A, which appears in the 
configured RPZ subscription list before RPZ B, and RPZ B has a rule for 
112.2o7.net (one of the interstitial names), that rule in RPZ B will never be 
tested, and will therefore never trigger an action, even though the empty 
nonterminals from RPZ A do not, upon analyizing its content, have any obvious 
rules for this name.

we could institute a change whereby a match on an empty nonterminal name has 
the same effect (search for a wildcard; consider moving on to the next policy 
zone) as a nonexistent name would have. indeed, treating empty nonterminal the 
same as NXDOMAIN is what some older authority name servers worked, but, it is 
not the way we interpreted this pattern when deciding how DNSSEC would work, 
and i am loathe to deviate in this subtle way from normal DNS search 
semantics... especially because i can imagine an RPZ B (referencing the above 
walkthrough) which has a bad (broken; destructive) rule that is not being hit 
today because of some (implicit) empty nonterminal in RPZ A. (don't want.)

> >> > this expansion
> >> > should be done by the rpz generator or by some preprocessor you'd write
> >> > in python or perl or whatever.
> >> 
> >> Yeah, I totally get that.
> >> But me having to write a preprocessor + not really understanding rpz
> >> zones changes running a dns firewall from an interesting project to
> >> holding a loaded shotgun aimed at my foot :(

it will be a time thief, no question. however, i think this learning will have 
more benefit than cost. (noting, i almost always see learning that way.)

> > would it help if i crafted a perl script that did this preprocessing for
> > you?
> 
> Thanks for the offer, but I'll learn a lot more if I do it myself.
> And doing it myself will force me to go step-by-step instead of trying
> to jump directly to what I think the desired end state is.

i think the BIND9 native, and the FastRPZ, implementations of the RPZ spec 
could easily be changed to log warnings about empty non-terminals. and that to 
avoid these warnings (or rather, to avoid this condition), an RPZ generator 
would iteratively generate a "trigger action" rule for an owner name and 
label-strip.

owner = translate(trigger)
while !empty(owner) {
  generate(owner, action)
  label_strip(owner, left)
}

where translate() is how you're mapping from your desired trigger to the RPZ 
encoding as an RR owner name, and generate() is one or two RR's, one for the 
generated owner itself, and possibly a second one as a wildcard subdomain of 
that generated owner.

if any of this seems counterfactual or confusing, let's keep talking.

with this zone content (in vix.su, but's incidental to the story):

> deep.space.nine CNAME   this.is.deep.space.nine.
> *.nine          CNAME   this.is.wildcard.nine.

the result of a lookup is directly instructive as to the applicability of 
wildcards:

> $ dig @ns.lah1.vix.su space.nine.vix.su. cname | egrep '(status|ANSWER):'
> ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 61298
> ;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

again i want to stress that it's the presence of empty nonterminals, and their 
outcome being the same as CNAME rpz-passthru, that creates the problem. the 
wildcard is only important to your story because it's not being seen.

-- 
Paul




More information about the DNSfirewalls mailing list