CloudFrontディストリビューションでSNIの設定について

このブログシリーズ 「クラウドセキュリティ 実践集」 では、一般的なセキュリティ課題を取り上げ、「なぜ危険なのか?」 というリスクの解説から、「どうやって直すのか?」 という具体的な修復手順(コンソール、AWS CLI、Terraformなど)まで、分かりやすく解説します。
今回は、Amazon CloudFrontディストリビューションで SNI (Server Name Indication) を利用したHTTPSリクエストが適切に設定されていない状態について、そのリスクと対策を解説します。

ポリシーの説明
Amazon CloudFront の Security Hub コントロール – AWS Security Hub
[CloudFront.8] CloudFront ディストリビューションでは、SNI を使用して HTTPS リクエストを処理する必要があります
このコントロールは、Amazon CloudFront ディストリビューションでカスタム SSL/TLS 証明書が使用されていて、SNI を使用して HTTPS リクエストを処理するように設定されているかチェックします。カスタム SSL/TLS 証明書が関連付けられているものの、SSL/TLS サポートメソッドが専用 IP アドレスである場合、このコントロールは失敗します。
リスク
CloudFrontディストリビューションでSNIを使用したHTTPSリクエストが有効になっていない、または適切に設定されていない場合、以下のような問題やセキュリティ上のリスクが発生する可能性があります。
- レガシーなSSL/TLSハンドシェイク方式の使用: SNIを使用しない従来の専用IPアドレス方式は、CloudFrontの各エッジロケーションでディストリビューション専用のIPアドレスを必要とします。これはリソースの利用効率が低く、費用も高くなる傾向があります。また、古いSSL/TLSプロトコルや暗号スイートに依存する可能性があり、最新のセキュリティ標準に準拠しにくくなります。
- HTTPS通信のセキュリティ脆弱性: SNIは、TLSプロトコルの拡張機能であり、クライアントがSSL/TLSハンドシェイクの初期段階でどのホスト名にアクセスしようとしているかをサーバーに伝えることを可能にします。SNIが利用できない場合、単一のIPアドレスで複数のドメインをホストする際に、正しいSSL/TLS証明書を提示できず、ブラウザの警告や接続エラーが発生する可能性があります。これは、HTTPS通信のセキュリティ信頼性を低下させます。
- 非対応ブラウザ・クライアントの発生: 2010年以降にリリースされたほとんどのモダンなブラウザとクライアントはSNIをサポートしていますが、SNI非対応の古いクライアントやIoTデバイスなどが特定のコンテンツにアクセスしようとした場合、接続が確立できない可能性があります。これにより、一部のユーザーがサービスにアクセスできなくなる事態が発生します。
対策
CloudFrontディストリビューションでSNIを使用したHTTPSリクエストを有効にすることは、パフォーマンス、セキュリティ、およびコスト効率の面で多くのメリットをもたらすベストプラクティスです。
- カスタムSSL証明書の用意: HTTPS通信を有効にするためには、AWS Certificate Manager (ACM) でドメイン名のSSL/TLS証明書をリクエストまたはインポートします。
- CloudFrontディストリビューションの設定: CloudFrontディストリビューションの「ビューワープロトコルポリシー」で「Redirect HTTP to HTTPS」または「HTTPS Only」を選択し、カスタムSSL証明書を関連付けます。
- カスタムSSL証明書の設定: CloudFrontのSSL証明書設定で、「カスタム SSL 証明書」 を選択し、ACMで用意した証明書を選択します。この際、「価格クラス」と「SSLクライアントサポート」 に注意が必要です。
- 「SSLクライアントサポート」 では、ほとんどのモダンなクライアントをサポートする 「SNI (Server Name Indication) を使用する」 を選択します。
- SNIを使用しないレガシーなクライアントをサポートする必要がある場合は、「専用IPアドレス」オプションを選択することも可能ですが、追加費用が発生し、推奨されません。
- DNS設定の確認: CNAMEレコードを使用して、代替ドメイン名(例:
www.example.com
)がCloudFrontのドメイン名(例:d111111abcdef8.cloudfront.net
)を指すようにDNSを設定します。 - HTTPからHTTPSへのリダイレクト: ビューワープロトコルポリシーを「Redirect HTTP to HTTPS」に設定することで、HTTPリクエストが自動的にHTTPSにリダイレクトされ、常に安全な通信が保証されます。
修復方法
AWSコンソールでの修復手順
AWSコンソールを使用して、CloudFrontディストリビューションでSNIを利用したHTTPSリクエストを有効にします。
- ACM (AWS Certificate Manager) で証明書をリクエスト/インポート:
- AWSコンソールにログインし、AWS Certificate Manager サービスを開きます。
- ディストリビューションに関連付けたいカスタムドメイン名(例:
www.example.com
)のSSL/TLS証明書をリクエストまたはインポートします。CloudFrontで使用する証明書は、us-east-1 (バージニア北部) リージョンでプロビジョニングする必要があります。 - 証明書が「発行済み」ステータスになるまで待ちます。
- CloudFrontサービスへ移動: AWSコンソールでCloudFrontサービスを開きます。
- ディストリビューションの選択: 設定を変更したいCloudFrontディストリビューションを選択します。
- 編集: ディストリビューションの詳細ページで、「編集」をクリックします。
- 代替ドメイン名 (CNAMEs) の追加: 「代替ドメイン名 (CNAMEs)」セクションに、このディストリビューションで使用するカスタムドメイン名(例:
www.example.com
)を入力します。 - SSL証明書の設定: 「カスタム SSL 証明書」で、ドロップダウンメニューからACMで作成またはインポートした証明書を選択します。 「SSL クライアントサポート」で、「SNI (Server Name Indication) を使用する」が選択されていることを確認します。これがデフォルトであり、推奨される設定です。

- ビューワープロトコルポリシーの設定: ビヘイビアのタブに移動し対象を選択後、「編集」を選択し、「ビューワープロトコルポリシー」セクションで、セキュリティ要件に応じて以下のいずれかを選択します。
- Redirect HTTP to HTTPS (推奨): HTTPリクエストをHTTPSに自動的にリダイレクトします。HTTPS Only: HTTPSリクエストのみを許可します。

- 変更の保存: 設定を確認し、「変更を保存」をクリックします。 CloudFrontディストリビューションのデプロイには数分かかる場合があります。ステータスが「デプロイ済み」になるまで待ちます。
- DNSレコードの更新 (重要): カスタムドメイン名がCloudFrontディストリビューションを指すように、DNSプロバイダーでCNAMEレコードを更新します。(例:
www.example.com
をd111111abcdef8.cloudfront.net
に向ける)
Terraformでの修復手順
TerraformでCloudFrontディストリビューションにSNIを使用したHTTPSリクエストを有効にするには、aws_cloudfront_distribution
リソースの viewer_certificate
ブロックを設定します。
前提: ACMでカスタムドメイン名のSSL/TLS証明書が us-east-1 (バージニア北部) リージョンで既に発行されている必要があります。
# AWS Certificate Manager (ACM) 証明書をデータソースとして参照
# us-east-1 リージョンで証明書が発行されている必要があります
data "aws_acm_certificate" "example_cert" {
domain = "your.custom.domain.com" # あなたのカスタムドメイン名に置き換え
statuses = ["ISSUED"]
# CloudFrontで利用するため、バージニア北部 (us-east-1) で証明書をプロビジョニングする必要がある
provider = aws.us_east_1 # providerエイリアスを使用
}
# us-east-1 provider を定義
provider "aws" {
alias = "us_east_1"
region = "us-east-1"
}
# CloudFront ディストリビューションの定義
resource "aws_cloudfront_distribution" "s_cloudfront_distribution" {
enabled = true
is_ipv6_enabled = true
comment = "CloudFront distribution for my application"
price_class = "PriceClass_AllLocations" # または PriceClass_200 / PriceClass_100
# オリジン (S3バケット、ALBなど)
origin {
domain_name = aws_s3_bucket.origin_bucket.bucket_regional_domain_name # 例: S3バケットをオリジンとする場合
origin_id = "S3-Origin"
s3_origin_config {
origin_access_identity = aws_cloudfront_origin_access_identity.s3_oai.cloudfront_access_identity_path
}
}
# デフォルトのキャッシュ動作
default_cache_behavior {
target_origin_id = "S3-Origin"
viewer_protocol_policy = "redirect-to-https" # HTTPをHTTPSにリダイレクト (推奨)
# viewer_protocol_policy = "https-only" # HTTPSのみを許可する場合
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD", "OPTIONS"]
forwarded_values {
query_string = true
headers = ["Origin"]
cookies {
forward = "none"
}
}
min_ttl = 0
default_ttl = 86400 # 24時間
max_ttl = 31536000 # 1年
compress = true
}
# カスタムドメイン名 (CNAMEs)
aliases = ["your.custom.domain.com"] # あなたのカスタムドメイン名に置き換え
# SSL証明書の設定 (SNIを有効化)
viewer_certificate {
acm_certificate_arn = data.aws_acm_certificate.example_cert.arn # ACM証明書のARNを指定
ssl_support_method = "sni-only" # SNIのみを有効化 (推奨)
minimum_protocol_version = "TLSv1.2_2021" # 最新の推奨プロトコルバージョン
}
restrictions {
geo_restriction {
restriction_type = "none" # または "whitelist", "blacklist"
locations = []
}
}
# CloudFrontログ (オプション)
logging_config {
include_cookies = false
bucket = aws_s3_bucket.cloudfront_log_bucket.bucket_domain_name
prefix = "cloudfront-logs/"
}
tags = {
Name = "MyCloudFrontDistribution"
}
}
# (例) オリジンとなるS3バケットとOAI
resource "aws_s3_bucket" "origin_bucket" {
bucket = "my-cloudfront-origin-bucket-unique-12345" # グローバルで一意の名前に変更
tags = {
Name = "CloudFrontOriginBucket"
}
}
resource "aws_cloudfront_origin_access_identity" "s3_oai" {
comment = "OAI for my CloudFront distribution"
}
resource "aws_s3_bucket_policy" "s3_bucket_policy" {
bucket = aws_s3_bucket.origin_bucket.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Principal = {
AWS = aws_cloudfront_origin_access_identity.s3_oai.iam_arn
},
Action = "s3:GetObject",
Resource = "${aws_s3_bucket.origin_bucket.arn}/*"
},
{
Effect = "Allow",
Principal = {
Service = "cloudfront.amazonaws.com"
},
Action = "s3:ListBucket",
Resource = aws_s3_bucket.origin_bucket.arn,
Condition = {
StringEquals = {
"aws:SourceArn" = aws_cloudfront_distribution.s_cloudfront_distribution.arn
}
}
}
]
})
}
# CloudFrontログ用のS3バケット (オプション)
resource "aws_s3_bucket" "cloudfront_log_bucket" {
bucket = "my-cloudfront-logs-bucket-unique-67890" # グローバルで一意の名前に変更
tags = {
Name = "CloudFrontLogBucket"
}
}
上記のTerraformコードでは、aws_cloudfront_distribution
リソースの viewer_certificate
ブロックで以下の設定を行っています。
acm_certificate_arn
: ACMで発行されたSSL/TLS証明書のARNを指定します。この証明書はus-east-1
リージョンにある必要があります。ssl_support_method = "sni-only"
: これがSNIを使用したHTTPSリクエストを有効にする設定です。minimum_protocol_version = "TLSv1.2_2021"
: 最新かつ安全なTLSプロトコルバージョンを指定することを推奨します。
また、viewer_protocol_policy = "redirect-to-https"
を設定することで、HTTPリクエストをHTTPSに自動的にリダイレクトし、セキュアな通信を強制しています。
your.custom.domain.com
や my-cloudfront-origin-bucket-unique-12345
などのプレースホルダーは、実際の環境に合わせて修正してください。
最後に
この記事では、CloudFrontディストリビューションでSNIを利用したHTTPSリクエストを有効にすることの重要性について解説しました。SNIを有効にすることで、最新のセキュリティ標準に準拠し、コスト効率を向上させながら、HTTPS経由でコンテンツを安全に配信できるようになります。 貴社のCloudFrontディストリビューションでは、SNIを使用したHTTPSリクエストが適切に設定されていますか?この機会にぜひご確認ください。 こちらの内容の検出は弊社が提供するSecurifyのCSPM機能で簡単に検出及び管理する事が可能です。運用が非常にラクに出来る製品になっていますのでぜひ興味がある方はお問い合わせお待ちしております。
最後までお読みいただきありがとうございました。この記事が皆さんの役に立てば幸いです。