After installing Ubuntu as WSL(Windows Subsystem for Linux) I've run:
root@teclast:~# python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 ...
and try to access to this web server from my windows machine http://0.0.0.0:8000
or http://192.168.1.178:8000
but no success, web server available only by the address http://127.0.0.1:8000
or http://localhost:8000
it means that I can't connect to this web server from another pc in my.network. Is it possible to getting an access to WSL from outside?
None of the existing answers work for me, as WSL2 is running in its own VM and has its own network adapter. You need some sort of bridge or port forwarding for non-localhost requests to work (ie from another host on the same network).
I found a script in https://github.com/microsoft/WSL/issues/4150 that worked to resolve the issue:
$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";
}
Running this script from an elevated/admin Powershell session did the trick for me. This allows accessing the WSL2 service running on a port to be accessible from the Windows host IP at that same port.
In your VM, execute ifconfig
You will see your IP in the first section (eth0:) inet xxxx
This xxxx is the IP you have to put in your browser.
Please follow the steps mentioned in the link shared by @erazerbrecht and run your HTTP server by providing your ip address (instead of using localhost) and port number.
example:
root@teclast:~# python3 -m http.server -b 192.168.1.178 8000 Serving HTTP on 192.168.1.178 port 8000 (http://192.168.1.178 :8000/) ...
Otherwise you can also do this instead of following the link :
1. Goto Windows defender firewall
2. select inbound
3. create new rule
; next
4. select Program
as a rule type; next
5. select All Program
; next
6. select allow the connection
; next
7. check all 3 (Domain, Private, Public); next
8. provide rule a name
9. finish
10. Your are good to go
To anyone coming new to this post have a look at Microsoft doc https://docs.microsoft.com/en-us/windows/wsl/networking#accessing-linux-networking-apps-from-windows-localhost .
According to the docs if you are running an older version of Windows (Build 18945 or less), you will need to get the IP address of the Linux host VM
This should be a non-issue post the Windows Build 18945.
I followed the answer by @toran-sahu about adding an inbound rule to Windows Defender Firewall but recently (after adding a 2nd wsl2 instance) it stopped working again. I came across this issue thread and running the following in cmd prompt got it working again for me.
wsl --shutdown
update: it seems this issue comes from having Fast Startup enabled https://stackoverflow.com/a/66793101/8917310
Similar to @countach 's answer:
If using Ubuntu type ip address
in the WSL terminal. Look for the entry that says #: eth0 ...
where #
is some small number. There is an ip address there. Use that.
I have written a PowerShell script, using 2 simple commands which worked perfectly for me.
# get the IP address of the WSL
$str = wsl -- ip -o -4 -json addr list eth0 | ConvertFrom-Json | %{ $_.addr_info.local } | ?{ $_ }
echo "Wsl IP: $str"
# establish the connection with the WSL
# listenport,connectport ports can be changes as per the needs
netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=$str
Create a .ps1
file using this code and execute it from the PowerShell terminal.
It can be added to the scheduler so that the script will run every time at Windows boot.
For now (03.2022) to access from outside an app running on WSL 2, we need to do the following:
Make rules in the firewall for accepting incoming (and maybe also outgoing) connexions on the protocol and port on which the app is running (eg TCP/80)
Get WSL's vm IP: hostname -I
As said on this page ( Accessing a WSL 2 distribution from your local area network (LAN) ), use this IP address to add, in Windows, a proxy that listens on the port and redirects to WSL's vm. This is done by the following command in a PowerShell running as administrator:
netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=192.168.101.100
Where 192.168.101.100
is vm's IP from hostname -I
and 80
the port we want to open to the outside.
As WSL's IP changes when rebooted, this should be automated in a PowerShell script, where the previous proxy is removed and a new one is set to the current IP. All credit goes to Edwindijas on Github from who's script this one is heavily inspired:
$ports=@(80,21,22) # the ports you want to open
$addr='0.0.0.0';
$wslIP = bash.exe -c "hostname -I"
$found = $wslIP -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
if(! $wslIP -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}') {
echo "WSL's IP cannot be found. Aborting";
exit;
}
$portsStr = $ports -join ",";
iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' ";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $portsStr -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $portsStr -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=$wslIP";
}
how ifconfig mentioned in the script works in windows? isn't it need to be 'ipconfig'?
Avoid using firewall rules used in some answers on the web, I saw some of them create some kind of allow-all firewall rule (allow any terrafic from any ip and any port), this can cause security problems
Simply use this single line from this answer which worked perfectly for me (just creates a port proxy):
netsh interface portproxy add v4tov4 listenport=<windows_port> listenaddress=0.0.0.0 connectport=<wsl_port> connectaddress=<WSL_IP>
where <WSL_IP>
is the ip of wsl, you can get it by running ifconfig
on wsl. Also <windows_port>
is the port windows will listen on and <wsl_port>
is the port server is running on WSL.
You can list current port proxies using:
netsh interface portproxy show all
it means that I can't connect to this web server from another pc in my network. Is it possible to getting an access to WSL from outside?
It should be noted, among all the answers here, that this question was originally for WSL1 (given when it was asked) and was self-answered by the OP as having been a WSL or Windows issue that was resolved by a Windows update.
Ironically, this is a known issue on WSL2 (see footnote), so years later, people started finding it (and answering it) in that context.
There multiple solutions for this on WSL2, but with no disrespect to the other answerers here, they have all missed the two easiest ones:
WSL1 : First, just use WSL1. For most (but not all) web development tasks where you need to access your app from another machine on the network, WSL1 will be better at networking and will run your application and tools just fine. WSL2 brings in real, virtualized Linux kernel, but the "fake kernel" (syscall translation layer) of WSL1 still works fine today for most tasks.
When running python3 -m http.server
under WSL1, you'll automatically be able to access it from other machines on the network via the Windows host's IP address (or DNS name). As the OP mentioned in the self-answer, that pesky WSL1 bug has been fixed for years now.
SSH reverse tunnel If you do need to use WSL2, here's an option that doesn't require port forwarding or any advanced firewall rules that need to be updated each time WSL restarts. The problem with those rules is that the IP address for WSL changes every time you restart, meaning those rules have to be deleted and recreated constantly.
On the other hand, we can use SSH within WSL2 to connect to Windows, where the name, and perhaps even the IP address, is constant.
There's some one-time setup for this, but it's useful regardless:
First, install/enable Windows OpenSSH server. This is a feature that is built-in to Windows and just needs to be enabled. You'll find the full instructions here , but it's typically just a matter of (from an Admin PowerShell):
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0 Start-Service sshd Set-Service -Name sshd -StartupType 'Automatic' if (,(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) { Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist. creating it..." New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 } else { Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists." }
Edit your C:\ProgramData\ssh\sshd_config
and set GatewayPorts yes
. This is what allows us to use SSH as a gateway from other devices on the network.
Finally, of course, you'll need a firewall rule in Windows allowing the HTTP(s) (or other) port you'll be using. Example (from Admin PowerShell):
New-NetFirewallRule -DisplayName "WSL Python 8000" -LocalPort 8000 -Action Allow -Protocol TCP
And restart the OpenSSH Server service:
Restart-Service sshd
With that in place, it's a simple matter to create the tunnel we need:
ssh -R 8000:localhost:8000 NotTheDr01ds@$(hostname).local
Replacing, of course, NotTheDr01ds
with your own Windows username, if it differs from the WSL username
That's going to use your Windows username and password since SSH is running on the Windows side.
Once you have ensured that it works, two other recommendations:
ssh -fN -R 8000:localhost:8000 NotTheDr01ds@$(hostname).local
That will put the SSH session into the background and not allocate a terminal for it.I've tested on Update for Microsoft Windows(KB4532132) with reinstalled WSL and it works as expected. Seems the issue was related to old windows version or old WSL version.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.