---
title: "ADR-0017: Controlled DNS queries for the default resolver"
manual: "HTTP Guard"
version: "main"
permalink: "https://docs.typo3.org/permalink/netresearch/nr-http-guard:adr-0017@main"
source: "Adr/ADR-0017-ControlledDnsWireResolution.rst"
rendered: "2026-10-18T14:31:38+00:00"
---

# ADR-0017: Controlled DNS queries for the default resolver {#adr-0017}

-   *Status:* Accepted
-   *Date:* 2026-10-10
-   *Supersedes:* ADR-0005 only for its default resolver choice.

## Context {#adr-0017-context}

[ADR-0005: Bind the checked address set directly to the connection](https://docs.typo3.org/permalink/netresearch/nr-http-guard:adr-0005@main) requires a complete, validated address set bound to the
connection. Its historical proposal also selects `dns_get_record()`
and records the absence of a hard interruption contract. The current
implementation explicitly controls the resolution path, response validation
and query deadlines. An implicit NSS, hosts-file or search-domain fallback
would introduce a different target or trust boundary.

## Decision {#adr-0017-decision}

`LibraryServiceFactory` wires `StaticThenDnsResolver`
to `WireDnsQuery`. Only explicit static policy entries bypass DNS;
their addresses remain subject to policy. Other names are queried as exact
absolute FQDNs using A, AAAA and CNAME questions. There is no implicit NSS,
`/etc/hosts` or search-domain fallback.

The wire backend uses numeric trusted nameservers from
`/etc/resolv.conf`, read lazily at the first DNS query. At most three
nameservers are allowed. Known directives are recognized without adopting
their search or NSS semantics; unknown or invalid configuration is rejected.
A trusted resolver may use a private infrastructure address. This does not
grant permission for HTTP connections to private endpoint addresses.

`DnsPacketCodec` validates the transaction ID, question, response
status, types, lengths and compression bounds. Only a valid response with
the TC bit set repeats the same question over length-prefixed TCP within
the same query deadline. Repeated truncation or unverifiable answers do not
produce a usable resolution. The resolver follows the complete CNAME chain
and bounds both hops and addresses. `NativeOperation` converts
native warnings and notices to fixed failures without exposing their text.

The default deadline is one second per nameserver and question. Positive
memo entries last at most five seconds and no longer than the smallest
remaining TTL in the chain; using them still requires policy validation.
The complete address checks and connection pinning in ADR-0005 remain
binding. This ADR replaces only its historical default choice of
`dns_get_record()`.

## Alternatives considered {#adr-0017-alternatives}

-   **Unbounded dns_get_record as the default backend:** lacks equivalent
    explicit control over the query deadlines used here.
-   **Implicit NSS, hosts or search domains:** changes the qualified resolution
    path and may introduce different targets.
-   **Filter dangerous addresses or continue after DNS failure:** violates
    the complete address-set validation required by ADR-0005.
-   **TCP after any UDP failure:** expands fallback beyond the validated
    truncation case.

## Consequences {#adr-0017-consequences}

DNS has a bounded, auditable flow but remains separate network traffic to
trusted resolvers. The guard does not impose a process-wide network ban.
NSS-specific names need an explicit static assignment or a qualified
resolver implementation.

Three nameservers, nine names in the maximum CNAME chain and three query
types can theoretically take up to 81 seconds sequentially, plus local
overhead. This is not a guaranteed application and HTTP deadline. An SDK
timeout does not create a general resolver cancellation contract. Custom
resolvers are trusted internal extensions and must preserve complete,
bounded and verifiable answers.

## Sources and evidence {#adr-0017-verification}

The implementation is in `Classes/HttpGuard/WireDnsQuery.php`,
`Classes/HttpGuard/DnsPacketCodec.php`,
`Classes/HttpGuard/StaticThenDnsResolver.php`,
`Classes/HttpGuard/NativeOperation.php` and
`Classes/Service/LibraryServiceFactory.php`. Current bounds and scope
are documented under [DNS and static resolution](https://docs.typo3.org/permalink/netresearch/nr-http-guard:security-dns@main).

`Tests/HttpGuard/Unit/Policy/WireDnsQueryTest.php` maintains real local
UDP-to-TCP truncation and blackhole deadline probes, numeric-server controls
and lazy configuration reading. `Tests/HttpGuard/Unit/Policy/WireIoBoundaryContractTest.php`
and `Tests/HttpGuard/Unit/Policy/DnsWireBoundaryContractTest.php`
exercise I/O and packet boundaries. Separate target-contact controls are in
`Tests/HttpGuard/Integration/DnsPolicyTransportTest.php`.
Previously executed source-bound results are under [Verification report](https://docs.typo3.org/permalink/netresearch/nr-http-guard:verification-report@main).
This ADR records inspected sources and does not establish a new test run.

## Reconsideration trigger {#adr-0017-reassessment-trigger}

New resolver protocols, NSS integration, search semantics or changes to
deadlines and caching require renewed trust and evidence qualification.
A different backend does not remove complete address validation or the
binding between the validated addresses and the connection.
