UFW ile Coğrafi IP Engelleme: Belirli Ülkelerden Gelen Trafiği Filtreleme
Sunucunuzu yönetirken bir süre sonra fark edersiniz: Log dosyaları belirli ülkelerden gelen başarısız SSH denemeleri, port taramaları ve web scraping trafiğiyle dolup taşıyor. Belki uygulamanız sadece Türkiye’ye hizmet veriyor ve Rusya, Çin veya Brezilya’dan gelen tek bir meşru kullanıcınız bile yok. Bu durumda coğrafi IP engelleme son derece mantıklı bir güvenlik katmanı haline geliyor.
Bu yazıda UFW ile birlikte ipset ve MaxMind ya da ip-country veritabanlarını kullanarak belirli ülkelerden gelen trafiği nasıl filtreleyeceğimizi, bunu nasıl otomatize edeceğimizi ve production ortamında karşılaşabileceğiniz edge case’leri nasıl yöneteceğinizi ele alacağım.
Coğrafi IP Engelleme Neden Gereklidir?
Önce şunu netleştirelim: Coğrafi IP engelleme sihirli bir güvenlik çözümü değildir. VPN kullanan bir saldırgan bu önlemi kolayca aşabilir. Ama şunu söyleyebilirim: Sunucularımda bu yöntemi devreye aldıktan sonra başarısız SSH girişim sayısı %70-80 oranında düştü. Brute force saldırılarının büyük çoğunluğu belirli coğrafyalardan geliyor ve bu trafiği daha firewall seviyesinde kesmek hem kaynak tasarrufu sağlıyor hem de log’larınızı okunabilir tutuyor.
Gerçek dünya senaryosu olarak düşünün: Bir e-ticaret sitesi işletiyorsunuz, müşterileriniz tamamen Türkiye’de. Sunucunuzun her gece binlerce başarısız giriş denemesini işlemesi, fail2ban’ın sürekli tetiklenmesi ve application log’larının gereksiz trafikle dolması ciddi bir operasyonel yük oluşturuyor.
Gereksinimler ve Araçlar
Bu çözüm için ihtiyacınız olanlar:
- Ubuntu/Debian tabanlı bir sistem (UFW kurulu)
- ipset: Büyük IP listelerini verimli şekilde yönetmek için
- wget veya curl: IP veritabanlarını indirmek için
- xtables-addons veya hazır ülke bazlı IP listeleri
- Root veya sudo yetkisi
ipset neden bu kadar önemli? UFW kuralları iptables üzerine inşa edilir ve her IP için ayrı bir kural oluşturursanız binlerce kural ortaya çıkar. Bu hem performansı mahveder hem de yönetimi imkânsız hale getirir. ipset ise hash tabanlı yapısıyla milyonlarca IP’yi tek bir kural referansıyla işleyebilir.
# Gerekli paketleri yükleyin
sudo apt update
sudo apt install -y ipset ipset-persistent iptables-persistent wget
# ipset versiyonunu kontrol edin
ipset version
IP Veritabanı Kaynağı Seçmek
İki popüler ücretsiz kaynak var:
- ipdeny.com: Ülke bazlı CIDR bloklarını düz metin olarak sunuyor, kullanımı çok basit
- MaxMind GeoLite2: Daha kapsamlı ama API key gerektiriyor
- db-ip.com: Alternatif ücretsiz kaynak
Ben ipdeny.com’u tercih ediyorum çünkü script entegrasyonu son derece kolay. Şimdi Çin (CN) ve Rusya (RU) için örnek bir engelleme kuralı oluşturalım.
# İndirme ve çalışma dizinini oluşturun
sudo mkdir -p /opt/geoblock
cd /opt/geoblock
# Çin IP bloklarını indirin
wget -q https://www.ipdeny.com/ipblocks/data/countries/cn.zone -O cn.zone
# Rusya IP bloklarını indirin
wget -q https://www.ipdeny.com/ipblocks/data/countries/ru.zone -O ru.zone
# Kaç tane CIDR bloğu var görelim
wc -l cn.zone ru.zone
Şimdi bu IP listelerini ipset ile bir hash set’e yükleyelim:
# Çin için ipset oluştur
sudo ipset create geoblock-cn hash:net hashsize 4096 maxelem 65536
# Listedeki her CIDR bloğunu set'e ekle
while IFS= read -r cidr; do
[[ -z "$cidr" || "$cidr" == #* ]] && continue
sudo ipset add geoblock-cn "$cidr" 2>/dev/null
done < /opt/geoblock/cn.zone
echo "Çin için $(sudo ipset list geoblock-cn | grep -c '/') CIDR bloğu yüklendi"
UFW ile ipset Entegrasyonu
UFW doğrudan ipset’i desteklemez ama UFW’nin before.rules dosyasını düzenleyerek bu entegrasyonu sağlayabiliriz. Bu yaklaşım UFW yeniden başlatıldığında kurallarınızın korunmasını garanti eder.
Önce mevcut UFW kurallarının yedeğini alın:
sudo cp /etc/ufw/before.rules /etc/ufw/before.rules.backup
sudo cp /etc/ufw/before6.rules /etc/ufw/before6.rules.backup
Şimdi /etc/ufw/before.rules dosyasını düzenleyin. Dosyanın başında *filter satırından sonra, :ufw-before-input satırından önce aşağıdaki bloğu ekleyin:
sudo nano /etc/ufw/before.rules
Eklenecek içerik (dosyada *filter satırının hemen altına):
# GeoBlock - Ülke bazlı engelleme
-I ufw-before-input -m set --match-set geoblock-cn src -j DROP
-I ufw-before-input -m set --match-set geoblock-ru src -j DROP
Bu yapılandırmanın püf noktası şudur: -I ile INSERT kullanıyoruz, -A (APPEND) değil. Böylece coğrafi engelleme kuralları diğer tüm kurallardan önce değerlendiriliyor ve eşleşen paketler diğer kurallara hiç uğramadan düşürülüyor.
Tam Otomatizasyon Scripti
Tek seferlik kurulum yetmez; IP veritabanları değişiyor, yeni IP blokları ekleniyor, eski bloklar kaldırılıyor. Haftalık güncelleme yapan bir script yazalım:
#!/bin/bash
# /opt/geoblock/update-geoblock.sh
# UFW Coğrafi IP Engelleme Güncelleme Scripti
set -euo pipefail
LOG_FILE="/var/log/geoblock-update.log"
WORK_DIR="/opt/geoblock"
IPDENY_URL="https://www.ipdeny.com/ipblocks/data/countries"
# Engellenecek ülke kodları - ISO 3166-1 alpha-2
BLOCKED_COUNTRIES=("cn" "ru" "kp" "ir" "br")
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "Coğrafi IP engelleme güncellemesi başlatıldı"
cd "$WORK_DIR"
for country in "${BLOCKED_COUNTRIES[@]}"; do
SET_NAME="geoblock-${country}"
ZONE_FILE="${country}.zone"
TEMP_SET="${SET_NAME}-temp"
log "${country^^} için IP listesi indiriliyor..."
# Zone dosyasını indir
if ! wget -q "${IPDENY_URL}/${country}.zone" -O "${ZONE_FILE}.tmp"; then
log "HATA: ${country} için indirme başarısız, atlanıyor"
continue
fi
mv "${ZONE_FILE}.tmp" "${ZONE_FILE}"
# Geçici set oluştur (swap için)
ipset create "$TEMP_SET" hash:net hashsize 4096 maxelem 131072 2>/dev/null ||
ipset flush "$TEMP_SET"
# IP'leri geçici sete yükle
ADDED=0
while IFS= read -r cidr; do
[[ -z "$cidr" || "$cidr" == #* ]] && continue
if ipset add "$TEMP_SET" "$cidr" 2>/dev/null; then
((ADDED++))
fi
done < "$ZONE_FILE"
# Ana seti oluştur (yoksa)
ipset create "$SET_NAME" hash:net hashsize 4096 maxelem 131072 2>/dev/null || true
# Atomik swap - servis kesintisi olmadan güncelleme
ipset swap "$TEMP_SET" "$SET_NAME"
ipset destroy "$TEMP_SET"
log "${country^^}: ${ADDED} CIDR bloğu yüklendi"
done
# UFW kurallarının aktif olduğunu doğrula
for country in "${BLOCKED_COUNTRIES[@]}"; do
SET_NAME="geoblock-${country}"
if ! iptables -C ufw-before-input -m set --match-set "$SET_NAME" src -j DROP 2>/dev/null; then
log "UYARI: ${SET_NAME} için iptables kuralı bulunamadı, ekleniyor..."
iptables -I ufw-before-input -m set --match-set "$SET_NAME" src -j DROP
fi
done
# ipset kurallarını kalıcı hale getir
ipset save > /etc/ipset.rules
log "Güncelleme tamamlandı"
Script’i çalıştırılabilir hale getirin ve test edin:
sudo chmod +x /opt/geoblock/update-geoblock.sh
sudo /opt/geoblock/update-geoblock.sh
# Log'u kontrol edin
tail -f /var/log/geoblock-update.log
Sistem Başlangıcında Otomatik Yükleme
Sunucu yeniden başladığında ipset kuralları silinir. Bu durumu engellemek için iki şey yapmanız gerekiyor: ipset kurallarını kaydetmek ve sistem açılışında yüklemek.
# Mevcut ipset kurallarını kaydet
sudo ipset save > /etc/ipset.rules
# Systemd servisi oluştur
sudo nano /etc/systemd/system/ipset-restore.service
Servis dosyası içeriği:
[Unit]
Description=ipset GeoBlock Kurallarini Yukle
Before=ufw.service network.target
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'ipset restore < /etc/ipset.rules'
ExecStop=/bin/bash -c 'ipset save > /etc/ipset.rules'
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
# Servisi etkinleştirin
sudo systemctl daemon-reload
sudo systemctl enable ipset-restore.service
sudo systemctl start ipset-restore.service
# Durumu kontrol edin
sudo systemctl status ipset-restore.service
Cron ile Haftalık Güncelleme
# Crontab düzenle
sudo crontab -e
# Her Pazar gece 02:00'de güncelle
0 2 * * 0 /opt/geoblock/update-geoblock.sh >> /var/log/geoblock-update.log 2>&1
Engelleme Kurallarını Test Etmek
Kuralların çalışıp çalışmadığını test etmek için belirli bir IP’nin hangi set’te olduğunu kontrol edebilirsiniz:
# Belirli bir IP'nin hangi set'te olduğunu test et
sudo ipset test geoblock-cn 1.180.0.1
# "1.180.0.1 is in set geoblock-cn." çıktısı beklenir
# Aktif ipset listelerini göster
sudo ipset list -n
# Belirli bir set'in istatistiklerini gör
sudo ipset list geoblock-ru | head -20
# iptables'da kuralların var olduğunu doğrula
sudo iptables -L ufw-before-input -n --line-numbers | grep "match-set"
# Canlı trafik sayacını izle (DROP edilen paket sayısı)
sudo iptables -L ufw-before-input -n -v | grep "match-set"
Drop edilen paket sayısının artıp artmadığını izlemek iyi bir sanity check yöntemidir. Eğer sayaçlar hiç artmıyorsa kurallar muhtemelen doğru konumda değildir.
İstisna Kuralları: Whitelist Ekleme
Bazen engellediğiniz bir ülkeden meşru bir IP adresine izin vermeniz gerekebilir. Örneğin Rus ortaklı bir şirketle çalışıyorsunuz ve onların ofis IP’sini whitelist’e almanız gerekiyor. Bu durumu şöyle yönetebilirsiniz:
# Whitelist seti oluştur
sudo ipset create geoblock-whitelist hash:net
# İzin verilecek IP veya CIDR'ı ekle
sudo ipset add geoblock-whitelist 185.x.x.x/32
sudo ipset add geoblock-whitelist 91.x.x.0/24
# UFW before.rules'a whitelist kuralını DROP kurallarından ÖNCE ekle
# /etc/ufw/before.rules dosyasında şu sırayla olmalı:
# 1. Whitelist RETURN kuralı (ÖNCE)
# 2. Country DROP kuralları (SONRA)
/etc/ufw/before.rules içindeki sıralama şöyle olmalı:
-I ufw-before-input 1 -m set --match-set geoblock-whitelist src -j RETURN
-I ufw-before-input 2 -m set --match-set geoblock-cn src -j DROP
-I ufw-before-input 3 -m set --match-set geoblock-ru src -j DROP
Kural sırası kritik önem taşıyor. Whitelist RETURN kuralı DROP kurallarından önce değerlendirilmezse whitelist hiçbir işe yaramaz.
Sadece Belirli Portlarda Coğrafi Engelleme
Herkese açık bir web siteniz var ama SSH ve admin panel’inize sadece Türkiye’den erişim olsun istiyorsunuz. Bu durumda tüm trafiği değil, sadece belirli portları filtrelemek daha mantıklı:
# Sadece SSH portuna (22) coğrafi engelleme uygula
# /etc/ufw/before.rules içine eklenecek kurallar:
-I ufw-before-input -p tcp --dport 22 -m set --match-set geoblock-cn src -j DROP
-I ufw-before-input -p tcp --dport 22 -m set --match-set geoblock-ru src -j DROP
# Admin panel portu için (örneğin 8443)
-I ufw-before-input -p tcp --dport 8443 -m set --match-set geoblock-cn src -j DROP
Bu yaklaşım çok daha granüler kontrol sağlar. Web trafiğiniz etkilenmez, sadece kritik servislerinize ek bir koruma katmanı eklemiş olursunuz.
Performans Değerlendirmesi ve İzleme
ipset hash yapısı sayesinde milyon satırlık listelerde bile arama süresi O(1)’dir. Yani 50.000 IP bloğu olan bir set ile 500 IP bloğu olan bir set arasında neredeyse hiç performans farkı yoktur. Bunu şöyle doğrulayabilirsiniz:
# ipset set boyutlarını kontrol et
sudo ipset list -n | while read setname; do
count=$(sudo ipset list "$setname" | grep -c "^[0-9]" 2>/dev/null || echo 0)
echo "$setname: $count entries"
done
# Sistem üzerindeki iptables kuralı sayısını kontrol et
sudo iptables -L | wc -l
# Network istatistiklerini izle
watch -n 5 'sudo iptables -L ufw-before-input -n -v | grep "match-set"'
Genel bir kıyaslama: Aynı işi bireysel iptables kurallarıyla yapmak isteseniz 50.000 kural eklemeniz gerekirdi ve bu hem bellek hem de CPU açısından felaket olurdu. ipset ile bu yük neredeyse sıfıra iniyor.
Sorun Giderme
Karşılaşabileceğiniz yaygın sorunlar ve çözümleri:
ipset kuralları UFW restart sonrası kayboluyor: UFW restart ettiğinizde iptables kuralları yeniden yazılır ama ipset set’leri bellekte kalır. Sadece iptables referansları silinir. update-geoblock.sh scriptinizdeki doğrulama bloğu bunu handle ediyor. Alternatif olarak /etc/ufw/after.rules sonuna ipset referanslarını da ekleyebilirsiniz.
“Set not found” hatası: ipset-restore servisi çalışmadan UFW başlamış olabilir. Servis bağımlılıklarını kontrol edin ve Before=ufw.service direktifinin doğru konumda olduğundan emin olun.
Meşru trafik engelleniyor: CDN arkasındaki IP’ler veya VPN çıkış noktaları bazen yanlış ülkeyle eşleşebilir. Bu durumlarda whitelist seti devreye giriyor. Ayrıca ipdeny.com verilerinin ne kadar güncel olduğunu düzenli kontrol edin.
Sonuç
UFW ile coğrafi IP engelleme, doğru kurulduğunda düşük maliyetli ve yüksek etkili bir güvenlik katmanıdır. Özellikle coğrafi olarak sınırlı hizmet veren sunucularda saldırı yüzeyini ciddi ölçüde azaltır. Şunu unutmayın: Bu yöntem tek başına bir güvenlik çözümü değil, derinlemesine savunma stratejisinin bir parçasıdır. fail2ban, düzenli güvenlik güncellemeleri ve güçlü kimlik doğrulama mekanizmalarıyla birlikte kullanıldığında gerçek anlamda değer kazanır.
Burada anlattığım yapıyı birkaç production sunucusunda aktif olarak kullanıyorum. Haftalık otomatik güncellemeler ve başlangıç servisinin doğru yapılandırılması ile birlikte “kur ve unut” modunda sorunsuz çalışıyor. Siz de kendi ihtiyaçlarınıza göre BLOCKED_COUNTRIES listesini özelleştirin, whitelist kurallarınızı ekleyin ve belki sadece kritik portlara uygulayarak işe başlayın.
