- Clone all 5 Zonemaster component repos (LDNS, Engine, CLI, Backend, GUI) - Dockerfile.backend: 8-stage multi-stage build LDNS→Engine→CLI→Backend - Dockerfile.gui: Astro static build served via nginx - docker-compose.yml: backend (internal) + frontend (port 5353) - nginx.conf: root redirects to /es/, /api/ proxied to backend - zonemaster-gui/config.ts: defaultLanguage set to 'es' (Spanish) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
283 lines
14 KiB
Markdown
283 lines
14 KiB
Markdown
# CONNECTIVITY04: IP Prefix Diversity
|
||
|
||
## Test case identifier
|
||
**CONNECTIVITY04**
|
||
|
||
## Table of contents
|
||
|
||
* [Objective](#objective)
|
||
* [Scope](#scope)
|
||
* [Inputs](#inputs)
|
||
* [Summary](#summary)
|
||
* [Test procedure](#test-procedure)
|
||
* [Outcome(s)](#outcomes)
|
||
* [Special procedural requirements](#special-procedural-requirements)
|
||
* [Prefix lookup methods](#prefix-lookup-methods)
|
||
* [Cymru prefix lookup](#cymru-prefix-lookup)
|
||
* [RIPE prefix lookup](#ripe-prefix-lookup)
|
||
* [Intercase dependencies](#intercase-dependencies)
|
||
* [Terminology](#terminology)
|
||
|
||
## Objective
|
||
|
||
The objective in this Test Case is to verify that all IP addresses of the
|
||
domain's authoritative name servers are not announced from the same IP prefix.
|
||
|
||
[RFC 2182, section 3.1][RFC 2182#3.1], clearly specifies that distinct authoritative
|
||
name servers for a child domain should be placed in different topological and
|
||
geographical locations. The objective is to minimise the likelihood of a single
|
||
failure disabling all of them.
|
||
|
||
## Scope
|
||
|
||
It is assumed that *Child Zone* is also tested and reported by [Connectivity01].
|
||
This Test Case will just ignore non-responsive name servers or name servers not
|
||
giving a correct DNS response for an authoritative name server.
|
||
|
||
## Inputs
|
||
|
||
* "Child Zone" - The domain name to be tested.
|
||
* "Prefix Database" - The database of IP Prefix data to be used. Possible values
|
||
are "RIPE" and "Cymru" (the default value).
|
||
* "Cymru Base Name" - If the *Prefix Database* is "Cymru", the default value
|
||
is "asnlookup.zonemaster.net".
|
||
* "RIS Whois Server" - If the *Prefix Database* is "RIPE", the default value
|
||
is "riswhois.ripe.net".
|
||
|
||
## Summary
|
||
|
||
Message Tag | Level | Arguments | Message ID for message tag
|
||
:---------------------------|:--------|:----------------------------|:------------------------------------------------------------------------------------------------
|
||
CN04_EMPTY_PREFIX_SET | NOTICE | ns_ip | Prefix database returned no information for IP address {ns_ip}.
|
||
CN04_ERROR_PREFIX_DATABASE | NOTICE | ns_ip | Prefix database error for IP address {ns_ip}.
|
||
CN04_IPV4_DIFFERENT_PREFIX | INFO | ns_list | The following name server(s) are announced in unique IPv4 prefix(es): "{ns_list}"
|
||
CN04_IPV4_SAME_PREFIX | NOTICE | ns_list, ip_prefix | The following name server(s) are announced in the same IPv4 prefix ({ip_prefix}): "{ns_list}"
|
||
CN04_IPV4_SINGLE_PREFIX | WARNING | | All name server(s) IPv4 address(es) are announced in the same IPv4 prefix.
|
||
CN04_IPV6_DIFFERENT_PREFIX | INFO | ns_list | The following name server(s) are announced in unique IPv6 prefix(es): "{ns_list}"
|
||
CN04_IPV6_SAME_PREFIX | NOTICE | ns_list, ip_prefix | The following name server(s) are announced in the same IPv6 prefix ({ip_prefix}): "{ns_list}"
|
||
CN04_IPV6_SINGLE_PREFIX | WARNING | | All name server(s) IPv6 address(es) are announced in the same IPv6 prefix.
|
||
|
||
The value in the Level column is the default severity level of the message. The
|
||
severity level can be changed in the [Zonemaster-Engine Profile]. Also see the
|
||
[Severity Level Definitions] document.
|
||
|
||
The argument names in the Arguments column lists the arguments used in the
|
||
message. The argument names are defined in the [Argument List].
|
||
|
||
## Test procedure
|
||
|
||
1. Create the following empty sets:
|
||
1. IP prefix, name server name and IP address ("IPv4 Prefix")
|
||
2. IP prefix, name server name and IP address ("IPv6 Prefix")
|
||
|
||
2. Obtain the set of name server names and IP addresses using
|
||
[Get-Del-NS-Names-and-IPs] and [Get-Zone-NS-Names-and-IPs] in [MethodsV2] and
|
||
split those into IPv4 and IPv6 ("NS IPv4" and "NS IPv6", respectively).
|
||
|
||
3. For each IP address in *NS IPv4* and *NS IPv6* ("NS IP Address"),
|
||
respectively, do:
|
||
1. Determine the IP prefix in which *NS IP Address* is announced
|
||
using *Prefix Database*. Go to [Prefix Lookup Methods] section below
|
||
with the IP address as input.
|
||
2. Add found IP prefix, if any, with *NS IP Address* and name server name
|
||
to the *IPv4 Prefix* and *IPv6 Prefix* sets, respectively.
|
||
|
||
4. If the *IPv4 Prefix* set is non-empty, then do:
|
||
1. For each IP prefix in the set that has two or more members, output
|
||
*[CN04_IPV4_SAME_PREFIX]* with the prefix and list of all members (name
|
||
server names and IP addresses) for that prefix.
|
||
2. For all IP prefixes in the set that have exactly one member, output
|
||
*[CN04_IPV4_DIFFERENT_PREFIX]* with the combined set of their associated
|
||
members (name server names and IP addresses).
|
||
3. If all members of *NS IPv4* are members of the same IP prefix in
|
||
*IPv4 Prefix* then output *[CN04_IPV4_SINGLE_PREFIX]*.
|
||
|
||
5. If the *IPv6 Prefix* set is non-empty, then do:
|
||
1. For each IP prefix in the set that has two or more members, output
|
||
*[CN04_IPV6_SAME_PREFIX]* with the prefix and list of all members (name
|
||
server names and IP addresses) for that prefix.
|
||
2. For all IP prefixes in the set that have exactly one member, output
|
||
*[CN04_IPV6_DIFFERENT_PREFIX]* with the combined set of their associated
|
||
members (name server names and IP addresses).
|
||
3. If all members of *NS IPv6* are members of the same IP prefix in
|
||
*IPv6 Prefix* then output *[CN04_IPV6_SINGLE_PREFIX]*.
|
||
|
||
## Outcome(s)
|
||
|
||
The outcome of this Test Case is "fail" if there is at least one message
|
||
with the severity level *[ERROR]* or *[CRITICAL]*.
|
||
|
||
The outcome of this Test Case is "warning" if there is at least one message
|
||
with the severity level *[WARNING]*, but no message with severity level
|
||
*ERROR* or *CRITICAL*.
|
||
|
||
In other cases, no message or only messages with severity level
|
||
*[INFO]* or *[NOTICE]*, the outcome of this Test Case is "pass".
|
||
|
||
## Special procedural requirements
|
||
|
||
This Test Case is dependent on one of two possible services that can provide
|
||
ASN lookup (Cymru or RIPE RIS). The service must be available over the network.
|
||
|
||
The *Child Zone* must be a valid name meeting
|
||
"[Requirements and normalization of domain names in input]".
|
||
|
||
## Prefix lookup methods
|
||
|
||
Use the prefix method set in *Prefix Database* and the IP address in the call to
|
||
this section. Refer to the appropriate section below with the IP address as
|
||
input.
|
||
|
||
### Cymru prefix lookup
|
||
|
||
The Cymru prefix lookup is described on the Team Cymru [IP to ASN Mapping]
|
||
using DNS lookup, but the default data comes from [bgp.tools] (Port 179 Ltd
|
||
in England and Wales) and is continuously being mapped into
|
||
`asnlookup.zonemaster.net` by the Zonemaster project. Data is fetched from
|
||
<https://bgp.tools/table.txt>. The Cymru source can also be used, if
|
||
requested.
|
||
|
||
1. Input is the IP address in the call to this section ("Input IP").
|
||
|
||
2. Prepend the *Cymru Base Name* with the label "origin" (IPv4) or
|
||
"origin6" (IPv6) ("Expanded Base Name"). Example of expanded basenames :
|
||
|
||
```
|
||
origin.asnlookup.zonemaster.net
|
||
origin6.asnlookup.zonemaster.net
|
||
```
|
||
|
||
3. Reverse *Input IP* with the same method as is used for reverse lookup
|
||
("Reverse IP"). For description see [RFC 1035][RFC 1035#3.5], section 3.5, for
|
||
IPv4 and [RFC 3596][RFC 3596#2.5], section 2.5, for IPv6.
|
||
|
||
4. Prepend the *Expanded Base Name* with *Reverse IP* ("Query Name").
|
||
See [IP to ASN Mapping] for details.
|
||
|
||
5. Create a [DNS Query] with query type TXT and query name *Query Name*.
|
||
("TXT Query").
|
||
|
||
6. Do [DNS Lookup] of *TXT Query*.
|
||
|
||
7. If at least one of the following criteria is met, output
|
||
*[CN04_EMPTY_PREFIX_SET]* and exit this lookup:
|
||
1. The [DNS Response] has the [RCODE Name] NXDomain.
|
||
2. The [DNS Response] has the [RCODE Name] NoError and an empty answer section.
|
||
|
||
8. If at least one of the following criteria is met, output
|
||
*[CN04_ERROR_PREFIX_DATABASE]* and exit this lookup:
|
||
1. There is no DNS response.
|
||
2. The [DNS Response] does not have the [RCODE Name] NoError.
|
||
3. The answer section has no TXT record.
|
||
|
||
9. Extract the TXT record(s) from the answer section (see [IP to ASN Mapping]
|
||
for examples). Do for each TXT record:
|
||
1. If the TXT record consists of multiple strings in RDATA, then [concatenate]
|
||
the strings into one string.
|
||
2. Using the format of such string parse the string into its parts and
|
||
extract the subnet specification.
|
||
1. If it was not possible to parse the string, ignore it and go to next TXT
|
||
record.
|
||
3. If *Input IP* does not match the extracted subnet, output
|
||
*[CN04_ERROR_PREFIX_DATABASE]*, break the processing of TXT records and
|
||
exit this loop without returning any prefix.
|
||
4. Store the extracted prefix.
|
||
|
||
10. If more than one IP prefix was stored from the loop above, keep the most
|
||
specific and discard the rest.
|
||
|
||
11. If no IP prefix was stored, output *[CN04_EMPTY_PREFIX_SET]*.
|
||
|
||
12. Return the IP prefix, or an empty string if no IP prefix was stored.
|
||
|
||
|
||
### RIPE prefix lookup
|
||
|
||
The RIPE Prefix lookup is described on the RIPE [RISwhois] page.
|
||
|
||
1. Create a query string by prepending the IP address with
|
||
" -F -M " ("WHOIS String"). E.g., using IP address "192.0.2.10":
|
||
|
||
```
|
||
" -F -M 192.0.2.10"
|
||
```
|
||
|
||
2. Create a WHOIS query (port 43 with the nicname ((whois)) protocol)
|
||
using the *WHOIS String* ("WHOIS Query"). E.g., on Linux:
|
||
|
||
```
|
||
whois -h riswhois.ripe.net " -F -M 192.0.2.10"
|
||
```
|
||
|
||
3. [Send] *WHOIS Query* to the *RIS Whois Server*.
|
||
|
||
4. If there is no response, output *[CN04_ERROR_PREFIX_DATABASE]* and exit this lookup.
|
||
|
||
5. Extract the string (non-empty line not prepended with "%") from the response, and do:
|
||
1. If there is no such string, output *[CN04_EMPTY_PREFIX_SET]* and exit this lookup.
|
||
2. Extract the IP prefix from the second field of the string.
|
||
3. If it was not possible to extract the IP prefix (i.e., malformed response),
|
||
output *[CN04_ERROR_PREFIX_DATABASE]* and exit this lookup.
|
||
|
||
6. Return the IP prefix.
|
||
|
||
## Intercase dependencies
|
||
|
||
None
|
||
|
||
## Terminology
|
||
|
||
* "Concatenate" - The term is used to refer to the conversion of a TXT
|
||
resource record’s data to a single contiguous string, as specified in [RFC
|
||
7208, section 3.3][RFC7208#3.3].
|
||
|
||
* "DNS Lookup" - The term is used when a recursive lookup is used, though
|
||
any changes to the DNS tree introduced by an [undelegated test] must be
|
||
respected. Compare with "[Send]".
|
||
|
||
* "Send" - The term "send" (to an IP address) is used when a DNS query is sent to
|
||
a specific name server IP address. Compare with "[DNS Lookup]".
|
||
|
||
|
||
|
||
[Argument List]: ../ArgumentsForTestCaseMessages.md
|
||
[Bgp.tools]: https://bgp.tools/
|
||
[CN04_EMPTY_PREFIX_SET]: #outcomes
|
||
[CN04_ERROR_PREFIX_DATABASE]: #outcomes
|
||
[CN04_IPV4_DIFFERENT_PREFIX]: #outcomes
|
||
[CN04_IPV4_SAME_PREFIX]: #outcomes
|
||
[CN04_IPV4_SINGLE_PREFIX]: #outcomes
|
||
[CN04_IPV6_DIFFERENT_PREFIX]: #outcomes
|
||
[CN04_IPV6_SAME_PREFIX]: #outcomes
|
||
[CN04_IPV6_SINGLE_PREFIX]: #outcomes
|
||
[Concatenate]: #terminology
|
||
[Connectivity01]: connectivity01.md
|
||
[CRITICAL]: ../SeverityLevelDefinitions.md#critical
|
||
[Cymru Database]: #cymru-prefix-lookup
|
||
[DEBUG]: ../SeverityLevelDefinitions.md#notice
|
||
[DNS Lookup]: #terminology
|
||
[DNS Query and Response Defaults]: ../DNSQueryAndResponseDefaults.md
|
||
[DNS Query]: ../DNSQueryAndResponseDefaults.md#default-setting-in-dns-query
|
||
[DNS Response]: ../DNSQueryAndResponseDefaults.md#default-handling-of-a-dns-response
|
||
[ERROR]: ../SeverityLevelDefinitions.md#error
|
||
[Get-Del-NS-Names-and-IPs]: ../MethodsV2.md#method-get-delegation-ns-names-and-ip-addresses
|
||
[Get-Zone-NS-Names-and-IPs]: ../MethodsV2.md#method-get-zone-ns-names-and-ip-addresses
|
||
[INFO]: ../SeverityLevelDefinitions.md#info
|
||
[IP to ASN Mapping]: https://www.team-cymru.com/ip-asn-mapping
|
||
[MethodsV2]: ../MethodsV2.md
|
||
[NOTICE]: ../SeverityLevelDefinitions.md#notice
|
||
[Prefix Lookup Methods]: #prefix-lookup-methods
|
||
[RCODE Name]: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
|
||
[Requirements and normalization of domain names in input]: ../RequirementsAndNormalizationOfDomainNames.md
|
||
[RFC 1035#3.5]: https://datatracker.ietf.org/doc/html/rfc1035#section-3.5
|
||
[RFC 2182#3.1]: https://datatracker.ietf.org/doc/html/rfc2182#section-3.1
|
||
[RFC 3596#2.5]: https://datatracker.ietf.org/doc/html/rfc3596#section-2.5
|
||
[RFC7208#3.3]: https://datatracker.ietf.org/doc/html/rfc7208#section-3.3
|
||
[RIPE Database]: #ripe-prefix-lookup
|
||
[RISwhois]: https://www.ripe.net/analyse/archived-projects/ris-tools-web-interfaces/riswhois
|
||
[Send]: #terminology
|
||
[Severity Level Definitions]: ../SeverityLevelDefinitions.md
|
||
[Undelegated test]: ../../test-types/undelegated-test.md
|
||
[WARNING]: ../SeverityLevelDefinitions.md#warning
|
||
[Zonemaster-Engine Profile]: ../../../configuration/profiles.md
|