Caddy Web Sunucusunda CrowdSec Güvenlik Entegrasyonu

Modern web altyapılarında güvenlik artık “sonradan düşünülecek bir şey” değil, tasarımın merkezinde yer alması gereken bir unsur. Caddy’yi tercih edenler genellikle onun sadeliğini ve otomatik HTTPS özelliğini seviyor, ancak tek başına bir web sunucusu günümüzün saldırı yüzeyini karşılamak için yeterli değil. İşte burada CrowdSec devreye giriyor. CrowdSec, davranış tabanlı tehdit tespiti yapan, topluluk destekli bir güvenlik motorudur ve Caddy ile entegrasyonu düşündüğünden çok daha temiz bir şekilde çalışıyor. Bu yazıda sıfırdan başlayarak Caddy + CrowdSec entegrasyonunu nasıl kuracağınızı, yapılandıracağınızı ve production ortamında nasıl işleteceğinizi adım adım ele alacağız.

CrowdSec Nedir ve Neden Caddy ile Kullanmalısınız?

CrowdSec, Fail2Ban’ın modern ve dağıtık bir alternatifi olarak düşünülebilir. Ancak Fail2Ban’dan farkı şu: sadece kendi sunucunuzdaki logları analiz etmekle kalmaz, aynı zamanda global bir tehdit istihbaratı ağından beslenir. Binlerce kullanıcının raporladığı kötü amaçlı IP’ler otomatik olarak sizin sunucunuza da uygulanır.

Caddy ile entegrasyonun iki yolu vardır:

  • Bouncer yaklaşımı: CrowdSec ayrı bir servis olarak çalışır, Caddy ise bir “bouncer” (engelleyici) modülü aracılığıyla CrowdSec API’sine bağlanır ve kararları gerçek zamanlı olarak uygular.
  • Log tabanlı yaklaşım: CrowdSec, Caddy’nin ürettiği access log dosyalarını okuyarak analiz yapar.

Bu yazıda her ikisini de ele alacağız, ancak ağırlıklı olarak daha güçlü ve reaktif olan bouncer yaklaşımını işleyeceğiz.

Ön Gereksinimler

Kuruluma başlamadan önce sisteminizin şu koşulları sağladığından emin olun:

  • Ubuntu 22.04 veya Debian 12 tabanlı bir sunucu (diğer dağıtımlarda komutlar biraz farklılaşabilir)
  • Caddy v2.7 veya üstü (tercihen Xcaddy ile derlenmiş)
  • Root veya sudo yetkisi
  • Açık portlar: 80, 443

Sisteminizi güncelleyerek başlayalım:

sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget gnupg2 software-properties-common

Caddy Kurulumu (Xcaddy ile)

Standart Caddy paketi CrowdSec bouncer modülünü içermez. Bu yüzden Xcaddy kullanarak Caddy’yi özel modüllerle derlememiz gerekiyor.

Önce Go’yu kuralım:

wget https://go.dev/dl/go1.21.5.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.21.5.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc
go version

Ardından Xcaddy’yi kuralım:

go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
export PATH=$PATH:$(go env GOPATH)/bin

Şimdi CrowdSec bouncer modülüyle birlikte Caddy’yi derleyelim:

xcaddy build 
  --with github.com/hslatman/caddy-crowdsec-bouncer/http@latest 
  --with github.com/hslatman/caddy-crowdsec-bouncer/layer4@latest

sudo mv caddy /usr/local/bin/caddy
sudo chmod +x /usr/local/bin/caddy
caddy version

Derleme birkaç dakika sürebilir. Tamamlandığında binary’yi doğru konuma taşıdık. Şimdi Caddy’yi bir systemd servisi olarak yapılandıralım:

sudo groupadd --system caddy
sudo useradd --system 
  --gid caddy 
  --create-home 
  --home-dir /var/lib/caddy 
  --shell /usr/sbin/nologin 
  --comment "Caddy web server" 
  caddy

sudo mkdir -p /etc/caddy
sudo mkdir -p /var/log/caddy
sudo chown caddy:caddy /var/log/caddy

cat << 'EOF' | sudo tee /etc/systemd/system/caddy.service
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/local/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable caddy

CrowdSec Kurulumu

CrowdSec’i resmi deposundan kuralım:

curl -s https://packagecloud.io/install/repositories/crowdsec/crowdsec/script.deb.sh | sudo bash
sudo apt install -y crowdsec

