Address03

Status: Final

Purpose

  • Verify that reverse PTR hostnames for nameserver IPs match the corresponding nameserver hostname.
  • Flag mismatch, missing reverse data, and no-response cases separately.

Preconditions And Inputs

  • Preconditions:
    • A zone.Zone object is available.
    • A recursor is available on the zone object.
  • Required inputs:
    • Nameserver addresses from ApexNameservers .
    • PTR lookup responses for each checked nameserver IP.
  • Profile/config knobs that affect behavior:
    • resolver.defaults.parallel: controls PTR query task parallelism.

Algorithm And Decision Flow

  1. Emit TEST_CASE_START.
  2. Collect nameserver entries with ApexNameservers .
  3. Build an ordered unique list by IP string:
    • Keep the first (nsname, ip) seen for each unique IP.
  4. For each unique IP, execute a PTR-check task (parallelized):
    • Compute reverse lookup owner with dns.ReverseAddr.
    • Send recursive PTR query.
    • If response message exists and RCODE == NOERROR with at least one PTR answer:
      • Collect PTR target names.
      • Compare targets against expected nameserver name (nsname) case-insensitively.
      • If none match, emit NAMESERVER_IP_PTR_MISMATCH (nsname, ns_ip, names).
    • Else if response message exists but PTR conditions above are not met, emit NAMESERVER_IP_WITHOUT_REVERSE (nsname, ns_ip).
    • Else emit NO_RESPONSE_PTR_QUERY (domain).
  5. After all tasks complete, if at least one IP was checked and no tag besides TEST_CASE_START was emitted, emit NAMESERVER_IP_PTR_MATCH.
  6. Emit TEST_CASE_END.
  7. When executed through AddressAll, this testcase runs only if Address02 produced NAMESERVERS_IP_WITH_REVERSE.

Per-IP PTR-vs-Name Match (steps 2-6)

collect nameserver IPs from ApexNameservers
 +- dedupe by IP string; first-seen (nsname, ip) wins
 |
 v
For each unique IP (parallel; fan-out = resolver.defaults.parallel):

   ptrQuery = dnsutil.ReverseAddr(ip)
    |
    v
   rec.Recurse(ptrQuery, PTR, IN)
    +- resp.Msg absent                       -> NO_RESPONSE_PTR_QUERY
    +- resp.Msg present
       +- RCODE == NOERROR and PTR records in answer
       |    +- collect PTR target names
       |    +- compare each to nsname (case-insensitive, normalized)
       |    +- any match?
       |        +- no  -> NAMESERVER_IP_PTR_MISMATCH (with sorted unique PTR names)
       |        +- yes -> (success; silent)
       +- otherwise (RCODE != NOERROR or no PTR records) -> NAMESERVER_IP_WITHOUT_REVERSE

After all tasks:
  at least one IP checked AND no failure tag emitted -> NAMESERVER_IP_PTR_MATCH
emit TEST_CASE_END

Module-level gating (in AddressAll):
  Address03 runs only when Address02 emitted NAMESERVERS_IP_WITH_REVERSE.

Emitted Tags (Possible Set)

TagEmitted when
CNAME_CHAIN_TOO_LONGA discovered NS hostname’s CNAME chain exceeds CNAMEMaxChainLength while resolving its address.
CNAME_TARGET_UNRESOLVEDA discovered NS hostname’s CNAME chain forms a loop, breaks, or fails to resolve to an address.
CNAME_TOO_MANY_RECORDSA single answer while resolving a discovered NS hostname carries more than CNAMEMaxRecords distinct CNAME RRs.
NAMESERVER_IP_PTR_MATCHAll checked IPs returned PTR answers that include their expected nameserver name.
NAMESERVER_IP_PTR_MISMATCHPTR answers exist for an IP, but none matches the expected nameserver name.
NAMESERVER_IP_WITHOUT_REVERSEPTR response is present but not successful (RCODE != NOERROR) or has no PTR record.
NO_RESPONSE_PTR_QUERYPTR recursive query returned no response message.
TEST_CASE_ENDTestcase completion marker is emitted.
TEST_CASE_STARTTestcase start marker is emitted.

