Shield Advanced Protection for Internet-Facing Load Balancers
Overview
This check verifies whether internet-facing Application Load Balancers (ALBs) have AWS Shield Advanced protection enabled. Shield Advanced provides enhanced DDoS (Distributed Denial of Service) protection beyond the basic Shield Standard that comes with all AWS accounts.
Internet-facing load balancers are common targets for DDoS attacks because they are publicly accessible entry points to your applications.
Risk
Without Shield Advanced protection, your internet-facing ALBs are vulnerable to:
- Volumetric attacks: Large-scale network floods (Layer 3/4) that can overwhelm your infrastructure
- Application-layer attacks: HTTP floods (Layer 7) that target your application directly
- Service outages: Extended downtime affecting your users and dependent services
- Unexpected costs: Auto-scaling responses to attack traffic can significantly increase your AWS bill
- Latency spikes: Even attacks that do not cause outages can degrade performance
Remediation Steps
Prerequisites
- AWS account with Shield Advanced subscription (this is a paid service with a monthly fee)
- Permission to modify Shield Advanced protections
- The ARN of the Application Load Balancer you want to protect
Important: Shield Advanced is a premium service with significant cost. Review the AWS Shield Pricing before enabling.
AWS Console Method
-
Open the AWS WAF & Shield console at https://console.aws.amazon.com/wafv2/
-
In the left navigation, expand AWS Shield and click Protected resources
-
Click the Add resources to protect button
-
Under Resource type, select Application Load Balancer
-
Select the Region where your ALB is located (e.g., us-east-1)
-
Check the box next to the internet-facing ALB you want to protect
-
Click Protect with Shield Advanced
-
Review the protection details and click Confirm
Your ALB is now protected by Shield Advanced.
AWS CLI (optional)
Enable Shield Advanced Protection via CLI
First, verify you have an active Shield Advanced subscription:
aws shield describe-subscription --region us-east-1
Get the ARN of your internet-facing ALB:
aws elbv2 describe-load-balancers \
--region us-east-1 \
--query "LoadBalancers[?Scheme=='internet-facing'].LoadBalancerArn" \
--output text
Create the Shield Advanced protection:
aws shield create-protection \
--name "my-alb-protection" \
--resource-arn "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/1234567890abcdef" \
--region us-east-1
Replace the following placeholders:
my-alb-protection- A friendly name for this protection (letters, numbers, underscores, hyphens, and periods only)- The resource ARN with your actual ALB ARN
Protect Multiple ALBs
To protect all internet-facing ALBs in a region:
# List all internet-facing ALBs
aws elbv2 describe-load-balancers \
--region us-east-1 \
--query "LoadBalancers[?Scheme=='internet-facing' && Type=='application'].[LoadBalancerName,LoadBalancerArn]" \
--output text | while read name arn; do
echo "Protecting ALB: $name"
aws shield create-protection \
--name "${name}-shield-protection" \
--resource-arn "$arn" \
--region us-east-1
done
CloudFormation (optional)
CloudFormation Template
AWSTemplateFormatVersion: '2010-09-09'
Description: Enable AWS Shield Advanced protection for an Application Load Balancer
Parameters:
ProtectionName:
Type: String
Description: Friendly name for the Shield Advanced protection
MinLength: 1
MaxLength: 128
LoadBalancerArn:
Type: String
Description: ARN of the Application Load Balancer to protect
AllowedPattern: arn:aws:elasticloadbalancing:[a-z0-9-]+:[0-9]+:loadbalancer/app/.+
Resources:
ShieldProtection:
Type: AWS::Shield::Protection
Properties:
Name: !Ref ProtectionName
ResourceArn: !Ref LoadBalancerArn
Tags:
- Key: Environment
Value: Production
- Key: ManagedBy
Value: CloudFormation
Outputs:
ProtectionId:
Description: The ID of the Shield Advanced protection
Value: !Ref ShieldProtection
Deploy the Stack
aws cloudformation create-stack \
--stack-name shield-alb-protection \
--template-body file://shield-protection.yaml \
--parameters \
ParameterKey=ProtectionName,ParameterValue=my-alb-shield-protection \
ParameterKey=LoadBalancerArn,ParameterValue=arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/1234567890abcdef \
--region us-east-1
Terraform (optional)
Terraform Configuration
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
variable "protection_name" {
description = "Friendly name for the Shield Advanced protection"
type = string
}
variable "load_balancer_arn" {
description = "ARN of the Application Load Balancer to protect"
type = string
}
variable "tags" {
description = "Tags to apply to the Shield protection"
type = map(string)
default = {}
}
resource "aws_shield_protection" "alb" {
name = var.protection_name
resource_arn = var.load_balancer_arn
tags = var.tags
}
output "protection_id" {
description = "The ID of the Shield Advanced protection"
value = aws_shield_protection.alb.id
}
output "protection_arn" {
description = "The ARN of the Shield Advanced protection"
value = aws_shield_protection.alb.arn
}
Deploy with Terraform
terraform init
terraform plan -var="protection_name=my-alb-shield-protection" \
-var="load_balancer_arn=arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/1234567890abcdef"
terraform apply
Protect All Internet-Facing ALBs
data "aws_lb" "internet_facing" {
for_each = toset(var.alb_names)
name = each.value
}
resource "aws_shield_protection" "albs" {
for_each = data.aws_lb.internet_facing
name = "${each.value.name}-shield-protection"
resource_arn = each.value.arn
tags = var.tags
}
Verification
After enabling Shield Advanced protection, verify it is working:
- Go to the AWS WAF & Shield console
- Click Protected resources under AWS Shield
- Find your ALB in the list - it should show as Protected
CLI Verification
Verify protection exists for your ALB:
aws shield describe-protection \
--resource-arn "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/my-alb/1234567890abcdef" \
--region us-east-1
List all Shield Advanced protections:
aws shield list-protections --region us-east-1
Check for unprotected internet-facing ALBs:
# Get all internet-facing ALB ARNs
aws elbv2 describe-load-balancers \
--region us-east-1 \
--query "LoadBalancers[?Scheme=='internet-facing' && Type=='application'].LoadBalancerArn" \
--output text | tr '\t' '\n' | while read arn; do
protection=$(aws shield describe-protection --resource-arn "$arn" --region us-east-1 2>&1)
if echo "$protection" | grep -q "ResourceNotFoundException"; then
echo "UNPROTECTED: $arn"
else
echo "Protected: $arn"
fi
done
Additional Resources
- AWS Shield Advanced Documentation
- AWS Shield Pricing
- Getting Started with Shield Advanced
- Adding Shield Advanced Protection to Resources
- AWS::Shield::Protection CloudFormation Reference
- Terraform aws_shield_protection Resource
Notes
-
Cost consideration: AWS Shield Advanced has a significant monthly cost ($3,000/month as of 2024) plus data transfer fees. Ensure this fits your security budget before enabling.
-
Subscription required: You must have an active Shield Advanced subscription before you can protect resources. Subscribe via the AWS Shield console or use
aws shield create-subscription. -
One-year commitment: Shield Advanced requires a one-year subscription commitment.
-
Additional protections: For maximum protection, pair Shield Advanced with:
- AWS WAF for Layer 7 filtering and rate limiting
- Health-based detection for faster response to attacks
- Shield Response Team (SRT) engagement for expert support during attacks
-
Regional consideration: Shield Advanced protections are created in the same region as the protected resource. For global resources like CloudFront, use
us-east-1. -
Protection groups: Consider creating protection groups to manage multiple protected resources together and configure shared health checks.