AWS for DevOps — WAF Basics

2 minute read

12.5 — WAF Basics

AWS WAF (Web Application Firewall) protects your web applications from common attacks like SQL injection, cross-site scripting (XSS), and bot traffic. It sits in front of CloudFront or ALB and inspects every request.

Real-World Analogy

WAF is like a bouncer at a nightclub. The bouncer checks every person at the door against a list of rules: no weapons (SQL injection), no fake IDs (XSS), no one from the banned list (IP blocklist). Good patrons get in; bad actors get turned away.

How WAF Works

  Incoming Request
       │
       ▼
  ┌────────┐    ┌───────────────────────┐
  │  WAF   │───→│ Rule 1: Block SQL     │──→ Block (403)
  │        │    │ Rule 2: Block XSS     │──→ Block (403)
  │        │    │ Rule 3: Rate limit    │──→ Block (429)
  │        │    │ Rule 4: IP blocklist  │──→ Block (403)
  │        │    │ Rule 5: Geo-restrict  │──→ Block (403)
  │        │    │ Default: Allow        │──→ Pass to ALB
  └────────┘    └───────────────────────┘

Creating a Web ACL

# Create a Web ACL with AWS Managed Rules
$ aws wafv2 create-web-acl \
    --name production-waf \
    --scope REGIONAL \
    --default-action Allow={} \
    --rules '[
      {
        "Name": "AWS-AWSManagedRulesCommonRuleSet",
        "Priority": 1,
        "Statement": {
          "ManagedRuleGroupStatement": {
            "VendorName": "AWS",
            "Name": "AWSManagedRulesCommonRuleSet"
          }
        },
        "OverrideAction": {"None": {}},
        "VisibilityConfig": {
          "SampledRequestsEnabled": true,
          "CloudWatchMetricsEnabled": true,
          "MetricName": "CommonRuleSet"
        }
      },
      {
        "Name": "AWS-AWSManagedRulesSQLiRuleSet",
        "Priority": 2,
        "Statement": {
          "ManagedRuleGroupStatement": {
            "VendorName": "AWS",
            "Name": "AWSManagedRulesSQLiRuleSet"
          }
        },
        "OverrideAction": {"None": {}},
        "VisibilityConfig": {
          "SampledRequestsEnabled": true,
          "CloudWatchMetricsEnabled": true,
          "MetricName": "SQLiRuleSet"
        }
      }
    ]' \
    --visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName=ProductionWAF

AWS Managed Rule Groups

Rule Group What It Blocks
AWSManagedRulesCommonRuleSet OWASP Top 10 vulnerabilities
AWSManagedRulesSQLiRuleSet SQL injection attempts
AWSManagedRulesKnownBadInputsRuleSet Known malicious patterns
AWSManagedRulesBotControlRuleSet Bad bots and scrapers
AWSManagedRulesAmazonIpReputationList IPs with bad reputation
AWSManagedRulesAnonymousIpList VPNs, Tor, proxies

Rate Limiting

# Add a rate-limiting rule (max 2000 requests per 5 minutes per IP)
{
  "Name": "RateLimit",
  "Priority": 0,
  "Statement": {
    "RateBasedStatement": {
      "Limit": 2000,
      "AggregateKeyType": "IP"
    }
  },
  "Action": {"Block": {}},
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "RateLimit"
  }
}

IP Blocklist / Allowlist

# Create an IP set for blocking
$ aws wafv2 create-ip-set \
    --name blocked-ips \
    --scope REGIONAL \
    --ip-address-version IPV4 \
    --addresses "1.2.3.4/32" "5.6.7.0/24"

# Reference in a rule
{
  "Name": "BlockBadIPs",
  "Priority": 0,
  "Statement": {
    "IPSetReferenceStatement": {
      "ARN": "arn:aws:wafv2:...:regional/ipset/blocked-ips/abc123"
    }
  },
  "Action": {"Block": {}},
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "BlockBadIPs"
  }
}

Associating WAF with ALB

# Associate the Web ACL with an ALB
$ aws wafv2 associate-web-acl \
    --web-acl-arn arn:aws:wafv2:ap-south-1:123456789012:regional/webacl/production-waf/abc123 \
    --resource-arn arn:aws:elasticloadbalancing:ap-south-1:123456789012:loadbalancer/app/my-alb/def456

Monitoring WAF

# View sampled requests
$ aws wafv2 get-sampled-requests \
    --web-acl-arn arn:aws:wafv2:...:regional/webacl/production-waf/abc123 \
    --rule-metric-name CommonRuleSet \
    --scope REGIONAL \
    --time-window StartTime=2026-03-30T00:00:00Z,EndTime=2026-03-30T23:59:59Z \
    --max-items 10

Common Mistakes

Mistake Why It Hurts Fix
No WAF on public ALBs Exposed to SQL injection, XSS Always attach WAF to public-facing resources
Blocking in production without testing Legitimate traffic blocked Start in Count mode, review, then switch to Block
No rate limiting Vulnerable to DDoS Add rate-based rules
Not monitoring blocked requests Don’t know if rules are too aggressive Enable CloudWatch metrics and sampled requests

Quick Reference

Task Command
Create Web ACL aws wafv2 create-web-acl --name NAME --scope REGIONAL --default-action Allow={} --rules '...'
Associate with ALB aws wafv2 associate-web-acl --web-acl-arn ACL_ARN --resource-arn ALB_ARN
List Web ACLs aws wafv2 list-web-acls --scope REGIONAL
Get sampled requests aws wafv2 get-sampled-requests --web-acl-arn ARN --rule-metric-name METRIC --scope REGIONAL ...
Create IP set aws wafv2 create-ip-set --name NAME --scope REGIONAL --ip-address-version IPV4 --addresses ...

Next → Advanced Networking Exercises

Updated: