ハンドシェイクが失敗した場合
ウェブサイトにアクセスしようとした際、ホームページの代わりに Chrome や Edge でグレーの警告画面が表示されることがあります。エラーコードは ERR_SSL_VERSION_OR_CIPHER_MISMATCH です。これはコードやインターネット接続の問題ではありません。本質的には、ブラウザとウェブサーバーがセキュリティプロトコルのハンドシェイクを試みたものの、共通の言語(プロトコル)を見つけられなかったことを意味します。
この失敗はインフラストラクチャレベルで発生します。通常、サーバーが最新のブラウザでは廃止され、危険とみなされているセキュリティ標準を使用しようとしていることを示しています。
接続がブロックされる理由
セキュリティ標準の進化は速いです。5年前に安全だったものが、今日では脆弱性となっていることがよくあります。ハンドシェイクの失敗の多くは、以下の4つの問題のいずれかに起因します。
- レガシーなTLSバージョン: 2020年以降、Chrome 84+や Firefox などの主要なブラウザでは TLS 1.0 および 1.1 が非推奨となりました。サーバーがこれらのバージョンのみをサポートしている場合、最新のブラウザは接続を拒否します。
- 脆弱な暗号化スイート: RC4、DES、3DES などの古い暗号を使用することは、大きなリスクとなります。現代のブラウザでは、安全な接続のために GCM ベースの暗号や ChaCha20 が求められます。
- 証明書の不一致: SSL証明書のドメインがURLと一致しない場合や、RSAキーと ECC (楕円曲線暗号) キーの間で競合がある場合に、このエラーが発生することがあります。
- Cloudflare のプロビジョニング: 最近 Cloudflare に移行した場合、Universal SSL 証明書が「検証保留中 (Pending Validation)」である可能性があります。このプロセスには15分から24時間ほどかかる場合があります。
ステップ1:現在のSSL設定を監査する
設定ファイルを調査する前に、サーバーが実際に何をブロードキャストしているかを確認しましょう。Qualys SSL Labs ツールを使用して詳細に調査するか、ターミナルから nmap を使ってクイックスキャンを実行できます。
nmap --script ssl-enum-ciphers -p 443 yourdomain.com
出力を注意深く確認してください。TLSv1.0 や TLSv1.1 のみがリストされている場合は、それが原因です。最新のセキュリティ要件を満たすには、サーバーが少なくとも TLSv1.2 をサポートしている必要があります。
ステップ2:サーバー設定の更新
Nginx の強化
Nginx でこの問題を解決するには、サイトの設定ファイルを特定します。通常は /etc/nginx/sites-available/ にあります。ssl_protocols と ssl_ciphers の行を探してください。
これらを以下の最新標準を使用するように更新します:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# 安全なプロトコルのみを許可
ssl_protocols TLSv1.2 TLSv1.3;
# 強度の高い最新の暗号化スイートを使用
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers on;
}
再起動する前に必ず構文を確認してください。sudo nginx -t を実行し、問題がなければ sudo systemctl reload nginx でサービスをリロードします。
Apache の設定
Apache の場合は、VirtualHost ファイルまたはグローバルな ssl.conf を編集する必要があります。古いプロトコルを明示的に無効にしていることを確認してください。
# SSLv3 および TLS 1.0/1.1 を無効化
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# GCMベースの最新の暗号化スイートを定義
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
SSLHonorCipherOrder on
sudo systemctl restart apache2 を実行して変更を適用します。
Cloudflare 設定の調整
サイトが Cloudflare の背後にある場合、ボトルネックはオリジンサーバーではなくエッジ設定にある可能性があります。ダッシュボードにログインし、SSL/TLS > エッジ証明書に移動します。
最低 TLS バージョンを確認してください。これが 1.3 に設定されている場合、古いデバイス(Android 4.4 や IE 11 など)は接続に失敗します。通常、セキュリティと互換性のバランスが良い 1.2 に設定するのが最適です。また、Universal SSL のステータスが「保留中」になっていないか確認してください。
ステップ3:修正の確認
サーバーを更新したら、openssl を使用して手動でハンドシェイクをテストします。これにより、ブラウザのキャッシュをバイパスして生のデータを取得できます。
openssl s_client -connect yourdomain.com:443 -tls1_2
接続に成功すると、証明書チェーンと特定の暗号の詳細が表示されます。alert handshake failure と表示される場合は、サーバーが依然として接続の試行を拒否しています。
最後のヒント:ブラウザのキャッシュをクリアするか、シークレットウィンドウを使用してください。ブラウザはセキュリティハンドシェイクの失敗状態を記憶していることがよくあります。単純なリフレッシュだけでは古いエラーが消えない場合があります。

