Server Name Indication (SNI 、サーバー ネーム インディケーション、サーバ名表示)は、SSL /TLS の拡張仕様の一つである。SSLハンドシェイク時にクライアントがアクセスしたいホスト名 を伝えることで、サーバ側がグローバルIP ごとではなくホスト名 によって異なる証明書 を使い分けることを可能にする。
SNIは特に、HTTP 1.1 の名前ベースバーチャルホスト をHTTPS に対応させるために使われる。SNIを機能させるには、Webサーバ 側とブラウザ 側両面の対応が必要である。SNIを実装しないブラウザでは全てのホスト名で同じサーバ証明書が使われるため、警告が表示されることがある。2016年時点でPC・モバイルの主要なブラウザで問題なく利用できる状況である。
問題の背景
SSL/TLS 接続のはじめに、クライアントはSSL/TLSのサーバから(サーバとCAの)証明書 を受け取り、証明書の改ざんされていないことなどを確認する。サーバ証明書にはホスト名が書かれており、それが今接続しようとしているホスト名と一致することをクライアントは確認する。そうでない場合、なりすましや中間者攻撃 の恐れがあるため、クライアントはユーザに警告をする。ユーザの責任で証明書を信用し、警告を迂回することができるアプリケーションも存在する。
HTTPの場合、名前ベースバーチャルホスト を使うと、複数のホスト名(同一のドメインであれ、異なるドメインであれ)を単一のサーバと単一のグローバルIP で運用できる。これは、ブラウザ側がHTTPヘッダ によって希望のホスト名を指定することで働く。しかし、HTTPS の場合、HTTP 要求をやりとりする前にSSL/TLSハンドシェイクを行う必要がある。このため、ブラウザがどのホストを訪問するかを、ハンドシェイク時点でサーバ側には予測できず、HTTPヘッダのホスト名によって複数枚のサーバ証明書を使い分けることができない。したがって、単一のサーバで複数枚のサーバ証明書を使い分けるには名前ベースバーチャルホストは利用できず、ホスト名ごとに異なるグローバルIPを使う必要があった(IPベースバーチャルホスト )。
この問題への対処方法として、1枚のサーバ証明書に複数のホスト名を指定する手段が知られていた。X.509 v3の証明書で導入されたsubjectAltName 拡張を利用することで、追加のホスト名を指定できる。通常、主体者のCommon Name属性同様、こちらでもワイルドカード を使える。しかし、実運用においてサーバの運用する全てのホスト名を予めCSR に含めておくことは現実的ではなく、ホスト(ワイルドカードの場合、ドメイン)名が増えるたびに別々にサーバ証明書を導入することが多い。2005年から、CAcert はTLSをバーチャルホスト下で使う方法について様々な実験を行なった[ 1] が、多くは非実用的なものだった。例えば、subjectAltName 拡張を使って運用する全ドメインのホスト名を1枚のサーバ証明書に集約し、ドメインが増えたりドメイン名が変わったりするごとに取得しなおすという方法[ 2] が提案された。
これらの事情によって、複数のサーバ証明書を使い分けたいサーバは、単数または少数のホスト名をIP別に運用することが要求される。ホスト(ワイルドカードの場合、ドメイン)名ごとに別のグローバルIPを取得することはコストがかかる(IPアドレス枯渇問題 )ため、多くのWebサイトにはHTTPS通信の利用はハードルが高かった。
SNIによる解決
Server Name Indication (SNI)では、TLS に拡張を加えることでこの問題に対処する。TLS のハンドシェイク手続きで、HTTPSクライアントが希望するドメイン名を伝える(この部分は平文となる)[ 3] 。それによってサーバが対応するドメイン名を記した証明書を使うことが可能になる。サーバとクライアントが共にSNIに対応していれば、一つのIPで複数のドメインにHTTPS サーバを提供することが可能になる。
SNIは2003年6月、RFC 3546 「TLS拡張仕様」に加わった。その後更新され、2014年1月現在、SNIの記述のある最新の仕様はRFC 6066 (日本語訳 ) である。
SNIの暗号化
SNIも暗号化する方法が検討されている。当初、Encrypted SNI (ESNI)が検討されていたものの、その後Encrypted Client Hello (ECH)が考案され、標準化に向けた検討が進められている[ 4] 。
対応状況
SNIに対応するには、アプリケーションの使うSSL ライブラリがホスト名を受け取る仕組みが必要である。OS の機能を利用してSSL通信を行うアプリケーションでは、OSのSSL機能がSNIをサポートしない場合はSNIを使うことはできない。2011年の時点でほとんどのブラウザやSSLライブラリはSNIを実装したが、ユーザの使うOSとの組み合わせによってはSNIを利用できない場合がしばしばある。
対応ソフト
2004年に、OpenSSL でTLS /SNIをサポートするパッチがEdelKeyプロジェクトによって作成された[ 5] 。このパッチは2006年開発ブランチに取り込まれ、2007年にOpenSSL 0.9.8にポートされた。
TLS/SNIをサポートするブラウザ[ 6]
Webサーバ
ライブラリ
非対応ソフト
以下の組み合わせのソフトウェアはSNIに対応していない。
クライアント
サーバ
ライブラリ
Qt 4.7[ 32]
Mozilla Network Security Services server side [ 43]
Java 1.6 およびそれ以前 [ 33]
Apache HttpComponents 4.3.1 およびそれ以前 [ 34]
Python 2.x (ssl
, urllib[2]
, httplib
モジュール) [ 31]
PhantomJS 1.x
脚注
関連項目
外部リンク