Skip to main content

EDNS Client Subnet in Practice: Evaluating Public Resolver Behaviors

·3217 words·16 mins·
Babak Farrokhi
Author
Babak Farrokhi
Engineering and Technical Operations Leader

When you query DNS, your resolver might be influencing geographic routing decisions behind the scenes using a technique called EDNS Client Subnet (ECS). But how do major DNS resolvers actually implement this technique? I decided to find out by testing public DNS resolvers, and the results revealed five distinct approaches to handling geographic intelligence. This article explains those behaviors and the test methodology.

Summary
#

Testing 10 public DNS resolvers revealed that ECS implementation is more complex than a simple on/off feature. Most (80%) of tested resolvers use ECS when querying authoritative servers (forwarding ECS to authoritative nameservers), but half (50%) also include ECS in responses back to clients (echoing). Five distinct behavior patterns emerged, each with different privacy and transparency trade-offs.

Resolver behavior varies not only by implementation, but also by queried domains. Google blocks explicit ECS to Akamai domains while forwarding to others. Subnet size matters too: Google requires /24 or broader for IPv4 and /56 or broader for IPv6, blocking more specific subnets entirely. Quad9 ECS (9.9.9.11) is the only resolver that consistently forwards explicit client subnet options across all tested authoritative servers.

Testing methodology is very important. Simple echo tests (checking stub-to-resolver responses) miss resolvers that forward ECS to authoritative servers without echoing back to clients. Subnet size restrictions can appear as complete blocking. Domain-specific behavior means testing against a single authoritative server provides an incomplete picture.

What is EDNS Client Subnet (ECS)?
#

EDNS Client Subnet is defined in RFC 7871. An important note about this RFC is that, due to privacy implications of ECS, the workgroup has decided to mark it as an Informational RFC, meaning that it does not necessarily represent community consensus or recommendation.

The RFC describes it in Section 5 as: “an EDNS0 option to allow Recursive Resolvers, if they are willing, to forward details about the origin network from which a query is coming when talking to other nameservers.”

Without ECS, a CDN sees only the resolver’s IP address. If I’m in Tokyo using Quad9 Resolver (9.9.9.9), the CDN might direct me to a server near Quad9’s resolver infrastructure (for example in Singapore) rather than near my actual location in Tokyo, resulting in suboptimal performance.

According to RFC 7871, Section 5: “an Authoritative Nameserver could use ECS as a hint to the end user’s network location and provide a better answer. Its response would also contain an ECS option, clearly indicating that the server made use of this information, and that the answer is tied to the client’s network.”

It also explains that ECS “is meant to be added in queries sent by Intermediate Nameservers in a way that is transparent to Stub Resolvers and end users.”

An important distinction is the relationship between stub-to-resolver and resolver-to-authoritative. In a typical scenario, when a user sends a regular query to an ECS-enabled resolver, the resolver adds the ECS option when forwarding the request to an authoritative DNS server. The authoritative server decides how to process ECS and returns its decision back to the resolver. RFC 7871, Section 7.2.2 specifies that resolvers MUST NOT include an ECS option in responses to clients that did not originally send one, as “a client that did not use an ECS option might not be able to understand it.”

In this context, two ECS parameters are important:

  • Source Prefix Length: The subnet mask sent in the ECS option (e.g, /24 for IPv4 or /56 for IPv6)
  • Scope Prefix Length: The subnet mask returned by the resolver, indicating the specificity of the cached answer.

When an authoritative server returns ECS response to resolver, or when resolver echoes ECS back to the client, it includes both the source prefix it used and the scope prefix indicating how specific the answer is for caching purposes.

In dig or dnsping output, this appears as “address/source/scope” (e.g., 203.0.113.0/24/24 or 203.0.113.0/24/0).

According to section 7.3.1, a scope of /0 indicates “an answer suitable for all client addresses.”, meaning the answer it’s providing is not location-specific and can be cached for any client address, not just the subnet that was queried.

While most users rely on their resolver’s automatic ECS implementation, RFC 7871, Section 7.1.2 allows stubs to send ECS options: “A Stub Resolver MAY generate DNS queries with an ECS option that sets SOURCE PREFIX-LENGTH to limit how network information should be revealed.” Tools like dig, kdig or dnsping allow manual specification of ECS options with custom subnet masks for testing. Different resolvers implement ECS differently, so choosing a resolver affects how geographic information is processed. Enterprise users can configure recursive resolvers with specific ECS policies, while VPNs or proxies change the source IP that resolvers use for ECS calculations.

RFC 7871 acknowledges this flexibility, noting in Section 5 that “operators of Intermediate Nameservers with ECS enabled are allowed to choose how many bits of the address of received queries to forward or to reduce the number of bits forwarded for queries already including an ECS option.”

ECS Behavior Patterns
#

Analysis of ECS echo behavior in stub-to-recursive queries across major DNS resolvers uncovered distinct behavior patterns.

Google Public DNS
#

Transparent proxy behavior with strict privacy boundaries. Rejects IPv4 subnets more specific than /24 and IPv6 subnets more specific than /56. Google mirrors ECS scope responses from authoritative nameservers.

Google DNS enforces strict privacy boundaries by rejecting IPv4 subnets more specific than /24 and IPv6 subnets more specific than /56 with EDE error code 49152. For all domains, Google mirrors the scope responses it receives from authoritative nameservers, whether that is a specific scope value or scope/0 when the authoritative nameserver does not support ECS.

Note: Google’s behavior varies by transport protocol for edge cases. When clients provide ECS prefixes more specific than /24 for IPv4, the unencrypted Do53 service rejects queries with a REFUSED status and error message, while the encrypted DoH and DoH3 services accept the queries but truncate the prefix to /24. RFC 8932 Section 5.1.6 states that “A DNS privacy service should deliver the same level of service as offered on unencrypted channels in terms of options such as filtering (or lack thereof), DNSSEC validation, etc.” This difference in handling between encrypted and unencrypted channels represents an implementation choice that may not align with this recommendation.

Testing across multiple domains confirms consistent mirroring behavior. Domains with ECS-enabled authoritative nameservers (such as google.com, netflix.com, cloudflare.com) show scope values echoed through Google DNS that match the authoritative responses. Domains without ECS support at the authoritative level (such as apple.com, amazon.com) consistently return scope/0 from both the authoritative nameserver and Google DNS. This demonstrates that Google acts as a transparent proxy for ECS scope information, faithfully mirroring what authoritative nameservers return regardless of the domain.

All echoed addresses have host bits zeroed.

AdGuard DNS
#

Client-to-resolver transparency with exact scope preservation for both IPv4 and IPv6. AdGuard DNS mirrors the input scope exactly in responses back to clients, but forwards the client’s actual subnet to authoritative servers (ignoring any explicit ECS options). Single host input returns single host precision, large network blocks return broad geographic scope. This approach is not privacy friendly with specific subnets.

For example, querying with a /32 prefix:

$ dig @94.140.14.14 +subnet=203.0.113.100/32 A google.com

; EDNS: version: 0, flags:; udp: 4096
; CLIENT-SUBNET: 203.0.113.100/32/32

The response shows scope/32, preserving the exact precision of the input. However, when forwarding to authoritative servers, AdGuard uses the client’s actual subnet rather than the explicit ECS option provided.

Control D, Verisign, Neustar
#

Privacy-focused processing where all inputs become scope /0 for both IPv4 and IPv6. These resolvers accept ECS for geographic processing but always return scope /0, revealing no geographic precision details. The ECS option still carries the submitted prefix, so authoritative servers can learn coarse location.

Cloudflare, Quad9, OpenDNS
#

Forward-only ECS processing that provides no feedback to clients. These resolvers forward ECS information to authoritative servers for geographic optimization but don’t include ECS options in responses back to clients. Authoritative server testing confirms these resolvers actively send ECS information when querying authoritative servers.

DNS.SB, NextDNS
#

No ECS support. These resolvers do not process or forward ECS information. Queries with ECS options receive responses identical to queries without ECS, and authoritative server testing confirms no ECS information is forwarded.

Testing 10 public DNS resolvers revealed that 5 echo ECS back to clients, 3 forward ECS without echoing, and 2 provide no ECS support. All resolvers that echo ECS zero the host bits before returning responses.

IPv6 ECS Support
#

Google DNS filters RFC 3849 documentation IPv6 addresses (2001:db8::/32) but accepts real IPv6 addresses for ECS queries.

AdGuard DNS mirrors input scope exactly in client responses for all queries. Verisign, Control D, and Neustar take a conservative approach and always return scope /0 regardless of input.

Google DNS implements IPv6 ECS processing with a maximum prefix length of /56 bits. The resolver rejects subnets more specific than /56 with EDE error codes and filters out RFC 3849 documentation addresses entirely. Google mirrors the scope responses from authoritative nameservers regardless of the domain queried. The resolver enforces different minimum prefix lengths for IPv4 (requiring /24 or broader) versus IPv6 (requiring /56 or broader).

Verifying ECS Behavior with Authoritative Testing
#

To verify whether “silent” resolvers actually forward ECS information to authoritative servers, I tested against multiple authoritative whoami services: Akamai’s whoami service (whoami.ds.akahelp.net), Google MyAddr (o-o.myaddr.l.google.com), and PowerDNS whoami service. These services return TXT records showing what information authoritative servers actually receive from recursive resolvers.

Authoritative Server Test Results
#

To verify actual ECS forwarding behavior, I tested against three authoritative servers: Akamai’s whoami service, Google MyAddr (o-o.myaddr.l.google.com), and PowerDNS whoami service. Testing revealed that resolver behavior varies significantly by authoritative domain.

  • Cloudflare (1.1.1.1) and OpenDNS (208.67.220.220): Forward the client’s actual subnet in ECS format (e.g., 198.51.100.0/24/24) to authoritative servers when the client provides a non-zero ECS prefix. Honors SOURCE PREFIX-LENGTH of 0 by not forwarding any ECS.
  • Quad9 ECS (9.9.9.11): Forwards the explicit ECS subnet provided by the client (203.0.113.0/24/24), not the client’s actual subnet. When SOURCE PREFIX-LENGTH is 0, forwards the client’s subnet instead of omitting ECS.

The following table summarizes what each resolver actually forwards to different authoritative servers when the client sends an explicit ECS option. Test configuration: 185.199.109.0/24 for IPv4, 2001:420:1101:1::/56 for IPv6 (using /24 and /56 to meet minimum subnet size requirements).

Table legend: “Forwarded” means the resolver sent the explicit ECS option provided by the client. “Client subnet” means the resolver ignored the explicit option and sent the client’s actual subnet instead. “Blocked” means the resolver sent no ECS information at all. “Stripped” means the resolver removed the ECS option entirely.

Resolver Akamai IPv4 Google/PowerDNS IPv4 Akamai IPv6 Google/PowerDNS IPv6 Pattern
Quad9 ECS (9.9.9.11) Forwarded Forwarded Forwarded Forwarded True transparency
Google (8.8.8.8) Blocked Forwarded Blocked Forwarded Domain-specific
AdGuard (94.140.14.14) Client subnet Client subnet Client subnet Client subnet Always client-based
Cloudflare (1.1.1.1) Client subnet Stripped Client subnet Stripped Domain-specific
OpenDNS (208.67.220.220) Client subnet Client subnet /0 Client subnet Resolver subnet /0 Domain-specific

Subnet Size Requirements
#

Google requires minimum subnet sizes:

  • IPv4: Requires /24 or broader. Blocks more specific prefixes. (/25 through /32)
  • IPv6: Requires /56 or broader. Blocks more specific prefixes (/57 through /128)

Quad9 accepts all subnet sizes and normalizes to /24 for IPv4 and /56 for IPv6.

Google’s Domain-Specific Filtering
#

Google implements domain-based ECS filtering. Testing shows:

  • Akamai domains (whoami.ds.akahelp.net): Blocks all explicit ECS
  • Other domains (Google MyAddr, PowerDNS): Forwards ECS when subnet size requirements are met

This behavior confirms the blocking comes from Google’s resolver, not from Akamai refusing queries.

Testing Commands:

# Test what authoritative servers receive from Quad9
dig +short @9.9.9.11 +subnet=185.199.109.0/24 TXT whoami.ds.akahelp.net

# Test Google's domain-specific blocking (Akamai)
dig +short @8.8.8.8 +subnet=185.199.109.0/24 TXT whoami.ds.akahelp.net  # No response

# Test Google forwarding to other domains
dig +short @8.8.8.8 +subnet=185.199.109.0/24 TXT o-o.myaddr.l.google.com  # Forwarded

# Test with insufficient subnet size (will be blocked)
dig +short @8.8.8.8 +subnet=185.199.109.1/32 TXT o-o.myaddr.l.google.com  # No response

Testing Methodology
#

I used the dnsping tool with ECS testing across multiple subnet sizes.

Running the examples:

The examples below use dnsping.py which requires installing dnsdiag (pip install dnsdiag or uv tool install dnsdiag). Alternatively, you can run the examples without installation by replacing dnsping.py with uvx --from dnsdiag dnsping in any command.

Test Parameters:

  • Primary Test: 203.0.113.0/24 (RFC 5737 documentation range)
  • Authoritative Testing: 185.199.109.0/24 for IPv4, 2001:420:1101:1::/56 for IPv6 (neutral public addresses)
  • Extended Testing: Multiple subnet masks (/16, /24, /26, /32 for IPv4; /48, /56, /64, /128 for IPv6)
  • Query Target: google.com A record (plus comparative runs against third-party names like nlnog.net to spot domain-dependent scope policies)
  • Tool: dnsping with --ecs option

Important: Use /24 or broader for IPv4 and /56 or broader for IPv6 when testing Google DNS to avoid subnet size filtering.

Example Test Commands:

# Test basic ECS echo behavior
dnsping.py -c 1 -s 8.8.8.8 --ecs 203.0.113.0/24 google.com

# Compare with AdGuard's mirroring
dnsping.py -c 1 -s 94.140.14.14 --ecs 203.0.113.100/32 google.com

# Test IPv6 ECS behavior (use real addresses with /56 or broader)
dnsping.py -c 1 -s 8.8.8.8 --ecs 2001:420:1101:1::/56 google.com

Extended Subnet Mask Testing Results
#

IPv4 Subnet Size Analysis
#

Resolver Input Subnet Source Scope Behavior Pattern
Google DNS 203.0.113.100/32 /32 REFUSED Rejects >24 bits
203.0.113.0/26 /26 REFUSED Rejects >24 bits
203.0.113.0/24 /24 /24 Mirrors authoritative response
203.0.0.0/16 /16 /16 Mirrors authoritative response
AdGuard DNS 203.0.113.100/32 /32 /32 Mirrors exactly
203.0.113.0/26 /26 /26 Mirrors exactly
203.0.113.0/24 /24 /24 Mirrors exactly
Verisign/Control D/Neustar 203.0.113.100/32 /32 /0 Always scope/0
203.0.113.0/24 /24 /0 Always scope/0
203.0.0.0/16 /16 /0 Always scope/0

Note that Google accepts input at /16 and /24, but the scope values in responses reflect what the authoritative nameserver returns, not a normalization of the input.

IPv6 Subnet Size Analysis (Real Addresses)
#

Resolver Input Subnet Source Scope Behavior Pattern
Google DNS 2001:420:.../128 /128 REFUSED Rejects more specific than /56
2001:420:.../64 /64 REFUSED Rejects more specific than /56
2001:420:.../56 /56 varies Mirrors authoritative response
2001:420:.../48 /48 varies Mirrors authoritative response
2001:420:.../32 /32 varies Mirrors authoritative response
AdGuard DNS 2001:420:.../128 /128 /128 Mirrors input exactly
2001:420:.../64 /64 /64 Mirrors input exactly
2001:420:.../48 /48 /48 Mirrors input exactly
Verisign/Control D/Neustar 2001:420:.../128 /128 /0 Always scope/0
2001:420:.../64 /64 /0 Always scope/0
2001:420:.../32 /32 /0 Always scope/0

Note that Google filters RFC 3849 documentation addresses (2001:db8::/32), so testing requires using real IPv6 addresses. The scope responses from Google vary by domain, reflecting the ECS implementation of each domain’s authoritative nameservers rather than a fixed Google policy.

Private Address Handling
#

While testing, I was curious about how resolvers handle private IP addresses in ECS requests - a simple test that revealed some interesting behavioral differences.

Private IPv4 Results (RFC 1918, RFC 6598)
#

Provider 192.168.x.x/24 10.x.x.x/24 100.64.x.x/24 (CGNAT) Behavior
Google DNS REFUSED REFUSED REFUSED Rejects all private addresses
AdGuard DNS scope/24 scope/24 scope/24 Mirrors private addresses
Verisign scope/0 scope/0 scope/0 Forwards but returns scope/0
Control D scope/0 scope/0 scope/0 Forwards but returns scope/0
Neustar scope/0 scope/0 scope/0 Forwards but returns scope/0

Private IPv6 Results (RFC 4193, RFC 4291)
#

Provider ULA (fc00::/64) Link-Local (fe80::/64)
Google DNS REFUSED REFUSED
AdGuard DNS scope/64 scope/64

Observations
#

Google DNS consistently rejects private addresses (RFC 1918 IPv4, RFC 6598 CGNAT, and RFC 4193/4291 IPv6), while other providers handle them according to their normal ECS policies. This is worth noting for organizations that prefer their internal addressing not be included in ECS requests to authoritative servers. All echoing resolvers stripped host bits before echoing, but conservative providers still exposed the /24 client prefix even when they advertised scope/0.

Real-World Impact Analysis
#

Having examined the technical details of how different resolvers implement ECS, what does this mean for network administrators, CDN operators, and privacy-conscious users in practice?

For Network Administrators
#

  • Google DNS: Mirrors authoritative nameserver scope responses for all domains. Requires minimum subnet sizes of /24 for IPv4 and /56 for IPv6.
  • AdGuard DNS: Mirrors input scope in client responses while forwarding actual client subnet to authoritative servers
  • Conservative Providers: Process geographically but always return scope/0, maximizing privacy

For CDN Operators
#

  • Different resolvers provide varying levels of geographic precision feedback
  • Scope responses indicate resolver confidence in geographic accuracy
  • IPv6 ECS support is consistent across the resolvers that echo data, but non-echoing providers still limit end-to-end visibility

For Privacy-Conscious Users
#

  • “No echo” doesn’t mean “no processing” - most resolvers still use ECS for optimization
  • Conservative resolvers accept ECS but don’t reveal processing details
  • Google provides the strongest private address protection by rejecting private ranges (RFC 1918 IPv4, RFC 6598 CGNAT, RFC 4193/4291 IPv6)

Understanding ECS Behavior
#

RFC 7871 mandates that authoritative nameservers echo ECS in responses, but gives recursive resolvers flexibility in whether to echo back to clients. The specification explains scope prefix interpretation: scope values longer than the source indicate insufficient precision, while shorter values (including /0) indicate the answer applies to a broader range. This explains why conservative resolvers like Control D and Verisign return scope /0, signaling their responses apply broadly regardless of geographic precision.

Recommendations
#

When testing ECS behavior, use multiple subnet sizes and test against multiple authoritative servers, as resolver behavior can vary by domain. For IPv6 testing, use real addresses rather than RFC 3849 documentation addresses which may be filtered. Monitor scope responses to understand geographic precision confidence.

For implementations, consider the trade-offs between different approaches. Google’s mirroring approach provides transparency about authoritative responses, AdGuard mirrors input in client responses while using actual client subnets for authoritative queries, and conservative approaches process ECS without revealing implementation details.

Conclusions
#

This analysis reveals that ECS implementation is far more nuanced than a simple “supported” or “not supported” binary. The combination of ECS echo testing and authoritative server verification shows five distinct behavior patterns representing different approaches to balancing geographic optimization, transparency, and privacy. The internet’s DNS infrastructure shows different approaches to geographic intelligence. Understanding these differences helps network operators make informed decisions about resolver selection and CDN optimization strategies.

As internet infrastructure evolves, ECS implementation differences will continue to be important for performance optimization and privacy considerations. This analysis demonstrates the value of comprehensive, multi-dimensional testing in understanding real-world DNS behavior.

RFC 7871 acknowledges the complexity inherent in ECS implementations, noting that “the expectation, however, is that this option will primarily be used between Recursive Resolvers and Authoritative Nameservers that are sensitive to network location issues. Most Recursive Resolvers, Authoritative Nameservers, and Stub Resolvers will never need to know about this option and will continue working as they had been.”

However this assumption may no longer be true. Given the dominance of resolvers like Google (8.8.8.8), Quad9 (9.9.9.9) and Cloudflare (1.1.1.1), combined with widespread CDN usage, a substantial portion of global DNS queries likely involve ECS. As encrypted DNS protocols (DoH, DoT and hopefully soon DoQ) become more prevalent for stub-to-resolver communication, the privacy implications of ECS become increasingly relevant. While encryption between stubs and resolvers addresses one privacy concern, the resolver-to-authoritative path remains largely unencrypted, meaning ECS information is still transmitted in clear text. Encrypting resolver-to-authoritative communication could mitigate some of these privacy concerns, though deployment challenges remain.

Acknowledgements
#

I am grateful to Sara Dickinson and Stephen Strowes for taking the time to review drafts of this article and providing valuable feedback and corrections. Their insights significantly improved the accuracy and clarity of this analysis. Any remaining errors or inaccuracies are entirely my own.