WSL2 で起動したサーバに Windows 側の localhost でアクセスできない
WSL2 のサーバに localhost で繋がらないときは、wsl --terminate でディストリを再起動すると直ることが多い。
0.0.0.0 へのバインドが要るのは WSL2 の IP や LAN から繋ぐときで、localhost なら不要だ。
公開: 更新:
wsl --version … MSRDC バージョン: 1.2.6353 Direct3D バージョン: 1.611.1-81528511 DXCore バージョン: 10.0.26100.1-240331-1435.ge-release Windows バージョン: 10.0.26200.9550
2026-09-26 に local host (Windows 11 Home, Docker 29.8.0)(Node.js 22.14.0 / npm 10.9.2) で実際に打って取った出力。検証環境の詳細
要約
WSL2 は既定で NAT ベースのネットワーク構成を取るが、Windows 上のブラウザなどから WSL2 内のサーバへは localhost でアクセスできるのが正常な状態である。
この localhost 転送はアプリの待ち受けアドレスに関係なく届く。
WSL2 内で 127.0.0.1 にだけバインドしたサーバでも、Windows 側からは localhost で到達できる。
つまり「localhost で繋がらない」ときにバインド先を 0.0.0.0 へ広げても効かないことが多く、先に疑うのは転送の不調やポートの取り合いである。
0.0.0.0 へのバインドが要るのは、localhost ではなく WSL2 の IP(172.x.x.x など)や LAN の別端末から繋ぐとき。
公式ドキュメントで 0.0.0.0 を勧めているのも「Connecting via remote IP addresses(新しいタブで開く)」の節であり、localhost の話ではない。
実行例
NAT モードの WSL2 で同じサーバを 127.0.0.1 と 0.0.0.0 の 2 通りで待ち受けさせると、Windows 側から localhost で叩いた場合はどちらも 200 が返り、WSL2 の実 IP で叩いた場合だけ 127.0.0.1 で待ち受けた方が 000 になって届かなかった。
$ wsl --version
WSL バージョン: 2.6.3.0
カーネル バージョン: 6.6.87.2-1
WSLg バージョン: 1.0.71
MSRDC バージョン: 1.2.6353
Direct3D バージョン: 1.611.1-81528511
DXCore バージョン: 10.0.26100.1-240331-1435.ge-release
Windows バージョン: 10.0.26200.9550$ wslinfo --networking-mode
nat$ nohup python3 -m http.server 18080 --bind 127.0.0.1 > /tmp/s1.log 2>&1 &$ nohup python3 -m http.server 18081 --bind 0.0.0.0 > /tmp/s2.log 2>&1 &$ ss -ltn | grep -E ':1808[01]'
LISTEN 0 5 0.0.0.0:18081 0.0.0.0:*
LISTEN 0 5 127.0.0.1:18080 0.0.0.0:*$ curl.exe -s -o NUL -w "%{http_code}\n" --max-time 5 http://localhost:18080/
200$ curl.exe -s -o NUL -w "%{http_code}\n" --max-time 5 http://localhost:18081/
200$ wsl -d Ubuntu hostname -I
172.17.238.163$ curl.exe -s -o NUL -w "%{http_code}\n" --max-time 5 http://172.17.238.163:18080/
000$ curl.exe -s -o NUL -w "%{http_code}\n" --max-time 5 http://172.17.238.163:18081/
200— 2026-09-26 時点の出力
検証環境Node.js 22.14.0 / npm 10.9.2 / Git 2.48.1.windows.1 / 2026-09-26 検証(ほか 1 件)
- 検証日
- 実行環境
local host (Windows 11 Home, Docker 29.8.0)- バージョン
- Node.js 22.14.0
- npm 10.9.2
- Git 2.48.1.windows.1
- Docker 29.8.0
この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。
解決策
1. ディストリを再起動する
wsl --terminate UbuntuPowerShell から実行し、該当ディストリを立ち上げ直す。
転送の不調はこれで戻ることが多い。
wsl --shutdown でも直るが、こちらはすべてのディストリと WSL2 の仮想マシンごと落とす。
Docker Desktop のように WSL を土台にしているアプリがあると巻き添えで止まるため、まずは --terminate で対象を絞る。
2. WSL2 側の IP へ直接繋いで切り分ける
wsl.exe hostname -I表示された IP へブラウザから繋げるなら、サーバ自体は動いており localhost 転送側の問題だと分かる。
大文字の -I を使う点に注意する。
ここで繋がらない場合は、サーバが 127.0.0.1 だけを待ち受けている可能性が高い。
次の項目へ進む。
3. 実 IP・LAN から繋ぐなら待ち受けアドレスを広げる
# Flask の例
flask run --host=0.0.0.0WSL2 の IP 経由の接続は LAN からの接続として扱われるため、127.0.0.1 ではなく 0.0.0.0 にバインドする必要がある(公式ドキュメント(新しいタブで開く))。
LAN へ開くことになるので、セキュリティは意識しておく。
localhost で繋ぎたいだけならこの変更は要らない。 localhost 転送は 127.0.0.1 だけを待ち受けているサーバにも届く。
4. LAN の別端末から使うなら転送を設定する
netsh interface portproxy add v4tov4 listenport=4000 listenaddress=0.0.0.0 connectport=4000 connectaddress=(wsl hostname -I)Windows 側のポートで待ち受け、WSL2 の IP へ中継する。
WSL2 の IP は再起動で変わりうるため、恒久運用ならミラーモードの利用も検討する。
5. ミラーモードを使う場合
Windows 11 22H2 以降では .wslconfig の [wsl2] に networkingMode=mirrored を書くとネットワーク構成が変わり、Linux 側から Windows のサーバへ 127.0.0.1 で繋げるようになる。
ただし IPv6 の ::1 は対象外である。
よくある原因
- 転送の不調: WSL2 の localhost 転送が一時的に効かなくなっている。
- ポートの取り合い: Windows 側の別プロセスが同じポートを先に押さえていると、転送が入り込めない。
- 実 IP・LAN からのアクセス: WSL2 は独自 IP を持つ仮想アダプタを使う。
この経路は LAN からの接続として扱われるため、127.0.0.1だけを待ち受けているサーバには届かない。 - ミラーモード:
networkingMode=mirroredを有効にすると構成そのものが変わる。