Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save jian-dong/8834cf5481375bfafaf9a667ea84e2be to your computer and use it in GitHub Desktop.

Select an option

Save jian-dong/8834cf5481375bfafaf9a667ea84e2be to your computer and use it in GitHub Desktop.
Workaround for WSL2 network broken on VPN
# Overview
Internet connection and DNS routing are broken from WSL2 instances, when some VPNs are active.
The workaround breaks down into two problems:
1. Network connection to internet
2. DNS in WSL2
This problem is tracked in multiple microsoft/WSL issues including, but not limited to:
microsoft/WSL#5068
microsoft/WSL#4277
microsoft/WSL#4246
## Network connection
When the VPN connection is active, network traffic out of WSL2 is not passed to the internet. This is probably a problem with `vEthernet (Default Switch)`.
Changing the Interface Metric 1 -> 6000 for AnyConnect VPN Adapter resolves the connection issue, but this has to be done after each time the VPN connects.
By default, the Interface Metrics for AnyConnect are:
- IPv6: 6000
- IPv4: 1
`ping` times out from WSL Shell.
Changing the Interface Metrics for AnyConnect to:
- IPv6: 6000
- IPv4: 6000
`ping` to IP Addresses succeed, but still no DNS Resolution.
## DNS Resolution
When the VPN is active, the autogenerated `/etc/resolv.conf` does not work. The list of nameservers must be manually built to include some sane default DNS Name Servers and the DNS from the VPN.
First, disable automatically generating `/etc/resolv.conf`. `generateResolvConf` in `/etc/wsl.conf`.
Add the following configuration, or create the file if it doesn't exist. The path to this file is from the shell prompt of your WSL2 instance.
*/etc/wsl.conf*
```
[network]
generateResolvConf = false
```
Next, manually add the corportate DNS Server as the first `nameserver` in `/etc/resolv.conf`.
*/etc/resolv.conf*
```
nameserver <corporateDNS1>
nameserver <corporateDNS2>
nameserver 1.1.1.1
```
## Automatically update Interface Metric
To automate this, I put the PS command in a script and created a Task to run every time there is a network change.
### Save the script in a file
First, create the script. I have a 'scripts' directory in my user home, so I put it at:
**%HOMEPATH%\scripts\UpdateAnyConnectInterfaceMetric.ps1**
```
Get-NetAdapter | Where-Object {$_.InterfaceDescription -Match "Cisco AnyConnect"} | Set-NetIPInterface -InterfaceMetric 6000
```
You can save it where you want, just make sure to use that path in step 13 below.
### Create the scheduled task:
1. Open 'Task Scheduler'
2. Click "Create Task" on Right Sidebar
3. Name: Update Anyconnect Adapter Interface Metric for WSL2
4. Set Security Options
- Check box: 'Run with highest priveleges'
5. Select 'Triggers' Tab
6. Click 'New' at bottom of Window
7. Open 'Begin the task' drop-down
8. Select 'On an Event'
9. Configure Event:
- Log: 'Microsoft-Windows-NetworkProfile/Operational'
- Source: 'NetworkProfile'
- Event ID: '10000'
10. Click 'OK'
11. Select 'Actions' Tab
12. Click 'New'
13. Configure Action:
- Action: 'Start a Program'
- Program/script: 'Powershell.exe'
- Add arguments: '-ExecutionPolicy Bypass -File %HOMEPATH%\scripts\UpdateAnyConnectInterfaceMetric.ps1'
14. Click 'OK'
15. Select 'Conditions' Tab
16. Uncheck box:
- Power -> Start the task only if the computer is on AC Power
17. (optional) Check box:
- Network -> Start only if the following network connection is available
- Select your corporate network name (e.g. cisco.com)
- This will avoid running the script unnecessarily (startup, connect to new wifi, VPN not active)
18. Click 'OK'
When AnyConnect finishes connecting, a Powershell window pops up for a couple seconds and WSL can reach the network.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment