Skip to content

Commit ab7c069

Browse files
committed
Fix DNS performance: preserve TTLs and enable systemd-resolved caching
DnsQueryRaw internally bypasses the Windows DNS cache, causing all DNS responses tunneled to WSL to carry reset TTL values. This breaks downstream caching in systemd-resolved, leading to repeated wire queries for every DNS lookup — including negative (NODATA) responses for unsupported record types like AAAA on IPv4-only networks. This commit applies two complementary fixes: 1. Add DNS_QUERY_DONT_RESET_TTL_VALUES flag to DnsQueryRaw requests (DnsResolver.cpp) so that responses carry real decremented TTL values from upstream resolvers instead of reset-to-original values. 2. Write a systemd-resolved drop-in config enabling Cache=yes (init.cpp) to cache both positive and negative DNS responses. The default Cache=no-negative discards NODATA/NXDOMAIN answers, causing repeated wire queries for record types that will never resolve. Together these changes restore effective DNS caching for WSL, reducing redundant network round-trips and improving DNS resolution latency. Fixes: #14568 Related: #9423, #13415
1 parent 107104e commit ab7c069

2 files changed

Lines changed: 16 additions & 1 deletion

File tree

src/linux/init/init.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,15 @@ int GenerateSystemdUnits(int Argc, char** Argv)
336336
// Mask NetworkManager-wait-online.service for the same reason, as it causes timeouts on distros using NetworkManager.
337337
THROW_LAST_ERROR_IF(symlink("/dev/null", std::format("{}/NetworkManager-wait-online.service", installPath).c_str()) < 0);
338338

339+
// Enable DNS response caching in systemd-resolved. On some distros (notably Ubuntu) the default
340+
// Cache=no-negative discards negative (NODATA/NXDOMAIN) responses, which causes repeated wire
341+
// queries for unsupported record types (e.g. AAAA on IPv4-only networks). This override aligns
342+
// all distros with the upstream systemd default of Cache=yes, ensuring systemd-resolved provides
343+
// effective DNS caching inside the VM.
344+
THROW_LAST_ERROR_IF(UtilMkdirPath("/run/systemd/resolved.conf.d", 0755) < 0);
345+
constexpr auto* resolvedCacheConfig = "[Resolve]\nCache=yes\n";
346+
THROW_LAST_ERROR_IF(WriteToFile("/run/systemd/resolved.conf.d/wsl-dns-cache.conf", resolvedCacheConfig) < 0);
347+
339348
// Only create the wslg unit if both enabled in wsl.conf, and if the wslg folder actually exists.
340349
if (enableGuiApps && access("/mnt/wslg/runtime-dir", F_OK) == 0)
341350
{

src/windows/common/DnsResolver.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,11 @@ try
238238
// Only unicast UDP & TCP queries are tunneled. Pass this flag to tell Windows DNS client to *not* resolve using multicast.
239239
request.queryOptions |= DNS_QUERY_NO_MULTICAST;
240240

241+
// DnsQueryRaw bypasses the Windows DNS cache internally, which means all responses return with TTL values
242+
// reset to their original values. Pass this flag so that the DNS client preserves the real (decremented) TTL
243+
// values from cached upstream responses, enabling downstream caches (e.g. systemd-resolved) to use meaningful TTLs.
244+
request.queryOptions |= DNS_QUERY_DONT_RESET_TTL_VALUES;
245+
241246
// In a DNS request from Linux there might be DNS records that Windows DNS client does not know how to parse.
242247
// By default in this case Windows will fail the request. When the flag is enabled, Windows will extract the
243248
// question from the DNS request and attempt to resolve it, ignoring the unknown records.
@@ -253,7 +258,8 @@ try
253258
}
254259

255260
// Start the DNS request
256-
// N.B. All DNS requests will bypass the Windows DNS cache
261+
// N.B. DnsQueryRaw bypasses the Windows DNS cache; DNS_QUERY_DONT_RESET_TTL_VALUES is set above
262+
// so that responses carry real TTL values for downstream caching (e.g. systemd-resolved).
257263
const auto result = s_dnsQueryRaw.value()(&request, &localContext->m_cancelHandle);
258264
if (result != DNS_REQUEST_PENDING)
259265
{

0 commit comments

Comments
 (0)