# Wsl Networking Mode Dns Fallback

> When WSL's mirrored networking fails and falls back to "None", plus /etc/wsl.conf has generateResolvConf=false, the distro has no DNS; fix both layers.

- Skill: `chen3feng/wsl-networking-mode-dns-fallback` (Agent Skill)
- Install (CLI): `npx skillmds@latest add chen3feng/wsl-networking-mode-dns-fallback`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chen3feng/wsl-networking-mode-dns-fallback/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: chen3feng (https://skillmd.com/u/chen3feng)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/chen3feng/wsl-networking-mode-dns-fallback

---


# WSL networking fallback leaves the distro with no DNS

## When to use

You're running something in a WSL2 distro from Windows (apt-get, curl,
git clone, cmake fetching deps, a CI sweep script) and it fails at
name resolution:

- `Temporary failure resolving 'archive.ubuntu.com'`
- `curl: (6) Could not resolve host: github.com`
- `apt-get update` prints `W: Failed to fetch ... Temporary failure resolving`
- `getent hosts <anything>` returns nothing, exit code 2.

And you see one or both of these on WSL startup:

- `wsl: An internal error occurred. Error code: CreateInstance/CreateVm/ConfigureNetworking/0x8007054f`
- `wsl: Failed to configure network (networkingMode Mirrored), falling back to networkingMode None.`

This is **not** a transient DNS glitch. The distro is actually
networkless, and `/etc/resolv.conf` is either missing or stale.

## Problem

Two independent misconfigurations combine into a total outage:

1. **`networkingMode = mirrored` in `%USERPROFILE%\.wslconfig`.**
   Mirrored mode depends on Hyper-V virtual-switch features that
   fail on some Windows builds / VPN / antivirus setups with
   `ConfigureNetworking/0x8007054f`. WSL then "helpfully" falls
   back to `networkingMode = None`, which means **no NAT, no vEthernet,
   nothing** — the distro only has `lo` and cannot reach the host
   network, let alone the internet.
   - `ip addr` inside the distro shows only `lo` and sometimes a
     leftover `10.255.255.254/32` on `lo` (the old mirrored address).
   - `ping 8.8.8.8` → `Network is unreachable`.

2. **`generateResolvConf = false` in `/etc/wsl.conf`.**
   With that flag, WSL will *not* rewrite `/etc/resolv.conf` on boot.
   Whatever state the file was last left in persists — and if it
   was a broken symlink (a common leftover from distros like
   `systemd-resolved` experiments), `cat /etc/resolv.conf` prints
   `No such file or directory`, and every lookup fails regardless
   of the underlying network.

Either one alone would break DNS. Together they look like "WSL is
totally broken" and the error messages don't point at either
config file.

## Solution

Fix the two layers in order. All commands run from **Windows
PowerShell** on the host; the `wsl -u root` ones execute inside the
distro.

### Step 1 — Disable mirrored networking in `.wslconfig`

Edit `%USERPROFILE%\.wslconfig` (create it if missing) and either
delete the mirrored block or comment it out:

```ini
# [wsl2]
# networkingMode=mirrored
```

Keep a backup so you can restore it later once the host-side bug is
resolved:

```powershell
Copy-Item $env:USERPROFILE\.wslconfig $env:USERPROFILE\.wslconfig.bak-mirrored
```

### Step 2 — Re-enable resolv.conf generation inside the distro

```powershell
wsl -d <Distro> -u root -- bash -lc @'
cp /etc/wsl.conf /etc/wsl.conf.bak 2>/dev/null || true
sed -i 's/^generateResolvConf\s*=.*/generateResolvConf = true/' /etc/wsl.conf
echo '--- /etc/wsl.conf ---'; cat /etc/wsl.conf
rm -f /etc/resolv.conf
'@
```

If `/etc/wsl.conf` didn't already have a `[network]` section, add one:

```powershell
wsl -d <Distro> -u root -- bash -lc @'
grep -q "^\[network\]" /etc/wsl.conf || printf "\n[network]\ngenerateResolvConf = true\n" >> /etc/wsl.conf
'@
```

### Step 3 — Shut down and restart WSL

```powershell
wsl --shutdown
Start-Sleep -Seconds 3
```

