[アップデート] Network Load Balancer で TLS ALPN がサポートされたので HTTP/2 が可能になりました。
本日のアップデートで Network Load Balancer(NLB)が TLS ALPN(Application-Layer Protocol Negotiation) をサポートするようになりました。
何が嬉しいのか
TLS リスナーで HTTP/2 が利用可能に
これまで NLB の TLS リスナーでは ALPN に対応していなかったため、HTTP/2 で受けることが出来ませんでした。そのため、NLB を介した HTTP/2 通信をするには TLS リスナーではなく TCP リスナーとして NLB を構成する必要がありました。
この場合、NLB は TCP パススルーとしてのみ機能しますので、TLS ネゴシエーションや、TLS の暗号化/復号といった処理は NLB のターゲットとなるサーバー側で行うこととなり、少なからず TLS 通信のための負荷が掛かることになります。
今回、gRPC は試していませんが、従来であれば以下の記事のように TCP リスナーとしてエンドツーエンドでの TLS ネゴシエーションだったところを、NLB の TLS リスナーで対応できるようになるかと思います。
ちなみに ALB の場合は、ALPN に対応していますが、ALB が HTTP/2 を HTTP/1.1 に変換してターゲットグループに流しますので、gRPC などは利用できません。
Application Load Balancer は、HTTPS リスナーに HTTP/2 のネイティブサポートを提供します。1 つの HTTP/2 コネクションで最大 128 のリクエストを並行して送信できます。ロードバランサーは、これらのリクエストを個々の HTTP/1.1 のリクエストに変換し、ターゲットグループの正常なターゲットにこれを分配します。
(引用:Application Load Balancer のリスナー)
TLS リスナーで終端は出来ない!?
今回のアップデートを見たとき、TLS リスナーで終端できるのだろうと思っていたのですが、ALPN ポリシーを利用する場合は、TLS リスナーに加えて TLS ターゲットグループが必須要件となっていますので、ターゲット側でも何らかの証明書が必要なようです。
・Requirements
- TLS listener
- TLS target group
(引用:TLS Listeners for Your Network Load Balancer)
なにわともあれ、HTTP/2 によって従来の HTTP/1.1 に比べて効率的な通信が利用できることに変わりはないですね。
やってみる
事前準備
NLB のターゲットとなる EC2 に証明書を作成しておきます。今回は以下の記事を参考に、自動生成された自己証明書を利用しました。
$ cert -k 18.181.203.233:443 DomainName: 18.181.203.233 IP: 18.181.203.233 Issuer: ip-192-168-0-129.ap-northeast-1.compute.internal NotBefore: 2020-05-28 07:11:04 +0900 JST NotAfter: 2021-06-02 08:51:04 +0900 JST CommonName: ip-192-168-0-129.ap-northeast-1.compute.internal SANs: [ip-192-168-0-129.ap-northeast-1.compute.internal] Error:
ターゲットグループ
ALPN ポリシーでサポートされるターゲットグループグループは TLS のみです。
リスナー
ALPN ポリシーでサポートされるリスナーも TLS のみです。リスナー設定時に、以下のように ALPN ポリシーの設定項目が追加されています。今回は HTTP/2 が優先される HTTP2Preferred
を指定しています。
ALPN ポリシーが有効である場合、ALPN Policy only applies when forwarding to a TLS target group
との警告メッセージが常時でているようです。
確認
それでは curl
コマンドでリクエストを送ってみます。手順は割愛していますが、作成した NLB は http2.marumo.classmethod.info
として Route53 に登録しています。
$ curl -v https://http2.marumo.classmethod.info * Trying 52.194.162.22... * TCP_NODELAY set * Connected to http2.marumo.classmethod.info (52.194.162.22) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/cert.pem CApath: none * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=*.marumo.classmethod.info * start date: Nov 22 00:00:00 2019 GMT * expire date: Dec 22 12:00:00 2020 GMT * subjectAltName: host "http2.marumo.classmethod.info" matched cert's "*.marumo.classmethod.info" * issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon * SSL certificate verify ok. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x7fc488008200) > GET / HTTP/2 > Host: http2.marumo.classmethod.info > User-Agent: curl/7.64.1 > Accept: */* > * Connection state changed (MAX_CONCURRENT_STREAMS == 100)! < HTTP/2 200 < date: Thu, 28 May 2020 03:51:17 GMT < server: Apache/2.4.43 () OpenSSL/1.0.2k-fips < last-modified: Wed, 27 May 2020 21:49:34 GMT < etag: "1b-5a6a8300d4035" < accept-ranges: bytes < content-length: 27 < content-type: text/html; charset=UTF-8 < <html> Classmethod </html> * Connection #0 to host http2.marumo.classmethod.info left intact * Closing connection 0
HTTP/2 で通信されていることが判ります。サーバー側の ssl_access_log
でも "GET / HTTP/2.0"
が確認できます。
101.xx.xx.xx - - [28/May/2020:03:51:17 +0000] "GET / HTTP/2.0" 200 27
ALPN 無効で試す
従来の ALPN 無効に戻した状態でも試してみます。
$ curl --http2 -v https://http2.marumo.classmethod.info * Trying 52.194.162.22... * TCP_NODELAY set * Connected to http2.marumo.classmethod.info (52.194.162.22) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/cert.pem CApath: none * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 * ALPN, server did not agree to a protocol * Server certificate: * subject: CN=*.marumo.classmethod.info * start date: Nov 22 00:00:00 2019 GMT * expire date: Dec 22 12:00:00 2020 GMT * subjectAltName: host "http2.marumo.classmethod.info" matched cert's "*.marumo.classmethod.info" * issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon * SSL certificate verify ok. > GET / HTTP/1.1 > Host: http2.marumo.classmethod.info > User-Agent: curl/7.64.1 > Accept: */* > < HTTP/1.1 200 OK < Date: Thu, 28 May 2020 03:58:08 GMT < Server: Apache/2.4.43 () OpenSSL/1.0.2k-fips < Upgrade: h2,h2c < Connection: Upgrade < Last-Modified: Wed, 27 May 2020 21:49:34 GMT < ETag: "1b-5a6a8300d4035" < Accept-Ranges: bytes < Content-Length: 27 < Content-Type: text/html; charset=UTF-8 < <html> Classmethod </html> * Connection #0 to host http2.marumo.classmethod.info left intact * Closing connection 0
ALPN, server did not agree to a protocol
とされており、HTTP/1.1 の通信になっていることが判ります。ssl_access_log
でも "GET / HTTP/1.1"
が確認できます。
101.xx.xx.xx - - [28/May/2020:03:58:08 +0000] "GET / HTTP/1.1" 200 27
さいごに
今回、TLS ALPN 対応により HTTP/2 の利用が可能となったわけですが、あらためて 「HTTP/2 って?」と考えると「TLS ネゴシエーションや、暗号化/復号、効率的な通信ができるんですよね…」くらいのふわっとした知識しかないことを認識したので、これを機に深堀りしてみようと思います。
その先に来るであろう QUIC なども見据えた HTTP/2 まわりのアップデートなのかな… などと想像するのも楽しいですね。
以上!大阪オフィスの丸毛(@marumo1981)でした!