microsoft / microsoft/WSL

Dual-mode IPv6 sockets do not accept IPv4 connections via localhost

Open
#14,154 2 comments 6 reactions 0 assignees View on GitHub
network
Dominant language
C++
Stars
33.7k
Forks
1.8k
Avg merge
3d 17h
Merged PRs (30d)
116

Description

### Windows Version

Microsoft Windows [Version 10.0.26200.7705]

### WSL Version

2.6.3.0

### Are you using WSL 1 or WSL 2?

- [x] WSL 2
- [ ] WSL 1

### Kernel Version

6.6.87.2-1

### Distro Version

Fedora Linux 43

### Other Software

N/A

### Repro Steps

1. Create a simple HTTP server in Go that listens on :8000 (dual-stack by default)
```golang
// main.go
package main
import "net/http"
func main() { http.ListenAndServe(":8000", nil) }
```
1. Run the server in WSL2
```bash
go run main.go
```
1. From the same WSL2 instance, try to connect via IPv4
```bash
curl http://localhost:8000/ -v -4
```
1. From the same WSL2 instance, try to connect via IPv6
```bash
curl http://localhost:8000/ -v -6
```

### Actual curl output

**IPv4 connection (FAILS):**
```console
$ curl http://localhost:8000/ -v -4
* Host localhost:8000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying 127.0.0.1:8000...
* connect to 127.0.0.1 port 8000 from 127.0.0.1 port 51042 failed: Connection refused
* Failed to connect to localhost port 8000 after 0 ms: Could not connect to server
* closing connection #0
curl: (7) Failed to connect to localhost port 8000 after 0 ms: Could not connect to server
```

**IPv6 connection (WORKS):**
```console
$ curl http://localhost:8000/ -v -6
* Host localhost:8000 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:8000...
* Connected to localhost (::1) port 8000
* using HTTP/1.x
> GET / HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Tue, 03 Feb 2026 14:15:18 GMT
< Content-Length: 19
<
404 page not found
* Connection #0 to host localhost left intact
```

### Expected Behavior

On standard Linux, when an IPv6 socket is created without setting `IPV6_V6ONLY`, it operates in **dual-stack mode** and accepts connections from both IPv4 and IPv6 clients. IPv4 connections are received as IPv4-mapped IPv6 addresses (e.g., `::ffff:127.0.0.1`).

The expected behavior is:
- `127.0.0.1:8080` → Connection succeeds (mapped to `::ffff:127.0.0.1`)
- `[::1]:8080` → Connection succeeds

### Actual Behavior

In WSL2, IPv4 connections to a dual-stack socket listening on `::` are refused, even when connecting from within the same WSL2 instance.

- `curl -4 http://localhost:8000/` → **Connection refused**
- `curl -6 http://localhost:8000/` → Connection succeeds (404 is expected, server is working)

### Additional Context

This issue is related to #4851 (Localhost relay does not support dual-mode sockets), but demonstrates that the problem also occurs **within WSL2 itself** (not just Windows-to-WSL communication).

Go's `net/http` package, when given an address like `:8000`, creates a dual-stack socket listening on `[::]` by default. This is standard behavior that works correctly on native Linux systems. Many applications and frameworks (e.g., Node.js, Python's `http.server`, various web frameworks) use this same pattern to serve both IPv4 and IPv6 clients with a single socket.

### Diagnostic Logs

[WslLogs-2026-02-03_23-34-10.zip](https://github.com/user-attachments/files/25048869/WslLogs-2026-02-03_23-34-10.zip)

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the issue with the main.go server and the curl -4 and curl -6 commands from the report, then review the WSL2 networking path implicated by the diagnostic logs. Done means a socket listening on [::] accepts both 127.0.0.1 and ::1 connections within WSL2, matching the expected dual-stack behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
networking, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.