Docker環境の構築で、ハマった問題の調査結果メモ。
docker image pullなどの、Webアクセス(https)系コマンドがVPN+WSL2環境で失敗する問題。aptとかgit系のコマンドも同様にエラーになる。
VPNソフトがGlobalProtectの場合のみ発生するかもしれない。
残念ながら、結局、解決には至っていない。
ただ、前半の対処だけで解決する環境もあるかもしれないので、記事としては残す。
現象
以下の環境において
- Windows環境にWSL2でLinuxを乗っけて動かしている
- Windows環境はVPN(GlobalProtect)を使用している
例えば、docker image pull が以下のように証明書の検証エラーになる。
$ docker image pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
c1ec31eb5944: Retrying in 1 second
error pulling image configuration: download failed after attempts=6: tls: failed to verify certificate: x509: certificate signed by unknown authority
なお、当該環境はwsl-vpnkitを導入済みで、レイヤ3までは疎通(pingは通る)している。
原因
GlobalProtectというVPN製品のみの仕様かもしれないが、VPN経由のSSL通信におけるサーバ認証に、以下のような動作があるため。
- SSL通信の接続先のサーバ証明書を、まず、VPNのサーバが自身で評価する
- 結果OKなら、当該サーバの証明書のチェインを、本来の中間証明書・ルート証明書へのものから、VPN専用の証明書へのものに置き換えてクライアントに渡す
- クライアントは、VPN専用の証明書(VPNセットアップ時に信頼されたルート証明書として登録)を用いて、接続先のサーバ証明書を評価する
- 結果、OKなら通信を開始する
ここで、WSL上のLinux環境には、このVPN専用の証明書がインストールされていないので、評価に失敗する。
以下はopensslコマンドで、証明書のチェックを行った例。
(「VPNSERVER.com」となっているところに、実際のVPNのサーバの名前が表示される)
$ openssl s_client -connect www.google.com:443
CONNECTED(00000003)
depth=1 CN = VPNSERVER.com
verify error:num=19:self-signed certificate in certificate chain
verify return:1
depth=1 CN = VPNSERVER.com
verify return:1
depth=0 CN = www.google.com
verify return:1
---
Certificate chain
0 s:CN = www.google.com
i:CN = VPNSERVER.com
a:PKEY: id-ecPublicKey, 256 (bit); sigalg: RSA-SHA256
v:NotBefore: Oct 21 08:38:45 2024 GMT; NotAfter: Jan 13 08:38:44 2025 GMT
1 s:CN = VPNSERVER.com
i:CN = VPNSERVER.com
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Dec 22 06:08:43 2021 GMT; NotAfter: Dec 17 06:08:43 2041 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
・
・
---
SSL handshake has read 1802 bytes and written 396 bytes
Verification error: self-signed certificate in certificate chain
---
・
・
回避方法
VPN専用の証明書をLinux側にインストールする。
sudo cp certification_for_VPN.crt /usr/share/ca-certificates/
sudo update-ca-certificates
※「certification_for_VPN.crt」がVPN専用の証明書(事前配布)
これで解決、と思ったのだが、ダメだった…。
さらに発生した問題
前述の対応を行っても以下のエラーになる。
$ docker image pull hello-world
Using default tag: latest
latest: Pulling from library/hello-world
c1ec31eb5944: Retrying in 1 second
error pulling image configuration: download failed after attempts=6: tls: failed to verify certificate: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "VPNSERVER.com")
$ openssl s_client -connect www.google.com:443
CONNECTED(00000003)
depth=1 CN = VPNSERVER.com
verify return:1
depth=0 CN = www.google.com
verify error:num=7:certificate signature failure
verify return:1
depth=0 CN = www.google.com
verify return:1
---
Certificate chain
0 s:CN = www.google.com
i:CN = VPNSERVER.com
a:PKEY: id-ecPublicKey, 256 (bit); sigalg: RSA-SHA256
v:NotBefore: Oct 21 08:38:45 2024 GMT; NotAfter: Jan 13 08:38:44 2025 GMT
1 s:CN = VPNSERVER.com
i:CN = VPNSERVER.com
a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256
v:NotBefore: Dec 22 06:08:43 2021 GMT; NotAfter: Dec 17 06:08:43 2041 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
・
・
---
SSL handshake has read 1801 bytes and written 396 bytes
Verification error: certificate signature failure
---
・
・
エラーは以下で、署名の検証に失敗している。
Verification error: certificate signature failure
実際、前述の openssl s_client -connect
の結果から、VPNサーバから返っているwww.googole.comのサーバ証明書を引っ張り出して(/tmp/test.crt)検証してみると、エラーになる。
$ openssl verify -show_chain -CAfile certification_for_VPN.crt /tmp/test.crt
CN = www.google.com
error 7 at 0 depth lookup: certificate signature failure
error /tmp/test.crt: verification failed
40079451FE7E0000:error:0200008A:rsa routines:RSA_padding_check_PKCS1_type_1:invalid padding:../crypto/rsa/rsa_pk1.c:79:
40079451FE7E0000:error:02000072:rsa routines:rsa_ossl_public_decrypt:padding check failed:../crypto/rsa/rsa_ossl.c:697:
40079451FE7E0000:error:1C880004:Provider routines:rsa_verify:RSA lib:../providers/implementations/signature/rsa_sig.c:774:
40079451FE7E0000:error:06880006:asn1 encoding routines:ASN1_item_verify_ctx:EVP lib:../crypto/asn1/a_verify.c:217:
ここから先は追いきれなかったが、以下あたりを読む感じ、VPNサーバが動的に発行するサーバ証明書 or VPN専用の証明書に、何らかの不備があるように見える。
なぜかSHA1を利用すると次のようなエラーでopensslによる署名検証が失敗してしまうので、SHA256で代替した
こうなるとVPNサーバ・環境の問題なので、こちらからは手が出せない。
残念ながら、ここでギブアップ。畜生。
その他
私の環境では該当しなかったが、類似の問題が以下で直るパターンはありそう。
とりあえずメモ。
- ネットワークのMTU調整
- WSL2のミラーモードを使用