How can I have a Windows program listening for connections coming from WSL without binding to 0.0.0.0?

Viewed 366

A native service needs to be reachable from stuff running in WSL (or other Windows processes) but not from the outside world.

I see that WSL sets up a virtual interface, but it's not clear if it has a fixed IP or what should I do to discover it, because I need this to reasonably work in a standard way regardless of the machine on which everything is installed.

2 Answers

Could be a bit problematic, depending on the exact use-case. You are running into kind of a reverse situation of this answer I did a while back. The options are similar, but not identical, to that use case:

Option 1: WSL1

The easiest method I can think of is to simply use WSL1, assuming that you don't need any features of WSL2. WSL1 runs on the actual Windows NIC, so if you bind the Windows service to 127.0.0.1 (and, if needed, ::1) then anything running in WSL1 will be able to see it, and the Windows service will accept connections from WSL1 processes as if they were from the Windows localhost.


Option 2: WSL2 with Windows service binding to two addresses

For WSL2, you would need the Windows service to listen on both 127.0.0.1, of course, for the Windows processes, and the address of the vNIC provided by WSL/Hyper-V:

> ipconfig.exe /all
...
Ethernet adapter vEthernet (WSL):

   Connection-specific DNS Suffix  . :
   Description . . . . . . . . . . . : Hyper-V Virtual Ethernet Adapter
   ...
   IPv4 Address. . . . . . . . . . . : 172.18.48.1(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.240.0
   ...

Unfortunately that address changes on reboot, so you'll need some way to retrieve it and pass it to the Windows service via config or startup. It can be obtained from within WSL via:

ip route | head -1 | cut -d" " -f3

But this may violate your "need it to operate the same way" rule.

This also, of course, assumes that you can bind the service to two different addresses.


Possible option 3: socat between WSL2 and WSL1

If you look at my Super User answer, you'll see a method to connect a WSL2 instance with a WSL1 instance. The flow here is reversed, since in your case the connection needs to be made from the WSL2 instance to the Windows host. Unfortunately, I'll have to leave the modification of the socat command-line to you for the moment, if you want to pursue that route.

In the end, it's best to bind on 0.0.0.0 add rely on the firewall to limit access to the service.

This is less secure and desirable but it's the only practical option as of Oct. 2021.

By default external connections are denied. The following rule allows them from the WSL interface.

New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow

To connect to this IP, one still needs to discover it from inside the WSL machine by inspecting the active nameserver configuration.

Pretty bad design choices from Microsoft all around, most virtual machines do this without this much of an headache.

Related