WSL2 DNS Problems: The resolv.conf Fix That Survives Reboots

Was this helpful?

You open WSL2, run apt update, and it just… hangs. Or Docker pulls fail. Or your internal
Git remote vanishes unless the VPN is “just right.” You check /etc/resolv.conf, it looks
plausible, and yet DNS acts like it’s negotiating a union contract.

This is the WSL2 DNS story: Windows networking, a lightweight VM, VPN clients with opinions, and a file
(resolv.conf) that WSL2 regenerates when you’re not looking. The fix is not “edit the file.”
The fix is making WSL2 stop rewriting it, then choosing a DNS strategy that matches your reality and survives reboots.

What’s really happening when WSL2 “loses DNS”

WSL2 is not a compatibility layer. It’s a real Linux kernel running in a managed VM.
Your distro gets a virtual NIC on a private vSwitch; Windows sits on the other side doing the “uplink” work.
DNS inside WSL2, by default, is a chain of trust:

  • Linux apps call the libc resolver (or systemd-resolved, depending on your distro config).
  • The resolver reads /etc/resolv.conf (directly or indirectly).
  • By default, WSL2 auto-generates /etc/resolv.conf at boot from Windows’ view of DNS.
  • Windows’ view of DNS changes when you join Wi‑Fi, switch networks, connect/disconnect VPN, or get a new DHCP lease.
  • Some VPNs install DNS proxies, split DNS rules, or “NRPT” policies, and Windows will happily comply.
  • WSL2 may not update its generated config on-the-fly in the way you intuitively expect.

When things break, it’s usually one of these:

  • Stale DNS server IP in /etc/resolv.conf (common after sleep, VPN toggle, network switch).
  • Unreachable DNS server because the Windows-side DNS is a local proxy only Windows can talk to.
  • Split-horizon mismatch: Windows knows how to resolve internal domains via policy; WSL2 doesn’t.
  • IPv6 weirdness: Windows prefers IPv6 DNS, WSL2 resolver prefers IPv4, or vice versa.
  • Broken search domains: you rely on short names (git, jenkins) that require a search suffix.
  • Resolver race / caching: a local resolver caches the wrong thing and makes you think the network is haunted.

Editing /etc/resolv.conf “works” until reboot because WSL2 overwrites it. That’s not a bug.
That’s the default contract: Windows is the source of truth unless you explicitly take control.

Dry reality: DNS is the dependency you forget until it breaks, and then it breaks everything.
The fix is boring. And boring is good.

Interesting facts and historical context (the stuff that explains the pain)

  1. resolv.conf dates back decades: the file format came from early Unix resolver implementations and survived because everything depends on it.
  2. WSL1 and WSL2 are fundamentally different: WSL1 translated Linux syscalls; WSL2 runs a real kernel in a VM, which changes networking behavior dramatically.
  3. WSL2 originally used a NAT model by design: it’s isolated behind a virtual switch, so Windows is effectively the gateway and often the DNS “advisor.”
  4. systemd wasn’t always enabled in WSL: older WSL distros ran without systemd, so DNS behavior depended heavily on distro defaults and scripts.
  5. Corporate Windows DNS can be policy-driven: Windows supports name resolution policies and per-domain behavior that doesn’t map cleanly into a Linux guest without extra work.
  6. DNS search domains are a legacy convenience: short hostnames depend on search rules; they’re also a frequent source of “works on my laptop” failures.
  7. VPN clients commonly implement DNS “protection”: many route DNS through tunnel-only resolvers to prevent leaks, which can make guest VMs look like untrusted outsiders.
  8. DNS caching changed expectations: modern stacks cache aggressively (systemd-resolved, nscd, browser caches). You can fix DNS and still see stale results.
  9. Windows and Linux prefer different tools: Windows leans on system services and policy; Linux expects explicit servers in resolv.conf. WSL2 sits awkwardly between the two.

Fast diagnosis playbook (first/second/third)

When production is on fire you don’t “explore.” You bisect. Here’s the fastest path to the truth.

First: is it DNS, routing, or the app?

  • Test raw IP reachability (ping gateway / known IP).
  • Test DNS resolution for a public domain and an internal domain.
  • Compare Windows resolution vs WSL2 resolution.

Second: is WSL2 using a stale or unreachable nameserver?

  • Read /etc/resolv.conf.
  • Try to contact the nameserver IP on port 53 (UDP/TCP tests).
  • Check if the nameserver is a Windows-local proxy address that WSL2 can’t reach.

Third: is this split DNS / VPN policy?

  • Resolve internal names with Windows tools and compare.
  • Check search domains and per-domain DNS expectations.
  • Decide: do you need a local resolver in WSL2, or can you point directly to corporate resolvers?

Decision rule: if the nameserver in /etc/resolv.conf is unreachable or stale, stop fighting symptoms.
Take control of how resolv.conf is generated. That’s the lever.

Practical tasks: commands, expected output, and decisions

These are the checks I actually run. Not because I enjoy typing, but because guessing is expensive.
Each task includes: command, what output means, and what decision it drives.

Task 1: Confirm you’re actually in WSL2 (not WSL1)

cr0x@server:~$ uname -r
5.15.133.1-microsoft-standard-WSL2

Meaning: If you see microsoft-standard-WSL2, you’re in WSL2.
WSL1 behaves differently and doesn’t have the same VM DNS edge cases.
Decision: If you’re not on WSL2, stop and adjust expectations; this article targets WSL2.

Task 2: Check the current resolver configuration

cr0x@server:~$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.26.112.1
search corp.example

Meaning: That comment tells you WSL is auto-generating the file. The nameserver is often a virtual gateway address.
Decision: If DNS breaks after reboots or VPN toggles, you need to disable generation and own this file.

Task 3: Resolve a public name quickly (does DNS work at all?)

cr0x@server:~$ getent ahosts example.com | head
93.184.216.34    STREAM example.com
93.184.216.34    DGRAM
93.184.216.34    RAW

Meaning: getent tests the system resolver path (NSS), not just a single tool.
Decision: If this fails, DNS is broadly broken. If it works but internal names fail, think split DNS/search domains.

Task 4: Confirm an internal name fails the way you think it fails

cr0x@server:~$ getent hosts git

Meaning: No output typically means “not resolved,” not “network down.”
Decision: If git fails but git.corp.example works, your search line is missing/wrong.

Task 5: Use dig to see the resolver’s opinion (timeouts vs NXDOMAIN)

cr0x@server:~$ dig +time=2 +tries=1 git.corp.example

; <<>> DiG 9.18.24-1ubuntu1.4-Ubuntu <<>> +time=2 +tries=1 git.corp.example
;; connection timed out; no servers could be reached

Meaning: Timeout means you can’t reach the configured DNS server(s). That’s different from NXDOMAIN.
Decision: Timeouts push you toward “nameserver unreachable/stale.” NXDOMAIN pushes you toward “wrong DNS server for that domain.”

Task 6: Identify the nameserver IP WSL2 is using

cr0x@server:~$ awk '/^nameserver/{print $2}' /etc/resolv.conf
172.26.112.1

Meaning: You want the exact IP to test connectivity.
Decision: If it’s a 172/10/192 private address, it’s likely the WSL2/Windows virtual gateway or a VPN-side resolver.

Task 7: Test connectivity to DNS server (UDP and TCP)

cr0x@server:~$ NS=$(awk '/^nameserver/{print $2; exit}' /etc/resolv.conf); echo $NS
172.26.112.1
cr0x@server:~$ nc -vz -w2 $NS 53
nc: connect to 172.26.112.1 port 53 (tcp) failed: Connection timed out

Meaning: TCP 53 timeout is a strong hint the server isn’t reachable from the guest.
UDP is harder to test with nc, but TCP failure already smells bad.
Decision: If port 53 isn’t reachable, stop chasing resolver config inside apps. Fix the path to DNS.

Task 8: Verify you have basic routing (is it DNS or network?)

cr0x@server:~$ ip route
default via 172.26.112.1 dev eth0
172.26.112.0/20 dev eth0 proto kernel scope link src 172.26.121.45

Meaning: Default route via the same IP as your nameserver is common in WSL2. If this route is missing, you’ve got bigger issues than DNS.
Decision: If routing is broken, restarting WSL or the network stack is step zero.

Task 9: Check for systemd-resolved and how it’s wired

cr0x@server:~$ ps -ef | grep -E 'systemd-resolved|named|dnsmasq' | grep -v grep
root         330       1  0 09:12 ?        00:00:00 /lib/systemd/systemd-resolved

Meaning: If systemd-resolved is running, your resolver may not be reading /etc/resolv.conf in the way you assume.
Decision: Decide whether to use systemd-resolved properly (recommended if you need split DNS), or keep it simple with a static resolv.conf.

Task 10: Inspect the current /etc/resolv.conf target (file vs symlink)

cr0x@server:~$ ls -l /etc/resolv.conf
-rw-r--r-- 1 root root 188 Feb  5 09:40 /etc/resolv.conf

Meaning: If it’s a symlink to systemd’s stub file, you troubleshoot differently.
Decision: Plain file means WSL wrote it (or you did). Symlink often means systemd-resolved owns it.

Task 11: Compare Windows DNS behavior (from inside WSL)

cr0x@server:~$ cat /etc/resolv.conf | sed -n '1,5p'
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.26.112.1

Meaning: You can’t run PowerShell in this bash block per our format constraints, but you can still reason:
if Windows is using a DNS proxy (common with VPN), WSL might be pointing at something that only Windows can reach reliably.
Decision: If corporate VPN is involved, plan for a stable, explicit DNS setup.

Task 12: Restart WSL2 cleanly (force regeneration tests)

cr0x@server:~$ wsl.exe --shutdown
The operation completed successfully.

Meaning: This shuts down all WSL instances. Next launch is a cold start.
Decision: Use this as your “did my fix survive reboot?” test loop.

Task 13: Prove the file is being overwritten (before you disable it)

cr0x@server:~$ sudo sh -c 'echo "# test-marker" >> /etc/resolv.conf'
cr0x@server:~$ tail -n 3 /etc/resolv.conf
search corp.example
# test-marker

Meaning: Now shut down WSL and restart. If the marker disappears, WSL regenerated it.
Decision: If overwritten, you must disable generation. Anything else is theater.

Task 14: Validate that DNS works after switching resolvers

cr0x@server:~$ dig +short example.com
93.184.216.34
cr0x@server:~$ dig +short git.corp.example
10.40.12.23

Meaning: You want both public and internal resolution to succeed consistently.
Decision: If public works but internal fails, your DNS server choice is wrong for split-horizon needs.

One quote to keep you honest: “Hope is not a strategy” — commonly attributed to operations culture (paraphrased idea).
DNS troubleshooting is exactly where “hope” shows up disguised as “maybe it’ll work after reconnecting the VPN.”

The resolv.conf fix that survives reboots (recommended paths)

There are three workable strategies. Pick one. Mixing them is how you create a “sometimes” system, and “sometimes” is the worst SLA.

Strategy A (recommended for most people): Disable auto-generation and write a static resolv.conf

This is the simplest fix when you can point directly to stable DNS servers (public resolvers, your router, or corporate resolvers reachable on your current network/VPN).
It also survives reboots because you stop WSL from rewriting the file.

Step 1: Stop WSL from generating resolv.conf

cr0x@server:~$ sudo tee /etc/wsl.conf >/dev/null <<'EOF'
[network]
generateResolvConf = false
EOF

Meaning: WSL reads /etc/wsl.conf at instance start. This tells it to leave /etc/resolv.conf alone.
Decision: If you need stability more than “auto-adapt to random networks,” this is your move.

Step 2: Create your own resolv.conf

cr0x@server:~$ sudo rm -f /etc/resolv.conf
cr0x@server:~$ sudo tee /etc/resolv.conf >/dev/null <<'EOF'
nameserver 10.10.0.53
nameserver 10.10.0.54
search corp.example
options timeout:2 attempts:2 rotate
EOF
cr0x@server:~$ sudo chmod 644 /etc/resolv.conf

