Fundamentos de AWS WAF e Shield para Proteção Web
AWS WAF (Web Application Firewall) e AWS Shield são serviços complementares que formam a primeira linha de defesa contra ataques na camada de aplicação e camada de rede. Shield oferece proteção automática contra ataques DDoS de camada 3 e 4, enquanto WAF fornece controle granular sobre requisições HTTP/HTTPS, permitindo bloquear padrões maliciosos específicos. Para times ágeis, compreender essa distinção é crítico: Shield Standard (gratuito) já protege sua infraestrutura automaticamente, mas Shield Advanced adiciona proteção contra ataques sofisticados e oferece suporte 24/7 do DDoS Response Team. WAF, por sua vez, requer configuração ativa e é onde sua inteligência tática entra.
O verdadeiro poder emerge quando você integra essas ferramentas ao pipeline de CI/CD. A maioria dos times ágeis falha aqui: criam regras WAF estáticas que nunca mudam. O correto é versionar suas regras WAF como código, testar em staging e promover para produção via Infrastructure as Code (IaC), permitindo rollback rápido em caso de falsos positivos.
Configuração Prática de WAF com Terraform
Vamos começar com um exemplo real. Aqui está uma configuração Terraform que implementa WAF com regras essenciais:
resource "aws_wafv2_web_acl" "main" {
name = "web-acl-production"
scope = "CLOUDFRONT"
default_action {
allow {}
}
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 0
action {
block {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
rule_action_override {
name = "SizeRestrictions_BODY"
action_to_use {
block {}
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesCommonRuleSetMetric"
sampled_requests_enabled = true
}
}
rule {
name = "RateLimitRule"
priority = 1
action {
block {}
}
statement {
rate_based_statement {
limit = 2000
aggregate_key_type = "IP"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "RateLimitRuleMetric"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "WebACLMetric"
sampled_requests_enabled = true
}
}
resource "aws_cloudfront_distribution" "cdn" {
enabled = true
web_acl_id = aws_wafv2_web_acl.main.arn
origin {
domain_name = aws_lb.main.dns_name
origin_id = "alb"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "https-only"
}
}
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "alb"
forwarded_values {
query_string = true
headers {
header_names = ["Authorization", "CloudFront-Viewer-Country"]
}
cookies {
forward = "all"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
cloudfront_default_certificate = true
}
}
Este exemplo implementa duas camadas: regras gerenciadas da AWS (que protegem contra vulnerabilidades comuns como SQL injection e XSS) e uma regra de rate limiting (máximo 2000 requisições por 5 minutos por IP). O CloudWatch Metrics integrado permite monitorar tentativas bloqueadas em tempo real.
Personalização de Regras para Seu Caso de Uso
Após o baseline, adicione regras específicas. Se sua API aceita JSON com campos de tamanho limitado, configure SizeRestrictions_BODY. Se você integra com serviços de terceiros por IP fixo, crie uma whitelist:
rule {
name = "WhitelistTrustedPartners"
priority = 0
action {
allow {}
}
statement {
ip_set_reference_statement {
arn = aws_wafv2_ip_set.trusted_partners.arn
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "WhitelistMetric"
sampled_requests_enabled = false
}
}
resource "aws_wafv2_ip_set" "trusted_partners" {
name = "trusted-partner-ips"
scope = "CLOUDFRONT"
ip_address_version = "IPV4"
addresses = ["203.0.113.0/24", "198.51.100.0/24"]
}
Monitoramento e Resposta a Incidentes
Configurar WAF sem observabilidade é como ter airbag sem velocímetro. Integre CloudWatch Logs com análise em tempo real:
import boto3
import json
from datetime import datetime, timedelta
cloudwatch = boto3.client('logs')
sns = boto3.client('sns')
def analyze_waf_logs():
query = """
fields @timestamp, action, httpRequest.clientIp, httpRequest.uri, rule
| stats count() as block_count by httpRequest.clientIp, rule
| sort block_count desc
| limit 10
"""
response = cloudwatch.start_query(
logGroupName='/aws/wafv2/production',
startTime=int((datetime.now() - timedelta(hours=1)).timestamp()),
endTime=int(datetime.now().timestamp()),
queryString=query
)
query_id = response['queryId']
# Aguardar conclusão
while True:
result = cloudwatch.get_query_results(queryId=query_id)
if result['status'] == 'Complete':
break
# Alertar se IPs maliciosos são identificados
for record in result['results']:
block_count = int([r['value'] for r in record if r['field'] == 'block_count'][0])
if block_count > 100:
sns.publish(
TopicArn='arn:aws:sns:us-east-1:123456789:waf-alerts',
Subject='WAF: Bloqueio em alta quantidade detectado',
Message=json.dumps(record, indent=2)
)
if __name__ == '__main__':
analyze_waf_logs()
Este script executa em uma Lambda agendada (CloudWatch Events) a cada hora, identifica padrões de ataque e envia alertas SNS para seu time. Integre isso com seu Slack para notificações imediatas, permitindo ação rápida em caso de falso positivo (ajuste da whitelist).
Shield Advanced para Camadas Mais Profundas
Shield Advanced ($3.000/mês) justifica-se apenas se você processa volumes alta de tráfego ou é alvo frequente. O real diferencial é o DDoS Response Team (DRT), que analisa seus logs e recommenda regras WAF personalizadas. Para times ágeis começando, comece com Shield Standard + WAF Standard e upgrade conforme necessário.
Integração com Pipeline CI/CD
Regras WAF devem ser testadas antes de produção. Aqui está como integrar com GitLab CI:
stages:
- validate
- test
- deploy
validate_waf_rules:
stage: validate
image: hashicorp/terraform:latest
script:
- terraform init
- terraform validate
- terraform plan -out=tfplan
test_waf_rules:
stage: test
image: python:3.9
script:
- pip install boto3
- python test_waf_rules.py
only:
- merge_requests
deploy_waf:
stage: deploy
image: hashicorp/terraform:latest
script:
- terraform apply tfplan
only:
- main
environment:
name: production
E o teste de segurança (test_waf_rules.py):
import boto3
import pytest
waf_client = boto3.client('wafv2')
def test_rate_limit_rule_exists():
acl = waf_client.get_web_acl(Name='web-acl-production', Scope='CLOUDFRONT')
rule_names = [r['Name'] for r in acl['WebACL']['Rules']]
assert 'RateLimitRule' in rule_names
def test_no_allow_all_rules():
acl = waf_client.get_web_acl(Name='web-acl-production', Scope='CLOUDFRONT')
for rule in acl['WebACL']['Rules']:
assert rule['Action']['Type'] != 'ALLOW' or 'whitelist' in rule['Name'].lower()
if __name__ == '__main__':
pytest.main([__file__, '-v'])
Conclusão
Três pontos essenciais aprendidos: Primeiro, WAF e Shield são complementares mas não redundantes — Shield protege infraestrutura, WAF protege aplicação. Implemente ambos. Segundo, regras WAF devem ser versionadas, testadas e auditadas como código, não configuradas manualmente no console. Terceiro, observabilidade não é opcional — sem monitoramento contínuo, você não saberá se está bloqueando ataques reais ou afastando clientes legítimos. Comece simples com regras gerenciadas AWS, adicione rate limiting e personalize com whitelists. Evoluir é mais seguro que começar perfeito.