WSL networking stopped working when upgrading from WSL 1 to WSL 2? Networking operations just hanging? Keep getting “Temporary failure in name resolution” all the time?

There are at least three known issues, all resulting from the combination of WSL 2 and a VPN. I will demonstrate with the Paloalto GlobalProtect solution, but other VPN clients have similar problems.

The issues are:

  1. VPN connections messing up the route from WSL 2 to the Windows host
  2. WSL 2 configured to auto-resolve nameservers when used with a VPN
  3. WSL 2 and VPN MTU mismatch leads to dropped connections

I will cover the first issue in this post.

What’s the deal?

WSL 2 contained significant changes in the network stack implementation. With WSL 2 the networking is done through a virtualized Ethernet adapter with its own unique IP address. This way is flexible but exposes WSL 2 to changes on the Windows host adapters. The differences between WSL 1 and WSL 2 lead to failure in many VPN scenarios.

The problem is a clash between the VPN adapter implementation and WSL 2. A VPN adapter needs to intercept local network traffic to tunnel it. It needs priority on all traffic flowing on the local machine to do so. Most implement this by registering a virtual network adapter with “InterfaceMetric” value 1. Run Get-NetAdapter and then Get-NetIPInterface in Powershell to have a look.

Get-NetAdapter

Get-NetIPInterface

On my machine, you see the VPN network adapter has a description of PANGP Virtual Ethernet Adapter #2, its name is Ethernet 3 and the interface index is 23. If you look at Ethernet 3 in the Get-NetIPInterface screenshot, you see the InterfaceMetric is 1. As high as it gets.

Windows selects how IP traffic flow by adding this metric to a similar route-specific metric on specific routes in your routing table. Adding the InterfaceMetric together with the route-specific metric of all routes in the system creates a table of prioritized active routes. It looks in this table to route all your IP packets. Run route print in Powershell to have a look.

RoutePrint

There are plenty of routes, but we are interested in the routes affecting the network in WSL 2. To find out which route those are, run ipconfig /all and check the IP and subnet mask of your WSL network adapter. Also, have a look at the IP of the VPN network adapter.

IPConfigall

On my machine, the IP for the WSL adapter is 172.20.176.1, and the subnet mask is 255.255.240.0. The IP of the VPN network adapter is 10.0.0.5.

If you run ip addr show eth0 inside WSL 2, you will find eth0 setup with an IP from the range defined by the WSL network adapter IP and subnet mask on the Windows host.

IPAddr

In my case, you can see eth0 was assigned 172.20.190.152.

It’s now easy to pick out the relevant rules from the routing table:

Network Destination Netmask Gateway Interface Metric
172.20.176.0 255.255.240.0 On-link 172.20.176.1 5001
172.20.176.0 255.255.240.0 On-link 10.0.0.5 1
172.20.176.1 255.255.255.255 On-link 172.20.176.1 5256

The exact numbers might differ, but the important bit is that every time your VPN turns on, a new active route for the WSL subnet with an effective metric of 1 is added to the routes. The new route routes all the traffic from WSL to the interface at 10.0.0.5, the VPN adapter. Metric 1 is the highest priority, so it takes precedence over the other two rules that default the traffic to the WSL virtual adapter. In short, the VPN “hijacks” the traffic.

On the surface, this makes sense. We want all the traffic to go through the VPN when the VPN is on. The only problem is.. the VPN will only forward traffic from the LOCAL COMPUTER, and the traffic coming from WSL 2 IS NOT considered your local computer. The VPN driver considers it as local network instead. Go figure!

So this is our problem in a nutshell: every time you VPN connects, it adds a high priority rule to the routing table for WSL 2. This route will route all WSL 2 traffic directly to the virtual adapter of the VPN. The adapter happily accepts and then drops it all into a black hole, effectively killing all network traffic.

What’s the fix?

Great! What’s the fix? Easy. We drop the priority route the VPN adds.

Once dropped, the routing will fall back on the other two lower-priority rules and route all the WSL 2 traffic to the Windows host. Once there, it will flow through the VPN as usual.

We drop a route with route delete. The command syntax is route delete <wsladapter_ip> mask <wsladapter_subnetmask> 0.0.0.0 IF <vpnadapter_interfaceindex>.

On my machine the final magic incantation is : route delete 172.20.176.0 mask 255.255.240.0 0.0.0.0 IF 23.

Once that rule is removed, traffic flows from WSL 2 through your Windows host and into the VPN again. BTW, you need to do this in an elevated Powershell terminal. And unfortunately, you have to do it every time the VPN turns on since the VPN will add the rule giving it priority again.

What’s not the fix?

I’ve seen people suggest a different “fix”. They set the InterfaceMetric of the VPN adapter to a very high value, like 6000. You can do that with a command like this Get-NetAdapter | Where-Object {$_.InterfaceDescription -Match "PANGP Virtual Ethernet Adapter"} | Set-NetIPInterface -InterfaceMetric 6000. This is not a good solution IMHO. A a high value of InterfaceMetric will prioritize every other network adapter over the VPN on the host machine. In effect, you are forcing ALL traffic to avoid the VPN, not just WSL 2! If that is an acceptable option, why not just turn the VPN off instead? Much easier. The whole point of a VPN is to tunnel the traffic through it. Any solution here will need to work THROUGH the VPN, not around it.

Sounds good, give me the exact steps to fix MY computer

  1. Use ipconfig /all and find your virtual WSL network adapter. On my machine this is called Ethernet adapter vEthernet (WSL) with a description of Hyper-V Virtual Ethernet Adapter #2. Note down the IPv4 adress and subnet mask, let’s call them wsladapter_ip and wsladapter_subnetmask.

    On my machine wsladapter_ip was 172.20.176.1 and the wsladapter_subnetmask was 255.255.240.0.

  2. Next, use the same ipconfig /all to find the virtual network adapter FOR YOUR VPN CONNECTION. The exact name of this adapter will vary depending on the VPN provider you use. In my case it’s Paloalto GlobalProtect and the network adapter is called Ethernet adapter Ethernet 3 with the description PANGP Virtual Ethernet Adapter #2. The description usually tells you which is the VPN adapter. Note down the IPv4; let’s call it vpnadapter_ip.

    On my machine, vpnadapter_ip was 10.0.0.5.

  3. Next up, we need to find the VPN adapter’s interface index(ifIndex). The Powershell command Get-NetAdapter is excellent for this.

    On my machine, PANGP Virtual Ethernet Adapter #2 had ifIndex = 23.

  4. Next, run route print in Powershell with the VPN turned on to print out all the routes in your system. It shows you how IP packets get routed by Windows.

    You should see a route with metric 1 from the WSL subnet to the interface of your VPN. In my case 172.20.176.0/255.255.240.0 to 10.0.0.5.

    Delete this rule in a elevated terminal. Again, the command syntax is route delete <network destination> mask <netmask> 0.0.0.0 IF <VPN network adapter ifIndex>.

    On my machine: route delete 172.20.176.0 mask 255.255.240.0 0.0.0.0 IF 23

  5. Re-run route print to make sure the rule is gone. If it’s still there, re-run the route delete command. For some reason, it sometimes takes a few tries before the rule is gone.

  6. At this point, you should be able to reach a known good public IP from inside WSL 2, for example, ping 8.8.8.8 (Google nameserver). You probably still have issues resolving hostnames, something I cover in another post.

Recap

So there you have it.

You can use WSL 2 networking with a VPN, but you will have to clear out this route by hand unless you automate it. You will have to delete this rule every time the VPN connects. Reuse the same route delete command as long as the WSL virtual network adapter IP stays the same.

Some enterprise VPN solutions offer the possibility to run scripts on connection events, which would be an excellent place to start for automation.