明滅するプログラマの思索

WEBエンジニアとして勤務している一介の男が、日々気づいたことをまとめるブログです

Client aborts on SNI unrecognized_name warning の サーバ側での対処

1つの Web サーバで複数の SSL サイトを運用する際、SNI(Server Name Indication)という拡張仕様を利用することが一般的になっています。
名前ベースで SSL のバーチャルホストを管理するということなのですが Apache では2.2.12以降において設定が可能となりました。
現在ではほとんどのクライアントが SNI 対応済みとなっています。

Java1.7 以降で実装したクライアントにおいて、SNI の設定にミスがある Web サーバへリクエストを行った際、タイトルのエラーが出力されることがあります。
今回は上記エラーが Apache の設定ミスにより発生した場合の対処を記載します。

SSL ハンドシェイク

SNI を利用して SSL 通信を行う場合、クライアントは対象サーバが正規の SSL 証明書を所持しているかを確認するため、SSL ハンドシェイクと呼ばれる通信を行います。
Web サーバは SSL ハンドシェイクのリクエストを受け取ると、SSLのバージョンや暗号方式、セッション固有のデータ、そして証明書という、その後の通信に必要な情報を返却します。
ここでクライアント側の Web サーバ側への SSL ハンドシェイクのリクエストがドメイン名を指定しない設計になっていると、Webサーバ側はどの SSL 証明書を返却すればよいかの指示がないため、デフォルトで設定されている情報を返却することになります。
ここで問題になってくるのが、VirtualHost ディレクティブに _default_ のものが残っていて、かつ有効な証明書が設定されている ServerName でない場合、Client aborts on SNI unrecognized_name warning というエラーを受け取ることになります。
この状況は、以下のコマンドを実行することで確認できます。

$ openssl s_client -connect www.webserver.com:443 -showcerts < /dev/null 2>&1 | grep subject
subject=/C=--/ST=SomeState/L=SomeCity/O=SomeOrganization/OU=SomeOrganizationalUnit/CN=example.com/emailAddress=root@example.com
# レスポンスに含まれる CN=ホスト が 有効な SSL 認証局のものでない

デフォルトの VirtualHost ディレクティブが残っているのが原因

つまり、Web サーバの デフォルトの SSL ホストが正しい SSL 証明書を持っていないことが原因。
したがって、

<VirtualHost _default_:443>
・
・
・
</VirtualHost>

が設定されている場合、削除します。
Apache は _default_ の VirtualHost ディレクティブが設定されていない場合、一番最初に記述されている VirtualHost をデフォルトとするからです。
もしくは、_default_ の VirtualHost ディレクティブに、有効な SSL 証明書と ServerName を指定することでも対応できます。
上記設定を見直すことで、Web サーバのデフォルトの SSL 証明書が正しいものになるため、エラーを回避できるようになります。