Connectivity from WSL2 to host by using actual IP
Asked Answered
G

4

2

Has anyone used WSL2 and connected to the host machine using its actual IP instead of through the WSL2 Network Adapter IP?

My situation is this: My ip is 192.168.1.2

I start a webserver on my actual machine, it binds to 127.0.0.1, and 192.168.1.2 I want do connect to the webserver from within a docker container under WSL2. If I ping/telnet/curl to 192.168.1.2 the call simply fails from a timeout, this happens both from my docker container as well as straight from within ubuntu under WSL2

I have verified that I can ping my router at 192.168.1.1 from within my docker container. I cannot access 192.168.1.2 from within my WSL2 shell outside of docker. I cannot use 127.0.0.1 as a replacement, as the end goal is to run a setup of docker inside WSL2, that calls the webserver on my machine (i.e. I want to start up 4 services and a database through docker, and then actively develop and debug a 5 service on my actual machine).

I've tried disabling the firewall completely to no avail.

Does anyone have an idea of what it could be? Or if I'm even supposed to be able to access 192.168.1.2 from within WSL2.

Gutta answered 21/7, 2022 at 8:46 Comment(5)
Presumably the 192.168.1.2 address is the address of the Ethernet card? Or WiFi? IP addresses belong to adapters, they're not system-wide. Docker adds its own virtual adapters on top of WSL2.Embank
To access host from WSL2, you can use $(hostname).local , also check #65626262 for enabling traffic from WSL2. And to access host from docker - host.docker.internal ( #31325481 )Pentarchy
@msalters Correct, 192.168.1.2 is the IP of my WiFi connection. I know the IP isn't system wide, but the webserver binds to that IP, so I need to be able to access it (since I can't use localhost/127.0.0.1 from within the docker containers, as they would just point to the docker container itself)Doll
@Pentarchy Yes, I can access the host machine itself using that, but the problem is that it will point to the WSL2 interface, which the webserver can't bind to. So even if I have connectivity to my local machine by using it, there's no way to get the webserver to bind to it (at least not that I've found)Doll
@LinusVikström , are you sure it's a binding and not a firewall issue? Tested with nginx running on Windows 10, default config ( server { listen 80; server_name localhost; ...} ) . By default requests from WSL2 were blocked but once blocking nginx rules for Public profile in Win Defender Firewall were disabled, everything (i.e. curl $(hostname).local from WSL2) )seems to work just fine.Pentarchy
C
3

A few different ways (and things you might have to do) to make this work. You may have some of this in place already:

  • First, as mentioned in the comments, the best name to use (in most cases) from WSL2 when accessing a service running Windows is the mDNS format $(hostname).local (or the equivalent from whatever language you are using). This can be hardcoded as simply the Windows "Computer Name" + (concatenated with) .local.

  • Next, remember that the first time you try to access a network service on a port, Windows Defender Firewall will ask you for permission to create a rule. By default, this rule only applies to Private network profiles. As a result, a corresponding Block rule is created for the port on any Public network profile. I honestly just discovered this when trying this out. I don't think I knew that a corresponding Block was generated by that GUI dialog.

    Since WSL's network is (oddly) considered Public, you'll need to delete that Block rule if it exists.

  • You'll then also need to open an Allow rule for the port from WSL. Something like:

    New-NetFirewallRule -DisplayName "WSL Testing" -InterfaceAlias "vEthernet (WSL)" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
    

    This will open the port on both Public and Private networks, but only on the WSL virtual interface. It will still be blocked from other machines on the network (assuming that's what you want).

  • Now for the bind address, you have several options:

    • If you really do want to bind only to the WSL virtual network, then you'll need to either obtain (or parse somehow) the correct address, since it will after each reboot (or wsl --shutdown). You can see the correct address with ipconfig in PowerShell, and look for:

      Ethernet adapter vEthernet (WSL):
      
         Connection-specific DNS Suffix  . :
         ...
         IPv4 Address. . . . . . . . . . . : 172.25.208.1
         Subnet Mask . . . . . . . . . . . : 255.255.240.0
         ...
      

      In this case, the bind address would be 172.25.208.1.

    • Alternatively, I don't believe there's much of a reason not to just bind to 0.0.0.0 (all interfaces), since the firewall is going to block connections from other networks (assuming you specified the -InterfaceAlias "vEthernet (WSL)").

    • However, from the comments, you also mention:

      192.168.1.2 is the IP of my WiFi connection. I know the IP isn't system wide, but the webserver binds to that IP, so I need to be able to access it

      If you really can't change the bind address to something else, then you won't be able to access it directly from WSL2. However, it's still possible to use port forwarding to get the packets to the right interface, if that's the case.

      The easiest way to do this is to install/enable the Windows OpenSSH server, and then use something like:

      ssh -L 80:localhost:80 $(hostname).local
      

      That will make localhost:80 in WSL2 connect to the Windows service on port 80.

      If you need the server name to match some virtual host name (SNI), then you can add the hostname to your Windows host file (which is mapped into WSL2 by default) as a pointer to localhost.

Conceit answered 21/7, 2022 at 15:32 Comment(0)
A
1

In my case, when the Windows host was connected to a VPN, the only chance to connect to the host from within WSL2 was to use the external VPN IP. From within WSL2, I got it with:

ipconfig.exe | grep -m 1 IPv4 | cut -d ':' -f2

(in my case, ipconfig outputs the VPN address always first)

Axiom answered 29/3, 2023 at 12:24 Comment(0)
B
0

Here is a simple, but maybe less secure approach (depending on your use case). What is happening is your WSL network doesn't have access to make a request to the IP of the host, this is because your firewall has blocked access from other networks aside from the localhost network which is 127.0.0.1 to.

Here is what worked for me.

  • Run this command on wsl to get your host ip address cat /etc/resolv.conf.
  • Turn off your firewall, navigate to your windows host control panel, under security and network, turn off the firewall.

This solution may not be recommended but it gives you the opportunity to test whatever you are doing. At least I had to save myself the stress. This also helps if you are running a software on WSL that needs access to open any port

Barony answered 22/7, 2023 at 20:39 Comment(0)
H
0

As you mention that the end game is a Docker solution then this answer reflects that.

First, make sure you can ping your host from another machine just to be sure you have the correct IP address.

If all good then this should work on WSL

docker run --rm busybox ping <IP of your Windows Host> -c 2

If this doesn't work, then you may have a DNS issue, Docker uses Google's DNS and if your network is using a different DNS or your network filters Google's DNS traffic then you'll need to tell docker about this.

Find the IP address of the DNS server your Windows network is using. Then try the following:

docker run --rm --dns "<IP Windows DNS>" busybox ping <IP for Windows Host> -c 2

To set and forget, you can add this IP address to docker's configuration file etc/docker/daemon.json

{
  "dns": [
        "<DNS IP address>",
        "8.8.8.8",
        "8.8.4.4"
   ]
}

restart the docker service

sudo service docker restart
Hydria answered 31/1 at 19:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.