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.