Skip to main content

CloudFront Distribution Serves HTTPS Requests Using SNI

Overview

This check verifies that your CloudFront distributions using custom SSL/TLS certificates are configured to use Server Name Indication (SNI) instead of dedicated IP addresses.

SNI is a modern TLS extension that allows multiple SSL certificates to share a single IP address. When you use a custom domain with CloudFront (like www.example.com), you need an SSL certificate. SNI lets CloudFront serve that certificate efficiently without reserving a dedicated IP address just for your distribution.

Risk

Without SNI enabled, CloudFront uses dedicated IP SSL, which creates several problems:

  • Higher costs: Dedicated IP addresses cost significantly more than SNI
  • IP quota strain: You may run out of available IP addresses as you scale
  • Reduced availability: IP constraints can limit your ability to expand
  • Operational complexity: Managing IP-bound certificates is harder during rotations and expansions

Remediation Steps

Prerequisites

  • Access to the AWS Console with permissions to modify CloudFront distributions
  • If using a custom SSL certificate, it must already be in AWS Certificate Manager (ACM) in the us-east-1 region

AWS Console Method

  1. Open the CloudFront console
  2. Select the distribution you want to update
  3. Click the General tab, then click Edit in the Settings section
  4. Scroll to Custom SSL certificate - you should see your certificate selected
  5. Under Legacy clients support, select SNI only (recommended) instead of "Legacy clients support"
  6. Click Save changes

Changes typically take 5-15 minutes to deploy across all CloudFront edge locations.

AWS CLI Method

The CLI approach requires downloading the current configuration, modifying it, and uploading the changes.

Step 1: Get the current configuration

# Replace DISTRIBUTION_ID with your actual distribution ID (e.g., E1A2B3C4D5E6F7)
DISTRIBUTION_ID="<your-distribution-id>"

# Get current config and ETag
aws cloudfront get-distribution-config \
--id "$DISTRIBUTION_ID" \
--region us-east-1 \
--output json > /tmp/dist-config.json

# Extract the ETag (needed for updates)
ETAG=$(aws cloudfront get-distribution-config \
--id "$DISTRIBUTION_ID" \
--region us-east-1 \
--query "ETag" \
--output text)

Step 2: Modify the configuration

Edit /tmp/dist-config.json to change the ViewerCertificate section:

"ViewerCertificate": {
"ACMCertificateArn": "arn:aws:acm:us-east-1:123456789012:certificate/abc123",
"SSLSupportMethod": "sni-only",
"MinimumProtocolVersion": "TLSv1.2_2021"
}

Important: You must also:

  • Remove the top-level ETag field from the JSON
  • Keep only the DistributionConfig object (remove the wrapper)

Step 3: Apply the update

aws cloudfront update-distribution \
--id "$DISTRIBUTION_ID" \
--distribution-config file:///tmp/dist-config.json \
--if-match "$ETAG" \
--region us-east-1
CloudFormation Template

Use this template to create a new CloudFront distribution with SNI enabled, or reference it when updating existing stacks.

AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFront Distribution with SNI-only SSL configuration

Parameters:
DomainName:
Type: String
Description: Your custom domain name (e.g., www.example.com)

AcmCertificateArn:
Type: String
Description: ARN of the ACM certificate in us-east-1 for your domain

S3BucketDomainName:
Type: String
Description: S3 bucket regional domain name for origin

Resources:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Comment: Distribution with SNI-only SSL configuration
DefaultRootObject: index.html
Aliases:
- !Ref DomainName
Origins:
- Id: S3Origin
DomainName: !Ref S3BucketDomainName
S3OriginConfig:
OriginAccessIdentity: ''
DefaultCacheBehavior:
TargetOriginId: S3Origin
ViewerProtocolPolicy: redirect-to-https
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
ForwardedValues:
QueryString: false
Cookies:
Forward: none
ViewerCertificate:
AcmCertificateArn: !Ref AcmCertificateArn
SslSupportMethod: sni-only
MinimumProtocolVersion: TLSv1.2_2021

Outputs:
DistributionId:
Description: CloudFront Distribution ID
Value: !Ref CloudFrontDistribution

DistributionDomainName:
Description: CloudFront Distribution Domain Name
Value: !GetAtt CloudFrontDistribution.DomainName

The key configuration is in the ViewerCertificate section:

  • SslSupportMethod: sni-only - Uses SNI instead of dedicated IP
  • MinimumProtocolVersion: TLSv1.2_2021 - Enforces modern TLS
Terraform Configuration
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = "us-east-1"
}

variable "domain_name" {
description = "Your custom domain name (e.g., www.example.com)"
type = string
}

variable "acm_certificate_arn" {
description = "ARN of the ACM certificate in us-east-1"
type = string
}

variable "origin_domain_name" {
description = "Domain name of the origin (e.g., S3 bucket)"
type = string
}

resource "aws_cloudfront_distribution" "main" {
enabled = true
comment = "Distribution with SNI-only SSL configuration"
default_root_object = "index.html"
aliases = [var.domain_name]

origin {
domain_name = var.origin_domain_name
origin_id = "S3Origin"
}

default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3Origin"
viewer_protocol_policy = "redirect-to-https"

forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
}

viewer_certificate {
acm_certificate_arn = var.acm_certificate_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}

restrictions {
geo_restriction {
restriction_type = "none"
}
}
}

output "distribution_id" {
description = "CloudFront Distribution ID"
value = aws_cloudfront_distribution.main.id
}

output "distribution_domain_name" {
description = "CloudFront Distribution Domain Name"
value = aws_cloudfront_distribution.main.domain_name
}

The critical setting in the viewer_certificate block is:

  • ssl_support_method = "sni-only" - Enables SNI instead of dedicated IP

Verification

After making changes, verify SNI is enabled:

  1. Open the CloudFront console
  2. Select your distribution
  3. In the General tab, look for Custom SSL certificate
  4. Confirm it shows SNI (not "Legacy clients support" or "Dedicated IP")
CLI Verification
aws cloudfront get-distribution \
--id "<your-distribution-id>" \
--region us-east-1 \
--query "Distribution.DistributionConfig.ViewerCertificate.SSLSupportMethod" \
--output text

The output should be sni-only.

Additional Resources

Notes

  • SNI compatibility: SNI is supported by all modern browsers and clients. The only exception is very old clients (Internet Explorer on Windows XP, Android 2.x). If you must support these legacy clients, you may need dedicated IP, but this should be rare.

  • Certificate location: Custom SSL certificates for CloudFront must be stored in ACM in the us-east-1 region, regardless of where your origin is located.

  • Cost difference: SNI is included at no additional charge. Dedicated IP SSL costs approximately $600/month per distribution.

  • Deployment time: Changes to SSL settings typically propagate across all CloudFront edge locations within 5-15 minutes.