企業プロキシ環境でGitがSSLエラーになる理由と対処法
会社のパソコンで git clone を実行したら、こんなエラーで止まった——という経験はないでしょうか。
fatal: unable to access '...': SSL certificate problem: self signed certificate in certificate chain
fatal: unable to access '...': SSL certificate problem: unable to get local issuer certificate
server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt
ブラウザではGitHubもGitLabも普通に開けるのに、Gitコマンドだけが通らない。
検索すると git config --global http.sslVerify false という解決策がすぐ見つかります。ただし、それは「エラーを消す」のではなく「証明書の検証をやめる」設定です。
この記事では、なぜこのエラーが起きるのかと、検証を維持したまま解決する方法を整理します。
原因:企業ネットワークのSSLインスペクション
多くの企業では、セキュリティ機器がHTTPS通信をいったん復号して検査し、企業自身が発行した証明書で暗号化し直してクライアントに渡しています。
この仕組みをSSLインスペクションと呼びます(詳しくは SSLインスペクションとは?企業ネットワークで証明書エラーが起きる仕組み)。
そのため、Gitから見るとGitHubの本物の証明書ではなく、会社が発行した見慣れない証明書が返ってきます。「発行元をたどれない」=unable to get local issuer certificate というエラーは、そのまま起きている事実を表しています。このエラーが出る仕組みそのものは 証明書チェーンとは?中間証明書が欠けるとエラーになる理由 にまとめています。
ブラウザで平気なのはなぜか
企業のPCには、あらかじめ会社のCA証明書がWindowsの証明書ストアに登録されています。ブラウザはそこを見るため、エラーになりません。
問題は、ツールがどこを見るかです。
Gitには2つの証明書バックエンドがある
ここがGit特有の、そして解決の鍵になる部分です。Windows版のGitは証明書の検証方式を選べます。
公式ドキュメントには、こう記載されています。
http.sslBackend
「Name of the SSL backend to use (e.g. “openssl” or “schannel”).」
(使用するSSLバックエンドの名前。例:openssl または schannel)
| バックエンド | 参照する証明書 | 企業環境での相性 |
|---|---|---|
| openssl | Gitに同梱された証明書ファイル(ca-bundle.crt) | 会社の証明書が入っていないためエラーになる |
| schannel | Windowsの証明書ストア | 会社の証明書が既に入っているので通る |
schannel に切り替えるだけで解決するケースが多いのは、このためです。ブラウザと同じ場所を見にいくようになります。
現在の設定を確認する
git config --global --get http.sslBackend
何も表示されなければ未設定(=ビルド既定の動作)です。
schannel に切り替える
git config --global http.sslBackend schannel
これで多くの環境は解決します。証明書ファイルを自分で用意する必要がありません。
※Git for Windows の比較的新しいインストーラでは、インストール時に「Use the native Windows Secure Channel library」を選ぶことができ、選択済みであればこの設定は不要です。
schannel にしても解決しないとき
公式ドキュメントには、schannel使用時の追加オプションが2つ記載されています。
① 失効確認でエラーになる場合
http.schannelCheckRevoke
「Used to enforce or disable certificate revocation checks in cURL when http.sslBackend is set to “schannel”. Defaults to true if unset. Only necessary to disable this if Git consistently errors and the message is about checking the revocation status of a certificate.」
(http.sslBackend が schannel のとき、証明書の失効確認を強制または無効化する。未設定時の既定は true。Gitが継続的にエラーになり、その内容が証明書の失効状態の確認に関するものである場合にのみ、無効化する必要がある)
企業ネットワークでは、失効確認のための外部通信(CRL/OCSP)自体がブロックされていることがあります。その場合に限り、次を設定します。
git config --global http.schannelCheckRevoke false
「エラーメッセージが失効確認に関するものである場合にのみ」という条件が公式に明記されています。とりあえず設定する類のものではありません。
② 証明書ファイルも併用したい場合
http.schannelUseSSLCAInfo
「the Secure Channel backend can use the certificate bundle provided via http.sslCAInfo, but that would override the Windows Certificate Store.」
(schannelバックエンドは http.sslCAInfo で指定した証明書バンドルを使えるが、それはWindowsの証明書ストアを上書きしてしまう)
望ましくないため、Gitは既定でファイル側を使わないようにしています。schannel を使うなら、原則として証明書ファイルの指定は不要と考えてください。
openssl バックエンドのまま解決する方法
Linux・macOS や、schannel が使えない環境ではこちらになります。
http.sslCAInfo
「File containing the certificates to verify the peer with when fetching or pushing over HTTPS. Can be overridden by the GIT_SSL_CAINFO environment variable.」
(HTTPSでのfetch/push時に相手を検証するための証明書を格納したファイル。環境変数 GIT_SSL_CAINFO で上書きできる)
手順は次のとおりです。
- 情報システム部門から社内CA証明書(PEM形式)を入手する
- 安全な場所に保存する
- Gitに読み込ませる
git config --global http.sslCAInfo /path/to/company-ca.pem
環境変数でも指定できます。
export GIT_SSL_CAINFO=/path/to/company-ca.pem
証明書は自分で用意せず、必ず情報システム部門から受け取ってください。出所の分からない証明書を信頼リストに入れる行為は、それ自体がリスクです。
【重要】やってはいけない設定
検索でよく出てくるのがこれです。
git config --global http.sslVerify false # ← 推奨しません
公式ドキュメントの説明はこうです。
http.sslVerify
「Whether to verify the SSL certificate when fetching or pushing over HTTPS. Defaults to true. Can be overridden by the GIT_SSL_NO_VERIFY environment variable.」
(HTTPSでのfetch/push時にSSL証明書を検証するかどうか。既定は true)
既定が true であるものを、わざわざ false にする設定です。しかも --global を付ければ、その端末のすべてのリポジトリに適用されます。
SSLインスペクション環境では、すでに検証の一部を検査機器に委ねた状態にあります(CISAが警告している点)。そのうえでクライアント側の検証まで放棄すれば、通信の正当性を確認する主体がいなくなります。
どうしても切り分けのために使う場合は、グローバルではなくそのリポジトリだけに限定し、原因が分かったら必ず戻してください。
プロキシ自体の設定が必要な場合
証明書ではなく、そもそもプロキシを経由できていないケースもあります。公式ドキュメントによれば http.proxy は通常 http_proxy/https_proxy/all_proxy の環境変数で設定されますが、Git側で明示することもできます。
git config --global http.proxy http://proxy.example.co.jp:8080
どの通信がプロキシを経由するかは、PACファイルで決まっている場合があります(PACファイルとは?/プロキシサーバーとVPNの違い)。
切り分けの順番
| 順 | 確認すること |
|---|---|
| 1 | ブラウザで同じURLを開けるか(開ければネットワークは通っている) |
| 2 | エラーが証明書の話か、接続の話かを読む |
| 3 | Windowsなら schannel に切り替える |
| 4 | 失効確認のエラーが出るなら schannelCheckRevoke=false |
| 5 | Linux/macOSなら 社内CA証明書を sslCAInfo で指定 |
| 6 | 解決しなければ情報システム部門に相談(設定変更の可否も含めて) |
他のツールでも同じことが起きる
この問題はGitに限りません。独自の証明書ストアを持つツールすべてで起こります。
特にAWS CLIは、環境変数での証明書指定が効かないという既知の制限があり、Gitより対処が限られます(企業プロキシ環境でAWS CLIがSSLエラーになる理由と対処法)。
Gitに schannel という選択肢があるのは、むしろ恵まれているほうです。
よくある質問
Q. 設定を変えると会社のセキュリティを回避することになりませんか?
schannel への切り替えや社内CA証明書の追加は、回避ではなく「会社の仕組みを正しく信頼する」設定です。通信は引き続きSSLインスペクションを経由します。
一方 sslVerify false は検証そのものをやめる操作なので、性質が異なります。
Q. SSH接続なら関係ありませんか?
SSH(git@github.com:...)はHTTPSを使わないため、この証明書エラーは起きません。ただし企業ネットワークではSSHの外向き通信(22番ポート)が塞がれていることが多いのが実情です。
Q. 会社のCA証明書はどこで手に入りますか?
情報システム部門に依頼してください。「Gitで社内CA証明書が必要」と伝えれば通じます。
ブラウザから証明書をエクスポートする方法もありますが、正規の入手経路を使うのが原則です。
Q. 一時的に回避したいときは?
リポジトリ単位に限定してください。
git -c http.sslVerify=false clone https://...
この形なら設定として保存されず、そのコマンド1回だけに効きます。ただし原因の解決にはならないため、必ず情報システム部門に相談してください。
参考にした主な調査・資料
- git-config Documentation(http.sslBackend / http.sslCAInfo / http.sslVerify / http.schannelCheckRevoke / http.schannelUseSSLCAInfo)|Git 公式
- HTTPS Interception Weakens TLS Security(Alert TA17-075A)|CISA
- TLS暗号設定ガイドライン|独立行政法人 情報処理推進機構(IPA)
※Git公式ドキュメントの引用は原文(英語)からの抜粋で、和訳は本記事によるものです。設定の可否は社内ポリシーによって異なります。実際の変更前に、情報システム部門にご確認ください。
まとめ
- 原因は企業ネットワークのSSLインスペクション。会社の証明書が返るためGitが検証できない
- ブラウザで平気なのはWindowsの証明書ストアに会社の証明書が入っているから
- Windows版Gitは証明書バックエンドを選べる(openssl / schannel)
- schannel に切り替えると、Windowsの証明書ストアを見るようになり解決することが多い
- 失効確認でエラーが出る場合に限り http.schannelCheckRevoke=false(公式も「その場合にのみ」と明記)
- schannel では証明書ファイルの指定は原則不要(指定するとストアを上書きしてしまう)
- Linux/macOSは http.sslCAInfo で社内CA証明書を指定
- http.sslVerify false は既定値をわざわざ落とす設定。–global で恒久化しない
このエラーは「Gitが壊れている」のではなく、Gitが正しく証明書を検証した結果です。
検証を止めるのではなく、正しい証明書を見にいくよう設定する——それが本来の対処になります。