The next `wsl` invocation creates a fresh VM that (a) uses default
NAT networking instead of mirrored, and (b) regenerates
`/etc/resolv.conf` automatically.

### Step 4 — Verify, in this exact order

Verifying piece-by-piece saves you from chasing red herrings later:

```powershell
wsl -d <Distro> -- bash -lc @'
echo "--- resolv.conf ---"; cat /etc/resolv.conf 2>/dev/null || echo MISSING
echo "--- interfaces ---"; ip -o -4 addr show
echo "--- DNS ---"; getent hosts archive.ubuntu.com || echo DNS_FAIL
echo "--- HTTP ---"; curl -sS -o /dev/null -w "status=%{http_code} time=%{time_total}s\n" http://archive.ubuntu.com/ubuntu/dists/noble/InRelease
'@
```

All four must succeed:

| Check | Healthy output |
|---|---|
| `resolv.conf` | non-empty, starts with the "automatically generated by WSL" comment or a `nameserver` line |
| `ip addr` | shows `eth0` with a routable address (e.g. `172.x.y.z/20`), not just `lo` |
| `getent hosts` | returns one or more IPs |
| `curl` | `status=200` |

If `resolv.conf` comes back but HTTP still fails, the problem is
upstream (corporate proxy, VPN split-tunnel) and not WSL.

## Example

Symptoms the reporter actually saw:

```text
W: Failed to fetch http://archive.ubuntu.com/ubuntu/dists/noble/InRelease
   Temporary failure resolving 'archive.ubuntu.com'

cat: /etc/resolv.conf: No such file or directory
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 ...
    inet 127.0.0.1/8 scope host lo
    inet 10.255.255.254/32 brd 10.255.255.254 scope global lo
DNS_FAIL
```

Notice the three smoking guns, all visible at once:

- only `lo` in `ip addr` (no `eth0`) → networkingMode fell back to None,
- `10.255.255.254/32` on `lo` → ghost of the failed mirrored mode,
- `/etc/resolv.conf` missing → `generateResolvConf = false`.

After Steps 1-3, the same diagnostics show `eth0` with a `172.x` IP,
`nameserver 10.255.255.254` in `resolv.conf` (now a regular file, not
a dead symlink), and `curl` returns `status=200`.

## Pitfalls

- **The fallback message is not harmless noise.** Earlier advice
  (including a line in the `wsl-bash-crlf-or-tempfile` skill)
  suggested the `Failed to configure network (networkingMode Mirrored),
  falling back to networkingMode None` banner can be ignored — that's
  true only if `None` happens to give you a working interface. On
  many hosts `None` means **no network at all**; treat the banner as
  a hard error and disable mirrored.
- **`wsl --shutdown` is mandatory.** Editing `.wslconfig` or
  `/etc/wsl.conf` without shutting down the VM does nothing; the
  running VM keeps the old config. Always shutdown + pause a few
  seconds before re-entering.
- **Don't just `echo nameserver 8.8.8.8 > /etc/resolv.conf`.** That
  "works" for five minutes, then WSL (or the user's next
  `wsl --shutdown`) overwrites or re-breaks it. Fix the generator
  flag, not the generated file.
- **Check for a broken symlink, not just a missing file.** A dangling
  `/etc/resolv.conf -> ../run/systemd/resolve/stub-resolv.conf` looks
  like a missing file to `cat` but like a present file to `rm` — use
  `ls -la /etc/resolv.conf` before deciding what to do, and `rm -f`
  handles both cases.
- **Mirrored mode is still useful when it works.** Once you've
  confirmed the rest of the toolchain runs under NAT, you can try
  re-enabling mirrored on a future Windows update; keep the `.bak`
  around so you can flip back with a single copy.
- **Corporate VPN split-tunnel is a separate failure mode.** If
  `resolv.conf` is healthy and `eth0` has an IP but `curl` still
  times out, suspect VPN routing; that's out of scope for this
  skill.

## See also

- [wsl-bash-crlf-or-tempfile](../wsl-bash-crlf-or-tempfile/SKILL.md) —
  sibling skill about CRLF contamination when driving WSL from
  PowerShell; the two failure modes often appear together in
  cross-platform sweep scripts.
- [workspace-path-constraints](../workspace-path-constraints/SKILL.md) —
  related Windows ↔ WSL boundary gotchas.

