Allowing Windows Subsystem for Linux to communicate with Hyper-V VMs
Howdy! ๐ Hope everyone's weekend is swell!
I was experimenting with Windows Subsystem for Linux and Hyper-V. I noticed that almost immediately that my Hyper-V Server 2019 virtual machine was unable to communicate with my Ubuntu 20.04 WSL system on the same host:
$ โฏ ping 172.25.0.196
PING 172.25.0.196 (172.25.0.196) 56(84) bytes of data.
-no data, timeout-
I do see that I can ping via PowerShell (same command). What's up here?๐ค Well, we have a Hyper-V VM on the same computer as the WSL system, so firewall shouldn't be a problem.
Let's investigate traffic forwarding.
Whatever network interface WSL is using might not be forwarding the traffic. We can test this with a traceroute:
Windows:
PS C:\WINDOWS\system32> tracert 172.25.0.196
Tracing route to OUR-HYPERV-HOST.mshome.net [172.25.0.196]
over a maximum of 30 hops:
1 <1 ms <1 ms <1 ms OUR-HYPERV-HOST.mshome.net [172.25.0.196]
WSL (needs traceroute installed via apt, if running Ubuntu):
$ โฏ traceroute 172.25.0.196
traceroute to 172.25.0.196 (172.25.0.196), 30 hops max, 60 byte packets
# this never finishes ๐
I know WSL has its own network. I verified this by running the following inside WSL:
$ โฏ cat /etc/resolv.conf
----
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.24.32.1
Which will display contents of the DNS resolver file telling you that WSL manages this.
Even in Hyper-V, there is a WSL virtual switch (running the below on the host system running Hyper-V)
PS C:\WINDOWS\system32> Get-VMSwitch
Name SwitchType NetAdapterInterfaceDescription
---- ---------- ------------------------------
Default Switch Internal
WSL Internal <--- interesting, huh ๐
Experimenting further, I grabbed all interfaces on my host system running Hyper-V. An interface called vEthernet (WSL) appears:
PS C:\WINDOWS\system32> Get-NetIPInterface
ifIndex InterfaceAlias AddressFamily NlMtu(Bytes) InterfaceMetric Dhcp ConnectionState PolicyStore
------- -------------- ------------- ------------ --------------- ---- --------------- -----------
52 vEthernet (WSL) IPv6 1500 5000 Enabled Connected ActiveStore
I then explored this WSL Interface and see the options I had available to me via the Get-Member cmdlet:
PS C:\WINDOWS\system32> Get-NetIPInterface | `
where {$_.InterfaceAlias -eq 'vEthernet (WSL)' -or `
$_.InterfaceAlias -eq 'vEthernet (Default Switch)'}| `
Get-Member
...
Forwarding ScriptProperty System.Object Forwarding `
{get=[Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetIPInterface.Forwarding]`
($this.PSBase.CimInstanceProperties['Forwarding'].Value);set=p...
...
There's an interesting scriptProperty for Forwarading.
One can logically assume this may enable Forwarding for us! Let's explore the Set-NetIPInterface PowerShell cmdlet and we will see that Forwarding is an argument we can set:
PS C:\WINDOWS\system32> help Set-NetIPInterface | `
Select-String -CaseSensitive:$false 'forwarding'
[-PolicyStore <string>] [-IncludeAllCompartments] `
**[-Forwarding {Disabled | Enabled}]** [-ClampMss {Disabled | Enabled}]`
[-Advertising {Disabled | Enabled}] [-NlMtuBytes <uint32>] `
[-InterfaceMetric <uint32>]
We know this has a value of Disabled or Enabled.
Let's give this a shot! We see that it seems like forwarding is not enabled and this may be the cause of our issue. Let's enable forwarding:
PS C:\WINDOWS\system32> Get-NetIPInterface | `
where {$_.InterfaceAlias -eq 'vEthernet (WSL)'} | `
Set-NetIPInterface -Forwarding Enabled -Verbose
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 52 -AddressFamily IPv4 -Store Active"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 52 -AddressFamily IPv6 -Store Active"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 52 -AddressFamily IPv6 -Store Persistent"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 52 -AddressFamily IPv4 -Store Persistent"
Okay we verify forwarding is now enabled:
PS C:\WINDOWS\system32> Get-NetIPInterface | where {$_.InterfaceAlias -eq 'vEthernet (WSL)'} | Select-Object ifIndex,InterfaceAlias,ConnectionState,Forwarding
PS C:\WINDOWS\system32> Get-NetIPInterface | where {$_.InterfaceAlias -eq 'vEthernet (WSL)'} | Select-Object ifIndex,InterfaceAlias,ConnectionState,Forwarding
ifIndex InterfaceAlias ConnectionState Forwarding
------- -------------- --------------- ----------
52 vEthernet (WSL) Connected Enabled
Let's try to ping and run a traceroute, from WSL:
$ โฏ traceroute 172.25.0.196
traceroute to 172.25.0.196 (172.25.0.196), 30 hops max, 60 byte packets
1 OUR-HYPER-V-HOST (172.24.32.1) 0.270 ms 0.263 ms 0.260 ms
Okay so we can traceroute now. But we cannot ping:
~ โฏ ping 172.25.0.196
PING 172.25.0.196 (172.25.0.196) 56(84) bytes of data.
-timeout, no data-
Let's try and enable this on both WSL and the Default interface for the host:
PS C:\WINDOWS\system32> Get-NetIPInterface | where {$_.InterfaceAlias -eq 'vEthernet (WSL)' -or $_.InterfaceAlias -eq 'vEthernet (Default Switch)'} | Set-NetIPInterface -Forwarding Enabled -Verbose
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 52 -AddressFamily IPv6 -Store Active"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 45 -AddressFamily IPv6 -Store Active"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 52 -AddressFamily IPv4 -Store Active"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 45 -AddressFamily IPv4 -Store Active"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 45 -AddressFamily IPv6 -Store Persistent"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 52 -AddressFamily IPv6 -Store Persistent"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 52 -AddressFamily IPv4 -Store Persistent"
VERBOSE: Performing operation "Set" on Target "NetIPInterface -InterfaceIndex 45 -AddressFamily IPv4 -Store Persistent"
Success! ๐ We have pings and traceroute works:
$ โฏ ping 172.25.0.196
PING 172.25.0.196 (172.25.0.196) 56(84) bytes of data.
64 bytes from 172.25.0.196: icmp_seq=277 ttl=127 time=0.389 ms
^C
--- 172.25.0.196 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.356/0.356/0.356/0.000 ms
$ โฏ traceroute 172.25.0.196
traceroute to 172.25.0.196 (172.25.0.196), 30 hops max, 60 byte packets
1 HOST (172.24.32.1) 0.288 ms 0.269 ms 0.265 ms
Hope this helps someone. ๐
About the author
I am a sysadmin who focuses on the Windows ecosystem (with a spattering of Linux ). I have a passion for the cloud, scripting and solving problems that engineers like me face daily.
Comments
Join the discussionThank you. It was very helpful.
You are welcome rejith kumar! Thank you for your feedback!
Very helpful with an exquisite pedagogic way; thank you :)
Thank you so much - this article is a live saver!
