シナリオ
新しいSSL証明書のインストールが完了したばかりだとします。理論上は、すべてが完璧に見えます。しかし、Firefoxでドメインにアクセスした瞬間、「SSL_ERROR_UNRECOGNIZED_NAME_ALERT」というエラーに突き当たります。Chromeの場合は「この接続ではプライバシーが保護されていません」という曖昧な警告を表示して流してしまうかもしれませんが、Firefoxはより親切で、TLSハンドシェイク中の失敗であることを具体的に指摘してくれます。
これは通常、5個、10個、あるいは100個もの異なるドメインをホストしているVPSや専用サーバーで発生します。サーバーが混乱してしまうのです。リクエストを受け取っても、どの特定の証明書をブラウザに返せばよいのか判断できません。
このエラーが発生する理由
Server Name Indication (SNI) を、デジタル界のアパートの部屋番号のようなものだと考えてください。かつては、1つのIPアドレスが1つのウェブサイトを意味していました。今日では、1つのIPで数百のサイトをホストすることもあります。SNIは、接続の最初にブラウザがサーバーに対して「example.comを探しています」と伝えることを可能にするTLSプロトコルの拡張機能です。
このアラートが表示されるとき、サーバーは実質的にこう言っています。「example.comへのリクエストは届きましたが、その名前に一致する設定ブロックや証明書がありません。」 サーバーは推測で間違った証明書を送るのではなく、「Unrecognized Name(認識されない名前)」アラートを出して接続を終了します。
ステップ 1:Nginxの設定を監査する
Nginxは厳格です。server_name ディレクティブがブラウザからのホストヘッダーと正確に一致しない場合、ハンドシェイクは高確率で失敗します。
サーバーブロックの確認
サイトの設定ファイル(通常は /etc/nginx/sites-available/ にあります)を探します。特にSSLブロックに注目してください:
server {
listen 443 ssl;
server_name example.com; # これはブラウザのURLバーと一致していますか?
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
}
サブドメインの欠落はよくある原因です。www.example.com にアクセスしているのに、設定にルートドメインしか記載されていない場合、サーバーはそのリクエストを認識しません。両方を記載することで修正してください:
server_name example.com www.example.com;
デフォルトサーバーの罠に注意
Nginxは、直接の一致が見つからない場合、「デフォルト」サーバーにフォールバックします。そのデフォルトブロックにSSL設定がないか、不明な名前を拒否するように設定されている場合、サイトは読み込まれません。特定のドメインブロックが、その固有のホスト名に対して常に最優先されるようにしてください。
ステップ 2:ApacheでSNIを修正する
Apacheユーザーも、VirtualHost コンテナ内で同様のハードルに直面します。ここでは正確さが重要です。ServerName と ServerAlias が、エラーを引き起こしているドメインと完全に一致している必要があります。
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
</VirtualHost>
モダンなApache (2.4+) はSNIを自動的に処理します。しかし、レガシーシステムを保守している場合は、1つのIPで複数の証明書を許可するために、グローバル設定で NameVirtualHost *:443 が定義されていることを確認してください。
ステップ 3:ポートの競合を突き止める
時として、迷い込んだ設定ファイルが、ドメインブロックに到達する前にポート443のトラフィックを「盗んで」しまうことがあります。これは、最近サイトを移行したりホスト名を変更したりした場合によく起こります。grepを使用して、設定ディレクトリ内のポート443のすべてのインスタンスをスキャンしてください:
# Nginxの場合
grep -r "443" /etc/nginx/
# Apacheの場合
grep -r "443" /etc/apache2/
default や 000-default ファイルを探してください。これらが有効な証明書なしで443ポートをリスニングしている場合、TLSトラフィックのブラックホールとして機能してしまいます。
「厳格な」SNI設定
高度なNginx設定では、しばしば ssl_reject_handshake on; が使用されます。これは、既知の server_name に一致しない接続をすべて遮断する強力なセキュリティ機能です。IPベースのスキャンを防ぐ一方で、設定にわずかなタイポ(打ち間違い)があるだけでも SSL_ERROR_UNRECOGNIZED_NAME_ALERT が不可避になります。
この拒否ルールが適用される前に、ドメインブロックがロードされ、アクティブであることを再確認してください。
検証:修正をテストする方法
ブラウザは強力なキャッシュを行うことで知られています。サーバーが実際に何を行っているかを確認するには、コマンドラインを使用しましょう。
OpenSSLを使用する
このコマンドは、SNIの問題をテストするための標準的な方法です。ハンドシェイク中にブラウザが行う動作を正確にシミュレートします:
openssl s_client -connect example.com:443 -servername example.com
ここでの決め手は -servername フラグです。これがSNIヘッダーを送信します。出力に Verification: OK と表示されているか確認し、Certificate chain が実際に自分のドメインのものであることを確認してください。ここで「unrecognized name」エラーが表示される場合は、サーバー側の設定がまだ壊れています。
Curlを使用する
より迅速で大まかな確認には、curlのverboseモードを使用します:
curl -Iv https://example.com
SSL connection using TLSv1.3 のような、接続成功を示す行を探してください。curlがホスト名について文句を言わずに接続できれば、パズルは解けたことになります。
まとめチェックリスト
- `server_name` (Nginx) や `ServerName` (Apache) はURLと正確に一致していますか?
- ルートドメインと `www` サブドメインの両方が含まれていますか?
- サービスを再起動しましたか? `systemctl restart nginx` または `apache2` を使用してください。
- デフォルトの設定ブロックがポート443のリクエストを横取りしていませんか?
- `.pem` や `.crt` ファイルのパスは有効で、ウェブサーバーから読み取り可能ですか?

