RFC 7301

ALPN (TLS)

[7] ALPN は、アプリケーション層プロトコル折衝を行う TLS拡張です。 TLS 上で利用するアプリケーション層プロトコルを選択するために使うことができます。

[9] サーバーが同じ TCP ポート上で TLS を介して複数のアプリケーション層プロトコルの通信を受け付けている場合に、 そのいずれを用いるかを決定するために使います。

[70] HTTP/2 に対応したクライアントサーバーは、 HTTP/1.1HTTP/2 のどちらを使うか決定するために ALPN を使っています。

仕様書

意味

[71] ALPN は、 TLS 上で使うプロトコルについてクライアントが候補を提示し、 サーバーがその中のいずれかを選ぶことにより、折衝するものです。

[72] ALPN は、対応が必須ではないTLS拡張です。 TLS の実装は必ずしも ALPN に対応する必要はありません。しかし HTTP/2 のように TLS 上で使うプロトコルによっては ALPN への対応が必要となることがあります。従って実用上汎用的な TLS の実装は ALPN にも対応する必要があります。

構文

[18] TLS拡張型は、 application_layer_protocol_negotiation (16) です >>4

[20] ClientHello および ServerHello における拡張データは、 ProtocolNameList でなければなりません >>4

[21] ProtocolNameList は、 2バイト以上216-1バイト以下で構成される欄 protocol_name_list であり、 ProtocolName のリストです。 >>4

width
16
  1. 2 長さ
  2. 14... ProtocolName の列

[23] クライアントProtocolNameList は、クライアント広告するプロトコルのリストを、 優先度の降順で示したものです。 >>4

[29] サーバーProtocolNameList は、プロトコルを1つだけ含まなければなりません >>4

[22] ProtocolName は、1バイト以上28-1バイト以下バイト列です >>4

width
16
  1. 1 長さ
  2. 15... プロトコル名

[24] ProtocolName は、 IANA に登録された不透明のバイト列です >>4

[45] 現実には登録されていない値も使われています。

文脈

[19] TLSクライアントは、 ClientHello で本 TLS拡張を使うことができます >>4

[35] TLSサーバーは、 ClientHello での指定に対して ServerHello で本 TLS拡張を使うことができます >>4

[36] ClientHelloALPN が使われなかった場合に使って良いのかは謎です。

[38] なお ALPN折衝時に使われるので、プロトコル平文でやりとりされます。 プロトコルを隠す必要があるなら、接続確立後に再折衝するなど対策が必要です >>4

[39] ALPN は、 HTTP/2 を利用する際に使われています。

HTTPS を参照。

[40] ALPN によりクライアントが指定するプロトコルのリストは、 fingerprinting vector です。

処理

[25] サーバーは、 ClientHelloALPN を受信したら、 適当なプロトコルを選択して、 ServerHelloALPN TLS拡張によって含めて構いません。 >>4

[30] ALPNTLSセッションではなく接続の特性であり、 セッション再開セッションチケットを使う場合でも、 以前の ALPN 折衝結果は影響しません >>4

[31] サーバーは、対応するプロトコルの一覧を保持しておき、 その中でクライアントが対応しているプロトコルのみを選ぶことが期待されています。 その場合には、クライアント広告したプロトコルの中でサーバーが最も好ましいと考えるものを選ぶべきです。 >>4

[26] サーバーは、認識しないプロトコル名は無視します。 >>4

[34] サーバーServerHelloALPN 拡張で示したプロトコルは (再折衝まで) 当該接続definitive なものでなければなりませんサーバーは示したプロトコルと異なるものを使ってはなりません>>4

[37] サーバーでプロトコル選択を行うため、サーバー証明書の選択や接続rerouting を必要に応じて行えます >>4

[32] サーバーは、クライアント広告したプロトコルのいずれも対応していない場合は、 no_application_protocol fatal alert を返すべきです >>4

[33] alertIANA登録簿にはなぜかこの値は掲載されていません。

[78] サーバーは、クライアントが指定したプロトコルの中から自身が対応しているものを1つ選択することが期待されています。 しかしクライアントが指定しなかったプロトコルを指定することも、 できなくはありません。クライアントはそれをエラーとして扱うべきと思われますが、 実際には対処方法は色々なようです。

[79] Webブラウザーによっては、 http/1.1 のみを指定したにも関わらずサーバーh2 を返してきた時、 HTTP/2 を使うことがあります。

[73] なお、 ALPN に対応していないサーバーは、クライアントALPN を指定したとしても無視します。その場合クライアントがどうするべきかは、 プロトコルに依存します。

[74] 旧来の HTTPSサーバーALPN に対応していませんでした。 ALPN 対応の HTTPS クライアントは常に http/1.1http/2ALPN で指定するので、 ALPN 対応のサーバーはどちらかを選ぶことになります。 ALPN 未対応のサーバーは、 ALPN の有無に関わらず昔ながらの動作、すなわち http/1.1 相当の動作をすることになります。

プロトコル名

[10] プロトコル名としては、通常は名前を UTF-8符号化したバイト列を使うこととなっています。

[11] IANA登録簿 (>>5) があります。

[12] 次の値が使われています。

[80] ALPNプロトコル名は、次の場面で使われます。

[82] 代替サービスでは、特に規定がない限り、当該プロトコルTLS 上で利用することを意味する >>81 とされています。

ALPN: ヘッダー (HTTP)

[54] HTTPALPN: ヘッダーは、 CONNECT トンネル内のプロトコルヒントを示すものです。

意味

[55] クライアントCONNECT 要求により確立するトンネル内で使うプロトコル(群)を示すものです >>53

[57] 複数あり得る時は、すべてを示します >>53

[58] このヘッダークライアントの意思を示すためだけのものであり、 折衝に使うことを目的とはしていません >>53

[75] ヘッダー名から分かる通り TLS拡張ALPN の強い影響下にあり、 併用するものとして設計されてはいますが、両者が連動するわけではありません。

構文

[61] ALPN: ヘッダーの値は、 1つ以上の値のリスト (#) です >>53

  1. *
    1. OWS
    2. ,
    3. OWS

[60] 値は、 ALPNプロトコル識別子を使います >>53。 ただし HTTP字句で表せないオクテットおよび % は、 RFC 3986 パーセント符号化しなければなりません >>53。 それ以外の字句で表せるオクテットは、パーセント符号化してはなりません >>53パーセント符号化十六進数は、大文字でなければなりません >>53

[62] 値の大文字と小文字は、区別されます。

[56] トンネル内で TLS を使う時は、 TLS handshakeClientHelloALPN によって示すプロトコルのリストと同じものとします >>53

[63] TLS を使わない場合など折衝しないと思われる場合は、 利用するプロトコルを1つ指定します。その他何らかの方法で折衝できる場合は、 折衝対象のプロトコルを指定します。 >>53

文脈

[66] CONNECT 要求で指定できます。 このヘッダーは必須ではありません >>53

[68] このヘッダーは、fingerprinting vector です。 機密や繊細な情報を晒してしまうことになるときは、 送信するべきではありません >>53

[76] CONNECT 以外での利用について何の規定もありませんが (それが IETF クオリティー)、 CONNECT 以外では意味をなしません。

処理

[59] プロキシは、示されたプロトコルを見てトンネルの拒絶や優先度制御、 その他の決定を行うことができます >>53

[64] しかし ALPN: ヘッダーの値が正しいとは限らないので、 アクセス制御に直ちに用いられるわけではありません >>53

[65] プロキシは、トンネルのプロトコルを認識できなかったというだけの理由でトンネルを切断するべきではありません >>53

関連

[17] HTTPS も参照。

歴史

NPN

[42] 13172 (next_protocol_negotiation)

[1] draft-agl-tls-nextprotoneg-00 - Transport Layer Security (TLS) Next Protocol Negotiation Extension ( 版) <http://tools.ietf.org/html/draft-agl-tls-nextprotoneg>

[2] HTML5 Revision Tracker ( 版) <http://html5.org/tools/web-apps-tracker?from=5287&to=5288>

[3] HTML5 Revision Tracker ( 版) <http://html5.org/tools/web-apps-tracker?from=5288&to=5289>

[6] >>2, >>3 この Web SocketNPN 対応、IETF に移管された後いつの間にか消えてなくなったようですね。。。 Web SocketHTTP から移行するモードで独立したプロトコルではない、 というのが IETF の主張だからなのでしょうか。

[43] FirefoxChrome も、まだ ClientHelloNPN を含めています。

[44] 廃案になったためか、実際に使われている値であるにも関わらず、 IANA登録簿には掲載されていません。

ALPN

[8] ALPNHTTP/2 のために IETF HTTPbis WG からの要求で開発されました >>4

[13] SPDY - OpenSSL の ALPN/NPN API の使い方 - Qiita ( ( 版)) <http://qiita.com/tatsuhiro-t/items/dea3fb279ad265681049>

[14] 1047698 – ALPN advertisment order may be wrong ( 版) <https://bugzilla.mozilla.org/show_bug.cgi?id=1047698>

[15] Chromium Blog: Hello HTTP/2, Goodbye SPDY ( ( 版)) <http://blog.chromium.org/2015/02/hello-http2-goodbye-spdy-http-is_9.html>

[16] RFC 7443 - Application-Layer Protocol Negotiation (ALPN) Labels for Session Traversal Utilities for NAT (STUN) Usages ( 版) <https://tools.ietf.org/html/rfc7443>

[46] 861266 – Implement TLS 1.2 (RFC 5246) in Gecko (Firefox, Thunderbird), on by default ( 版) <https://bugzilla.mozilla.org/show_bug.cgi?id=861266>

[47] 996238 – ALPN identifiers for WebRTC ( 版) <https://bugzilla.mozilla.org/show_bug.cgi?id=996238>

[48] 959664 – Add ALPN (RFC 7301) support to NSS ( 版) <https://bugzilla.mozilla.org/show_bug.cgi?id=959664>

[49] 1047698 – ALPN advertisment order may be wrong ( 版) <https://bugzilla.mozilla.org/show_bug.cgi?id=1047698>

[51] Issue 497770 - chromium - BoringSSL ALPN callback cannot send SSL ALERT 120 (no application protocol found) - An open-source project to help move the web forward. - Google Project Hosting ( 版) <https://code.google.com/p/chromium/issues/detail?id=497770>

[52] ALPN Status · http2/http2-spec Wiki ( 版) <https://github.com/http2/http2-spec/wiki/ALPN-Status>

Note that some client implementations deal very poorly if a server sends both ALPN and NPN in the ServerHello. When a server responds negotiating a protocol via ALPN in the ServerHello, it must not also send a list of protocols for NPN negotiation as well.

ALPN: ヘッダー

[41] draft-ietf-httpbis-tunnel-protocol-05 - The ALPN HTTP Header Field ( 版) <https://tools.ietf.org/html/draft-ietf-httpbis-tunnel-protocol-05>

[50] 1125292 – Support Tunnel-Protocol for WebRTC ( 版) <https://bugzilla.mozilla.org/show_bug.cgi?id=1125292>

実装

[67] HTTPS において ChromeFirefoxALPN を使って HTTP/1HTTP/2 を選択しています。

HTTPS も参照。

[69] HTTPS のための CONNECT 要求には、 FirefoxChromeALPN: ヘッダーを使わないようです。

[77] 古い OpenSSL では ALPN が使えません。少し古めの OS の標準 OpenSSL パッケージは古い OpenSSL (にパッチを当てたもの) しか提供していないことがあるので、しばらくは注意が必要です。

[83] API Deprecations and Removals in Chrome 51 | Web Updates - Google Developers ( ()) <https://developers.google.com/web/updates/2016/04/chrome-51-deprecations#remove-tls-next-protocol-negotiation-npn>

As part of deprecation of SPDY, NPN is removed, having previously been replaced with ALPN.

[84] Added a link to the ALPN Protocol IDs registry #122 (#125) (plehegar著, ) <https://github.com/w3c/resource-timing/commit/68372fd743899173148227cab10caad3bf762e8c>

[85] NextHopProtocol Values · Issue #122 · w3c/resource-timing () <https://github.com/w3c/resource-timing/issues/122>

[86] Added a link to the ALPN Protocol IDs registry by plehegar · Pull Request #125 · w3c/resource-timing () <https://github.com/w3c/resource-timing/pull/125>

[88] Better registry definition, removed HTTP0.9 and 1.0, made ALPN a MUST (yoavweiss著, ) <https://github.com/w3c/resource-timing/commit/de148c01702782055f4d3309c0c879f0d10d22a5>

[89] Add nextHopProtocol HTTP/0.9 and 1.0. Link to QUIC by yoavweiss · Pull Request #159 · w3c/resource-timing () <https://github.com/w3c/resource-timing/pull/159>