[9] [[TLS]] の [DFN[[[SNI]]]] は、[[クライアント]]が[[サーバー]]に対して接続中の[[サーバー]]の名前を知らせるものです。
[[バーチャルホスト]] (単一の[[ネットワークアドレス]]によって複数の名前の[[ホスト]]を提供するもの) の実装のために必要です。

[25] [[SNI]] は [[TLS拡張]]であり、仕様上は必須とはされていません。近年 [[SNI]]
による [[HTTPS]] [[バーチャルホスト]]が普及してきており、[[クライアント]]は事実上 [[SNI]]
への対応が必要です。 [[SNI]] に対応しない [[HTTPS]] [[クライアント]]は
[[Web互換]]ではありません。

* 仕様書

[REFS[
- [7] [CITE@en[RFC 6066 - Transport Layer Security (TLS) Extensions: Extension Definitions]] ([TIME[2015-02-01 18:07:52 +09:00]] 版) <http://tools.ietf.org/html/rfc6066>
-- [8] '''[CITE@en[RFC 6066 - Transport Layer Security (TLS) Extensions: Extension Definitions]] ([TIME[2015-02-01 18:07:52 +09:00]] 版) <http://tools.ietf.org/html/rfc6066#section-3>'''
-- [26] [CITE@en[RFC 6066 - Transport Layer Security (TLS) Extensions: Extension Definitions]] ([TIME[2015-02-01 18:07:52 +09:00]] 版) <http://tools.ietf.org/html/rfc6066#section-11.1>
]REFS]

* プロトコル

[10] [[クライアント]]は、 [CODE[[[ClientHello]]]] の [[TLS拡張]]
[DFN[[CODE[[[server_name]]]]]] に[[サーバー]]の名前を指定できます [SRC[>>8]]。
[[クライアント]]は、対応している種類の名前の[[サーバー]]に接続する時は
[CODE[[[server_name]]]] を指定する[['''べきです''']] [SRC[>>18]]。

[12] [[サーバー]]は、 [[SNI]] に対応していて、かつ指定された[[サーバー]]名を認識できないなら、
[CODE[[[unrecognized_name]]]] ([CODE[[[112]]]]) [[fatal alert]]
を送信するか、[[ハンドシェイク]]を継続するかのいずれかとする[['''べきです''']] [SRC[>>18]]。

;; [34] [[Apache]] も www.google.com, www.yahoo.com, github.com, herokuapp.com
のいずれも、 [[SNI]] でおかしな値を指定しても、
エラーや警告とはせず、同じ値を送り返してきます。
([[HTTP応答]]には [CODE(HTTP)@en[[[Host:]]]] の値を使い、 [[SNI]]
で指定された値は無視しているようです。) [TIME[2015-09-06T16:06:50.000Z]]

;; [35] [[CloudFlare]] は [[SNI]] でおかしな値を指定すると
[CODE[[[internal_error]]]] [[fatal alert]] とします。
(>>34 は[[サーバー]]側で [[SNI]] により分岐していないと思われます。
[[CloudFlare]] は [[SNI]] により[[証明書]]の選択を行っているようです。) [TIME[2015-09-06T16:09:34.00Z]]

[20] [[サーバー]]は、 [CODE[[[ClientHello]]]] に [CODE[[[server_name]]]]
が含まれている場合、これを使って適切な[[証明書]]を選択して[[クライアント]]に送信したり、
その他[[セキュリティー]]に関わる選択を行ったりして構いません。その場合
[CODE[[[ServerHello]]]] に [CODE[[[server_name]]]] [[TLS拡張]]を含めなければ[['''なりません''']]。その際 [CODE[[[extension_data]]]] は空としなければ[['''なりません''']]。
[SRC[>>18]]

[13] [[クライアント]]の指定した[[サーバー]]名と[[サーバー]]が選んだ[[サーバー]]名が一致しない場合、
[[クライアント]]が server endpoint identification する際に違いが判明するはずなので、
[[クライアント]]はその時通信を続けるかどうかを決めることになります [SRC[>>18]]。

[29] [[SNI]] の[[拡張データ]]は、 [DFN[[CODE[[[ServerNameList]]]]]] 型の欄
[CODE[[[server_name_list]]]] です [SRC[>>18]]。
すなわち、[[16ビット符号無し整数]] ([[ネットワークバイト順]]) と、
その値が長さである1バイト以上2[SUP[16]]-1バイト以下の[[バイト列]]として表された
[CODE[[[ServerName]]]] のリストです [SRC[>>18]]。

[FIG(packet)[
:width:16

= 2 長さ
= 14... [CODE[[[ServerName]]]] の列
]FIG]

[38] [[IPアドレス]]その他、[[ドメイン名]]以外の[[ホスト]]の指定方法は用意されていません。

* サーバー名

[31] [DFN[[CODE[[[ServerName]]]]]] は、名前の種類を表す [CODE[[[name_type]]]]
欄と、実際の名前を表す [CODE[[[name]]]] 欄で構成されます [SRC[>>18]]。

[14] [DFN[[CODE[[[name_type]]]]]] 欄の値は[[列挙型]] [DFN[[CODE[[[NameType]]]]]]
ですが、現在 [[DNSホスト名]] ([DFN[[CODE[[[host_name]]]]]] = [DFN[[CODE[[[0]]]]]]) 
のみ対応しています [SRC[>>18]]。1バイトで表されます [SRC[>>18]]。

[15] [DFN[[CODE[[[name]]]]]] [[欄]]の値は [CODE[[[HostName]]]]
型です。 [DFN[[CODE[[[HostName]]]]]] 型は、
[[16ビット符号無し整数]] ([[ネットワークバイト順]]) と、
その値が長さである1バイト以上2[SUP[16]]-1[[バイト]]以下の[[バイト列]]です [SRC[>>18]]。

[FIG(packet)[
:width:16:

= 1 [CODE[[[0]]]]
= 2 長さ
= 13... 名前
]FIG]

[17] [[DNSホスト名]]は、 [[DNS]] [[FQDN]] を、
[[末尾の[CODE[.]]]] を''付けず''に
[[ASCII]] [[バイト列]]として表現したものです [SRC[>>18]]。
[[IPアドレス]]を指定してはなりません [SRC[>>18]]。

;; [18] [[IDN]] は[[Aラベル]]で表現します [SRC[>>18]]。

[19] [[DNSホスト名]]の[[比較]]は、[[IDNA2008ラベル等価性]]によります [SRC[>>18]]。

[11] [[サーバー]]の名前は複数指定できますが、同じ [CODE[[[name_type]]]]
の名前が複数あっては[['''なりません''']] [SRC[>>18]]。

;; [30] 複数の指定を[[サーバー]]がどう解釈するべきかは定かではありません。

[32] [[Firefox]] も [[Chrome]] も [[IE]] も、[[末尾の点]]がついた[[ホスト名]]が [[URL]]
で指定された時は、 [[SNI]] にも[[末尾の点]]がついた[[ホスト名]]を記載するようです。 [TIME[2015-08-22T09:59:44.00Z]]

[42] [[Firefox]] も [[Chrome]] も、 [[IPアドレス]]の [[URL]]
の時は、 [[SNI]] を使いません (使えません)。 [TIME[2016-05-08T04:47:30.700Z]]

* 応用プロトコルとの関係

[21] [[アプリケーションプロトコル]]が[[サーバー]]名の折衝を行ってから [[TLS]]
に切り替えた場合で [[SNI]] を使う場合には、[[アプリケーションプロトコル]]で折衝したのと同じ[[サーバー]]名を指定する[['''べきです''']]。 [SRC[>>18]]

[22] [[SNI]] で[[サーバー]]名を確立した場合には、[[クライアント]]は
[[TLS]] 上の[[アプリケーションプロトコル]]で別の[[サーバー]]名を要求しようと試みる[['''べきではありません''']]。
[SRC[>>18]]

[23] [[アプリケーションプロトコル]]は、 [[SNI]] による[[サーバー]]名と[[アプリケーションプロトコル]]内で指定する[[プロトコル]]が異なる際にどう処理するか規定する必要があります。

;; [24] [[HTTP]] については[[実効要求URL]]を参照。

[27] [[サーバー]]の実装は、両者が一致することを前提にしている場合、一致しているか検査しなければ[['''なりません''']] [SRC[>>26]]。

[36] [[再折衝]]が行われる場合、その [CODE(HTTP)@en[[[ClientHello]]]]
にも [[SNI]] が含められます。普通は最初の [[SNI]] と同じ値にします。
異なる値を指定した時にどう扱われるのかは定かではありません。

[EG[
[37] 例えば [[HTTP応答]]の途中で[[再折衝]]が発生し[[クライアント]]が [[SNI]]
で異なる[[ホスト名]]を送信してくるとしたら穏やかではありません。
]EG]

[41] 次の[[プロトコル]]は、 [[SNI]] への対応を要求しています。
[FIG(short list)[
- [[WebSocket]]
- [[HTTP/2]]
- [[代替サービス]]
]FIG]

;; [40] 更に、明文規定こそありませんが、
[[HTTP/1]] over [[TLS]] も [[SNI]] への対応が必要です。

* 歴史

[1] [CITE@ja[ウェブブラウザのSNI対応 | dodaの日記 | スラッシュドット・ジャパン]]
( ([TIME[2013-08-01 07:24:13 +09:00]] 版))
<http://slashdot.jp/journal/495893/%E3%82%A6%E3%82%A7%E3%83%96%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%AESNI%E5%AF%BE%E5%BF%9C>

[2] [CITE@ja[Server Name Indication - Wikipedia]]
( ([TIME[2013-07-25 06:12:14 +09:00]] 版))
<http://ja.wikipedia.org/wiki/Server_Name_Indication>

[3] [CITE@ja[AndroidにおけるSNI対応状況 - さくらのナレッジ]]
( ([TIME[2014-08-07 14:44:32 +09:00]] 版))
<http://knowledge.sakura.ad.jp/tech/1706/>

[4] [CITE@en[Bug 909604 – wget: Missing support for SNI (Server Name Indication)]]
( ([TIME[2014-09-18 07:40:21 +09:00]] 版))
<https://bugzilla.redhat.com/show_bug.cgi?id=909604>

[5] [CITE[#653267 - wget: Please include SNI patch - Debian Bug report logs]]
( ([TIME[2013-06-03 08:52:03 +09:00]] 版))
<https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=653267>

[6] [CITE@ja-JP[GNU Wget - バグ: bug #26786, TLS SNI support ''''''[''''''Savannah'''''']'''''']]
( ([[Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved]] 著, [TIME[2014-09-18 07:42:39 +09:00]] 版))
<http://savannah.gnu.org/bugs/?26786>

[FIG(quote)[
[FIGCAPTION[
[28] [CITE@en[RFC 7525 - Recommendations for Secure Use of Transport Layer Security (TLS) and Datagram Transport Layer Security (DTLS)]]
([TIME[2015-05-29 03:22:56 +09:00]] 版)
<https://tools.ietf.org/html/rfc7525#section-3.6>
]FIGCAPTION]

> TLS implementations MUST support the Server Name Indication (SNI)
>    extension defined in Section 3 of '''['''RFC6066''']''' for those higher-level
>    protocols that would benefit from it, including HTTPS.  However, the
>    actual use of SNI in particular circumstances is a matter of local
>    policy.

]FIG]


[FIG(quote)[
[FIGCAPTION[
[33] [CITE@en[RFC 7590 - Use of Transport Layer Security (TLS) in the Extensible Messaging and Presence Protocol (XMPP)]]
([TIME[2015-06-20 11:06:39 +09:00]] 版)
<https://tools.ietf.org/html/rfc7590#section-3.5>
]FIGCAPTION]

> Although there is no harm in supporting the TLS Server Name
>    Indication (SNI) extension '''['''RFC6066''']''', this is not necessary since the
>    same function is served in XMPP by the 'to' address of the initial
>    stream header as explained in Section 4.7.2 of '''['''RFC6120''']'''.

]FIG]


[39] [CITE[The CPAN Search Site - search.cpan.org]]
([TIME[2016-02-01 16:04:38 +09:00]] 版)
<http://search.cpan.org/diff?from=AnyEvent-7.11&to=AnyEvent-7.12>



[43] [CITE@ja[韓国でSNIフィールドを使った特定サイトの接続遮断が始まる | スラド IT]]
([TIME[2019-02-13 18:51:51 +09:00]])
<https://it.srad.jp/story/19/02/13/0735240/>

[44] [CITE@ja[中国政府、TLS 1.3とESNIを使用するすべての暗号化されたHTTPSトラフィックをブロック中 | スラド YRO]]
([TIME[2020-08-13 18:35:07 +09:00]])
<https://yro.srad.jp/story/20/08/12/1642231/>