See this video, it helped me:
https://www.youtube.com/watch?v=yCK3easuYm4
netsh interface portproxy add v4tov4 listenport=<port-to-listen> listenaddress=0.0.0.0 connectport=<port-to-forward> connectaddress=<forward-to-this-IP-address>
for example
netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=172.30.16.3
Microsoft has published a little bit of information about this on their WSL1 to WSL2 comparison page
First, you will need to open a port in your machine to be able to access it from your network.
netsh advfirewall firewall add rule name="Allowing LAN connections" dir=in action=allow protocol=TCP localport=5000
After you open the port (5000 in my case) you will need to make port forwarding from this port to the port that your app is listening on in the WSL.
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=5000 connectaddress=localhost connectport=<the port that your app is listening on>
Notice: I set the connectaddress to localhost not to the IP address of the WSL because by default the requests that go to localhost are forwarded to the WSL. By doing this you won't need to set the port forwarding every time you restart your machine because the IP address of the WSL is dynamic.
This one worked for me:
The firewall commands in that script didn't work on my system. So I deactivated the Windows firewall completely and use the following stripped version. (The final users will use a 3d party firewall anyway, so that's ok).
$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=@(123,456);
#[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 ",";
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";
}
#Then so something, e.g.
#bash.exe -c "cd /g-inverter; ./start_docker.sh"
You may need to "apt install net-tools" for ifconfig in the script. There's also a solution with "ip addr" in the internet somewhere that does not need ifconfig" in a great thread, I haven't a link for here and now.
Caveat
This works only for TCP traffic. netsh interface portproxy does not support port forwaarding of UDP traffic.
Solution: Switch from NAT to Bridge mode
WSL2 comes by default in NAT mode. There the wsl2 system has another ip in another subnet than the host. The PC is from external peers only visible by the windows IP and the wsl2 ip/net is hidden/internal. So all traffic would need to be accepted by the windows IP and then forwarded to the wsl2 ip (port forwarding).
There is another mode called bridge mode. In bridge mode your network interface card will be shared to the wsl2 system, and it will get its own IP/Net in wsl2. So in effect your network card is shared to both systems (windows / wsl2) and will have two IPs, as if you'd have two systems with its own network card each. Cool thing: You will never have port conflicts when Windows uses the same port as well, as your wsl2 app (like 111).
Enable bridge mode
Open Hyper-V Manager as administrator
Select your pc, open Virtual Switch Manager
Select WSL
Set to external network
Select the network card the traffic runs through
Then login to wsl2 terminal and configure an IP address. E.g.
sudo ip addr add 192.168.0.116/24 dev eth0
You need to use another free IP (not your Windows IP). If your network has a DHCP server your wsl can get one by:
sudo ip addr flush dev eth0
sudo dhclient eth0
Caveat
I haven't elaborated yet, how to get DNS working in this scenario in case you want to still be able to access the internet (apt etc.). There's some documentation from MS written in /etc/resolv.conf and maybe executing what's written there and installing resolvconf (prior to all steps above, as you have no internet once you start to bridge) might do the trick.
WSL2 exposes ports on the local interface (which is why in Windows you can accesslocalhost:8080
when your8080
service is running in WSL2), but they listen on127.0.0.1
(which is why you can't accessyourhostname:8080
on other computers your LAN).
There's a tool to fix this called WSLHostPatcher, which you can find here (download via the Releases section): https://github.com/CzBiX/WSLHostPatcher
WSLHostPatcher changes the behaviour to listen on all IPs, exposing any WSL2 services to all computers on your network.
WSLHostPatcher.exe
The service should now be accessible via other computers on your network.
Taking into consideration the above (correct) solutions this is a simplified one liner version that works for me:
Run the following command using the IP found in the previous step in connectaddress parameter:
netsh interface portproxy add v4tov4 listenport= listenaddress=0.0.0.0 connectport= connectaddress=172.24.26.277
Parameters explanation:
listenport: the port that Windows will listen
listenaddress: the address that your Windows will listen. Usually 0.0.0.0 should do.
connectport: the port that your Linux Distro through wsl2 will listen.
connectaddress: the public IP of your Linux wsl2 instance (found in step 1)
Use cmd or PowerShell as Administrator to run the above command.
Building on Roelofs suggestion no.2, here's what made everything tick in my case. I'm too fresh to just leave a comment unfortunately.
My starting point:
Win 10 Pro
Ubuntu under WSL2
(Docker with Linux containers)
My goal:
Getting an rtmp stream from a client on the network into and back out of an nginx server running on the Ubuntu machine.
In my case, I could not get Hyper-V to set the bridge up properly. After selecting External network for the WSL switch in the Virtual switch section of Hyper-V Manager and hitting apply, it eventually failed with error 0x80070490. Don't know why and didn't have the time to investigate. WSL was not running and neither was the Docker service.
Instead, I just left the setting on Internal network and bridged the interfaces the manual way, under Network Connections (run->ncpa.cpl). In my case, the WiFi connection and vEthernet (WSL). Immediately after doing this, I lost internet connectivity and it took me an embarrassingly long time to find out that a reboot was needed. (Windows for once did not ask me to!)
After the reboot, I now had internet access from the host, the bridge was set to DHCP and had inherited the IP of the WiFi interface (192.168.1.246). Great.
The VM however was still getting the IP of the virtual switch (or however you want to view it, the random 172.x.x.x address that windows seems to assign to the switch as well as the VM).
Firing up Ubuntu, I decided to do a:
sudo ip addr flush dev eth0
Continuing with:
sudo dhclient eth0
threw a handful of errors at me since I was using the vanilla Ubuntu distro from Windows store, no systemd, no fun. Despite that, it did manage to add the IP of the bridge to eth0. As this was not very handy, I got rid of that with:
sudo ip addr del 192.168.1.248/24 dev eth0
but not before taking a sneak peek at the routing table:
user@vm:~$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
After deleting the old IP, I added a unique one from outside of my DHCP range:
sudo ip addr add 192.168.1.50/24 dev eth0
I checked the routing table again and the first entry was gone. At this stage I could ping LAN but not WAN.
Added the entry back with:
sudo ip route add default via 192.168.1.1 dev eth0
Pinging WAN IPs was now possible, but no DNS resolution. LMGTFM: Adding permanent DNS In case the solution goes missing, here it is, credit to non-static:
Create a file: /etc/wsl.conf. Put the following lines in the file [network] generateResolvConf = false In a cmd window, run wsl --shutdown Restart WSL2 Create a file: /etc/resolv.conf. If it exists, replace existing one with this new file. Put the following lines in the file nameserver 8.8.8.8 Or the IP of whatever DNS server you want to use, repeat step 3 and 4.
So, to conclude, check your routing and setup your DNS-conf properly. Unfortunately, the IP settings are reverted every time you restart WSL. If you are not ok with doing this manually every time there are discussions on how to automate it here and here. I haven't had the time to find my favorite.
Best regards Alexander
Here's the full three steps I found worked for LAN development access to something running in WSL2 (Ubuntu 20 on Windows 10 20H2):
Windows firewall should be on — don't turn it off! —, and it should block inbound attempts by default.
The following will open the ports 19000–19001, inbound, but only on a network that you have configured as "private" (that's the-Profile Private
part, replace withDomain
if you're on a domain):
19000-19001
with the port(s) you need.DisplayName
with one that works for you. It's handy for finding the rule later.(powershell as Admin)
New-NetFireWallRule -Profile Private -DisplayName 'Expo ports for LAN development' `
-Direction Inbound -LocalPort 19000-19001 -Action Allow -Protocol TCP
(You can check it after withGet-NetFirewallRule |Where-Object {$_.DisplayName -Match "Expo.*"}
— replace the-Match
arg with the DisplayName you chose)
portproxy
to WSL; Re-run "Each time WSL has a new IP address"(I'm not sure yet how often the WSL IP address changes, but I suspect only a reboot would)
I saw stuff on the web, including other answers here, saying portproxy toconnectaddress=127.0.0.1
but it did not work for me (WSL2, Windows 10 20H2).
I can't say why others found it worked, I can only say that repeated testing confirmed for me that127.0.0.1
did not work, but the WSL IP address did work.
So here's a reusable command to auto set the connectaddress to the right WSL address:
(powershell — just for the easy inlineTrim()
— as Admin)
netsh interface portproxy add v4tov4 listenport=19000 listenaddress=0.0.0.0 `
connectport=19000 connectaddress=$($(wsl hostname -I).Trim());
netsh interface portproxy add v4tov4 listenport=19001 listenaddress=0.0.0.0 `
connectport=19001 connectaddress=$($(wsl hostname -I).Trim());
(e.g. QR-Code mobile apps like Expo)
You'll need to re-run the following inside WSL "Each time dev host has a new IP address"
Fortunately it's also pastable / aliasable:
WSL2 shell
netsh.exe interface ip show address "Wi-Fi" | grep 'IP Address' | sed -r 's/^.*IP Address:\W*//'
# e.g. for Expo, I used:
export REACT_NATIVE_PACKAGER_HOSTNAME=$(netsh.exe interface ip show address "Wi-Fi" | grep 'IP Address' | sed -r 's/^.*IP Address:\W*//')
echo Meteor will use dev machine IP address: $REACT_NATIVE_PACKAGER_HOSTNAME
I "wish I didn't have to re-run things and it could all be automated",
but that same laziness makes me happy to at least have command 2 (and 3) easy to "rerun" and consistently get the LAN access I need to my WSL2-hosted service.
install the ssh server on WSL
Find some ssh client on windows
Execute on windows: (Windows's IP with 192.168.x.x and WSL ip with 172.28.x.x)
ssh -L 192.168.x.x:3000:172.28.x.x:3000 [email protected]
if it doesn't work, try to using another local port such as (192.168.x.x:3001:172.28.x.x:3000)
Another solution is to bridge WSL2 directly to the relevant network adapter. I tried doing it within Hyper-V, but couldn't get it to work. However, what did work was going toControl Panel\Network and Internet\Network Connections
, selecting the NIC (Ethernet 3
in my case) andvEthernet (WSL)
and bridging them by right clicking and selecting "Bridge Connections":
You should end up with something like this:
After the bridge is set up let Windows do its thing for a minute or so (seriously!) before continuing.
Next open WSL and have it run dhcp to get a new address:
sudo ip addr flush dev eth0 && sudo dhclient eth0
At this point, both WSL and Windows should have connectivity. Check by pinging some IP address like 1.1.1.1 or 8.8.8.8. If that doesn't work, dismantle the bridge and try again. Remember to wait for a minute or two while Windows configures everything.
Additionally, make sure thateth0
has an address from your LAN (ip addr sh eth0
).
The problem now is that WSL probably can't resolve domain names since WSL creates/etc/resolv.conf
on startup which points to the virtual gateway which is no longer there. This can be solved by asking wsl not to create/etc/resolv.conf
by appending the following to/etc/wsl.conf
(create the file if it doesn't exist):
[network]
generateResolvConf=false
Then restart wsl by restarting theLxssManager
windows services.
The only thing that remains is setting up alternative DNS servers within WSL. Instead of the generated/etc/resolv.conf
, just create a/etc/resolv.conf
with something like:
nameserver 1.1.1.1
nameserver 1.0.0.1
That's it! WSL should now be bridged to your network and have its own unique address on it.
This worked for me using wsl2. I had an app in wsl2 listening on port4200
. In an administrator elevated powershell:
netsh interface portproxy add v4tov4 listenport=8080 connectport=4200 connectaddress=127.0.0.1
Note the lack oflistenaddress=
argument and the different listening port8080
instead of4200
netsh advfirewall firewall add rule name= "Open Port 8080" dir=in action=allow protocol=TCP localport=8080
Then on my wifi-connected mobile phone visithttp://192.168.1.2:8080
You can delete your proxy withnetsh interface portproxy delete v4tov4 listenport=8080
and your firewall rule withnetsh advfirewall firewall delete rule name="Open port 8080"
Obviously change to your ports to your case and192.168.1.2
to your PCs IP on your LAN. Useipconfig
to find it. You may need to make sure the code you're running in wsl2 is bound on0.0.0.0
.
Good luck.
WSL2-PortForward.cmd
@ECHO OFF
REM ** Set WSL Distro, Distro Port, Host Port
SET LXDISTRO=WinKDE
SET WSL2PORT=3389
SET HOSTPORT=13389
REM ** Reset any existing port proxies and delete any stale firewall rule
NETSH INTERFACE PORTPROXY RESET & NETSH AdvFirewall Firewall delete rule name="%LXDISTRO% Port Forward" > NUL
REM ** Get IP from WSL2 instance and write it out to IP.tmp
WSL -d %LXDISTRO% -- ip addr show eth0 ^| grep -oP '(?^<=inet\s)\d+(\.\d+){3}' > IP.TMP
REM ** Read IP.tmp back into batch variable
SET /p IP=<IP.TMP
REM ** Create the port proxy
NETSH INTERFACE PORTPROXY ADD v4tov4 listenport=%HOSTPORT% listenaddress=0.0.0.0 connectport=%WSL2PORT% connectaddress=%IP%
REM ** Create a new firewall rule for the port listening on the LAN
NETSH AdvFirewall Firewall add rule name="%LXDISTRO% Port Forward" dir=in action=allow protocol=TCP localport=%HOSTPORT% > NUL
REM ** Summary
ECHO WSL2 Virtual Machine %IP%:%WSL2PORT%now accepting traffic on %COMPUTERNAME%:%HOSTPORT%
Output::
WSL2 Virtual Machine 172.17.109.95:3389 now accepting traffic on MYCOMPUTER:13389
Regarding bridge mode - Windows would prevent of modifying WSL virtual switch (access denied error) when any Linux distribution is running. From the other hand WSL switch is created when first Linux distro is started. I did as follows:
Finally I've got a solution that has to be run just once after the Windows host boot, works with multiple WSL2 instances at the same time, and does not have to be re-run when a WSL2 instance restarts!
Drawback: cannot listen on 0.0.0.0; you have to specify IPs or adapters for listening explicitly. (This version listens only on one IP address, but can be easily extended to use a list).
$ports = @(8000,8001); # ports to forward
$iface = "Ethernet"; # alias of the Adapter to listen on
# if your host has a fixed IP, you can specify it here explicitly
# and remove the ping-and-if safeguard;
# but 0.0.0.0 won't work!
$external_ip = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceAlias $iface).IPv4Address;
ping -n 1 "$external_ip" > $null
if( !$? ) {
echo "error: cannot determine the external IP address";
exit 1;
}
$firewall_rule_name = "WSL2 Firewall Hole"
Remove-NetFireWallRule -DisplayName "$firewall_rule_name"
New-NetFireWallRule -DisplayName "$firewall_rule_name" -Direction Outbound -LocalPort $ports -Action Allow -Protocol TCP
New-NetFireWallRule -DisplayName "$firewall_rule_name" -Direction Inbound -LocalPort $ports -Action Allow -Protocol TCP
ForEach( $port in $ports ) {
netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$external_ip
netsh interface portproxy add v4tov4 listenport=$port listenaddress=$external_ip connectport=$port connectaddress=127.0.0.1
}
Credits:
localhost
instead of obtaining the IP address of a running WSL2 instance was gleaned from this answer by Charl Botha here.The original edwindijas's script didn't work for me because I run WSL2 under a limited user, the script has to run as admin, and runningbash
orwsl -e
as admin gets a new WSL2 instance with a different IP address.
Here's a solution that is perhaps simpler than many of the others that have been offered. You need a WSL1 instance withsocat
installed in addition to the WSL2 instance that you're using.
On the WSL1 instance, startsocat
like this:
socat -d TCP-LISTEN:3000,reuseaddr,fork TCP:localhost:3000
When you start socat like this, Windows will ask if you want to allow network access to the port. Confirm.
Make sure your puma binds to port 3000 on all interfaces.
You will now be able to access your dev server from the LAN. What's happening here is that socat is forwarding requests to 3000 on your ethernet port to port 3000 on localhost, which will magically get forwarded by Windows to WSL2.
(I'm currently using this exact setup to access my Django dev server on WSL2 from an iOS app on my LAN.)
So, I struggled with this for a while the last two days, nothing seemed to work, in this thread or elsewhere. I finally got it worked out though by piecing together a few things I've seen, and I figured I'd post my solution here in case it helps anyone. A few caveats though. First, I'm definitely no Linux guru, so "it works" is just about my real only consideration :) Second, this is on a home dev server, which means that security isn't my biggest concern (the server isn't exposed outside my LAN in any way), so I did some things that I wouldn't do on a real, important machine. Finally, I didn't need this to work all the time, meaning I'm okay with having to do something myself after a server reboot to get it all working.
With all that in mind, the first step was, as malt above describes, bridging the WSL adapter with the server's physical adapter. In my case, the server has a static IP, so I configured the Network Bridge adapter that results with a static IP, gateway and DNS servers for IPv4.
After that, I wrote the following script named startup_tasks.sh in my home directory:
#!/bin/bash
clear
echo Running startup tasks...
# Clear existing IP config
sudo ip addr flush eth0
echo .
sleep 2
# Add static IP
sudo ip addr add 192.168.1.100/24 dev eth0
echo .
sleep 2
# Remove existing default gateway
sudo ip route del default
echo .
sleep 2
# Add default gateway
sudo ip route add default via 192.168.1.1
echo .
sleep 2
# Remove existing name resolution config file
sudo rm /etc/resolv.conf
echo .
sleep 2
# Create name resolution config file
sudo touch /etc/resolv.conf
echo .
sleep 2
# Update permissions on file so we can edit it
sudo chmod 777 /etc/resolv.conf
echo .
sleep 2
# Add name servers
sudo echo "nameserver 8.8.8.8" >> /etc/resolv.conf
echo .
sleep 2
sudo echo "nameserver 1.1.1.1" >> /etc/resolv.conf
echo .
sleep 2
echo - Static IP set
echo .
echo ...done!
For this to work, I also had to ensure my user account has sudo rights without a password, so this was added to the sudoer's file:
devuser=(ALL) NOPASSWD:ALL
I simply run that script after a server reboot and the result is WSL gets a static IP address and all the servers I run (all in Docker containers, though I removed all that from the script above) are accessible.
For me, it's that easy.
I've also considered writing a simple .vbs file and dropping it in my startup folder to run that script after a reboot automatically. That should work fine and make it all completely automatic, but I just haven't done it yet.
for someone who may have been as desperate as me
I tried so many ways, I was desperate things get messed up, I can't even keep accessing localhost:3000 as default (at first, I could)
I converted wsl2 to wsl and converted it back to wsl2 (look like I reset all config for wsl2, anyway, I'm not sure) then I just added portproxy and did nothing more, it worked
PS C:\Windows\system32> netsh interface portproxy add v4tov4 listenport=3001 listenaddress=0.0.0.0 connectport=3001 connectaddress=localhost
PS C:\Windows\system32> netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=localhost
PS C:\Windows\system32> netsh interface portproxy show all
Listen on ipv4: Connect to ipv4:
Address Port Address Port
Unfortunately, for me, this is a simplified case because my Home network is defined by my Router. Since my home devices don't communicate using the back-to-back connection and my network is protected by the Router's firewall I have to respect the Router's configuration.
Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.
Find the answer in similar questions on our website.
Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.
PHP (from the English Hypertext Preprocessor - hypertext preprocessor) is a scripting programming language for developing web applications. Supported by most hosting providers, it is one of the most popular tools for creating dynamic websites.
The PHP scripting language has gained wide popularity due to its processing speed, simplicity, cross-platform, functionality and distribution of source codes under its own license.
https://www.php.net/
React is currently the leader in JavaScript UI frameworks. First, the Facebook developers started working on this to make their job easier. An app called Facebook Ads grew very quickly, which meant complex management and support. As a result, the team began to create a structure that would help them with efficiency. They had an early prototype before 2011, and two years later, the framework was open source and available to the public. It is currently used by many business giants: AirBNB, PayPal, Netflix, etc.
https://reactjs.org/
A web framework called Skybreak was released at the end of 2011. After a couple of months, the team changed their name to Meteor. Using simple JavaScript, you can create apps that can be used across multiple platforms, including but not limited to Android and iOS. The Meteor JS framework provides full stack solutions. The use of this infrastructure includes important areas such as back-end development, database management, business logic, and front-end rendering.
https://www.meteor.com/
Welcome to the Q&A site for web developers. Here you can ask a question about the problem you are facing and get answers from other experts. We have created a user-friendly interface so that you can quickly and free of charge ask a question about a web programming problem. We also invite other experts to join our community and help other members who ask questions. In addition, you can use our search for questions with a solution.
Ask about the real problem you are facing. Describe in detail what you are doing and what you want to achieve.
Our goal is to create a strong community in which everyone will support each other. If you find a question and know the answer to it, help others with your knowledge.