【実務・中級編】 ALBにおけるSSL/TLSターミネーションとマネージド証明書(ACM連携) – クラウド&コンテナネットワーク実践ガイド

ALBのSSLターミネーションとACM:現場で迷わない「暗号化の境界線」の設計術

こんにちは。現場で泥臭いパケット解析と格闘し続けてきたSREです。

クラウドインフラを設計する際、避けて通れないのが「どこで暗号化を解くか」という問いです。ALB(Application Load Balancer)のSSL/TLSターミネーションは、AWSにおけるWeb API設計の標準的な構成ですが、意外と「なぜその構成にするのか」という本質を飛ばして、とりあえずACMを紐付けて終わり、というケースをよく見かけます。

今回は、パケットがALBに到達してからバックエンドに届くまでの裏側を紐解きつつ、実務で絶対に外してはいけないポイントを整理しましょう。

—

1. なぜALBでSSLを「終端」させるのか?

結論から言うと、「計算負荷のオフロード」と「証明書管理の一元化」が最大の理由です。

TLSハンドシェイクは、公開鍵暗号方式を用いるためCPUリソースをそれなりに消費します。これをALBというマネージドな層に丸投げすることで、アプリケーションサーバー(EC2やFargate)は、本来のビジネスロジック処理に全力を注げるようになります。

通信のシーケンス:パケットの旅路

1. Client -> ALB: インターネット経由のHTTPS通信。ここでALBがACMの証明書を使ってハンドシェイクを完了します。
2. ALB -> Backend: ここが分岐点。ALBは復号された平文のHTTPパケットをバックエンドに転送します。
3. Backend -> Client: レスポンスは逆順を辿り、ALBで再び暗号化されてクライアントへ届きます。

この構成において、クライアントからは「暗号化された安全な通信」に見えても、VPC内のプライベートネットワーク上では平文で流れているという点には注意が必要です。

—

2. ACM連携のキモ:設定と注意点

AWS Certificate Manager (ACM) は、証明書の更新を自動化してくれるエンジニアの「救世主」です。ALBの設定自体はシンプルですが、実務でハマりやすいのが「セキュリティポリシー」の選択です。

推奨されるセキュリティポリシー

ALBのリスナー設定で選ぶ ELBSecurityPolicy-TLS-1-2-2017-01 などのポリシーは、クライアントがサポートすべきTLSバージョンを定義します。

  • ELBSecurityPolicy-2016-08: 互換性重視(古めのモバイル端末向け)
  • ELBSecurityPolicy-TLS-1-2-2017-01: 最低限のセキュリティ基準(現代のAPI開発ならここから)

古いブラウザやクライアントを切り捨てる勇気があるなら、TLS-1-2-PFS など、Forward Secrecy(前方秘匿性)を強制するポリシーを選択してください。

—

3. 実践:ALBとバックエンドの通信を確認する

ALBがバックエンドへ転送する際、HTTPヘッダーには「実はSSL経由だった」という情報が付与されます。これを適切に拾わないと、アプリ側で無限リダイレクトループが発生することがあります。

ALBが付与する主なヘッダー

  • X-Forwarded-For: クライアントのIPアドレス
  • X-Forwarded-Proto: クライアントが使用したプロトコル(httpsかhttpか)
  • X-Forwarded-Port: クライアントが接続したポート

Flask(Python)での受け取り例

バックエンドのWebサーバーで、ALB経由の通信かどうかを判定するロジック例です。

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def index():
    # ALB経由でhttpsアクセスされたか確認
    proto = request.headers.get('X-Forwarded-Proto')
    if proto == 'https':
        return "セキュアな通信が確立されています。"
    else:
        return "注意:暗号化されていない通信経路です。"

# 実際の実務では、信頼できるALBのIP範囲からのみ
# これらのヘッダーを許可する設定をミドルウェア等で実装します

—

4. トラブルシューティングの勘所

「APIが動かない!」という連絡を受けたとき、まず確認すべきは以下の3点です。

1. ACM証明書のステータス: ISSUED になっていますか? DNS検証が完了していないと、ALBはリスナーを作成できません。
2. ターゲットグループのヘルスチェック: ALBのリスナーをHTTPSにしていても、ターゲットグループ(バックエンド)のポート設定が一致していないと、ALBは「502 Bad Gateway」を返します。
3. セキュリティグループの穴: ALBからバックエンドへの通信(例: ポート80/8080)が、ターゲットグループのセキュリティグループで許可されているか確認してください。

curlでのデバッグコマンド

ALBのエンドポイントに対して、SSLの詳細を確認するコマンドです。

# 証明書の有効期限や暗号スイートを確認する
curl -Iv https://your-api-endpoint.com/ 2>&1 | grep -E "SSL|Certificate"

# 期待通りのレスポンスが返るか確認
curl -H "X-Forwarded-Proto: https" http://your-internal-backend:8080/health

—

最後に:再暗号化(HTTPS to HTTPS)の考え方

最後に、「ALBからバックエンドもHTTPSにすべきか?」という議論について。
「VPC内は閉域だから平文でOK」という考え方が主流ですが、金融や医療など、コンプライアンス要件で「エンドツーエンドの暗号化」が求められる場合は、ALBからバックエンド間もHTTPS通信を行います。

その場合、バックエンドサーバーにも証明書が必要になります(ACMの証明書はALB等のAWSリソースにしかインストールできないため、バックエンド用には別途オレオレ証明書か、内部CAが発行した証明書を用意することになります)。

結論: 特別な要件がない限り、ALBでSSLを終端してバックエンドは平文にする構成が、運用コストとパフォーマンスのバランスが最も優れています。

インフラは「繋がって当たり前」の世界ですが、その裏側にある技術的必然性を理解しているだけで、障害発生時の初動速度が劇的に変わります。ぜひ、設計図を眺める際は「パケットがどこで暗号を解いているか」を想像してみてください。

コメント

タイトルとURLをコピーしました