2026年5月20日
2026年5月20日
WordPressのSSL証明書エラーの直し方|ERR_CERT系の原因別とcURL error 60
WordPressのサイトでSSL証明書のエラーが出たときは、まず「訪問者のブラウザがサイトに接続するときのエラー」なのか、「WordPress(PHP)が外部のサービスに接続するときのエラー」なのかを分けて考えます。前者はブラウザのエラーコードで、後者は cURL error 60 などのメッセージで原因の見当がつきます。
この記事のコマンドは、Ubuntu / Debian のサーバーで Apache または Nginx と Let's Encrypt(certbot)を使っている場合の例です(2026年10月時点)。example.com は自分のドメインに置き換えてください。
エラーコードと主な原因
Chrome系のブラウザで表示される主なエラーコードと、最初に疑う原因です。
| エラーコード | 主な原因 | 見る章 |
|---|---|---|
NET::ERR_CERT_DATE_INVALID |
証明書の有効期限切れ、または閲覧している端末の時計のずれ | 証明書の期限が切れている |
NET::ERR_CERT_AUTHORITY_INVALID |
中間証明書が送られていない、自己署名証明書を使っている | 中間証明書が足りない |
NET::ERR_CERT_COMMON_NAME_INVALID |
証明書に含まれるドメイン名と、開いたURLのドメイン名が違う(www の有無など) |
ドメイン名が一致しない |
ERR_SSL_VERSION_OR_CIPHER_MISMATCH |
サーバーが古いTLS(1.0/1.1)しか使えない、暗号の設定が合わない | TLSの設定が合わない |
ERR_SSL_PROTOCOL_ERROR |
443番ポートでHTTPSの設定が動いていない、Webサーバーの設定ミス | TLSの設定が合わない |
エラー画面にはならず、アドレスバーの鍵マークに警告が出るだけの場合は、証明書ではなく、HTTPSのページの中で http:// の画像やスクリプトを読み込んでいる「混在コンテンツ」が原因のことが多いです。
まず証明書の状態を確認する
サーバーにSSHで接続できる場合は、openssl コマンドで、実際にサーバーが返している証明書を確認します。手元のパソコン(macOS や WSL など)からでも同じコマンドを使えます。
# 証明書の対象ドメイン(subject)、発行者(issuer)、有効期間
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
# 証明書に含まれるドメイン名の一覧(SAN)
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -ext subjectAltName
# 送られてくる証明書の並び(チェーン)と検証結果
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>&1 \
| grep -E "^ *[0-9] s:|^ *i:|Verify return code"
最後のコマンドで Verify return code: 0 (ok) と出れば、証明書のチェーンは正しく検証できています。notAfter= の日付が過去なら期限切れです。
Let's Encrypt の証明書を certbot で管理している場合は、次のコマンドでも有効期限とドメイン名を確認できます。
sudo certbot certificates
外部から総合的に確認したい場合は、Qualys の SSL Server Test にドメインを入力すると、チェーンの不足や対応しているTLSのバージョンを一覧で確認できます。
証明書の期限が切れている(ERR_CERT_DATE_INVALID)
certbot で取得した証明書は、通常は自動で更新されます。期限が切れているときは、自動更新が止まっているので、手動で更新してから原因を確認します。
# 自動更新のタイマーが動いているか(certbot の入れ方によって名前が違う)
systemctl list-timers | grep -i certbot
# 更新できるかを試す(実際には更新しない)
sudo certbot renew --dry-run
# 期限が近い・切れている証明書を更新する
sudo certbot renew --cert-name example.com
# Webサーバーに新しい証明書を読み込ませる(使っている方)
sudo systemctl reload apache2
sudo systemctl reload nginx
--dry-run が失敗する場合は、表示されたエラーを確認します。よくある原因は、DNSのAレコードが別のサーバーを向いている、/.well-known/acme-challenge/ へのアクセスが .htaccess やWAFで止められている、80番ポートが閉じている、などです。
レンタルサーバーの無料SSLを使っている場合は、各社のコントロールパネルで証明書の状態と更新の設定を確認します。
証明書が正しく更新されているのに、特定の人の端末だけで ERR_CERT_DATE_INVALID が出る場合は、その端末の日付と時刻がずれていないかを確認してもらいます。
中間証明書が足りない(ERR_CERT_AUTHORITY_INVALID)
パソコンのブラウザでは開けるのに、一部のスマートフォンや curl、ほかのサーバーからの接続でだけエラーになる場合は、サーバーが中間証明書を送っていないことがよくあります。上のチェーンを確認するコマンドで、0 s:(サーバー証明書)だけが表示され、1 s:(中間証明書)がなければ不足しています。
Let's Encrypt の場合は、サーバー証明書と中間証明書をまとめた fullchain.pem を指定します。
# いまの設定を確認する
grep -rn "SSLCertificateFile\|SSLCertificateChainFile" /etc/apache2/sites-enabled/
grep -rn "ssl_certificate" /etc/nginx/sites-enabled/
# Apache 2.4.8 以降:SSLCertificateFile に fullchain.pem を指定する
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
# Nginx
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
Apache 2.4.8 以降では、SSLCertificateFile に中間証明書を含むファイルを指定すれば、SSLCertificateChainFile は不要です(SSLCertificateChainFile は非推奨になっています)。有料の証明書を使っている場合は、発行元から届いた中間証明書をサーバー証明書の後ろに連結したファイルを指定します。
詳しい確認方法はSSL証明書の中間証明書が抜けている場合の確認方法と直し方で説明しています。
自己署名証明書(自分で作った証明書)は、公開サイトではブラウザに信頼されません。公開サイトでは Let's Encrypt などの認証局が発行した証明書を使います。
ドメイン名が一致しない(ERR_CERT_COMMON_NAME_INVALID)
example.com の証明書しかないのに www.example.com で開いた場合などに出ます。上の subjectAltName を表示するコマンドで、開いたドメイン名が含まれているかを確認します。
含まれていない場合は、必要なドメイン名をすべて含めて証明書を取り直します。certbot の Apache プラグインを使っている場合の例です(Nginx なら --nginx)。
sudo certbot --apache -d example.com -d www.example.com
あわせて、WordPress の「設定」→「一般」の「WordPress アドレス (URL)」と「サイトアドレス (URL)」が、証明書に含まれるドメイン名(https:// 付き)になっているかを確認します。
TLSの設定が合わない(ERR_SSL_VERSION_OR_CIPHER_MISMATCH / ERR_SSL_PROTOCOL_ERROR)
現在の主なブラウザは TLS 1.0 と 1.1 での接続をやめています。サーバーが TLS 1.2 以上で接続できるかを確認します。
# 接続できれば証明書の情報が表示される。できなければ handshake failure などのエラーになる
openssl s_client -connect example.com:443 -servername example.com -tls1_2 </dev/null
openssl s_client -connect example.com:443 -servername example.com -tls1_3 </dev/null
TLS 1.2 で接続できない場合は、Webサーバーの設定で TLS 1.2 と 1.3 を有効にします。
# Apache(mod_ssl)
SSLProtocol -all +TLSv1.2 +TLSv1.3
# Nginx
ssl_protocols TLSv1.2 TLSv1.3;
暗号スイート(SSLCipherSuite や ssl_ciphers)を自分で書いている場合は、古い設定が残っていると接続できないことがあります。Mozilla の SSL Configuration Generator で、使っているWebサーバーとバージョンに合った設定を出力して置き換えるのが安全です。設定を変えたら、構文を確認してから反映します。
sudo apachectl configtest && sudo systemctl reload apache2
sudo nginx -t && sudo systemctl reload nginx
ERR_SSL_PROTOCOL_ERROR の場合、openssl s_client の出力に wrong version number と出ることがあります。これは、443番ポートでHTTPSではなく普通のHTTPが応答していることを示します。Apache なら a2enmod ssl でSSLモジュールを有効にしているか、443番のバーチャルホストに SSLEngine on があるか、Nginx なら listen 443 ssl; になっているかを確認します。
Cloudflare を使っている場合
Cloudflare のプロキシを通している場合、ブラウザに表示される証明書は Cloudflare のものです。SSL/TLS の暗号化モードを「フル (厳密)」(Full (strict))にしていると、Cloudflare からサーバーへの接続でもサーバー側の証明書が検証されます。Cloudflare のエラー 526(Invalid SSL certificate)や 525(SSL handshake failed)が出る場合は、サーバー側の証明書と TLS の設定を、この記事の手順で確認します。
WordPressから外部への接続でSSLエラーになる(cURL error 60)
プラグインの更新、外部APIとの連携、決済などで、WordPressが外部に接続するときに次のようなエラーが出ることがあります。
cURL error 60: SSL certificate problem: unable to get local issuer certificate
WordPressが使う証明書の一覧
wp_remote_get() などの WordPress の HTTP API は、初期設定ではサーバーのOSの証明書ストアではなく、WordPress に同梱されているルート証明書の一覧(wp-includes/certificates/ca-bundle.crt)で相手の証明書を検証します。この一覧は WordPress の更新で新しくなります。そのため、サーバーの ca-certificates パッケージを更新しても、WordPress の HTTP API の結果は変わりません。
原因として多いのは次の3つです。
- 接続先のサーバーが中間証明書を送っていない:自分のサーバーから
openssl s_client -connect 接続先:443 -servername 接続先 -showcertsを実行して確認します。接続先の問題なので、接続先の管理者に連絡します。 - WordPress が古い:同梱の証明書の一覧が古く、新しいルート証明書を知らないことがあります。WordPress を最新版に更新します。
- 社内のプロキシなどが通信を中継している:独自の認証局の証明書で通信を検査する環境では、その認証局を含む証明書の一覧を指定する必要があります(後述)。
エラーの内容を記録する
どの接続で何のエラーが出ているかを確認するには、http_api_debug アクションでエラーをログに書き出します。wp-config.php で WP_DEBUG と WP_DEBUG_LOG を true にしておくと、wp-content/debug.log に記録されます。
<?php
/**
* Plugin Name: HTTP API のエラーを記録する(調査が終わったら削除する)
*/
add_action( 'http_api_debug', function ( $response, $context, $class, $parsed_args, $url ) {
if ( is_wp_error( $response ) ) {
error_log( sprintf( 'HTTP API error: %s (%s)', $response->get_error_message(), $url ) );
}
}, 10, 5 );
このコードは wp-content/mu-plugins/ に log-http-errors.php などの名前で置きます(フォルダーがなければ作ります)。調査が終わったら削除してください。
WP-CLI が使える場合は、その場で1回接続して結果を確かめることもできます(WP-CLI はコマンドライン用のPHPで動くので、Webサーバーが使うPHPとバージョンが違う場合があります)。
wp eval '$r = wp_remote_get( "https://api.example.com/" ); echo is_wp_error( $r ) ? $r->get_error_message() : wp_remote_retrieve_response_code( $r ), PHP_EOL;'
PHP の cURL と OpenSSL のバージョンは、「ツール」→「サイトヘルス」の「情報」タブで、「サーバー」の項目にある cURL のバージョンの欄で確認できます。OpenSSL が非常に古いと、新しい暗号方式の相手に接続できないことがあります。その場合はサーバーのOSやPHPの更新が必要です。
独自の認証局を使う接続先の場合
社内システムなど、独自の認証局が発行した証明書を使う接続先だけ、OSの証明書の一覧を使うように指定できます。http_request_args フィルターで sslcertificates を変更します。パスは Ubuntu / Debian の例で、独自の認証局の証明書をOSに追加してある前提です。
<?php
add_filter( 'http_request_args', function ( $args, $url ) {
// 対象の接続先だけ、OS の証明書の一覧で検証する
if ( str_starts_with( $url, 'https://internal.example.jp/' ) ) {
$args['sslcertificates'] = '/etc/ssl/certs/ca-certificates.crt';
}
return $args;
}, 10, 2 );
証明書の検証を無効にする設定は開発環境だけにする
sslverify を false にしたり、https_ssl_verify フィルターで false を返したりすると、相手の証明書を検証しなくなり、通信を盗み見・改ざんされても気づけなくなります。公開しているサイトでは使わず、自己署名証明書を使うローカルの開発環境に限ってください。
<?php
// ローカルの開発環境だけで使う。公開サイトには置かない
if ( 'local' === wp_get_environment_type() ) {
add_filter( 'https_ssl_verify', '__return_false' );
}
https_local_ssl_verify というフィルターもありますが、これは WP-Cron やサイトヘルスが自分のサイトに接続するとき(ループバック接続)だけに使われるもので、初期値はもともと false です。外部への接続には影響しません。
開発環境でも、ローカル用の認証局を作るツール(mkcert など)で証明書を作り、その認証局を信頼させれば、検証を無効にせずに済みます。
まとめ
- ブラウザのエラーは、エラーコードで原因の見当をつけ、
openssl s_clientでサーバーが返している証明書を確認する - 期限切れは
certbot renewで更新し、自動更新が止まった原因(DNS、acme-challengeへのアクセス、ポート)を確認する - 中間証明書の不足は
fullchain.pemを指定して直す。ドメイン名の不一致は、必要なドメイン名を含めて証明書を取り直す - TLS 1.2 以上で接続できるようにし、暗号スイートは Mozilla の生成ツールの設定に置き換える
cURL error 60は、WordPress 同梱の証明書の一覧で検証している点に注意して、接続先のチェーンと WordPress のバージョンを確認する。検証の無効化は開発環境だけにする
関連記事: