Whenever i try to run expo start
or npm start
the IP for it is not my LAN IP but my WSL2 eth0 IP and this will cause my phone not connecting to the expo.
i have already tried to set REACT_NATIVE_PACKAGER_HOSTNAME
with export
command and it will change the ip in the browser related to expo as well but i think it will not run at that ip because my phone again will not connect (i also have turned firewall off too)
the expected thing for me is to be able to run my expo code on my phone without using the tunnel option which will use internet for it.
I was having this issue and this is the main thread about the topic so I thought I'd add a solution that worked for me.
To reiterate, this is running Expo SDK 36 and WSL2 (Ubuntu 18.04 LTS, Win 10 build 19559.1000).
expo start would run (in WSL2), and the QR code would pop up. Scanning the code with my phone would result in an error.
The solution I found was to go to the Metro Bundler window that opens up. Under "Connection", three options are available: Tunnel, LAN, and Local. expo start defaults to LAN. This is where the error is seeming to occur.
The solution was to switch from LAN to Tunnel. This produces a new QR code which allows the Expo phone app to correctly identify and connect to the Expo project.
expo start --tunnel
I understand that the original post didn't want to use the tunneling option, but for those who can, this works.
Hope this helps!
To add to Simons answer, here is what I had to do to get it running.
In your WSL2, run ip addr
(Ubuntu). This will give you your IP address. Look for eth0, probably something like "inet 172.22.182.52". (note that if you are running multiple Expos on your machine then you may need to do this for more ports)
Then, in a Windows terminal (as administrator), run:
netsh interface portproxy add v4tov4 listenport=19000 connectport=19000 connectaddress=172.22.185.52
netsh interface portproxy add v4tov4 listenport=19001 connectport=19001 connectaddress=172.22.185.52
netsh interface portproxy add v4tov4 listenport=19002 connectport=19002 connectaddress=172.22.185.52
Windows firewall blocks stuff. Good. Now open up the ports expo needs. (note that if you are running multiple Expos on your machine then you may need to do this for more ports)
Inside Windows terminal (as administrator):
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort 19000 -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort 19001 -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort 19002 -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort 19000 -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort 19001 -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort 19002 -Action Allow -Protocol TCP";
I haven't tried these yet, but here are some scripts that automatically update the above stuff for you on restart.
You need to have a custom environment variable that specifies a different host for the QR code URL. Easiest is to prepend the variable to the command that you run. Preferably your project would have a file set up where you can put these variables.
In a terminal in Windows, run: ipconfig /all
. Somewhere there you will have the IP address to your Windows machine. Probably under Wireless adapter or Ethernet adapter.
In your project (from WSL2): REACT_NATIVE_PACKAGER_HOSTNAME=<IP address to your Windows machine> yarn expo:start
(or whatever your command is).
Here's the full steps I found worked for LAN development between my mobile and expo running in WSL2 (Ubuntu 20 on Windows 10 20H2):
Windows firewall should be on, and it should block inbound attempts by default.
The following will open the Expo ports 19000–19006, inbound, but only on a network that you have configured as "private" (that's the -Profile Private
part):
(powershell as Admin)
New-NetFireWallRule -Profile Private -DisplayName 'Expo ports for LAN development' `
-Direction Inbound -LocalPort 19000-19006 -Action Allow -Protocol TCP
(You can check it after with Get-NetFirewallRule |Where-Object {$_.DisplayName -Match "Expo.*"}
)
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 to connectaddress=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 that 127.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 inline Trim()
— 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());
This is the one that probably changes most often. Your laptop local network IP certainly changes when you change networks (eg home/office) — and can change at other times too.
Fortunately it's also pastable / aliasable:
WSL2 shell
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
(If your dev box doesn't change LAN often, you might get away with setting REACT_NATIVE_PACKAGER_HOSTNAME in your.bashrc /.zshrc)
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 commands 2 and 3 able to simple "rerun" and consistently get Expo LAN mode working for my WSL2-hosted Expo dev mode.
Tunneling will redirect your traffic through the internet and is slower than a direct connection.
I solved the issue by forwarding the ports 19000 and 19001 to WSL
netsh interface portproxy add v4tov4 listenport=19000 listenaddress=0.0.0.0 connectport=19000 connectaddress=127.0.0.1
netsh interface portproxy add v4tov4 listenport=19001 listenaddress=0.0.0.0 connectport=19001 connectaddress=127.0.0.1
(based on this excellent blog post)
A few other things to verify:
An update, two years later, in case it's helpful - I no longer need to do the netsh
commands shown in the Accepted answer to get this to work on WSL2 (and in fact, doing so breaks other things.) but I DID still need to do the firewall commands. Then all works well.
If you have IPV6 enabled on your windows machine, you can forward IPV4 requests on Exo's ports to locahost IPV6, like this:
netsh interface portproxy add v4tov6 listenport=19002 connectport=19002 connectaddress=::1 listenaddress=0.0.0.0
netsh interface portproxy add v4tov6 listenport=19001 connectport=19001 connectaddress=::1 listenaddress=0.0.0.0
netsh interface portproxy add v4tov6 listenport=19000 connectport=19000 connectaddress=::1 listenaddress=0.0.0.0
This is a permanent solution, since it keep working even when your WSL2 IP changes.
On your phone, you need to use exp://YOUR_WINDOWS_IP:19000
I found this when searching for a similar problem running Dokcer inside WSL2: https://github.com/microsoft/WSL/issues/4983
You can check if ports are correctly opened and set with sudo lsof -i -P -n | grep LISTEN
sudo lsof -i -P -n | grep LISTEN
I also had to add export EXPO_DEVTOOLS_LISTEN_ADDRESS=0.0.0.0
in my zshrc config
Maybe as bit of a summary here's what I ended up doing.
expo_wsl2_port_forwarding.ps1
and run once after my PC booted and WSL was opened: $local_ip = "0.0.0.0";
$wsl_ip = iex "wsl hostname -I"
$ports = @(19000, 19001, 19002);
$ports_list = $ports -join ",";
# Firewall rules
iex "Remove-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock'";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Outbound -LocalPort $ports_list -Action Allow -Protocol TCP";
iex "New-NetFireWallRule -DisplayName 'WSL 2 Firewall Unlock' -Direction Inbound -LocalPort $ports_list -Action Allow -Protocol TCP";
# Port-forwarding
for($i = 0; $i -lt $ports.length; $i++){
$port = $ports[$i];
iex "netsh interface portproxy delete v4tov4 listenport=$port listenaddress=$local_ip";
iex "netsh interface portproxy add v4tov4 listenport=$port listenaddress=$local_ip connectport=$port connectaddress=$wsl_ip";
}
You need to run this in an elevated prompt ("Run as administrator").
You may see an error you run it the first time as there won't be an existing firewall rule to delete.
REACT_NATIVE_PACKAGER_HOSTNAME=`dig host.docker.internal +short` expo start --lan
Here's it's important to note that the hostname host.docker.internal
will only be available if you're running Docker on the host (Windows). If you don't do that you'll have to figure out your host IP using another technique (see other answers).
You can use this script that i made!
It automates the entire process that Simon Farshid and Skurpi commented, such as:
19000,19001,19002,19003,19004,19005
on the Windows firewall;REACT_NATIVE_PACKAGER_HOSTNAME
environment variable into the .bashrc
and .zshrc
files (if there's);REACT_NATIVE_PACKAGER_HOSTNAME
automatically receives the IP address of the local machine (Windows);(Windows + "R")
with the command wsl2host
;Download this repository or if you have Git installed:
$ git clone https://github.com/jonhoffmam/wsl2_host.git
Run the start.bat file on the first run of the script
After is possible run script with command wsl2host
on Run
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.