Skip to content

Unable to reach WSL from Windows with mirrored networking mode #13013

Open

Description

@gaac510

Windows Version

Microsoft Windows [Version 10.0.26100.4202]

WSL Version

2.5.7.0

Are you using WSL 1 or WSL 2?

  • WSL 2
  • WSL 1

Kernel Version

6.6.87.1-1

Distro Version

Ubuntu 24.04

Other Software

No response

Repro Steps

Preparation

  1. Set WSL to use mirrored networking mode, make sure systemd is enabled, and leave everything else default.
  2. Reboot Windows to make sure the settings take effect. (The reboot has been necessary for me, I'm not sure about everyone else's situation.)

Scenario A - Docker 101 served from port 80

In WSL, run docker run --rm -p 80:80 docker/getting-started to start serving Docker 101 tutorial from port 80.

Scenario B - Serve a Next.js dev app from port 3000

  1. In WSL, run npx create-next-app@latest to create a Next.js app.
  2. cd into the project directory, and run npm run dev to start a dev server at port 3000.

Scenario C - Serving various Supabase services with Docker from port 5432*

  1. In WSL, run npx create-next-app@latest to create a Next.js app.
  2. cd into the project directory, and run npm install supabase --save-dev to install Supabase as a project dev dependency.
  3. Run npx supabase init and then npx supabase start to start various containerised services - they should occupy port 54321, 54323 and 54324.

Expected Behavior

These URLs should all be reachable from both within WSL and from host Windows:

Actual Behavior

  • All URLs listed were only reachable from within WSL.
  • Loading any of the URLs in MS Edge running in host Windows resulted in (address differed for each URL):
    Hmmm… can't reach this page
    localhost refused to connect.
    
    Try:
    Search the web for [localhost](https://www.bing.com/search?form=ANLKDR&q=localhost)
    Checking the connection
    [Checking the proxy and the firewall](chrome-error://chromewebdata/#buttons)
    
    ERR_CONNECTION_REFUSED
    
    I also tried requesting using Bruno, and I always got connect ETIMEDOUT 127.0.0.1:3000 (port differed for each URL).

Additional troubleshooting I've done

  • Installed a brand-new Ubuntu 24.04 distro and tested from there - got same issue.
  • Changed to NAT networking mode while leaving everything else unchanged - didn't get the same issue, i.e. can reach WSL from Windows.
  • Tried systemctl disable network-manager.service and systemctl disable NetworkManager.service - neither worked since neither service existed.
  • Realised there's systemd-networkd.service and it was already disabled; in vain hope, tried enabling & starting the service and then stopping & disabling the service - in the end, nothing changed i.e. still got the same issue.
  • Tried both Hyper-V firewall commands noted at https://learn.microsoft.com/en-us/windows/wsl/networking#mirrored-mode-networking - made no difference i.e. still got the same issue.
  • Played with disabling/enabling the "Hyper-V" and/or the "Windows Hypervisor Platform" Windows features - made no difference i.e. still got the same issue.

Diagnostic Logs

WslNetworkingLogs-2025-05-30_21-43-52.zip

Activity

  1. github-actions commented on May 30, 2025

    @github-actions
    Contributor
    Diagnostic information
    .wslconfig found
    Detected appx version: 2.5.7.0
    optional-components.txt not found
    
  2. IbrahimTanyalcin commented on Jun 2, 2025

    @IbrahimTanyalcin

    I have an unrelated issue across devices on WSL2 even with older docker images that used to work. What is broken in my case is the detection of whether the app is running as container or not. And to do that, the old school method is to grep inside /proc/1/cgroup and check if it matches docker|lxc. This recently stopped working, across WSL2, across docker versions suddenly.

    Did they push something on the wsl kernel?

    The above check is important because if running inside container, you listen to 0.0.0.0:3000 otherwise 127.0.0.1:3000. I believe somewhere in your stack, a similar check has failed resulting in the behavior you observe: reachable inside WSL, but otherwise EMPTY response from windows because it is not listening on 0.0.0.0

  3. gaac510 commented on Jun 5, 2025

    @gaac510
    Author

    Ibrahim Tanyalcin (@IbrahimTanyalcin) Thanks for the input. What you described is a little over my head. Does the cgroup issue only impact docker containers running inside a WSL distro? Or does it impact WSL distros themselves?

    I did an additional check based on your info, which was to check if my (only) distro supports cgroup v2 following this, and I did get nodev cgroup2.

    Also, my issue occurs even in scenario B where a web app was not served from a docker container. Does this mean I'm more likely experiencing a different issue?

  4. WangMinan commented on Jun 11, 2025

    @WangMinan

    same issue

  5. kjkent commented on Jul 11, 2025

    @kjkent

    Similar issue here. It seems that binding to 0.0.0.0 vs localhost is involved, at least in my case. However, there's something non-intuitive/quirky/broken with the forwarding of localhost between Windows host and Linux VM. Example:

    1. Inside WSL, start an Astro dev server: pnpm run dev

      By default, this listens to localhost only. Similarly, WSL sets the linux hosts file, with 127.0.0.1 defining localhost. WSL's own settings default to localhostForwarding=true

      • Astro server runs and listens to http://localhost:4321.
      • Inside WSL: curl http://localhost:4321 works.
      • On host: curl http://localhost:4321 times out (error 28)
      • On host: curl http://127.0.0.1 returns a "couldn't connect" error (error 27).
    2. Stop the dev server and re-run to bind to all host addresses: pnpm run dev --host

      • Astro's dev server now listens to http://localhost:4321, http://10.255.255.254:4321, and http://<the host's LAN IP>
      • Out of these, one works from Windows: localhost:4321

    So, in order for Windows to be able to connect to a server in WSL via localhost, the server needs to be listening on all addresses, not just localhost.

  6. HeavenZhi commented on Jan 12, 2026

    @HeavenZhi

    I have the same problem with WSL on my laptop, but strangely, sometimes mirrored mode works fine, but the problem reappears once my computer connects to another network.

  7. q1uxu commented on Feb 2, 2026

    @q1uxu

    Similar too. My old laptop works well, but my new laptop do not work. They use the same wsl network config.

  8. yongzhang commented on Feb 27, 2026

    @yongzhang

    same issue, this works for me previously but stopped working a few months ago and never work again

  9. Christophoclese commented on May 4, 2026

    @Christophoclese

    Similar trouble here with a uvicorn python web app in WSL2. No matter if bound to 0.0.0.0 or Windows IP, when attempting to reach the webserver from the Windows host by IP, the connection appears to time out or is refused. When using localhost to initiate the connection succeeds.

    A packet capture shows that while the intial SYN is being received on eth1 in WSL guest, it responds with SYN-ACK on lo which triggers a RST on lo:

    sudo tcpdump -i any dst port 8000 or src port 8000
    tcpdump: data link type LINUX_SLL2
    tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
    listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
    08:08:43.065807 eth1  In  IP 10.28.36.10.64866 > 10.28.36.10.8000: Flags [S], seq 4017707596, win 65535, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
    08:08:43.066156 lo    In  IP 10.28.36.10.8000 > 10.28.36.10.64866: Flags [S.], seq 2415860432, ack 4017707597, win 65495, options [mss 65495,nop,nop,sackOK,nop,wscale 7], length 0
    08:08:43.066170 lo    In  IP 10.28.36.10.64866 > 10.28.36.10.8000: Flags [R], seq 4017707597, win 0, length 0
    08:08:43.067175 eth1  In  IP 10.28.36.10.51810 > 10.28.36.10.8000: Flags [S], seq 30470504, win 65535, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
    08:08:43.068336 lo    In  IP 10.28.36.10.8000 > 10.28.36.10.51810: Flags [S.], seq 703373215, ack 30470505, win 65495, options [mss 65495,nop,nop,sackOK,nop,wscale 7], length 0
    08:08:43.068356 lo    In  IP 10.28.36.10.51810 > 10.28.36.10.8000: Flags [R], seq 30470505, win 0, length 0
    
  10. hot-tofu-curd commented on Jul 31, 2026

    @hot-tofu-curd

    I can reproduce this issue with native Docker Engine installed directly inside a Debian WSL distribution (not Docker Desktop). The documented --network host workaround succeeds, while Docker bridge networking with a published port times out from the Windows host.

    Environment

    • Windows: Microsoft Windows [Version 10.0.22621.6060] (22H2, Core edition)
    • WSL: 2.7.11.0
    • WSL kernel: 6.18.33.2-microsoft-standard-WSL2
    • Distribution: Debian GNU/Linux 12 (bookworm)
    • Docker Engine: 20.10.24+dfsg1 (native /usr/bin/docker inside Debian)
    • Docker storage driver: overlay2
    • Cgroup driver/version: systemd / 2
    • WSL networking mode reported by wslinfo --networking-mode: mirrored

    Relevant .wslconfig:

    [wsl2]
    networkingMode=mirrored
    localhostForwarding=true

    WSL correctly warns that localhostForwarding is ignored in mirrored mode.

    Bridge/published-port reproduction

    I started a custom Apache image using Docker's default bridge network and published container port 80:

    docker run -p 80:80 -dit --name my-app my-apache2

    Docker reported the expected publication:

    0.0.0.0:80->80/tcp, :::80->80/tcp
    

    Inside WSL, port 80 was listening on both IPv4 and IPv6, and the service worked:

    curl -4 http://127.0.0.1/

    Result: HTTP/1.1 200 OK from Apache/2.4.68 (Unix) with the expected HTML page.

    From Windows PowerShell, both of these timed out:

    curl.exe -4 --connect-timeout 5 http://127.0.0.1/
    curl.exe --connect-timeout 5 http://localhost/

    Access through the mirrored host/LAN address also timed out.

    Checks already performed

    • IIS W3SVC was stopped and its startup type was set to Disabled.
    • Windows netstat / Get-NetTCPConnection showed no Windows process listening on TCP port 80.
    • In WSL, ss showed Docker listening on 0.0.0.0:80 and [::]:80.
    • The container remained reachable from inside WSL and consistently returned HTTP 200.
    • I added the documented scoped Hyper-V firewall rule for WSL TCP port 80:
    New-NetFirewallHyperVRule `
      -Name "MyWebServer" `
      -DisplayName "My Web Server" `
      -Direction Inbound `
      -VMCreatorId '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' `
      -Protocol TCP `
      -LocalPorts 80

    The rule reports:

    Enabled           : True
    Direction         : Inbound
    Action            : Allow
    Protocol          : TCP
    LocalPorts        : 80
    EnforcementStatus : OK
    

    Adding this rule did not make the bridge-published port reachable from Windows.

    Host-network control test

    I stopped the bridge-mode container and ran the same image using the host networking namespace:

    docker run --rm -d --network host --name my-app-host my-apache2

    With this container running, the following Windows request succeeds immediately and returns the expected HTML:

    curl.exe -4 http://127.0.0.1/

    This A/B result appears to isolate the failure to the interaction between WSL mirrored networking and Docker's default bridge/published-port path, rather than Apache, the image, IIS, a Windows port conflict, or the basic Windows-to-WSL localhost path.

    I can collect and provide the full WSL networking logs privately if a Microsoft maintainer needs them. I have not attached them publicly because networking logs may contain host or network identifiers; please reply with the preferred private submission method. I can also retest with a newer Docker Engine build if that would help isolate whether the Docker version affects this behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions