microsoft / WSL

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

WSL2 Set static ip? #4210

Open scrossan-crown opened 5 years ago

scrossan-crown commented 5 years ago

This maybe the wrong place to post this but not sure where else to post. Is it currently possible to set a static ip for the WSL2 machine?

I'm loving WSL2 so far with docker and vscode and my only issue is dynamic ip at the moment.

edwindijas commented 5 years ago

There is a work around. You can port forward to host ip. Check the below link. https://github.com/microsoft/WSL/issues/4150

zippaaa commented 5 years ago

I agree with the author of the question, please, Wsl2 must have option "static IP". Maybe cmd: wsl --ip <Distro> <IP address>?

scrossan-crown commented 5 years ago

My issue isn't just with port forwarding and docker. The biggest issue was that I am using VSCode remote development extension and remote developing in WSL and if I need to restart WSL2 to release some resources then I can't just reconnect in the usual way and any unsaved changes get lost which accidentally happened last week.

MiklerGM commented 5 years ago

@alekseymvt You could execute any command using wsl like this

wsl -- ifconfig eth0
yanyan33333 commented 5 years ago

Any solution? also see https://github.com/MicrosoftDocs/WSL/issues/418#issuecomment-511104330

The Hyper-V Switch IP change everytime when the windows reboot, so the gateway in wsl 2 also need to change

GhostvOne commented 4 years ago

Looking for a solution too :)

MiklerGM commented 4 years ago

With the latest update, you can access remote ports(WSL2) as local on Windows Host

You can have a look at this Windows Service - assign a static hostname for WSL machine

zippaaa commented 4 years ago

With the latest update, you can access remote ports(WSL2) as local on Windows Host

Can anybody check?: Will "http://mysite" work too, if I add "127.0.0.1 mysite" in "windows/hosts"? or localhost only?

MiklerGM commented 4 years ago

Yes, it should work

scrossan-crown commented 4 years ago

It would be nice but instead of WSL 2 ports being bound to 127.0.0.1 they are bound to ::1 and that doesn't work in the browser or hosts file. So we got localhost support but not in a way we can map other domains to it.

moigagoo commented 4 years ago

@MiklerGM

Yes, it should work

It doesn't, unfortunately. To point a custom domain to WSL, I'm adding a line like 172.25.203.130 mysite.com, where 172.25.203.130 is the IP of eth0 interface of the WSL VM: ip addr show eth0 | grep 'inet\b' | awk '{print $2}' | cut -d/ -f1

MiklerGM commented 4 years ago

@moigagoo check out this https://github.com/shayne/go-wsl2-host you can do it automatically with this service

moigagoo commented 4 years ago

@MiklerGM Thanks, I've seen it. I'm OK with my own self-written script.

MiklerGM commented 4 years ago

btw, I have no problem accessing the custom domain, for example, test.com from my browser My hosts file on Windows host machine

127.0.0.1 localhost api db test.com
172.20.124.104 wsl.local

image

moigagoo commented 4 years ago

@MiklerGM Huh, that's interesting. Tried that several times, it never worked, adn still doesn't 🤔

It works even if you remove the last line, doesn't it? Maybe, you did something else apart from editing hosts file, like installed something like dnsmasq? Also, maybe this Go service does more than just writes to hosts?

yanyan33333 commented 4 years ago

maybe build 18945 https://devblogs.microsoft.com/commandline/whats-new-for-wsl-in-insiders-preview-build-18945/

scrossan-crown commented 4 years ago

@yanyan33333 I'm already on build 18945 but still no joy

image

GhostvOne commented 4 years ago

With the latest update, you can access remote ports(WSL2) as local on Windows Host

Can anybody check?: Will "http://mysite" work too, if I add "127.0.0.1 mysite" in "windows/hosts"? or localhost only?

Yes, it should work

I confirm it doesn't work. I would add my custom domain with 127.0.0.1 but doesn't work when I try to access with this domain. localhost work, but not custom hosts

scrossan-crown commented 4 years ago

One work around I've found is if you are using docker and you install the latest edge version. It has support for WSL2 and it uses some magic (not sure what it's doing) but now 127.0.0.1 is working for in my hosts file for the apps in my docker containers on WSL2.

yanyan33333 commented 4 years ago

@scrossan-crown it works ,I start nginx on wsl and I can visit the website in windows brower by using localhost

scrossan-crown commented 4 years ago

@yanyan33333 I can do the same but can't use 127.0.0.1 in my hosts file with a domain name and access my docker container running on port 80 but I can now that I'm using docker desktop edge version

zippaaa commented 4 years ago

@yanyan33333

I start nginx on wsl and I can visit the website in windows brower by using localhost

Check custom domain: WSL2 /etc/nginx/conf.d/mysite.conf ->

server {
    server_name mysite;
    listen 80;
    ...
}

Windows hosts -> 127.0.0.1 mysite -> http://mysite

MiklerGM commented 4 years ago

@alekseymvt it is working for me image

I do not have dnsmasq, but I've got service in Go (I should've removed it by now), and a started systemd service. /etc/hosts on my WSL and windows systems are in sync, I did not change anything on WSL.

From my knowledge, this should not affect the GET requests. You can even send GET request via telnet. The domain in your browser's address bar only represents the HTTP Header for HOST directive.

Steps to debug

In case it is not working

zippaaa commented 4 years ago

@MiklerGM

it is working for me

Thank you, I saw your answer. I answered to @yanyan33333, because he wrote about localhost. I will check a custom domain later for myself, I need download 3Gb :)

craigloewen-msft commented 4 years ago

We also had a bug where you needed to bind your Linux applications to 0.0.0.0 instead of 127.0.0.1 to access it, which we've fixed. This is being tracked in issue #4353

webfaqtory commented 4 years ago

On build 18963 I can access http://localhost fine but in my Windows host file I have defined domains: 127.0.0.1 www.tripal.john 127.0.0.1 www.tripal3.john 127.0.0.1 clean.tripal3.john These refuse to connect. Even added them to /etc/hosts. No joy

sth4me commented 4 years ago

Set 127.0.0.1 domain in Windows hosts file does not work all the time,even only do nothing. File I/O in /mnt is slow, so I put my project files in ~/, then IDE should use them by sftp. But when sftp connect for a while, all connections by hosts file will fail. I use script change hosts file ip to wsl ip, and let project files in /mnt, it works well. Static IP may be better.

therealkenc commented 4 years ago

Rider that really what is needed is a static MAC address, on which a static IP can follow as a side effect if desired. Ref #4454, use case being that some software uses the MAC address to implement intellectual property control.

Really the IP address is neither here nor there; the address needs a stable name. Depending on some memorized IP addresses goes against best practice. Acknowledging that this is what a lot of people do, and it is a valid ask. Noting the strategy doesn't work so good with ipv6.

therealkenc commented 4 years ago

Someone was looking at a $WSL_HOST_IP approach in July ref #4212 (message) although the repo appears empty now.

You can get the WSL2 instance IP address easy enough:

C:>wsl.exe -d Ubuntu-18.04 /bin/bash -c "hostname -I | awk '{print $1}'"
172.21.141.235

And the other direction:

$ ip route | grep default | awk '{print $3}'
172.21.128.1

Those can be assigned to environment variables to taste. But that's not really the ask(s).

jpsenior commented 4 years ago

Changing the guest VM static IP address here doesn't satisfy the behavior that the WSL-side bridge /16 will change on every subsequent reboot. The problem needs to be resolved on both Host side and Guest side, and we cannot control Host.

You can be deterministic about the IP address you get within 172.21.0.0/16 -- but we cannot even be sure you are in 172.21.0.0/16 in the first place.

compagnon commented 4 years ago

An additional use case is to enable easily remote debugging with Linux hosted servers and W10 hosted IDE. concrete example is PHP-fpm server with XDebug Zend extension on WSL2 (node should be the same headache, python is OK because remote debugging is on SSH) trying to connect XDebug agent inside VS Code (PHP Debug extension)

As of now, the setup is complex:

VS Code must listen on hostname 0.0.0.0 (and not the default localhost) PHP-fpm must be setup with remote host on IP of host (nameserver inside /etc/resolv.conf (the xdebug.remote_host must be setup on Windows IP to dialog with VS Code) - if not , the Xdebug will never be able to go outside WSL2 boxing to the Windows hosted listening agent.

moreover, Windows firewall / defender must authorise VS Code to listen on Private

=> a Static IP or an env variable could be clearly make this simpler my 2 cents

therealkenc commented 4 years ago

I haven't used PHP-fpm, but at least with my plugin of choice (cpptools) remote development works (to a first order) out of the box with WSL Remote and/or SSH Remote. Is this not the case with PHP? If not I'll burn some cycles and take a look to better grok what you are describing.

must be setup with remote host on IP of host

You don't need an IP address. This is what I have been trying to drive at. Whatever you are setting up configuration-wise surely is able to take a name. Having to choose and setup a static IP somewhere for WSL, and then configure that same static IP somewhere else like your PHP environment configuration thingy (probably lots of somewhere else-else too) is at least one configuration step too many. That configuration field could instead have hostname wslhost or wslhost.local (or bikeshed your naming preference) and you'd be done.

Someone (at least with their inside voice) is going to say "yeah but once localhost sharing is available in both directions, you'll just use localhost". Which is not wrong, up to a point; but everything that wants to use a popular port on both Windows and WSL, glaringly SSH port 22, makes for an unnecessary configuration headache with having configure and use port 2222 on one side or t'other.

[Worse, SMB port 445 can't be shared on localhost period, because Windows (inexplicably) hogs 445 on 0.0.0.0 with no way I've found to netmask it. Likewise you can't choose a nonstandard port to serve SMB on the WSL side (say 4445) because there is no way on the Windows side to net use with a nonstandard port or convince Explorer to take a smb://hostname:port/path URI. Caveat "that I know of".]

TL;DR This all is solved if a hostname for the WSL IP is available on the Windows side -- whatever that IP address turns out to be, static or otherwise.

compagnon commented 4 years ago

+1 for the need of out-of-the-box hostnames for IP addresses generated inside /etc/hosts with legacy hosts file as an additional option of /etc/wsl.conf Could you propose a standard ? wsl.host wsl.host.local could be the IP to the windows host ( found in /etc/resolv.conf) wsl.debian wsl.ubuntu …. wsl.<distriName> could be the IP for each distribution.(found with ip addr ) At the glance:

-------------------------------------------
|    Win10 : The **WSL Host**             |
|     for several distributions           |
|                                         |
|       wsl.distributionName              |
|        |                                |
|     ---v-----------------               |
|    | WSL distribution1 | ---> wsl.host  |
|     ---------------------               |
|                                         |
-------------------------------------------

PHP specific: PHP's XDebug protocol: DBGP is not SSH out of the box. The server's agent has to connect to the IDE's XDebug listening port. (wsl.host:9000) and this must be setup in the php.ini

+1: Remote WSL is really a must-have for editing PHP files directly inside the WSL

therealkenc commented 4 years ago

/etc/hosts with legacy hosts file

Not (just) /etc/hosts. It would be C:\Windows\System32\Drivers\etc\hosts too. That's assuming the Windows-proper people were amenable to WSL banging on their hosts file.

But I think (?) it can be done all in the container itself with mDNS. I even took a very half-hearted run at it for a few hours in July, but never made the necessary effort to prove the premise.

wsl.<distriName>

Or maybe (f.e.) DESKTOP-BNN97ME.wsl.debian.local or just DESKTOP-BNN97ME.debian.local or DESKTOP-BNN97ME.debian, where DESKTOP-BNN97ME is my Windows hostname. That's if we want to make WSL container visible on the rest of the local segment, firewall rules notwithstanding. The general idea would require some more thought and effort.

OhYee commented 4 years ago

I tried to use a command to set both /etc/hosts and C:/Windows/System32/drivers/etc/hosts

It works for /etc/hosts, but I don't have permission to set C:\Windows\System32\Drivers\etc\hosts (I can use vim to change the file content without sudo, but can not use sed)

I have tried sudo for Windows but it will cause UAC warning.

Any idea to change the C:/Windows/System32/drivers/etc/hosts without UAC warning?


#!/bin/sh
export HOSTIP=$(cat /etc/resolv.conf | grep 'nameserver' | cut -f 2 -d ' ')
export CLIENTIP=$(ip addr show eth0 | grep 'inet ' | cut -f 6 -d ' ' | cut -f 1 -d '/')
echo $HOSTIP
echo $CLIENTIP
echo "<your password>" | sudo -S sed -i "/winhost/c $HOSTIP\twinhost" /etc/hosts 

(Before runing this, add a line with winhost first)

therealkenc commented 4 years ago

Any idea to change the C:/Windows/System32/drivers/etc/hosts without UAC warning?

Without a UAC? Doable but not straightforward, because you're giving a non-privileged user escalation rights to that file.

One way to do it would be a schmancy LocalSystem account service on the Windows side; communicate with that using a RPC mechanism of choice.

[Not strictly related but along the same lines, I wrote a small daemon to proxy pcap here which needs to run as Administrator to work. I never actually made the effort to turn it into a Windows Service, but that step would amount to turning the main() there into service startup entry point. It uses TCP as the transport and rpclib.]

OhYee commented 4 years ago

@therealkenc

Thanks.

I have add the permission of C:/Windows/System32/drivers/etc/hosts to my Windows login account.

And now, I can use vim Ex mode to modify the hosts file.


Maybe somebody need this.

#!/bin/sh
export WINIP=$(cat /etc/resolv.conf | grep 'nameserver' | cut -f 2 -d ' ') 
export WSLIP=$(ip addr show eth0 | grep 'inet ' | cut -f 6 -d ' ' | cut -f 1 -d '/')
echo $WINIP
echo $WSLIP
echo "<Password>" | sudo -S sed -i "/winip/c $WINIP\twinip" /etc/hosts
echo "%s/^.*wslip/$WSLIP\t\twslip/g|wq" | vim -E /mnt/c/Windows/System32/drivers/etc/hosts
therealkenc commented 4 years ago

Yeah; I didn't want to even mention that as an option. Now any program that runs as user you can, without any special rights or trouble, spoof any address (for example, your bank's). Maybe that doesn't matter in your specific workflow. But anyone looking to replicating the approach should be aware of that.

timesnewmen commented 4 years ago

Looks like if WSL2 can boot up with a static IP, it will solve all those kind of issue.... I also found WSL2 is conflict with my VPN when it's getting an ip address of 172.x.x.x. Current I am still using WSL1. I will change to WSL2 if some day it can support static IP.

diqidoq commented 4 years ago

PLEASE note: The shell script is wrong and is not waiting for input in the moment when password is required. Apart from that please also read carefully therealkenc's comment https://github.com/microsoft/WSL/issues/4210#issuecomment-538766423 regarding security.

I do not even know what this wants to do: echo "%s/^.*wslip/$WSLIP\t\twslip/g|wq" | vim -E ? The echo will not work here the way you expect, @OhYee .

And BTW, what about this message in /etc/hosts then? It seems to be autogenerated and will override the mentioned modifications:

This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf

xtremeperf commented 4 years ago

Here's a couple methods I've used to reference the Windows host address from WSL...

Install libnss-myhostname, a plugin for the Name Service Switch. It will always assign a hostname of _gateway that resolves to the current gateway/default route addresses, ordered by their metric. I use it for my X-server DISPLAY variable and it always resolves to the Windows host address, regardless of the current network configuration.

Also, since the Windows host and WSL have the same hostname, you can append a . (dot) to the hostname, which is how you request the hostname for the host closest to the root zone. The name server is running in Windows, so naturally its hostname is closer to the root zone. Windows also adds a $NAME variable to the shell environment when launching WSL, and it's value is the system hostname. So, the Windows host can be reached at ${NAME}. (notice the dot suffix, indicating we want the host closest to the root zone)

fsoikin commented 4 years ago

@xtremeperf which X server do you use?

kangzj commented 4 years ago

Loving WSL 2 from the first day. Yet the random IP is really an issue which sometimes confilicts with my company VPN subnet and I have to reboot the host to walk around.

FabienD commented 4 years ago

Yes, WSL2 is awesome, I'm back under Windows after 15 years of OS X use. The only annoying thing I found for the moment is the dynamic IP of WSL2 VM. I hope it'll be available soon.

luxzg commented 4 years ago

@craigloewen-msft && @benhillis && @therealkenc

Can we get any updates on any of these issues regarding static IPs and/or usage of DefaultSwitch? Thanks!

jovton commented 4 years ago

I need to join the WSL2 instance to an AD domain. Correct me if I'm wrong, but as far as I can tell this would require greater control over the WSL2 network interface and IP configuration than we currently have, won't it?

tabarnakos commented 4 years ago

What are we trying to solve ? Dynamic IP addresses. Why not use similar idea like DynDNS services?

Here is what I am thinking:

  1. WSL boots up
  2. From within WSL, add a script at the end of the init process to:
    1. Figure out its own IP address
    2. Tell the host system

For that last point, there are multiple options:

I'm not a huge fan of the whole service idea, but having an extra init script in WSL itself could resolve the problem with most flexibility, and with least side effects.

bytemain commented 4 years ago

What are we trying to solve ? Dynamic IP addresses. Why not use similar idea like DynDNS services?

Here is what I am thinking:

  1. WSL boots up
  2. From within WSL, add a script at the end of the init process to:

    1. Figure out its own IP address
    2. Tell the host system

For that last point, there are multiple options:

  • using the gateway IP, send the new dynamic IP to a process on the host
  • directly call an .exe on the host to update the IP address (my preferred option)

I'm not a huge fan of the whole service idea, but having an extra init script in WSL itself could resolve the problem with most flexibility, and with least side effects.

I mod the https://github.com/microsoft/WSL/issues/4150#issuecomment-504209723 script to update my hosts:
https://github.com/lengthmin/dotfiles/blob/master/windows/wsl2.ps1
save as wsl2.ps1 on your computer.

the line2 and line3 is the domain you wanted. and create an task scheduler on Hyper-V create a WSL switch.

How To:

  1. Launch Event Viewer Hit Start, type “Event Viewer” into the search box, and then click the result. You can refer to this: http://techgenix.com/attaching-tasks-event-viewer-logs-events/

  2. Select System in the left panel, select Windows Logs -> System

  3. find events which source is Hyper-V-VmSwith

  4. find the event which is "create switch" click each entry of step 3, find the message is : Port xxxxx successfully created on switch xxxx (Friendly Name: WSL)

  5. right click the entry and then click the "Attach Task To This Event..."

  6. click next, in the action tab, select Start a program, input the program: powershell, the argument is the wsl2.ps1, and select next, finish.

  7. Go to search, search for task scheduler. Select the Event Viewer Tasks, and right click your task just created, select properties, In the "General" tab, Select "Run with highest privileges". You can refer to this: https://superuser.com/questions/770420/schedule-a-task-with-admin-privileges-without-a-user-prompt-in-windows-7

ghost commented 4 years ago

Does somebody know how many topics are about this issue? And are you going to give a solution?

That's the big difference with OpenSource, i'd resolve this in 5min.

kangzj commented 4 years ago

so frustrating.. the localhost still doesn't work all the time