Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

After converting to WSL2 no longer able to route traffic to other VSwitches on the same host. #4288

Open
wallrick opened this issue Jul 9, 2019 · 40 comments
Labels

Comments

@wallrick
Copy link

wallrick commented Jul 9, 2019

Issue
WSL2 on the same system (laptop) as other hyper-V systems and vswitches. Not able to reach other hyper-v systems from within WSL2 like I am from the host command prompt. This boils down to a routing issue with no clear way of resolving it.

Issue Details
Windows Version: 1903
Build: 18922.1000

Originally WSL 1 was working along side other Hyper-V VMs. I had set up a dedicated switch for hyper-v, config details from netsh below for "NAT-Switch". The WSL 1 was able to connect to the other Hyper-V VMs through various networking protocols like, ssh, ping, etc

After upgrading the WSL instance to WSL 2 the routing from WSL 2 to the other hyper-V VMs appears to be broken.

From within WSL1 instance, pinging a VM in Hyper-V.

ping 192.168.250.200 PING 192.168.250.200 (192.168.250.200) 56(84) bytes of data.
64 bytes from 192.168.250.200: icmp_seq=1 ttl=64 time=0.512 ms
64 bytes from 192.168.250.200: icmp_seq=2 ttl=64 time=0.391 ms
64 bytes from 192.168.250.200: icmp_seq=3 ttl=64 time=0.407 ms
^C
--- 192.168.250.200 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.391/0.436/0.512/0.058 ms

After converting to WSL2 instance,

$ ping 192.168.250.200 PING 192.168.250.200 (192.168.250.200) 56(84) bytes of data.
^C
--- 192.168.250.200 ping statistics ---
6 packets transmitted, 0 received, 100% packet loss, time 5193ms

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether 3e:b7:bd:be:ba:ca brd ff:ff:ff:ff:ff:ff
3: sit0@NONE: mtu 1480 qdisc noop state DOWN group default qlen 1000
link/sit 0.0.0.0 brd 0.0.0.0
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:15:5d:13:2d:83 brd ff:ff:ff:ff:ff:ff
inet 192.168.190.173/24 brd 192.168.190.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::215:5dff:fe13:2d83/64 scope link
valid_lft forever preferred_lft forever
$ netstat -arn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 192.168.190.161 0.0.0.0 UG 0 0 0 eth0
192.168.190.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

From the host,

ping 192.168.250.200 Pinging 192.168.250.200 with 32 bytes of data:
Reply from 192.168.250.200: bytes=32 time<1ms TTL=64
Reply from 192.168.250.200: bytes=32 time<1ms TTL=64
Reply from 192.168.250.200: bytes=32 time<1ms TTL=64

Ping statistics for 192.168.250.200:
Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms

Expected Behavior
I would expect that from within WSL2 network traffic should be routed correctly to other VSwitches within the same physical host. Maybe additional configuration instructions are required for my above scenario but I suspect since the WSL2 network properties seem to be reconfigured on every reboot it won't help. Greater control over WSL2 networking would help, like setting static IP or subnet ranges or being able to change the vswitch that WSL2 uses.

Attempted Workarounds
Attempted to switch my Hyper-V VMs over to the WSL vswitch. This worked however the second problem discovered is every time I reboot my laptop WSL vswitch has a different IP and subnet. This makes accessing the hyper-V's using a consistent IP impossible and requires configuring IPs and hostnames, etc after every reboot. Because the subnet changes I am unable to set static IP's for the hyper-v instances.

I also attempted scripting the reconfiguration of the WSL adapter after every reboot so that it always uses the same subnet. This somewhat worked, if WSL and hyper-V VMs were on the same "WSL" virtual switch they could talk to each other. The problem with this approach is that the WSL 2 instance and hyper-V VMs are no longer able to reach outside IPs. So the routing somewhere in the "WSL" VSwitch is broken when I manually configure the "WSL VSwitch". Rebooting the host restores the routing to external IPs but results in the first problem of constantly changing subnets and IPs.

Additional Details
netsh dump

pushd interface ipv4
reset
set global icmpredirects=enabled
set interface interface="Ethernet (Kernel Debugger)" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Wi-Fi" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Local Area Connection* 1" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Bluetooth Network Connection" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="vSwitch (NAT-Switch)" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Local Area Connection* 11" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Npcap Loopback Adapter" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Ethernet 4" forwarding=enabled advertise=enabled metric=1 nud=enabled ignoredefaultroutes=disabled
set interface interface="Ethernet 5" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Bluetooth Network Connection 2" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Ethernet 2" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Ethernet 3" forwarding=enabled advertise=enabled metric=1 nud=enabled ignoredefaultroutes=disabled
set interface interface="Local Area Connection* 2" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Ethernet" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="Ethernet 6" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="vEthernet (NAT-Switch)" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="vEthernet (Default Switch)" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
set interface interface="vEthernet (WSL)" forwarding=enabled advertise=enabled nud=enabled ignoredefaultroutes=disabled
add address name="vEthernet (NAT-Switch)" address=192.168.250.1 mask=255.255.255.0
add address name="vEthernet (Default Switch)" address=172.18.56.161 mask=255.255.255.240
add address name="vEthernet (WSL)" address=192.168.190.161 mask=255.255.255.240

@zewpo
Copy link

zewpo commented Oct 14, 2019

