Unbound DNS Sunucusu Ubuntu ve Debian’a Kurulum Rehberi

Bir süredir BIND9 ile uğraşan sistem yöneticileri biliyor: büyük altyapılarda BIND muhteşemdir, ama küçük-orta ölçekli ortamlarda, özellikle sadece recursive resolver ihtiyacı varsa, beraberinde getirdiği karmaşıklık gereksiz bir yük oluşturabilir. İşte tam bu noktada Unbound devreye giriyor. NLnet Labs tarafından geliştirilen bu hafif, güvenlik odaklı DNS resolver, özellikle DNSSEC doğrulama ve önbellekleme konularında ciddi avantajlar sunuyor. Bu yazıda Ubuntu ve Debian üzerinde Unbound’u sıfırdan kurup production-ready hale getireceğiz.

Neden Unbound?

Şunu açıkça söyleyeyim: Unbound her ortam için değil. Authoritative DNS sunucusu ihtiyacınız varsa yanlış araçsınız. Ama şu senaryolar için gerçekten biçilmiş kaftan:

  • Kurumsal ağda dahili DNS çözümleyici (recursive resolver) olarak
  • Pi-hole veya benzeri reklam engelleyicilerle entegrasyon
  • DNSSEC doğrulaması zorunlu olan ortamlar
  • DNS-over-TLS veya DNS-over-HTTPS ihtiyacı olan yapılar
  • Yüksek önbellekleme performansı istenen küçük-orta datacenter kurulumları

Özellikle bir müşteri projesinde, şirketin tüm DNS trafiğini dışa bağımlı genel resolver’lardan (8.8.8.8 gibi) kurtarıp kendi altyapısında çözümlemek istediğinde Unbound bu işi oldukça temiz çözdü. Hafıza kullanımı minimal, yapılandırması anlaşılır, güvenlik açısından varsayılan ayarlar zaten makul seviyede.

Kurulum Öncesi Hazırlık

Sistem Gereksinimlerini Kontrol Etme

Ubuntu 20.04, 22.04, 24.04 ve Debian 11, 12 için kurulum adımları büyük ölçüde aynı. Önce mevcut DNS durumunu kontrol edelim:

# Mevcut DNS servisini kontrol et
systemctl status systemd-resolved
netstat -tulpn | grep :53
ss -tulpn | grep :53

Çoğu modern Ubuntu kurulumunda systemd-resolved 53 portunu dinliyor. Unbound ile çakışma yaşamamak için bunu düzgünce yönetmek gerekiyor. Bunu atlayan kurulumlar sonradan “port already in use” hatasiyla karşılaşıyor.

systemd-resolved ile Çakışmayı Önleme

# systemd-resolved'ın stub listener'ını devre dışı bırak
sudo mkdir -p /etc/systemd/resolved.conf.d/
sudo tee /etc/systemd/resolved.conf.d/nostublistener.conf > /dev/null <<EOF
[Resolve]
DNSStubListener=no
DNS=127.0.0.1
EOF

# Servisi yeniden başlat
sudo systemctl restart systemd-resolved

# /etc/resolv.conf symlink'ini güncelle
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Bu adım özellikle Ubuntu 20.04 ve sonrasında kritik. Debian kurulumlarında genellikle sorun daha az çıkıyor, ama kontrol etmekte fayda var.

Unbound Kurulumu

Paket Kurulumu

# Paket listelerini güncelle
sudo apt update

# Unbound ve yardımcı araçları kur
sudo apt install -y unbound unbound-anchor dns-root-data

# Kurulumu doğrula
unbound -V

unbound-anchor paketi DNSSEC için root trust anchor dosyasını yönetiyor. dns-root-data ise root zone verilerini içeriyor ve root hints dosyasını sisteme sağlıyor. Bu ikisini atlamayın.

Servis Durumunu Kontrol Etme

sudo systemctl status unbound
sudo systemctl enable unbound

İlk kurulumdan sonra servis hata verebilir, çünkü varsayılan yapılandırma dosyası çok minimal. Asıl konfigürasyon adımından sonra düzelecek.

Ana Yapılandırma Dosyası

