Work around for AnyConnect client and Windows Subsystem for Linux 2

When using the Cisco AnyConnect client and WSL2 you may find that your WSL environment loses network connectivity. Here is a work around.

When using the Cisco AnyConnect client and WSL2 you may find that your WSL environment loses network connectivity. Here is a work around.

We use the Cisco AnyConnect client to connect to our work VPN. We have split tunneling enabled where all traffic for specific subnets gets sent over the VPN connection. This includes the 172.16.x.x subnets (Class B). WSL 2 puts it's Linux distributions on a random part of that network, it changes during every reboot. One thing you could do is create a virtual NIC through Hyper-V and assign it an address in that subnet with a really big subnet mask, but that is dumb and breaks anything else you may have sitting in that network. Doing that will tell the subsystem to use a random 192.168.x.x/24 subnet. Also, not ideal.

The underlying issue is that when the client creates the VPN tunnel it assigns an interface metric of 1. Meaning, that all network traffic flows through it before it goes through any other interface. You can either manually change that metric every time you connect to the VPN or set up a scheduled task to do it. Since I like automatic, I'll go the task route. Here's everything you need to do it.

First, let's create the PowerShell script to do the work. I'm going to store this in c:\tools\anyconnectworkaround.ps1 It is a simple one-line script. All it does is find the adapters a description with Cisco in the name. You can adjust that to be more specific if you need. It then sets the interface metric to 6000. Which is higher than the other interfaces on your system. You can adjust higher or lower as necessary.

Get-NetAdapter | ? {$_.InterfaceDescription -like "*Cisco*" } |Set-NetIPInterface -InterfaceMetric 6000

Now that we have the script, we will create the task that will run whenever the VPN client establishes a connection.

In summary, the task will run as system with elevated privileges. It will trigger on a specific event in the Cisco AnyConnect Secure Mobility Client log looking for Event ID 3020. The action will be to start powershell.exe and execute the c:\tools\anyconnectworkaround.ps1 script.

Here are the detailed steps on creating that task:

  1. Open Scheduled Tasks
  2. In the right-hand pane, under Actions click Create Task...
  3. In the name put something descriptive, like AnyConnect Work Around
  4. Click the Change User or Group... button
  5. Type in system and click OK
  6. Check the Run with highest privileges
  7. Click the Triggers tab
  8. Click New...
  9. Change the Begin the task drop down to On an event
  10. Change the Log drop down to Cisco AnyConnect Secure Mobility Client
  11. Put 3020 in the Event ID box
  12. Click OK to close the trigger dialog
  13. Click the Actions tab
  14. Click New...
  15. Put powershell.exe in the Program/script box
  16. Put the path to your script in the Add arguments (optional) box. Example: c:\tools\anyconnectworkaround.ps1
  17. Click OK to close the action dialog
  18. Click OK to close the event dialog
  19. Now, if you are connected to the VPN, disconnect.
  20. Connect to the VPN
  21. Validate that you can get to the internet from your WSL2 installation. ping 8.8.8.8

Conclusion

AnyConnect is great. WSL2 is great. Combined, not so great. But with this workaround I am able to connect to the VPN and still use my WSL2 distributions and, more importantly, Docker (which sits in a WSL2 distribution). If I find that the metric is configurable in the AnyConnect client, I'll update this post. But as of now I do not know anyway of changing the metric through configuration.