i tried using bridged adaptor, instead of nat, but it appears to fail with the same issue. any news on how to work-around or fix?

@Larswa
Copy link

Larswa commented Oct 24, 2019

I am seeing the exact same issue today, after getting the 19008.1 build.

Unable to ping or ssh through to other hyper-v machines on the same host. In my instance I used the builtin hyper-v "Default Switch" for my other hyperv guests.

This worked for me on the previous flight build 18999. But now it seems to be broken. It works fine if I set the WSL version back to 0. Then I can access other hyperv guests just fine.

Also ... the WSL2 can access other resources on my network and over the internet just fine. As in doing ping, curl and ssh requests. Problem is only to other machines on the same host.

@heggrik
Copy link

heggrik commented Nov 19, 2019

I just discovered this issue today.

Running multiple Hyper-V VM's and not being able to connect in any way from wsl2 to any of them.

Tried various ways of adding routes, changing switches around in hyper-v, bridged mode, static ip's.
Nothing seemed to solve it, other than reverting back to wsl1.

It'd be awfully nice to have either a workaround or a permanent fix.

@very-random-man
Copy link

very-random-man commented Dec 5, 2019

I've been experiencing this issue. I was playing about with things and noticed that i can ssh in from WSL2 if i go via Powershell. I've got /usr/local/bin/powershell symlinked to the fully qualified path for powershell.exe.

powershell ssh [user]@[guest vm ip]

This isn't really a solution to anything other than just opening up an SSH session. I'd be interested if anyone knows of a way to route all traffic for an ip through this. Since connection is fine from the host is there a way to route traffic via the host ip? Some kind of proxy or ssh tunnel maybe?

@kristof-mattei
Copy link

kristof-mattei commented Feb 3, 2020

Bumping. Running minikube on Hyper-V, can't reach it from WSL, even with netsh portfwd.

@very-random-man
Copy link

very-random-man commented Feb 3, 2020

I don't know if something has changed but I've been able to get this working a bit now. I have an Ubuntu hyperv vm connected to an internal virtual switch I created and I can ssh to it from wsl2. I've set up the switch for NAT as I have virtualbox running on the hyperv vm and I am able to access the various nested vms through that as well. I can't get back to wsl2 from any of those things though. I thought it'd be neat to serve files from wsl2 to them via nfs but that is a non-starter.

@kristof-mattei
Copy link

kristof-mattei commented Feb 4, 2020

@very-random-man that is awesome.

Can you tell us how you did this?

Let's say WSL is 172.24.245.108/20 and the VM is 172.23.108.50/20.

I'm assuming you set up the NAT on the switch of the VM.

How did you write the rules?
And more importantly, what is the target IP when you connect from WSL to the VM?

Thanks!

@very-random-man
Copy link

very-random-man commented Feb 5, 2020

Thanks. I'm wrapping it all up in a single-command deploy. I'll link the project on here when it's done. I'm using win vagrant to build the vm. I had hoped to keep it all in the WSL2 domain but hyper-v vms need to be built in an elevated powershell.

Basically creating and assigning an internal switch on its own isn't enough and you need to make sure the networking config on the vm is in place. Any nested VMs also need to use the same hyper-v virtual switch.

I'm hoping to get something out there in the next week or two. Will be looking for guinea pigs to test it out. ;-)

@jshmlr
Copy link

jshmlr commented Mar 11, 2020

I was able to work around this by attaching my Hyper-V server VM to the WSL network and adding a static IP with the following.

IP Address: 172.24.128.10/20 (You could use anything on the 172.24.128.0/20 subnet, except (.1 of course))
Gateway: 172.24.128.1
DNS: 172.24.128.1

Double check your WSL subnet by running an ipconfig in a windows CMD prompt.

As always: YYMV

@luxzg
Copy link

luxzg commented Mar 18, 2020

I'm hoping to get something out there in the next week or two. Will be looking for guinea pigs to test it out. ;-)

Guinea pigs still waiting here... Thanks!

@jshmlr
Copy link

jshmlr commented Mar 30, 2020

I was able to work around this by attaching my Hyper-V server VM to the WSL network and adding a static IP with the following.

IP Address: 172.24.128.10/20 (You could use anything on the 172.24.128.0/20 subnet, except (.1 of course))
Gateway: 172.24.128.1
DNS: 172.24.128.1

Double check your WSL subnet by running an ipconfig in a windows CMD prompt.

As always: YYMV

This is broken now. I'm trying to figure out why.

@wynnw
Copy link

wynnw commented Jun 2, 2020

Any luck @jshmlr or @very-random-man? Tried upgrading yesterday and all my workflows are totally destroyed by WSL2 and this networking problem.

@gwillcox-r7
Copy link

gwillcox-r7 commented Jun 2, 2020

Having this same issue here. Could only use the Internal Network switch to communicate with my host via networking, all other switches were failing. Ended up going back to WSLv1, its impossible to do network testing with this WSLv2 error.

@phantomkingx
Copy link

phantomkingx commented Jun 9, 2020

This is a must fix in order for many to use WSL2. Thank you for making rollback to WSL1 easy.

@ivan-section-io
Copy link

ivan-section-io commented Jul 1, 2020

I had a similar issue (Win10 2004 19041.329) - and noticed the forwarding value returned by netsh dump (all enabled) didn't match Forwarding returned via PowerShell with Get-NetIPInterface | select ifIndex,InterfaceAlias,AddressFamily,ConnectionState,Forwarding | Sort-Object -Property IfIndex | Format-Table (all disabled)