Unbound’un ana yapılandırma dosyası /etc/unbound/unbound.conf ve bu dosyanın include ettiği /etc/unbound/unbound.conf.d/ dizini. Ben production ortamlarda her zaman modüler yapıyı tercih ediyorum: ana conf dosyasına dokunmadan, unbound.conf.d/ altında özel dosyalar oluşturuyorum.

Temel Resolver Yapılandırması

sudo tee /etc/unbound/unbound.conf.d/resolver.conf > /dev/null <<'EOF'
server:
    # Dinlenecek arayüz ve port
    interface: 0.0.0.0
    port: 53
    
    # IPv6 kullanmıyorsak devre dışı bırak
    do-ipv6: no
    do-ip4: yes
    do-udp: yes
    do-tcp: yes
    
    # Erişim kontrolü - sadece yerel ağdan gelen sorgulara izin ver
    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"
    
    # Root hints dosyası
    root-hints: "/usr/share/dns/root.hints"
    
    # Önbellekleme ayarları
    cache-min-ttl: 300
    cache-max-ttl: 86400
    cache-max-negative-ttl: 30
    
    # Performans ayarları
    num-threads: 2
    msg-cache-slabs: 4
    rrset-cache-slabs: 4
    infra-cache-slabs: 4
    key-cache-slabs: 4
    rrset-cache-size: 256m
    msg-cache-size: 128m
    
    # Gizlilik ve güvenlik
    hide-identity: yes
    hide-version: yes
    harden-glue: yes
    harden-dnssec-stripped: yes
    use-caps-for-id: yes
    
    # Log ayarları
    verbosity: 1
    log-queries: no
    log-replies: no
    logfile: "/var/log/unbound/unbound.log"
    
    # Unwanted reply threshold
    unwanted-reply-threshold: 10000

EOF

Birkaç parametreye dikkat çekmek istiyorum:

  • use-caps-for-id: DNS 0x20 encoding olarak bilinen teknik. Sorgulardaki harfleri rastgele büyük/küçük yaparak cache poisoning saldırılarını zorlaştırıyor.
  • harden-dnssec-stripped: DNSSEC imzalı bir zone’dan imzasız cevap gelirse reddet. Bunu aktif tutun.
  • cache-max-negative-ttl: 30: NXDOMAIN cevaplarını 30 saniyeden fazla cache’leme. Uzun negative caching bazı ortamlarda sorun çıkarabiliyor.

Log Dizinini Oluşturma

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

Yapılandırmayı Doğrulama ve Servisi Başlatma

# Yapılandırma sözdizimini kontrol et
sudo unbound-checkconf

# Servisi yeniden başlat
sudo systemctl restart unbound
sudo systemctl status unbound

# DNS çözümlemesini test et
dig @127.0.0.1 google.com
dig @127.0.0.1 google.com +dnssec

unbound-checkconf hiçbir çıktı vermeden dönerse yapılandırma dosyası sözdizimi doğrudur. Hata varsa satır numarasıyla birlikte bildiriyor, oldukça kullanışlı.

DNSSEC Doğrulamasını Yapılandırma

DNSSEC Unbound’un en güçlü yanlarından biri. Root key’i güncel tutmak için unbound-anchor aracını kullanıyoruz:

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

# DNSSEC doğrulamasını test et
# Bu sorgu SERVFAIL dönmemeli
dig @127.0.0.1 sigok.verteiltesysteme.net +dnssec

# Bu sorgu SERVFAIL dönmeli (kasıtlı bozuk DNSSEC)
dig @127.0.0.1 sigfail.verteiltesysteme.net +dnssec

İkinci komutun SERVFAIL dönmesi aslında doğru davranış: Unbound DNSSEC doğrulaması başarısız olduğunda sorguyu reddediyor. Bu tam olarak istediğimiz şey.

Root key otomatik güncelleme için bir cron görevi veya systemd timer ayarlamak iyi pratik:

sudo tee /etc/cron.weekly/unbound-anchor > /dev/null <<'EOF'
#!/bin/bash
/usr/sbin/unbound-anchor -a /var/lib/unbound/root.key
chown unbound:unbound /var/lib/unbound/root.key
systemctl reload unbound
EOF

sudo chmod +x /etc/cron.weekly/unbound-anchor

Dahili Alan Adları için Local Zone Tanımlama

Bu kısım özellikle kurumsal ortamlarda çok işe yarıyor. Diyelim ki sirket.local gibi dahili bir domain var ve bu domain için özel DNS kayıtları tanımlamak istiyorsunuz:

sudo tee /etc/unbound/unbound.conf.d/local-zones.conf > /dev/null <<'EOF'
server:
    # Dahili zone tanımı
    local-zone: "sirket.local." static
    
    # A kayıtları
    local-data: "webserver.sirket.local. IN A 192.168.1.10"
    local-data: "dbserver.sirket.local. IN A 192.168.1.20"
    local-data: "mailserver.sirket.local. IN A 192.168.1.30"
    local-data: "vpn.sirket.local. IN A 192.168.1.40"
    
    # PTR kayıtları (reverse DNS)
    local-data-ptr: "192.168.1.10 webserver.sirket.local"
    local-data-ptr: "192.168.1.20 dbserver.sirket.local"
    local-data-ptr: "192.168.1.30 mailserver.sirket.local"
    local-data-ptr: "192.168.1.40 vpn.sirket.local"

EOF

local-zone tiplerine dikkat:

  • static: Zone’da tanımlanmayan kayıtlar için NXDOMAIN dönülür
  • transparent: Tanımlanmayan kayıtlar için upstream’e sorulur
  • redirect: Tüm sorgular belirtilen adrese yönlendirilir

Reklam engelleme amacıyla tüm domaine yönlendirme yapmak için redirect kullanılabilir, ama bu konu ayrı bir yazıyı hak ediyor.

Belirli Domain’leri Forward Etme

Bazı durumlarda belirli domain’leri farklı DNS sunucularına yönlendirmek gerekiyor. Örneğin şirket VPN üzerindeyken corp.example.com sorgularını şirket DNS’ine göndermek:

sudo tee /etc/unbound/unbound.conf.d/forward-zones.conf > /dev/null <<'EOF'
# Belirli domain'ler icin forward
forward-zone:
    name: "corp.example.com."
    forward-addr: 10.0.0.53
    forward-first: no

# Tüm diğer sorgular için upstream DNS (opsiyonel)
# Bu olmadan Unbound root sunuculardan recursive çözümleme yapar
# forward-zone:
#     name: "."
#     forward-addr: 1.1.1.1@853#cloudflare-dns.com
#     forward-tls-upstream: yes

EOF

Dikkat: Eğer root zone için forward-zone tanımlarsanız Unbound artık tam recursive çözümleme yapmaz, sorguları o sunucuya iletir. Bu durumda DNSSEC doğrulamasının davranışı değişir. Root zone forward etmek yerine Unbound’u tam recursive resolver olarak kullanmanızı öneririm, zira bu en güvenli ve gizlilik dostu seçenek.

DNS-over-TLS (DoT) Yapılandırması

Gelen sorgular için DoT desteği veya upstream sorgularını TLS üzerinden göndermek için:

sudo tee /etc/unbound/unbound.conf.d/tls.conf > /dev/null <<'EOF'
server:
    # DoT için port 853'ü dinle
    interface: 0.0.0.0@853
    
    # TLS sertifika dosyaları (Let's Encrypt veya kendi CA'nızdan)
    tls-service-key: "/etc/ssl/private/dns-server.key"
    tls-service-pem: "/etc/ssl/certs/dns-server.crt"
    
    # DoT erişim kontrolü
    access-control: 192.168.0.0/16 allow

EOF

Sertifika dosyaları hazır değilse bu bölümü şimdilik atlayıp yalnızca temel kurulumu tamamlayabilirsiniz.

Performans İzleme ve İstatistikler

Unbound’un yerleşik istatistik özelliği var. Bunu etkinleştirmek için:

sudo tee /etc/unbound/unbound.conf.d/stats.conf > /dev/null <<'EOF'
server:
    statistics-interval: 0
    extended-statistics: yes
    statistics-cumulative: no

remote-control:
    control-enable: yes
    control-interface: 127.0.0.1
    control-port: 8953
    control-use-cert: yes
    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
sudo unbound-control-setup

# Servisi yeniden başlat
sudo systemctl restart unbound

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

unbound-control ile yapabileceğiniz bazı faydalı komutlar:

  • sudo unbound-control status: Servis durumu ve temel bilgiler
  • sudo unbound-control stats: Anlık istatistikler (cache hit/miss, sorgu sayıları)
  • sudo unbound-control flush google.com: Belirli bir domain’i cache’den sil
  • sudo unbound-control flush_zone sirket.local: Tüm zone’u cache’den temizle
  • sudo unbound-control reload: Yapılandırmayı yeniden yükle (servisi durdurmadan)
  • sudo unbound-control dump_cache: Mevcut cache içeriğini döktür

Güvenlik Duvarı Ayarları

Unbound’u bir DNS sunucusu olarak ağa açıyorsanız güvenlik duvarı kurallarını da ayarlamak gerekiyor:

# UFW kullanıyorsanız
sudo ufw allow 53/udp
sudo ufw allow 53/tcp
sudo ufw allow 853/tcp  # DNS-over-TLS kullanıyorsanız

# iptables kullanıyorsanız
sudo iptables -A INPUT -p udp --dport 53 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 53 -j ACCEPT

# Kuralları kalıcı hale getir
sudo netfilter-persistent save

Yaygın Sorunlar ve Çözümleri

Servis başlamıyor, “Address already in use” hatası: 53 portunu başka bir servis kullanıyor demektir. Yukarıda anlatılan systemd-resolved adımlarını kontrol edin.

sudo ss -tulpn | grep :53
sudo lsof -i :53

DNSSEC doğrulaması SERVFAIL veriyor ama domain var: Root key güncel olmayabilir. sudo unbound-anchor -a /var/lib/unbound/root.key komutunu çalıştırın.

Dahili zone çalışmıyor: Yapılandırma sözdizimini sudo unbound-checkconf ile kontrol edin ve nokta (.) karakterlerine dikkat edin. Zone isimleri trailing dot ile bitmelidir: sirket.local.

Yüksek gecikme: Önbellekleme çalışmıyor olabilir. sudo unbound-control stats | grep cache çıktısında cache hit oranını kontrol edin. Düşük bir oran için rrset-cache-size ve msg-cache-size değerlerini artırın.

# Hızlı tanılama scripti
echo "=== Servis Durumu ===" && systemctl is-active unbound
echo "=== Port Kontrolü ===" && ss -tulpn | grep :53
echo "=== Temel Sorgu Testi ===" && dig @127.0.0.1 google.com | grep "Query time"
echo "=== DNSSEC Testi ===" && dig @127.0.0.1 +dnssec sigok.verteiltesysteme.net | grep -E "RRSIG|SERVFAIL|status"
echo "=== Cache Istatistikleri ===" && unbound-control stats_noreset | grep -E "cache.(hits|miss)"

Logrotate Yapılandırması

Log dosyasının şişmesini önlemek için logrotate ayarlayalım:

sudo tee /etc/logrotate.d/unbound > /dev/null <<'EOF'
/var/log/unbound/unbound.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    postrotate
        /usr/sbin/unbound-control log_reopen
    endscript
}
EOF

Sonuç

Unbound, doğru yapılandırıldığında ciddi bir altyapı katmanı oluşturuyor. Anlattığım adımları izleyerek kurduğunuzda elinizde şunlar var: DNSSEC doğrulaması yapan, önbellekleme ile gecikmeyi düşüren, erişim kontrolü ile dışarıya kapalı, dahili zone desteğiyle kurumsal ortama uygun bir recursive DNS resolver.

Production’a almadan önce şu kontrol listesini geçin:

  • unbound-checkconf temiz dönüyor mu
  • dig @127.0.0.1 google.com başarılı yanıt veriyor mu
  • DNSSEC testi doğru çalışıyor mu
  • Firewall kuralları doğru mu
  • access-control yalnızca yerel ağa açık mı
  • Log rotasyon ayarı yapıldı mı
  • Root key otomatik güncelleme tanımlandı mı

Ölçek büyüdükçe, birden fazla Unbound sunucusu arasında yük dağıtımı veya anycast yapılandırmaları gibi konulara girmek gerekebilir. Ama tek site, birkaç yüz kullanıcılı bir ortam için bu yapılandırma fazlasıyla yeterli ve uzun süre bakım gerektirmeden çalışır.

Bir yanıt yazın

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