Access a localhost running in Windows from inside WSL 2 [closed]
Asked Answered
C

7

56

I am running a local AEM server in my Windows machine. The server is running on localhost:4502. I am using a Ubuntu distribution running in WSL 2 for my development. I want to access the localhost:4502 running in the Windows machine in my WSL 2 Ubuntu.

Is there a way to do that or is it not possible?

Cedrickceevah answered 10/11, 2020 at 5:1 Comment(4)
Your Windows's machine IP plus the 4502 should be enough, though you would like to check that the firewall is allowing the connection,Yon
No this is completely wrong!, I have this problem too and your answer is wrong unfortunately. I try ssh -p <myCustomPort> <myWindowsIPstartingWith192.168..> and the connection is immediately and always refused ! any other ideas?Felony
Please do the following steps: 1. Get IP of window by run command line on WSL Ubuntu: cat /etc/resolv.conf. It will show "nameserver <your_windows_mechine_ip>". 2. Turn of the Firewall on the Windows. 3. Connect to your windows host.Aguste
For me, was solved after execute in PowerShell: netsh interface portproxy add v4tov4 listenport=4000 listenaddress=0.0.0.0 connectport=4000 connectaddress=192.168.101.100 .... connectaddress = nameserver in resolv.confYounker
M
114

Please note that, since this question has been closed as off-topic, I recommend that new answers and updated information be posted on this Super User question. As such, please refer to my answer there for the latest version of this information. I'll try to keep both up to date, but I'll give priority to the Super User version.

As of WSL2 2.0.0 (September 2023), there are two good options. Note that these options are "mutually exclusive", in that using one means that the other can't work.

Short(ish) answers:

  1. NAT (default) WSL2 networking with mDNS

    Concatenating your WSL2 hostname (or the equivalent command/function in your programming/language environment) with ".local" (the host mDNS name) should 1 get you access. For example, in Bash try:

    ping "$(hostname).local"
    

    Or, let's say you are trying to access MongoDB from Python, as in this question:

    import socket
    server = f'{socket.gethostname()}.local'
    host = f'mongodb://{socket.gethostname()}.local'
    
  2. Mirrored Mode WSL2 Networking

    Note: Requires Windows 11 23H2 or later

    In Mirrored mode, localhost should "just work". To enable:

    • Add the following to your <windows_user_profile>/.wslconfig:

      [wsl2]
      networkingMode=mirrored
      
    • Exit your WSL distribution

    • Run wsl --shutdown from PowerShell then restart WSL

    You should then be able to access services running in Windows via localhost.

    Note that when running in Mirrored mode, mDNS will not work.

More explanation:

Option 1: NAT with mDNS

The default network mode of WSL2 is NAT'd behind a virtual Hyper-V switch. Up until recently, this was the only networking mode for WSL2. In this mode, WSL2 is running with a virtual network (vNIC) that is created by the Windows Virtual Machine Platform (a subset of Hyper-V). Inside WSL2, localhost is the address of the vNIC rather than that of the Windows host.

In this mode, using the mDNS name for the Windows host 2 is usually the easiest solution.

mDNS has been a feature of WSL2 for a while now. Concatenating your WSL2 hostname (or the equivalent command/function in your programming/language environment) with ".local" should get you access.

As mentioned above, from Bash, try:

ping "$(hostname).local"

For instance, if your hostname is "MyComputer", then the mDNS should be MyComputer.local.

If ICMP is blocked (as it seems to be on new Windows 11 installs), or if you want to test the connection to the actual port, then use netcat instead of ping. It's available by default in the WSL Ubuntu installation, but may need to be installed in other distributions like openSUSE:

nc -zv "$(hostname).local" <portnumber>

See also "Other NAT/mDNS considerations" 1.

Option 2: Mirrored Network Mode

Release 2.0.0 of WSL2 introduced a new Mirrored networking mode that can simplify many of the network access issues.

In this mode, the Windows network interfaces are mirrored into WSL2. When you run ip addr, for example, you'll see (mostly) the same interfaces as when you run ipconfig /all from PowerShell/CMD.

Because of this, localhost is routing through the mirrored Windows loopback adapter.


Footnotes:

1 Other NAT/mDNS considerations

  • mDNS is reliant on the Windows host to resolve the name. If you have changed your /etc/resolv.conf under WSL, then this will likely not work.

  • Remember to open any necessary firewall ports. WSL2 is considered a separate network from that of the Windows host. Windows will consider network connections from WSL2 to be coming from an external source. (Credit to @RamilGilfanov for a comment pointing this out)

    The first time a connection is made from WSL2 to a particular port, Windows Defender (if that is your firewall) will typically display a dialog asking if you want to grant access. However, in my experience, this dialog often gets buried under the main window due to timing of mouse-clicks, keyboard, etc., so it's easy to miss.

  • Remember to have your Windows service accept connections from remote hosts.

    Many servers are configured by default to bind to localhost/127.0.0.1. Because WSL2 appears to Windows as a remote network, you'll typically need to update your configuration to bind to 0.0.0.0 or a specific address.

    Note that, since the address for WSL2 changes after each reboot, it can be difficult to update your configuration each time. If at all possible, use 0.0.0.0 unless there are security concerns. Since WSL is designed for development rather than production, this shouldn't be an issue.


2 Technically, this is the IP address of the virtual switch that WSL2 uses to interface with Windows and the outside world.

You can see this via:

ip route

This is the address you need to use for the Windows host.

You could, of course, parse it from the route (or, as in an earlier answer, from /etc/resolv.conf), but since WSL sets up the convenience mDNS (the .local domain) it's easier to just use that.

Muffin answered 1/10, 2021 at 13:53 Comment(14)
Excellent! Why isn't this marked as the answer? You can wrap this idea with a convenient script which you call, instead of curl directly.Broil
and open ports in windows firewallHereafter
@RamilGilfanov Great point! I've edited that into the answer.Muffin
I am able to ping windows host IP but still unable to access any opened port on windows from WSL2 (firewall closed), do you have any insights? Thanks!Cribbage
@Cribbage I'll probably need more info. If you'd like, open a Super User question on it with more detail (commands, ports, firewall rules, whatever you can think of), and I can take a look. I'm a little bit unclear on what you mean by the "opened port / (firewall closed)" part.Muffin
Hi @NotTheDr01ds, I have posted a question: superuser.com/questions/1738265/…, would you mind if you can take a look? Thanks!Cribbage
What if you wanted to reach some other address within the 127.0.0.0/8 range?Tavel
@Tavel Can you provide more details on your use-case (possibly with a new Super User question)? The simple answer is that the entire loopback subnet in Windows isn't accessible from WSL2. That's why we need the mDNS address.Muffin
Got an app that securely connects to some servers via ssh. When the connection is established, in the PC running said app, you ssh to an address in that space. So I wanted to ssh from WSL to one of those. I can set up an ssh server in the Windows host that runs the app, then make an ssh tunnel as a workaround.Tavel
@Tavel Agreed - that's my typically recommendation. Having that SSH server in Windows makes a lot of WSL2 tasks easier. See my jumphost answer here for details. I've used it in quite a few other answers as well.Muffin
None of the top 2 answers work for me. In this answer, I got the hostname and filled it in both nc -zv "$(hostname).local" <portnumber> and ping "$(hostname).local". Both just hang. Maybe I should hang as well.Directional
@BobtheBuilder It could be the firewall issue that RamilGilfanov pointed out. Are you sure the firewall rule got created on first access as mentioned in the answer?Muffin
@Muffin I had made a rule in windows firewall that allows connections from port 4502. I also made another rule that allows ports from a range starting from and ending to a range I cannot recall at the moment, another post said these were possible ports WSL could connect from. No banana.Directional
@BobtheBuilder You might want to post a new question on Super User (or Ask Ubuntu, if you are using Ubuntu). Reference this one, but add any specifics on what you've tried. I'll try to take a look at it. Thanks!Muffin
M
14

I was also looking for some solution to do this, but currently there isn't any such option available. Check out this GitHub issue:

[WSL 2] WSL 2 cannot access Windows service via localhost:port #4619

One solution can be this:

If you have the IP address of the Windows (host) then it will do the job, but the only problem is that the IP address will change every time. But, WSL 2 stores your Windows (host) IP address in the /etc/resolv.conf file. So we can modify our etc/hosts file to map winhost to the IP address dynamically.

Add the following lines at the end of the ~/.bashrc file file. This will grep the IP address and modify the etc/hosts file when you boot the WSL.

export winhost=$(cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }')
if [ ! -n "$(grep -P "[[:space:]]winhost" /etc/hosts)" ]; then
        printf "%s\t%s\n" "$winhost" "winhost" | sudo tee -a "/etc/hosts"
fi

Then run the following command to reload the changes.

source ~/.bashrc

Now you can use winhost instead of localhost in WSL 2 (client) to access the servers running Windows (host). In your case, it will be winhost:4502, but this will work for any other use cases as well like accessing a PostgreSQL or MySQL server running on Windows, etc.

Note: Always remember to configure your firewall on Windows to allow those ports, so that WSL 2 can access it. Otherwise, your connection may get blocked by the firewall.

Melindamelinde answered 23/6, 2021 at 21:0 Comment(3)
Hello, I have this problem too and your answer is wrong unfortunately. I try ssh -p <myCustomPort> <myWindowsIPstartingWith192.168..> and the connection is immediately and always refused ! Any other ideas?Felony
@Felony I am not sure what you are trying to achive. Can you elaborate more?Melindamelinde
This is the accepted answer but it implies that the service is not listening on localhost, but on 0.0.0.0 with a firewall...Shoop
S
5

This is simple; you just need to do two things. Set the IP address to localhost in the hosts file and allow Windows Firewall to allow incoming connections.

Here are step-by-step instructions:

  1. Get the IP address. Open cmd.exe and type ipconfig /all. Note down the IP address 172.22.16.1

    image

  2. Open Notepad as administrator, menu Fileopen, browse to C:\Windows\System32\drivers\etc\hosts, add the line 172.22.16.1 localhost, save and close.

  3. The last option is to allow Firewall rules to accept public connections. For this, open Control Panel* → System and SecurityWindows Defender FirewallAdvanced SettingsInbound RulesNew Rule

  4. Rule Type: choose Port and click Next

  5. Protocol and Ports: type Specific local port: 4502, and click Next

  6. Action: Allow the connection and click Next

  7. Profile: check Public and click Next

  8. Name: type AEM server and click Finish

  9. Close other windows, and again open cmd. Type wsl --shutdown for shutting down the Ubuntu subsystem.

  10. Open Ubuntu again.

  11. Testing connection: type curl localhost:4502 in command prompt. If it returns something, it means you are good to go.

Spermaceti answered 6/3, 2021 at 10:20 Comment(7)
wanted to add if it doesn't return something you can also be good to go -- just so long as it doesn't hang or give a message about connection refused. I had a test service that was just logging get requests but not returning anything :)Tetchy
@Tetchy by not hanging you mean it should return and let you type another command? does not work for me then :(Directional
@Spermaceti Isn't making port 4502 public a security risk?Directional
@BobtheBuilder correctTetchy
@BobtheBuilder - What kind of Security risk? sniffing attack or data breach? opening port is not always a security risk, we had allowed our hosted OS to access with a virtual private network created to access a virtual OS. I don't think there is any security risk.Spermaceti
@Spermaceti Nvm chatgpt explained it. A local port isn't accessible to the internet unless we configure a port on our router to forward traffic to the port on our computer. Afaik.Directional
@BobtheBuilder yes, you can't access private network outside of local network, if you want then setup apache, nginx server and write port forwarding. ChatGPT can give you the steps as well if you want that. Actually those are just few lines of configuration and restart.Spermaceti
D
2

You need add an IPv6 rule in the hosts file.

Like:

127.0.0.1 example.com
::1 example.com localhost

I had a similar problem and found the solution at the page WSL 2 Linux host cannot be accessed by a custom domain name or 127.0.0.1 #5728.

Dermatoplasty answered 13/12, 2021 at 19:49 Comment(1)
Windows hostfile?Kislev
C
0

The easy way:

On the Ubuntu command line, type:

ip route

Output:

default via 172.23.96.1 dev eth0
172.23.96.0/20 dev eth0 proto kernel scope link src 172.23.97.122

In your application, configure the host to: 172.23.97.122

Now you can access it using Windows Browser.

Conjoined answered 22/11, 2021 at 18:54 Comment(2)
Hello and Welcome to Stack Overflow. Just a heads-up that I already covered the ip route command as an option to get the IP address in my existing answer. Duplicate answers should be avoided, so please make sure to read the existing answers before writing a new one. Also note that this IP address changes each time you restart WSL (or your computer), so it's not "the easy way", unfortunately. As I mentioned in my answer, it's best to use the mDNS name, since that will always resolve to the correct address (as long as mDNS is enabled).Muffin
What is "Windows Browser"? File Explorer?Wintry
N
-4

Windows 10 considers localhost as ::1. Ubuntu considers localhost as 127.0.0.1.

So solution is to create a mapping. Create a file called *.wslconfig* in C:\Users\<your_username>\.wslconfig.

Add the following to it.

[wsl2]
localhostForwarding=true

PS: I don’t know if it messes up anything else, but it helped me run Django servers which were broken after upgrading to WSL 2.

Natalyanataniel answered 26/1, 2021 at 22:20 Comment(4)
localhostForwarding should already default to true on WSL2, but sometimes it seems to break down, and I haven't been able to identify a cause. Usually just doing a wsl --shutdown and restarting the session will restore it for most people.Muffin
This answer really needs at least one correction. ::1 vs 127.0.0.1 has absolutely nothing to do with Windows 10 vs. Ubuntu. Windows 10 understands 127.0.0.1 just fine, and Ubuntu understands ::1 just fine, too. The real difference is that ::1 is the IPv6 address, and 127.0.0.1 (or any IP address starting with 127, really) is IPv4.Continuous
so please do explain exactly why this fixed my issue? because as far i'm concerned it fixed the issue. and apparently for the users as well.Natalyanataniel
From microsoft doc, localhostForwarding means "ports bound to localhost in the WSL 2 VM should be connectable from the host" but not "ports bound to localhost in the host should be connectable from the WSL 2 VM", so this answer won't work.Hoarding
T
-5

I suspect you could do this.

  1. Step 1. Run your AEM server on your actual IP address (or all addresses) instead of binding to just localhost.

  2. Step 2. Your Ubuntu WSL client instance won't share localhost with the host machine, but it will share the local IP address your machine actually has (e.g. 10.0.0.2). Just have your client connect to that IP address instead of localhost.

  3. I don't know anything about AEM, but you might need to secure it if you are exposing it to a larger network. Block port 4502 on the upstream firewall or use a Windows Firewall rule to only allow incoming on port 4502 from your own IP address. This certainly appears possible.

Thebaine answered 10/11, 2020 at 10:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.