2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WSLC (WSL containers) で謎の通信エラーになる問題の対処法

2
Last updated at Posted at 2026-10-01

WSL 3.0.1 で WSLC がGA (一般提供) となりました。

「待ってました!」と、意気揚々と試してみたところ、謎のTLSハンドシェイクエラーにより、コンテナイメージのpullすらできずに撃沈しました。

コンテナイメージpullでTLSエラー発生

このエラーは、Windowsホストはもちろん、WSLCではない通常のWSLディストリビューション環境では発生しません。WSLCだけ発生します。

本稿は、同じようなエラーに遭遇した人のための、トラブルシューティングの記録です。

TL;DR (解決)

詳細を全部省略して、解決策だけ先に書くと、WSLCのネットワークモードを nat に設定することで解決しました。

WSLCの設定は、%USERPROFILE%\AppData\Local\wslc\settings.yaml にyaml形式で定義できます。以下のように設定します。

%USERPROFILE%\AppData\Local\wslc\settings.yaml
session:
  networkingMode: nat

設定内容を反映させるために、wslc system session terminate で一度WSLCセッションを終了させる必要があります。

調査記録

以下は、興味のある人向けの調査記録です。

TLSハンドシェイクの確認

Windowsホストからは、TLSハンドシェイクは成功します。
※レスポンスは401ですが、TLSハンドシェイクの確認が目的なので、期待通りの成功です。

Windowsホスト
PS C:\> curl -ISs https://registry-1.docker.io/v2/
HTTP/1.1 401 Unauthorized
Date: Wed, 30 Sep 2026 10:09:58 GMT
Content-Type: application/json
Content-Length: 87
Connection: keep-alive
docker-distribution-api-version: registry/2.0
www-authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io"
strict-transport-security: max-age=31536000

通常のWSLからも成功です。

WSL
PS C:\> wsl --system --exec curl -ISs https://registry-1.docker.io/v2/
HTTP/2 401
date: Wed, 30 Sep 2026 10:09:31 GMT
content-type: application/json
content-length: 87
docker-distribution-api-version: registry/2.0
www-authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io"
strict-transport-security: max-age=31536000

しかしながら、WSLCからは、以下のエラーとなります。

WSLC
PS C:\> wslc system session run curl -ISs https://registry-1.docker.io/v2/
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the webpage mentioned above.

wslc system session run {シェルコマンド} で、WSLCのコンテナホスト環境で任意のシェルコマンドを実行できます。また、wslc system session shell で対話シェルに入ることもできます。デバッグに役立ちます。

上記エラーの内容としては、サーバー証明書のissuerの証明書、つまりCA証明書が無いので、サーバー証明書の検証に失敗しています。

Issuerを確認します。まずは正常なWSL側で見てみます。IssuerはAmazonであることが確認できます。

WSL
PS C:\> wsl --system --exec sh -c 'openssl s_client -connect registry-1.docker.io:443 -servername registry-1.docker.io -showcerts </dev/null 2>/dev/null | openssl x509 -noout -issuer -subject'
issuer=C=US, O=Amazon, CN=Amazon RSA 2048 M01
subject=CN=*.docker.com

続いて、問題のWSLCです。

WSLC
PS C:\> wslc system session run sh -c 'openssl s_client -connect registry-1.docker.io:443 -servername registry-1.docker.io -showcerts </dev/null 2>/dev/null | openssl x509 -noout -issuer -subject'
issuer=OU=generated by Norton Antivirus for SSL/TLS scanning, O=Norton Web/Mail Shield, CN=Norton Web/Mail Shield Root
subject=CN=*.docker.com

ん? Norton? 貴様の仕業か!!!

これでTLSハンドシェイクエラーの直接的な問題原因は特定できました。ローカルPCにインストールされた、NortonのセキュリティソフトによるTLSインスペクションが原因でした。Nortonが、クライアント (WSLCホスト) とサーバー (コンテナレジストリ) の間に割って入り、WSLCホストに対してNorton自身のサーバー証明書を用いてTLSハンドシェイクをさようとしたが、WSLCホスト側にはNortonの証明書を検証するための設定がされていなかったということです。

なぜWSLでは成功するが、WSLCではエラーになるのか

ネットワークモードの違いが原因

今回頭を悩ませたのが、なぜWSLでは問題ないが、WSLCではエラーになるのか、という点です。

WSLCアーキテクチャを紹介するMicrosoft公式のブログ記事を確認したところ、WSLCでは consomme という新しいネットワークモードをデフォルトで採用していることがわかりました。一方で、従来のWSLのデフォルトネットワークモードは nat です。どうやら、WSLとWSLCのネットワークモードの違いが怪しそうです。

WSLと同じネットワークモードを使うとエラーは解消

WSLCのネットワークモードを、実績のあるWSLと同じ nat に変更して試してみます。WSLC設定ファイルに、以下の設定を行います。

%USERPROFILE%\AppData\Local\wslc\settings.yaml
session:
  networkingMode: nat

設定を反映させるために、一度セッションを終了し再起動します。

PS C:\> wslc system session terminate

そして、コンテナイメージのpullを再トライしたところ、成功しました!

PS C:\> wslc image pull debian:latest  # pull成功!
latest: Pulling from library/debian
6eefb2f5d3e9: Pull complete
Digest: sha256:9cc080028c43b27d2074d63a5f9caf7166d731494965616c1a6d2827a004585c
Status: Downloaded newer image for debian:latest
docker.io/library/debian:latest

コンテナ起動も正常です。

PS C:\> wslc run --rm debian apt-get moo
                 (__)
                 (oo)
           /------\/
          / |    ||
         *  /\---/\
            ~~   ~~
..."Have you mooed today?"...

今回は、NortonによるTLSインスペクション問題を、ネットワークモード設定を変更することで対応しましたが、NortonのルートCA証明書をWSLC側に登録することでも解決できるはずです。しかしながら、WSLCホストだけでなく、WSLCで起動する各コンテナ側にも設定が必要になり、それなりに構成が複雑になるでしょう。

では、consomme モードと nat モードはどう違うのでしょうか?

consomme モード

先述のブログ記事や、WSLドキュメントによれば、Linux (WSLCホスト) 側ではvirtio-netドライバを通じて通信が行われ、Windows側ではユーザープロセスにより通信が中継されます。Windows側では通常のWindowsソケットを用いた普通のアプリケーションと同じような通信として扱われるので、Windowsホスト環境のネットワークポリシーと統合してファイアウォールやVPN等との連携がよりシームレスに行える利点があります。一方で、通常のWindowsアプリケーションと同じように、ローカルPCのセキュリティソフトによる監視の対象にもなりやすくなります。今回、NortonによるTLSインスペクションにより、WSLCによるTLSハンドシェイクがエラーとなったのも、この consomme モードの特徴に起因します。

動作確認

まずは、Linux側のドライバを確認します。ドキュメント通り、virtio-netが使われていることが確認できます。

consomme
PS C:\> wslc system session run sh -c '
>>   for adapter in /sys/class/net/*; do
>>     if [ -e "$adapter/device/driver" ]; then
>>       printf "%s: " "${adapter##*/}"
>>       readlink -f "$adapter/device/driver"
>>     fi
>>   done
>> '
eth0: /sys/bus/virtio/drivers/virtio_net
loopback0: /sys/bus/virtio/drivers/virtio_net

次に、comsomme モードによる通信が、実際にWindowsホスト上でユーザープロセスによって中継されていることを確認します。
※以下では、裏でWSLCホストからコンテナレジストリへのTCP接続を試み、その接続を維持した状態で確認しています。

以下のとおり、Windows側では、WSL関連モジュールをロードする Windowsプロセス (dllhost) がTCP接続を所有していることが確認できます。Windowsソケットを通じて外部との通信が行われることになります。つまり通常のWindowsアプリの通信と同様に、ローカルPCのセキュリティソフトによる監視/検査の対象となりえます。

consomme
PS C:\> Get-NetTCPConnection | ?{ $_.RemoteAddress -eq '3.220.149.94'} | select State,OwningProcess

      State OwningProcess
      ----- -------------
Established         22104

PS C:\> Get-Process -Id 22104 | select ProcessName

ProcessName
-----------
dllhost

PS C:\> Get-Process -Id 22104 -Module | ?{ $_.ModuleName -match 'wsl|consomme' }

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      1780 wsldevicehost.dll                                  C:\Program Files\WSL\wsldevicehost.dll
       128 wsldevicehostproxystub.dll                         C:\Program Files\WSL\wsldevicehostproxystub.dll

nat モード

nat モードでは、consomme と異なりWindowsのユーザープロセスが外部とのTCP接続を作成したりせずに、Linux側からの通信はWindowsカーネルによってアドレス変換され転送されます。

動作確認

natモードに設定を変更し、同じように確認していきます。

natモードでのドライバは、Hyper-Vネットワークドライバーの hv_netvsc が使用されています。

nat
PS C:\> wslc system session run sh -c '
>>   for adapter in /sys/class/net/*; do
>>     if [ -e "$adapter/device/driver" ]; then
>>       printf "%s: " "${adapter##*/}"
>>       readlink -f "$adapter/device/driver"
>>     fi
>>   done
>> '
eth0: /sys/bus/vmbus/drivers/hv_netvsc

次に肝心のWindows側にTCP接続を中継するプロセスがいるかどうかです。以下の通り、該当するWindowsプロセスはいません。

nat
PS C:\> Get-NetTCPConnection | ?{ $_.RemoteAddress -eq '3.220.149.94'} | select State,OwningProcess
PS C:\>

consommeモードとは異なり、ユーザープロセスによるWindowsソケットを用いた通信は行われていません。

比較

確認項目 consomme nat
デフォルト状況 WSLCデフォルト WSLデフォルト
SSLハンドシェイク 証明書検証エラー 成功
仮想NICドライバー virtio_net hv_netvsc
Windowsユーザープロセスによる中継 あり なし
ローカルのNortonによるTLSインスペクション された されなかった

さいごに

WSLでは問題ないが、WSLCでネットワーク関連のエラーが発生する場合、WSLCのネットワークモードを nat に設定することを一度試してみてください。nat は、WSLのデフォルトです。

ただし、WSLCデフォルトの consomme モードの利点が失われるので、適用にあたってはドキュメント等参考にしてください。

参考資料

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?