2026年8月18日
2026年8月18日
WordPressでSSL handshake failureが出るときの原因と解決方法
WordPressで「SSL handshake failure」(TLSハンドシェイクの失敗)が出るときは、最初に「訪問者やCDNからサイトへの接続で失敗しているのか」「WordPressから外部サービスへの接続で失敗しているのか」を切り分けます。向きによって原因も直す場所もまったく違うためです。この記事では、エラーの見え方から向きを判断する方法、openssl と curl での確認手順、よくある原因ごとの直し方を解説します。
SSL handshake failureとは
HTTPSの通信では、データを送る前に、クライアントとサーバーが使うTLSのバージョンや暗号方式を決め、サーバー証明書を受け渡す「ハンドシェイク」を行います。ここでお互いに合意できなかったり、途中で接続が切られたりすると、ハンドシェイクの失敗になります。
似たエラーに「証明書の検証に失敗した」(cURLのエラー60など)がありますが、こちらはハンドシェイクで受け取った証明書が信頼できないという意味で、原因は中間証明書の不足や証明書の期限切れであることがほとんどです。ハンドシェイクの失敗はそれより手前、TLSのバージョンや暗号方式、SNI(どのドメインに接続したいかを伝える仕組み)の段階で止まっていることが多く、対処の方向が異なります。
エラーの見え方で向きを判断する
訪問者やCDNからサイトへの接続で失敗している場合は、次のような形で現れます。
- ブラウザで「ERR_SSL_VERSION_OR_CIPHER_MISMATCH」「ERR_SSL_PROTOCOL_ERROR」などが表示される
- Cloudflareを使っていて「Error 525: SSL handshake failed」が表示される
- サイト全体、または特定のドメインやサブドメインだけが開けない
WordPressから外部への接続で失敗している場合は、サイト自体は開けるのに、次のような症状が出ます。
- プラグインやテーマ、WordPress本体の更新が「cURL error 35」などで失敗する
- 決済、メール配信、SNS連携などのプラグインが外部APIに接続できない
- 「ツール」→「サイトヘルス」で、外部への通信やループバックリクエスト(サイト自身への接続)の失敗が表示される
- PHPのエラーログに
sslv3 alert handshake failureやSSL_ERROR_SYSCALLを含むメッセージが残る
後者の sslv3 という文字はOpenSSLが使う内部の表記で、実際にSSLv3で通信しているという意味ではありません。
接続を手元で再現して確認する
どちらの向きでも、openssl s_client を使うとハンドシェイクのどこで止まるかを確認できます。サイトへの接続を調べるときは手元のPCから、WordPressから外部への接続を調べるときはWordPressが動いているサーバー上で実行します。
# SNIを付けて接続し、ハンドシェイクの結果を表示する
openssl s_client -connect example.com:443 -servername example.com </dev/null
# TLSのバージョンを指定して、それぞれ通るか確認する
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
成功すると、証明書の内容や、使われたプロトコル・暗号方式が表示されます。handshake failure や no protocols available と出る場合は、バージョンか暗号方式が合っていません。-servername を付けたときだけ成功する場合は、SNIが関係しています。
curl でも同じ確認ができ、どの段階で止まったかが詳しく表示されます。
curl -v -o /dev/null https://example.com/
原因1:サーバー側のTLS設定がクライアントと合わない
サイトに接続できない場合によくあるのが、サーバーが受け付けるTLSのバージョンや暗号方式と、クライアントが使えるものが重ならないケースです。古いTLS 1.0・1.1を無効にするのは正しい対応ですが、TLS 1.3だけに絞ると、TLS 1.3に対応していない古い環境や一部のクローラーが接続できなくなります。現在はTLS 1.2と1.3の両方を有効にする構成が一般的です(2026年10月現在)。
設定ファイルを変更する前に、元のファイルを別名でコピーしておきます。
# Nginx の server ブロック(listen 443 ssl の中)
ssl_protocols TLSv1.2 TLSv1.3;
# Apache の VirtualHost *:443 の中、または ssl.conf
SSLProtocol -all +TLSv1.2 +TLSv1.3
変更後は、構文チェックをしてから再読み込みします。構文エラーのまま再起動すると、サイト全体が止まるおそれがあるためです。
sudo nginx -t && sudo systemctl reload nginx
# Apache の場合
sudo apachectl configtest && sudo systemctl reload apache2
暗号方式(Nginxの ssl_ciphers、Apacheの SSLCipherSuite)を独自に細かく指定している場合は、指定が厳しすぎて一般的なクライアントと合わなくなっていないかも確認します。特別な理由がなければ、OSやWebサーバーの標準設定に近い構成に戻して試すと切り分けがしやすくなります。
原因2:そのドメインに証明書が設定されていない
1台のサーバーで複数のドメインを運用している場合、SNIで指定されたドメインに対応する設定が見つからないと、別のドメインの設定が使われたり、接続が切られたりします。次のような点を確認します。
- 対象のドメインに、443番ポートで待ち受ける設定(Nginxの
server、ApacheのVirtualHost)があるか server_nameやServerName・ServerAliasに、www付き・無しの両方が含まれているか- IPv6でも待ち受けているか。DNSにAAAAレコードがあるのに、IPv6の443番ポートでTLSの設定が無いと、IPv6で接続した訪問者だけ失敗します
証明書と秘密鍵の組み合わせが正しいかは、公開鍵のハッシュを比べると確認できます。2つの出力が同じであれば、組み合わせは合っています。
openssl x509 -noout -pubkey -in /path/to/fullchain.pem | openssl sha256
openssl pkey -pubout -in /path/to/privkey.pem | openssl sha256
原因3:CDNとオリジンサーバーの間で失敗している
Cloudflareのエラー525は、Cloudflareとオリジンサーバー(WordPressが動いているサーバー)の間のハンドシェイクが失敗したことを示します。訪問者とCloudflareの間は正常なので、ブラウザでは証明書に問題が無いように見えるのが特徴です。
CloudflareのSSL/TLSの暗号化モードを「Full」または「Full (strict)」にしている場合、オリジンサーバーの443番ポートでTLSが動いている必要があります。オリジン側の証明書が未設定、または前の原因1・2に当てはまる状態だと525になります。オリジンのIPアドレスに対して、ドメイン名をSNIとして指定し、openssl s_client で接続できるか確認します。
openssl s_client -connect 203.0.113.10:443 -servername example.com </dev/null
原因4:WordPressのサーバーが古いTLSしか使えない
WordPressから外部への接続で失敗する場合は、サーバーのOpenSSLやPHPのcURL拡張が古く、接続先が求めるTLSのバージョンや暗号方式に対応していないことがあります。接続先のサービスがセキュリティ強化のために古い方式を停止したタイミングで、急に失敗し始めるのがよくあるパターンです。
サーバー上で、PHPが使っているcURLとOpenSSLのバージョンを確認します。
openssl version
php -r 'print_r( curl_version() );'
ssl_version が古い場合は、OSやPHPのアップデートが必要です。共用サーバーでは利用者が更新できないため、新しいPHPバージョンへの切り替えで解決するか、サーバー会社に問い合わせます。
WordPress上から実際に接続を試すには、WP-CLIで次のように実行します。
wp eval '$r = wp_remote_get( "https://api.wordpress.org/" ); echo is_wp_error( $r ) ? $r->get_error_message() : wp_remote_retrieve_response_code( $r );'
200が表示されれば接続できています。エラーメッセージが表示された場合は、そのメッセージにcURLのエラー番号が含まれるため、原因の手がかりになります。
このほか、社内ネットワークやサーバー会社のプロキシ、ファイアウォールが通信の中身を検査していて、ハンドシェイクを妨げている場合もあります。同じサーバー上で openssl s_client が失敗し、別のネットワークからは成功するなら、経路上の機器を疑います。接続先がクライアント証明書を求めるAPI(相互TLS)の場合は、証明書を設定していないとハンドシェイクが失敗します。
やってはいけない対処
検索すると、http_request_args フィルターや https_ssl_verify フィルターで sslverify を false にする方法が見つかることがあります。これは証明書の検証を止めるもので、通信の盗聴や改ざんを防げなくなります。しかも検証より手前で失敗しているハンドシェイクのエラーは、この設定では直りません。一時的な切り分けであっても本番環境では使わず、原因をサーバー側で直すようにします。
WordPressの wp-includes/certificates/ca-bundle.crt を書き換える方法も、本体の更新で上書きされるうえ、ハンドシェイクの失敗とは関係が無いことが多いため勧められません。
まとめ
- まず、訪問者やCDNからサイトへの接続か、WordPressから外部への接続かを切り分けます。
openssl s_client -servernameとcurl -vで、TLSのバージョン、SNI、証明書のどこで止まるかを確認します。- サイト側では、TLS 1.2と1.3を有効にし、対象ドメインの443番ポートの設定と証明書・秘密鍵の組み合わせを見直します。
- Cloudflareの525は、オリジンサーバー側のTLS設定を確認します。
- 外部への接続では、サーバーのOpenSSLとcURLのバージョンを確認し、
sslverifyを無効にする対処は避けます。