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:
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'
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.