10BC0 In WSL using networkingMode=mirrored, "docker run -d -p 8080:80 nginx:alpine" results in localhost:8080 not being accessible from Windows · Issue #48056 · moby/moby · GitHub
[go: up one dir, main page]

Skip to content

In WSL using networkingMode=mirrored, "docker run -d -p 8080:80 nginx:alpine" results in localhost:8080 not being accessible from Windows #48056

@CatalinFetoiu

Description

@CatalinFetoiu

Description

After investigating from WSL side the following issue microsoft/WSL#10494, we found the root cause and a fix that can be made by Docker

more details added in the "Additional info" section

Reproduce

  1. Setup WSL with networkingMode=mirrored in the .wslconfig file
  2. In WSL, run docker run -d -p 8080:80 nginx:alpine
  3. In a Windows browser, go to localhost:8080

Expected behavior

Windows browser is able to access the nginx server running in the Docker container

docker version

Client:
Version:           24.0.7
API version:       1.43
Go version:        go1.21.1
Git commit:        24.0.7-0ubuntu2~22.04.1
Built:             Wed Mar 13 20:23:54 2024
OS/Arch:           linux/amd64
Context:           default
 
Server:
Engine:
  Version:          24.0.7
  API version:      1.43 (minimum version 1.12)
  Go version:       go1.21.1
  Git commit:       24.0.7-0ubuntu2~22.04.1
  Built:            Wed Mar 13 20:23:54 2024
  OS/Arch:          linux/amd64
  Experimental:     false
containerd:
  Version:          1.7.12
  GitCommit:
runc:
  Version:          1.1.12-0ubuntu2~22.04.1
  GitCommit:
docker-init:
  Version:          0.19.0
  GitCommit:

docker info

Client:
Version:    24.0.7
Context:    default
Debug Mode: false
 
Server:
Containers: 1
  Running: 1
  Paused: 0
  Stopped: 0
Images: 1
Server Version: 24.0.7
Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version:
runc version:
init version:
Security Options:
  seccomp
   Profile: builtin
Kernel Version: 5.15.153.1-microsoft-standard-WSL2
Operating System: Ubuntu 22.04.3 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 7.758GiB
Name: wsl-test
ID: d62f9024-99e1-4774-8d65-b5554f8f2b11
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
  127.0.0.0/8
Live Restore Enabled: false
 
WARNING: No blkio throttle.read_bps_device support
WARNING: No blkio throttle.write_bps_device support
WARNING: No blkio throttle.read_iops_device support
WARNING: No blkio throttle.write_iops_device support

Additional Info

What's the issue and root cause:
Docker uses an nftables NAT rule to implement port forwarding and the rule applies to inbound traffic arriving in Linux.

Docker assumes that 127.0.0.1 traffic is not coming from outside Linux and so the NAT rule won't be applied to this traffic. Docker has a different mechanism to do port forwarding for 127.0.0.1

In mirrored mode 127.0.0.1 traffic can come from outside Linux, when Windows and Linux communicate using 127.0.0.1 (traffic will flow through the Linux loopback0 interface), so the NAT rule will be applied to this traffic, which breaks Docker's assumption.

How does Docker’s NAT solution work today with networkingMode = NAT? Even though Windows and Linux can communicate on 127.0.0.1 using the localhost relay, 127.0.0.1 traffic will arrive in Linux on an hvsocket connection and it won't be considered inbound traffic, so the rule won't be applied to it.

Proposed fix that can be made by Docker:
Exclude inbound traffic on interface "loopback0" from being processed by the NAT rule, by modifying the rule as shown below

Original rule (second rule in the chain):

chain DOCKER {
iifname "docker0" counter packets 0 bytes 0 return
iifname != "docker0" tcp dport 8080 counter packets 0 bytes 0 dnat to 172.17.0.2:80
}

New rule (second rule in the chain):

chain DOCKER {
iifname "docker0" counter packets 0 bytes 0 return
iifname != "docker0" iifname != "loopback0" tcp dport 8080 counter packets 0 bytes 0 dnat to 172.17.0.2:80
}

Fix was tested by running "docker run -d -p 8080:80 nginx:alpine" in Linux, then connecting to localhost:8080 in a Windows browser - the scenario did not work before the fix and worked after applying the fix manually.

Risk assesment:
Risk of the fix is low

In mirrored mode, loopback0 interface is only used for 127.0.0.1 traffic. 127.0.0.1 traffic is not supposed to be processed by the NAT rule - excluding loopback0 traffic from being processed by the NAT rule should not affect existing functionality.

Metadata

Metadata

Assignees

Labels

area/lcowIssues and PR's related to the experimental LCOW featurearea/networkingNetworkingarea/networking/d/bridgeNetworkingkind/bugBugs are bugs. The cause may or may not be known at triage time so debugging may be needed.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0