はじめに (対象読者・この記事でわかること)
本記事は、サーバー管理者・DevOps エンジニア・Web 開発者など、curl を利用して外部 API や内部サービスと通信する際に SSL 証明書の検証エラーに悩んでいる方を対象としています。
この記事を読むことで、以下のことが理解・実践できるようになります。
- curl が証明書チェックに失敗する典型的なシナリオとその根本原因
- ローカル環境・CI/CD パイプライン・本番サーバーそれぞれで有効な対処法
--cacert、--capath、--insecureなどオプションの正しい使い分けと、システム全体の CA バンドル設定方法
背景として、近年のクラウド環境やコンテナ化の普及に伴い、証明書チェーンが複雑化し「証明書が信頼できない」エラーが頻発しています。そこで、実務で即座に役立つチェックリストと具体例を交えて解説します。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- 基本的な Linux コマンド操作(
cat、openssl、curlなど) - TLS/SSL の概念と、サーバー証明書・中間証明書・ルート証明書の関係性
- システムの証明書ストア(
/etc/ssl/certs、/etc/pki/tls/certs)や OpenSSL の設定ファイルの場所
curl の証明書検証とは何か(概要・背景)
curl はデフォルトでシステムにインストールされている CA(Certificate Authority)バンドルを利用し、接続先サーバーが提示する証明書チェーンを検証します。検証が成功すれば通信は暗号化され、かつ相手の正当性が保証されます。逆に、証明書が信頼できない、有効期限が切れている、ホスト名が一致しない といった問題があると、curl はエラーを返し接続を中止します。
この挙動はセキュリティ上重要ですが、開発・テスト環境では自己署名証明書や社内 CA が使われることが多く、システムの CA バンドルにそれらが含まれていないケースが頻発します。その結果、curl https://example.com が以下のようなエラーを出すことがあります。
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/libcurl/c/libcurl-errors.html
つまり、「curl が証明書チェックできない」 という状態は、「CA バンドルの設定が不適切」 または 「サーバー側の証明書チェーンが不完全」 が原因です。本章では、こうした原因を体系的に整理し、対処の方向性を示します。
証明書チェックが失敗する原因と対処法(具体的な手順や実装方法)
本セクションでは、実務で遭遇しやすいケースを想定し、順序立ててトラブルシューティングを行う手順を解説します。各ステップでは実際にターミナルで入力するコマンド例や設定ファイルの記述例を示します。
ステップ 1 ‑ 環境の確認
まずは現在の curl バージョンと、使用している CA バンドルの場所を把握します。
Bash# curl のバージョンとビルドオプションを確認 curl -V # 使用中の CA バンドルパスを取得(OpenSSL がリンクしている場合) openssl version -d
curl -V の出力例:
curl 7.88.1 (x86_64-pc-linux-gnu) libcurl/7.88.1 OpenSSL/1.1.1t zlib/1.2.13
Release-Date: 2023-10-12
Protocols: dict file ftp ftps http https imap imaps pop3 pop3s smtp smtps telnet tftp
Features: AsynchDNS HTTPS-proxy IPv6 Largefile libz NTLM NTLM_WB SSL TLS-SRP
ここで OpenSSL/ のバージョンが表示されていることを確認し、次に openssl version -d でデフォルトの設定ディレクトリ(例: /usr/lib/ssl)を確認します。
ステップ 2 ‑ CA 証明書の設定
2‑1. システム CA バンドルに社内CA を追加
自己署名証明書や社内 CA の PEM ファイル(例: mycorp-ca.pem)がある場合、システムの CA バンドルに追記します。
Bash# 例: Debian/Ubuntu 系の場合 sudo cp mycorp-ca.pem /usr/local/share/ca-certificates/ sudo update-ca-certificates
CentOS/RHEL 系では次のようにします。
Bashsudo cp mycorp-ca.pem /etc/pki/ca-trust/source/anchors/ sudo update-ca-trust extract
2‑2. curl に個別の CA ファイルを指定
環境ごとに CA バンドルを切り替えたくない場合、curl の --cacert オプションで明示的にファイルを指定できます。
Bashcurl --cacert /path/to/mycorp-ca.pem https://internal.example.com
--capath を利用するとディレクトリ単位で証明書を検索させることも可能です。
Bashcurl --capath /etc/ssl/certs https://internal.example.com
ステップ 3 ‑ サーバー側証明書チェーンの確認
サーバー側が中間証明書を正しく返していないと、クライアント側では「証明書が不完全」エラーが出ます。openssl s_client でチェーンを検証します。
Bashopenssl s_client -connect internal.example.com:443 -showcerts
出力の最後に「Verify return code: 0 (ok)」が表示されていればチェーンは正常です。エラーが出た場合はサーバー管理者に中間証明書の設定を依頼しましょう。
ハマった点やエラー解決
| 発生したエラー | 主な原因 | 解決策 |
|---|---|---|
SSL certificate problem: self signed certificate |
自己署名証明書が CA バンドルに未登録 | --cacert で PEM を指定、またはシステム CA に追加 |
SSL: no alternative certificate subject name matches target host name |
サーバー証明書の CN/SAN がリクエストホストと不一致 | サーバー側の証明書を再発行、もしくは --resolve で名前解決を偽装 |
SSL certificate problem: unable to get local issuer certificate |
中間証明書がサーバー側で未提供 | openssl s_client でチェーン確認し、サーバー設定に ssl_certificate(NGINX)や SSLCertificateChainFile(Apache)を追記 |
curl: (35) error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure |
TLS バージョン/暗号スイートの不一致 | curl --tlsv1.2 でバージョン固定、またはサーバー側で対応する暗号スイートを有効化 |
解決策のまとめ
-
CA バンドルの確認・更新
- システムに社内 CA を追加
-update-ca-certificates(Debian系)やupdate-ca-trust(RHEL系)で即時反映 -
curl オプションで明示的に証明書を指定
---cacertで個別 PEM を指定
---capathでディレクトリを指定
- テスト環境は一時的に--insecure(ただし本番では使用しない) -
サーバー側の証明書チェーンを正しく構成
- 中間証明書を適切に設定
-openssl s_clientでチェーン検証を行う -
TLS バージョン・暗号スイートの整合性
---tlsv1.2や--tls-maxを使用して互換性を確保
これらを順に実施すれば、curl が証明書チェックできない問題は大半解消できます。
まとめ
本記事では、curl の証明書検証が失敗する原因と、システム CA バンドルの更新、curl のオプション活用、サーバー側証明書チェーンの検証という三つの観点から対処法を解説しました。
- 原因①:ローカルに信頼できる CA が無い → 対策:
update-ca-certificatesで追加または--cacert指定 - 原因②:サーバーが中間証明書を返さない → 対策:
openssl s_clientでチェーン確認し、サーバー側設定を修正 - 原因③:TLS バージョンや暗号スイートの不整合 → 対策:
--tlsv1.2などでバージョン固定
これにより、開発・ステージング・本番環境すべてで安全に curl を利用できるようになります。今後は、自動化された CI/CD パイプラインでの証明書検証や、Docker コンテナ内部での CA 設定についても取り上げる予定です。
参考資料
- curl コマンドマニュアル(公式)
- OpenSSL コマンドリファレンス
- Linux の証明書ストア管理 – Debian Wiki
- TLS の基礎と証明書チェーン – 入門書「HTTP/2 と TLS」
