SNIでサーバ上に複数のSSLサイトを設定する

2017年3月8日

SNI(Server Name Indication)は、従来IPアドレス1つに対して、SSLサイトが1つしか
運用できなかったものを、複数運用するための規格です。

SSLサイトは、ネゴシエーション前に接続先ホストが決まっているため、バーチャルホスト
で複数サイトを運用することができませんでした。

SNIでは、SSLネゴシエーション時に接続先ホストを通知し、そのホストに対する証明書を
やり取りすることで、1つのIPアドレスで複数のSSLサイトを運用することができます。

ただし、ブラウザがSNIに対応している必要があります。ガラケーは全滅ですが、現在の
モダンブラウザであればすべて対応済みです。

SNIで1台のサーバ上に複数のSSLサイトを運用 – 前編

Apacheでは、以下のように設定します。
通常のバーチャルホストのSSL版といったところでしょうか。
SSLStrictSNIVHostCheck off はSNIに対応していないブラウザにエラーを返さず、最初に定義されたSSLサイトを応答するための設定です。

SSLサイト A:a.example.com
SSLサイト B:b.example.net

NameVirtualHost *:443
SSLStrictSNIVHostCheck off

<VirtualHost *:443>
    ServerName a.example.com
    DocumentRoot "/var/www/a.example.com/html"
    SSLEngine on
    SSLCertificateFile /var/www/conf/a.example.com.crt
    SSLCertificateKeyFile /var/www/conf/a.example.com.key
</VirtualHost>

<VirtualHost *:443>
    ServerName b.example.net
    DocumentRoot "/var/www/b.example.net/html"
    SSLEngine on
    SSLCertificateFile /var/www/conf/b.example.net.crt
    SSLCertificateKeyFile /var/www/conf/b.example.net.key
</VirtualHost>

確認のため、b.example.netの証明書が確認できるかテストします。
opensslクライアントの-servername で b.example.net を指定します。
コモンネーム CN にb.example.netが確認できます。

$ echo -en 'GET / HTTP/1.1\nHost: b.example.net\n\n' | openssl s_client -connect b.example.net:443 -servername b.example.net
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = b.example.net
verify return:1
---
Certificate chain
 0 s:/CN=b.example.net
   i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
 1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
   i:/O=Digital Signature Trust Co./CN=DST Root CA X3
以下省略