After issuing Set-NetIPInterface -ifindex MYvEthernetWSLID -Forwarding Enabled and Set-NetIPInterface -ifindex MYvEthernetSWITCHID -Forwarding Enabled traffic then passed back-and-forth.

I'm now able to access Hyper-V VMs via WSL2 tools (ping/ssh/etc).

Strangely, undoing my change via PowerShell disabling of forwarding on the interface seems to then show as disabled via netsh dump. (Some internal state toggled maybe?)

Could be related - hope it helps.

@HumanPrinter
Copy link

HumanPrinter commented Jul 1, 2020

Briljant, I've tested this on my machine (same Windows build number) and it works like a charm

@AdalZanabria
Copy link

AdalZanabria commented Jul 1, 2020

After issuing Set-NetIPInterface -ifindex MYvEthernetWSLID -Forwarding Enabled and Set-NetIPInterface -ifindex MYvEthernetSWITCHID -Forwarding Enabled traffic then passed back-and-forth.

@ivan-section-io
EDIT: Nevermind! I was using the first commands wrong lol thanks a lot it really worked!

@gwillcox-r7
Copy link

gwillcox-r7 commented Jul 1, 2020

Thanks @ivan-section-io this also worked for me, running very smoothly now :)

@AntonOfTheWoods
Copy link

AntonOfTheWoods commented Jul 3, 2020

Does this look right?

PS C:\Users\anton> Get-NetIPInterface | select ifIndex,InterfaceAlias,AddressFamily,ConnectionState,Forwarding | Sort-Object -Property IfIndex | Format-Table

ifIndex InterfaceAlias               AddressFamily ConnectionState Forwarding
------- --------------               ------------- --------------- ----------
      1 Loopback Pseudo-Interface 1           IPv6       Connected   Disabled
      1 Loopback Pseudo-Interface 1           IPv4       Connected   Disabled
      2 Local Area Connection* 2              IPv4    Disconnected   Disabled
      8 Bluetooth Network Connection          IPv4    Disconnected   Disabled
      9 WiFi                                  IPv4       Connected   Disabled
     15 vEthernet (WiFi)                      IPv4       Connected   Disabled
     15 vEthernet (WiFi)                      IPv6       Connected   Disabled
     21 Local Area Connection* 1              IPv4    Disconnected   Disabled
     30 vEthernet (Default Switch)            IPv6       Connected    Enabled
     30 vEthernet (Default Switch)            IPv4       Connected    Enabled
     53 vEthernet (WSL)                       IPv6       Connected    Enabled
     53 vEthernet (WSL)                       IPv4       Connected    Enabled

If so, is there anything else I should check/do because I still have no access from WSL2 to other VMs (multipass VMs that can only use the Default Switch)? Was I only supposed to enable these and the forwarding should work? Thanks!

@ivan-section-io
Copy link

ivan-section-io commented Jul 3, 2020

@AntonOfTheWoods I only have the 2 vSwitches: "WSL" and "Default". It looks like you've got another - "Wifi".

If that is where your VMs are - it would make sense that you should enable forwarding for that adapter.

I have not tried anything beyond the system installed vSwitches. I did read that "Default Switch" has some special properties (e.g. NAT?) - but I'm not sure how/if they would come into play in a simple routing scenario.

For reference, my (simple) setup:

PS C:\WINDOWS\system32> Get-NetIPInterface | select ifIndex,InterfaceAlias,AddressFamily,ConnectionState,Forwarding | Sort-Object -Property IfIndex | Format-Table

ifIndex InterfaceAlias                  AddressFamily ConnectionState Forwarding
------- --------------                  ------------- --------------- ----------
      1 Loopback Pseudo-Interface 1              IPv4       Connected   Disabled
      1 Loopback Pseudo-Interface 1              IPv6       Connected   Disabled
      2 Wi-Fi                                    IPv6       Connected   Disabled
      2 Wi-Fi                                    IPv4       Connected   Disabled
     10 Ethernet                                 IPv4    Disconnected   Disabled
     10 Ethernet                                 IPv6    Disconnected   Disabled
     55 vEthernet (Default Switch)               IPv6       Connected    Enabled
     55 vEthernet (Default Switch)               IPv4       Connected    Enabled
     94 vEthernet (WSL)                          IPv6       Connected    Enabled
     94 vEthernet (WSL)                          IPv4       Connected    Enabled

@AntonOfTheWoods
Copy link

AntonOfTheWoods commented Jul 3, 2020

@ivan-section-io , I have been using Linux for too long... It was McAfee Firewall blocking the connections. Thanks for your help!

EDIT:
However, I can't for the life of me work out how to persist this. Having to specifically open an admin console to re-run these commands every reboot is a real PITA and against my DevOps nature... Is it possible without some nasty kludge?

Would a powershell scheduled task on boot be an appropriate way to automate this? (sorry, really haven't done anything on Windows in over a decade...). It seems to work alright...

@AntonOfTheWoods
Copy link

AntonOfTheWoods commented Jul 3, 2020

Actually this has a REALLY big hole in it for some users (like me). Hyper-V for some reason that I can't work out changes the IP ranges for both the Default and WSL virtual switches. That means I either have to add a big "allow everything" for 172.16.0.0/12 (and hope it doesn't switch to 192.168, which it used to previously but maybe not anymore) or somehow query to see what has been assigned and then reconfigure the firewall every boot. Wow, that's really annoying.

