What's?
WSLのネットワークに関するドキュメントを読んでみるのと、簡単に確認してみます。
他にもWSLに関して気になることは、こちらにまとめています。
WSLのネットワークに関する話
こちらのドキュメントのことですね。
このあたりが書かれています。
- Windowsから見た時のWSLディストリビューションのIPアドレス
- WSLディストリビューションから見た時のWindowsのIPアドレス
- WSLのネットワークモード
- DNSトンネリング
- プロキシ
- ファイアーウォール
IPアドレスの確認方法は、あとで実際に試してみます。
ネットワークモードは以下の2種類があります。
ネットワークモードは.wslconfigファイルでの設定になります。つまり、ディストリビューション単位には設定できません。
指定できる値はnone、nat、bridged、mirrored、virtioproxyです。
noneにするとWSLはネットワークアクセスができなくなり、bridgedはすでに非推奨です。
virtioproxyについてはドキュメントに説明がありませんでした…。
NAT
ネットワークモードがNATの場合、以下の特徴があります。
- WindowsからWSLディストリビューションのネットワークアプリケーションに
localhostでアクセスできる - WSLディストリビューションからWindowsのネットワークアプリケーションにアクセスするには、Windows側のIPアドレスが必要
注意点としては、ディストリビューション内で0.0.0.0に対してリッスンしてしまうとLAN内からアクセスできるようになってしまう点ですね。
ミラーモード
ネットワークモードがミラーの場合、以下の特徴があります。
- WSLディストリビューションからWindowsのネットワークアプリケーションに
localhostでアクセスできる- IPv6アドレス(
::1)は未サポート
- IPv6アドレス(
- VPNネットワークの互換性向上
- マルチキャストのサポート
- LANからWSLディストリビューションに直接接続可能
自動プロキシ
WSLはデフォルトでWindowsのプロキシ設定を引き継ぎます。
この.wslconfigのautoProxyで設定します。
ファイアーウォール
WSLではHyper-Vファイアーウォールが既定で有効です。
Hyper-Vファイアーウォールについてはこちら。
環境
今回の環境はこちらです。
PS > 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.7623
WSLのディストリビューションはUbuntu Linux 24.04 LTSを使います。
PS > wsl --install Ubuntu-24.04
ネットワークモードごとの動作を確認してみる
それでは、ネットワークモードごとの動作を確認してみます。
共通の話として、WSLディストリビューションのIPアドレスを確認してみます。
PS > wsl -d Ubuntu-24.04 hostname -i
127.0.1.1
…これはちょっと違いますね。
こんな感じでしょうか。
PS > wsl -d Ubuntu-24.04 bash -c "ip a show eth0 | grep 'inet '"
inet 172.24.91.193/20 brd 172.24.95.255 scope global eth0
WSLディストリビューション側からWindowsのIPアドレスを確認してみます。
PS > wsl -d Ubuntu-24.04
$ ip route show | grep -i default | awk '{ print $3 }'
172.24.80.1
このIPアドレスはなにかというと、WSLのネットワークアダプタのことのようです。
PS > ipconfig
Windows IP Configuration
Ethernet adapter Ethernet:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::6dc2:2cae:93d0:2af4%11
IPv4 Address. . . . . . . . . . . : 192.168.79.15
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . :
Ethernet adapter Ethernet 2:
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::86b8:d672:b21f:2462%7
IPv4 Address. . . . . . . . . . . : 192.168.121.120
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.121.1
Ethernet adapter vEthernet (WSL (Hyper-V firewall)):
Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::ba36:453f:de4f:b81e%31
IPv4 Address. . . . . . . . . . . : 172.24.80.1
Subnet Mask . . . . . . . . . . . : 255.255.240.0
Default Gateway . . . . . . . . . :
NAT
まずはNATの確認。
WSLディストリビューション側で、ローカルアドレスのみにバインドしたHTTPサーバを起動してみます。
$ python3 -m http.server --bind 127.0.0.1
Windows側からlocalhost向けにアクセス。
PS > Invoke-WebRequest -Method HEAD http://localhost:8000
StatusCode : 200
StatusDescription : OK
Content :
RawContent : HTTP/1.0 200 OK
Content-Length: 2172
Content-Type: text/html; charset=utf-8
Date: Sun, 01 Feb 2026 14:44:47 GMT
Server: SimpleHTTP/0.6 Python/3.12.3
Forms : {}
Headers : {[Content-Length, 2172], [Content-Type, text/html; charset=utf-8], [Date, Sun, 01 Feb 2026 14:44:47 GMT], [Server, SimpleHTTP/0.6 Python/3.12.3]}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : System.__ComObject
RawContentLength : 0
なるほど、アクセスできました。
すべてのアドレスにバインドしても、Windowsから見た時の結果は同じです。
$ python3 -m http.server
こうすると、LAN内からは見えてしまうようですが…?
今度はWSLディストリビューション側からアクセスしてみましょう。
Windows側にHTTPサーバを立ててみます。
PS > python -m http.server 18000
WSLディストリビューション側からアクセスできました。
$ curl -I $(ip route show | grep -i default | awk '{ print $3 }'):18000
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.13.11
Date: Sun, 01 Feb 2026 14:50:13 GMT
Content-type: text/html; charset=utf-8
Content-Length: 2172
ちなみに、localhostではつながりません。
$ curl -I localhost:18000
curl: (7) Failed to connect to localhost port 18000 after 0 ms: Couldn't connect to server
またWindows側でローカルアドレスのみにバインドすると
PS > python -m http.server -b 127.0.0.1 18000
WSLディストリビューション側から見ると、応答が返ってこなくなります。
$ curl -I $(ip route show | grep -i default | awk '{ print $3 }'):18000
ミラー
今度はミラーモードを試してみます。
1度WSLを停止。
PS > wsl --shutdown
ミラーモードに変更するには、.wslconfigに設定する必要があるようですが、デフォルトではファイルがありません。
C:\Users\<UserName>\.wslconfigに作ればよいみたいです。
こんな感じでしょうか。
[wsl2]
networkingMode=mirrored
再度WSLディストリビューションを起動。
PS > wsl -d Ubuntu-24.04
Windows側にHTTPサーバを立ててみます。
PS > python -m http.server 18000
WSL側からlocalhostでアクセスしてみます。
$ curl -I localhost:18000
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.13.11
Date: Sun, 01 Feb 2026 14:57:30 GMT
Content-type: text/html; charset=utf-8
Content-Length: 2217
つながるようになりました。これがNATとの違いですね。
WSLディストリビューション側でローカルアドレスにバインドしたHTTPサーバにも
$ python3 -m http.server --bind 127.0.0.1
Windows側からlocalhostで依然として接続できます。
PS > Invoke-WebRequest -Method HEAD http://localhost:8000
StatusCode : 200
StatusDescription : OK
Content :
RawContent : HTTP/1.0 200 OK
Content-Length: 2217
Content-Type: text/html; charset=utf-8
Date: Sun, 01 Feb 2026 14:59:23 GMT
Server: SimpleHTTP/0.6 Python/3.12.3
Forms : {}
Headers : {[Content-Length, 2217], [Content-Type, text/html; charset=utf-8], [Date, Sun, 01 Feb 2026 14:59:23 GMT], [Server, SimpleHTTP/0.6 Python/3.12.3]}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : System.__ComObject
RawContentLength : 0
ただ、初回はやたら遅かったですが。
ちょっと気になること
NATで複数のWSLディストリビューションが同じポートをリッスンすると?
Windowsから見てlocalhostでWSLディストリビューションにアクセスできました。
こうなると、複数のWSLディストリビューションが同じポートでネットワークアプリケーションを公開しているとどうなるのでしょう。
ひとつWSLディストリビューションを追加して試してみます。ネットワークのモードはNATに戻しました。
PS > wsl --install AlmaLinux-9
## Ubuntu Linux 24.04
$ echo 'Hello, Ubuntu Linux' > hello.txt
$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
## AlmaLinux 9
$ echo 'Hello, AlmaLinux' > hello.txt
$ python3 -m http.server
Traceback (most recent call last):
File "/usr/lib64/python3.9/runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib64/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/usr/lib64/python3.9/http/server.py", line 1308, in <module>
test(
File "/usr/lib64/python3.9/http/server.py", line 1259, in test
with ServerClass(addr, HandlerClass) as httpd:
File "/usr/lib64/python3.9/socketserver.py", line 452, in __init__
self.server_bind()
File "/usr/lib64/python3.9/http/server.py", line 1302, in server_bind
return super().server_bind()
File "/usr/lib64/python3.9/http/server.py", line 137, in server_bind
socketserver.TCPServer.server_bind(self)
File "/usr/lib64/python3.9/socketserver.py", line 466, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use
なんと後から起動した方はポートが競合しました。
ssコマンドで見ると、他のディストリビューションが使っているポートが見えています。
$ ss -tnl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 4096 127.0.0.54:53 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 5 0.0.0.0:8000 0.0.0.0:*
LISTEN 0 1000 10.255.255.254:53 0.0.0.0:*
面白いですね?
では、こうするとどうでしょう。
## Ubuntu Linux 24.04
$ python3 -m http.server -b 172.24.91.193
## AlmaLinux 9
$ python3 -m http.server -b 127.0.0.1
これならリッスンできました。
Windowsからアクセスしてみます。
PS > Invoke-WebRequest http://localhost:8000/hello.txt
StatusCode : 200
StatusDescription : OK
Content : Hello, AlmaLinux
RawContent : HTTP/1.0 200 OK
Content-Length: 17
Content-Type: text/plain
Date: Sun, 01 Feb 2026 15:10:00 GMT
Last-Modified: Sun, 01 Feb 2026 15:04:50 GMT
Server: SimpleHTTP/0.6 Python/3.9.23
Hello, AlmaLin...
Forms : {}
Headers : {[Content-Length, 17], [Content-Type, text/plain], [Date, Sun, 01 Feb 2026 15:10:00 GMT], [Last-Modified, Sun, 01 Feb 2026 15:04:50 GMT]...}
Images : {}
InputFields : {}
Links : {}
ParsedHtml : System.__ComObject
RawContentLength : 17
どちらの結果が返ってくるのだろうと思いましたが、ローカルアドレスにバインドした方が返ってきました。
WSLディストリビューション側で動作しているネットワークアプリケーションにWindowsからアクセスしようと思うと、WSLディストリビューションは0.0.0.0かローカルアドレスにバインドする必要があるようです。
ちなみに、Windows側で同じポートにバインドしてもなにも問題なかったです。
PS > python -m http.server 8000
NATならこうなりますよね。
ミラーモードでWindows側と同じポートを使うと?
ミラーモードで、WSLディストリビューションとWindowsで同じポートを使うとどうなるのでしょう?
再びミラーモードにしてみます。
[wsl2]
networkingMode=mirrored
Windows側でHTTPサーバを起動。
PS > python -m http.server 8000
WSLディストリビューション側でも同じポートを使って起動しようとすると、失敗しました。
$ python3 -m http.server
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/usr/lib/python3.12/http/server.py", line 1314, in <module>
test(
File "/usr/lib/python3.12/http/server.py", line 1261, in test
with ServerClass(addr, HandlerClass) as httpd:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/socketserver.py", line 457, in __init__
self.server_bind()
File "/usr/lib/python3.12/http/server.py", line 1308, in server_bind
return super().server_bind()
^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.12/http/server.py", line 136, in server_bind
socketserver.TCPServer.server_bind(self)
File "/usr/lib/python3.12/socketserver.py", line 473, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use
やっぱりこうなりますよね。