You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The managed DnsResolver stub resolver (DnsResolverPal.Managed.cs), used on Linux and — as of #132216 — all other Unix platforms, does not implement EDNS(0) (RFC 6891). Queries are sent without an OPT pseudo-record, so the resolver is stuck with the original RFC 1035 512-byte UDP payload limit.
In DnsResolverPal.Managed.cs:
privateconstintMaxUdpResponseSize=512;
and the UDP receive buffer is rented at exactly that size. No OPT record is ever appended to the additional section of an outgoing query — AdditionalCount is only ever read when parsing a response.
Impact
Any response larger than 512 bytes comes back with the TC (truncation) bit set, which sends us down the TCP fallback path (ValidateResponse returns ResponseValidation.TcpFallback). That costs a full extra round trip plus a TCP connection setup, versus a single UDP exchange for a resolver that advertises a larger payload size.
This is not an edge case. Responses that routinely exceed 512 bytes include:
Domains with many A/AAAA records (large CDN or load-balanced pools)
TXT lookups — SPF/DKIM/DMARC records are frequently well over 512 bytes
MX and NS sets with a lot of additional-section glue
Anything DNSSEC-signed (RRSIG records are large)
glibc's stub resolver has enabled EDNS0 by default since 2.26 (RES_DFLT_OPTIONS), with a 1232-byte buffer, so today we pay a TCP round trip in cases where the platform resolver would not.
Proposal
Append an OPT record to the additional section of outgoing queries, advertising a sensible UDP payload size, and grow the receive buffer to match. 1232 bytes is the value recommended by DNS Flag Day 2020 — it is chosen to stay under the smallest plausible path MTU and avoid IP fragmentation, which is a reliability and security problem for DNS.
Additionally, ResolvConf.cs currently parses only nameserver lines and ignores options entirely. If EDNS0 is added, it would be reasonable to honour the related knobs:
options edns0 / options no-edns0
options bufsize:N (glibc does not support this one, but other resolvers do)
Care is needed around resolvers that mishandle OPT: the conventional mitigation is to retry without EDNS0 when a server responds FORMERR/NOTIMP or does not answer at all.
Notes
This is a pre-existing gap, not a regression — the resolver behaves correctly today, just with an extra round trip on large responses. Filing as a follow-up from the discussion on #132216.
Related: #132212 (Android DNS server discovery), #132215 (WASI support).
Another gap noticed in the same area, filed here for visibility rather than as part of this request: ResolvConf also ignores search and domain lines, so short/unqualified names that resolve via Dns.GetHostEntry will return NXDOMAIN through Dns.ResolveAddresses. Happy to split that into its own issue if preferred.
Description
The managed
DnsResolverstub resolver (DnsResolverPal.Managed.cs), used on Linux and — as of #132216 — all other Unix platforms, does not implement EDNS(0) (RFC 6891). Queries are sent without an OPT pseudo-record, so the resolver is stuck with the original RFC 1035 512-byte UDP payload limit.In
DnsResolverPal.Managed.cs:and the UDP receive buffer is rented at exactly that size. No OPT record is ever appended to the additional section of an outgoing query —
AdditionalCountis only ever read when parsing a response.Impact
Any response larger than 512 bytes comes back with the TC (truncation) bit set, which sends us down the TCP fallback path (
ValidateResponsereturnsResponseValidation.TcpFallback). That costs a full extra round trip plus a TCP connection setup, versus a single UDP exchange for a resolver that advertises a larger payload size.This is not an edge case. Responses that routinely exceed 512 bytes include:
TXTlookups — SPF/DKIM/DMARC records are frequently well over 512 bytesMXandNSsets with a lot of additional-section glueRRSIGrecords are large)glibc's stub resolver has enabled EDNS0 by default since 2.26 (
RES_DFLT_OPTIONS), with a 1232-byte buffer, so today we pay a TCP round trip in cases where the platform resolver would not.Proposal
Append an OPT record to the additional section of outgoing queries, advertising a sensible UDP payload size, and grow the receive buffer to match. 1232 bytes is the value recommended by DNS Flag Day 2020 — it is chosen to stay under the smallest plausible path MTU and avoid IP fragmentation, which is a reliability and security problem for DNS.
Additionally,
ResolvConf.cscurrently parses onlynameserverlines and ignoresoptionsentirely. If EDNS0 is added, it would be reasonable to honour the related knobs:options edns0/options no-edns0options bufsize:N(glibc does not support this one, but other resolvers do)Care is needed around resolvers that mishandle OPT: the conventional mitigation is to retry without EDNS0 when a server responds
FORMERR/NOTIMPor does not answer at all.Notes
This is a pre-existing gap, not a regression — the resolver behaves correctly today, just with an extra round trip on large responses. Filing as a follow-up from the discussion on #132216.
Related: #132212 (Android DNS server discovery), #132215 (WASI support).
Another gap noticed in the same area, filed here for visibility rather than as part of this request:
ResolvConfalso ignoressearchanddomainlines, so short/unqualified names that resolve viaDns.GetHostEntrywill return NXDOMAIN throughDns.ResolveAddresses. Happy to split that into its own issue if preferred.Note
This issue was drafted by GitHub Copilot.