Skip to main content

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

  1. Open the AWS WAF & Shield console at https://console.aws.amazon.com/wafv2/

  2. In the left navigation, expand AWS Shield and click Protected resources

  3. Click the Add resources to protect button

  4. Under Resource type, select Application Load Balancer

  5. Select the Region where your ALB is located (e.g., us-east-1)

  6. Check the box next to the internet-facing ALB you want to protect

  7. Click Protect with Shield Advanced

  8. 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:

  1. Go to the AWS WAF & Shield console
  2. Click Protected resources under AWS Shield
  3. 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

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.