host.wsl.internal or use the host’s IP address assigned to the WSL virtual network adapter. Unlike previous versions of WSL, WSL2 runs in a lightweight utility VM with its own NAT network, meaning it cannot reach localhost directly. This guide explains how to identify the correct endpoint and configure your application to connect successfully.
Understanding WSL2 Networking Architecture
The fundamental difference between WSL1 and WSL2 lies in their networking models. WSL1 operated as a translation layer directly on top of the Windows kernel, allowing direct access to localhost. In contrast, WSL2 utilizes a full Linux kernel inside a Hyper-V utility VM. This VM is isolated by default, which means that when you start a web server on port 8080 in Windows, it binds to the Windows loopback interface. The WSL2 environment sees this as a separate machine on a private network.
Consequently, attempting to curl http://localhost:8080 from inside WSL2 will fail because there is no service listening on the WSL2 instance's own localhost. You need to route traffic from the WSL2 VM back to the host machine. Microsoft has provided specific mechanisms to handle this routing without requiring complex manual firewall rules for every single port.
Method 1: Using the Special DNS Name (Recommended)
The most robust and future-proof method introduced in recent updates to WSL2 is using the special DNS name host.wsl.internal. This hostname resolves automatically to the IP address of the host machine from within the WSL2 environment. It handles cases where the host IP might change dynamically due to network adapters being enabled or disabled.
- Start your HTTP server on Windows: Ensure your application is bound to
0.0.0.0or127.0.0.1on Windows. For example, if using Python’s built-in server:python -m http.server 8080 --bind 0.0.0.0 - Test connectivity from WSL2: Open your WSL2 terminal and run a request to the special hostname.
curl http://host.wsl.internal:8080 - Update your application configuration: Modify any client-side code or browser shortcuts to point to
http://host.wsl.internal:8080instead oflocalhost.
This method eliminates the need to constantly query for IP addresses. If you find that host.wsl.internal does not resolve, ensure your WSL2 version is up to date by running wsl --update in PowerShell. This approach is significantly more reliable than hardcoding IP addresses, which can break after a reboot or network switch.
Method 2: Using the Host IP Address
If you are using an older version of WSL2 or require explicit IP control, you can determine the IP address of the host machine from the perspective of the WSL2 instance. This IP is part of the virtual network created by the Hyper-V switch.
- Identify the gateway IP: Run the following command in your WSL2 terminal:
ip route show default - Extract the IP: The output will look something like
default via 172.x.x.x dev eth0. The number afterviais the IP address of your Windows host machine on the WSL2 virtual network. - Connect using the IP: Use this IP in your requests.
curl http://172.x.x.x:8080
Note that this IP address may change if you disconnect and reconnect Wi-Fi or Ethernet adapters. Therefore, while this method works, it requires more maintenance than the DNS-based approach. For persistent connections, consider setting up a static DHCP reservation for the WSL VM in your router, though this is often overkill for development environments.
Handling Firewall and Binding Issues
Even with correct addressing, you might encounter connection timeouts. This is usually due to how the server is bound on the Windows side. If your server only binds to 127.0.0.1, it listens exclusively on the loopback interface. While host.wsl.internal routes through the virtual network, some strict configurations might block cross-boundary traffic depending on Windows Defender Firewall profiles.
To ensure maximum compatibility, bind your server to 0.0.0.0 on Windows. This tells the OS to listen on all available network interfaces, including the virtual Ethernet adapter used by WSL2. Additionally, verify that your Windows Firewall allows inbound connections on the specific port. You can test this by temporarily disabling the firewall or creating an inbound rule for port 8080.
For deeper insights into network diagnostics within WSL, you might also want to check how to ping your WSL2 Ubuntu instance from the Windows host to verify bidirectional connectivity. See our guide on How to Ping WSL2 Ubuntu from Windows Host for complementary troubleshooting steps.
Troubleshooting Common Errors
If you receive a "Connection Refused" error, the server is likely not running or is bound to the wrong interface. A "Timeout" error suggests a firewall block or incorrect IP/DNS resolution. Always verify the server status on Windows first by accessing http://localhost:8080 in a native Windows browser. If it works there but not in WSL2, the issue is strictly network routing.
Another common pitfall involves Docker containers. If you are running a containerized app on Windows and trying to access it from WSL2, remember that Docker Desktop often uses a different virtual network bridge. In such cases, you may need to use host.docker.internal instead of host.wsl.internal depending on how Docker is configured to expose ports.
Frequently Asked Questions
Why doesn't localhost work in WSL2?
WSL2 runs in a lightweight utility VM with its own network stack, isolated from the Windows host via NAT. Localhost refers to the loopback interface of the current machine, so localhost in WSL2 points to the WSL2 VM itself, not your Windows PC. You must explicitly route to the host's network address.
What is the best way to access local services from WSL2?
The recommended approach is using the DNS name host.wsl.internal. It automatically resolves to the correct host IP address regardless of network changes, providing a stable and maintainable solution compared to manually tracking IP addresses.
Can I forward ports from WSL2 to Windows?
Yes, you can use netsh interface portproxy in Windows PowerShell to forward incoming connections on a Windows port to the WSL2 IP address. However, this is generally unnecessary for development workflows since host.wsl.internal allows direct outbound access from WSL2 to Windows without reverse proxying.
Why am I getting a timeout even with the correct IP?
This is typically caused by Windows Defender Firewall blocking inbound traffic on the specific port. Ensure your application is bound to 0.0.0.0 and create an inbound firewall rule for the port you are using, allowing connections from private networks.
Does this work for database connections too?
Absolutely. Whether you are connecting to MySQL, PostgreSQL, or Redis running on Windows, you can replace localhost with host.wsl.internal in your connection strings. Just ensure the database service is configured to accept remote connections and is not restricted to local-only access.