Summary
WSL's DNS tunneling suffers from significant performance degradation because DnsQueryRaw bypasses the Windows DNS cache (by injecting DNS_QUERY_BYPASS_CACHE internally), and systemd-resolved — the only remaining caching layer — is compiled with Cache=no-negative on several major distros (Ubuntu 24.04, etc.). This means NODATA/NXDOMAIN responses (e.g., AAAA lookups for IPv4-only hosts) are never cached, causing every dual-stack lookup to pay a full DNS tunnel round-trip for the uncached negative response.
Reproduction Steps
- Use WSL 2 with Ubuntu 24.04 (systemd 255)
- Run
resolvectl statistics to observe cache state
- Run
dig github.com multiple times
- Observe that AAAA NODATA responses are never cached — cache misses remain high
Expected Behavior
Negative DNS responses (NODATA/NXDOMAIN) should be cached by systemd-resolved so that repeated lookups for the same hostname don't pay a full round-trip through the DNS tunnel each time.
Actual Behavior
Every AAAA lookup for an IPv4-only hostname results in a cache miss because systemd-resolved is configured (at compile time on Ubuntu) with Cache=no-negative, and since DnsQueryRaw bypasses the Windows DNS cache, there is no caching layer at all for these responses.
Benchmark Data (Ubuntu 24.04, systemd 255, WSL 2.7.1.0)
| Metric |
Cache=no-negative (default) |
Cache=yes (fix) |
| Avg latency (10 queries) |
24.0 ms |
10.1 ms |
| Cache hits / misses |
9 / 11 |
18 / 3 |
| Cache entries |
1 (A only) |
2 (A + AAAA NODATA) |
2.3× faster average, 9× fewer cache misses.
Root Cause Analysis
DnsResolver.cpp line 207 explicitly notes: "// N.B. All DNS requests will bypass the Windows DNS cache"
DnsQueryRaw injects DNS_QUERY_BYPASS_CACHE internally — this is documented Microsoft API behavior
- Ubuntu 24.04 compiles systemd-resolved with
Cache=no-negative (visible via resolvectl statistics)
- With the Windows cache bypassed and negative caching disabled, every dual-stack lookup (A + AAAA) for an IPv4-only host sends the AAAA query through the full tunnel every time
Proposed Fix
Write a systemd-resolved drop-in configuration at /run/systemd/resolved.conf.d/wsl-dns-cache.conf with Cache=yes during GenerateSystemdUnits() in init.cpp. This:
- Uses the same
UtilMkdirPath() + WriteToFile() pattern already used in HardenMirroredNetworkingSettingsAgainstSystemd()
- Is non-persistent (
/run is tmpfs, cleared on reboot)
- Is non-fatal (failure to write is silently ignored)
- Is distro-agnostic (only affects distros using systemd-resolved)
- Has zero impact on distros that don't use systemd-resolved
Related Issues
Environment
- WSL version: 2.7.1.0
- Windows version: Windows 11
- Distro: Ubuntu 24.04 (systemd 255)
- DNS tunneling: enabled (default)
Summary
WSL's DNS tunneling suffers from significant performance degradation because
DnsQueryRawbypasses the Windows DNS cache (by injectingDNS_QUERY_BYPASS_CACHEinternally), and systemd-resolved — the only remaining caching layer — is compiled withCache=no-negativeon several major distros (Ubuntu 24.04, etc.). This means NODATA/NXDOMAIN responses (e.g., AAAA lookups for IPv4-only hosts) are never cached, causing every dual-stack lookup to pay a full DNS tunnel round-trip for the uncached negative response.Reproduction Steps
resolvectl statisticsto observe cache statedig github.commultiple timesExpected Behavior
Negative DNS responses (NODATA/NXDOMAIN) should be cached by systemd-resolved so that repeated lookups for the same hostname don't pay a full round-trip through the DNS tunnel each time.
Actual Behavior
Every AAAA lookup for an IPv4-only hostname results in a cache miss because systemd-resolved is configured (at compile time on Ubuntu) with
Cache=no-negative, and sinceDnsQueryRawbypasses the Windows DNS cache, there is no caching layer at all for these responses.Benchmark Data (Ubuntu 24.04, systemd 255, WSL 2.7.1.0)
2.3× faster average, 9× fewer cache misses.
Root Cause Analysis
DnsResolver.cppline 207 explicitly notes: "// N.B. All DNS requests will bypass the Windows DNS cache"DnsQueryRawinjectsDNS_QUERY_BYPASS_CACHEinternally — this is documented Microsoft API behaviorCache=no-negative(visible viaresolvectl statistics)Proposed Fix
Write a systemd-resolved drop-in configuration at
/run/systemd/resolved.conf.d/wsl-dns-cache.confwithCache=yesduringGenerateSystemdUnits()ininit.cpp. This:UtilMkdirPath()+WriteToFile()pattern already used inHardenMirroredNetworkingSettingsAgainstSystemd()/runis tmpfs, cleared on reboot)Related Issues
0#9423 — DNS resolution performanceEnvironment