microsoft / WSL

Issues found on WSL
https://docs.microsoft.com/windows/wsl
MIT License
17.43k stars 822 forks source link

Binding WSL2 ports to a different IP address in 127.0.0.0/8 range #5732

Open milolav opened 4 years ago

milolav commented 4 years ago

Is your feature request related to a problem? Please describe. If I have webserver or a database running on specific port in Windows, I cannot start server in WSL that listens that same port because it is already in use. For example, if I have IIS running on port 80, I cannot start php server inside WSL with php -S 0.0.0.0:80.

There are 16777216 addresses in the loopback range and apps always wants to use 127.0.0.1 and then listen on a random, hopefully unused port. Why not use a different IP?

Can we have an option to specify a custom IP in the loopback range?

Describe the solution you'd like A configuration option to specify a custom IP address in the 127.0.0.0/8 range for mapping WSL ports

Describe alternatives you've considered Using a different ports between host and guest or binding host's processes to something other than 127.0.0.1 so that WSL can use 127.0.0.1

therealkenc commented 4 years ago

Why not use a different IP?

WSL2 has its own IP segment. Assigning the address is #4210.

milolav commented 4 years ago

@therealkenc It is not the same. In my case, I cannot even start the server inside WSL2 if the port is in use on the host unless I turn off localhostForwarding.

When a server inside WSL2 is started, wslhost.exe automatically opens the port on 127.0.0.1 or fails if the port is in use. Not related to WSL network segment but to localhost forwarding. There is only one mention of a different IP in https://github.com/microsoft/WSL/issues/4210#issuecomment-626669198, 127.0.1.1 but that is not working.

therealkenc commented 4 years ago

I cannot even start the server inside WSL2 if the port is in use on the host unless I turn off localhostForwarding

[edit, simplified extraneous]

Cannot repro your scenario. You've got other variables. Using sshd port 22 as an example:

image

[^--- that is with localhostForwarding left alone equivalent =true.]

therealkenc commented 4 years ago

image

milolav commented 4 years ago

My appologies @therealkenc, it took me some time to reproduce everything.

1) PHP running on both Windows and WSL, using same port

SS20200807_221352

SS20200807_221357

  1. No processes listening on port 80
  2. Start php.exe on Windows listening on 127.0.0.1:80
  3. netstat.exe shows php.exe listening on 127.0.0.1 port 80
  4. Open http://127.0.0.1/hello.txt in browser - 200 from php.exe
  5. Start php inside WSL, listening on 0.0.0.0:80
  6. netstat.exe shows two processes (php.exe and wslhost.exe) listening on 127.0.0.1 port 80
  7. Open http://127.0.0.1/hello.txt in browser - 200 from php.exe
  8. Terminate php.exe
  9. Open URL in browser - 404 from wsl php

2) IIS listening on 127.0.0.1 IP (single IP set with netsh http add iplisten 127.0.0.1)

SS20200807_220650

  1. No processes is listening on port 80
  2. Start IIS service
  3. netstat.exe shows IIS (no ownership information) listening on 127.0.0.1 port 80
  4. Open http://127.0.0.1/ in browser - Site serverd by IIS
  5. Start php inside WSL, listening on 0.0.0.0:80
  6. netstat.exe still shows only IIS (no ownership information) listening on 127.0.0.1 port 80. WSL php is inaccessible from Windows.

3) IIS listening on 0.0.0.0 (Standard configuration)

SS20200807_220158

  1. No processes is listening on port 80
  2. Start IIS service
  3. netstat.exe shows IIS (no ownership information) listening on 0.0.0.0 port 80 and [::] port 80
  4. Open http://127.0.0.1/ in browser - Site serverd by IIS
  5. Start php inside WSL, listening on 0.0.0.0:80
  6. netstat.exe still shows only IIS (no ownership information) listening on 0.0.0.0:80 and [::]:80. WSL php is inaccessible from Windows.
  7. Stop IIS service
  8. netstat.exe shows no processes listening on port 80
  9. Start php inside WSL, listening on 0.0.0.0:80
  10. netstat.exe shows wslhost.exe listening on 127.0.0.1 port 80
  11. Open URL in browser - 404 from wsl php (not visible in the screenshot, sorry)

4) WSL php listening on 0.0.0.0:80

SS20200807_224909

  1. No processes is listening on port 80
  2. Start php inside WSL, listening on 0.0.0.0:80
  3. netstat.exe shows wslhost.exe listening on 127.0.0.1 port 80
  4. Start IIS service
  5. netstat.exe still shows wslhost.exe listening on 127.0.0.1 port 80. IIS server is inaccessible.
  6. Open URL in browser - 404 from wsl php
  7. Looking at the IIS Manager I can see that website is stopped. Trying to start it shows an error SS20200807_224429
  8. Stop WSL php
  9. No processes is listening on port 80
  10. Start IIS Site from the UI
  11. netstat.exe still shows only IIS (no ownership information) listening on 127.0.0.1 port 80
  12. Open http://127.0.0.1/ in browser - Site serverd by IIS

So if I could set WSL (wslhost.exe) to use specific loopback IP address for localhost forwarding (let's say 127.0.51.1) I would avoid clashing with the existing services running in Windows.

I hope this makes it a bit more understandable.

//edit Regarding initial comment that starting server inside WSL fails if the port is in use on Windows, seems like I had another server already running in a different linux distro and as they all share the same VM, that was the source of the error I was getting.

therealkenc commented 4 years ago

Okay but that's just square by-design territory. You've bound to the same port on 127.0.0.1. Even in the (academic hypothetical) that you got your ask for WSL to fire up on 127.0.0.42, you'd have to bind to that and address and connect to that address. You'd have to type 127.0.0.42 into your window browser (you sure as heck wouldn't type localhost).

Which is #4210: a static configurable IP address. [With a really bizarre choice of the remote IP address.]

linux distro and as they all share the same VM, that was the source of the error I was getting.

That was my guess.

milolav commented 4 years ago

Yes, I'd have to type that IP address or have it set in hosts, but it wouldn't interfere with other services running on 127.0.0.1. And with the source of an error being cleared out, it might fall under the #4210, with, as you say, a really bizarrely chosen static configurable IP 😁

therealkenc commented 4 years ago

Let's call it #4210, on the basis your ask isn't actually happening whether this issue is closed, or left open 'feature request' loophole.

Pro-tip for the price you paid for it, try out avahi-daemon(8). TL;DR, sudo service dbus start and sudo service avahi-daemon start, after editing /etc/avahi/avahi-daemon.conf. That will get you wsl.local to type into your browser. Which is probably what you actually want, contrast typing 127.0.0.42, or mucking hosts.

milolav commented 4 years ago

Thanks, but what I actually do want WSL on a different loopback IP. Then I can add just another entry to the dnsmasq configuration similar to address=/iis.local/127.0.2.1 for .iis.local or address=/php.local/127.0.5.1 for .php.local, etc. While 127.0.0.1 is for stuff related to "localhost". Just a way of organizing services. And it works with real TLDs so I can easily change underlying IP to wherever something is deployed.

Still hoping that someone would find this reasonable and implement configuration for binding a different loopback IP.

richardzuidhof commented 2 years ago

Currently only localhost traffic (127.0.0.1/32) is forwarded from Windows to WSL. I would like to see all loopback traffic for 127.0.0.0/8 forwarded from Windows to the same IP within WSL. I use the requested feature mainly for tunneling to remote environments. This works using SSH outside WSL but not with SSH from within WSL. For instance if I tunnel to remote site 1 the local IP would be 127.0.1.1 and to remote site 2 the IP is 127.0.2.1, both port 443. With a hosts file entry I can then access those site as if they were local. Since WSL2 the workaround is to run a full GUI within WSL so I can do the tunneling from within WSL.

vbrozik commented 2 years ago

@richardzuidhof I use SSH tunnels in a similar way. My main difference is that I replace the first octet of the destination IP address by 127 to get the local IP address of the SSH tunnel. So tunnel to 192.168.6.59:443 would be: 127.168.6.59:443. (I did not need to solve an address conflict yet.)

It would be great to have a possibility to automatically map the whole 127.0.0.0/8 range. Currently I create the tunnels twice: inside WSL2 and inside Windows.

merarischroeder commented 1 year ago

Note: Linux usually only has an interface binding for 127.0.0.1/32 alone. You can get it to listen for the other localhost IP addresses. But I suspect explicit support will be required via WSL to make it work.

BTW, I need this kind of thing too: