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. ๐