AWS WAF

Web Application Firewall - Protect against common web exploits

πŸ’΅ Cost: WAF costs $5/month per Web ACL + $1/month per rule + $0.60 per million requests. AWS Managed Rules are free (included in rule count). Can add up for high-traffic sites. See aws.amazon.com/waf/pricing. Last verified: January 2026.

What is AWS WAF?

AWS WAF (Web Application Firewall) protects your web applications from common web exploits like SQL injection, cross-site scripting (XSS), and other OWASP Top 10 vulnerabilities. It sits in front of your ALB, CloudFront, or API Gateway.

When to Use WAF

  • Protect against OWASP Top 10 vulnerabilities
  • Block malicious bots and scrapers
  • Rate limiting to prevent DDoS
  • Geographic restrictions
  • IP allowlist/blocklist

WAF Components

ComponentPurpose
Web ACLContainer for rules, associated with ALB/CloudFront
RuleCondition + action (allow, block, count)
Rule GroupCollection of reusable rules
Managed RulesPre-built rules from AWS or partners
IP SetList of IP addresses to allow/block

WAF Architecture

Plain Text
Internet
    β”‚
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  AWS WAF (Web ACL)                  β”‚
β”‚  β”œβ”€β”€ AWS Managed Rules              β”‚
β”‚  β”‚   β”œβ”€β”€ AWSManagedRulesCommonRuleSet
β”‚  β”‚   β”œβ”€β”€ AWSManagedRulesSQLiRuleSet β”‚
β”‚  β”‚   └── AWSManagedRulesKnownBadInputsRuleSet
β”‚  β”‚                                  β”‚
β”‚  β”œβ”€β”€ Rate Limiting Rule             β”‚
β”‚  β”‚   └── 2000 requests/5 min/IP     β”‚
β”‚  β”‚                                  β”‚
β”‚  └── Custom Rules                   β”‚
β”‚      β”œβ”€β”€ Block specific IPs         β”‚
β”‚      └── Geo-block certain countriesβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β”‚
    β–Ό
Application Load Balancer β†’ ECS Tasks

AWS provides free managed rule groups that protect against common vulnerabilities:

Rule GroupProtects AgainstRecommended
AWSManagedRulesCommonRuleSetOWASP Top 10, XSS, command injectionYes
AWSManagedRulesSQLiRuleSetSQL injection attacksYes
AWSManagedRulesKnownBadInputsRuleSetKnown malicious patternsYes
AWSManagedRulesAmazonIpReputationListKnown bad IPs (bots, spammers)Yes
AWSManagedRulesAnonymousIpListVPNs, Tor, proxiesOptional
AWSManagedRulesBotControlRuleSetBot traffic managementPaid add-on

Start in Count Mode

Enable new rules in count mode first to monitor without blocking. Review CloudWatch metrics for false positives before switching to block mode.
HCL
# Web ACL for ALB
resource "aws_wafv2_web_acl" "main" {
  name        = "my-app-waf"
  description = "WAF for my application"
  scope       = "REGIONAL"  # Use "CLOUDFRONT" for CloudFront

  default_action {
    allow {}
  }

  # AWS Managed Rules - Common Rule Set
  rule {
    name     = "AWSManagedRulesCommonRuleSet"
    priority = 1

    override_action {
      none {}
    }

    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesCommonRuleSet"
        vendor_name = "AWS"
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "CommonRuleSetMetric"
      sampled_requests_enabled   = true
    }
  }

  # AWS Managed Rules - SQL Injection
  rule {
    name     = "AWSManagedRulesSQLiRuleSet"
    priority = 2

    override_action {
      none {}
    }

    statement {
      managed_rule_group_statement {
        name        = "AWSManagedRulesSQLiRuleSet"
        vendor_name = "AWS"
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "SQLiRuleSetMetric"
      sampled_requests_enabled   = true
    }
  }

  # Rate limiting rule
  rule {
    name     = "RateLimitRule"
    priority = 3

    action {
      block {}
    }

    statement {
      rate_based_statement {
        limit              = 2000
        aggregate_key_type = "IP"
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "RateLimitMetric"
      sampled_requests_enabled   = true
    }
  }

  # IP Blocklist (optional)
  rule {
    name     = "IPBlocklist"
    priority = 0

    action {
      block {}
    }

    statement {
      ip_set_reference_statement {
        arn = aws_wafv2_ip_set.blocklist.arn
      }
    }

    visibility_config {
      cloudwatch_metrics_enabled = true
      metric_name                = "IPBlocklistMetric"
      sampled_requests_enabled   = true
    }
  }

  visibility_config {
    cloudwatch_metrics_enabled = true
    metric_name                = "MyAppWAFMetric"
    sampled_requests_enabled   = true
  }

  tags = {
    Environment = var.environment
  }
}

# IP Set for blocklist
resource "aws_wafv2_ip_set" "blocklist" {
  name               = "ip-blocklist"
  description        = "Known bad IPs"
  scope              = "REGIONAL"
  ip_address_version = "IPV4"
  addresses          = []  # Add blocked IPs here
}

# Associate WAF with ALB
resource "aws_wafv2_web_acl_association" "main" {
  resource_arn = aws_lb.main.arn
  web_acl_arn  = aws_wafv2_web_acl.main.arn
}

WAF Pricing

Pricing Note

WAF pricing is consistent across regions. Always verify at aws.amazon.com/waf/pricing. Last verified: January 2026.
ComponentCost
Web ACL$5.00/month
Rule$1.00/month each
Requests$0.60 per million
AWS Managed RulesFree (counts toward rule limit)
Bot Control$10/month + $1/million requests

Cost Example

Basic WAF setup with 5 rules and 10 million requests/month:
$5 (ACL) + $5 (5 rules) + $6 (10M requests) = ~$16/month

AWS Deployment Guide β€” Built with Next.js