Jan 30

Partly out of curiosity on the usage of NSEC3 (see RFC 5155) and partly for experimenting with BIND 10‘s Python DNS library, I’ve written a small Python script that uses the BIND 10 library and checks whether and how NSEC3 is used in top level domains (TLDs). Of my particular interest was whether there was a non Opt-Out TLD, because that was one major advertised feature of NSEC3 especially for very large zones (many of TLDs are very large) with many insecure delegations (which should also be the case today for many TLDs).

Overall the results were not so different from what I had expected, but I still found some interesting (to me) facts:

  • Some TLDs (still? or intentionally?) use NSEC, including “cutting edge” TLDs in this area like .se.
  • Some, seemingly large, TLDs are (also seemingly) not Opt-Out zones.
  • There’s one TLD that uses a quite large number of hash iterations (150).
  • The experiment identified a bug in BIND 10:-)

The Script

The Python script I used for this experiment is publicly available here for reference.

Obviously it depends on BIND 10. If you happen to want to try this script, you’ll first need to build (and install – it would require a lot of setup efforts if used in source) it.

Furthermore, the script doesn’t work with released versions of BIND 10 as of this writing, due to the bug mentioned above. You’ll need to get and apply an (unofficial) patch to fix the bug.

The script should be otherwise self-contained, but unless you install the BIND10 Python libraries under some known place for the Python interpreter, you’ll need to specify the path to the libraries in PYTHONPATH:

% PYTHONPATH=/usr/local/bind10/lib/python3.1/site-packages \
  python3.1 nsec3prober.py

(where it’s assumed that BIND 10 was installed using –prefix=/usr/local/bind10 at configure time)

This script works as follows:

  • Fetch root zone’s data from an F-root server instance (F is chosen because it replies to AXFR queries)
  • Remember TLDs under the root zone and the known IPv6 and IPv4 addresses of the name servers of the TLDs (not all addresses may be available in the root zone, but in practice it should be quite effective)
  • For each TLD, send a few queries to the known addresses of the TLD in order to identify whether the zone is signed, and if it is, with NSEC or NSEC3
  • For TLDs that are identified as signed with NSEC3, send further queries to (try to) identify whether they are Opt-Out zones, i.e., whether there’s an Opt-Out NSEC3 record

For the third step, it sends an NSEC query (with DO bit on) for the TLDs origin (for simplicity it assumes at least one name server of each TLD knows EDNS0). If the zone is unsigned, the result should be a “no data” response and should not contain NSEC or NSEC3 in the authority section; if it’s signed with NSEC, it should return a positive answer (with answer section having the NSEC); if it’s signed with NSEC3 (in which case we assume it doesn’t have NSEC), the result should be a “no data” response and the authority section should have an NSEC3 RR.

The fourth step is tricky, because, in theory, we need to examine all NSEC3 RRs of the zone to determine whether it’s Opt-Out or not with confidence. But unless we know the domains of the zone it’s supposed to be extremely difficult (to the extent of the strength of the hash). So this script employs some heuristic approach: First, it assumes that if a zone is Opt-Out, the owner name of any insecure delegation is covered by an Opt-Out NSEC3 (i.e., it doesn’t have a matching NSEC3). Second, it tries to find an insecure delegation under a TLD by adding some well-known subdomains that exist under many TLDs: Specifically, it tries “google” (it also tries “google.com” and “google.co”) and “aaa”. As far as I know, no google domains are signed, and it exists under quite a lot of TLDs, so this heuristics should actually be pretty effective. Once it finds an insecure delegation (which can be detected by the non-existence of a DS RR with NS RR that indicates a delegation), it checks the flags field of the corresponding NSEC3 to see if the Opt-Out bit is set; if it is, the zone is (by definition) Opt-Out. If not, the zone is not Opt-Out under our assumption.

This script employs one other heuristics: There are TLDs that are signed with NSEC but some of their child zones are signed with NSEC3. Such NSEC3 child zones are often for commercial names that are postfixed with “com” or “co”. The pair of br and com.br is one example. So, if this script identifies a TLD as signed with NSEC, it also tries to its “com” and “co” subdomains could be a separate zone (but served by the same server) signed with NSEC3. If that’s the case, it performs further checks for the found NSEC3 child zones.

The Result

The script first dumps the number of TLDs for each type (signed or unsigned, NSEC vs NSEC, optout or not). This is a copy of my latest experimental result (omitting some noisy notes or uninteresting details and folding longer lines for readability):

found 312 TLDs, 429 IPv6 addresses, 1185 IPv4 addresses
unknown: 0 ()
unsigned: 224 (ad., ae., aero., af., ai., al., ...za.,
        zm., zw.)
signed with NSEC: 25 (arpa., bg., biz., co., kg., lk.,
        mm., na., nz., pr., se., us., ... some IDNs...)
signed with NSEC3, no optout: 6 (cat., ch., cz., gov.,
        li., nu.)
signed with NSEC3, optout: 50 (ac., ag., am., asia., at.,
        be., bz., cl., co.th., com., com.br., de., dk.,
        edu., eu., fi., fr., gl., gr., hn., in., info.,
        io., jp., kr., la., lc., lu., me., mn., my., net.,
        nl., org., pl., pm., pt., re., sc., sh., si., su.,
        tf., tm., tw., ug., uk., vc., wf., yt.)
signed with NSEC3, may/maynot optout: 7 (gi., mil., museum.,
        nc., sx., xn--kprw13d., xn--kpry57d.)

Not surprisingly, most of the TLDs (71%) are still not signed.

One point interesting to me was that not a small number of signed TLDs use NSEC. I thought TLDs generally don’t like to allow “zone enumeration” by NSEC and the vast majority of them are using NSEC3. In particular, it’s interesting to me that .se uses NSEC. In my understanding it’s very advanced in terms of developing and adopting DNSSEC, so that shouldn’t be a technical reason.

It was also interesting to me that some TLDs, including seemingly quite large TLDs such as .ch and .cz, chose not to be Opt-Out.

Many others (57% of NSEC3 zones) were Opt-Out, which were not surprising.

Due to the limitation of the heuristic approach, there were 7 cases (8%) where it couldn’t identify whether they were Opt-Out or not.

The second part of output shows a histogram of NSEC3 hash iterations:

Statistics about NSEC3 iterations:
0: 4 (com., edu., net., uk.)
1: 19 (ag., asia., bz., eu., fr., hn., in., info., lc.,
     me., mn., org., pm., re., sc., tf., vc., wf., yt.)
2: 3 (ch., cl., li.)
3: 2 (lu., su.)
5: 9 (ac., at., be., fi., io., nl., sh., si., tm.)
8: 2 (gov., jp.)
10: 11 (am., co.th., com.br., cz., gl., gr., kr., my.,
      pt., tw., ug.)
12: 3 (cat., nu., pl.)
15: 1 (de.)
17: 1 (dk.)
150: 1 (la.)

There’s one very interesting point to me: .la uses an exceptionally large number of iterations. I don’t know whether it’s intentional or not, but I wonder about its performance impact.

コメントを投稿 / Submit Comments


Warning: Undefined variable $user_ID in /usr/home/jinmei/src/itheme/comments.php on line 74



(あれば / Optional):