@bavibm
Copy link

bavibm commented Jul 8, 2020

@AntonOfTheWoods My first guess would be to stick it in a .ps1 script and create a task to run it on login with admin privileges, you can do this really easy with the Windows Task Scheduler. I have a PowerShell Script that runs on my personal laptop that way.

Personally I am testing these commands right now to see if it fixes my issue: I am on Win10 2004 running a CodeReady Containers instance (Hyper-V) and my WSL2 instance is not able to connect to the VM. If it works I would then need to see if the settings persist across reboots, if not I will have to stick it in the Task Scheduler

@bavibm
Copy link

bavibm commented Jul 8, 2020

The commands worked perfectly for my issue, thanks @ivan-section-io !!! Now I have to see if it persists and if it helps my connection when I connect to a VPN on Windows but this is a great start for me

@jonaskuske
Copy link

jonaskuske commented Jul 11, 2020

After issuing Set-NetIPInterface -ifindex MYvEthernetWSLID -Forwarding Enabled and Set-NetIPInterface -ifindex MYvEthernetSWITCHID -Forwarding Enabled traffic then passed back-and-forth.

Since the indices seem to change between reboots I'm now using the following command instead, which gets both the default switch and the WSL one by their alias and enables forwarding:

Get-NetIPInterface | where {$_.InterfaceAlias -eq 'vEthernet (WSL)' -or $_.InterfaceAlias -eq 'vEthernet (Default Switch)'} | Set-NetIPInterface -Forwarding Enabled

I've also tried running this script on every start using Task Scheduler, however this way forwarding is only enabled for (Default Switch), not for (WSL) – I assume the WSL one is added lazily and doesn't exist yet immediately on startup?

Instead, I've now added the script to a function in my PowerShell profile so I only have to run Enable-WSLForward when I need to access VM IPs from there.

@jagd
Copy link

jagd commented Sep 6, 2020

Set-NetIPInterface -Forwarding Enabled works.

Is there anyway to set the forwarding permanently or at least without the requirement of admin privilege?

@gbraad
Copy link

gbraad commented Feb 14, 2021

After issuing Set-NetIPInterface -ifindex MYvEthernetWSLID -Forwarding Enabled and Set-NetIPInterface -ifindex MYvEthernetSWITCHID -Forwarding Enabled traffic then passed back-and-forth.

No need for IDs, use the alias instead:

PS> Set-NetIPInterface -ifAlias "vEthernet (WSL)" -Forwarding Enabled
PS> Set-NetIPInterface -ifAlias "vEthernet (Default Switch)" -Forwarding Enabled

Note: these can be localized, so this would work on an English (international) system only.

@astroboylrx
Copy link

astroboylrx commented Apr 8, 2021

Actually this has a REALLY big hole in it for some users (like me). Hyper-V for some reason that I can't work out changes the IP ranges for both the Default and WSL virtual switches. That means I either have to add a big "allow everything" for 172.16.0.0/12 (and hope it doesn't switch to 192.168, which it used to previously but maybe not anymore) or somehow query to see what has been assigned and then reconfigure the firewall every boot. Wow, that's really annoying.

I'm not sure if this is happening now. I just upgraded to the Insider Preview build 21354.1 today and suddenly WSL2 has IP address 192.168.XXX.1 (previously it's 172.16.0.0/12). This seems to be a big change but is not mentioned in the release announcement. I cannot ssh myself@localhost -p2222 into WSL2 anymore from Windows. Any suggestions would be greatly appreciated!

Screenshot 2021-04-08 152129

@AntonOfTheWoods
Copy link

AntonOfTheWoods commented Apr 8, 2021

I'm not sure if this is happening now. I just upgraded to the Insider Preview build 21354.1 today and suddenly WSL2 has IP address 192.168.XXX.1 (previously it's 172.16.0.0/12). This seems to be a big change but is not mentioned in the release announcement.

I'm pretty sure this is just the typical behaviour. HyperV based solutions have a certain number of gotchas that you can't work around. As I have said many times, it is an amazing tool for virtualizing Windows in enterprise/domain environments. It is highly inferior to even basic open source options in some other environments. But they broke virtualization for all competitors a while back, so many of us had to adapt.

@aapoalas
Copy link

aapoalas commented Apr 9, 2021

I tried to use this to setup some communication between a WSL2 Ubuntu 18.04 and a Windows guest VM where the two would need to communicate between each other with through multicast.