Meaning: Two nameservers, a search domain, and conservative timeouts so failures fail fast instead of stalling builds.
Decision: If you don’t have stable internal DNS IPs, don’t guess. Get them from your network/VPN team or from Windows adapter details.

Step 3: Restart WSL to apply

cr0x@server:~$ wsl.exe --shutdown
The operation completed successfully.

Launch the distro again and retest resolution (Task 14). If it survives multiple restarts, you’re done.

Joke #1: DNS is like office coffee—nobody funds it properly until the day it stops, and then it’s suddenly everyone’s top priority.

Strategy B: Use systemd-resolved inside WSL2 for split DNS (when corp VPN rules matter)

If you have split-horizon DNS (internal domains must go to internal resolvers, everything else goes public),
a static resolv.conf can be too blunt. systemd-resolved can handle per-domain routing in a principled way.
But you must wire it correctly, or you’ll get the worst of both worlds: caching plus wrong servers.

High-level approach:

  • Disable WSL’s resolv.conf generation.
  • Make /etc/resolv.conf point to systemd’s stub resolver (127.0.0.53) or the resolved-managed file.
  • Configure systemd-resolved with the right DNS servers and routing domains.

Step 1: Confirm systemd is available/active

cr0x@server:~$ ps -p 1 -o comm=
systemd

Meaning: PID 1 is systemd. If it’s not, enabling resolved becomes a different conversation.
Decision: If systemd isn’t running, prefer Strategy A unless you’re ready to re-plumb the distro.

Step 2: Configure resolved

cr0x@server:~$ sudo tee /etc/systemd/resolved.conf >/dev/null <<'EOF'
[Resolve]
DNS=10.10.0.53 10.10.0.54
FallbackDNS=1.1.1.1 8.8.8.8
Domains=~corp.example corp.example
DNSSEC=no
EOF
cr0x@server:~$ sudo systemctl restart systemd-resolved

Meaning: Domains=~corp.example makes it a routing domain: queries for that zone go to your corporate DNS.
The plain corp.example sets a search domain for convenience.
Decision: Use this when your VPN requires internal names to resolve internally but public DNS should stay fast.

Step 3: Point /etc/resolv.conf to resolved

cr0x@server:~$ sudo rm -f /etc/resolv.conf
cr0x@server:~$ sudo ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
cr0x@server:~$ ls -l /etc/resolv.conf
lrwxrwxrwx 1 root root 39 Feb  5 10:02 /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf

Meaning: Apps read /etc/resolv.conf, hit 127.0.0.53, and resolved makes the smart decisions.
Decision: If you see weird caching, you now know where it lives (resolved), and you can flush it.

Strategy C: Make resolv.conf immutable (effective, but I don’t love it)

Yes, you can slap chattr +i on /etc/resolv.conf. It can stop overwrites even if you forget wsl.conf.
It’s also a footgun: future you (or your automation) will fail to update DNS and waste time debugging permissions.

cr0x@server:~$ sudo chattr +i /etc/resolv.conf
cr0x@server:~$ lsattr /etc/resolv.conf
----i--------e----- /etc/resolv.conf

Meaning: The immutable bit is set.
Decision: Only use this if you have a controlled environment and you understand the tradeoff. Otherwise: disable generation properly.

Joke #2: Setting chattr +i on resolv.conf is like supergluing the thermostat—quietly satisfying until facilities management finds out.

VPN, corporate DNS, and split-horizon: don’t guess

Corporate DNS is rarely just “a couple of nameservers.” It’s policy. It’s conditional forwarding. It’s internal zones that should never leak to the public internet.
VPN clients often enforce this by funneling DNS through:

  • a resolver only reachable on the VPN tunnel,
  • a Windows-local DNS proxy bound to loopback or a virtual adapter,
  • per-domain rules that Windows honors but Linux inside WSL2 never sees.

The failure mode looks like this:

  • Windows resolves git.corp.example fine.
  • WSL2 times out or returns NXDOMAIN.
  • You edit resolv.conf, it works for a moment, then resets.
  • After sleep/resume, it breaks again.

The key decision is: do you need split DNS inside WSL2?

  • If you only need public internet resolution: static resolv.conf pointing to public DNS is fine.
  • If you need internal corp zones: point to corporate resolvers that are actually reachable from WSL2, or run a local resolver with proper routing domains.
  • If your VPN only exposes DNS via a Windows-local proxy: you may need to point WSL2 at a reachable address (sometimes the WSL gateway), or use systemd-resolved and feed it the right servers.

If your environment changes networks often (laptop life), static resolv.conf can be “too stable.”
But here’s the practical reality: WSL2’s auto-generation is not the same as “dynamic DNS that always stays correct.”
It’s “best effort at boot.” If your day includes VPN toggles and sleeps, you want explicit control.

Three corporate mini-stories from the DNS trenches

Mini-story 1: The incident caused by a wrong assumption

A product team had a WSL2-based developer image: Ubuntu, Docker tooling, a few internal CLI utilities.
It worked in the office. It worked on home Wi‑Fi. It even worked on the VPN—most of the time.
Then an on-call rotation started using it for a staging incident, and suddenly half the team couldn’t resolve internal hostnames.

The wrong assumption was subtle: “If Windows can resolve it, WSL2 can resolve it.”
On Windows, the VPN client installed per-domain DNS policies and routed corp.example to internal resolvers,
while leaving public domains on the local ISP DNS. Windows name resolution was policy-aware.
WSL2 was not; it inherited a generated resolv.conf at launch that pointed to a gateway IP that wasn’t reliably forwarding DNS under VPN.

The team tried the usual ritual: restart VPN, restart WSL, flush caches, try again.
They got intermittent success, which is worse than consistent failure because it wastes hours and builds false confidence.
One engineer “fixed” it by hardcoding a public DNS server, which solved public names and silently broke internal resolution.

The real fix was to stop auto-generation and explicitly configure split DNS using systemd-resolved:
internal zones routed to corporate resolvers, fallback DNS for the rest, and a clear test plan.
After that, the bug reports stopped. Not because DNS became magical, but because the assumptions were removed from the system.

Mini-story 2: The optimization that backfired

Another organization ran large dependency installs inside WSL2 during CI-like local workflows. Someone noticed DNS lookups were “slow”
and decided to optimize by cranking resolver attempts and adding multiple public nameservers “for redundancy.”
They added four nameservers and set attempts:5 and timeout:5.

In the lab, it looked resilient. In the real world, it created a perfect storm:
when the first nameserver became unreachable on VPN, every lookup paused for 25 seconds before failing over.
Multiply that by package repositories, container registries, and internal service discovery.
The laptop fans spun up, developers blamed Docker, and the VPN team got dragged into meetings.

The backfire was classic: “redundancy” with long timeouts is not redundancy; it’s latency amplification.
A resolver can only be as fast as its slowest failure.
Adding more nameservers without tightening timeouts just increases the number of slow failures you’ll wait through.

The fix was boring: two nameservers max, short timeouts, and explicit split DNS so internal queries didn’t wander into public resolvers.
Once they measured again, the “DNS slowness” disappeared—because it had been self-inflicted.

Mini-story 3: The boring but correct practice that saved the day

A platform team maintained a standard WSL2 bootstrap for engineers.
They did something deeply unsexy: they wrote a one-page runbook with three commands to verify DNS, plus a canonical resolv.conf strategy.
No heroics. No “just reboot.” Everything was testable.

One Monday, a Windows update and a VPN client update landed close together. Suddenly, a chunk of engineers couldn’t resolve internal domains from WSL2.
Instead of everyone trying random fixes, they followed the runbook:
check current nameserver, test port 53 reachability, compare internal vs public lookups.

The diagnosis was consistent across machines: WSL2 was being handed a nameserver IP that was only valid when a specific VPN adapter was up.
After sleep/resume, the adapter came up late, WSL2 started early, and resolv.conf was generated with an unreachable server.
The “fix” wasn’t to fight timing. It was to disable generation and use stable corporate DNS IPs reachable over the tunnel.

They pushed an update to their bootstrap: set generateResolvConf = false, deploy a resolv.conf template,
and include a quick verification step. The outage turned into a minor annoyance, mostly because the practice was repeatable and dull.
Dull beats exciting when you’re trying to ship.

Common mistakes: symptom → root cause → fix

1) “It works until I reboot WSL”

Symptom: You edit /etc/resolv.conf, DNS works, then breaks after restart.

Root cause: WSL auto-generates resolv.conf at startup and overwrites your changes.

Fix: Add generateResolvConf = false in /etc/wsl.conf, then write your own resolv.conf.

2) “Public domains resolve, internal domains fail”

Symptom: example.com works; git.corp.example returns NXDOMAIN or times out.

Root cause: You’re using public DNS servers that don’t know internal zones, or your split DNS policy isn’t replicated in WSL.

Fix: Point WSL at corporate resolvers (reachable on VPN) or use systemd-resolved with routing domains (~corp.example).

3) “Internal FQDN works, short hostname doesn’t”

Symptom: getent hosts git.corp.example works; getent hosts git fails.

Root cause: Missing or wrong search domain in resolv.conf (or resolved config).

Fix: Add search corp.example (or set Domains=corp.example in resolved).

4) “DNS is slow, builds hang, but eventually succeed”

Symptom: Commands pause for seconds per lookup; sometimes minutes during package installs.

Root cause: Long resolver timeouts, too many nameservers, unreachable first server, or TCP fallback delays.

Fix: Use 1–2 reachable nameservers, set options timeout:2 attempts:2. Ensure port 53 reachability to the chosen servers.

5) “It broke after connecting to VPN”

Symptom: DNS fails immediately after VPN connect/disconnect.

Root cause: Windows DNS changed to VPN-provided servers/proxies; WSL resolv.conf didn’t update correctly or updated to an unreachable proxy.

Fix: Disable auto-generation and explicitly set DNS servers appropriate for VPN mode; consider systemd-resolved for split DNS.

6) “It only fails after sleep/resume”

Symptom: Morning laptop wake-up = DNS timeout party inside WSL.

Root cause: The WSL VM resumes with stale network state; resolv.conf points to a gateway/proxy that isn’t ready.

Fix: wsl.exe --shutdown and restart; long-term fix is stable DNS configuration not tied to a transient gateway/proxy.

7) “I set chattr +i and now nothing can change resolv.conf”

Symptom: Updates or scripts fail editing resolv.conf; you get permission errors even as root.

Root cause: Immutable attribute set.

Fix: sudo chattr -i /etc/resolv.conf, then manage resolv.conf properly via /etc/wsl.conf and your chosen strategy.

8) “nslookup works but apt still fails”

Symptom: One tool resolves; another tool times out.

Root cause: Different resolver paths (NSS vs direct queries), caching layers, or IPv6/IPv4 preference differences.

Fix: Use getent for system path; verify /etc/nsswitch.conf includes dns for hosts; validate both A and AAAA records with dig.

Checklists / step-by-step plan

Checklist 1: The “make it stop breaking after reboot” plan (static DNS)

  1. Inspect current /etc/resolv.conf and capture the current nameserver IP.
  2. Test reachability to that nameserver on TCP 53. If it times out, stop blaming apt.
  3. Create /etc/wsl.conf with generateResolvConf = false.
  4. Replace /etc/resolv.conf with two stable nameservers and your search domain.
  5. Restart WSL with wsl.exe --shutdown.
  6. Validate: resolve a public domain and an internal domain. Repeat after another restart.

Checklist 2: The “I’m on corporate VPN and split DNS matters” plan (systemd-resolved)

  1. Confirm systemd is PID 1 (or accept that you’ll use static DNS).
  2. Disable WSL resolv.conf generation.
  3. Configure /etc/systemd/resolved.conf with corporate DNS as DNS=, public as FallbackDNS=, and routing domain ~corp.example.
  4. Symlink /etc/resolv.conf to /run/systemd/resolve/stub-resolv.conf.
  5. Restart systemd-resolved and re-test with dig for both internal and public names.
  6. When debugging: flush caches (restart resolved) and re-run queries to confirm behavior.

Checklist 3: The “it’s 2am and I need it working now” plan

  1. Run getent ahosts example.com. If it fails, this is broad DNS.
  2. Check /etc/resolv.conf nameserver IP and test TCP 53 connectivity.
  3. If unreachable: temporarily set resolv.conf to a known reachable DNS (public or corp) and finish the incident.
  4. After the incident: implement Strategy A or B properly so you’re not repeating this next week.

FAQ

1) Why does WSL2 keep rewriting /etc/resolv.conf?

Because by default WSL2 treats Windows as the network authority and generates resolv.conf at instance start.
You disable it with generateResolvConf = false in /etc/wsl.conf.

2) What’s the safest “set it and forget it” fix?

Strategy A: disable auto-generation and point to stable nameservers you control and can reach.
Add reasonable timeouts. Validate after multiple restarts.

3) Should I point WSL2 DNS to 8.8.8.8 or 1.1.1.1?

Only if you do not need corporate internal zones, and your organization permits it.
If you need internal names, use corporate resolvers (or split DNS with systemd-resolved).

4) My /etc/resolv.conf has a 172.x address. Is that wrong?

Not automatically. It’s often the WSL2 gateway or a DNS forwarder.
It becomes “wrong” when it’s unreachable, stale, or doesn’t forward correctly under VPN conditions.
Test port 53 reachability and actual resolution, not vibes.

5) Why do I see timeouts instead of NXDOMAIN?

Timeout means your resolver couldn’t contact any DNS server. That’s network path or firewall policy.
NXDOMAIN means you reached a DNS server and it told you the name doesn’t exist (or not in that DNS view).

6) Can I fix this by restarting WSL every time?

You can, and people do. It’s also how you end up with tribal knowledge instead of a system.
Restarting is a diagnostic step; stable config is the fix.

7) Does systemd-resolved help, or does it just add complexity?

Both. It helps when you need split DNS or consistent caching behavior. It adds complexity when all you needed was two static nameservers.
Use it intentionally, not because you saw a blog post.

8) What about Docker inside WSL2—does that change DNS?

It can. Containers have their own DNS behavior and may inherit from the host’s resolver or use embedded DNS in the container network.
Fix WSL2 host DNS first. Then validate container resolution separately if issues persist.

9) Why does it break only on one Wi‑Fi network?

Different networks hand out different DNS servers, different IPv6 settings, and different captive portal behaviors.
Auto-generated resolv.conf can pick up a “works for Windows, weird for WSL” configuration. Stable explicit DNS avoids this.

10) If I disable generation, will WSL2 ignore Windows DNS changes forever?

Yes. That’s the point. If you roam between networks and depend on auto-adapting DNS, you’ll need a strategy to update your config deliberately
(or use a resolver that can ingest policy), not accidentally.

Conclusion: next steps you can actually do today

If WSL2 DNS breaks after reboots, you don’t have a “Linux problem.” You have an ownership problem.
WSL is generating /etc/resolv.conf from a Windows network view that changes under your feet.
Your edits disappear because they were never in control.

Do this next, in order:

  1. Run the fast diagnosis playbook once. Confirm whether the nameserver is stale/unreachable or the domain is split-DNS.
  2. Implement Strategy A (static resolv.conf) if you can use stable reachable DNS servers. It’s the least moving parts.
  3. Implement Strategy B (systemd-resolved) if you need split-horizon DNS. Route internal domains explicitly.
  4. Test after wsl.exe --shutdown twice. If it only works “sometimes,” you’re not done.

The goal is not to have DNS “working right now.” The goal is to have DNS working tomorrow morning after sleep, after VPN, after the next update,
without you performing rituals. Production systems don’t accept rituals. Your dev environment shouldn’t either.

← Previous
Restore Points Are Missing: The Setting Windows Keeps Turning Off
Next →
Proxmox CPU Pinning Myths — The Setting That Makes Latency Worse

Leave a comment