microsoft / microsoft/WSL

`networkingMode=mirrored` in WSL2 makes loopback interface unreachable for ports exposed by Podman/Docker

Open
#13,868 11 comments 9 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

network
Dominant language
C++
Stars
33.7k
Forks
1.8k
Avg merge
3d 17h
Merged PRs (30d)
116

Description

### Windows Version

Microsoft Windows [Version 10.0.26100.7171]

### WSL Version

2.6.1.0

### Are you using WSL 1 or WSL 2?

- [x] WSL 2
- [ ] WSL 1

### Kernel Version

6.6.87.2-1

### Distro Version

Oracle Linux Server 9.7

### Other Software

podman version 5.6.0

### Repro Steps

When running Podman/Docker containers in WSL2 with `networkingMode=mirrored`, containers are not reachable on loopback interface (localhost, 127.0.0.1) inside WSL2, despite the fact that `netstat` shows, that the port listens on all interfaces.

The exposed containers ports are still reachable on real interface IPs inside WSL2, and they are reachable on both loopback (localhost, 127.0.0.1) and real interface IPs from Windows host (e.g. in PowerShell).

The inability to connect to Podman/Docker containers on localhost doesn't allow to use the services in e.g. remote WSL sessions of VS Code (because real IPs are dynamic and you cannot configure a static connection string in VS Code for the service).

**Steps to reproduce:**

**Step 1.** Run a test container that exposes ports.

```bash
# podman run --rm -d -p 8080:8080 --name test-http-server registry.access.redhat.com/ubi9/python-39 python3 -m http.server 8080
```

**Step 2.** Verify that the port listens on the specified port:

```bash
# netstat -tulnp | grep 8080

tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 205661/conmon
```

**Step 3.** Ping loopback interface to confirm it is there and is up:

```bash
# ping 127.0.0.1

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.041 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.205 ms
...

# ping localhost

PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.071 ms
...
```

**Step 4.** Test connectivity to the exposed port:

❌ **Not reachable on loopback interface inside WSL2:**

```bash
# nc -w 5 -v 127.0.0.1 8080

Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: TIMEOUT.

# nc -w 5 -v localhost 8080

Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: TIMEOUT.
```

✅ Still reachable on real interface IPs inside WSL2:

```bash
# nc -w 5 -v $(hostname -I | awk '{print $1}') 8080

Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.X.X:8080.
^C
```

✅ Reachable on loopback interface from Windows host:

```ps
> Test-NetConnection -ComputerName localhost -Port 8080

ComputerName : localhost
RemoteAddress : 127.0.0.1
RemotePort : 8080
InterfaceAlias : Loopback Pseudo-Interface 1
SourceAddress : 127.0.0.1
TcpTestSucceeded : True
```

✅ Reachable on real interface IPs from Windows host:

```ps
> Test-NetConnection -ComputerName 192.168.X.X -Port 8080

ComputerName : 192.168.X.X
RemoteAddress : 192.168.X.X
RemotePort : 8080
InterfaceAlias : Ethernet
SourceAddress : 192.168.X.X
TcpTestSucceeded : True
```

Native processes that listen on the same ports and interfaces are reachable on both loopback and real interfaces in WSL2:

```bash
# python3 -m http.server 8080

Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
```

In parallel WSL terminal:

The port listens on all interfaces:

```bash
# netstat -tulnp | grep 8080

tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 3122/python3
```

Reachable on both loopback and real interface IP address:

```bash
# nc -w 5 -v localhost 8080

Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 127.0.0.1:8080.
^C

# nc -w 5 -v 127.0.0.1 8080

Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 127.0.0.1:8080.
^C

# nc -w 5 -v $(hostname -I | awk '{print $1}') 8080

Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Connected to 192.168.X.X:8080.
^C
```

### Expected Behavior

Exposed ports should be reachable on loopback interface inside WSL.

### Actual Behavior

Exposed ports are not reachable on loopback interface, but are only reachable on real interface IPs inside WSL.

From Windows host the same ports are reachable on loopback (localhost, 127.0.0.1).

### Diagnostic Logs

WSL Networking Logs: [WslNetworkingLogs-2025-12-10_12-19-02.zip](https://github.com/user-attachments/files/24076366/WslNetworkingLogs-2025-12-10_12-19-02.zip)

WSL diagnostic logs were emailed to [wsl-gh-logs@microsoft.com](mailto:wsl-gh-logs@microsoft.com).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Run the provided Podman reproduction with WSL2 networkingMode=mirrored, checking localhost and the WSL interface address as shown. Use the attached WSL networking logs to investigate the mirrored-networking path; the fix is complete when published Podman/Docker ports are reachable through localhost inside WSL2 while native listeners retain their current behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, linux
Domain
networking, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.