However, despite normal pings working after the Forwarding Enabled -setting, multicast communication seemed to still not work (or at least the two apps on either side of the WSL2 <-> Hyper-V VM gap couldn't see each other). Any idea as to whether this is expected or not?

@bennettnw2
Copy link

bennettnw2 commented Dec 15, 2021

Wow, I've been working on this for like a week now and I've made no progress... Can we just fix this and have it work?

Edit: I actually think it is my company that has this locked down for one reason or another.

Edit: Actually, WSL1 has network connectivity so I think it has something to do with Hyper-V... FIX IT!

@luxzg
Copy link

luxzg commented Dec 15, 2021

@bennettnw2 this is from July 2019 and hasn't been fixed for 2.5 years, as it pretty much doesn't resonate with MS team that says it's "not a bug but a feature". So don't expect it to be "fixed". Best way to use WSL (1 or 2) is not to use it, and use Hyper-V (or some other hypervisor) with small friendly Linux distro (like Ubuntu, that's pretty much "default" for most of WSL users anyway). It's even worth the small upgrade price from Home to Pro to get proper Hyper-V and proper virtualized networking stack, without hand holding and crutches. I tried WSL 1/2 over and over again, and every time I lose more time trying to make it work, instead just downloading Ubuntu ISO and starting a normal proper VM. I gave up on WSL a year ago, and I'm waiting if WSL 3/4/5 maybe fix the way of thinking in MS team. Hyper-V VM + Ubuntu server works like a charm though, and has been working awesome for me for years, through all the W10 minor/major updates, and from Ubuntu 16.04 till the latest ones, for good 5-6 years now, no flaws, no issues, on hundreds of VMs, tests, production, development, whatever. Takes 10-15 minutes to download, install, and setup, and most of that time is due to download speeds and hard drive speeds (downloading large ISO, waiting for installation, and updates during/after installation).

@wynnw
Copy link

wynnw commented Dec 15, 2021

I love using WSL2, but this bug is annoying (as are the blue screen of death's when opening large database backup files). But everything is annoying at some level if you push far enough and wsl2 + vscode has been a great productivity boon for me and my team overall using a custom wsl2 distribution we've built to match our deployment platform.

For this particular bug I've added a command to our python build framework that looks like:

def wsl_fix_network(ctx):
    #this solution is based on a comment from jonaskuske in: https://github.com/microsoft/WSL/issues/4288
    provider = VmProvider.load(ctx, default="hyperv")
    networks = ["vEthernet (WSL)", f"vEthernet ({provider.switch})", "vEthernet (Default Switch)"]
    wheres = " -or ".join([f"$_.InterfaceAlias -eq '{n}'" for n in networks])
    cmd = f"Get-NetIPInterface | where {{{wheres}}} | Set-NetIPInterface -Forwarding Enabled"
    provider.powershell(cmd, admin=True)

This is using some other utility methods to run powershell commands, but the idea is just that Set-NetIPInterface command can fix things. I run that after a reboot when I'm using a hyper-v vm + wsl2 and realize my connectivity between the two is broken. Thanks to jonaskuske for posting the original script solution.

@nickjj
Copy link

nickjj commented Sep 12, 2022

As of a recent Windows 10 Pro patch I'm no longer able to SSH from WSL 2 into a separate Hyper-V Ubuntu 22.04 VM that I created. This set up was working great for years previously.

I never had to run any PowerShell commands to enable forwarding but as per a few comments in this thread I ran this:

Get-NetIPInterface | where {$_.InterfaceAlias -eq 'vEthernet (WSL)' -or $_.InterfaceAlias -eq 'vEthernet (Default Switch)'} | Set-NetIPInterface -Forwarding Enabled

And now I see this:

PS C:\Users\Nick>  Get-NetIPInterface | select ifIndex,InterfaceAlias,AddressFamily,ConnectionState,Forwarding | Sort-Object -Property IfIndex | Format-Table

ifIndex InterfaceAlias                       AddressFamily ConnectionState Forwarding
------- --------------                       ------------- --------------- ----------
      1 Loopback Pseudo-Interface 1                   IPv4       Connected   Disabled
      1 Loopback Pseudo-Interface 1                   IPv6       Connected   Disabled
      3 vEthernet (External Virtual Network)          IPv6       Connected    Enabled
      3 vEthernet (External Virtual Network)          IPv4       Connected    Enabled
     30 vEthernet (Default Switch)                    IPv4       Connected    Enabled
     30 vEthernet (Default Switch)                    IPv6       Connected    Enabled
     36 vEthernet (WSL)                               IPv6       Connected    Enabled
     36 vEthernet (WSL)                               IPv4       Connected    Enabled

But when I try to SSH into my Hyper-V VM (IP: 192.168.1.4 / hostname dtp) from WSL 2 I get:

nick@kitt ~ $ ssh 192.168.1.4
ssh: connect to host 192.168.1.4 port 22: No route to host

nick@kitt ~ $ ssh dtp
ssh: connect to host dtp port 22: Network is unreachable

The IP address and hostname are correct (I'm able to SSH into it from PowerShell). SSH is running on that VM and iptables isn't blocking any ports. I was able to successfully SSH into this VM in the past before whatever Windows patch broke things. This is a real bummer because I want to run Ansible against the VM but I can only do that from WSL 2.

Any suggestions on where to go from here?

My Hyper-V switches look like this:

image

And my VM is configured like this:

image

Basically all I did was create an external switch so the VM has public internet access.

I also went as far as deleting all of the switches and making new ones, then I created both a fresh WSL 2 instance and a fresh Hyper-V VM. The result was the same. Unable to SSH into the VM from WSL 2.

@KijoteX
Copy link

KijoteX commented Oct 26, 2022

After issuing Set-NetIPInterface -ifindex MYvEthernetWSLID -Forwarding Enabled and Set-NetIPInterface -ifindex MYvEthernetSWITCHID -Forwarding Enabled traffic then passed back-and-forth.

No need for IDs, use the alias instead:

PS> Set-NetIPInterface -ifAlias "vEthernet (WSL)" -Forwarding Enabled
PS> Set-NetIPInterface -ifAlias "vEthernet (Default Switch)" -Forwarding Enabled

Note: these can be localized, so this would work on an English (international) system only.

Thanks a lot. You are great. This absolutely fixed the communication issue between Kali on WSL and windows 10 on HyperV. (5tupid virtual switches!!!)

@luxzg
Copy link

luxzg commented Oct 26, 2022

Since I just got bumped on email about this issue, I'd like to point everyone to the fact that vSwitch can now be used to directly connect WSL2 distro, officially, no hacks, using "networkingMode=bridged". You do need W11 Pro, which shouldn't be an issue. I've compiled a nice big tutorial couple of days ago as a comment in main networking thread:
#4150 (comment)

Likewise added it to my GitHub:
https://github.com/luxzg/WSL2-fixes

I went through W10 to W11 upgrade (linked instructions for those with "unsupported" hardware), WSL2 Preview, creation of vSwitch, configuration of a bridge, and as a bonus systemd configuration on Ubuntu with complete systemd based networking setup. It should be doable for both newbies and experienced users. Btw, I can now tear up and setup new WSL2 instance with proper networking and full apt upgrades and all in less than 10 minutes, easy-peasy.

@ghecko
Copy link

ghecko commented Nov 24, 2022

Hello,

How to switch back from the bridged network for WSL2 to Nat network ? I did not have access anymore to the Internet.
I have tried changing vmSwitch to the internal network adapter and networkingMode to "nat" and also tried deleting the config within the .wslconfig file, without success

@luxzg
Copy link

luxzg commented Nov 26, 2022

@ghecko removing config from .wslconfig should revert to default NAT. But here is a more complete "cleanup" procedure.

This is what you need:

# inside WSL distro
sudo nano /etc/wsl.conf
# erase modifications, eg.
[network]
generateResolvConf = false
# save and exit editor
Ctrl + X ; Y
# erase networking config if you've used one like this:
rm /lib/systemd/network/wsl_external.network
# disable networking services if you've used systemd
sudo systemctl disable systemd-networkd
sudo systemctl disable systemd-resolved
# exit WSL
exit
# shutdown all instances in Windows cmd.exe / Terminal / PowerShell window
wsl.exe --shutdown
# edit .wslconfig from eg. PowerShell prompt
cd ~
.\.wslconfig
# remove all lines like
networkingMode= ...
vmSwitch= ...
dhcp= ...
macAddress= ...
ipv6= ...
# save file and exit editor
# then start your distro again
wsl.exe -d <distro name>

This would remove all modifications made by my guides.

But I have to say that following my guide step by step should 100% work for Ubuntu. I have also tried ArchWSL and works fine (with minor modifications due to apt being replaced by yum and package names being slightly different, plus ArchWSL already has systemdenabled so I skipped directly to that. Haven't tested Debian, but it should be close enough to Ubuntu, I'll try today.

Are you using some other distro? I'd be happier solving the issue than giving up.

In past 2 days I've had someone with OpenVPN, we solved that easily. Also in process I've tested networking in Ubuntu with NetPlan and NetworkManager. I'd be happy to test your case and solve it with you, it's a learning process for the whole community, if you have time.

EDIT: Also, note that I used clean distros and systems that had all previous workarounds removed. I can't vouch for what happens if you have few powershell or bash scripts changing networking as old workarounds, then trying to use bridged network. Any previous workarounds need to be removed for bridged option to work properly.

EDIT 2: Added separate guide for reverting settings:
https://github.com/luxzg/WSL2-fixes/blob/master/Removing_network_bridge_and_systemd_settings.md

EDIT 3: Tested Debian, works exactly as Ubuntu, to the letter. systemd, networkd, resolved, bridge, static IPv4, access to Apache installed in Debian, WSLg apps. Debian doesn't have NetPlan or NetworkManager by default, and instead uses systemd, so it's a perfect fit for how I've explained it in the guide.

luxzg added a commit to luxzg/WSL2-fixes that referenced this issue Nov 26, 2022
added Removing_network_bridge_and_systemd_settings.md due to request from community member:
microsoft/WSL#4288 (comment)
@ghecko
Copy link

ghecko commented Nov 28, 2022

@luxzg, thank you for your very detailed response!
I'm on kali WSL (Debian based).

I will try to implement your solution to switch back to NAT. It's probably due to the networkd and resolvd systemd services that are still running after the config modification. Let me try this ASAP and tell you if your instruction solves my issue :)

EDIT: I just tried your solution and still not having Internet access. The DNS resolution does not work, and when I try accessing an Internet service, I obtain the following error:

#> curl https://xxx.xxx.xxx.xxx
curl: (7) Failed to connect to xxx.xxx.xxx.xxx port 443 after 3130 ms: No route to host

DNS resolution failed with the following error:

#> nslookup google.com
;; communications error to 172.25.128.1#53: timed out
;; communications error to 172.25.128.1#53: timed out
;; communications error to 172.25.128.1#53: timed out
;; no servers could be reached

However, the default route seems correct.

#> route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.25.128.1    0.0.0.0         UG    0      0        0 eth0
172.25.128.0    0.0.0.0         255.255.240.0   U     0      0        0 eth0

the IP configuration:

6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:89:5b:62 brd ff:ff:ff:ff:ff:ff
    inet 172.25.131.169/20 brd 172.25.143.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fe89:5b62/64 scope link
       valid_lft forever preferred_lft forever

And finally, the following systems services are enabled:

console-getty.service                      enabled-runtime disabled
cron.service                               enabled         enabled
docker.service                             enabled         enabled
e2scrub_reap.service                       enabled         disabled
getty@.service                             enabled         enabled
ModemManager.service                       enabled         enabled
networking.service                         enabled         enabled
regenerate-ssh-host-keys.service           enabled         enabled
rsyslog.service                            enabled         enabled
sudo.service                               masked          enabled
systemd-pstore.service                     enabled         enabled
systemd-remount-fs.service                 enabled-runtime disabled
systemd-timesyncd.service                  enabled         enabled

EDIT2: I've restarted the WSL NAT adapter as described here: https://gist.github.com/danvy/9486bf730371436131cb888ff4c2ceb6 and now everything seems working as expected.

@luxzg
Copy link

luxzg commented Nov 28, 2022

I'm glad you've got it working. Well, some of it at least. I finally got some time to test with kali few minutes ago, and it's been exactly same experience as Ubuntu and Debian. I'll document the bridge mode here again, in very short, and post same info you did so you can compare if you decide to try again with a bridge.

Actually, I'll start with the very basic base of everything. Did you try running this command?

wsl --version

It should return something like this:

WSL version: 1.0.0.0
Kernel version: 5.15.74.2
WSLg version: 1.0.47
MSRDC version: 1.2.3575
Direct3D version: 1.606.4
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.22621.819

If it throws error you have wrong and/or older version of WSL !!! Please install latest version from Microsoft Store !

Since I keep reusing same vSwitch for all distros (and few Hyper-V VMs) I don't touch my vSwitch, but here is my network setup (laptop with just the WiFi adapter being connected right now):

PS C:\Users\lux_z> Get-NetAdapter | select Name, ifAlias, InterfaceDescription, Status

Name                         ifAlias                      InterfaceDescription
----                         -------                      --------------------
Bluetooth Network Connection Bluetooth Network Connection Bluetooth Device (Personal Area Network)
Network Bridge               Network Bridge               Microsoft Network Adapter Multiplexor Driver
Wi-Fi                        Wi-Fi                        Killer(R) Wi-Fi 6 AX1650x 160MHz Wireless Network Adapter (2…
Realtek-2.5G                 Realtek-2.5G                 Realtek Gaming 2.5GbE Family Controller
vEthernet (WSL_external)     vEthernet (WSL_external)     Hyper-V Virtual Ethernet Adapter #2

And this:

PS C:\Users\lux_z> Get-VmSwitch | Select Name, SwitchType, NetAdapterInterfaceDescription, AllowManagementOS

Name              SwitchType NetAdapterInterfaceDescription                                     AllowManagementOS
----              ---------- ------------------------------                                     -----------------
Private 10.10.1.x    Private                                                                                False
WSL_external        External Killer(R) Wi-Fi 6 AX1650x 160MHz Wireless Network Adapter (200NGW)              True
Default Switch      Internal                                                                                 True

So, my Physical WiFi (Killer WiFi 6) adapter is used for vSwitch WSL_external and is shared with host (AllowManagementOS True).

If I want WSL to have working network, I need to use same settings as my PC, so let's get that:

PS C:\Users\lux_z> netsh interface ip show addresses "vEthernet (WSL_external)"

Configuration for interface "vEthernet (WSL_external)"
    DHCP enabled:                         No
    IP Address:                           192.168.0.27
    Subnet Prefix:                        192.168.0.0/24 (mask 255.255.255.0)
    Default Gateway:                      192.168.0.1
    Gateway Metric:                       256
    InterfaceMetric:                      35

OK, so if my host IP is 192.168.0.27 and my gateway is 192.168.0.1 I go for something in the same network but far from possibly crowded DHCP space. I am testing at home so it's easy, I know there's less than 10 devices, so anything beyond .40 is safe, and I keep testing with .93 (weird, random number).

Same with my wslconfig I just keep it same for all distros tested thus far. This is my current config:

cd ~
.\.wslconfig

Contents of the file:

# Settings apply across all Linux distros running on WSL 2
[wsl2]

# Bridged networking
networkingMode=bridged
vmSwitch=WSL_external
dhcp=false
macAddress=5c:bb:f6:9e:ee:55
ipv6=true

# Limits VM memory to use no more than 4 GB, this can be set as whole numbers using GB or MB
memory=4GB 

# Sets the VM to use two virtual processors
processors=2

# Turn on/off default connection to bind WSL 2 localhost to Windows localhost ; default is true
localhostforwarding=true

# Turns on/off output console showing contents of dmesg when opening a WSL 2 distro for debugging ; default is false
debugConsole=false

# Turns on/off running GUI apps ; default is true
guiApplications=true
#guiApplications=false

  • Note that some of these are already the defaults, but I'm doing copy/paste as is for you here.

Then I had to install kali, obviously.

wsl --list --online
wsl --install kali-linux

It downloads, installs, boots, and I go through setting my new user and password.

In the same window with new user I do these:

sudo nano /etc/wsl.conf

    [boot]
    systemd=true
    [network]
    generateResolvConf = false

sudo nano /lib/systemd/network/wsl_external.network

    [Match]
    Name=eth0
    [Network]
    Description=WSL_external
    DHCP=false
    Address=192.168.0.93/24
    Gateway=192.168.0.1

I wait for it to exit, or kill it:

exit
...
wsl --list --running
wsl.exe --shutdown

Here you'd usually edit .wslconfig in my guide I believe.

Then I start it again, with new wslconfig + wsl.conf + .network:

wsl.exe -d kali-linux

Note that we didn't touch resolv.conf intentionally, because only now should the generateResolvConf = false be in effect, otherwise if you've edited file earlier it may have been overwritten in the menatime, so you'll need to do it now again anyway. But that's last time.

Anyway, inside kali WSL I finish the configurations as root (sudo):

sudo su

nano /etc/resolv.conf

    nameserver 8.8.8.8

systemctl restart systemd-networkd
systemctl enable systemd-networkd
systemctl restart systemd-resolved.service
systemctl enable systemd-resolved.service

ip a
ping www.google.com

apt-get update
apt-get upgrade -y
apt-get full-upgrade -y

apt-get install apache2 -y
systemctl enable apache2
systemctl restart apache2

apt-get install x11-apps -y
xeyes &
xcalc &

Exiting distro, shutting it down, even restarting PC, then going back in, should keep you on same IP, same working settings, Apache accessible from outside, WSLg working. It does for me.

My system & network info from kali WSL running with working systemd, networkd, resolved, static IP, on network bridge and Hyper-V vSwitch:

route

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.0.1     0.0.0.0         UG    0      0        0 eth0
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0


ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 26:b5:36:89:d3:96 brd ff:ff:ff:ff:ff:ff
3: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether fa:18:ac:7a:6b:fd brd ff:ff:ff:ff:ff:ff
4: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
5: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/sit 0.0.0.0 brd 0.0.0.0
6: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 5c:bb:f6:9e:ee:55 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.93/24 brd 192.168.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5ebb:f6ff:fe9e:ee55/64 scope link
       valid_lft forever preferred_lft forever


systemctl list-unit-files | grep enabled

apache2.service                        enabled         disabled
console-getty.service                  enabled-runtime disabled
cron.service                           enabled         enabled
e2scrub_reap.service                   enabled         disabled
getty@.service                         enabled         enabled
networking.service                     enabled         enabled
regenerate-ssh-host-keys.service       enabled         enabled
rsyslog.service                        enabled         enabled
sudo.service                           masked          enabled
systemd-network-generator.service      enabled         enabled
systemd-networkd-wait-online.service   enabled         disabled
systemd-networkd.service               enabled         enabled
systemd-pstore.service                 enabled         enabled
systemd-remount-fs.service             enabled-runtime disabled
systemd-networkd.socket                enabled         disabled
reboot.target                          disabled        enabled
remote-cryptsetup.target               disabled        enabled
remote-fs.target                       enabled         enabled
remote-veritysetup.target              disabled        enabled
apt-daily-upgrade.timer                enabled         disabled
apt-daily.timer                        enabled         disabled
dpkg-db-backup.timer                   enabled         enabled
e2scrub_all.timer                      enabled         enabled
fstrim.timer                           enabled         enabled
logrotate.timer                        enabled         enabled
man-db.timer                           enabled         enabled
plocate-updatedb.timer                 enabled         enabled


systemctl | grep running

  init.scope                                      loaded active running   System and Service Manager
  apache2.service                                 loaded active running   The Apache HTTP Server
  console-getty.service                           loaded active running   Console Getty
  cron.service                                    loaded active running   Regular background program processing daemon
  getty@tty1.service                              loaded active running   Getty on tty1
  getty@tty2.service                              loaded active running   Getty on tty2
  getty@tty3.service                              loaded active running   Getty on tty3
  getty@tty4.service                              loaded active running   Getty on tty4
  getty@tty5.service                              loaded active running   Getty on tty5
  getty@tty6.service                              loaded active running   Getty on tty6
  rsyslog.service                                 loaded active running   System Logging Service
  systemd-journald.service                        loaded active running   Journal Service
  systemd-networkd.service                        loaded active running   Network Configuration
  systemd-udevd.service                           loaded active running   Rule-based Manager for Device Events and Files
  syslog.socket                                   loaded active running   Syslog Socket
  systemd-journald-dev-log.socket                 loaded active running   Journal Socket (/dev/log)
  systemd-journald.socket                         loaded active running   Journal Socket
  systemd-networkd.socket                         loaded active running   Network Service Netlink Socket
  systemd-udevd-control.socket                    loaded active running   udev Control Socket
  systemd-udevd-kernel.socket                     loaded active running   udev Kernel Socket


nslookup google.com

Server:         8.8.8.8
Address:        8.8.8.8#53

Non-authoritative answer:
Name:   google.com
Address: 216.58.214.14
Name:   google.com
Address: 2a00:1450:400e:800::200e


cat /etc/os-release

PRETTY_NAME="Kali GNU/Linux Rolling"
NAME="Kali GNU/Linux"
VERSION="2022.4"
VERSION_ID="2022.4"
VERSION_CODENAME="kali-rolling"
ID=kali
ID_LIKE=debian
HOME_URL="https://www.kali.org/"
SUPPORT_URL="https://forums.kali.org/"
BUG_REPORT_URL="https://bugs.kali.org/"
ANSI_COLOR="1;31"

I'll understand if you've had enough testing, but I'd be glad if you tried again, or even if you just do the wsl --version to confirm we're both running compatible versions.

Cheers!
Luka

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests