23

The issue with my WSL is the following my WSL can't make a cURL request anywhere under localhost. For this example, I have created a page that returns hello world.

My cURL looks like this (note that the response is the same even with http://)

curl -vvv localhost:80/hello_world.html

and the response is the following

*   Trying 127.0.0.1...
* TCP_NODELAY set
* connect to 127.0.0.1 port 80 failed: Connection refused
* Failed to connect to localhost port 80: Connection refused
* Closing connection 0
curl: (7) Failed to connect to localhost port 80: Connection refused

Now if I run the following cURL on Powershell:

curl  http://localhost:80/hello_world.html

The response I get is

StatusCode        : 200
StatusDescription : OK
Content           : <h1> Hello World </h1>
RawContent        : HTTP/1.1 200 OK
                    Keep-Alive: timeout=5, max=100
                    Connection: Keep-Alive
                    Accept-Ranges: bytes
                    Content-Length: 22
                    Content-Type: text/html
                    Date: Mon, 24 Feb 2020 09:52:20 GMT
                    ETag: "16-59f4f46118cab...
Forms             : {}
Headers           : {[Keep-Alive, timeout=5, max=100], [Connection, Keep-Alive], [Accept-Ranges, bytes], [Content-Length, 22]...}    Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : System.__ComObject
RawContentLength  : 22

which returns the actual hello world and not the error message i get on WSL

eg curl: (7) Failed to connect to localhost port 80: Connection refused


Edit: The server runs in windows 10 machine and the curl also in the same windows 10 machine. Also, the windows are on Insider version 19569.100

Update: I checked out this Microsoft article that @Anaksunaman shared in the comments and followed the step that says to cat /etc/resolv.conf then from there I got my IP and tried the curl with my IP from resolv.conf and it worked but still with localhost doesn't seem to work also in the article it says

Depending on which version of Windows you're using, you might need to retrieve the IP address of the virtual machine. If your build is 18945 or higher, you can use localhost just like normal.

My build is higher than 18945 as I'm a windows insider user. Is there any way that I can map my IP (EG 111.222.333.444) to localhost? so when I do a CURL to localhost the curl actually uses the IP 111.222.333.444?

8
  • To clarify, is the server running under Windows and the plain curl command under WSL? Feb 24, 2020 at 12:15
  • They are all on the same windows pc both application and wsl Feb 25, 2020 at 8:36
  • At a guess, it's possible that this issue is due to WSL. It's a little old but see this Microsoft article. It's also probably worth mentioning that curl has up-to-date native Windows builds you can test with that don't rely on WSL. Otherwise, you may want to check your server software and firewalls to ensure none of those is blocking curl's access to your server. Feb 25, 2020 at 9:08
  • That said, if you still run into problems, it might be good to edit your question and detail the exact steps and software (including relevant config files) you are using, which could help resolve any non-obvious issues. Feb 25, 2020 at 9:12
  • Okay, thank you I'm going to check it. Also, note that the server is a simple apache2 and right now I have disabled some parts of the firewall in order to ping my public IP and this works. (Eg curl -vvv localhost:80/hello_world.html doesn't work but curl -vvv 111.222.333.4444:80/hello_world.html works.) (the IPs are fake only for this example) Feb 25, 2020 at 9:13

2 Answers 2

23

Updated 2023-12-27

This should be addressed now with the mirrored networking mode and recent patches. Definitely follow the instructions from 2023-10-31 and avoid rolling back to WSL1 if possible since it's largely unpatched now and will likely continue to degrade.

If you already downgraded to WSL1 and want to patch up to WSL2, you'll want to follow a standard upgrade guide (to the Microsoft Store variant ideally) with the special step of removing the existing WSL2 VHDX file in the corresponding directory for your WSL1 image first.

That VHDX file has not been updated since you downgraded and will actively block the upgrade despite the upgrade process giving no indication of an issue (it'll just hang interminably). Also ensure you have plenty of disk space - the upgrade will copy all content from the WSL1 structure into the VHDX, effectively doubling its footprint during the migration, and running out of space will also cause a full hang in the upgrade process without notification.

Updated 2023-10-31

Microsoft is fixing this! The following issues are being resolved with a new feature that's available on preview but appears might roll out to regular update paths in the near future:

https://github.com/microsoft/WSL/issues/4619 https://github.com/microsoft/WSL/issues/5211

Quoting @dons20 on the second thread with special thanks:

  1. Update Windows to at least the October 10th build. See more info here: [WSL 2] WSL 2 cannot access windows service via localhost:port #4619 (comment)
  2. Update your WSL to the latest pre-release by running this in CMD or Powershell wsl --update; wsl --update --pre-release. You can view the changes of the pre-release versions here: https://github.com/microsoft/WSL/releases
  3. Update (or create) your .wslconfig file which is located at %USERPROFILE% in explorer. Add the following:
[wsl2]
networkingMode=mirrored # add this line if file already exists
  1. (Optional) Shutdown and restart your WSL (after a few seconds) so that the config changes apply.

Original

I suspect you're actually running WSL2, which handles networking almost entirely differently from how WSL handled it. See this issue on git for a very long breakdown of what's happening and why.

The short answer: it's not going to be easy to get localhost running the way you'd like on WSL2, and I've personally downgraded to WSL (the first version) for the moment until they finally offer a method to do that without both having to map all of your requests to an arbitrary assigned-on-startup IP and opening your Windows firewall rules up to allow public inbound connections on your service port.

If you do want to downgrade and magically have localhost interactions back, just open a Powershell console as admin and enter the following (assuming running an Ubuntu release):

wsl --set-version Ubuntu 1

You'll lose any WSL2 features but regain your sanity. Note that there may be one or two migration tasks to perform on the Ubuntu instance itself.

3
  • 1
    Thanks for the response, this is useful. However I wonder if there is a less terminal response like the one stated here Jul 11, 2020 at 5:22
  • 2
    @ManuelMartinez Yeah, that's what I was referring to with the inbound connections. If you follow that approach, you're no longer using a loopback address and now need to accept inbound connections on your service ports, which is a complete non-starter for many organizations (security and all). Also, fun fact: organization IPs are often unstable, so you'll have the pleasure of getting random networking errors and rewriting your resolv.conf whenever that happens.
    – bsplosion
    Jul 13, 2020 at 13:14
  • 2
    Spent what felt like hours reading through github issues and other posts about this and yours was the first I found that mentioned the possibility of rolling back the WSL version. Worked like a charm, no extra config needed. +1 May 16, 2021 at 6:57
9

A quick workaround is to set an alias to the cmd version of curl and use that from wsl2.

In you ~/.bashrc, set following:

alias curl="cmd.exe /C curl"

After you restart or source .bashrc, you can use curl as usual.

enter image description here

If you need to use it in a bash script, where your aliases is not set, you can use cmd.exe /C curl in the scripts. It is ugly but it works.

3
  • My WSL Debian distro doesn't recognize cmd. I can't find anything on the googles about cmd except for Windows CMD. Any suggestions?
    – gabe
    Jan 15, 2021 at 20:13
  • 3
    Windows shell has a different resolution of executable names than popular Linux shells. Just cmd is not going to be enough as there is no such executable actually. You can get around this with simple alias: alias cmd="cmd.exe /c" Jan 25, 2021 at 17:04
  • Sorry, I indeed have alias cmd='cmd.exe' in my .bashrc. I have changed the answer to use cmd.exe, which is available natively in WSL2.
    – MyrionSC2
    Jun 3, 2022 at 13:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .