AWS WAF ile Web Uygulama Güvenlik Duvarı Kurulumu ve Yönetimi
Web uygulamalarınız internete açık her an saldırı altında. SQL injection, XSS, bot trafiği, DDoS… Bunları manuel olarak yönetmeye çalışmak hem yorucu hem de etkisiz. AWS WAF tam da bu noktada devreye giriyor ve doğru yapılandırıldığında gerçekten hayat kurtarıcı bir araç haline geliyor. Bu yazıda AWS WAF’ı sıfırdan yapılandırmayı, gerçek dünya senaryolarını ve production ortamında dikkat edilmesi gereken noktalara değineceğim.
AWS WAF Nedir ve Nasıl Çalışır?
AWS WAF (Web Application Firewall), HTTP/HTTPS trafiğini uygulama katmanında (Layer 7) filtreleyen bir güvenlik servisidir. CloudFront, Application Load Balancer, API Gateway ve AppSync ile entegre çalışır. Temel mantığı şu: gelen her isteği tanımladığınız kurallara göre değerlendirir ve Allow, Block veya Count aksiyonu uygular.
WAF’ın güzel yanı, ağ katmanı yerine uygulama katmanında çalışması. Yani sadece IP adresi veya port bazında değil, HTTP header’ları, URI, query string, body içeriği gibi detaylara göre karar verebilirsiniz. Bu da onu SQL injection veya XSS gibi saldırılara karşı çok daha etkili kılıyor.
Web ACL (Access Control List): WAF’ın temel yapı taşı. İçinde kurallar barındırır ve bir kaynağa (ALB, CloudFront vb.) attach edilir.
Rule: Her kural bir koşul kümesi ve aksiyon içerir. Koşullar sağlandığında belirtilen aksiyon tetiklenir.
Rule Group: Birden fazla kuralı gruplayan yapı. AWS managed rule group’ları kullanabileceğiniz gibi kendi özel gruplarınızı da oluşturabilirsiniz.
Capacity Unit (WCU): Her kuralın bir kapasitesi var. Web ACL başına 1500 WCU limiti var, bu da kaç tane ve ne kadar karmaşık kural ekleyebileceğinizi belirliyor.
İlk Web ACL Oluşturma
AWS CLI ile başlayalım. Önce temel bir Web ACL oluşturup sonra üzerine inşa edeceğiz.
# Web ACL oluştur (Regional - ALB için)
aws wafv2 create-web-acl
--name "production-web-acl"
--scope REGIONAL
--default-action Allow={}
--description "Production ortami icin ana WAF kurallari"
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName="ProductionWebACL"
--region eu-west-1
# Oluşturulan Web ACL'nin ID ve ARN'ını al
aws wafv2 list-web-acls
--scope REGIONAL
--region eu-west-1
--query 'WebACLs[?Name==`production-web-acl`]'
CloudFront için scope değeri CLOUDFRONT olmalı ve bölge mutlaka us-east-1 olmalı. Bu sık yapılan hatalardan biri, dikkat edin.
# ALB'ye Web ACL attach et
aws wafv2 associate-web-acl
--web-acl-arn "arn:aws:wafv2:eu-west-1:123456789012:regional/webacl/production-web-acl/abc12345-..."
--resource-arn "arn:aws:elasticloadbalancing:eu-west-1:123456789012:loadbalancer/app/my-alb/..."
--region eu-west-1
AWS Managed Rule Group’larını Kullanmak
Sıfırdan kural yazmak zaman alıcı. AWS’nin hazır kural grupları bu işi hızlandırıyor. Özellikle başlangıç için mükemmel.
# Mevcut managed rule group'larını listele
aws wafv2 list-available-managed-rule-groups
--scope REGIONAL
--region eu-west-1
# Belirli bir rule group'un detaylarını gör
aws wafv2 describe-managed-rule-group
--vendor-name AWS
--name AWSManagedRulesCommonRuleSet
--scope REGIONAL
--region eu-west-1
En çok kullanılan managed rule group’ları şunlar:
- AWSManagedRulesCommonRuleSet: Genel web saldırılarına karşı temel koruma. OWASP Top 10’u kapsar.
- AWSManagedRulesKnownBadInputsRuleSet: Bilinen zararlı input pattern’larını bloklar.
- AWSManagedRulesSQLiRuleSet: SQL injection saldırılarına karşı özelleşmiş kurallar.
- AWSManagedRulesLinuxRuleSet: Linux sistemlere yönelik saldırıları engeller.
- AWSManagedRulesBotControlRuleSet: Bot trafiğini tespit ve yönetir (ekstra ücretli).
- AWSManagedRulesATPRuleSet: Account takeover saldırılarına karşı (ekstra ücretli).
Şimdi bu kuralları Web ACL’ye nasıl ekleyeceğimize bakalım. JSON ile bir konfigürasyon dosyası hazırlayıp uygulayacağız:
# rules.json dosyası oluştur ve Web ACL'yi güncelle
cat > /tmp/waf-rules.json << 'EOF'
[
{
"Name": "AWSManagedCommonRules",
"Priority": 1,
"OverrideAction": {"None": {}},
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesCommonRuleSet",
"ExcludedRules": [
{"Name": "SizeRestrictions_BODY"}
]
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "CommonRuleSet"
}
},
{
"Name": "AWSManagedSQLiRules",
"Priority": 2,
"OverrideAction": {"None": {}},
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesSQLiRuleSet"
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "SQLiRuleSet"
}
}
]
EOF
# Web ACL'yi güncelle (önce mevcut lock token'ı al)
LOCK_TOKEN=$(aws wafv2 get-web-acl
--name "production-web-acl"
--scope REGIONAL
--id "abc12345-..."
--region eu-west-1
--query 'LockToken' --output text)
aws wafv2 update-web-acl
--name "production-web-acl"
--scope REGIONAL
--id "abc12345-..."
--lock-token $LOCK_TOKEN
--default-action Allow={}
--rules file:///tmp/waf-rules.json
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName="ProductionWebACL"
--region eu-west-1
Dikkat: SizeRestrictions_BODY kuralını exclude ettim çünkü büyük dosya upload eden uygulamalarda false positive oluşturuyor. Hangi kuralları exclude edeceğinizi Count modunda test ederek belirlemenizi öneririm.
Özel Kurallar Yazmak
Managed rule’lar her senaryoyu kapsamaz. Kendi iş mantığınıza özgü kurallar yazmanız gerekebilir.
IP Tabanlı Kural
# Önce bir IP set oluştur
aws wafv2 create-ip-set
--name "blocked-ips"
--scope REGIONAL
--ip-address-version IPV4
--addresses "192.0.2.0/24" "198.51.100.44/32"
--region eu-west-1
# Trusted IP'leri whitelist'e al
aws wafv2 create-ip-set
--name "trusted-ips"
--scope REGIONAL
--ip-address-version IPV4
--addresses "10.0.0.0/8" "203.0.113.100/32"
--region eu-west-1
Rate Limiting Kuralı
Rate limiting, DDoS koruması ve brute force saldırılarına karşı vazgeçilmez. Örneğin login endpoint’ine gelen istekleri sınırlayalım:
cat > /tmp/rate-limit-rule.json << 'EOF'
{
"Name": "LoginRateLimit",
"Priority": 5,
"Action": {"Block": {}},
"Statement": {
"RateBasedStatement": {
"Limit": 100,
"AggregateKeyType": "IP",
"ScopeDownStatement": {
"ByteMatchStatement": {
"SearchString": "/api/auth/login",
"FieldToMatch": {"UriPath": {}},
"TextTransformations": [
{"Priority": 0, "Type": "LOWERCASE"}
],
"PositionalConstraint": "STARTS_WITH"
}
}
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "LoginRateLimit"
}
}
EOF
Bu kural, /api/auth/login endpoint’ine 5 dakika içinde 100’den fazla istek gönderen IP’leri otomatik olarak blokluyor.
Geo Restriction Kuralı
Uygulamanız sadece belirli ülkelere hizmet veriyorsa coğrafi kısıtlama mantıklı:
cat > /tmp/geo-block-rule.json << 'EOF'
{
"Name": "GeoBlockHighRiskCountries",
"Priority": 3,
"Action": {"Block": {}},
"Statement": {
"GeoMatchStatement": {
"CountryCodes": ["KP", "IR", "CU", "SY"]
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "GeoBlock"
}
}
EOF
User-Agent Filtreleme
Kötü niyetli botları veya scraper’ları user-agent bazında engellemek için:
cat > /tmp/bad-bot-rule.json << 'EOF'
{
"Name": "BlockBadBots",
"Priority": 4,
"Action": {"Block": {}},
"Statement": {
"OrStatement": {
"Statements": [
{
"ByteMatchStatement": {
"SearchString": "sqlmap",
"FieldToMatch": {"SingleHeader": {"Name": "user-agent"}},
"TextTransformations": [{"Priority": 0, "Type": "LOWERCASE"}],
"PositionalConstraint": "CONTAINS"
}
},
{
"ByteMatchStatement": {
"SearchString": "nikto",
"FieldToMatch": {"SingleHeader": {"Name": "user-agent"}},
"TextTransformations": [{"Priority": 0, "Type": "LOWERCASE"}],
"PositionalConstraint": "CONTAINS"
}
},
{
"ByteMatchStatement": {
"SearchString": "masscan",
"FieldToMatch": {"SingleHeader": {"Name": "user-agent"}},
"TextTransformations": [{"Priority": 0, "Type": "LOWERCASE"}],
"PositionalConstraint": "CONTAINS"
}
}
]
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "BadBots"
}
}
EOF
Terraform ile WAF Yönetimi
Production ortamında AWS konsolu veya tek seferlik CLI komutları yeterli değil. Terraform ile infrastructure as code yaklaşımı çok daha sağlıklı.
# main.tf - AWS WAF yapılandırması
cat > waf.tf << 'TERRAFORM'
resource "aws_wafv2_ip_set" "blocked_ips" {
name = "blocked-ips"
description = "Manuel olarak engellenen IP adresleri"
scope = "REGIONAL"
ip_address_version = "IPV4"
addresses = []
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
resource "aws_wafv2_web_acl" "main" {
name = "production-web-acl"
description = "Production ortami ana WAF kurallari"
scope = "REGIONAL"
default_action {
allow {}
}
rule {
name = "AWSManagedCommonRules"
priority = 1
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
excluded_rule {
name = "SizeRestrictions_BODY"
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "CommonRuleSet"
sampled_requests_enabled = true
}
}
rule {
name = "LoginEndpointRateLimit"
priority = 5
action {
block {}
}
statement {
rate_based_statement {
limit = 100
aggregate_key_type = "IP"
scope_down_statement {
byte_match_statement {
search_string = "/api/auth/login"
positional_constraint = "STARTS_WITH"
field_to_match {
uri_path {}
}
text_transformation {
priority = 0
type = "LOWERCASE"
}
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "LoginRateLimit"
sampled_requests_enabled = true
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "ProductionWebACL"
sampled_requests_enabled = true
}
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
resource "aws_wafv2_web_acl_association" "alb" {
resource_arn = aws_lb.main.arn
web_acl_arn = aws_wafv2_web_acl.main.arn
}
TERRAFORM
Loglama ve Monitoring
WAF’ın değeri sadece bloklama değil, görünürlük sağlaması. Logları doğru yapılandırmazsanız neyin bloklandığını bilemezsiniz.
# S3 bucket'a loglama aktif et
aws wafv2 put-logging-configuration
--logging-configuration '{
"ResourceArn": "arn:aws:wafv2:eu-west-1:123456789012:regional/webacl/production-web-acl/abc12345-...",
"LogDestinationConfigs": [
"arn:aws:s3:::my-waf-logs-bucket"
],
"RedactedFields": [
{
"SingleHeader": {
"Name": "authorization"
}
}
]
}'
--region eu-west-1
# Kinesis Firehose üzerinden CloudWatch Logs'a yönlendir
aws firehose create-delivery-stream
--delivery-stream-name "aws-waf-logs-production"
--delivery-stream-type DirectPut
--extended-s3-destination-configuration '{
"RoleARN": "arn:aws:iam::123456789012:role/firehose-role",
"BucketARN": "arn:aws:s3:::my-waf-logs-bucket",
"Prefix": "waf-logs/year=!{timestamp:yyyy}/month=!{timestamp:MM}/day=!{timestamp:dd}/",
"CompressionFormat": "GZIP"
}'
--region eu-west-1
Loglar Kinesis Firehose üzerinden S3’e yazılıyor. Önemli nokta: delivery stream ismi mutlaka aws-waf-logs- prefix’iyle başlamalı, aksi halde WAF kabul etmiyor.
CloudWatch’ta anlamlı alarm kurmak için:
# Blocked request sayısı için alarm
aws cloudwatch put-metric-alarm
--alarm-name "WAF-HighBlockRate"
--alarm-description "WAF blok orani yuksek"
--metric-name BlockedRequests
--namespace AWS/WAFV2
--statistic Sum
--period 300
--threshold 1000
--comparison-operator GreaterThanThreshold
--dimensions Name=WebACL,Value=production-web-acl Name=Region,Value=eu-west-1 Name=Rule,Value=ALL
--evaluation-periods 2
--alarm-actions "arn:aws:sns:eu-west-1:123456789012:security-alerts"
--region eu-west-1
Gerçek Dünya Senaryosu: E-Ticaret Sitesi Koruma
Bir e-ticaret sitesini düşünelim. Account takeover, carding (kart test etme), scraping ve flash sale anında bot trafiği gibi sorunlarla boğuşuyor. İşte bu duruma özel bir strateji:
Karşılaşılan sorunlar ve çözümler:
- Carding saldırısı:
/checkout/paymentendpoint’ine dakikada yüzlerce istek geliyor, çalıntı kartlar test ediliyor. Çözüm: IP başına 5 dakikada 10 istek limiti. AyrıcaAWSManagedRulesATPRuleSetaktif edildi.
- Price scraping: Rakipler ürün fiyatlarını sürekli çekiyor. Çözüm: Bot Control rule group aktif edildi, bilinen bot user-agent’ları bloklandı, headless browser fingerprint’leri tespit edildi.
- Flash sale DDoS: İndirim başladığında anormal trafik. Çözüm: CloudFront seviyesinde WAF + rate limiting kombinasyonu.
- Admin panel koruması:
/adminpath’ine sadece ofis IP’leri erişebilmeli. Çözüm: Whitelist IP set oluşturuldu, diğer tüm trafik bloklandı.
# Admin panel için whitelist kuralı
cat > /tmp/admin-protection.json << 'EOF'
{
"Name": "AdminPanelProtection",
"Priority": 0,
"Action": {"Block": {}},
"Statement": {
"AndStatement": {
"Statements": [
{
"ByteMatchStatement": {
"SearchString": "/admin",
"FieldToMatch": {"UriPath": {}},
"TextTransformations": [{"Priority": 0, "Type": "LOWERCASE"}],
"PositionalConstraint": "STARTS_WITH"
}
},
{
"NotStatement": {
"Statement": {
"IPSetReferenceStatement": {
"ARN": "arn:aws:wafv2:eu-west-1:123456789012:regional/ipset/trusted-ips/..."
}
}
}
}
]
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AdminProtection"
}
}
EOF
Count Modu ile Güvenli Test
Yeni bir kural production’a geçmeden önce mutlaka Count modunda test edin. Bu, kuralın tetiklenip tetiklenmediğini görmenizi sağlar ama trafiği bloklamaz.
Managed rule group eklerken override_action olarak count seçin:
# Mevcut bir kuralı count moduna al
aws wafv2 update-web-acl
--name "production-web-acl"
--scope REGIONAL
--id "abc12345-..."
--lock-token $LOCK_TOKEN
--rules '[
{
"Name": "AWSManagedCommonRules",
"Priority": 1,
"OverrideAction": {"Count": {}},
"Statement": {
"ManagedRuleGroupStatement": {
"VendorName": "AWS",
"Name": "AWSManagedRulesCommonRuleSet"
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "CommonRuleSet-Count"
}
}
]'
--default-action Allow={}
--visibility-config SampledRequestsEnabled=true,CloudWatchMetricsEnabled=true,MetricName="ProductionWebACL"
--region eu-west-1
1-2 gün Count modunda bırakın, CloudWatch metriklerini izleyin, false positive var mı kontrol edin. Özellikle AllowedRequests vs BlockedRequests oranına bakın. Her şey yolundaysa None override action’a geçin.
Sık Yapılan Hatalar
Uzun süre AWS WAF yönetirken gördüğüm en yaygın hataları paylaşayım:
- Kural önceliğini yanlış ayarlamak: Düşük numara daha yüksek öncelik. Allow ve Block kurallarının sırası kritik. Örneğin whitelist kuralını blocklist’ten önce koymazsanız kendi kullanıcılarınızı bloklarsınız.
- WCU limitini aşmak: Bot Control ve ATP gibi gelişmiş kurallar çok WCU tüketiyor. Eklediğiniz her managed rule group’un WCU maliyetini hesaplayın.
- Loglama için doğru IAM permission’ları vermemek: WAF’ın Firehose veya S3’e yazabilmesi için servis rolü doğru yapılandırılmalı.
- Body inspection’ı ihmal etmek: Bazı saldırılar body’de gizlenir.
AWSManagedRulesCommonRuleSetiçindeki body inspection kurallarını exclude etmemeye dikkat edin.
- Test ortamında farklı, production’da farklı config: Terraform kullanmak bu sorunu çözüyor. Her ortam için ayrı workspace veya değişken seti kullanın.
Maliyet Optimizasyonu
AWS WAF ucuz değil. Yanlış yapılandırma maliyetleri patlatabilir:
- Web ACL başına aylık 5 USD sabit ücret.
- Her kural için aylık 1 USD.
- Analiz edilen her 1 milyon istek için 0.60 USD.
- Bot Control: ek 10 USD/ay + istek başına ücret.
- ATP: ek 20 USD/ay + istek başına ücret.
Maliyet düşürmek için öneriler:
- CloudFront önüne koyun: CloudFront WAF ile birleştiğinde edge lokasyonlarda filtreleme yapıyor, ALB’ye gereksiz trafik gelmiyor.
- Gereksiz kuralları kaldırın: Uygulamanızla alakasız rule group’ları eklemeyin. PHP uygulaması yoksa PHP kurallarına gerek yok.
- Sampled requests’i dikkatli kullanın: Hem WCU hem de maliyet etkisi var.
- Bot Control’ü sadece gerekli path’lere uygulayın: Scope-down statement ile
/api/path’ine limitleyebilirsiniz.
Sonuç
AWS WAF, doğru yapılandırıldığında web uygulamalarınız için çok katmanlı ve güçlü bir koruma sağlıyor. Başlangıç için AWS Managed Rule Group’larıyla başlayın, Count modunda bir süre izleyin, false positive’leri eliminate edin ve sonra Block moduna geçin. Kademeli yaklaşım hem güvenli hem de öğretici.
Infrastructure as code prensibiyle Terraform’u tercih edin, kural değişikliklerini versiyon kontrolünde tutun. Loglama ve alarmlama olmadan WAF’ın yarı değeri var, monitoring’i ihmal etmeyin. Son olarak, WAF tek başına yeterli değil: Shield, GuardDuty, Security Groups ve uygulama seviyesi güvenlik önlemleriyle birlikte katmanlı bir savunma mimarisi oluşturun.
Herhangi bir kural veya senaryo hakkında soru sormak isterseniz yorumlara yazın, elimden geldiğince yanıtlayayım.
