Unbound ile DNSSEC İmzalı Zone Doğrulama

DNSSEC doğrulaması, üzerinde yıllarca konuşulup “eninde sonunda herkes kullanacak” denilen ama pratikte hala bir çok ortamda devre dışı bırakılmış ya da yanlış yapılandırılmış halde karşılaştığım bir konu. Unbound ise bu işi gerçekten iyi yapan, hafif ve güvenilir bir çözücü. Bu yazıda Unbound ile DNSSEC imzalı zone doğrulamasını, sadece “nasıl açılır” seviyesinde değil, gerçekte ne yaptığını anlayarak yapılandırmayı ele alacağız.

DNSSEC Nedir ve Neden Unbound?

Klasik DNS, bir yanıtın gerçekten o yetkili sunucudan gelip gelmediğini doğrulamanın hiçbir yolunu sunmaz. Cache poisoning saldırıları, BGP hijack senaryoları, ya da ortadaki adam saldırıları DNS yanıtlarını manipüle edebilir. DNSSEC bu soruna kriptografik imzalar ekleyerek çözüm üretir. Her zone, özel anahtarıyla kayıtlarını imzalar; çözücü ise bu imzaları güven zincirini takip ederek doğrular.

Unbound bu işi için iki temel nedenden ötürü tercih ediyorum: birincisi, DNSSEC doğrulamasını native olarak desteklemesi ve doğru varsayılan değerlerle gelmesi. İkincisi ise BIND gibi devasa bir yazılımın aksine, sadece çözücü (resolver) rolüne odaklanmış olması. Yetkili DNS sunucusu işi başka araçlara bırakıp bu konuda uzmanlaşmış.

Kurulum

Çoğu dağıtımda Unbound paket deposunda mevcut. Ama önce ihtiyacınız olan versiyonu teyit edin; DNSSEC için 1.5.x ve üzeri yeterli olmakla birlikte, güncel openssl kütüphanesiyle derlenmesi gerekiyor.

# Debian/Ubuntu
apt update && apt install unbound unbound-anchor -y

# RHEL/CentOS/Rocky Linux
dnf install unbound -y

# Versiyon kontrolü
unbound -V

Kurulumdan sonra root anahtarını (trust anchor) güncellemeniz gerekiyor. Bu adım atlanırsa DNSSEC doğrulaması ya hiç çalışmaz ya da eski anahtarla başarısız doğrulamalar üretir:

# Root trust anchor dosyasını oluştur ve güncelle
unbound-anchor -a /var/lib/unbound/root.key

# İşlemin başarılı olduğunu kontrol et
# Çıktıda "success" ya da "already up to date" görmek istiyoruz
echo $?

Bir not: unbound-anchor her çalıştırmada internet bağlantısı gerektirir. Hava boşluklu (air-gapped) ortamlarda root.key dosyasını manuel olarak [IANA’nın güven çıpası sayfasından](https://www.iana.org/dnssec/files) almanız gerekir.

Temel DNSSEC Yapılandırması

Unbound’un ana yapılandırma dosyası genellikle /etc/unbound/unbound.conf konumunda bulunur. Üretim ortamında bu dosyayı doğrudan düzenlemek yerine /etc/unbound/unbound.conf.d/ altında parçalı config dosyaları kullanmayı tercih ediyorum; geri alma ve versiyon kontrolü açısından çok daha temiz.

cat > /etc/unbound/unbound.conf.d/dnssec.conf << 'EOF'
server:
    # DNSSEC doğrulamasını etkinleştir
    auto-trust-anchor-file: "/var/lib/unbound/root.key"
    
    # Doğrulanamayan yanıtları reddet
    val-permissive-mode: no
    
    # DNSSEC hataları için log üret
    val-log-level: 1
    
    # Negative yanıtlar için NSEC/NSEC3 doğrulaması
    aggressive-nsec: yes
    
    # Bogus yanıt sayacını izle
    extended-statistics: yes
EOF

val-permissive-mode: no ayarı kritik. Bu ayar yes yapıldığında Unbound DNSSEC hatalarını loglar ama geçersiz yanıtları yine de istemciye iletir; test için kullanılabilir ama üretimde kesinlikle kapalı olmalı.

aggressive-nsec: yes ise özellikle vurgulamak istediğim bir optimizasyon. NSEC kayıtları, bir zone’da hangi isimlerin var olmadığını kriptografik olarak kanıtlar. Bu ayar açık olduğunda Unbound, var olmayan domainler için her seferinde upstream’e gitmek yerine önbellekteki NSEC kayıtlarını kullanarak yanıt üretebilir. Hem bant genişliği hem de gecikme açısından önemli bir kazanım.

Doğrulamanın Test Edilmesi

Yapılandırmayı uyguladıktan sonra servis yeniden başlatılmalı ve doğrulama gerçekten çalışıyor mu test edilmeli:

systemctl restart unbound
systemctl status unbound

# DNSSEC imzalı bir domain için test
# dnssec.works doğrulamanın çalıştığını doğrulayan bir test domaindir
dig @127.0.0.1 dnssec.works A

# Yanıtta "ad" (Authenticated Data) flag'ini görmelisiniz
# flags: qr rd ra ad

Burada yanıt başlığındaki ad bayrağı, Unbound’un bu yanıtı DNSSEC ile doğruladığını gösterir. Bu bayrağı görmüyorsanız ya doğrulama çalışmıyor ya da sorguladığınız domain DNSSEC imzalı değil.

DNSSEC imzalı olmayan bir domain için negatif test:

# DNSSEC imzasız bir domain - "ad" flag olmayacak, bu normal
dig @127.0.0.1 example-without-dnssec.com A

# Kasıtlı olarak bozuk DNSSEC yapılandırması olan test domain
dig @127.0.0.1 dnssec-failed.org A
# Bu sorgu SERVFAIL dönmeli - bunu bekleriz

dnssec-failed.org için SERVFAIL alıyorsanız, Unbound doğru çalışıyor; geçersiz imzayı reddetti.

Detaylı Log ve Hata Analizi

Üretimde DNSSEC sorunlarını teşhis etmenin en kritik parçası logları doğru okumak. Unbound’un DNSSEC ile ilgili ürettiği log satırlarını anlamak için verbosity seviyesini geçici olarak artırabilirsiniz:

# Unbound log yapılandırması
cat >> /etc/unbound/unbound.conf.d/logging.conf << 'EOF'
server:
    verbosity: 2
    log-queries: yes
    log-replies: yes
    log-tag-queryreply: yes
    logfile: "/var/log/unbound/unbound.log"
EOF

mkdir -p /var/log/unbound
chown unbound:unbound /var/log/unbound

Log’larda dikkat etmeniz gereken DNSSEC ile ilgili mesaj tipleri:

  • validation failure: Zincir doğrulaması başarısız, imza geçersiz
  • BOGUS: Yanıt kriptografik olarak geçersiz kabul edildi
  • NSEC proof: NSEC/NSEC3 kaydıyla var olmayan domain kanıtı
  • key expired: DNSKEY’in geçerlilik süresi dolmuş

Gerçek dünyada en sık karşılaştığım senaryo, bir zone’un DNSSEC anahtarını yenilemiş ama DS kaydını üst zone’da güncellememiş olması. Bu durumda güven zinciri kopar ve Unbound SERVFAIL döner. Bu tür sorunları teşhis etmek için:

# Bir domain'in DNSSEC zincirini detaylı incele
unbound-host -C /etc/unbound/unbound.conf -v dnssec.works

# Ya da dig ile ayrıntılı DNSSEC bilgisi
dig @127.0.0.1 +dnssec +multiline dnssec.works DNSKEY

# DS kaydını kontrol et (üst zone'daki parmak izi)
dig @127.0.0.1 +dnssec dnssec.works DS

Yerel Zone’lar ve DNSSEC İstisnalar

Kurumsal ortamlarda iç domain’ler için yerel zone’lar tanımlamak zorundasınız. Bu zone’lar çoğunlukla DNSSEC imzalı değil ve Unbound bunları BOGUS olarak değerlendirip reddedebilir. Bu durumu yönetmek için iki yaklaşım var:

Birinci yaklaşım: İç zone’u tamamen güvenilir olarak işaretle:

cat > /etc/unbound/unbound.conf.d/internal-zones.conf << 'EOF'
server:
    # Dahili zone için DNSSEC doğrulamasını atla
    domain-insecure: "corp.example.internal"
    domain-insecure: "10.in-addr.arpa"
    domain-insecure: "168.192.in-addr.arpa"

# İç DNS sunucusuna yönlendir
forward-zone:
    name: "corp.example.internal"
    forward-addr: 10.0.0.10
    forward-addr: 10.0.0.11
    forward-dnssec-prime: no
EOF

İkinci yaklaşım: Eğer iç DNS sunucunuz DNSSEC destekliyorsa ve iç zone’larınızı imzaladıysanız, stub-zone kullanarak daha temiz bir yapı kurabilirsiniz:

cat > /etc/unbound/unbound.conf.d/stub-zones.conf << 'EOF'
stub-zone:
    name: "corp.example.internal"
    stub-addr: 10.0.0.10@53
    stub-prime: no
    stub-first: no
EOF

domain-insecure ile forward-zone birlikte kullanıldığında, Unbound o zone için DNSSEC doğrulamasını devre dışı bırakır. Bu bir güvenlik tavizi olmakla birlikte, iç ağı kontrol ettiğinizi varsaydığınızda kabul edilebilir. Ama dikkat: bu kuralları olabildiğince dar tutun, geniş wildcard kullanmaktan kaçının.

Negatif Güven Çıpası ve Özel Senaryolar

Bazen belirli bir domain için DNSSEC’i tamamen devre dışı bırakmak yerine, o domain’i negatif güven çıpası olarak tanımlamanız gerekir. Bu, o domain’in DNSSEC imzalı görünmesine rağmen doğrulamanın kasıtlı olarak devre dışı bırakılması anlamına gelir:

cat >> /etc/unbound/unbound.conf.d/trust-anchors.conf << 'EOF'
server:
    # Belirli zone için DNSSEC doğrulamasını devre dışı bırak
    # (domain-insecure ile aynı etkiyi sağlar ama daha açık)
    domain-insecure: "broken-dnssec-vendor.com"
    
    # Varsayılan güven zinciri dışında özel trust anchor
    # (split-horizon ya da özel CA senaryoları için)
    trust-anchor: "example.internal. 3600 IN DS 12345 8 2 AABBCCDD..."
EOF

Özel trust anchor senaryosu, internal CA ile imzalanmış private zone’lar için kullanışlı. Root zincirini bypass ederek kendi güven noktanızı tanımlıyorsunuz.

Performans Ayarları ve Önbellekleme

DNSSEC doğrulaması ekstra kriptografik işlem gerektirdiğinden, yüksek yük altındaki Unbound için bazı optimizasyonlar kritik:

cat > /etc/unbound/unbound.conf.d/performance.conf << 'EOF'
server:
    # Thread sayısını CPU sayısıyla eşleştir
    num-threads: 4
    
    # Her thread için mesaj önbelleği
    msg-cache-slabs: 4
    rrset-cache-slabs: 4
    infra-cache-slabs: 4
    key-cache-slabs: 4
    
    # Önbellek boyutları
    msg-cache-size: 128m
    rrset-cache-size: 256m
    
    # DNSSEC anahtar önbelleği - bu çok önemli
    key-cache-size: 32m
    neg-cache-size: 8m
    
    # Paralel sorgu limitleri
    outgoing-range: 8192
    num-queries-per-thread: 4096
    
    # Prefetch - TTL dolmadan önce yenile
    prefetch: yes
    prefetch-key: yes
EOF

key-cache-size ve prefetch-key ayarlarına özellikle dikkat edin. DNSKEY ve DS kayıtlarının önbelleklenmesi, her sorgu için tekrar doğrulama zinciri oluşturmayı engeller. 32 MB genellikle yeterli ama yüksek trafikli ortamlarda 64-128 MB’a çıkabilirsiniz.

prefetch-key: yes ayarı ise DNSKEY kayıtları TTL dolmadan önce arka planda yeniler. Bu olmadan TTL süresinin dolduğu anda bir sonraki istek doğrulama zincirini sıfırdan kurmak zorunda kalır ve gecikme artar.

İzleme ve Metrik Toplama

Unbound’un DNSSEC doğrulamasını üretimde izlemek için statistics arayüzünü açmanız gerekiyor:

cat >> /etc/unbound/unbound.conf.d/monitoring.conf << 'EOF'
server:
    statistics-interval: 0
    extended-statistics: yes

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"
EOF

# Kontrol sertifikalarını oluştur
unbound-control-setup

# İstatistikleri görüntüle
unbound-control stats_noreset

DNSSEC ile ilgili izlemeniz gereken metrikler:

  • num.answer.bogus: BOGUS olarak işaretlenen yanıt sayısı; ani artış kötü bir şeyin olduğuna işaret eder
  • num.answer.secure: DNSSEC doğrulamasından geçen yanıtlar
  • num.answer.nodata: Güvenli negatif yanıtlar
  • total.num.cachehits: Önbellek kullanım oranı; düşükse key-cache-size artırın

Bu metrikleri Prometheus ve Grafana ile görselleştirmek için unbound_exporter kullanabilirsiniz. Ayrı bir yazı konusu ama kısa not olarak: exporter’ı unbound-control üzerinden bağlayıp metrikleri /metrics endpoint’inden sunabilirsiniz.

Güvenlik Sertleştirme

DNSSEC doğrulamasını yapılandırdıktan sonra Unbound’un kendisini de sertleştirmek gerekiyor:

cat > /etc/unbound/unbound.conf.d/hardening.conf << 'EOF'
server:
    # DNS rebinding koruması
    private-address: 10.0.0.0/8
    private-address: 172.16.0.0/12
    private-address: 192.168.0.0/16
    private-address: fd00::/8
    private-address: fe80::/10
    
    # Amplifikasyon saldırılarına karşı
    hide-identity: yes
    hide-version: yes
    
    # DNSSEC için minimum RSA anahtar boyutu
    # 1024 bit anahtarları reddet
    val-min-rsa-size: 1024
    
    # Harden ayarları
    harden-dnssec-stripped: yes
    harden-below-nxdomain: yes
    harden-referral-path: yes
    harden-algo-downgrade: no
    
    # QName minimization - gizlilik için
    qname-minimisation: yes
    qname-minimisation-strict: no
EOF

harden-dnssec-stripped belki de en kritik ayar. Bir DNS yanıtında DNSSEC kaydı olması bekleniyorken yoksa, Unbound bu yanıtı reddeder. Saldırgan DNSSEC kayıtlarını yanıttan sıyırıp doğrulamayı atlatmaya çalışabilir; bu ayar buna karşı koruma sağlar.

qname-minimisation, DNSSEC ile doğrudan ilgili olmasa da gizlilik açısından önemli. Normal DNS çözümlemesinde her yetkili sunucuya tam domain adı sorulur; bu ayar açık olduğunda Unbound yalnızca gerekli olan kısımları gönderir, tam adı yalnızca yetkili sunucu belirtince açıklar.

Yapılandırmayı Doğrulama ve Sorun Giderme

Tüm yapılandırmaları uyguladıktan sonra kapsamlı bir doğrulama yapın:

# Yapılandırma syntax kontrolü
unbound-checkconf /etc/unbound/unbound.conf

# Servis yeniden başlatma ve durum
systemctl restart unbound && systemctl status unbound

# Kapsamlı DNSSEC test seti
echo "=== DNSSEC Doğrulaması Aktif Domainler ==="
dig @127.0.0.1 cloudflare.com A | grep -E "flags:|ANSWER"

echo "=== Bozuk DNSSEC - SERVFAIL Beklenir ==="
dig @127.0.0.1 dnssec-failed.org A | grep -E "flags:|status:"

echo "=== İmzasız Domain - ad flag olmayacak ==="
dig @127.0.0.1 example.com A | grep "flags:"

echo "=== BOGUS Sayacı ==="
unbound-control stats_noreset | grep bogus

Eğer meşru bir domain için SERVFAIL alıyorsanız ve bunun DNSSEC kaynağı olduğundan şüpheleniyorsanız:

# Geçici olarak doğrulamayı devre dışı bırakıp test et
# NOT: Bu sadece teşhis içindir, üretimde yapmayın
dig @8.8.8.8 problemli-domain.com A  # Google DNS ile karşılaştır
dig @127.0.0.1 +cd problemli-domain.com A  # +cd: checking disabled

# DNSKEY kayıtlarını kontrol et
dig @127.0.0.1 +dnssec problemli-domain.com DNSKEY
dig @127.0.0.1 +dnssec problemli-domain.com DS

+cd bayrağı DNSSEC doğrulamasını bypass eder ve yanıt geliyorsa sorunun gerçekten DNSSEC’ten kaynaklandığını teyit eder. Bu durumda domain sahibinin düzeltmesi gereken bir sorun var demektir; Unbound doğru davranıyor.

Sonuç

Unbound ile DNSSEC doğrulamasını doğru yapılandırmak birkaç saat alan bir iş ama getirisi uzun vadede önemli. Cache poisoning ve DNS spoofing saldırılarına karşı kriptografik bir güvence elde ediyorsunuz. Yapılandırmanın kritik noktalarını özetlersem:

Root trust anchor’ın güncel tutulması şart; unbound-anchor komutunu cron’a ekleyin. val-permissive-mode: no ile geçersiz yanıtların geçmesine izin vermeyin. Dahili zone’lar için domain-insecure ile istisna tanımlayın ama kapsamı dar tutun. Key cache boyutunu ve prefetch ayarlarını performans için optimize edin. harden-dnssec-stripped asla kapatmayın.

DNSSEC doğrulaması “kurup unut” değil, izlenmesi gereken bir bileşen. num.answer.bogus metriğini alarm sistemine ekleyin; beklenmedik bir artış ya Unbound’un gerçek saldırıları engellediğini ya da bir zone’un bozulduğunu gösterir, her iki durumda da bilmeniz gerekiyor.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir