Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WSL 2] NIC Bridge mode 🖧 (Has TCP Workaround🔨) #4150

Open
jkasten2 opened this issue Jun 16, 2019 · 776 comments
Open

[WSL 2] NIC Bridge mode 🖧 (Has TCP Workaround🔨) #4150

jkasten2 opened this issue Jun 16, 2019 · 776 comments

Comments

@jkasten2
Copy link

jkasten2 commented Jun 16, 2019

Issue

WSL 2 seems to NAT it's virtual network, instead of making it bridged to the host NIC. My goal is for a service running in Ubuntu in WSL 2 to be accessible from anywhere on my local network.

Issue Details

  • Your Windows build number: Microsoft Windows [Version 10.0.18917.1000]

  • What you're doing and what's happening:
    Running ipconfig on my Windows 10 host machine

   IPv4 Address. . . . . . . . . . . : 192.168.1.41
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.1.1

Running ifconfig in Ubuntu WSL 2

eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.72.60  netmask 255.255.0.0  broadcast 172.18.255.255

Accessing 172.18.72.60 from my Window host does work, however this IP is not accessible from another system on my network.

  • What's wrong / what should be happening instead:
    I would expect to ifconfig in Ubuntu WSL 2 to have an IP address in the same network as my host machine.

  • Searching the docs:
    The only detail I have found about WSL 2 networking is the following that notes that it will have it's own IP and that localhost is something that will be used for WSL 2 in the future.
    https://docs.microsoft.com/en-us/windows/wsl/wsl2-ux-changes
    This is fine, however I would like the IP WSL 2 is getting to be on my local LAN which means I need to configure the virtual NIC to be bridged.

Workaround

See @edwindijas #4150 (comment)

@briandesousa
Copy link

briandesousa commented Jun 18, 2019

Same issue here.

IP address of Windows machine is 192.168.1.95 and the eth0 interface in Ubuntu on WSL2 is getting 172.18.47.17.

I originally had Ubuntu on WSL1 running and then upgraded the installation to WSL2 but same problem. Then I uninstalled Ubuntu altogether and reinstalled fresh but same issue after reinstall.

Prior to using WSL2 I had an instance of Ubuntu setup as a Hyper-V VM on the same machine (Hyper-V NIC bridge already existed).

@zzz1990771
Copy link

Same issue. I have a rstudio server running in docker container in WSL2 and wanted to access it from other machine but failed. Really need some fix/idea on it.

@nicolazj
Copy link

I can confirm this issue.
I can no longer access the service running in subsystem from my mobile device, which is within the same wifi network with my windows laptop.

@edwindijas
Copy link

edwindijas commented Jun 20, 2019

It's not a bug with WSL 2, WSL 2 is running as a hyper-v virtual machine. The hyper-v adapter can be found in network adapters. You can use port forwarding to forward the port with netsh as below.
Example command below will forward tcp from port 3000 of the WSL 2 client to port 3000 of the host OS.
netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=172.18.28.x
Next allow incoming and outgoing ports on port 3000 in firewall.

@zzz1990771
Copy link

It's not a bug with WSL 2, WSL 2 is running as a hyper-v virtual machine. The hyper-v adapter can be found in network adapters. You can use port forwarding to forward the port with netsh as below.
Example command below will forward tcp from port 3000 of the WSL 2 client to port 3000 of the host OS.
netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=172.18.28.x
Next allow incoming and outgoing ports on port 3000 in firewall.

Hi! Did you try it on your end? It didn't work for me when I was trying to access it from another machine in the same network. Although I did work when I use the windows host.

@edwindijas
Copy link

I tried it. It worked but the craziest thing is happening, the ip address is changing on reboot. Don't forget to add inbound and outbound rules. Microsoft will fix this issue in the future

@edwindijas
Copy link

edwindijas commented Jun 20, 2019

WSL 2 TPC NETWORK FORWARDING

Introduction

With the introduction of WSL 2 Beta, Microsoft has made changes to the system architecture.
The changes include changing from the default bridged network adapter to a hyper-v virtual network adapter.
The implementation was not completed during the launch of the beta program. This makes accessing of network resources under WSL 2 complex.
The work around is to forward the TCP ports of WSL 2 services to the host OS.
The virtual adapter on WSL 2 machine changes it's ip address during reboot which makes it tough to implement a run once solution.
Also a side note, windows firewall will block the redirected port.

