microsoft / WSL

Issues found on WSL
https://docs.microsoft.com/windows/wsl
MIT License
17.46k stars 821 forks source link

Cannot connect WSL2 vEth interfaces in Mirrored mode even hostAddressLoopback is true. #10731

Open kenvix opened 1 year ago

kenvix commented 1 year ago

Windows Version

Microsoft Windows [Version 10.0.22631.2506]

WSL Version

2.0.7.0

Are you using WSL 1 or WSL 2?

Kernel Version

5.15.133.1-1

Distro Version

Ubuntu 22.04.3 LTS

Other Software

.wslconfig:

[wsl2]
memory=4GB
localhostForwarding=true
#networkingMode=bridged
#vmSwitch=vNAT
#networkingMode=mirrored
guiApplications=true

[experimental]
autoMemoryReclaim=gradual #
networkingMode=mirrored
dnsTunneling=true
firewall=true
autoProxy=true
sparseVhd=true
hostAddressLoopback=true

Repro Steps

  1. Enter WSL2 and create a network space and veth device with commands below
ip netns add ns1
  1. Create a pair of veth devices and activate them with commands below
ip link add type veth
ip link set up dev veth0
ip link set veth1 netns ns1
ip a a 192.168.99.1/24 dev veth0
  1. Enter ns1 and allocate an IP.
ip netns exec ns1 bash
ip link set up dev veth1
ip a a 192.168.99.2/24 dev veth1
  1. Ping each other to make sure that netns is working
ping  192.168.99.1 # in ns1
ping 192.168.99.2 # in wsl2 root

PING 192.168.99.2 (192.168.99.2) 56(84) bytes of data.
64 bytes from 192.168.99.2: icmp_seq=1 ttl=64 time=0.034 ms
  1. Ping either 192.168.99.1 or 192.168.99.2 in Windows cmd.
ping 192.168.99.1

Windows firewall is disabled.

Expected Behavior

Windows can ping and connect the veth network normally.

Actual Behavior

Windows can't ping or connect the veth network at all.

22:08:29 -1 ❯ ping 192.168.99.1

Pinging 192.168.99.1 with 32 bytes of data:
Request timed out.
Request timed out.
Request timed out.
Request timed out.

Ping statistics for 192.168.99.1:
    Packets: Sent = 4, Received = 0, Lost = 4 (100% loss),

15:28:32 ERROR ❯ ping 192.168.99.2

Pinging 192.168.99.2 with 32 bytes of data:
Request timed out.
Request timed out.
Request timed out.
Request timed out.

Ping statistics for 192.168.99.2:
    Packets: Sent = 4, Received = 0, Lost = 4 (100% loss),

Diagnostic Logs

No response

### Tasks
brett19 commented 10 months ago

I was also trying to do something similar to @kenvix and am unable to get the Windows host to be able ping the veth (192.168.99.x addresses). I don't believe this issue is related to hostAddressLoopback, having it enabled or disabled both yield the same failure.

My environment is broadly the same as theirs: Ubuntu 22.04

WSL version: 2.1.0.0
Kernel version: 5.15.137.3-1
WSLg version: 1.0.59
MSRDC version: 1.2.4677
Direct3D version: 1.611.1-81528511
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.22621.3007

.wslconfig

[experimental]
networkingMode=mirrored
hostAddressLoopback=true ***also disabled yields same result
chanpreetdhanjal commented 5 months ago

Hi. Can you please collect networking logs by following the instructions below? https://github.com/microsoft/WSL/blob/master/CONTRIBUTING.md#collect-wsl-logs-for-networking-issues

brett19 commented 3 months ago

Hey @chanpreetdhanjal, can you elaborate on what kind of networking logs should be collected? The link you sent indicates to "reproduce the issue", but there isn't really traffic to reproduce in this case since it's more of an issue with the mechanism itself.

Though it's worth mentioning that the instructions in the original ticket description trivially reproduces the issue I'm seeing across a number of different WSL2 installations (including my local system which has the WSL 2.3.14 pre-release).

CatalinFetoiu commented 3 months ago

hello. thanks for reporting the issue and sorry for the delay following up on this

the hostAddressLoopback setting is intended for communication between Windows and Linux using IP addresses assigned to Windows, and only using TCP and UDP traffic.

for example if Windows has IP A, you can have a TCP/UDP server on Windows listening on IP A and connect to it from Linux, or a TCP/UDP server in Linux listening on IP A and connect to it from Windows

In this case you are trying to communicate with an IP that is assigned exclusively to Linux. for this scenario you will need some sort of iptables/nftables configuration to redirect traffic to the Linux vEth interfaces.

brett19 commented 3 months ago

@CatalinFetoiu One of the issues I ran into is that routes are mirrored from windows -> linux, but don't appear to be mirrored from linux -> windows. In this particular case, and excuse my potential miss-understanding here, but the veth in linux creates a route for 192.168.99.1/24 pointing to veth0, however this is not visible in Windows. If I create a route in windows pointing 192.168.99.1/24 to the interface that's mirrored for WSL2, I end up with two conflicting routes on the linux side, and traffic destined to that interface from Windows does not appear to make it to the veth. Perhaps a clarifying question here might be how I can get traffic from a windows application to be routed using the linux nftables, such that it can be routed to the veth.

CatalinFetoiu commented 3 months ago

@brett19, regarding mirrored mode, you are right, it is intended to mirror IP properties, such as addresses, routes from windows to linux, but not the other way around.

regarding configuration of nftables/iptables, you might look at what rules Docker configures when you run "docker run -d -p 8080:80 nginx:alpine", since Docker also creates veth interfaces and configures nftables rules to send traffic to/from them

for example you might try the following scenario: enable the hostAddressLoopback setting in wslconfig, run "docker run -d -p 8080:80 nginx:alpine", then connect to hostIP:8080 from Windows, where hostIP is an ipv4 address assigned to your Windows machine. Please make sure to have the latest wsl version, since we made some fixes for those types of scenarios

brett19 commented 3 months ago

Hey @CatalinFetoiu, do you have any suggestions on how I might be able to get windows to route an alternative ip address into WSL in the context of mirrored networking? I broadly attempted to do what you are describing, the issue I ran into (in the context of the issues veth setup) was that if I create a route in windows for 192.168.99.1/24 pointing to the mirrored interface, this route ends up being mirrored onto the linux side, making it challenging to then route the packets differently from there. For reference, the actual use-case here is that when using docker, I'm broadly able to set up containers to have their own IP addresses with the default bridge network, and this largely works correctly from the linux side of things (there is connectivity between WSL linux using the containers IP address), however those container IPs are not routable from Windows. Note that I believe this is slightly distinct from the hostAddressLoopback scenario you described where the packets are already being routed through the mirrored host interface.

P.S. The more I'm discussing this issue, the more I'm realizing this may not actually be anything fundamentally "broken" with WSL, but rather a confluence of my lack of understanding of how WSL2 intends to have this kind of setup routed, along with more of a feature-request for enabling WSL mirrored networking to natively support correctly representing veth interfaces on the Windows side.

CatalinFetoiu commented 3 months ago

@brett19 thanks for following up and for your explanation

mirrored mode supports communication between the Windows host and Linux using either 127.0.0.1 or an IPv4 address assigned to Windows (for which case you need to enable the hostAddressLoopback setting). If you are trying to communicate from Windows with an IP address that is not assigned to Windows (such as the IP address assigned to the Linux veth interface), that traffic will be sent out of the Windows host, it will not be sent to Linux.

if you want to communicate from Windows or from an external machine with a Linux server that listens on the IP assigned to the Linux veth interface, then the common way to enable this would be the following: Let's say Windows has an Ethernet interface with IP X. Then we'll mirror that interface as a Linux eth0 interface and assign it the same IP X. Then Windows or an external machine will communicate with the "external facing" IP of Linux (in this case X) and Linux will receive that traffic on the eth0 interface and forward it between eth0 and the veth interface. a way to do this would be using iptables/nftables

hope this helps. Let me know if you have any questions