Unbound DNS Nedir: Recursive Resolver ve Güvenlik Odaklı DNS

Kurumsal ortamlarda DNS altyapısı söz konusu olduğunda çoğu zaman iki seçenekten biri akla gelir: BIND ya da bulut sağlayıcının sunduğu hazır resolver. Oysa yıllardır güvenlik odaklı ağ mimarlarının tercihi olan Unbound, hem performansı hem de güvenlik özellikleriyle bu iki alternatifin önüne geçebiliyor. Ben de tam olarak bu noktada, bir müşteri ağında yaşadığım DNS sızıntısı olayının ardından Unbound’a ciddi anlamda yöneldim ve o günden bu yana neredeyse her kurumsal kurulumda tercihim bu yönde oldu.

Unbound Nedir ve Neden Önemlidir

Unbound, NLnet Labs tarafından geliştirilen, açık kaynaklı, güvenlik odaklı bir recursive DNS resolver‘dır. BIND gibi hem authoritative hem recursive çalışabilen bir sunucu değildir; Unbound yalnızca recursive resolver rolünü üstlenir ve bunu son derece iyi yapar.

Recursive resolver ne demek? Bir istemci “google.com’un IP’si ne?” diye sorduğunda, resolver bu soruyu yanıtlamak için root sunuculardan başlayarak TLD sunucularına, oradan authoritative name server’lara kadar sorguyu zincir halinde ilerletir ve nihai yanıtı istemciye döner. Unbound işte bu zinciri yönetir.

Peki BIND’dan farkı ne? BIND, onlarca yıllık bir geçmişe sahip devasa bir yazılım. Esnekliği tartışılmaz ama aynı zamanda karmaşıklığı da öyle. Unbound ise tek bir amaca odaklanmış, sade bir kod tabanına sahip. Bu sadelik hem güvenlik açığı yüzeyini küçültüyor hem de yapılandırmayı kolaylaştırıyor.

Unbound’un Temel Özellikleri

Unbound’u tercih etmemizin arkasında birkaç somut özellik var:

  • DNSSEC doğrulama: Unbound, kutudan çıktığı gibi DNSSEC doğrulaması yapabilir. Sahte DNS yanıtlarına karşı kritik bir koruma katmanıdır.
  • DNS-over-TLS (DoT): İstemcilerden gelen sorguları şifreli tünel üzerinden alabilir.
  • DNS-over-HTTPS (DoH): Özellikle tarayıcı uyumluluğu gerektiren ortamlar için DoH desteği mevcuttur.
  • Query minimization: RFC 7816 uyumlu bu özellik, root ve TLD sunucularına yalnızca minimum düzeyde bilgi göndererek gizlilik sağlar.
  • Aggressive NSEC: DNSSEC imzalı bölgelerde negatif önbellekleme yaparak gereksiz sorguları azaltır.
  • RPZ (Response Policy Zone) desteği: Belirli domain’leri veya IP aralıklarını engellemek için kullanılabilir.
  • Önbellekleme: Ayarlanabilir TTL yönetimiyle güçlü bir önbellekleme motoru sunar.

Kurulum

Farklı dağıtımlarda Unbound kurulumu oldukça basittir.

Debian/Ubuntu üzerinde:

apt update
apt install unbound unbound-anchor -y

RHEL/Rocky Linux/AlmaLinux üzerinde:

dnf install unbound -y
systemctl enable --now unbound

FreeBSD üzerinde:

pkg install unbound
sysrc unbound_enable="YES"
service unbound start

Kurulumun ardından root güven çapası (trust anchor) dosyasını güncellemek gerekir. Bu adım DNSSEC doğrulaması için zorunludur:

unbound-anchor -a /var/lib/unbound/root.key

Temel Yapılandırma

Unbound’un ana yapılandırma dosyası /etc/unbound/unbound.conf konumundadır. Ancak büyük ortamlarda her şeyi tek dosyaya koymak yerine parçalı yapılandırma tercih edilir. Bunun için include: direktifini kullanabilirsiniz.

Gerçek bir kurumsal ortam için kullandığım temel yapılandırma şablonu şu şekilde:

# /etc/unbound/unbound.conf

server:
    # Dinlenecek arayüz ve port
    interface: 0.0.0.0
    port: 53

    # IPv6 kullanılmıyorsa kapat
    do-ip6: no
    do-ip4: yes
    do-udp: yes
    do-tcp: yes

    # Erişim kontrolü - sadece iç ağdan sorgu kabul et
    access-control: 127.0.0.0/8 allow
    access-control: 10.0.0.0/8 allow
    access-control: 172.16.0.0/12 allow
    access-control: 192.168.0.0/16 allow
    access-control: 0.0.0.0/0 refuse

    # DNSSEC doğrulama
    auto-trust-anchor-file: "/var/lib/unbound/root.key"

    # Önbellekleme
    cache-min-ttl: 300
    cache-max-ttl: 86400
    cache-max-negative-ttl: 30

    # Güvenlik ayarları
    hide-identity: yes
    hide-version: yes
    harden-glue: yes
    harden-dnssec-stripped: yes
    harden-below-nxdomain: yes
    harden-referral-path: yes
    use-caps-for-id: yes

    # Gizlilik
    qname-minimisation: yes
    qname-minimisation-strict: no

    # Performans
    num-threads: 4
    so-reuseport: yes
    msg-cache-slabs: 8
    rrset-cache-slabs: 8
    infra-cache-slabs: 8
    key-cache-slabs: 8
    rrset-cache-size: 256m
    msg-cache-size: 128m

    # Log ayarları
    logfile: "/var/log/unbound/unbound.log"
    log-queries: no
    log-replies: no
    verbosity: 1

    # Root hints
    root-hints: "/var/lib/unbound/root.hints"

Root hints dosyasını indirmek için:

curl -o /var/lib/unbound/root.hints https://www.internic.net/domain/named.cache

Stub Zone ile İç Ağ DNS Entegrasyonu

Kurumsal ortamlarda en sık karşılaştığım senaryo şu: Unbound internete bakan recursive resolver olarak çalışıyor ama şirketin iç domain’leri için ayrı bir authoritative sunucu var (genellikle Active Directory ya da PowerDNS). Bu durumda Unbound’u belirli zone’lar için farklı bir sunucuya yönlendirmeniz gerekir.

Bu amaçla stub-zone kullanılır:

# /etc/unbound/conf.d/internal-zones.conf

stub-zone:
    name: "sirket.local"
    stub-addr: 10.0.1.10
    stub-addr: 10.0.1.11

stub-zone:
    name: "10.0.10.in-addr.arpa"
    stub-addr: 10.0.1.10
    stub-addr: 10.0.1.11

stub-zone ile forward-zone arasındaki fark önemlidir: stub-zone NS kayıtlarını sorgulayarak yönlendirme yapar, yani biraz daha “akıllı” davranır. forward-zone ise sorguyu doğrudan belirtilen adrese iletir. İç authoritative sunucular için stub-zone, upstream resolver kullanımı için forward-zone tercih edilmeli.

DNS-over-TLS Yapılandırması

Özellikle güvenlik gereksinimlerinin yüksek olduğu ortamlarda, Unbound’u DoT istemcisi olarak yapılandırabilirsiniz. Yani Unbound upstream resolver’lara sorgu gönderirken şifreli kanal kullanır.

# /etc/unbound/conf.d/dot-upstream.conf

forward-zone:
    name: "."
    forward-tls-upstream: yes
    # Cloudflare DoT
    forward-addr: 1.1.1.1@853#cloudflare-dns.com
    forward-addr: 1.0.0.1@853#cloudflare-dns.com
    # Quad9 DoT
    forward-addr: 9.9.9.9@853#dns.quad9.net
    forward-addr: 149.112.112.112@853#dns.quad9.net

Bu yapılandırmada @853 port numarasını, #cloudflare-dns.com ise TLS sertifika doğrulaması için kullanılan hostname’i temsil eder. Eğer hostname’i atarsanız Unbound IP adresini doğrulamaya çalışır ki bu da genellikle başarısız olur.

Öte yandan eğer Unbound’u aynı zamanda DoT sunucusu olarak da çalıştırmak istiyorsanız:

server:
    interface: 0.0.0.0@853
    tls-service-key: "/etc/ssl/private/dns.key"
    tls-service-pem: "/etc/ssl/certs/dns.crt"
    tls-port: 853

Bu durumda geçerli bir TLS sertifikasına ihtiyacınız olacak. Let’s Encrypt üzerinden alabileceğiniz ücretsiz bir sertifika bu iş için yeterlidir.

DNSSEC Doğrulamasını Test Etme

Unbound DNSSEC doğrulamasını aktif ettiğinizde, imzasız veya yanlış imzalanmış zone’lardan gelen yanıtlar reddedilir. Bunu test etmek için:

# Geçerli DNSSEC imzası olan bir domain
dig +dnssec cloudflare.com @127.0.0.1

# DNSSEC doğrulama başarısızlığını simüle eden test domain'i
dig dnssec-failed.org @127.0.0.1

# Beklenen çıktı: SERVFAIL - çünkü bu domain kasıtlı olarak yanlış imzalanmış

dig çıktısında ad (Authenticated Data) flag’ini görüyorsanız DNSSEC doğrulaması çalışıyor demektir. SERVFAIL yanıtı ise Unbound’un sahte veya bozuk DNS yanıtını reddettiğini gösterir ki bu tam istediğimiz davranış.

Unbound’un DNSSEC durumunu kontrol etmek için:

unbound-control status
unbound-control dump_cache | head -50

RPZ ile Domain Engelleme

Response Policy Zone, Unbound’a zararlı domain engelleme kapasitesi kazandıran güçlü bir özelliktir. Pi-hole benzeri bir DNS engelleme sistemi kurmak istemiyorsanız ama yine de belirli kategorilerdeki domain’leri engellemek istiyorsanız RPZ doğru tercih.

Önce RPZ feed’ini yapılandıralım:

# /etc/unbound/conf.d/rpz.conf

rpz:
    name: "rpz.local"
    zonefile: "/etc/unbound/rpz-blocklist.zone"
    rpz-log: yes
    rpz-log-name: "blocklist"

RPZ zone dosyası örneği:

# /etc/unbound/rpz-blocklist.zone

$ORIGIN rpz.local.
$TTL 300

@ SOA localhost. root.localhost. (
    2024010101  ; serial
    3600        ; refresh
    600         ; retry
    86400       ; expire
    300 )       ; minimum TTL

    NS localhost.

; Engellenen domain'ler - NXDOMAIN ile yanıtlanır
malware-domain.example.rpz.local.       CNAME   .
phishing-site.example.rpz.local.        CNAME   .
tracking-domain.example.rpz.local.      CNAME   .

RPZ zone dosyasını güncelledikten sonra Unbound’u yeniden başlatmadan reload edebilirsiniz:

unbound-control reload

Gerçek Dünya Senaryosu: Kurumsal Split-Horizon DNS

Şimdi daha gerçekçi bir senaryo ele alalım. Diyelim ki şirketinizin hem iç ağa hem de internete bakan bir sirket.com domain’i var. İç ağdan portal.sirket.com sorgulandığında 10.0.5.100 dönsün, dışarıdan sorgulandığında ise gerçek public IP dönsün. Bu klasik split-horizon DNS senaryosudur.

# /etc/unbound/conf.d/split-horizon.conf

# İç ağ için local-zone tanımı
local-zone: "sirket.com" transparent

# İç kayıtlar
local-data: "portal.sirket.com. A 10.0.5.100"
local-data: "intranet.sirket.com. A 10.0.5.101"
local-data: "mail.sirket.com. A 10.0.5.102"

# PTR kayıtları
local-data-ptr: "10.0.5.100 portal.sirket.com"
local-data-ptr: "10.0.5.101 intranet.sirket.com"

transparent tipi burada önemli: Bu tip, local-data ile tanımlanmış kayıtlar için o yanıtı dönerken, tanımlanmamış kayıtlar için recursive sorguya devam etmesini sağlar. Yani www.sirket.com için local kayıt yoksa Unbound internete sorgu atmaya devam eder.

Performans Ayarlaması ve İzleme

Yüksek trafikli ortamlarda Unbound’un performansını optimize etmek için birkaç kritik parametre var:

server:
    # Thread sayısını CPU core sayısına eşitle
    num-threads: 8

    # Her thread için outgoing port sayısı
    outgoing-range: 8192

    # Aynı anda işlenebilecek maksimum sorgu sayısı
    num-queries-per-thread: 4096

    # Slab sayıları thread sayısının 2 katı olmalı (2'nin kuvveti)
    msg-cache-slabs: 16
    rrset-cache-slabs: 16
    infra-cache-slabs: 16
    key-cache-slabs: 16

    # Önbellek boyutları (toplam RAM'in %10-15'i makul bir başlangıç)
    rrset-cache-size: 512m
    msg-cache-size: 256m

    # Prefetch: TTL dolmadan önce popüler kayıtları yenile
    prefetch: yes
    prefetch-key: yes

Unbound’un istatistiklerini gerçek zamanlı izlemek için:

# İstatistik toplamayı etkinleştir
# unbound.conf içine ekle:
# statistics-interval: 60
# extended-statistics: yes

# Anlık istatistikleri çek
unbound-control stats_noreset

# Önbellek durumu
unbound-control dump_infra | head -30

# Belirli bir domain'in önbellekteki durumu
unbound-control lookup portal.sirket.com

Prometheus ile entegrasyon için unbound_exporter kullanabilirsiniz:

# unbound.conf içinde remote control aktif olmalı
remote-control:
    control-enable: yes
    control-interface: 127.0.0.1
    control-port: 8953
    server-key-file: "/var/lib/unbound/unbound_server.key"
    server-cert-file: "/var/lib/unbound/unbound_server.pem"
    control-key-file: "/var/lib/unbound/unbound_control.key"
    control-cert-file: "/var/lib/unbound/unbound_control.pem"

SSL sertifikalarını oluşturmak için:

unbound-control-setup

Güvenlik Sertleştirme Kontrol Listesi

Unbound’u production’a almadan önce şu maddeleri gözden geçirin:

  • hide-identity: yes aktif olmalı – sunucu kimliğini gizler
  • hide-version: yes aktif olmalı – sürüm bilgisini gizler
  • harden-glue: yes aktif olmalı – glue kayıtlarını doğrular
  • harden-dnssec-stripped: yes aktif olmalı – DNSSEC soyulma saldırılarına karşı korur
  • use-caps-for-id: yes aktif olmalı – 0x20 encoding ile DNS zehirlenmesine karşı ek koruma
  • qname-minimisation: yes aktif olmalı – DNS gizliliğini artırır
  • access-control direktifleri doğru yapılandırılmalı – açık resolver olmaktan kaçının
  • chroot ile çalıştırmayı değerlendirin (karmaşıklık artsa da)
  • AppArmor veya SELinux profili aktif olmalı

Açık resolver olup olmadığınızı test etmek için:

# Dışarıdan test - başka bir sunucu veya IP üzerinden
dig +short google.com @SUNUCU_IP

# Eğer yanıt dönüyorsa access-control ayarlarınızı gözden geçirin

Systemd ve Servis Yönetimi

Unbound’u systemd altında güvenli çalıştırmak için özel bir service override’ı oluşturabilirsiniz:

# /etc/systemd/system/unbound.service.d/hardening.conf

[Service]
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
NoNewPrivileges=yes
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID
ReadWritePaths=/var/lib/unbound /var/log/unbound

[Unit]
After=network-online.target
Wants=network-online.target

Değişiklikleri uygulamak için:

systemctl daemon-reload
systemctl restart unbound
systemctl status unbound

Sık Karşılaşılan Sorunlar ve Çözümleri

SERVFAIL yanıtları alıyorum ama domain gerçekten var: Büyük ihtimalle DNSSEC doğrulama hatası. unbound-control flush sirket.com komutuyla önbelleği temizleyip dig +dnssec sirket.com @127.0.0.1 ile test edin. Hata mesajı için de verbosity: 3 ile log’ları inceleyin.

stub-zone çalışmıyor, iç domain’ler resolve edilmiyor: stub-first: yes ekleyebilirsiniz. Bu seçenek, stub sunucusu yanıt vermezse Unbound’un recursive sorguya geçmesini sağlar. Ancak production’da dikkatli kullanın, istenmeyen veri sızıntısına yol açabilir.

systemd-resolved çakışması: Ubuntu’da Unbound kurduğunuzda port 53 zaten systemd-resolved tarafından tutulmuş olabilir:

systemctl disable --now systemd-resolved
rm /etc/resolv.conf
echo "nameserver 127.0.0.1" > /etc/resolv.conf

Yüksek memory kullanımı: rrset-cache-size ve msg-cache-size değerlerini düşürün. Ayrıca cache-max-ttl değerini kısaltmak önbellek boyutunu kontrol altında tutar.

Sonuç

Unbound, “sadece çalışan bir DNS resolver” ihtiyacının çok ötesine geçiyor. DNSSEC doğrulaması, DNS-over-TLS desteği, query minimization gibi özellikleriyle modern bir güvenlik altyapısının vazgeçilmez parçası olabiliyor. Üstelik BIND’ın karmaşıklığından uzak, anlaşılır bir yapılandırma diliyle geliyor.

Küçük bir ofis ağından yüz binlerce sorgu işleyen kurumsal ortama kadar geniş bir yelpazede kullanılabiliyor. Ben kişisel olarak, recursive resolver seçimi söz konusu olduğunda artık Unbound’dan başka tarafa bakmıyorum. Zaman içinde altyapınıza özgü yapılandırmaları oturttuğunuzda, hem güvenlik hem de performans açısından farkı net biçimde hissedeceksiniz.

Bir sonraki adım olarak Unbound ile birlikte Redis önbellekleme entegrasyonunu ya da Prometheus ve Grafana ile DNS metrik izlemeyi ele alabiliriz. İkisi de production ortamlar için ciddi fayda sağlayan konular.

Bir yanıt yazın

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