Skip to content

Search-expanded forms of allowed single-label names are REFUSED: c-ares clients never reach the bare name #127

Description

@matthewdevenny

Symptom

With a search list in resolv.conf, every stub resolver asks <name>.<search> before <name> when the name has fewer dots than ndots. Under enforce with query filtering, the gate REFUSES that expanded form unless a rule happens to cover it. glibc and Go treat REFUSED as "try the next form"; c-ares does not — a REFUSED on a multi-label attempt ends its search (src/lib/ares_search.c, search_callback: the issue #852 carve-out for REFUSED/SERVFAIL applies to single-label attempts only). So on such a host:

  • a single-label allow rule myhost does not make myhost resolvable for c-ares clients — the bare name is never tried;
  • audit reports a dns_blocked for myhost.<search>, a name the operator never asked about, for every lookup.

Affected: Node dns.resolve* (not dns.lookup), Python grpcio, curl and gRPC builds on c-ares.

Reproduced on the #126 branch before its synthetic-specific handling, Lima VM, enforce + filtering, search lan:

c-ares (pycares)  _gateway: error=6 (DNS server refused query)
glibc (getent)    _gateway: 192.168.5.2          ← same second
proxy log         7× "DNS query blocked (domain not allowed)" domain=_gateway.lan

#128 closes this for the synthetic names by answering <synthetic>.<host search suffix> NXDOMAIN locally — correct there because the bare name is what resolves. This issue is the general form, which needs the opposite treatment: for a real host the expanded form is what resolves.

Why the gate does what it does

The gate judges the name as asked, after stripping the configured search domains — the operator's search-domains plus the Kubernetes defaults (StripSearchDomains). The host's own resolv.conf search list is never consulted, so myhost.lan is not myhost for matching purposes, and a denied query is REFUSED. REFUSED is the honest answer for a name policy denies; it is the wrong rcode for a form the client is merely iterating through on its way to a name policy allows.

Proposal

Strip the host's own resolv.conf search suffixes before the gate judges a name — the Kubernetes-suffix semantics StripSearchDomains already has — so myservice.corp.lan is matched as myservice, forwarded when allowed, and the client gets the real answer on its first attempt. Stripping only: not the search-domain bypass (HasSearchDomainSuffix), which lets unmatched names through and must stay operator-configured, since resolv.conf is DHCP-written.

Not NXDOMAIN. An earlier draft of this issue proposed answering the expanded form NXDOMAIN so the client falls through to the bare name; that is wrong for a real host. On a network with a search list the expanded form is the name that exists — myservice.corp.lan is the record, myservice is a convenience — so NXDOMAINing it and falling to bare myservice breaks the ordinary enterprise short-name pattern instead of fixing it. NXDOMAIN is right only for the resolved synthetic set (#128), whose expanded form never exists and whose bare form is what resolves.

Also not proposed: NXDOMAIN or any other rcode change for names denied outright. REFUSED stays the diagnosable answer for a name policy denies.

Out of scope

  • Names whose bare form is also denied — REFUSED stays.
  • Container listeners — a container carries its own resolv.conf.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions