Unbound DNS Sunucusunda Allowlist ve Blocklist Yönetimi ile Özelleştirilmiş Filtreleme
Ağ yönetiminde DNS filtreleme, hem güvenlik hem de performans açısından kritik bir rol oynar. Unbound DNS sunucusu, bu filtrelemeyi oldukça esnek bir şekilde yapmanıza olanak tanır. İster belirli alan adlarını tamamen engellemek, ister yalnızca belirli kaynaklara izin vermek isteyin, Unbound’un sunduğu yapılandırma seçenekleri bu ihtiyaçları karşılamak için yeterince güçlüdür. Bu yazıda, Unbound üzerinde allowlist ve blocklist yönetimini, özelleştirilmiş filtreleme tekniklerini ve bunları gerçek dünya senaryolarında nasıl uygulayabileceğinizi detaylıca ele alacağız.
Unbound’da Filtreleme Mantığı Nasıl Çalışır?
Unbound, DNS sorgularını işlerken birkaç farklı katmanda müdahale imkânı sunar. Bu katmanların mantığını anlamadan filtreleme yapmaya çalışmak, beklenmedik sonuçlar doğurabilir.
Temel olarak iki yaklaşım vardır:
- local-zone direktifi: Belirli bir alan adı için yerel bir yanıt tanımlar. Bu yanıt “refuse”, “static”, “redirect”, “transparent” gibi farklı türlerde olabilir.
- local-data direktifi: Belirli bir alan adı için özel bir DNS kaydı döndürür.
- response-ip direktifi: Belirli IP adreslerinden gelen yanıtları filtreler.
- rpz (Response Policy Zone): Daha gelişmiş politika tabanlı filtreleme için kullanılır.
Blocklist mantığında, engellemek istediğiniz alan adları için local-zone "example.com" refuse veya local-zone "example.com" static kullanırsınız. Allowlist mantığında ise belirli alan adlarını izin verilen listede tutarken geri kalanları engellersiniz.
Temel Blocklist Yapılandırması
En basit engelleme yöntemi, Unbound’un ana yapılandırma dosyasına local-zone direktifleri eklemektir. Ancak bunu doğrudan unbound.conf dosyasına yazmak yerine ayrı bir dosyaya alıp include ile çağırmak çok daha yönetilebilir bir yapı oluşturur.
Öncelikle blocklist dosyasını oluşturalım:
sudo mkdir -p /etc/unbound/lists
sudo touch /etc/unbound/lists/blocklist.conf
Blocklist dosyasının içeriği şu formatta olur:
cat /etc/unbound/lists/blocklist.conf
server:
local-zone: "malware-site.com" refuse
local-zone: "adtracker.net" refuse
local-zone: "phishing-domain.org" refuse
local-zone: "tracking.example.com" refuse
refuse türü, DNS sorgusuna REFUSED yanıtı döndürür. Alternatif olarak static kullanırsanız NXDOMAIN yanıtı döner, yani alan adı hiç yokmuş gibi davranır. Güvenlik perspektifinden refuse genellikle daha şeffaftır çünkü istemci bunun kasıtlı bir engelleme olduğunu anlayabilir.
Şimdi bu dosyayı ana yapılandırmaya dahil edelim:
sudo nano /etc/unbound/unbound.conf
include: "/etc/unbound/lists/blocklist.conf"
Yapılandırmayı test edip yeniden yükleyelim:
sudo unbound-checkconf
sudo systemctl reload unbound
Büyük Ölçekli Blocklist Yönetimi
Gerçek dünyada yüzlerce veya binlerce alan adını engellemek gerekebilir. Bu durumda listeyi elle yönetmek yerine otomatik güncelleme mekanizmaları kurmak gerekir. Pek çok güvenlik kuruluşu ve topluluk projesi, kötü amaçlı alan adlarının listelerini düzenli olarak yayınlar.
Aşağıdaki script, popüler blocklist kaynaklarından veri çekip Unbound formatına dönüştürür:
#!/bin/bash
# /usr/local/bin/update-blocklist.sh
BLOCKLIST_DIR="/etc/unbound/lists"
BLOCKLIST_FILE="$BLOCKLIST_DIR/auto-blocklist.conf"
TEMP_FILE=$(mktemp)
# Farklı kaynaklardan hostsfile formatında listeler indir
SOURCES=(
"https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts"
"https://someonewhocares.org/hosts/hosts"
)
echo "server:" > "$TEMP_FILE"
for SOURCE in "${SOURCES[@]}"; do
echo "Indiriliyor: $SOURCE"
curl -s "$SOURCE" | grep -E "^0.0.0.0" | awk '{print $2}' |
grep -v "^0.0.0.0$" |
grep -v "^localhost" |
grep -v "#" |
sort -u | while read domain; do
echo " local-zone: "$domain" refuse"
done >> "$TEMP_FILE"
done
# Tekrar eden satırları temizle
sort -u "$TEMP_FILE" > "$BLOCKLIST_FILE"
rm "$TEMP_FILE"
# Yapılandırmayı doğrula ve yeniden yükle
if unbound-checkconf; then
systemctl reload unbound
echo "Blocklist guncellendi ve Unbound yeniden yuklendi."
else
echo "HATA: unbound.conf gecersiz, guncelleme iptal edildi."
exit 1
fi
Script’e çalıştırma izni verelim ve cron ile düzenli çalışmasını sağlayalım:
sudo chmod +x /usr/local/bin/update-blocklist.sh
# Crontab'a ekleyelim - her gece saat 02:00'de çalışsın
sudo crontab -e
0 2 * * * /usr/local/bin/update-blocklist.sh >> /var/log/blocklist-update.log 2>&1
Allowlist (İzin Listesi) Yapılandırması
Allowlist, blocklist’in tersi bir mantıkla çalışır. Burada iki farklı senaryo söz konusu olabilir:
Birinci senaryo: Genel erişimi açık bırakıp yalnızca belirli alan adlarının engellenmesine izin verirsiniz. Bu zaten standart blocklist yaklaşımıdır.
İkinci senaryo: Varsayılan olarak her şeyi engelleyip yalnızca belirli alan adlarına izin verirsiniz. Bu, özellikle kiosk sistemleri, okul ağları veya kurumsal kısıtlı ortamlar için idealdir.
İkinci senaryo için local-zone hiyerarşisini kullanırız. Önce tüm sorgular için bir varsayılan reddetme politikası belirlenir, ardından izin verilen alan adları ayrıca açılır:
cat /etc/unbound/lists/allowlist.conf
server:
# Tum sorguları reddet (root zone'u blokla)
local-zone: "." refuse
# Izin verilen alan adlarini transparent yap
local-zone: "google.com." transparent
local-zone: "github.com." transparent
local-zone: "ubuntu.com." transparent
local-zone: "microsoft.com." transparent
# Dahili DNS cozumlemesine izin ver
local-zone: "internal.company.com." transparent
local-zone: "10.in-addr.arpa." transparent
local-zone: "168.192.in-addr.arpa." transparent
Burada transparent tipi, Unbound’un bu alan adı için normal recursive çözümleme yapmasına olanak tanır. "." ile root zone’u kapatmak tüm bilinmeyen alan adlarını etkiler.
Özel Yönlendirme ve Redirect Kullanımı
Bazen bir alan adını tamamen engellemek yerine başka bir adrese yönlendirmek isteyebilirsiniz. Örneğin, reklam sunucularından gelen istekleri kendi sunucunuzdaki bir karşılama sayfasına yönlendirebilirsiniz:
cat /etc/unbound/lists/redirect.conf
server:
# Reklam ve takip sitelerini loopback'e yonlendir
local-zone: "doubleclick.net" redirect
local-data: "doubleclick.net A 0.0.0.0"
local-zone: "googlesyndication.com" redirect
local-data: "googlesyndication.com A 0.0.0.0"
# Kendi "engellendi" sayfaniza yonlendirme
local-zone: "banned-site.com" redirect
local-data: "banned-site.com A 192.168.1.100"
# AAAA kaydini da engelle (IPv6)
local-data: "banned-site.com AAAA ::"
redirect tipi kullanıldığında, local-data ile verilen kayıt o alan adının tüm alt alan adlarına da uygulanır. Yani sub.doubleclick.net sorgusu da aynı IP’yi döndürür.
İstemci Bazlı Filtreleme
Unbound, farklı istemcilere farklı filtreleme politikaları uygulamanıza olanak tanır. Bu özellik, özellikle hem çocuklar hem de yetişkinler tarafından kullanılan ağlarda ya da farklı güvenlik gereksinimlerine sahip departmanlar arasında ayrım yapmak için kullanışlıdır.
Bunun için access-control ve view direktiflerini birlikte kullanırız:
cat /etc/unbound/unbound.conf
server:
# Varsayilan erisim engeli
access-control: 0.0.0.0/0 refuse
access-control: ::0/0 refuse
# Yerel agdan erişime izin ver
access-control: 127.0.0.1 allow
access-control: 192.168.1.0/24 allow_snoop
access-control: 10.10.0.0/16 allow
# View bazli erisim tanımla
access-control-view: 192.168.1.0/24 "home-network"
access-control-view: 10.10.1.0/24 "kids-network"
access-control-view: 10.10.2.0/24 "corporate-network"
view:
name: "home-network"
local-zone: "malware-site.com" refuse
view:
name: "kids-network"
local-zone: "malware-site.com" refuse
local-zone: "adult-content.com" refuse
local-zone: "gambling-site.com" refuse
include: "/etc/unbound/lists/kids-blocklist.conf"
view:
name: "corporate-network"
local-zone: "socialmedia.com" refuse
local-zone: "streaming.com" refuse
include: "/etc/unbound/lists/corporate-blocklist.conf"
Bu yapılandırmayla çocukların kullandığı ağ segmenti daha kapsamlı bir blocklist alırken, kurumsal ağ sosyal medya ve video streaming platformlarını engeller.
RPZ (Response Policy Zone) ile Gelişmiş Filtreleme
Unbound 1.16 ve sonrası, RPZ desteği sunar. RPZ, DNS filtrelemesini standartlaştırılmış bir zone formatında yönetmenizi sağlar ve büyük ölçekli ortamlarda çok daha güçlü bir yaklaşım sunar.
Önce RPZ zone dosyası oluşturalım:
cat /etc/unbound/rpz/blocklist.rpz
$ORIGIN rpz.example.com.
$TTL 3600
@ SOA localhost. root.localhost. (
1 ; serial
3600 ; refresh
900 ; retry
604800 ; expire
300 ; minimum TTL
)
NS localhost.
; Engellenen alan adlari
malware-site.com.rpz-nsdname CNAME .
phishing.com.rpz-nsdname CNAME .
adtracker.net.rpz-nsdname CNAME .
; Engellenen IP araligina yonelen cevaplar
32.1.2.3.4.rpz-ip CNAME .
Unbound yapılandırmasına RPZ zone’u ekleyelim:
cat >> /etc/unbound/unbound.conf << 'EOF'
rpz:
name: "rpz.example.com"
zonefile: "/etc/unbound/rpz/blocklist.rpz"
rpz-action-override: refuse
rpz-log: yes
rpz-log-name: "main-rpz"
EOF
RPZ ile birden fazla politika katmanı oluşturabilir, öncelik sırası belirleyebilir ve log takibini çok daha kolay yapabilirsiniz.
Filtreleme Etkinliğini Test Etme
Yapılandırmalarınızın doğru çalışıp çalışmadığını test etmek kritik önem taşır:
# Engellenen bir alan adini test et
dig @localhost malware-site.com
# Beklenen cikti REFUSED veya NXDOMAIN olmali
# Status: REFUSED gorulmeli
# Izin verilen bir alani test et
dig @localhost google.com
# Normal A kaydi donmeli
# Yonlendirilen adresi test et
dig @localhost doubleclick.net
# 0.0.0.0 donmeli
# Unbound istatistiklerini kontrol et
unbound-control stats_noreset | grep -i "query|cache|num"
# Gercek zamanli log takibi
tail -f /var/log/unbound/unbound.log | grep -E "REFUSED|NXDOMAIN|query"
Daha kapsamlı bir test için küçük bir script yazalım:
#!/bin/bash
# /usr/local/bin/test-blocklist.sh
DNS_SERVER="127.0.0.1"
# Test edilecek engellenmis alan adlari
BLOCKED_DOMAINS=(
"malware-site.com"
"adtracker.net"
"phishing-domain.org"
)
# Test edilecek izin verilen alan adlari
ALLOWED_DOMAINS=(
"google.com"
"github.com"
"ubuntu.com"
)
echo "=== ENGELLEME TESTLERI ==="
for domain in "${BLOCKED_DOMAINS[@]}"; do
result=$(dig @"$DNS_SERVER" "$domain" +short 2>/dev/null)
status=$(dig @"$DNS_SERVER" "$domain" +noall +comments 2>/dev/null | grep "status:" | awk '{print $4}' | tr -d ',')
if [[ "$status" == "REFUSED" || "$status" == "NXDOMAIN" ]]; then
echo "[OK] $domain - $status (Engellendi)"
else
echo "[HATA] $domain - $status (Engellenmedi! Kontrol et)"
fi
done
echo ""
echo "=== ERISIM TESTLERI ==="
for domain in "${ALLOWED_DOMAINS[@]}"; do
result=$(dig @"$DNS_SERVER" "$domain" +short 2>/dev/null | head -1)
if [[ -n "$result" ]]; then
echo "[OK] $domain - $result (Erisilebilir)"
else
echo "[HATA] $domain - Yanit alinamadi"
fi
done
Loglama ve İzleme
Filtrelemenin etkinliğini ölçmek için Unbound’un log mekanizmasını yapılandırmak gerekir:
sudo nano /etc/unbound/unbound.conf
server:
verbosity: 1
log-queries: yes
log-replies: yes
log-tag-queryreply: yes
logfile: "/var/log/unbound/unbound.log"
# Her engellenen sorgu icin ek bilgi
val-log-level: 1
Log dosyasından engelleme istatistiklerini çıkarmak için:
# Son 24 saat icinde en cok sorgulanan engellenen alanlar
grep "REFUSED" /var/log/unbound/unbound.log |
awk '{print $6}' |
sort | uniq -c | sort -rn | head -20
# Hangi istemcinin en cok engellemeyle karsilastigini bul
grep "REFUSED" /var/log/unbound/unbound.log |
awk '{print $4}' |
cut -d'@' -f2 |
sort | uniq -c | sort -rn | head -10
Beyaz Liste ile Blocklist Çakışmalarını Yönetmek
Bazen büyük bir blocklist kullanırken belirli alt alan adlarına erişim açmak gerekebilir. Örneğin google.com gibi büyük bir servisi engellemek istemiyorsunuz ama analytics.google.comu engellemek istiyorsunuz. Ya da tam tersi: genel bir blocklist fonts.googleapis.comu engelliyorsa ama siz buna izin vermek istiyorsunuzdur.
Unbound, daha spesifik eşleşmelere öncelik verir. Yani allowlist dosyanızda şunu yapabilirsiniz:
cat /etc/unbound/lists/exceptions.conf
server:
# Blocklist "fonts.googleapis.com" i engelliyorsa bu satir onu acar
local-zone: "fonts.googleapis.com." transparent
# analytics alt alanini engelle ama ana alana dokunma
local-zone: "analytics.example.com." refuse
# Belirli bir subdomain'i farkli IP'ye yonlendir
local-zone: "api.internal.com." redirect
local-data: "api.internal.com. A 10.0.0.50"
Bu dosyayı unbound.conf‘a include ederken blocklist’ten sonra geldiğinden emin olun. Unbound yapılandırmada sonraki tanımları önce işler, bu yüzden sıralama önemlidir.
Kurumsal Ortamda Gerçek Dünya Senaryosu
Diyelim ki 200 kişilik bir şirkette DNS yöneticisisiniz. İnsan kaynakları departmanı sosyal medyaya erişebilecek ama üretim sunucuları kesinlikle sadece paket depolarına bağlanabilecek. Geliştirici makineleri ise genel erişime açık olacak.
Bunun için şu yapıyı kurabilirsiniz:
- 10.10.1.0/24: Sunucu ağı – sadece paket repoları, update servisleri
- 10.10.2.0/24: İdari ofis – sosyal medya dahil genel erişim, zararlı site engeli
- 10.10.3.0/24: İK departmanı – LinkedIn gibi seçili sosyal medya açık
Her ağ segmenti için ayrı bir blocklist dosyası oluşturun, view direktifleriyle bu segmentlere atayın ve günlük otomatik güncellemelerle listeleri güncel tutun. Loglama ile hangi departmandan hangi alan adlarına istek geldiğini takip edin ve bu verilerle listeleri ince ayar yapın.
Sonuç
Unbound DNS sunucusunda allowlist ve blocklist yönetimi, ilk bakışta basit görünse de üretim ortamında dikkatli bir planlama gerektirir. local-zone direktiflerinin farklı tipleri, view yapısıyla segmentasyon, RPZ ile standartlaştırılmış politika yönetimi ve otomatik liste güncellemeleri birlikte kullanıldığında son derece güçlü bir filtreleme altyapısı ortaya çıkar.
En önemli nokta, yapılandırmalarınızı düzenli olarak test etmek ve loglama ile filtrelemenin etkinliğini ölçmektir. Engellediğinizi sandığınız bir alan adının aslında erişilebilir olması ya da yanlışlıkla kritik bir servisi engellemeniz, her ikisi de ciddi operasyonel sorunlara yol açabilir. unbound-checkconf komutunu her değişiklikten sonra çalıştırma alışkanlığı edinin ve büyük değişiklikleri önce test ortamında deneyin. Listeleri manuel yönetmek yerine script tabanlı otomatik güncelleme mekanizmaları kurmak, uzun vadede hem zaman kazandırır hem de güvenlik açıklarının zamanında kapatılmasını sağlar.
