AWSの環境構築で初めて意識したTLS終端の話
背景
八月頭あたりから、業務で初めて、お客様が利用するアプリケーション環境の構築を行った。元々用意されていたアプリケーションをEC2にデプロイしてお客様に触ってもらうために、AWSのインフラ設計、構築を実施した。 その中で、TLS終端という考え方を初めて学んだので、今回この記事にまとめる。
想定読者
- 業務で初めてAWSインフラの設計を実施する方
- HTTPSについて理解したい方
目次
- HTTPSの基礎
- TLS終端とは何か
- AWSにおける選択肢
- 判断
- まとめ
1. HTTPSの基礎
まずは、HTTPSについておさらいする。 HTTPSとは簡単に言うと、HTTP通信をTLSで暗号化したものである。通常のHTTPは、ブラウザとWebサーバー間を流れるリクエストやレスポンスが暗号化されていないため、そのまま読める形になりえる。そのまま読める形であることの何が問題かというと、「盗聴」と「書き換え」のリスクが発生することである。
- 盗聴について、暗号化されていない状態だとリクエストやレスポンスがそのままの形で第三者に見られる。となると、氏名や住所、パスワードなどの情報が盗まれる可能性が発生する。
- 書き換えについて、攻撃者が通信経路に介入すると、内容を見ることができるだけでなく書き換えることも可能になる。となると、例えば偽サイトへの誘導、不正なJavaScriptを送信するなどのリスクが生じる。 ということで、従来のHTTP通信をTLSで暗号化しようということで、HTTPSプロトコルが生まれた。
TLSについて理解する。 TLSは、インターネットのセキュリティを強化するためのプロトコルである。SSLの開発段階で生まれたプロトコルであり、基本的にはSSLと同列で語られることが多い。詳しい説明は省くが、TLSは以下を実現してくれる。
- 暗号化:転送されるデータを第三者が見れないように暗号化する
- 認証:情報を交換する当事者が本人であることを保証する
- 完全性:データが改竄されていないことを確認する
TLSを利用するにあたり、配信元サーバーにTLS証明書をインストールする必要がある。TLS証明書とは、サーバーがそのドメインの相手であることを証明するためのものである。その証明書には公開鍵が記載されている。ブラウザがアクセスするときにその証明書を受け取り、ブラウザは公開鍵を持つことになる。さらにサーバーは秘密鍵を持つことで、キーペアによる暗号化・復号が実現される。したがって、このTLS証明書がどこで保管されているかが今後重要になってくる。
2. TLS終端とは何か
TLS終端とは、暗号化されているHTTPS通信をHTTP通信に変換する処理のことを指す。つまり、暗号化された通信を復号する場所という理解でよい。 設計において、TLS終端をどこにすべきかは非常に重要である。例えば、ブラウザからWebサーバーへの接続がロードバランサーを経由するとし、ロードバランサーで復号を実施するとする。すると、ブラウザからロードバランサーまでの通信はHTTPSであり暗号化されるが、ロードバランサーからサーバーまでの通信はHTTPで暗号化されない。そのため、その経路間については別の方法でセキュリティを担保する必要がある。
3. AWSにおける選択肢
では、AWSでインフラを構築するにあたり、どのような選択肢があるのかを見ていく。TLS終端を考えるにあたり、以下の3点の場所がどこになるかを考えると理解しやすい。
- 証明書の保存場所
- 秘密鍵の保存場所
- 復号する場所(いわばTLS終端)
1. EC2上のCaddyやnginxがTLS終端をする(ALBなし もしくはNLBでTCPパススルー)
整理すると以下のようになる。
| 項目 | 場所 |
|---|---|
| 証明書の保存場所 | EC2のローカルディスク |
| 秘密鍵の保存場所 | EC2のローカルディスク |
| 復号する場所 | EC2インスタンス(dockerコンテナ)のcaddy, nginxプロセス |
- Caddyはデフォルトで自動HTTPS(Let's Encrypt/ZeroSSLへの自動発行、更新)を行い、証明書と秘密鍵はローカルに保存する。
- nginxは自動発行機能を持たないため、certbot等で取得した証明書をローカルに配置する。
この構成の利点は、Caddyが持つ証明書の取得・更新機能をそのまま利用できることである。ALBを使用しない場合は構成要素が少なくなり、利用料金も抑えやすい。また、ブラウザからEC2上のCaddyまでHTTPS通信を維持できる。一方で、証明書と秘密鍵をEC2側で安全に管理する必要がある。CaddyをDockerコンテナで動かす場合は、コンテナを再作成しても証明書が失われないように保存領域を永続化しなければならない。また、EC2を複数台に増やす場合は、証明書や設定をどのように共有するかも検討する必要がある。
2. ALBがTLS終端し、EC2へは平文で転送
| 項目 | 場所 |
|---|---|
| 証明書の保存場所 | ACM |
| 秘密鍵の保存場所 | ACM |
| 復号する場所 | ALB |
ACMは、SSL/TLSの発行、管理、自動化を行うフルマネージドサービスである。ACMを利用することで、証明書をさまざまなAWSリソースに適用可能になる。適用可能なリソースはELB、API Gateway、CloudFrontである。 ALBでTLS終端する場合、ALBにHTTPSリスナーを作成し、ACMで保管するTLS証明書と関連付けをする。
この構成の利点は、ACMを利用して証明書の発行と更新をAWSに任せられることである。EC2上にインターネット公開用の秘密鍵を配置する必要がなく、TLSの暗号化・復号処理もALBが担当する。さらに、複数のEC2への負荷分散、ヘルスチェック、URLパスやホスト名に応じたルーティングも利用できる。一方で、ALBの利用料金が発生し、リスナーやターゲットグループなどの管理対象も増える。また、ALBからEC2までをHTTPで転送する場合、その区間は暗号化されない。そのため、EC2を外部から直接アクセスできない場所に配置し、セキュリティグループではALBからの通信だけを許可するなど、ネットワーク側で通信経路を制限する必要がある。
3. ALBがTLS終端し、再度暗号化してEC2へ転送する
この構成では、ブラウザからALBまでのTLS接続をALBで一度終端した後、ALBとEC2の間に別のTLS接続を確立する。ブラウザからEC2まで一つのTLS接続が継続するわけではなく、ALBを境に二つのTLS接続へ分かれる点が重要である。
| 項目 | 場所 |
|---|---|
| ブラウザ向け証明書の保存場所 | ACM |
| ブラウザ向け証明書の秘密鍵の保存場所 | ACM |
| ブラウザとのTLS接続を復号する場所 | ALB |
| EC2向け証明書と秘密鍵の保存場所 | EC2 |
| ALBからのTLS接続を復号する場所 | EC2上のCaddyやnginx |
ALBにはHTTPSリスナーとACMの証明書を設定し、ターゲットグループのプロトコルにもHTTPSを指定する。ALBはブラウザから受信したHTTPS通信を復号し、リスナールールに従って転送先を決定する。その後、転送先のEC2と新たにTLSハンドシェイクを行い、HTTPリクエストを再度暗号化して転送する。
この構成の利点は、ブラウザからALBまでだけでなく、ALBからEC2までの通信も暗号化できることである。VPC内部を含むすべての通信経路で暗号化が求められる場合に選択肢となる。一方で、ALB用の証明書に加えてEC2側にも証明書と秘密鍵が必要になるため、平文で転送する構成よりも証明書の管理対象が増える。
4. 判断
今回は、1の「EC2上のCaddyでTLS終端する構成」を採用した。EC2へデプロイする予定だった既存のアプリケーションに、CaddyによるTLS終端の処理がすでに揃っていたためである。Caddyには証明書の取得と更新を自動化する仕組みもあり、既存の構成をそのまま活用できると判断した。
そのため、新たにALBを導入してTLS終端を移すのではなく、EC2上のCaddyまでHTTPS通信を届け、Caddyで復号する構成とした。今回の要件では、構成要素を増やさず、既存のアプリケーションが持つ仕組みを利用できる点を優先した。
5. まとめ
今回、TLS終端をどこで実施するかについて深く考えることができた。提示した3つの構成は、どのような環境を構築するか、規模感はどうか、保守をどこまで人間が実施できるかなどの観点から選択が変わってくると思う。今後は、そのような観点から良い構成を選択できるようにしたい。