Skip to content

Instantly share code, notes, and snippets.

@pyther
Last active November 2, 2024 22:25
Show Gist options
  • Save pyther/b7c03579a5ea55fe431561b502ec1ba8 to your computer and use it in GitHub Desktop.
Save pyther/b7c03579a5ea55fe431561b502ec1ba8 to your computer and use it in GitHub Desktop.

WSL 2 Cisco AnyConnect Networking Workaround

Overview

WSL 2 uses a Hyper-V Virtual Network adapter. Network connectivity works without any issue when a VPN is not in use. However when a Cisco AnyConnect VPN session is established Firewall Rules and Routes are added which breaks connectivity within the WSL 2 VM. This issue is tracked WSL/issues/4277

Below outline steps to automatically configure the Interface metric on VPN connect and update DNS settings (/etc/resolv.conf) on connect/disconnect.

Manual Configuration

Set Interface Metrics

After connecting to the VPN, you'll want to modify the Interface Metric of the Cisco VPN Adapter

PS C:\Users\gyurgyik> Get-NetAdapter | Where-Object {$_.InterfaceDescription -Match "Cisco AnyConnect"} | Set-NetIPInterface -InterfaceMetric 6000

Run the following command in Powershell with Administrative permission.

At this point you should have connectivity in your container (but without name resolution). You can test this by running ping 8.8.8.8.

Set DNS servers in Linux VM

Once connected the VPN determine the DNS servers that are configured:

PS C:\Users\gyurgyik> (Get-NetAdapter | Where-Object InterfaceDescription -like "Cisco AnyConnect*" | Get-DnsClientServerAddress).ServerAddresses
10.10.0.124
10.10.0.132

Update /etc/resolv.conf

N-20S5PF20MB4R:~$ cat /etc/resolv.conf
nameserver 10.10.0.124
nameserver 10.10.0.132

Verify Connectivity

ping google.com -c 4

Automatic Configuration

Create Scripts

Save the following scripts to %homepath%\wsl\scripts

setCiscoVpnMetric.ps1

Get-NetAdapter | Where-Object {$_.InterfaceDescription -Match "Cisco AnyConnect"} | Set-NetIPInterface -InterfaceMetric 6000

setDns.ps1

$dnsServers = (Get-NetAdapter | Where-Object InterfaceDescription -like "Cisco AnyConnect*" | Get-DnsClientServerAddress).ServerAddresses -join ','
$searchSuffix = (Get-DnsClientGlobalSetting).SuffixSearchList -join ','

function set-DnsWsl($distro) {
    if ( $dnsServers ) {    
        wsl.exe -d $distro -u root /opt/wsl_dns.py --servers $dnsServers --search $searchSuffix
    }
    else {
        wsl.exe -d $distro -u root /opt/wsl_dns.py
    }
}

set-DnsWsl fedora

wsl_dns.py

Download from: https://gist.githubusercontent.com/pyther/20bba4aee1a7e1485dd065adbf736891/raw/bb00f46d30da1b1eb7ba0fec4e6946a654c7b186/wsl_dns.py

Disable WSL Resolv Update

For each Linux instance:

  1. Disable automatic updating of resolv.conf by WSL
    $ cat <<EOF > /etc/wsl.conf
    [network]
    generateResolvConf = false
    EOF
    
  2. Restart/Shutdown WSL: wsl --shutdown (WARNING: this will kill all current sessions!)

Copy wsl_dns.py to Linux VMs

For each VM, run:

$ cp /mnt/c/Users/$username/wsl/scripts/wsl_dns.py /opt/wsl_dns.py
$ chmod +x /opt/wsl_dns.py

Create Scheduled Tasks

Windows Scheduled Tasks allows you to trigger an action when a certain log event comes in. The Cisco AnyConnect VPN client generates a number of log events.

We will create two tasks. The first task, will configure the interface metric when the VPN connects. The second task, will execute the dns update script inside of your Linux VM when the VPN Connects and Disconnects.

Cisco AnyConnect Events

  • 2039: VPN Established and Passing Data
  • 2061: Network Interface for the VPN has gone down
  • 2010: VPN Termination
  • 2041: The entire VPN connection has been re-established.

Procedure

  1. Open Task Scheduler
  2. Create a Folder called WSL (Optional, but easier to find rules later)
  3. Create Rules
    1. Update AnyConnect Adapter Interface Metric for WSL2
      • General: Check: Run with highest privileges
      • Triggers:
        • On an Event, Log: Cisco AnyConnect Secure Mobility Client, Source: acvpnagent, Event ID: 2039
        • On an Event, Log: Cisco AnyConnect Secure Mobility Client, Source: acvpnagent, Event ID: 2041
      • Action: Start a program, Program: Powershell.exe, Add arguments: -WindowStyle Hidden -NonInteractive -ExecutionPolicy Bypass -File %HOMEPATH%\wsl\scripts\setCiscoVpnMetric.ps1
      • Condition: Uncheck: Start the task only if the computer is on AC power
    2. Update DNS in WSL2 Linux VMs
      • Triggers:
        • On an Event, Log: Cisco AnyConnect Secure Mobility Client, Source: acvpnagent, Event ID: 2039
        • On an Event, Log: Cisco AnyConnect Secure Mobility Client, Source: acvpnagent, Event ID: 2010
        • On an Event, Log: Cisco AnyConnect Secure Mobility Client, Source: acvpnagent, Event ID: 2061
        • On an Event, Log: Cisco AnyConnect Secure Mobility Client, Source: acvpnagent, Event ID: 2041
        • At log on: At log on of $USER
      • Action: Start a program, Program: Powershell.exe, Add arguments: -WindowStyle Hidden -NonInteractive -ExecutionPolicy Bypass -File %HOMEPATH%\wsl\scripts\setDns.ps1
      • Condition: Uncheck: Start the task only if the computer is on AC power
  4. Test: Connect to the VPN, a powershell window should pop-up briefly

FAQ

Q: Does traffic orginating from the Linux VM still route through the VPN?
A: Yes, I believe so. I did not see any leaked traffic when running a tcpdump on my router.

Q: Are VPN resources accessible from the Linux VM?
A: Yes

Q: Can the Linux VM communicate with Windows?
A: No, it appears a firewall rule is preventing traffic between Windows and the Linux VM.

Q: Can I still run WSL1 instances?
A: Yes, you can run WSL1 and WSL2 insatnces simutaneously

Q: How do I revert/disable these changes?
A: Disable scheduled Tasks, remove/modify /etc/wsl.conf from each WSL Instance, Reboot

@jacob-pro
Copy link

jacob-pro commented Jun 6, 2022

Thanks for this @pyther

It has inspired me to create a slightly easier to use / more reliable version of the wsl_dns.py utility: https://github.com/jacob-pro/wsl2-dns-agent

One of the main things I found was this bug: microsoft/WSL#6977
It causes /etc/resolv.conf to get overwritten when a WSL2 distribution shuts down, this is especially a problem in Windows 11, because they get shutdown automatically due to vmIdleTimeout. I was able to work around it by setting (and unsetting) the read only flag on the file.

Another problem I noticed is that you have to be very careful with modifying the metric on the anyconnect adapter, because it will then have a lower internet metric than your Ethernet/WiFi - for me this caused DNS in Windows to take up to 10s as it tried those DNS servers first - the solution was to increase those metrics to then be higher than the anyconnect adapter!

@brianott
Copy link

I think it's really awesome you posted this to help people!

@PrinceS17
Copy link

Thanks @pyther. Want to add something in case someone needs it. Have been using this for a while, but recently stopped working. I figured out that in my case the name of the application and source should be changed to "Cisco Secure Client - AnyConnect VPN" and csc_vpnagent. Not sure if it's general since some cisco update. These can be double-checked using Event Viewer.

@ikorchynskyi
Copy link

Thanks @PrinceS17,
This was exactly my case. It is clearly connected with the recent Cisco VPN client update

@dg424
Copy link

dg424 commented Oct 20, 2023

I have disabled ipv6 on the adapters to get around this issue.

@markcaudill
Copy link

I have disabled ipv6 on the adapters to get around this issue.

Are you saying disabling IPv6 on your interfaces complete fixed the entire AnyConnect WSL2 issue or something more specific?

@dg424
Copy link

dg424 commented Oct 20, 2023

Yep, fixed everything.

@dusweaver
Copy link

This worked for me. Thank you so much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment