I recently switched from Linux to WSL2 (Ubuntu 20.04) on Windows 10. When I run any NodeJs application or a server like Apache or Nginx everything works fine on localhost or 127.0.0.1 but doesn't work when I use my local IP address (192.168.1.65).
netstat -tupln when running node js application
I have tried turning off firewall in windows and wsl but it didn't work.
I enabled the IIS from "Program and Features" and it seems to work fine on localhost and ip. So, I figured it wasn't a problem with the network.
All the post I have read suggest that if the site is accessible through 127.0.0.1 and not through ip then you can configure the server config files for Apache or Nginx. But I reinstalled wsl and am hosting through NodeJs / Express only.
The code for the express app's server.js is:
const express = require("express");
const next = require("next");
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.use(express.static("public"));
server.all("*", (req, res) => {
return handle(req, res);
});
server.listen(port, "0.0.0.0", (err) => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
});
All I want to do is access the site on my mobile on the same network.
Best Answer
The core issue here is that WSL2 operates in a Hyper-V VM with its own virtual NIC, running NAT'd behind the Windows host. WSL1, on the other hand, ran bridged with the Windows NIC.
On
localhost
, Windows does seem to do an automatic mapping, but for the host IP address (and thus, on the local network), it does not.You'll find a lot of information on this particular topic on this Github thread, along with several workarounds:
Option 1: WSL1
First, and the simplest, is to use WSL1 if you can for this particular application. You can convert the WSL2 instance to WSL1 by either doing (from PowerShell) a
wsl --set-version <distroname> 1
or by cloning the existing with awsl --export <distroname> <archivename>.tar
and thenwsl --import <distroname> <installlocation) <archivename>.tar
. I prefer cloning since it gives you a backup.Option 2: Windows port forwarding using
netsh
Port forward under Windows using
netsh
per this comment on that thread. Note that the virtual NIC for the WSL2 instance gets a new address on each reboot, so you'll have to either repeat thenetsh
command on each reboot or set it up in a script as described and set it to run on each boot via Task Manager. Note also that you'll need ot modify Windows firewall rules.Option 3: Port forward through WSL1 with
socat
socat
on bothsocat -d -d TCP-LISTEN:3000,reuseaddr,fork EXEC:'wsl.exe -d <WSL2DistroName> "socat -d -d TCP-CONNECT:127.0.0.1:3000 -"'
, making sure to replace with the correct name (without brackets).That will basically port forward anything on port 3000 on WSL1 to 3000 on WSL2, and since WSL1 runs "bridged" anyway, connections to port 3000 on the Windows host are going to go through that route as well.
This has the advantage over the
netsh
option of not needing to worry about the WSL2 IP changing on each boot, since it works over stdout of thewsl.exe
command.Option 4: Bridge Mode
If you are running on Windows 10 Pro or higher, there are instructions in that thread on how to run the WSL2 NIC in bridge mode. I've never gone this route, since I've been able to use the other three methods.