[アップデート] Application Load Balance (ALB) がTLS 1.3をサポートしました

既存のALBのセキュリティポリシーを変更してTLS 1.3でアクセスできるようにしよう
2023.03.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ALBでもTLS 1.3を使いたいな

こんにちは、のんピ(@non____97)です。

皆さんはApplication Load Balance (以降ALB) でもTLS 1.3を使いたいなと思ったことはありますか? 私はあります。

NLBでは一足先にTLS 1.3に対応しています。

本日、ALBでもTLS 1.3がサポートされました。

早速試してみたので紹介します。

追加されたセキュリティポリシーの確認

ALBがTLS 1.3をサポートするにあたって、TLS 1.3を含むセキュリティポリシーがALBでも使用できるようになりました。

  • ELBSecurityPolicy-TLS13-1-2-2021-06
  • ELBSecurityPolicy-TLS13-1-2-Res-2021-06
  • ELBSecurityPolicy-TLS13-1-2-Ext1-2021-06
  • ELBSecurityPolicy-TLS13-1-2-Ext2-2021-06
  • ELBSecurityPolicy-TLS13-1-1-2021-06
  • ELBSecurityPolicy-TLS13-1-0-2021-06
  • ELBSecurityPolicy-TLS13-1-3-2021-06

マネジメントコンソールでリスナー設定時にデフォルトで指定されているものはELBSecurityPolicy-TLS13-1-2-2021-06なので、以降ALBを作成する場合は特に意識しなくてもTLS 1.3で接続できそうです。

$ aws elbv2 describe-ssl-policies --names ELBSecurityPolicy-TLS13-1-2-2021-06 --output table
---------------------------------------------------
|               DescribeSSLPolicies               |
+-------------------------------------------------+
||                  SslPolicies                  ||
|+-----------------------------------------------+|
||                     Name                      ||
|+-----------------------------------------------+|
||  ELBSecurityPolicy-TLS13-1-2-2021-06          ||
|+-----------------------------------------------+|
|||                   Ciphers                   |||
||+--------------------------------+------------+||
|||              Name              | Priority   |||
||+--------------------------------+------------+||
|||  TLS_AES_128_GCM_SHA256        |  1         |||
|||  TLS_AES_256_GCM_SHA384        |  2         |||
|||  TLS_CHACHA20_POLY1305_SHA256  |  3         |||
|||  ECDHE-ECDSA-AES128-GCM-SHA256 |  4         |||
|||  ECDHE-RSA-AES128-GCM-SHA256   |  5         |||
|||  ECDHE-ECDSA-AES128-SHA256     |  6         |||
|||  ECDHE-RSA-AES128-SHA256       |  7         |||
|||  ECDHE-ECDSA-AES256-GCM-SHA384 |  8         |||
|||  ECDHE-RSA-AES256-GCM-SHA384   |  9         |||
|||  ECDHE-ECDSA-AES256-SHA384     |  10        |||
|||  ECDHE-RSA-AES256-SHA384       |  11        |||
||+--------------------------------+------------+||
|||                SslProtocols                 |||
||+---------------------------------------------+||
|||  TLSv1.2                                    |||
|||  TLSv1.3                                    |||
||+---------------------------------------------+||
|||         SupportedLoadBalancerTypes          |||
||+---------------------------------------------+||
|||  application                                |||
|||  network                                    |||
||+---------------------------------------------+||

一方、AWS CLIで作成するリスナーのデフォルトはELBSecurityPolicy-2016-08なので注意が必要です。

$ aws elbv2 describe-ssl-policies --names ELBSecurityPolicy-2016-08 --output table
---------------------------------------------------
|               DescribeSSLPolicies               |
+-------------------------------------------------+
||                  SslPolicies                  ||
|+-----------------------------------------------+|
||                     Name                      ||
|+-----------------------------------------------+|
||  ELBSecurityPolicy-2016-08                    ||
|+-----------------------------------------------+|
|||                   Ciphers                   |||
||+--------------------------------+------------+||
|||              Name              | Priority   |||
||+--------------------------------+------------+||
|||  ECDHE-ECDSA-AES128-GCM-SHA256 |  1         |||
|||  ECDHE-RSA-AES128-GCM-SHA256   |  2         |||
|||  ECDHE-ECDSA-AES128-SHA256     |  3         |||
|||  ECDHE-RSA-AES128-SHA256       |  4         |||
|||  ECDHE-ECDSA-AES128-SHA        |  5         |||
|||  ECDHE-RSA-AES128-SHA          |  6         |||
|||  ECDHE-ECDSA-AES256-GCM-SHA384 |  7         |||
|||  ECDHE-RSA-AES256-GCM-SHA384   |  8         |||
|||  ECDHE-ECDSA-AES256-SHA384     |  9         |||
|||  ECDHE-RSA-AES256-SHA384       |  10        |||
|||  ECDHE-RSA-AES256-SHA          |  11        |||
|||  ECDHE-ECDSA-AES256-SHA        |  12        |||
|||  AES128-GCM-SHA256             |  13        |||
|||  AES128-SHA256                 |  14        |||
|||  AES128-SHA                    |  15        |||
|||  AES256-GCM-SHA384             |  16        |||
|||  AES256-SHA256                 |  17        |||
|||  AES256-SHA                    |  18        |||
||+--------------------------------+------------+||
|||                SslProtocols                 |||
||+---------------------------------------------+||
|||  TLSv1                                      |||
|||  TLSv1.1                                    |||
|||  TLSv1.2                                    |||
||+---------------------------------------------+||
|||         SupportedLoadBalancerTypes          |||
||+---------------------------------------------+||
|||  application                                |||
|||  network                                    |||
||+---------------------------------------------+||

その他のセキュリティポリシーの暗号化アルゴリズムの情報については以下AWS公式ドキュメントをご覧ください。

試してみた

検証環境

実際にALBのセキュリティポリシーでTLS 1.3を含むものを指定して、TLS 1.3の通信ができるか確認してみましょう。

検証環境は以下の通りです。

Application Load Balance (ALB) がTLS 1.3をサポートしました検証環境構成図

検証環境はAWS CDKでデプロイします。使用したコードは以下GitHubリポジトリに保存しています。

お手元で試す場合はzoneNameをよしなにご変更ください。

TLS 1.3で接続

それではTLS 1.3で接続してみます。

curlで作成したALBに対してアクセスすると以下のようになりました。

$ curl -s -v https://alb.non-97.net > /dev/null
*   Trying 54.205.156.154:443...
* Connected to alb.non-97.net (54.205.156.154) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
} [319 bytes data]
* (304) (IN), TLS handshake, Server hello (2):
{ [122 bytes data]
* (304) (IN), TLS handshake, Unknown (8):
{ [19 bytes data]
* (304) (IN), TLS handshake, Certificate (11):
{ [4954 bytes data]
* (304) (IN), TLS handshake, CERT verify (15):
{ [264 bytes data]
* (304) (IN), TLS handshake, Finished (20):
{ [36 bytes data]
* (304) (OUT), TLS handshake, Finished (20):
} [36 bytes data]
* SSL connection using TLSv1.3 / AEAD-AES128-GCM-SHA256
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=alb.non-97.net
*  start date: Mar 23 00:00:00 2023 GMT
*  expire date: Apr 21 23:59:59 2024 GMT
*  subjectAltName: host "alb.non-97.net" matched cert's "alb.non-97.net"
*  issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M02
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* h2h3 [:method: GET]
* h2h3 [:path: /]
* h2h3 [:scheme: https]
* h2h3 [:authority: alb.non-97.net]
* h2h3 [user-agent: curl/7.84.0]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x15c00e400)
> GET / HTTP/2
> Host: alb.non-97.net
> user-agent: curl/7.84.0
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
< date: Thu, 23 Mar 2023 04:14:19 GMT
< content-type: text/html; charset=UTF-8
< content-length: 10
< server: Apache/2.4.55 (Amazon Linux)
< last-modified: Thu, 23 Mar 2023 02:48:19 GMT
< etag: "a-5f7884f287348"
< accept-ranges: bytes
<
{ [10 bytes data]
* Connection #0 to host alb.non-97.net left intact

SSL connection using TLSv1.3 / AEAD-AES128-GCM-SHA256となっていることからTLS 1.3で接続できていることが分かります。

また、INOUTのやり取りから1.5往復でTLSのハンドシェイクができていることが分かります。

S3バケットに出力したALBのアクセスログからもTLS 1.3でアクセスしたことが分かります。

h2 2023-03-23T04:14:19.321902Z app/AlbSt-Alb16-1FLZW7PCK4KF2/73bd7418134d161b 13.231.11.115:16586 10.1.1.83:80 0.000 0.001 0.000 200 200 30 186 "GET https://alb.non-97.net:443/ HTTP/2.0" "curl/7.84.0" TLS_AES_128_GCM_SHA256 TLSv1.3 arn:aws:elasticloadbalancing:us-east-1:<AWSアカウントID>:targetgroup/AlbSta-AlbLi-5GO47GEI6AXG/3bb20115df7fd5fe "Root=1-641bd21b-4b1923d174e29f51336b83f9" "alb.non-97.net" "arn:aws:acm:us-east-1:<AWSアカウントID>:certificate/0584501a-4bd7-4156-a033-9fd7379ef8c9" 0 2023-03-23T04:14:19.320000Z "forward" "-" "-" "10.1.1.83:80" "200" "-" "-"

その際の通信をWiresharkでパケットキャプチャーした結果は以下の通りです。

tls1.3

TLS 1.3となっているパケットはClient HelloとServer Hello、Change Cipher Spec、Application Dataのみですね。Server Hello DoneやClient Key Exchangeは存在していません。

なお、本来であればTLS 1.3はChange Cipher Specは不要ですがミドルボックス互換性のために送信しているようです。

  • The server sends a dummy change_cipher_spec record immediately after its first handshake message. This may either be after a ServerHello or a HelloRetryRequest.

(以下機械翻訳)

  • サーバは、最初のハンドシェイクメッセージの直後にダミーの change_cipher_spec レコードを送信する。 これは、ServerHello または HelloRetryRequest の後のいずれかである。

RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3

また、TLS 1.3なのでClient Helloにkey_shareが含まれていることも分かりますね。

TLS 1.2で接続

比較用にTLS 1.2でも接続してみます。

$ curl -s -v --tls-max 1.2 https://alb.non-97.net > /dev/null
*   Trying 54.205.156.154:443...
* Connected to alb.non-97.net (54.205.156.154) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
*  CAfile: /etc/ssl/cert.pem
*  CApath: none
* (304) (OUT), TLS handshake, Client hello (1):
} [226 bytes data]
* (304) (IN), TLS handshake, Server hello (2):
{ [100 bytes data]
* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [4945 bytes data]
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
{ [300 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [37 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
{ [1 bytes data]
* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=alb.non-97.net
*  start date: Mar 23 00:00:00 2023 GMT
*  expire date: Apr 21 23:59:59 2024 GMT
*  subjectAltName: host "alb.non-97.net" matched cert's "alb.non-97.net"
*  issuer: C=US; O=Amazon; CN=Amazon RSA 2048 M02
*  SSL certificate verify ok.
* Using HTTP2, server supports multiplexing
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* h2h3 [:method: GET]
* h2h3 [:path: /]
* h2h3 [:scheme: https]
* h2h3 [:authority: alb.non-97.net]
* h2h3 [user-agent: curl/7.84.0]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x152813400)
> GET / HTTP/2
> Host: alb.non-97.net
> user-agent: curl/7.84.0
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
< date: Thu, 23 Mar 2023 04:19:22 GMT
< content-type: text/html; charset=UTF-8
< content-length: 10
< server: Apache/2.4.55 (Amazon Linux)
< last-modified: Thu, 23 Mar 2023 02:48:19 GMT
< etag: "a-5f7884f287348"
< accept-ranges: bytes
<
{ [10 bytes data]
* Connection #0 to host alb.non-97.net left intact

SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256となっていることからTLS 1.2で接続していることが分かります。

また、INOUTのやり取りからTLSのハンドシェイクの際に2往復していることが分かります。

S3バケットに出力したALBのアクセスログからもTLS 1.2でアクセスしたことが分かります。

h2 2023-03-23T04:19:22.948513Z app/AlbSt-Alb16-1FLZW7PCK4KF2/73bd7418134d161b 13.231.11.115:55145 10.1.1.83:80 0.000 0.000 0.000 200 200 30 186 "GET https://alb.non-97.net:443/ HTTP/2.0" "curl/7.84.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 arn:aws:elasticloadbalancing:us-east-1:<AWSアカウントID>:targetgroup/AlbSta-AlbLi-5GO47GEI6AXG/3bb20115df7fd5fe "Root=1-641bd34a-680d0b063a9671a10096bd35" "alb.non-97.net" "arn:aws:acm:us-east-1:<AWSアカウントID>:certificate/0584501a-4bd7-4156-a033-9fd7379ef8c9" 0 2023-03-23T04:19:22.947000Z "forward" "-" "-" "10.1.1.83:80" "200" "-" "-"

その際の通信をWiresharkでパケットキャプチャーした結果は以下の通りです。

tls1.2

Server Key ExchangeやServer Hello Doneのパケットが存在していますね。

既存のALBのセキュリティポリシーを変更してTLS 1.3でアクセスできるようにしよう

ALBがTLS 1.3をサポートしたアップデートを紹介しました。

もし、ALBを使われている方はセキュリティポリシーを確認した上で、TLS 1.3でアクセスできるようにすることをご検討ください。

IEを除く主要ブラウザではTLS 1.3を軒並みサポートしています。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!