# Servis durumunu kontrol edelim
sudo systemctl status crowdsec

CrowdSec kurulumu tamamlandıktan sonra, Caddy için gerekli olan collection paketini ekleyelim. Collection’lar, belirli yazılım türleri için hazırlanmış parser ve scenario gruplarıdır:

# Caddy için resmi collection henüz yoksa Nginx collection'ı da işe yarar
# çünkü access log formatı benzer şekilde ayarlanabilir
sudo cscli collections install crowdsecurity/caddy
sudo cscli collections install crowdsecurity/base-http-scenarios
sudo cscli collections install crowdsecurity/http-cve

# Kurulu collection'ları listeleyelim
sudo cscli collections list

CrowdSec’i Caddy Log Formatına Göre Yapılandırma

CrowdSec’in Caddy loglarını düzgün okuyabilmesi için hem Caddy’nin log formatını hem de CrowdSec’in acquis (kaynak) yapılandırmasını ayarlamamız gerekiyor.

Önce Caddy’nin JSON formatında log üretmesini sağlayalım. /etc/caddy/Caddyfile dosyasını oluşturalım:

cat << 'EOF' | sudo tee /etc/caddy/Caddyfile
{
    # Global ayarlar
    admin localhost:2019
    log {
        output file /var/log/caddy/access.log {
            roll_size 100mb
            roll_keep 10
        }
        format json
        level INFO
    }
}

example.com {
    root * /var/www/html
    file_server
    
    # CrowdSec bouncer direktifi
    crowdsec {
        api_url http://localhost:8080
        api_key {$CROWDSEC_API_KEY}
        ticker_interval 15s
    }
    
    encode gzip
    
    log {
        output file /var/log/caddy/example.com-access.log {
            roll_size 50mb
            roll_keep 7
        }
        format json
    }
}
EOF

Şimdi CrowdSec’e bu log dosyasını nerede bulacağını söyleyelim:

cat << 'EOF' | sudo tee /etc/crowdsec/acquis.yaml
---
filenames:
  - /var/log/caddy/*.log
labels:
  type: caddy
---
EOF

Eğer acquis.yaml yerine acquis.d dizini kullanıyorsanız:

sudo mkdir -p /etc/crowdsec/acquis.d

cat << 'EOF' | sudo tee /etc/crowdsec/acquis.d/caddy.yaml
filenames:
  - /var/log/caddy/access.log
  - /var/log/caddy/*.log
labels:
  type: caddy
EOF

Bouncer API Anahtarı Oluşturma

Caddy bouncer modülünün CrowdSec Local API’sine bağlanabilmesi için bir API anahtarı oluşturmamız gerekiyor:

# Bouncer kaydı oluştur
sudo cscli bouncers add caddy-bouncer

# Çıktı şöyle görünecek:
# Api key for 'caddy-bouncer':
# abc123def456...
# Bu anahtarı güvenli bir yerde saklayın!

Bu anahtarı bir environment variable olarak tanımlayalım. Systemd servis dosyasını bu şekilde düzenleyebilirsiniz:

sudo mkdir -p /etc/caddy
sudo touch /etc/caddy/.env

# API anahtarını dosyaya yazın (gerçek anahtarınızla değiştirin)
echo 'CROWDSEC_API_KEY=abc123def456...' | sudo tee /etc/caddy/.env
sudo chmod 600 /etc/caddy/.env
sudo chown caddy:caddy /etc/caddy/.env

# Systemd service dosyasına EnvironmentFile ekleyin
sudo sed -i '/ExecStart/i EnvironmentFile=/etc/caddy/.env' /etc/systemd/system/caddy.service
sudo systemctl daemon-reload

Alternatif olarak API anahtarını doğrudan Caddyfile içinde de kullanabilirsiniz ancak bu güvenlik açısından önerilmez. Production ortamında her zaman environment variable kullanın.

Servisleri Başlatma ve Test Etme

Her şey hazır, servisleri sırasıyla başlatalım:

# CrowdSec'i yeniden başlat
sudo systemctl restart crowdsec
sudo systemctl status crowdsec

# Caddy'yi başlat
sudo systemctl start caddy
sudo systemctl status caddy

# Log dosyalarını izle
sudo journalctl -u crowdsec -f &
sudo journalctl -u caddy -f &

CrowdSec’in kararlarını ve mevcut engellemeleri kontrol edelim:

# Aktif kararları listele
sudo cscli decisions list

# Aktif alert'leri listele
sudo cscli alerts list

# Bouncer'ların bağlı olup olmadığını kontrol et
sudo cscli bouncers list

Gerçek Dünya Senaryosu: WordPress Saldırısı Tespiti

Diyelim ki bir WordPress sitesi yönetiyorsunuz ve /wp-login.php dosyasına brute force saldırısı var. CrowdSec bu senaryoyu otomatik olarak algılamalı. Test edelim:

# Önce mevcut log akışını izleyelim
sudo tail -f /var/log/caddy/access.log | python3 -m json.tool

# Başka bir terminalden simüle edilmiş brute force (DİKKAT: sadece kendi sunucunuzda test edin)
for i in {1..20}; do
  curl -s -o /dev/null -w "%{http_code}n" 
    -X POST https://example.com/wp-login.php 
    --data "log=admin&pwd=wrongpassword$i"
  sleep 0.5
done

Birkaç dakika içinde CrowdSec bu IP’yi tespit edip karar üretmeli:

# Kararı kontrol et
sudo cscli decisions list

# Manuel olarak bir IP ekleyip test edebilirsiniz
sudo cscli decisions add --ip 192.168.1.100 --duration 1h --reason "test-engelleme"

# Engellenen IP'den istek geldiğinde Caddy 403 döndürmeli
curl -v http://example.com -H "X-Forwarded-For: 192.168.1.100"

# Test bittikten sonra kaldırın
sudo cscli decisions delete --ip 192.168.1.100

Whitelist (İzin Listesi) Yapılandırması

Yönetim IP’lerinizin veya güvendiğiniz aralıkların yanlışlıkla engellenmemesi için whitelist tanımlamak kritik öneme sahip:

cat << 'EOF' | sudo tee /etc/crowdsec/parsers/s02-enrich/mywhitelists.yaml
name: crowdsecurity/whitelists
description: "Guvenilir IP'leri beyaz listeye al"
whitelist:
  reason: "Yerel aglar ve yonetim IP'leri"
  ip:
    - "127.0.0.1"
    - "192.168.1.50"
  cidr:
    - "10.0.0.0/8"
    - "172.16.0.0/12"
    - "192.168.0.0/16"
EOF

sudo systemctl reload crowdsec

Özel Senaryolar Oluşturma

CrowdSec’in varsayılan kuralları dışında kendi saldırı profillerinizi de tanımlayabilirsiniz. Örneğin, /admin paneline çok sık erişen IP’leri engellemek için:

cat << 'EOF' | sudo tee /etc/crowdsec/scenarios/custom-admin-bf.yaml
type: leaky
name: custom/admin-bruteforce
description: "Admin sayfasina brute force korumasi"
filter: "evt.Meta.log_type == 'http_access-log' && evt.Parsed.request contains '/admin'"
groupby: evt.Meta.source_ip
capacity: 5
leakspeed: "10s"
blackhole: 5m
labels:
  service: http
  type: bruteforce
  remediation: true
EOF

sudo systemctl reload crowdsec

# Senaryonun yüklendiğini doğrula
sudo cscli scenarios list | grep custom

CrowdSec Hub ile Tehdit İstihbaratı

CrowdSec’in en güçlü özelliklerinden biri, global topluluk tarafından beslenen tehdit istihbaratıdır. Bu özelliği aktifleştirmek için bir CrowdSec hesabı açıp enrollment yapmanız gerekiyor:

# CrowdSec Central API'ye kayıt (crowdsec.net'ten aldığınız token ile)
sudo cscli capi register

# Enrollment token'ını CrowdSec konsolundan alın
sudo cscli console enroll <enrollment-token>

# Bağlantıyı test edin
sudo cscli capi status

# Hub güncellemelerini çekin
sudo cscli hub update
sudo cscli hub upgrade

Bu adımdan sonra dünyanın dört bir yanındaki CrowdSec kullanıcılarının tespit ettiği kötü amaçlı IP’ler otomatik olarak sizin blocklist’inize eklenecek. Bu özellik, henüz sizi hedeflemeyen ama başkalarına saldıran IP’leri proaktif olarak engellemenizi sağlar.

Prometheus ile İzleme

CrowdSec ve Caddy her ikisi de Prometheus metriklerini destekliyor. Monitoring altyapınıza entegre etmek için:

# CrowdSec Prometheus endpoint kontrolü
curl http://localhost:6060/metrics | grep crowdsec

# Caddy admin API üzerinden metrikler
curl http://localhost:2019/metrics

Grafana dashboard için CrowdSec’in resmi dashboard ID’si 14584‘tür. Prometheus scrape konfigürasyonuna şunları ekleyin:

cat << 'EOF' >> /etc/prometheus/prometheus.yml

  - job_name: 'crowdsec'
    static_configs:
      - targets: ['localhost:6060']
    
  - job_name: 'caddy'
    static_configs:
      - targets: ['localhost:2019']
EOF

Firewall ile Katmanlı Güvenlik

Bouncer yaklaşımı HTTP katmanında çalışır, yani engellenmiş IP’den gelen paketler hala sunucuya ulaşır. Daha derin bir koruma için CrowdSec’in cs-firewall-bouncer‘ını da kurabilirsiniz:

sudo apt install -y crowdsec-firewall-bouncer-nftables

# Konfigürasyonu düzenle
sudo nano /etc/crowdsec/bouncers/crowdsec-firewall-bouncer.yaml

# api_key satırını güncelleyin
sudo cscli bouncers add firewall-bouncer
# Üretilen anahtarı yaml dosyasına yapıştırın

sudo systemctl enable --now crowdsec-firewall-bouncer
sudo systemctl status crowdsec-firewall-bouncer

# NFTables kurallarını kontrol et
sudo nft list ruleset | grep crowdsec

Bu sayede kötü amaçlı IP’ler hem network katmanında (NFTables ile) hem de uygulama katmanında (Caddy bouncer ile) engellenir. Katmanlı savunma prensibi gereği bu yaklaşım çok daha güvenlidir.

Sık Karşılaşılan Sorunlar ve Çözümleri

Bouncer bağlanamıyor hatası: CrowdSec Local API’nin çalışıp çalışmadığını kontrol edin.

sudo systemctl status crowdsec
sudo cscli lapi status
# Port 8080'in dinlenip dinlenmediğini kontrol edin
ss -tlnp | grep 8080

Log dosyaları okunmuyor: Caddy kullanıcısının log dizinine yazma, CrowdSec kullanıcısının ise okuma yetkisi olduğundan emin olun.

sudo chmod 755 /var/log/caddy
sudo chmod 644 /var/log/caddy/*.log
# CrowdSec'i crowdsec grubuna ekleyin ve caddy loglarına erişim verin
sudo usermod -aG caddy crowdsec
sudo systemctl restart crowdsec

Parser eşleşmiyor: Caddy log formatının CrowdSec parser’ıyla uyumlu olup olmadığını test edin.

sudo cscli explain --file /var/log/caddy/access.log --type caddy --verbose

Yanlış pozitifler çok fazla: Sensitivity ayarını düşürün veya whitelist’i genişletin. Belirli bir senaryo için eşiği artırmak mümkün:

sudo cscli scenarios inspect crowdsecurity/http-crawl-non_statics

Sonuç

Caddy ile CrowdSec entegrasyonu, hem kurulum kolaylığı hem de güvenlik derinliği açısından oldukça etkileyici bir kombinasyon sunuyor. Caddy’nin temiz yapılandırma sözdizimi ve otomatik TLS yönetimi, CrowdSec’in davranış tabanlı tehdit tespiti ve global tehdit istihbaratıyla birleşince sağlam bir savunma katmanı ortaya çıkıyor.

Bu yazıda ele aldığımız temel noktalar şöyle özetlenebilir:

  • Xcaddy ile özel modül desteği
  • CrowdSec bouncer entegrasyonu ile HTTP katmanında gerçek zamanlı engelleme
  • Log tabanlı tehdit analizi için doğru format yapılandırması
  • Whitelist ve özel senaryo tanımlarıyla kalibrasyonu ince ayar yapma
  • Firewall bouncer ile ağ katmanında ek koruma
  • Prometheus ile izleme altyapısı

Production’a geçmeden önce mutlaka kendi ortamınızda test edin, whitelist’lerinizi dikkatlice hazırlayın ve monitoring’i devreye alın. CrowdSec’in Hub güncellemelerini düzenli yapmayı da ihmal etmeyin; yeni tehdit senaryoları sürekli ekleniyor. Güvenlik bir hedef değil, süregelen bir süreçtir ve bu araçlar o süreci önemli ölçüde kolaylaştırıyor.

Yorum yapın