The work around is to use a script that does :

  1. Get Ip Address of WSL 2 machine
  2. Remove previous port forwarding rules
  3. Add port Forwarding rules
  4. Remove previously added firewall rules
  5. Add new Firewall Rules

Configuration

The script must be run at login ,under highest privileges to work, and Powershell must be allowed to run external sources.

PowerShell Configuration

Enable power shell to run external scripts, run the command below in power shell with administrative privileges.

How To:
Go to search, search for task scheduler. In the actions menu on the right, click on create task.
Enter Name, go to triggers tab. Create a new trigger, with a begin task as you login, set delay to 10s.
Go to the actions and add the script. If you are using Laptop, go to settings and enable run on power.

Finally:
I am no expert at security nor scripting and technically new to the windows OS.

Update
The update adds the feature to remove unwanted firewall rules.
Here is the script.


$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if( $found ){
  $remoteport = $matches[0];
} else{
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

#[Ports]

#All the ports you want to forward separated by coma
$ports=@(80,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 -LocalPort $ports_a -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=$remoteport";
}


@jkasten2
Copy link
Author

jkasten2 commented Jun 21, 2019

@edwindijas Awesome, that worked for me! 👍 🎉 I can access my running Linux service from any system on my network via my Windows host IP!
Thanks for all the detail and Task Scheduler suggestion too.

In addition, this workaround means localhost works too.

I was trying to go down another route by forcing bridge mode of WSL virtual adapter, that didn't work. Just including it here for completeness.

PS C:\WINDOWS\system32> Set-VMSwitch WSL -NetAdapterName 'Name_of_your_phsyical_windows_NIC'
Set-VMSwitch : Failed while adding virtual Ethernet switch connections.
External Ethernet adapter 'Name_of_your_phsyical_windows_NIC' is already bound to the Microsoft Virtual Switch
protocol.
At line:1 char:1
+ Set-VMSwitch WSL -NetAdapterName 'Name_of_your_phsyical_windows_NIC'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Set-VMSwitch], VirtualizationException
    + FullyQualifiedErrorId : InvalidParameter,Microsoft.HyperV.PowerShell.Commands.SetVMSwitch

@edwindijas Linked your comment as a workaround for this issue in my original post #4150 (comment).

@jkasten2 jkasten2 changed the title [WSL 2] NIC Bridge mode [WSL 2] NIC Bridge mode 🖧 (Has Workaround🔨) Jun 21, 2019
@edwindijas
Copy link

edwindijas commented Jun 22, 2019

The script only opens ports you desired. And the ports are redirected to WSL machine.
That said, I am no security expert, if you have a better suggestion, I am open to suggestions.

@fengrk
Copy link

fengrk commented Jun 23, 2019

my method to solve this problem: refresh ip in win10:hosts file

@gstorelli
Copy link

WSL 2 TPC NETWORK FORWARDING

Introduction
....
Configuration

The script must be run at login ,under highest privileges to work, and Powershell must be allowed to run external sources.

PowerShell Configuration

Enable power shell to run external scripts, run the command below in power shell with administrative privileges.

I saved your script in a file called "wslbridge.ps1" and then in Windows Scheduler just set Powershell.exe as Action and as argument I wrote this (instead of setting the Unrestricted ExecutionPolicy):
-ExecutionPolicy Bypass c:\scripts\wslbridge.ps1

Thanks

@shayne
Copy link

shayne commented Jun 30, 2019

I wrote a Windows Service that automatically writes the WSL2 VM's IP address to the Windows hosts file. You can then just always reference "wsl.local" from your host machine and it will resolve to the WSL2 VM.

I've been using this for a week now and just open-sourced it.

https://github.com/shayne/go-wsl2-host

@shayne
Copy link

shayne commented Jul 1, 2019

I've collected a few WSL2 hacks into a repo:
https://github.com/shayne/wsl2-hacks

One thing I wanted to point out, relevant to this thread, was "Access localhost ports from Windows", a way to access ports bound to 127.0.0.1 / localhost from the Windows host.

@joaopluigi
Copy link

Thanks @edwindijas, it is a great workaround.

For people using Debian, which does not come with ifconfig out of the box, you can try:

$remoteport = bash.exe -c "ip addr | grep -Ee 'inet.*eth0'"

Also, the hint from @gstorelli of using -ExecutionPolicy Bypass inside the arguments of your Task Scheduler script action is awesome!

Thanks, guys!

@QingGo
Copy link

QingGo commented Jul 20, 2019

If there are multi wsl2 in your system, remember use this command on cmd to change the wsl2 which you want to bind these port as the default one, because bash.exe will run command in the default wsl2 environment:

# list the wsl on you system
wslconfig /l
# set Debian as default for example
wslconfig /setdefault Debian

@abnerfreitas
Copy link

abnerfreitas commented Jul 21, 2019

@edwindijas I was hoping to make my Google Chrome (inside my Kali Distro) recognize my Chromecast, but i couldn't find anywhere the actual ports chromecast uses to connect, however now i can access my Kali from anywhere trought SSH.

@sangemaru
Copy link

You can now use localhost to connect in recent WSL2 versions

@ericblade
Copy link

You can now use localhost to connect in recent WSL2 versions

That's really sort of a different problem -- you can use "localhost" from the host itself, but there's no obvious way to get there from a different machine on the network:

WSL2 is running on Windows host A
WSL2 on Windows host A is running server application B
You can connect to the application from host A by just doing "localhost:port"
You can't connect to the application from Windows Host C in any obvious way.

@xorinzor
Copy link

You can connect to the application from host A by just doing "localhost:port"
You can't connect to the application from Windows Host C in any obvious way.

If you open the port, why would you not be able to connect to host A from host C by just doing "host-A-ip:port"?

This behaviour shouldn't be any different then it is for linux.

@ericblade
Copy link

I don't know the technical reason for it, but it doesn't work by default, and is what brought me here.

@timesnewmen
Copy link

You can connect to the application from host A by just doing "localhost:port"
You can't connect to the application from Windows Host C in any obvious way.

If you open the port, why would you not be able to connect to host A from host C by just doing "host-A-ip:port"?

This behaviour shouldn't be any different then it is for linux.

Although you can open Win app by localhost:port from WSL2, but they are definitely not sharing the same network like WSL1.

This is working in WSL1, but in WSL2 it's not. Still waiting form a solution.

@ericblade
Copy link

ericblade commented Feb 4, 2024

@pawelgnatowski I recently installed a fresh W11 system with WSL2, and it just works out of the box. Mirror mode completely breaks networking for WSL2 for me, though. It could be something in docker that is attaching it, though, I haven't tried directly connecting to a service running in the bare wsl2.

@sarim
Copy link

sarim commented Feb 5, 2024

Me, along with 341 more people learned that WSL actually stands for macos inside windows :v

@pawelgnatowski @ericblade You don't need to use custom scripts anymore. Just use the "bridged" network mode. Create a new hyper-v switch and set it in .wslconfig. I have been using this since Nov 12, 2022 and never had any problem like network connectivity loss or hyperv / wsl config reset etc... It had been rock solid.

Here is my config for reference.

.wslconfig

[wsl2]
kernelCommandLine=ipv6.disable=1
memory=16GB
swap=0
guiApplications=true
debugConsole=false
#vmIdleTimeout=-1

networkingMode=bridged
vmSwitch=WSLBridged
dhcp=false
macAddress=0E:00:00:00:00:00
ipv6=false

[experimental]
autoMemoryReclaim=gradual

And inside ubuntu distro:

/etc/wsl.conf

[user]
default=gittu
[boot]
systemd=true
[network]
hostname = GITTUW11WSL
generateResolvConf=false

/etc/systemd/network/20-wslbridged.network

[Match]
Name=eth0

[Network]
Description=WSLBridged
DHCP=yes

NB: ipv6 is disabled in both wsl and in ubuntu because of #4851.

@ericblade
Copy link

@sarim i haven't had to do any of that anymore to get it to bridge. i wish we had host support now, though. :D

@pbasov
Copy link

pbasov commented Feb 7, 2024

Seems like a good place to ask. I have this config:

[wsl2]
swap=0
kernel=C:\\WSL\\arch0\\bzImage
networkingMode=bridged
vmSwitch="intel"
dhcp=false
localhostForwarding=true

Intel vmSwitch is a hyper-v switch with my other VMs and physical NIC to access the local network, it works perfectly fine, except bridged mode obviously breaks local port forwarding, but more importantly WSL VSCode integration and Windows Explorer WSL filesystem access. The obvious workaround is to use SSH but it's not as conventient.

Mirrored mode is another potential solution, but I'm not ready to try it yet.

Anything else I can do to get VSCode integration and filesystem access back?

[UPDATE]
Adding hostname of the WSL to /etc/hosts on Windows solves the problem with VSCode at least.

@sarim
Copy link

sarim commented Feb 7, 2024

@pbasov local port forwarding works for me with my bridged configuration. Try to replicate my settings #4150 (comment) and see if it works.

@deadcoder0904
Copy link

@sarim i used your solution & got this when i tried to do wsl:

The VmSwitch 'WSLBridged' was not found.
Error code: Wsl/Service/CreateInstance/CreateVm/ConfigureNetworking/WSL_E_VMSWITCH_NOT_FOUND

Note: I haven't restarted my PC but I used wsl --shutdown. Any ideas on how to solve this? I tried a few solutions on Google but no luck.

@sarim
Copy link

sarim commented Feb 23, 2024

@deadcoder0904 You have to create a hyper-v bridge named WSLBridged that is bridged to your primary NIC beforehand. The name doesn't matter, but you have to create a bridge then use it in wsl config.

@deadcoder0904
Copy link

deadcoder0904 commented Feb 24, 2024

@sarim i tried your suggestion.

i first installed & enabled hyper-v using this video & then i tried to follow this guide. i'm stuck at the last 2 steps.

what they show:

their hyper-v

what i see:

my hyper-v

how do i find a virtual machine? i tried solutions here but no luck. i'm assuming this should point to wsl2 but how would i do it? is it import?

would love a suggestion.

@sarim
Copy link

sarim commented Feb 24, 2024

@deadcoder0904 It is not related to virtual machines. You have to click "Virtual Switch Manager" in the right sidebar. Detailed tutorial is somewhere in this thread buried deep.

@deadcoder0904
Copy link

@sarim i did exactly that. the guide i linked above (2nd link) but i don't see a virtual machine. idk if that step (like seeing a virtual machine) is necessary. i'll try it again sometime. for now, changing localhost to 0.0.0.0 in dockerfile works.

@deadcoder0904
Copy link

alright, so this solution (read the comments below that) is much better.

i only have to change localhost to 0.0.0.0 in dockerfile to make it work. no need to make it complex at all.

@Unsigned-Char
Copy link

Simply put, thanks for the inspiration – The ultimate recipe

https://github.com/Unsigned-Char/WSL2HyperVSwitch

@micheldiemer
Copy link

Here a detailed working procedure on how to use WSLAttachSwitch

Script : #4799 (comment)

Text : #4799 (comment)

@colemar
Copy link

colemar commented May 29, 2024

How I made WSL2 use the external LAN interface:
#11632

@seflerZ
Copy link

seflerZ commented Jun 25, 2024

@salimmj In Windows Server 2025 with the following info:

WSL : 2.2.4.0
kernel: 5.15.153.1-2
WSLg: 1.0.61
MSRDC: 1.2.5326
Direct3D: 1.611.1-81528511
DXCore: 10.0.26091.1-240325-1447.ge-release
Windows: 10.0.26100.1

The networkingMode=bridged is not working. You can enable it in .wslconfig but the interface can not obtain any IP actually.

@young03600
Copy link

young03600 commented Aug 4, 2024

I tried it. It worked but the craziest thing is happening, the ip address is changing on reboot. Don't forget to add inbound and outbound rules. Microsoft will fix this issue in the future

Hi,
It works like a charm!
Even this thread is quite old though, but I am just wondering why it doesn't work if I only setup the Inbound firewall rule?
Thanks.

@mrefky
Copy link

mrefky commented Aug 4, 2024

To set the IP I have the below commands that runs whenever WSL2 is loged on:

sudo ip addr flush dev eth0
sudo ip addr add 192.168.169.154/24 dev eth0
sudo ifconfig eth0 broadcast 192.168.169.255
sudo route add default gw 192.168.169.1

And whenever WSL2 is logged on it re-sets the IP to 192.168.169.154

Of course you must use Ips that are in your subnet and use proper ethernet name if eth0 is not correct.

@xiaokentrl
Copy link

Here a detailed working procedure on how to use WSLAttachSwitch

Script : #4799 (comment)

Text : #4799 (comment)

I really love the Dynamic-Wallpaper software. If there were a Windows or Linux version, I would be willing to purchase it for a lifetime.

@xiaokentrl
Copy link

I really love the Dynamic-Wallpaper software. If there were a Windows or Linux version, I would be willing to purchase it for a lifetime.

@codan84
Copy link

codan84 commented Aug 12, 2024

Instead of working on a project I am fighting with this 💩. Seriously MS, since 2019! Dual-boot Linux for me that is...

@Esensats
Copy link

I am just wondering why it doesn't work if I only setup the Inbound firewall rule? Thanks.

@young03600 Outbound rules are required because otherwise your server would not have a way to serve whatever it serves to the outside network.

Here's a tool I created to deal with all of this automatically. You can use it like this: pfwsl add 8080 and it'll add all of the rules. pfwsl ls to list existing and pfwsl rm to remove the rules

@bhagavansprasad
Copy link

After returning to WSL following a 3-year hiatus, I've found that things are still quite complicated. It seems like there's a real need for a comprehensive table that documents various connection scenarios in WSL. Maybe Microsoft should consider hiring me as a tester – just a thought, LOL!

Here's what I've observed in my tests, assuming all firewalls are disabled:

  • The tests were conducted using the latest mirrored mode.
  • I ran a server (python3 -m http.server) on either the WSL, the host, or remotely.
  • A multipass Hyper-V VM was operational on the same host as the WSL.
  • Another Windows machine was functioning on the same LAN as the WSL host.
  • Port forwarding using netsh is NOT configured.

Using 127.0.0.1 Using IP Using Host Name
From: LAN, To: WSL NA + +
From: Host, To: WSL + ! (1) ! (2)
From: VM, To: WSL NA ! (3) ! (4)
From: WSL, To: WSL + + +
From: WSL, To: Host + ! (5) ! (6)
From: WSL, To: LAN NA + -
From: WSL, To: VM NA NA NA
Key to the table:

  • "+" indicates a successful connection.
  • "!" signifies that the connection is expected to work but doesn't.
  • "NA" means not applicable or untested.
  • Rows represent different source-to-destination scenarios (e.g., "From: LAN, To: WSL").
  • Columns denote the methods of connection (using 127.0.0.1, mirrored IP, or host name).

Question:

  • Is this what people see?
  • what of those 1-6 should we expect to work?
  • note there is at least 1 + for each row (except the last row), so almost all connections can be made.
  • note this is tested on a recently imaged windows laptop with 1 ethernet port and 1 wireless adapter.

What about WSL-Distro1 to WSL-Distro2 Networking/Connections?

@ab5y
Copy link

ab5y commented Nov 18, 2024

WSL 2 TPC NETWORK FORWARDING

Introduction

With the introduction of WSL 2 Beta, Microsoft has made changes to the system architecture. The changes include changing from the default bridged network adapter to a hyper-v virtual network adapter. The implementation was not completed during the launch of the beta program. This makes accessing of network resources under WSL 2 complex. The work around is to forward the TCP ports of WSL 2 services to the host OS. The virtual adapter on WSL 2 machine changes it's ip address during reboot which makes it tough to implement a run once solution. Also a side note, windows firewall will block the redirected port.

The work around is to use a script that does :

1. Get Ip Address of WSL 2 machine

2. Remove previous port forwarding rules

3. Add port Forwarding rules

4. Remove previously added firewall rules

5. Add new Firewall Rules

Configuration

The script must be run at login ,under highest privileges to work, and Powershell must be allowed to run external sources.

PowerShell Configuration

Enable power shell to run external scripts, run the command below in power shell with administrative privileges.

How To: Go to search, search for task scheduler. In the actions menu on the right, click on create task. Enter Name, go to triggers tab. Create a new trigger, with a begin task as you login, set delay to 10s. Go to the actions and add the script. If you are using Laptop, go to settings and enable run on power.

Finally: I am no expert at security nor scripting and technically new to the windows OS.

Update The update adds the feature to remove unwanted firewall rules. Here is the script.


$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if( $found ){
  $remoteport = $matches[0];
} else{
  echo "The Script Exited, the ip address of WSL 2 cannot be found";
  exit;
}

#[Ports]

#All the ports you want to forward separated by coma
$ports=@(80,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 -LocalPort $ports_a -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=$remoteport";
}

Nearly 2025 and this is the only working solution!

@colemar
Copy link

colemar commented Nov 18, 2024

There is a solution to expose on the LAN an IP address tied directly to the WSL2 guest operating system, even in Windows 10 where WSL2 does not support networkingMode = bridged in .wslconfig.
Here is my take: https://github.com/colemar/Win10WSL2UbuntuExternalIP
Unfortunately, this kludge does not seem to survive a reboot of the host Windows 10 machine.

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

No branches or pull requests