简体   繁体   中英

How can i connect my phone to expo when using WSL2 to run it

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.

Forward the requests coming to Windows to the WSL2 instance.

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

Allow requests through Windows firewall

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";

WSL2 IP changes on restart

I haven't tried these yet, but here are some scripts that automatically update the above stuff for you on restart.

(Bonus) Update QR code that comes from Expo

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):

1. One time at the start: open Expo ports inbound in Windows Firewall

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.*"} )

2. Point 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());

3. Point Metro to your dev machine LAN IP Address; Re-run inside WSL "Each time dev host has a new IP address"

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:

  • You might need to configure your Linux Firewall to allow connections on ports 19000 and 19001 (I didn't need to do this)
  • You might need to set up a Windows Firewall rule for ports 19000, 19001 (I didn't need to do this)
  • Make sure that both your PC and your mobile device are on the same WiFi network

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.

1. Saved this as 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.

2. Then in WSL2 I run the following:

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!

https://github.com/jonhoffmam/wsl2_host

It automates the entire process that Simon Farshid and Skurpi commented, such as:

  • Open ports 19000,19001,19002,19003,19004,19005 on the Windows firewall;
  • Insert the REACT_NATIVE_PACKAGER_HOSTNAME environment variable into the .bashrc and .zshrc files (if there's);
  • The environment variable REACT_NATIVE_PACKAGER_HOSTNAME automatically receives the IP address of the local machine (Windows);
  • Defines a Windows registry key to facilitate the execution of the script through Run (Windows + "R") with the command wsl2host ;
  • Creates a schedule task on Windows to run the script at logon

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM