Unbound ile DNSSEC Doğrulama Yapılandırması
DNS sorgularınızın gerçekten güvenilir kaynaklardan gelip gelmediğini hiç sorguladınız mı? Bir istemci DNS yanıtı aldığında, o yanıtın yolculuk boyunca manipüle edilmediğini nasıl anlarsınız? İşte tam bu noktada DNSSEC devreye giriyor ve Unbound, bu doğrulama sürecini sunucu tarafında en sağlıklı biçimde yönetebilen çözümlerden biri.
Bu yazıda Unbound üzerinde DNSSEC doğrulamasını sıfırdan yapılandıracağız. Teorik bilgiyi bir kenara bırakıp, gerçek üretim ortamlarında karşılaştığım senaryolar üzerinden ilerleyeceğiz.
DNSSEC Nedir ve Neden Unbound?
DNSSEC (DNS Security Extensions), DNS yanıtlarını dijital imzalarla doğrulayan bir güvenlik katmanıdır. Temelde iki şeyi garantiler: yanıtın gerçekten yetkili sunucudan geldiğini ve iletim sırasında değiştirilmediğini.
Peki neden Unbound? BIND veya dnsmasq de DNSSEC yapabilir, ancak Unbound baştan sona güvenli DNS çözümleyici (recursive resolver) olarak tasarlanmıştır. BIND gibi hem yetkili hem de çözümleyici olmaya çalışmaz. Bu tek amaçlılık, yapılandırmasını sadeleştirir ve saldırı yüzeyini küçültür.
Unbound’un DNSSEC ile çalışma mantığı şöyle özetlenebilir: İstemciden bir sorgu gelir, Unbound bu sorguyu kök sunuculara kadar izler, aldığı her yanıtı RRSIG (Resource Record Signature) kayıtlarıyla doğrular ve zincirin bütünlüğünü kontrol eder. Bu zincirin başlangıç noktası ise trust anchor olarak adlandırdığımız kök güven anahtarıdır.
Kurulum
Çoğu modern dağıtımda Unbound paket depolarında hazır gelir. Ama versiyon önemli, özellikle DNSSEC desteği açısından 1.6.x ve üstünü kullanmanızı öneririm.
Debian/Ubuntu:
apt update && apt install unbound unbound-anchor -y
RHEL/CentOS/AlmaLinux:
dnf install unbound -y
FreeBSD:
pkg install unbound
Kurulumdan sonra versiyon kontrolü yapın:
unbound -V
Çıktıda DNSSEC desteğinin etkin olup olmadığını görebilirsiniz. Eğer paket kaynaklı kurulum yaptıysanız genellikle zaten etkindir.
Trust Anchor: Güven Zincirimizin Temeli
DNSSEC doğrulamasının kalbi, kök zone için tanımladığımız trust anchor’dır. Bu anahtar olmadan Unbound, imzaları doğrulayacak referans noktasına sahip olmaz.
unbound-anchor aracı bu anahtarı otomatik olarak çeker ve günceller:
unbound-anchor -a /var/lib/unbound/root.key
Bu komut /var/lib/unbound/root.key dosyasını oluşturur ya da günceller. Dosyanın içeriğine bakalım:
cat /var/lib/unbound/root.key
Çıktıda şuna benzer bir şey görmelisiniz:
. IN DS 20326 8 2 E06D44B980783A31...
Bu DS kaydı, ICANN tarafından yönetilen kök zone’un KSK (Key Signing Key) özetidir. 2017’de yapılan kök zone KSK rollovers’tan bu yana bu değer güncel tutulmalıdır.
Kritik nokta: Bu dosyanın unbound kullanıcısı tarafından okunabilir ve yazılabilir olması gerekir. Unbound, RFC 5011 mekanizmasıyla bu anahtarı otomatik günceller, bu yüzden yazma izni şart.
chown unbound:unbound /var/lib/unbound/root.key
chmod 644 /var/lib/unbound/root.key
Ana Yapılandırma
Şimdi /etc/unbound/unbound.conf dosyasına geçelim. Temel bir DNSSEC yapılandırmasından başlayıp üzerine ekleyeceğiz.
cat > /etc/unbound/unbound.conf << 'EOF'
server:
# Dinleme adresi ve port
interface: 0.0.0.0
port: 53
# IPv4 ve IPv6
do-ip4: yes
do-ip6: yes
do-udp: yes
do-tcp: yes
# Erişim kontrolü
access-control: 127.0.0.0/8 allow
access-control: 192.168.0.0/16 allow
access-control: 10.0.0.0/8 allow
access-control: 0.0.0.0/0 refuse
# DNSSEC yapılandırması
auto-trust-anchor-file: "/var/lib/unbound/root.key"
val-log-level: 1
# Güvenlik seçenekleri
harden-glue: yes
harden-dnssec-stripped: yes
harden-below-nxdomain: yes
harden-referral-path: no
# QNAME minimization (RFC 7816)
qname-minimisation: yes
# Cache ayarları
cache-min-ttl: 300
cache-max-ttl: 86400
msg-cache-size: 128m
rrset-cache-size: 256m
# Log
logfile: "/var/log/unbound/unbound.log"
log-queries: no
log-replies: no
verbosity: 1
# Chroot
chroot: ""
username: "unbound"
# Root hints
root-hints: "/var/lib/unbound/root.hints"
EOF
Birkaç parametre üzerinde duralım:
harden-dnssec-stripped: Bu bence en önemli seçenek. Bir yanıt DNSSEC imzasız gelirse ama zone DNSSEC destekliyorsa, Unbound bu yanıtı reddeder. Ortadaki adam saldırısına karşı temel savunma mekanizmasıdır.
harden-below-nxdomain: NXDOMAIN yanıtlarının alt alanlarını da kapsayacak şekilde sertleştirir. DNS rebinding saldırılarına karşı koruma sağlar.
qname-minimisation: RFC 7816’ya uygun olarak, tam alan adını üst sunuculara göndermek yerine minimum gerekli bilgiyi gönderir. Gizlilik açısından önemli.
val-log-level: 1 değeri başarısız DNSSEC doğrulama girişimlerini loglar. Hata ayıklama için değeri 2’ye çıkarabilirsiniz ama production’da 1 yeterli.
Root Hints Güncelleme
Kök sunucu listesini de güncel tutmak gerekir:
wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.root
Bunu bir cron job’a ekleyin, ayda bir yeterli:
echo "0 0 1 * * root wget -q -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.root && systemctl reload unbound" > /etc/cron.d/update-root-hints
Yapılandırmayı Test Etme
Servisi başlatmadan önce yapılandırma dosyasını kontrol edin:
unbound-checkconf /etc/unbound/unbound.conf
Hatasız çıktı aldıysanız servisi başlatın:
systemctl enable --now unbound
systemctl status unbound
Şimdi DNSSEC doğrulamasının çalışıp çalışmadığını test edelim. Bunun için dig komutunun +dnssec ve +cd bayraklarını kullanacağız:
# DNSSEC imzalı bir zone sorgusu (sigok.uri.arpa test zone'u)
dig @127.0.0.1 sigok.uri.arpa A +dnssec
# AD bayrağını kontrol et
dig @127.0.0.1 google.com A +dnssec | grep -E "^;; flags"
Çıktıdaki flags satırında ad (Authenticated Data) bayrağını görmelisiniz:
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
ad bayrağı, yanıtın DNSSEC ile başarıyla doğrulandığını gösterir.
Şimdi bir de kasıtlı olarak bozuk DNSSEC’e sahip test domain’ini deneyelim:
dig @127.0.0.1 dnssec-failed.org A
Bu sorgu SERVFAIL döndürmeli. Döndürüyorsa DNSSEC doğrulama düzgün çalışıyor demektir. Bu domain özellikle DNSSEC doğrulama testleri için tasarlanmıştır.
Gerçek Dünya Senaryosu: Split-DNS ile DNSSEC
Üretim ortamlarında sıkça karşılaşılan bir durum: iç ağda özel domain’leriniz var ve bunlar için yetkili sunucunuz ayrı. Bu durumda DNSSEC doğrulamasını iç zone’lar için devre dışı bırakmak gerekebilir ya da iç CA’dan imzalanmış zone’ları yapılandırmanız gerekir.
Diyelim ki internal.sirket.com zone’unuz için ayrı bir yetkili DNS sunucunuz var ve bu zone DNSSEC imzalı değil:
# /etc/unbound/unbound.conf.d/internal.conf
server:
# internal zone için DNSSEC doğrulamasını atla
domain-insecure: "internal.sirket.com"
stub-zone:
name: "internal.sirket.com"
stub-addr: 10.10.1.53
stub-prime: no
domain-insecure direktifi, belirtilen zone için DNSSEC doğrulamasını atlar. Bu zone’dan gelen yanıtlar ad bayrağı taşımaz ama SERVFAIL da dönmez.
Daha güvenli bir alternatif: Eğer iç zone’unuzu DNSSEC ile imzalayabildiyseniz, trust anchor’ı Unbound’a tanıtın:
server:
trust-anchor: "internal.sirket.com. DS 12345 8 2 ABCDEF1234..."
Bu yaklaşım zincirin kopmaması açısından daha sağlıklıdır, ancak iç CA ve zone signing altyapısı gerektirir.
Negative Trust Anchors (NTA)
Bazen bir zone’un DNSSEC yapılandırması bozuk olabilir ama erişmeniz gerekir. Örneğin bir iş ortağınızın domain’i geçici olarak bozuk DNSSEC imzasıyla yayın yapıyor. Bu durumda NTA mekanizmasını kullanabilirsiniz:
# Geçici NTA ekle (runtime, restart'ta sıfırlanır)
unbound-control insecure_add ortakfirma.com
# Kalıcı NTA için yapılandırma dosyasına ekle
# /etc/unbound/unbound.conf.d/nta.conf
server:
domain-insecure: "ortakfirma.com"
Önemli not: NTA’ları geçici çözüm olarak kullanın. Sorunu çözdükten sonra kaldırın. Bir zone için kalıcı NTA tanımlamak, o zone’daki tüm DNSSEC korumasını ortadan kaldırır.
DNSSEC Doğrulama Loglarını Anlama
val-log-level: 2 ile detaylı loglama açıkken şuna benzer girişler görebilirsiniz:
[1234567890] unbound[1234:0] info: validation failure <example.com. A IN>: signatures expired
[1234567890] unbound[1234:0] info: RRSIG expired
Bu logları takip etmek için basit bir izleme komutu:
tail -f /var/log/unbound/unbound.log | grep -E "(validation failure|BOGUS|SERVFAIL)"
Sık karşılaşılan DNSSEC hata mesajları:
- signatures expired: Zone’un RRSIG kayıtları süresi dolmuş. Zone operatörünün yeniden imzalaması gerekiyor.
- no signatures: DNSSEC imzası beklenirken bulunamadı. Ortadaki kişi imzaları silmiş olabilir.
- DNSKEY missing: İmzayı doğrulamak için gerekli DNSKEY kaydı yok.
- DS record not found: Üst zone’dan gelen delegation imzası eksik.
unbound-control ile Yönetim
Unbound’un remote control arayüzü production’da hayat kurtarır. Önce etkinleştirin:
# Sertifikaları oluştur
unbound-control-setup
Bu komut /etc/unbound/ altında unbound_control.key, unbound_control.pem, unbound_server.key, unbound_server.pem dosyalarını oluşturur.
Yapılandırmaya ekleyin:
remote-control:
control-enable: yes
control-interface: 127.0.0.1
control-port: 8953
server-key-file: "/etc/unbound/unbound_server.key"
server-cert-file: "/etc/unbound/unbound_server.pem"
control-key-file: "/etc/unbound/unbound_control.key"
control-cert-file: "/etc/unbound/unbound_control.pem"
Artık şu komutları kullanabilirsiniz:
# Servis durumu
unbound-control status
# İstatistikler (DNSSEC doğrulama sayıları dahil)
unbound-control stats_noreset | grep dnssec
# Cache'i temizle
unbound-control flush_zone example.com
# Yapılandırmayı yeniden yükle (restart gerekmez)
unbound-control reload
# Belirli bir kaydı sorgula ve cache'e bak
unbound-control lookup example.com
stats_noreset çıktısındaki DNSSEC ile ilgili sayaçlar:
unbound-control stats_noreset | grep -i dnssec
Burada num.dnssec.bogus değeri, başarısız DNSSEC doğrulama sayısını gösterir. Bu değer sıfıra yakın olmalı, eğer anormalce yüksekse araştırmanız gerekir.
Performans Ayarları
DNSSEC doğrulama, ek kriptografik işlem demektir. Cache boyutlarını artırmak bu yükü azaltır:
server:
# Her RRset için ayrı cache
rrset-cache-size: 256m
msg-cache-size: 128m
# Prefetch: TTL dolmadan önce popüler kayıtları yenile
prefetch: yes
prefetch-key: yes
# Thread sayısı (CPU core sayısına eşit ayarlayın)
num-threads: 4
# Her thread için buffer
outgoing-range: 4096
num-queries-per-thread: 4096
# So-reuseport kernel desteği varsa etkinleştir
so-reuseport: yes
prefetch-key: DNSKEY kayıtlarını TTL dolmadan önce yeniler. Bu sayede imza doğrulaması için her seferinde yeniden sorgu yapılmaz ve gecikme azalır.
Monitoring ve Alerting
Production’da DNSSEC doğrulama başarısızlıklarını izlemek için basit bir script:
#!/bin/bash
# /usr/local/bin/check_dnssec.sh
RESOLVER="127.0.0.1"
TEST_DOMAIN="sigok.uri.arpa"
FAIL_DOMAIN="dnssec-failed.org"
ALERT_MAIL="[email protected]"
# Başarılı DNSSEC testi
RESULT=$(dig @$RESOLVER $TEST_DOMAIN A +dnssec +short 2>/dev/null)
if [ -z "$RESULT" ]; then
echo "KRITIK: DNSSEC dogrulama calismıyor - $TEST_DOMAIN cevaplanmiyor" |
mail -s "Unbound DNSSEC Hatasi" $ALERT_MAIL
exit 2
fi
# AD bayragi kontrolu
FLAGS=$(dig @$RESOLVER $TEST_DOMAIN A +dnssec 2>/dev/null | grep "^;; flags")
if ! echo "$FLAGS" | grep -q " ad"; then
echo "UYARI: AD bayragi bulunamadi - DNSSEC dogrulama devre disi?" |
mail -s "Unbound DNSSEC Uyarisi" $ALERT_MAIL
exit 1
fi
# Bogus domain SERVFAIL donmeli
BOGUS=$(dig @$RESOLVER $FAIL_DOMAIN A +short 2>&1)
STATUS=$(dig @$RESOLVER $FAIL_DOMAIN A 2>/dev/null | grep "^;; ->>HEADER" | grep -o "SERVFAIL")
if [ "$STATUS" != "SERVFAIL" ]; then
echo "KRITIK: Bogus DNSSEC dogrulama basarisiz - $FAIL_DOMAIN SERVFAIL donmuyor!" |
mail -s "Unbound DNSSEC Kritik Hata" $ALERT_MAIL
exit 2
fi
echo "OK: DNSSEC dogrulama normal calisiyor"
exit 0
Bu scripti cron’a ekleyin:
*/5 * * * * root /usr/local/bin/check_dnssec.sh >> /var/log/dnssec_check.log 2>&1
Yaygın Sorunlar ve Çözümleri
Sorun: Bazı domain’ler SERVFAIL dönüyor ama DNSSEC bozuk değil.
Sebebi çoğunlukla sistem saatidir. DNSSEC imzaları zaman damgasına dayanır, sunucu saati yanlışsa tüm doğrulama bozulur.
# NTP senkronizasyonunu kontrol et
timedatectl status
chronyc tracking
Sorun: harden-dnssec-stripped aktifken bazı kurumsal uygulamalar çalışmıyor.
Bazı eski veya kötü yapılandırılmış zone’lar DNSSEC desteğini yarım bırakmış. domain-insecure direktifiyle bu zone’ları kapsama dışı bırakın, ancak bunu kalıcı çözüm olarak değil geçici çözüm olarak düşünün.
Sorun: unbound-anchor trust anchor dosyasını güncelleyemiyor.
Dosya izinlerini kontrol edin. Unbound kullanıcısının bu dosyaya yazma izni olmalı:
ls -la /var/lib/unbound/root.key
chown unbound:unbound /var/lib/unbound/root.key
chmod 644 /var/lib/unbound/root.key
Sonuç
Unbound üzerinde DNSSEC doğrulaması, DNS altyapınıza ekleyebileceğiniz en değerli güvenlik katmanlarından biri. Yapılandırması görece basit, bakım maliyeti düşük ve sağladığı koruma ciddi.
Özetle dikkat etmeniz gereken kritik noktalar:
- Trust anchor dosyasının güncel ve doğru izinlerde olduğundan emin olun
harden-dnssec-strippedher zaman açık tutun- NTP senkronizasyonunu ihmal etmeyin, DNSSEC için saat doğruluğu şarttır
unbound-control statsile periyodik olarak bogus sayacını takip edin- İç zone’lar için
domain-insecurekullanmak yerine mümkünse o zone’ları da imzalamayı tercih edin - Monitoring scriptini mutlaka kurun ve hem pozitif hem negatif test edin
DNS güvenliğini katmanlı düşünmek gerekiyor: DNSSEC kayıt manipülasyonunu engeller, DoT/DoH ise dinlemeyi engeller. İkisini birlikte kullandığınızda sağlam bir DNS güvenlik mimarisi elde edersiniz. Ama bu başka bir yazının konusu.
