Known Inconsistency in DNSRPZ’s NSDNAME and NSIP Rules
Response Policy Zones define several possible triggers for each rule, and among these, two are known to produce inconsistent results. This is not a bug, but relates to inconsistencies in the Domain Name System (DNS) delegation model. Since a complete understanding of the triggers and actions in a DNS firewall rule is necessary for the construction of a rule set that will correctly implement a security policy, this article will explain these known inconsistencies in detail.
In DNS authority data, an NS RRset at the bottom of a DNS zone gives rise to a sub-zone. That sub-zone’s data is separate from the current (or “parent”) zone, and it can have different authority name servers than the current zone. In this way, the root zone gives rise to COM, NET, ORG, and so on, each of which have their own name servers and their own way of managing their authority data. Similarly ORG has delegations to ISC.ORG and to millions of other “dot-ORG” zones who can each have its own set of authority name servers. In the parlance of the protocol, these NS RRsets at the bottom of a zone are called “delegation points.”
At the apex of every zone there is also an NS RRset. Ideally this so-called “apex NS RRset” is identical to the “delegation point NS RRset” but this ideal is rarely obtained. In the real DNS, it’s almost always easier for a zone administrator to update one of these NS RRsets than the other, so that one will be correct, and the other will be out-of-date in some way. This inconsistency is so common that it’s been necessarily rendered harmless – domains that are inconsistent in this way will be less reliable and perhaps slower, so long as there is some overlap between each of the NS RRsets and the actual truth. “Truth” in this case refers to the actual set of name servers who are authoritative for the zone.
In DNS recursive name servers, an incoming query that cannot be answered from the local cache will be sent to the closest known delegation point for the query name. For example, if you’re looking up XYZZY.ISC.ORG and you know who the name servers for ISC.ORG are, then you will send the query to those servers directly, but if you have never heard of ISC.ORG before you would have to first send it to the name servers for ORG or perhaps even to the root zone that is the parent of ORG. Of course, when you ask the wrong name server, it will not have an answer, so it will send a “referral” consisting only of the “delegation point NS RRset.” Once you receive this referral you will “iterate” by sending the same query again, but this time to name servers for a “more specific” part of the query name. Eventually this iteration terminates, either by getting an answer or a “name error” (NXDOMAIN) from the query name’s authority server, or by getting some kind of error such as a delegation being upward rather than downward.
When an authority server for the query name sends an answer, it has the option of including a copy of the zone’s apex NS RRset. If this is done, then the recursive name server will cache this NS RRset, replacing the delegation point NS RRset that it had received during the iteration process. In the parlance of the DNS, the delegation point NS RRset is “glue,” meaning non-authoritative data, more of a hint than a real truth. On the other hand the apex NS RRset is authority data, coming as it does from the zone itself, and it is considered more credible than the “glue.” For this reason, it’s a little bit more important that the apex NS RRset be correct than that the delegation point NS RRset be correct, since the former will quickly replace the latter, and will be used more often and for a longer total period of time.
Importantly, the authority name server need not include its apex NS RRset in any answers, and recursive name servers will not ordinarily query directly for this RRset. Therefore it is possible for the apex NS RRset to be completely wrong without any operational ill-effects, since the wrong data need not be exposed. Of course, if a query comes in for this NS RRset, most recursive name servers will forward the query to the zone’s authority servers, since it’s bad form to return “glue” data when you’ve been asked a specific question. In these corner cases, bad apex NS RRset data can cause a zone to become unreachable, unpredictably, according to what other queries the recursive name server has processed.
There is another kind of “glue," which are name servers whose names are below delegation points. If ORG delegates ISC.ORG to NS-EXT.ISC.ORG then it is necessary that the ORG server know an address for NS-EXT.ISC.ORG and that this address be returned as part of the delegation response. However, the name-to-address binding for this name server is only authoritative inside the ISC.ORG zone, and so the A or AAAA RRset given out with the delegation is non-authoritative “glue” which would be replaced by an authoritative RRset if one is seen. As with apex NS RRsets, the real A or AAAA RRset will not automatically be queried for by the recursive name server, but will be queried for if an incoming query asks for this RRset.
RPZ has two rules that are intended to allow policy zone authors to target entire groups of domains based on those domains all being served by the same DNS servers. The NSDNAME and NSIP rules are matched against the name and IP (respectively) of the nameservers for the zone the answer is in and all of its parent zones. In its default configuration BIND will actively fetch any missing NS RRsets and address records.
If, in the process of attempting to resolve the names of all of these delegated server names, BIND receives a SERVFAIL response for any of the queries then it will abort the policy rule evaluation and return SERVFAIL for the query. This is technically neither a match nor a non-match of the rule.
Every "." in a FQDN represents a potential delegation point. When BIND goes searching for parent zone NS RRsets (and, in the case of NSIP, their accompanying address records) it has to check every possible delegation point. This can become a problem for some specialized pseudo-domains, such as some domain name and network reputation systems, that have many "." characters in the names. It is further complicated if that system also has non-compliant DNS servers that silently drop queries for NS and SOA records. This forces BIND to wait for those queries to time out before it can finish evaluating the policy rule, even if this takes longer than a reasonable client will typically wait for an answer (delays of over 60 seconds have been observed).
While both of these cases do involve configurations and/or servers that are technically "broken," they may still "work" outside of RPZ NSIP and NSDNAME rules because of redundancy and iteration optimizations.
There are two RPZ options, nsip-wait-recurse (implemented in 9.11 and later branches) and nsdname-wait-recurse (not yet implemented), that alter BIND's behavior by allowing it to use only those records that already exist in the cache when evaluating NSIP and NSDNAME rules, respectively.
Therefore NSDNAME and NSIP rules are unreliable. The rules may be matched against either the apex NS RRset or the "glue" NS RRset, each with their associated addresses (that also might or might not be "glue"). It’s in your interests to discover both the delegation name server names and addresses, and the apex name server names and authoritative address records, for any evil that you wish to stop using the NS and NSIP triggers in RPZ. Even then, there may be collateral damage to completely unrelated domains, that otherwise "work," just by having NSIP and NSDNAME rules.