Üretim ortamında bir web sunucusu yönetiyorsanız, erişim kontrolü meselesini er ya da geç ciddiye almak zorunda kalıyorsunuz. Belki admin panelinize sadece ofis IP’sinden girilmesini istiyorsunuz, belki API endpoint’lerinizi belirli ülkelerle kısıtlamak istiyorsunuz ya da botlardan ve zararlı IP bloklarından gelen trafiği durdurmak istiyorsunuz. Nginx ve Apache’de bu işler çeşitli modüllerle yapılıyor ama Caddy’de işler biraz farklı işliyor. Caddy, bu konuda hem daha sade hem de bazı açılardan daha güçlü bir yaklaşım sunuyor.
Bu yazıda Caddy ile IP beyaz listesi oluşturmayı, coğrafi erişim kontrolü yapmayı ve bunları gerçek dünya senaryolarında nasıl birleştireceğinizi adım adım anlatacağım.
Caddy’de Erişim Kontrolüne Genel Bakış
Caddy’nin erişim kontrol mekanizması temelde iki katmanda çalışıyor. Birincisi yerleşik remote_ip direktifi ile IP bazlı filtreleme, ikincisi ise caddy-geo-ip gibi eklentilerle coğrafi konum bazlı filtreleme. Nginx’te ngx_http_geo_module veya ngx_http_geoip2_module ile yapılan işlemlerin karşılığı Caddy’de eklenti mimarisi üzerinden geliyor.
Caddy’nin standart kurulumunda IP filtreleme için remote_ip matcher’ı kullanılıyor. Geo-IP işlevselliği için ise xcaddy ile özel bir build oluşturmanız ya da hazır binary’leri kullanmanız gerekiyor.
Temel IP Whitelist Yapılandırması
En basit senaryodan başlayalım. Diyelim ki bir admin panelini sadece belirli IP adreslerinden erişilebilir yapmak istiyorsunuz.
# /etc/caddy/Caddyfile
admin.orneksite.com {
@allowed_ips remote_ip 192.168.1.0/24 10.0.0.5 203.0.113.42
handle @allowed_ips {
reverse_proxy localhost:8080
}
handle {
respond "Erisim reddedildi." 403
}
}
Burada @allowed_ips adında bir matcher tanımladık. Bu matcher, isteğin kaynak IP’sinin belirtilen listede olup olmadığını kontrol ediyor. Eşleşme varsa isteği backend’e iletiyoruz, yoksa 403 dönüyoruz.
remote_ip matcher şu formatları destekliyor:
- Tekil IP:
192.168.1.100 - CIDR bloğu:
10.0.0.0/8 - Birden fazla değer: Boşlukla ayrılmış liste
Birden Fazla Site İçin Yeniden Kullanılabilir Yapı
Aynı IP listesini birden fazla yerde kullanıyorsanız, Caddyfile’ın snippet özelliğinden faydalanabilirsiniz:
# /etc/caddy/Caddyfile
(ofis_ipleri) {
@izinli_ip remote_ip 192.168.1.0/24 10.10.0.0/16 203.0.113.0/24
handle @izinli_ip {
{args[0]}
}
handle {
respond "Bu alana erisim yetkiniz yok." 403
}
}
admin.orneksite.com {
import ofis_ipleri "reverse_proxy localhost:8080"
}
monitoring.orneksite.com {
import ofis_ipleri "reverse_proxy localhost:3000"
}
Snippet kullanımı büyük altyapılarda hayat kurtarıyor. IP listesini tek bir yerden yönetip her yerde kullanabiliyorsunuz.
Reverse Proxy Arkasında Gerçek IP Tespiti
Cloudflare, load balancer veya herhangi bir proxy arkasında çalışıyorsanız, remote_ip matcher proxy’nin IP’sini görür, istemcinin değil. Bu durum beyaz listelerinizi işe yaramaz hale getirir.
# /etc/caddy/Caddyfile
{
# Guvenmediginiz proxy'leri buraya EKLEMEYINIZ
trusted_proxies static 10.0.0.1 10.0.0.2
}
api.orneksite.com {
# trusted_proxies ayarlandiktan sonra remote_ip
# X-Forwarded-For headerindaki gercek IP'yi kullanir
@guvenli_kaynaklar remote_ip 203.0.113.0/24 198.51.100.0/24
handle @guvenli_kaynaklar {
reverse_proxy localhost:9000
}
handle {
respond "Yetkisiz erisim." 403
}
}
Önemli uyarı: trusted_proxies ayarını dikkatli yapılandırın. Yanlış yapılandırma, saldırganların X-Forwarded-For header’ını taklit ederek IP kontrolünüzü atlatmasına neden olabilir.
Cloudflare kullanıyorsanız, Cloudflare’in IP aralıklarını trusted proxy olarak tanımlamanız gerekiyor:
{
trusted_proxies static
173.245.48.0/20
103.21.244.0/22
103.22.200.0/22
103.31.4.0/22
141.101.64.0/18
108.162.192.0/18
190.93.240.0/20
188.114.96.0/20
197.234.240.0/22
198.41.128.0/17
162.158.0.0/15
104.16.0.0/13
104.24.0.0/14
172.64.0.0/13
131.0.72.0/22
}
Geo-IP ile Ülke Bazlı Erişim Kontrolü
Coğrafi erişim kontrolü için önce xcaddy ile özel bir Caddy binary’si derlemeniz gerekiyor. Ülke bazlı filtreleme için github.com/porech/caddy-maxmind-geolocation eklentisini kullanacağız.
xcaddy Kurulumu ve Özel Build
# xcaddy kurulumu
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
# Geo-IP eklentisi ile Caddy build etme
xcaddy build
--with github.com/porech/caddy-maxmind-geolocation
# Binary'yi system path'e tasima
sudo mv caddy /usr/local/bin/caddy
sudo setcap cap_net_bind_service=+ep /usr/local/bin/caddy
Alternatif olarak, Docker tabanlı build kullanabilirsiniz:
docker run --rm -v $PWD:/output caddy:builder
xcaddy build
--output /output/caddy
--with github.com/porech/caddy-maxmind-geolocation
MaxMind GeoLite2 Veritabanı Kurulumu
Ülke tespiti için MaxMind’ın GeoLite2 veritabanına ihtiyacınız var. Ücretsiz hesap açarak indirebilirsiniz:
# MaxMind hesabinizdan license key alindiktan sonra
# mmdbinspect aracini kurun
sudo apt-get install mmdb-bin # Ubuntu/Debian
# veya
sudo dnf install libmaxminddb-utils # RHEL/Fedora
# Veritabanini indirin (license key gerekli)
wget "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=SIZIN_KEY&suffix=tar.gz"
-O GeoLite2-Country.tar.gz
tar -xzf GeoLite2-Country.tar.gz
sudo mkdir -p /etc/caddy/geoip
sudo mv GeoLite2-Country_*/GeoLite2-Country.mmdb /etc/caddy/geoip/
# Otomatik guncelleme icin cron job
echo "0 3 * * 2 root wget -q 'https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=SIZIN_KEY&suffix=tar.gz' -O /tmp/GeoLite2.tar.gz && tar -xzf /tmp/GeoLite2.tar.gz -C /tmp && mv /tmp/GeoLite2-Country_*/GeoLite2-Country.mmdb /etc/caddy/geoip/ && systemctl reload caddy" | sudo tee /etc/cron.d/geoip-update
Ülke Bazlı Erişim Yapılandırması
# /etc/caddy/Caddyfile
{
order maxmind_geolocation before file_server
}
orneksite.com {
maxmind_geolocation {
db_path /etc/caddy/geoip/GeoLite2-Country.mmdb
allow_countries TR GB DE FR NL
}
reverse_proxy localhost:8080
}
Bu yapılandırma ile Türkiye (TR), İngiltere (GB), Almanya (DE), Fransa (FR) ve Hollanda (NL) dışındaki ülkelerden gelen istekler otomatik olarak reddedilecek.
Belirli Ülkeleri Bloklama (Blacklist Yaklaşımı)
Whitelist yerine blacklist yaklaşımı tercih ediyorsanız:
orneksite.com {
maxmind_geolocation {
db_path /etc/caddy/geoip/GeoLite2-Country.mmdb
deny_countries CN RU KP IR
}
reverse_proxy localhost:8080
}
Gelişmiş Senaryo: IP Whitelist ve Geo Filtreyi Birleştirme
Gerçek dünyada genellikle birden fazla kontrol katmanı istiyorsunuz. Örneğin: “API endpoint’lerime sadece Türkiye’den erişilebilsin, ama ofis IP’lerimiz her yerden erişebilsin.”
# /etc/caddy/Caddyfile
{
order maxmind_geolocation before reverse_proxy
}
api.orneksite.com {
# Oncelikli kontrol: Ofis IP'leri her zaman gecebilir
@ofis_agi remote_ip 203.0.113.0/24 10.0.0.0/8
handle @ofis_agi {
reverse_proxy localhost:9000
}
# Geo kontrolu: Sadece Turkiye'den giris
maxmind_geolocation {
db_path /etc/caddy/geoip/GeoLite2-Country.mmdb
allow_countries TR
}
# Geo filtreden gecenler icin normal islem
reverse_proxy localhost:9000
}
API Anahtari ile Geo Kontrolunu Bypass Etme
Bazı durumlarda yabancı ülkelerden gelen ama geçerli API anahtarına sahip istemcilerin geçmesine izin vermek isteyebilirsiniz. Bu senaryoda request matcher’larını birleştiriyoruz:
api.orneksite.com {
# Gecerli API anahtarina sahip istekler geo kontrolunu atlar
@api_key_bypass {
header X-API-Key "gizli-api-anahtariniz-buraya"
}
handle @api_key_bypass {
reverse_proxy localhost:9000
}
# Diger istekler icin geo kontrolu
maxmind_geolocation {
db_path /etc/caddy/geoip/GeoLite2-Country.mmdb
allow_countries TR DE GB
}
reverse_proxy localhost:9000
}
Rate Limiting ile Entegrasyon
IP whitelist ve geo filtreye ek olarak rate limiting ekleyerek daha kapsamlı bir koruma katmanı oluşturabilirsiniz. Bunun için caddy-rate-limit eklentisini de build’e dahil etmeniz gerekiyor:
xcaddy build
--with github.com/porech/caddy-maxmind-geolocation
--with github.com/mholt/caddy-ratelimit
# /etc/caddy/Caddyfile
api.orneksite.com {
# Ofis aglari icin rate limit yok
@ofis_agi remote_ip 10.0.0.0/8 192.168.0.0/16
handle @ofis_agi {
reverse_proxy localhost:9000
}
# Geo filtre
maxmind_geolocation {
db_path /etc/caddy/geoip/GeoLite2-Country.mmdb
allow_countries TR
}
# Dis dunya icin rate limiting
rate_limit {
zone api_zone {
key {remote_host}
events 100
window 1m
}
}
reverse_proxy localhost:9000
}
Caddyfile’i Harici Dosyalarla Modüler Hale Getirme
Büyük altyapılarda IP listelerini ana Caddyfile’dan ayrı tutmak yönetimi kolaylaştırıyor:
# /etc/caddy/ip_lists/whitelist.conf icerigine yazin:
# 203.0.113.0/24
# 198.51.100.10
# 10.0.0.0/8
# /etc/caddy/Caddyfile
(guvenli_ip_listesi) {
@yetkili_ip remote_ip {
# Dosyadan okuma icin caddy-exec veya ayni dosyada
# listeleme yapmak daha pratiktir
203.0.113.0/24
198.51.100.10
10.0.0.0/8
}
}
admin.orneksite.com {
import guvenli_ip_listesi
handle @yetkili_ip {
reverse_proxy localhost:8080
}
handle {
respond "Yetkisiz erisim. IP adresiniz: {remote_host}" 403
}
}
Log Yapılandırması ile Erişim Takibi
Hangi IP’lerin bloklandığını takip etmek için detaylı loglama önemli:
# /etc/caddy/Caddyfile
{
log {
level INFO
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 10
roll_keep_for 720h
}
format json
}
}
admin.orneksite.com {
log {
output file /var/log/caddy/admin-access.log
format json
level DEBUG
}
@yetkili_ip remote_ip 203.0.113.0/24 10.0.0.0/8
handle @yetkili_ip {
reverse_proxy localhost:8080
}
handle {
log_append blocked_ip {remote_host}
respond "Erisim engellendi." 403
}
}
JSON formatındaki logları analiz etmek için:
# Son 1 saatte engellenen IP'leri listele
sudo journalctl -u caddy --since "1 hour ago" |
grep '"status":403' |
jq -r '.request.remote_addr' |
sort | uniq -c | sort -rn | head -20
# Veya log dosyasindan
cat /var/log/caddy/admin-access.log |
jq -r 'select(.status == 403) | .request.remote_addr' |
sort | uniq -c | sort -rn
Yapılandırma Testleri ve Doğrulama
Değişikliklerinizi production’a almadan önce mutlaka test edin:
# Caddyfile syntax kontrolu
caddy validate --config /etc/caddy/Caddyfile
# Yapılandırmayı yeniden yukleme (downtime yok)
sudo systemctl reload caddy
# Veya Caddy'nin kendi API'si ile
curl -X POST "http://localhost:2019/load"
-H "Content-Type: text/caddyfile"
--data-binary @/etc/caddy/Caddyfile
# Belirli bir IP'yi test etmek icin curl
curl -H "X-Forwarded-For: 203.0.113.100" https://admin.orneksite.com/
# Geo filtreyi test etmek (VPN ile farkli ulkeden test)
curl -v https://api.orneksite.com/test
Geo filtrenin doğru çalışıp çalışmadığını test etmek için:
# mmdbinspect ile bir IP'nin hangi ulkeye ait oldugunu kontrol et
mmdbinspect -db /etc/caddy/geoip/GeoLite2-Country.mmdb 8.8.8.8
# Cikti: US (Amerika Birlesik Devletleri)
mmdbinspect -db /etc/caddy/geoip/GeoLite2-Country.mmdb 5.26.0.1
# Cikti: TR (Turkiye)
Sık Karşılaşılan Sorunlar ve Çözümleri
Problem: Tüm istekler bloklanıyor, whitelist’teki IP’ler de giremiyorso
Bu genellikle proxy arkasında çalışırken oluyor. Caddy’nin gördüğü IP, gerçek istemci IP’si değil proxy IP’si. Çözüm:
{
trusted_proxies static 10.0.0.1 # load balancer IP'niz
}
Problem: Geo-IP doğru ülkeyi tanımıyorsa
MaxMind veritabanının güncel olduğundan emin olun. Veritabanı aylık güncelleniyor ve eski sürümler %5-10 hata payına sahip olabiliyor.
Problem: maxmind_geolocation direktifi tanınmıyorsa
Caddy binary’nizin eklentiyle build edildiğini doğrulayın:
caddy list-modules | grep maxmind
# Cikti: http.handlers.maxmind_geolocation gozukmuyorsa
# binary'yi yeniden olusturmaniz gerekiyor
Performans Değerlendirmesi
Geo-IP kontrolü her request için veritabanı sorgusu anlamına geliyor. MaxMind MMDB formatı bellek içi (in-memory) çalışma için optimize edilmiş olsa da yüksek trafikli sitelerde benchmark yapmanızı öneririm:
- Düşük trafik (saniyede 100 istek altı): Herhangi bir performans etkisi görmezsiniz
- Orta trafik (saniyede 100-1000 istek): Milisaniye düzeyinde gecikme artışı olabilir, genellikle kabul edilebilir
- Yüksek trafik (saniyede 1000+ istek): Caddy’nin önüne bir CDN/WAF katmanı koyarak geo filtrelemeyi orada yapmayı düşünün
IP whitelist kontrolü ise neredeyse sıfır maliyetli. Caddy bu kontrolü hash tablosunda O(1) karmaşıklıkla yapıyor.
Sonuç
Caddy ile IP whitelist ve geo erişim kontrolü, nginx veya Apache’ye kıyasla daha temiz ve okunabilir bir yapılandırma sunuyor. Temel IP filtreleme için ekstra eklenti gerekmezken, ülke bazlı kontrol için xcaddy ile özel build oluşturmanız gerekiyor. Bu biraz zahmetli görünse de, eklenti mimarisi uzun vadede büyük esneklik sağlıyor.
Pratik açıdan şunu öneriyorum: Önce remote_ip matcher ile temel IP whitelist’inizi kurun ve doğru çalıştığından emin olun. Sonra geo filtreyi ekleyin. İkisini birden aynı anda devreye almak, sorun çıktığında nereden geldiğini bulmayı zorlaştırıyor. Ayrıca her değişiklikten sonra logları takip edin; meşru kullanıcıları bloklamak, zararlı trafiğe izin vermekten çok daha kötü bir deneyim yaratıyor.
Son olarak, geo-IP veritabanını düzenli güncellemeyı unutmayın. Cron job’u bir kez kurup unutun, her hafta otomatik güncellensin. MaxMind’ın veritabanı canlı bir şey; IP bloklarının ülke atamaları değişiyor ve güncel kalmak önemli.