TL;DR
サーバーがTLS 1.0またはTLS 1.1を使用しています。モダンブラウザは2020年初頭に両方のサポートを打ち切りました — Chrome 84とFirefox 74がいずれも対応を終了しています。TLS 1.2/1.3を有効にして古いバージョンを無効化すれば完了です。
# Nginx — サーバーブロックまたはhttpブロックに追記する
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
変更後にNginxをリロードする: sudo systemctl reload nginx
このエラーの意味
ERR_SSL_VERSION_OR_CIPHER_MISMATCHは、ページのデータが1バイトも転送される前にTLSハンドシェイクが失敗したときに表示されます。原因は主に3つあります:
- サーバーがTLS 1.0またはTLS 1.1しか提供していない。Chrome 84(2020年8月)とFirefox 74(2020年3月)はいずれもこれらのサポートを削除しました。
- サーバー上のすべての暗号スイートが安全でないと判断され、モダンクライアントから除外されている。
- SSL証明書のCommon Nameがドメイン名と一致していない — まれなケースですが、同じエラーコードが表示されます。
ほとんどの場合、2014年頃に設定されてそのまま放置されたサーバーが原因です。古い設定、新しいブラウザ、ハンドシェイク失敗という流れです。
現在のTLS設定を確認する
設定を変更する前に、サーバーが実際にアドバタイズしている内容を確認しましょう:
# opensslがインストールされているLinuxマシンから実行する
openssl s_client -connect yourdomain.com:443 -tls1
openssl s_client -connect yourdomain.com:443 -tls1_1
openssl s_client -connect yourdomain.com:443 -tls1_2
openssl s_client -connect yourdomain.com:443 -tls1_3
-tls1や-tls1_1では接続できるのに-tls1_2で失敗する場合 — それが問題の原因です。暗号スイートの詳細を確認するにはnmapの方が手軽です:
nmap --script ssl-enum-ciphers -p 443 yourdomain.com
詳細なグレード評価レポートが必要ですか?SSL Labs Server Test(「ssllabs server test」で検索)を実行してください。サポートされているすべてのプロトコルが一覧表示され、非推奨のものには赤いFマークが付きます。
Nginxでの修正
Nginxの設定ファイルを開きます — 通常は/etc/nginx/nginx.confか/etc/nginx/sites-available/配下のサイト設定ファイルです。SSLブロックを見つけて次のように置き換えます:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# 既存のssl_protocolsの行をこれに置き換える:
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:DHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
}
# 設定をテストしてからリロードする
nginx -t
sudo systemctl reload nginx
Apacheでの修正
バーチャルホストの設定ファイルか/etc/apache2/mods-enabled/ssl.confを編集します。重要なディレクティブはSSLProtocolです — マイナス記号で古いバージョンを明示的に無効化します:
<VirtualHost *:443>
ServerName yourdomain.com
SSLEngine on
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/key.pem
# 古いプロトコルを無効化する
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
# モダンな暗号スイートのみ使用する
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
</VirtualHost>
# 設定を確認して再起動する
apache2ctl configtest
sudo systemctl restart apache2
Node.js(HTTPSサーバー)での修正
カスタムのNode.js HTTPSサーバーを使っていますか?createServerの呼び出しでTLSオプションを明示的に指定します:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem'),
minVersion: 'TLSv1.2', // TLS 1.2未満を拒否する
ciphers: [
'ECDHE-RSA-AES128-GCM-SHA256',
'ECDHE-RSA-AES256-GCM-SHA384',
'ECDHE-RSA-CHACHA20-POLY1305',
].join(':'),
};
https.createServer(options, app).listen(443);
サーバーではなくクライアント側の場合
サードパーティのAPIを呼び出してこのエラーが発生している場合、問題はリモートサーバー側にあります — こちらのサーバーは正常です。対処法は以下の通りです:
- **APIプロバイダーに連絡する。**TLS 1.2を有効化するよう依頼してください。それが根本的な解決策です。
- 内部システムで待機中の短期的な回避策が必要な場合、HTTPクライアントでTLS 1.2を明示的に指定できます:
# Python requests — カスタムアダプターでTLS 1.2以上を強制する
import ssl
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.ssl_ import create_urllib3_context
class TLS12Adapter(HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
ctx = create_urllib3_context()
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
kwargs['ssl_context'] = ctx
super().init_poolmanager(*args, **kwargs)
session = requests.Session()
session.mount('https://', TLS12Adapter())
response = session.get('https://old-api.example.com/endpoint')
本番環境でTLS 1.0/1.1を受け入れるようにクライアントをダウングレードしてはいけません。それでは対策の意味が完全になくなります。
OpenSSLバージョンの確認
TLS 1.3にはOpenSSL 1.1.1以降が必要です。それより古いバージョンではnginx.confに何を書いてもTLS 1.3は利用できません。
openssl version
# TLS 1.3サポートにはOpenSSL 1.1.1以上が必要
OpenSSL 1.0.xのままですか?まずライブラリをアップグレードしてから、サーバーの設定を更新してください:
# Debian/Ubuntuの場合
sudo apt update && sudo apt install openssl libssl-dev
# CentOS/RHEL 8以降の場合
sudo dnf install openssl
修正を確認する
# TLS 1.2が動作することを確認する
openssl s_client -connect yourdomain.com:443 -tls1_2
# 表示されるはず: SSL handshake has read ... bytes
# 確認する内容: Protocol: TLSv1.2
# 古いTLSが拒否されることを確認する
openssl s_client -connect yourdomain.com:443 -tls1_1
# 失敗するはず: alert handshake failure など
# TLS 1.3が動作することを確認する(サポートされている場合)
openssl s_client -connect yourdomain.com:443 -tls1_3
Chromeでサイトを開いてください。エラーが消え、鍵マークが表示されるはずです。鍵マークをクリックして「接続は保護されています」→「証明書は有効です」を確認し、どのプロトコルバージョンが使われているかを確認してください。
証明書のCN不一致(同じエラー、異なる原因)
ホスト名の不一致が原因で一部のブラウザにERR_SSL_VERSION_OR_CIPHER_MISMATCHが表示されることがあります — 紛らわしいことに同じエラーコードです。以下のコマンドで確認できます:
openssl s_client -connect yourdomain.com:443 | openssl x509 -noout -subject -subj_hash
# subject= CN=yourdomain.com
# SANを確認する
openssl s_client -connect yourdomain.com:443 | openssl x509 -noout -text | grep -A1 "Subject Alternative Name"
CNまたは少なくとも1つのSANエントリが、接続しようとしているドメインと一致している必要があります。どちらも一致しない場合は、正しいドメインで証明書を再発行してください。

