microsoft / WSL

Issues found on WSL
https://docs.microsoft.com/windows/wsl
MIT License
17.23k stars 808 forks source link

Windows Defender Firewall blocks access from WSL2 #4139

Closed dmchurch closed 3 months ago

dmchurch commented 5 years ago
jeffshantz commented 5 years ago

I have the same issue. It would also be nice if it were possible to change the network profile of the vEthernet adapter that WSL2 creates to Private. This way, we could at least disable the firewall for private networks. I tried doing this in PowerShell, but PS claims the adapter doesn't exist (I'm using the correct alias):

PS C:\Users\Jeff> Set-NetConnectionProfile -InterfaceAlias "vEthernet (WSL)" -NetworkCategory Private
Set-NetConnectionProfile : No MSFT_NetConnectionProfile objects found with property 'InterfaceAlias' equal to
'vEthernet (WSL)'.  Verify the value of the property and retry.
At line:1 char:1
+ Set-NetConnectionProfile -InterfaceAlias "vEthernet (WSL)" -NetworkCa ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (vEthernet (WSL):String) [Set-NetConnectionProfile], CimJobException
    + FullyQualifiedErrorId : CmdletizationQuery_NotFound_InterfaceAlias,Set-NetConnectionProfile
faymek commented 5 years ago

I want to connect from WSL2 to X410. And this works currently: Check Settings -> Firewall -> Advance Settings. In the opened window, check in-site rules, you can find TCP & UDP rules of X410. You can double click each rule, switch to advance tab in the dialog, check on all three checkboxes: domain, private, universal. This changes the profile private to all.

For xeyes demo:

sudo apt install libgtk2.0-0 libxss1 libasound2
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0.0
sudo apt install x11-apps -y && xeyes
jovton commented 4 years ago

Allowing traffic for Public networks via firewall rules works as described by @faymek, But it's kind-of working on my nerves security-wise.

So I tried to make the network private using the tricks mentioned here and here, but to no avail. Even after disabling and re-enabling the device (vEthernet (WSL) / Hyper-V Virtual Ethernet Adapter) the firewall still blocks it. And rebooting the host recreates the keys in the registry. I even tried protecting the keys with access permissions, but Windows can still overwrite them on reboot.

sandric commented 4 years ago

@jovton also having the same problem. After disabling public profile vEthernet WSL rule - it works untill reboot. Tried with admin privileges also - button "apply" is simply disabled, all you can do is either "OK" or "Cancel" - which in term disabling defender rule for current session only.

Is there any solution to this? Or maybe script I can run at startup to make it automatic?

paul-reilly commented 4 years ago

@sandric: I wrote this PS script to deal with the WSL2 IP address changing on reboot:

https://github.com/paul-reilly/WSL2-Xming-Init

It works with firewall active on my machine at least.

rob-solana commented 4 years ago

upon reboot, I disable the firewall on the WSL2 interface with an Administrator Powershell:

Copyright (C) Microsoft Corporation. All rights reserved.

Try the new cross-platform PowerShell https://aka.ms/pscore6

PS C:\WINDOWS\system32> Set-NetFirewallProfile -DisabledInterfaceAliases "vEthernet (WSL)"

this only works after I've launched the X client that is trying to talk to my VcXsrv

I launch my X client (xterm) with a desktop shortcut whose "Target" is set to:

C:\Windows\System32\wsl.exe /mnt/c/Users/me/wslrun.sh /usr/bin/X11/xterm -ls

Where wslrun.sh is:

#!/bin/bash
exec 1> wslrun.log 2>&1

PATH=/usr/bin:/bin
# DISPLAY to default gateway
ip_r_l_default=( $(ip r l default) )
export DISPLAY=${ip_r_l_default[2]}:0.0
cd ~
nohup "$@" &
# don't understand why I need this sleep
sleep 1

Tedious parts of this:

  1. the Powershell script, which has to run on every reboot
  2. the fact that the WSL2 interface dies whenever I change WiFi networks (all X clients die, poo)
jefferai commented 4 years ago

Just chiming in that it was very unintuitive to figure out that the network being created was marked public and that's why I couldn't actually access host services due to the firewall. I'd expect it to be marked private.

a-schaefers commented 4 years ago

I have the same issue. It would also be nice if it were possible to change the network profile of the vEthernet adapter that WSL2 creates to Private. This way, we could at least disable the firewall for private networks. I tried doing this in PowerShell, but PS claims the adapter doesn't exist (I'm using the correct alias):

PS C:\Users\Jeff> Set-NetConnectionProfile -InterfaceAlias "vEthernet (WSL)" -NetworkCategory Private
Set-NetConnectionProfile : No MSFT_NetConnectionProfile objects found with property 'InterfaceAlias' equal to
'vEthernet (WSL)'.  Verify the value of the property and retry.
At line:1 char:1
+ Set-NetConnectionProfile -InterfaceAlias "vEthernet (WSL)" -NetworkCa ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (vEthernet (WSL):String) [Set-NetConnectionProfile], CimJobException
    + FullyQualifiedErrorId : CmdletizationQuery_NotFound_InterfaceAlias,Set-NetConnectionProfile

This would just be a workaround and is not good.

All you need to do is add an inbound firewall rule using the program name

C:\Program Files\VcXsrv\vcxsrv.exe

fquinner commented 4 years ago

For the record, I added some more surgical options and documented here:

https://github.com/cascadium/wsl-windows-toolbar-launcher#firewall-rules

For me though the ideal solution would be for this to work:

https://github.com/microsoft/WSL/issues/4619

drewhemm commented 4 years ago

Confirmed adding the firewall rule and limiting the source IP scope range works. Functional and secure!

Firewall

wmertens commented 4 years ago

Just a note, the settings from the above comment work for me, but I had trouble finding them: control panel > system and security > windows defender firewall > advanced settings > inbound rules > edit the vcxvsrv rule for public networks.

Also, since the hostname is in the DNS forwarder, you can do

export DISPLAY=$(host $HOST | head -n1 | cut -d' ' -f4):0

to set the display

QingGo commented 4 years ago

Confirmed adding the firewall rule and limiting the source IP scope range works. Functional and secure!

Firewall

I tried this method but it didn't work. After some searching I find that there are two block rule of "VcXsrv windows xserver" in my firewall rule list and these rules take precedence. Windows OS will add rules to your firewall when you first start VcXsrv windows xserver, and you should disable these rules manually(not remove it, or Windows OS will try to add it again when you open VcXsrv next time).

Fubuchi commented 4 years ago

@QingGo You just need to edit the TCP rule for "VcXsrv windows xserver" from Block to Allow, no need to disable and create a new rule. I have successfully used this approach to allow WSL 2 connect to a Postgres SQL installed on Windows.

P/S: can someone enlighten me why we limit the IP range to 172.16.0.0/12 ?

fquinner commented 4 years ago

@QingGo You just need to edit the TCP rule for "VcXsrv windows xserver" from Block to Allow, no need to disable and create a new rule. I have successfully used this approach to allow WSL 2 connect to a Postgres SQL installed on Windows.

P/S: can someone enlighten me why we limit the IP range to 172.16.0.0/12 ?

It's a standard private ip subnet range that wsl seems to rattle around:

https://tools.ietf.org/html/rfc1918

Fubuchi commented 4 years ago

WSL may pick the ip range 192.168.0.0/16 too:

image

This firewall setting should cover all case

image

wmertens commented 4 years ago

Hmm if you add that range, you get most home networks, and there's some chance of an attack via a compromised printer or whatever. Granted, very unlikely but not impossible.

The rule should only allow connections from the local pc.

Fubuchi commented 4 years ago

Because powershell allows we to modify firewall rule, so I think writing a script to update wsl 2 ip address for each inbound rules maybe a good idea, we only need to create the rules manually once and run the script after windows startup. Some thing like this: (run in admin shell)

Import-Module -Name 'NetSecurity'

$wsl2Ip = wsl.exe /bin/bash -c "ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'"

Get-NetFirewallRule -Direction Inbound | Where-Object {
    $_.DisplayName -eq "postgres.exe" `
        -and ($_ | Get-NetFirewallPortFilter).Protocol -eq "TCP"
} | ForEach-Object {
    Set-NetFirewallRule -Name $_.Name -RemoteAddress $wsl2Ip
}
cybtachyon commented 4 years ago

Related to https://github.com/microsoft/WSL/issues/4150

This is the script I use, run via Task Scheduler on login, sourced from https://github.com/microsoft/WSL/issues/4150 :

$remoteip = wsl.exe /bin/bash -c "ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'"
$found = $remoteip -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if( !$found ){
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

#[Ports]

#All the ports you want to forward separated by comma
$ports=@(80,8080,443,10000,3000,5000);

#[Static ip]
#You can change the addr to your ip config to listen to a specific address
$addr='0.0.0.0';
$ports_a = $ports -join ",";

#Remove Firewall Exception Rules
iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";

#adding Exception Rules for inbound and outbound Rules
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_a -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -RemoteAddress $remoteip -Action Allow -Protocol TCP";

for( $i = 0; $i -lt $ports.length; $i++ ){
  $port = $ports[$i];
  iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$addr";
  iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$addr connectport=$port connectaddress=$remoteip";
}
PavelSosin-320 commented 4 years ago

Cross WSL 2 distro access via ports published to Windows host should work bypassing all firewalls. Am I right? In the case of Docker Desktop Kubernetes integration using HTTP port 6443 works well. Is it a firewall issue or something else, like of difference between Kubernetes and Docker proxy implementation?

hwo411 commented 4 years ago

https://github.com/microsoft/WSL/issues/4585#issuecomment-610061194 Might be helpful for solving firewall problem.

therealkenc commented 4 years ago

4585 (comment) Might be helpful for solving firewall problem.

Inlining here since this issue ended up being the landing zone. Props go to @dansanduleac

New-NetFirewallRule -DisplayName "WSL" -Direction Inbound  -InterfaceAlias "vEthernet (WSL)"  -Action Allow
kppullin commented 4 years ago

4585 (comment) Might be helpful for solving firewall problem.

Inlining here since this issue ended up being the landing zone. Props go to @dansanduleac

New-NetFirewallRule -DisplayName "WSL" -Direction Inbound  -InterfaceAlias "vEthernet (WSL)"  -Action Allow

I've found that this configuration does not persist across Windows reboots. Actually I think the rule does persist, it just stops working and I have to create another copy of the rule. Is this a me problem or more general? Running the regular, non-insider 2004 build.

therealkenc commented 4 years ago

I've found that this configuration does not persist across Windows reboots

I think (but can't prove) that is because the WSL interface is transient as opposed to a permanent fixture of a WSL install. The hangout for that is open issues #4467 #4210 et al.

hwo411 commented 4 years ago

In my setup I created one init script for WSL2 and one PowerShell script which set up windows settings. WSL script calls powershell script.

I call it when I need it for Android development, that's how it works for me. I created PowerShell script because multiple commands are required and they require administrator priveleges. I did it to reduce the number of times I need to click "Yes" in Windows to 1 :)

zosoabi commented 3 years ago

The following workaround works for me:

Set-NetFirewallProfile -Name $(Get-NetConnectionProfile).NetworkCategory -DisabledInterfaceAliases $(Get-NetAdapter | Where-Object Name -like 'WSL').Name

drdamour commented 3 years ago

The following workaround works for me:

Set-NetFirewallProfile -Name $(Get-NetConnectionProfile).NetworkCategory -DisabledInterfaceAliases $(Get-NetAdapter | Where-Object Name -like 'WSL').Name

Sure until GPO reapplies it

zosoabi commented 3 years ago

The following workaround works for me: Set-NetFirewallProfile -Name $(Get-NetConnectionProfile).NetworkCategory -DisabledInterfaceAliases $(Get-NetAdapter | Where-Object Name -like 'WSL').Name

Sure until GPO reapplies it

The following GPO section could help too:

Computer Configuration -> Policies -> Windows Settings -> Scripts (Startup / Shutdown)

transiient commented 3 years ago

This works, even persists after a reboot. Basically what was already suggested, but using the interface name instead of IP (the IP changes, the interface name does not).

Run this in an elevated PowerShell: New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow

Credit to @dansanduleac in this comment.

avzero07 commented 3 years ago

I inspected the "WSL" rule using the Windows Defender Firewall application and it seems like an allow-everything type of inbound rule. Even if you try creating a new rule via the wizard in the Widows Defender Firewall application, it doesn't give you any option to choose the adapter.

I could be wrong but it seems like the -InterfaceAlias is not doing anything in that PS command and all we're setting is up is a very generic inbound rule that allows all traffic inbound (seems very unsafe).

Could someone please explain how we can confirm that the rule which is set up using that command is specifically tied to inbound connections coming in through the vEthernet adapter?

rmja commented 3 years ago

I found the following to work for me: Open windows firewall settings, and remove the vEthernet (WSL) connection for each of the Domain, Private, and Public profiles: image

veliebm commented 3 years ago

I was having trouble getting my X11 server to work with WSL2, but I fixed it after reading this thread. I had to allow VcXsrv to communicate through my firewall. Appreciate your help everyone 🙂

avzero07 commented 3 years ago

I found the following to work for me: Open windows firewall settings, and remove the vEthernet (WSL) connection for each of the Domain, Private, and Public profiles: image

@rmja excellent. I think what you propose here is the best solution! You can just uncheck vEthernet instead of configuring a risky inbound firewall rule.

noseratio commented 3 years ago

I found the following to work for me:

@rmja and @avzero07, is it not the same as Set-NetFirewallProfile -DisabledInterfaceAliases "vEthernet (WSL)" from above in this thread?

Between this and New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow (also from this thread) I'd pick the latter because it doesn't result in the alerted Windows Firewall icon in the systray.

Ideally, it'd be great to have a separate Network Profile (under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkList\Profiles) for vEthernet (WSL), which we could then set to Public or Private similar to what we can do for WiFi.

I've been looking at this, but I haven't figured out yet how to create a custom Windows Network Profile and assign an interface to it.

Updated: following this similar Docker issue, I've tried adding *NdisDeviceType to the vEthernet (WSL) registry key under HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class. The goal was make it appear under a separate Windows network profile, so I could use Set-NetConnectionProfile -InterfaceAlias 'vEthernet (WSL)' -NetworkCategory Private to make it private.

Sadly, that did not work and *NdisDeviceType disappeared after a reboot.

Then I tried to create a new profile manually: New-CimInstance -Namespace root/StandardCimv2 -ClassName MSFT_NetConnectionProfile -Property @{Name="WSL"}, so I could try adding vEthernet (WSL) to it somehow. This produced an error: The requested operation is not supported.

piotrmocko commented 3 years ago

I did the following to make it working with Bitdefender Firewall as above solutions did not resolve it.

  1. Create file %USERPROFILE%\wsl-eth0.cmd with the following content and replace 192.168.33.17 with the desired IP address

    @echo off
    wsl -d Ubuntu -u root ip addr replace 192.168.33.17/24 broadcast 192.168.33.255 dev eth0 label eth0:1
    netsh interface ip add address "vEthernet (WSL)" 192.168.33.27 255.255.255.0
  2. Open start menu, type run. Then type shell:startup. Create file wsl-eth0.vbs with the following content

    Set WinScriptHost = CreateObject("WScript.Shell")
    WinScriptHost.Run Chr(34) & "%USERPROFILE%\wsl-eth0.cmd" & Chr(34), 0
    Set WinScriptHost = Nothing
  3. Bitdefender Firewall setup

  1. After restarting the computer run ip addr show eth0 on WSL to get the IP address of your Ubuntu machine and confirm that it is the one you set above.
iancward commented 3 years ago

If the profile was set to Private by default, none of his hokey firewall business would be required. And considering its a NAT Interface behind the main host networkk(s), it's certainly a private network.

In the interim, it would be nice to set it manually as a Private Interface, but on Windows 10 Home, it doesn't show up in the list of adapters in the Control Panel and does not show up in a Get-NetConnectionProfile cmdlet call in PowerShell. The only thing it shows up in is an ipconfig /all call.

cameronkerrnz commented 3 years ago

Note that if you have a machine (like my work-managed laptop) that has local firewall rules turned off by GPO...

image

...then the following won't work for you:

New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow

You can (I think) infer this by the following line from the result from Net-NetFirewallRule: "EnforcementStatus: NotApplicable"

You should get the equivalent rule added by your domain administrators... maybe create an OU for power-users or developers etc.

But when you can't (yet) get it done via appropriate firewall policy, the following will work, with the priviso that Windows Defender will raise this as an insecurity.

Set-NetFirewallProfile -DisabledInterfaceAliases "vEthernet (WSL)"

TSlivede commented 3 years ago

Regarding this option:

New-NetFirewallRule -Name "WSL" -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow

@avzero07 asked:

I inspected the "WSL" rule using the Windows Defender Firewall application and it seems like an allow-everything type of inbound rule. Even if you try creating a new rule via the wizard in the Widows Defender Firewall application, it doesn't give you any option to choose the adapter.

I could be wrong but it seems like the -InterfaceAlias is not doing anything in that PS command and all we're setting is up is a very generic inbound rule that allows all traffic inbound (seems very unsafe).

Could someone please explain how we can confirm that the rule which is set up using that command is specifically tied to inbound connections coming in through the vEthernet adapter?

You can check that the rule only applies to the named interface using this command:

Get-NetFirewallInterfaceFilter -AssociatedNetFirewallRule (Get-NetFirewallRule -DisplayName "WSL")

Output should be:

InterfaceAlias : vEthernet (WSL)

(Just to be sure I tested to connect to an open port on my PC from my phone, and indeed the created rule does not open the ports for my main network interface, it only opens the ports for the WSL interface.)


@kppullin mentioned:

I've found that this configuration does not persist across Windows reboots. Actually I think the rule does persist, it just stops working and I have to create another copy of the rule. Is this a me problem or more general? Running the regular, non-insider 2004 build.

Yes, sadly after a reboot the rule doesn't work anymore:

Get-NetFirewallInterfaceFilter -AssociatedNetFirewallRule (Get-NetFirewallRule -DisplayName "WSL")

printed

InterfaceAlias : eb3a4260-024a-4a60-8f01-58c27bd975dd

after I rebooted.

The rule can be modified to work again after reboot, no need to recreate:

Get-NetFirewallInterfaceFilter -AssociatedNetFirewallRule (Get-NetFirewallRule -DisplayName 'WSL')|Set-NetFirewallInterfaceFilter -InterfaceAlias 'vEthernet (WSL)'
Automate adjusting of firewall rule (only works if you have admin rights): Create a task in the windows taskscheduler (taskschd.msc), that runs as your useraccount, "Run only when user is logged on", "Run with highest privileges":

The task doesn't need any triggers, and the action should be:
cmd /c start "" /min powershell -WindowStyle hidden -c Get-NetFirewallInterfaceFilter -AssociatedNetFirewallRule (Get-NetFirewallRule -DisplayName 'WSL')^|Set-NetFirewallInterfaceFilter -InterfaceAlias 'vEthernet (WSL)'
The command uses cmd /c start "" /min to avoid a flashing window. Note the carret (^) before the pipe to ensure that cmd doesn't interpret the pipe for itself and instead sends it to powershell.
After this preparation add
schtasks.exe /run /tn "\\name of your task"
to your ~/.bashrc to run the task at each execution of WSL.

If even after creating the rule a connection can't be established, ensure that no blocking rules accidentally exist.

If an application tries to open a port, you typically get a message like this (sorry for the german localization of Windows 🤷‍♂️): firewall question After accepting that dialog, Windows will not only create allow rules for the selected profiles, but also block rules for the not selected profiles: firewall result You need to delete those created block rules (in wf.msc), otherwise the connection is refused because these block rules are more important than our created "WSL" allow rule.

Note: even if you pressed "Cancel" in the firewall question dialog, the block rules will be created...

DachuanZhao commented 3 years ago

Any processing ? It causes this https://github.com/microsoft/WSL/issues/5211

ryanspletzer commented 3 years ago

I found the following to work for me: Open windows firewall settings, and remove the vEthernet (WSL) connection for each of the Domain, Private, and Public profiles: image

This needs to be bumped because I spent way too long spelunking for a fix for this and this was it.

ryanspletzer commented 3 years ago

Agree though that ability to set vEthernet (WSL) to Private net connection profile would be the ideal workaround/real fix...

ryanspletzer commented 3 years ago

FWIW I'm on a Windows Hello for Business machine (non-domain-joined - Azure AD joined only w/ Intune etc. -- so it's not using Group Policy) and I was able to adjust the Group Policy setting for merging local firewall policies alone to get things working. I've rebooted the machine and it's persisted and still working.

I realize this may not apply for everyone if they're domain-joined and a scheduled Group Policy enforcement swings around and explicitly resets this to "No," but wanted to throw it out there. You may be surprised and find out that it's not explicitly set to "No" by Group Policy and that it's actually set to "Not Configured," so you may be able to set it explicitly, if not through the Group Policy UI then perhaps through the registry directly.

This is the registry key and property:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\WindowsFirewall\PublicProfile

AllowLocalPolicyMerge: 1

To set via PowerShell:

$path = 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsFirewall\PublicProfile'
if (-not (Test-Path -Path $path)) {
    New-Item -Path $path
}

New-ItemProperty -Path $path -Name AllowLocalPolicyMerge -Value 1

At the very least if that doesn't fix it entirely, it should at least open up the ability to add a local firewall rule to do so. (As a side note: I wonder if fully opening up the firewall is necessary or if you just need select ports -- really port 53 UDP was the issue for me for DNS resolution which is mentioned in other issues.)

image

image

meijieru commented 2 years ago

Everything is OK if I disable the firewall for the public network.

However, I tried both New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow and @rmja 's solution, none of them work. Get-NetFirewallInterfaceFilter -AssociatedNetFirewallRule (Get-NetFirewallRule -DisplayName "WSL") gives me InterfaceAlias : vEthernet (WSL)

Do you have any suggestions?

cameronkerrnz commented 2 years ago

@meijieru Suggest you turn on the firewall log within Windows Defender Firewall for packets being dropped, that will allow you to see what is being blocked.

Chaz6 commented 2 years ago

Windows firewall ultimately makes me less secure. I cannot apply a rule that applies only to the WSL network adapter, which means the only way to make this work is either manually check and add the specific ipv4 /32 (why no IPv6 support?), or create a general rule for 172.19.240.0/20 applied to networks of type public (and hope that when I am roaming that the foreign LAN does not use those addresses, otherwise I am left vulnerable), and interface type local area network. It would be much more useful if I could apply a rule that applied to the specific WSL network adapter.

rlnt commented 2 years ago

I found the following to work for me: Open windows firewall settings, and remove the vEthernet (WSL) connection for each of the Domain, Private, and Public profiles: image

I am also using this as the working solution but this will result in Windows yelling at you that you no longer use the recommended firewall configuration. Anyone with a solution for that? Also this does not save across reboots.

pduchnovsky commented 2 years ago

FWIW I'm on a Windows Hello for Business machine (non-domain-joined - Azure AD joined only w/ Intune etc. -- so it's not using Group Policy) and I was able to adjust the Group Policy setting for merging local firewall policies alone to get things working. I've rebooted the machine and it's persisted and still working.

I realize this may not apply for everyone if they're domain-joined and a scheduled Group Policy enforcement swings around and explicitly resets this to "No," but wanted to throw it out there. You may be surprised and find out that it's not explicitly set to "No" by Group Policy and that it's actually set to "Not Configured," so you may be able to set it explicitly, if not through the Group Policy UI then perhaps through the registry directly.

This is the registry key and property:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\WindowsFirewall\PublicProfile

AllowLocalPolicyMerge: 1

To set via PowerShell:

$path = 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsFirewall\PublicProfile'
if (-not (Test-Path -Path $path)) {
    New-Item -Path $path
}

New-ItemProperty -Path $path -Name AllowLocalPolicyMerge -Value 1

At the very least if that doesn't fix it entirely, it should at least open up the ability to add a local firewall rule to do so. (As a side note: I wonder if fully opening up the firewall is necessary or if you just need select ports -- really port 53 UDP was the issue for me for DNS resolution which is mentioned in other issues.)

image

image

I improved upon your script so it also checks whether the value exists or not, also after allowing local rules merging 'default' dns started working so no longer need to add dns servers to resolv.conf..

# Powershell as admin
$path = 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsFirewall\PublicProfile'
if (-not (Test-Path -Path $path)) {
    New-Item -Path $path
}
if ((Get-ItemProperty $path).PSObject.Properties.Name -contains "AllowLocalPolicyMerge") {
    Set-ItemProperty -Path $path -Name AllowLocalPolicyMerge -Value 1
} else {
    New-ItemProperty -Path $path -Name AllowLocalPolicyMerge -Value 1
}
# I had to reboot to apply changes in registry

As mentioned this only works for PCs not using GPO, therefore as an alternative there is also this piece of code to create a task to disable FW on the WSL interface altogether, however, as mentioned above, this comes with a side effect of notification that fw is disabled.

# CMD.exe/powershell as admin
schtasks /create /tn "WSL disable FW" /sc onlogon /delay 0000:15 /rl highest /ru system /tr "C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -Command 'Set-NetFirewallProfile -DisabledInterfaceAliases ''vEthernet (WSL)'''"

Edit: seems it's not persistent even this way.. needs to be re-run manually, unlucky.

pduchnovsky commented 2 years ago

FWIW I'm on a Windows Hello for Business machine (non-domain-joined - Azure AD joined only w/ Intune etc. -- so it's not using Group Policy) and I was able to adjust the Group Policy setting for merging local firewall policies alone to get things working. I've rebooted the machine and it's persisted and still working. I realize this may not apply for everyone if they're domain-joined and a scheduled Group Policy enforcement swings around and explicitly resets this to "No," but wanted to throw it out there. You may be surprised and find out that it's not explicitly set to "No" by Group Policy and that it's actually set to "Not Configured," so you may be able to set it explicitly, if not through the Group Policy UI then perhaps through the registry directly. This is the registry key and property: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\WindowsFirewall\PublicProfile AllowLocalPolicyMerge: 1 To set via PowerShell:

$path = 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsFirewall\PublicProfile'
if (-not (Test-Path -Path $path)) {
    New-Item -Path $path
}

New-ItemProperty -Path $path -Name AllowLocalPolicyMerge -Value 1

At the very least if that doesn't fix it entirely, it should at least open up the ability to add a local firewall rule to do so. (As a side note: I wonder if fully opening up the firewall is necessary or if you just need select ports -- really port 53 UDP was the issue for me for DNS resolution which is mentioned in other issues.) image image

I improved upon your script so it also checks whether the value exists or not, also after allowing local rules merging 'default' dns started working so no longer need to add dns servers to resolv.conf..

# Powershell as admin
$path = 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsFirewall\PublicProfile'
if (-not (Test-Path -Path $path)) {
    New-Item -Path $path
}
if ((Get-ItemProperty $path).PSObject.Properties.Name -contains "AllowLocalPolicyMerge") {
    Set-ItemProperty -Path $path -Name AllowLocalPolicyMerge -Value 1
} else {
    New-ItemProperty -Path $path -Name AllowLocalPolicyMerge -Value 1
}
# I had to reboot to apply changes in registry

As mentioned this only works for PCs not using GPO, therefore as an alternative there is also this piece of code to create a task to disable FW on the WSL interface altogether, however, as mentioned above, this comes with a side effect of notification that fw is disabled.

# CMD.exe/powershell as admin
schtasks /create /tn "WSL disable FW" /sc onlogon /delay 0000:15 /rl highest /ru system /tr "C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe -Command 'Set-NetFirewallProfile -DisabledInterfaceAliases ''vEthernet (WSL)'''"

Edit: seems it's not persistent even this way.. needs to be re-run manually, unlucky.

I created automated solution to this it seems.. creating a run-as-admin shortcut that disables the FW for WSL interface and this shortcut is run when opening WSL console.

# powershell as admin
$linkPath = "$env:SystemDrive\WSL_FW.lnk"
$psPath = "$env:WINDIR\System32\WindowsPowerShell\v1.0\powershell.exe"
$WScriptShell = New-Object -ComObject WScript.Shell
$Shortcut = $WScriptShell.CreateShortcut($linkPath)
$Shortcut.TargetPath = $psPath
$Shortcut.Arguments  = '-WindowStyle Hidden -Command "Set-NetFirewallProfile -DisabledInterfaceAliases """vEthernet (WSL)""""'
$Shortcut.Save()
$bytes = [System.IO.File]::ReadAllBytes($linkPath)
$bytes[0x15] = $bytes[0x15] -bor 0x20 #set byte 21 (0x15) bit 6 (0x20) ON
[System.IO.File]::WriteAllBytes($linkPath, $bytes)

# Add this to .bashrc/.zshrc
# Disable FW for WSL Interface
[[ $(ls /dev/pts/  | wc -l) -le 3 ]] && cmd.exe /c "%HOMEDRIVE%\WSL_FW.lnk" 2>/dev/null
davelet commented 2 years ago

I found the following to work for me: Open windows firewall settings, and remove the vEthernet (WSL) connection for each of the Domain, Private, and Public profiles: image

I am also using this as the working solution but this will result in Windows yelling at you that you no longer use the recommended firewall configuration. Anyone with a solution for that? Also this does not save across reboots.

Wakaka, you are the ONE. Thx.

alastairtree commented 2 years ago

I also have a version of this problem with some insteresting symptoms.

I have 2 users on the same machine, each with their own WSL2 instance. User 1 can make TCP from linux to windows via the 127.0.0.1 address without disabling the firewall, and user 2 (me!) cannot, even if I use the machinename.local DNS.

One option was disabling the firewall on the Public profile (BAD!).

My GPOs stop me changing adapter specific settings on the default firewall profile so the solution described above was not working for me.

However I was allowed to change the protected network connections on just the Public profile for user 2, and that made it work without opening everything up. Cannot explain why 2 users on the same machine have different behaviour but at least now both can work.

In summary - you only need to modify the public profile, not all/default profiles for WSL to be unblocked

image

fishbone1 commented 2 years ago

@rmja and @avzero07, is it not the same as Set-NetFirewallProfile -DisabledInterfaceAliases "vEthernet (WSL)" from above in this thread?

Between this and New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow (also from this thread) I'd pick the latter because it doesn't result in the alerted Windows Firewall icon in the systray.

@noseratio

The latter won't work if you have additional rules.

I have a similar problem with XDebug and PhpStorm: The "WSL" firewall rule works. Unfortunately PhpStorm creates additional rules that block all connections to PhpStorm for the public profile. I don't want to deactivate that rule. So I have no other choice but to remove the WSL adapter from the public profile.