Enable Shield Advanced Protection for Route 53 Hosted Zones
Overview
This check verifies that your critical Route 53 hosted zones have AWS Shield Advanced protection enabled. Shield Advanced provides enhanced DDoS (Distributed Denial of Service) protection for your DNS infrastructure, helping ensure your domain names remain resolvable even during an attack.
Risk
Without Shield Advanced protection, your Route 53 hosted zones are vulnerable to:
- DDoS attacks: Large-scale volumetric attacks can overwhelm your DNS infrastructure
- DNS query floods: Application-layer attacks targeting your DNS resolution
- Service disruption: Attacks can cause your websites and applications to become unreachable
- Latency spikes: Attack traffic can slow down legitimate DNS queries
- Unexpected costs: You may incur charges from attack-generated traffic
If attackers successfully disrupt your DNS, users cannot reach your applications even if the applications themselves are running normally.
Remediation Steps
Prerequisites
- AWS account with Shield Advanced subscription (additional monthly cost applies)
- Permission to manage Shield Advanced protections
- Your Route 53 hosted zone ID (found in the Route 53 console)
About Shield Advanced pricing
AWS Shield Advanced has a monthly subscription fee plus data transfer charges. Before enabling:
- Review current pricing at AWS Shield Pricing
- Evaluate which hosted zones are business-critical
- Consider that Shield Advanced also protects other resources (CloudFront, ALB, etc.)
The subscription covers unlimited protections, so once subscribed, protect all critical resources.
AWS Console Method
-
Open the AWS WAF & Shield console
- Go to https://console.aws.amazon.com/wafv2/shieldv2
- Ensure you are in the us-east-1 region (Shield Advanced for Route 53 is managed globally from us-east-1)
-
Subscribe to Shield Advanced (if not already subscribed)
- Click Getting started in the left navigation
- Review the terms and pricing
- Click Subscribe to Shield Advanced
-
Add protection for your hosted zone
- Click Protected resources in the left navigation
- Click Add resources to protect
- Select Route 53 hosted zone as the resource type
- Select the hosted zone(s) you want to protect
- Click Protect with Shield Advanced
-
Configure protection settings
- Enter a friendly name for the protection (e.g.,
production-hosted-zone) - Optionally associate a health check for proactive engagement
- Click Protect
- Enter a friendly name for the protection (e.g.,
-
Verify the protection is active
- Return to Protected resources
- Confirm your hosted zone appears in the list with status Active
AWS CLI (optional)
Enable Shield Advanced Protection via CLI
First, list your Route 53 hosted zones to get the zone ID:
aws route53 list-hosted-zones --region us-east-1 \
--query 'HostedZones[*].[Id,Name]' --output table
Create the Shield Advanced protection:
aws shield create-protection \
--name "my-hosted-zone-protection" \
--resource-arn "arn:aws:route53:::hostedzone/Z1234567890ABC" \
--region us-east-1
Replace:
my-hosted-zone-protectionwith a descriptive nameZ1234567890ABCwith your actual hosted zone ID (without the/hostedzone/prefix)
Note: Shield Advanced API calls must be made to the us-east-1 region regardless of where other resources are located.
Add tags to the protection (optional)
aws shield create-protection \
--name "production-dns-protection" \
--resource-arn "arn:aws:route53:::hostedzone/Z1234567890ABC" \
--tags Key=Environment,Value=Production Key=CostCenter,Value=Security \
--region us-east-1
Verify the protection was created
aws shield describe-protection \
--resource-arn "arn:aws:route53:::hostedzone/Z1234567890ABC" \
--region us-east-1
CloudFormation (optional)
CloudFormation Template
Save this template as shield-route53-protection.yaml:
AWSTemplateFormatVersion: '2010-09-09'
Description: Enable AWS Shield Advanced protection for Route 53 hosted zone
Parameters:
HostedZoneId:
Type: String
Description: The Route 53 hosted zone ID to protect (without leading slash)
AllowedPattern: ^[A-Z0-9]+$
ConstraintDescription: Must be a valid Route 53 hosted zone ID
ProtectionName:
Type: String
Description: Friendly name for the Shield Advanced protection
MaxLength: 128
AllowedPattern: ^[a-zA-Z0-9_.\-]+$
ConstraintDescription: Name must contain only alphanumeric characters, underscores, periods, and hyphens
Resources:
ShieldProtection:
Type: AWS::Shield::Protection
Properties:
Name: !Ref ProtectionName
ResourceArn: !Sub arn:aws:route53:::hostedzone/${HostedZoneId}
Outputs:
ProtectionId:
Description: The ID of the Shield Advanced protection
Value: !Ref ShieldProtection
ProtectedResourceArn:
Description: The ARN of the protected Route 53 hosted zone
Value: !Sub arn:aws:route53:::hostedzone/${HostedZoneId}
Deploy the stack
aws cloudformation create-stack \
--stack-name shield-route53-protection \
--template-body file://shield-route53-protection.yaml \
--parameters \
ParameterKey=HostedZoneId,ParameterValue=Z1234567890ABC \
ParameterKey=ProtectionName,ParameterValue=production-dns-protection \
--region us-east-1
Check stack status
aws cloudformation describe-stacks \
--stack-name shield-route53-protection \
--region us-east-1 \
--query 'Stacks[0].StackStatus'
Terraform (optional)
Terraform Configuration
Create a file named main.tf:
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
}
}
provider "aws" {
region = "us-east-1" # Shield Advanced API requires us-east-1
}
variable "hosted_zone_id" {
description = "The Route 53 hosted zone ID to protect"
type = string
}
variable "protection_name" {
description = "Friendly name for the Shield Advanced protection"
type = string
}
resource "aws_shield_protection" "route53_hosted_zone" {
name = var.protection_name
resource_arn = "arn:aws:route53:::hostedzone/${var.hosted_zone_id}"
tags = {
ManagedBy = "Terraform"
Purpose = "DDoS-Protection"
}
}
output "protection_id" {
description = "The ID of the Shield Advanced protection"
value = aws_shield_protection.route53_hosted_zone.id
}
output "protection_arn" {
description = "The ARN of the Shield Advanced protection"
value = aws_shield_protection.route53_hosted_zone.arn
}
Create a variables file
Create terraform.tfvars:
hosted_zone_id = "Z1234567890ABC"
protection_name = "production-dns-protection"
Apply the configuration
terraform init
terraform plan
terraform apply
Protect multiple hosted zones
To protect multiple zones, use a for_each loop:
variable "hosted_zones" {
description = "Map of hosted zone IDs to protection names"
type = map(string)
default = {
"Z1234567890ABC" = "production-dns"
"ZDEF456789012" = "staging-dns"
}
}
resource "aws_shield_protection" "route53_hosted_zones" {
for_each = var.hosted_zones
name = each.value
resource_arn = "arn:aws:route53:::hostedzone/${each.key}"
tags = {
ManagedBy = "Terraform"
Purpose = "DDoS-Protection"
}
}
Verification
After enabling Shield Advanced protection, verify it is working:
-
In the AWS Console:
- Go to AWS WAF & Shield console
- Click Protected resources
- Find your hosted zone in the list
- Confirm the status shows Active
-
Re-run the Prowler check:
prowler aws --check shield_advanced_protection_in_route53_hosted_zones
Advanced verification via CLI
List all Shield Advanced protections
aws shield list-protections --region us-east-1
Filter for Route 53 protections only
aws shield list-protections \
--inclusion-filters ResourceTypes=ROUTE_53_HOSTED_ZONE \
--region us-east-1
Verify a specific hosted zone is protected
aws shield describe-protection \
--resource-arn "arn:aws:route53:::hostedzone/Z1234567890ABC" \
--region us-east-1
A successful response confirms the protection is active. An error like ResourceNotFoundException means the zone is not protected.
Additional Resources
- AWS Shield Advanced Documentation
- Getting Started with AWS Shield Advanced
- Adding Shield Advanced Protection to Resources
- AWS Shield Pricing
- Route 53 DDoS Resilience Best Practices
Notes
-
Cost consideration: Shield Advanced has a monthly subscription fee (currently $3,000/month) plus data transfer charges. Evaluate your business needs before subscribing.
-
Global service: Shield Advanced for Route 53 is managed from the
us-east-1region, even though Route 53 itself is a global service. -
Subscription required: You must subscribe to Shield Advanced before you can create protections. The subscription covers your entire AWS organization.
-
Proactive engagement: Consider enabling proactive engagement and associating health checks with your protections. This allows the AWS Shield Response Team (SRT) to contact you during detected events.
-
Coverage: Once subscribed to Shield Advanced, protect all business-critical resources (CloudFront distributions, Application Load Balancers, Elastic IPs, Global Accelerators) to maximize the value of your subscription.
-
DRT access: For the Shield Response Team to assist during attacks, grant them access via an IAM role. See Configuring access for the Shield Response Team.