Tag Arguments

TagArgument keyTypeMeaning
CNAME_CHAIN_TOO_LONGquery_namestringThe NS hostname whose CNAME chain exceeded the depth bound.
CNAME_TARGET_UNRESOLVEDquery_namestringThe NS hostname whose CNAME target could not be resolved.
CNAME_TARGET_UNRESOLVEDcname_targetstringThe last attempted CNAME target.
CNAME_TOO_MANY_RECORDSquery_namestringThe NS hostname whose answer carried too many CNAME RRs.
NAMESERVER_IP_PTR_MATCH--No arguments.
NAMESERVER_IP_PTR_MISMATCHnsnamestringExpected nameserver name for the checked IP (first-seen for that IP).
NAMESERVER_IP_PTR_MISMATCHns_ipstringChecked nameserver IP address.
NAMESERVER_IP_PTR_MISMATCHnamesstringSlash-delimited PTR target names returned in answer.
NAMESERVER_IP_WITHOUT_REVERSEnsnamestringNameserver name associated with the checked IP.
NAMESERVER_IP_WITHOUT_REVERSEns_ipstringChecked nameserver IP address.
NO_RESPONSE_PTR_QUERYdomainstringPTR owner name queried.
TEST_CASE_ENDtestcasestringTestcase display name (Address03).
TEST_CASE_STARTtestcasestringTestcase display name (Address03).

Severity Levels Per Tag

TagLevelNotes
CNAME_CHAIN_TOO_LONGERRORDefault from share/profile.json (test_levels.ADDRESS).
CNAME_TARGET_UNRESOLVEDERRORDefault from share/profile.json (test_levels.ADDRESS).
CNAME_TOO_MANY_RECORDSERRORDefault from share/profile.json (test_levels.ADDRESS).
NAMESERVER_IP_PTR_MATCHINFODefault from share/profile.json (test_levels.ADDRESS).
NAMESERVER_IP_PTR_MISMATCHNOTICEDefault from share/profile.json (test_levels.ADDRESS).
NAMESERVER_IP_WITHOUT_REVERSEWARNINGDefault from share/profile.json (test_levels.ADDRESS).
NO_RESPONSE_PTR_QUERYWARNINGDefault from share/profile.json (test_levels.ADDRESS).
TEST_CASE_ENDDEBUGDefault from share/profile.json (test_levels.ADDRESS).
TEST_CASE_STARTDEBUGDefault from share/profile.json (test_levels.ADDRESS).

Differences From Upstream

  • Differences (Upstream vs Gonemaster):
    • Upstream: describes consuming ADDRESS02 outcome data as input. Gonemaster: performs fresh PTR lookups inside Address03.
    • Upstream: states ADDRESS03 depends on ADDRESS02 success. Gonemaster: enforces gating in AddressAll by requiring NAMESERVERS_IP_WITH_REVERSE from Address02.
  • Potential upstream report:
    • no

Implementation Notes

The following behaviors are implementation choices, not mandated by protocol:

  • Module orchestration gating: Address03 runs only when Address02 emitted NAMESERVERS_IP_WITH_REVERSE. No DNS standard mandates this sequencing; it is a gonemaster-specific orchestration decision to skip PTR-match checks when no reverse data was found in the preceding testcase.
  • First-seen-wins deduplication: When multiple nameserver entries share the same IP, only the first-seen (nsname, ip) pair is retained for PTR checking. The protocol does not define how to handle nameserver IP collisions; first-seen is an implementation choice.
  • PTR name list delimiter: Multiple PTR target names in the names argument of NAMESERVER_IP_PTR_MISMATCH are joined with / (slash). This delimiter is an internal formatting choice with no protocol counterpart.

Edge Cases And Limitations

  • If ApexNameservers yields no IP addresses, only TEST_CASE_START and TEST_CASE_END are emitted.
  • Duplicate IPs are checked once; if multiple nameservers share an IP, only the first-seen nameserver name is evaluated for PTR-name match.
  • PTR target matching is case-insensitive and exact on normalized DNS name string.