Unbound ile BIND’dan Geçiş Rehberi
Yıllarca BIND çalıştırdıktan sonra bir gün sunucunuzun bellek kullanımına bakıp “bu kadar mı lazım?” diye sorduğunuzda, Unbound’u araştırmaya başlıyorsunuz. Ben de tam olarak böyle başladım bu yolculuğa. Küçük ve orta ölçekli altyapılarda, özellikle recursive resolver ihtiyacı olan ortamlarda BIND bazen gereksiz yere şişirilmiş bir çözüm gibi görünüyor. Unbound ise tam bu noktada devreye giriyor: hafif, güvenli ve modern DNS standartlarını destekleyen bir recursive resolver.
Bu yazıda BIND’dan Unbound’a geçiş sürecini, gerçek bir ortamda karşılaşabileceğiniz problemlerle birlikte ele alacağız. Teorik değil, sahada çalışan bir rehber olmasını hedefliyorum.
Neden Unbound?
BIND, yıllardır DNS dünyasının standartı olarak kabul görüyor. Authoritative ve recursive her iki rolü de üstlenebilen kapsamlı bir çözüm. Ancak bu kapsamlılık beraberinde karmaşıklık ve kaynak tüketimi getiriyor.
Unbound’un öne çıkan avantajları:
- DNSSEC doğrulama desteği varsayılan olarak geliyor, ayrıca yapılandırmanıza gerek yok
- Bellek ayak izi çok daha küçük, tipik bir ortamda BIND’ın yarısı kadar bile değil
- Yapılandırma dosyası çok daha okunabilir ve anlaşılır
- Güvenlik odaklı mimari ile tasarlanmış, chroot ve privilege separation varsayılan
- QNAME minimization gibi gizlilik özelliklerini destekliyor
- DNS-over-TLS (DoT) desteği mevcut
Şunu da açıkça söylemek gerekiyor: eğer authoritative DNS sunucusu işletiyorsanız, Unbound tek başına bu iş için uygun değil. Authoritative görev için NSD veya PowerDNS’e bakmanız gerekecek. Unbound tamamen recursive resolver rolüne odaklanmış.
Geçiş Öncesi Mevcut Durumu Analiz Etme
Herhangi bir göçü başlatmadan önce mevcut BIND kurulumunuzun tam olarak ne yaptığını belgelemeniz şart. Bunu atlamak sonradan başınızı çok ağrıtır.
# Mevcut BIND konfigürasyonunu kontrol et
named-checkconf -p /etc/named.conf
# Hangi zone'lar var?
grep -E "^zone" /etc/named.conf | awk '{print $2}' | tr -d '"'
# BIND'ın hangi portları dinlediğini gör
ss -tlnp | grep named
# Günlük ne kadar sorgu geliyor?
journalctl -u named --since "24 hours ago" | grep "query:" | wc -l
Bu analiz size şu soruların cevabını verdiğinde devam edebilirsiniz:
- Recursive resolver mi, authoritative sunucu mu, yoksa her ikisi mi çalıştırıyorsunuz?
- Hangi forwarder’lar kullanılıyor?
- Access control list’ler nasıl yapılandırılmış?
- Split-horizon DNS ihtiyacı var mı?
- DNSSEC kullanıyor musunuz?
# BIND forwarder ayarlarını bul
grep -A5 "forwarders" /etc/named.conf
# ACL tanımlamalarını çıkar
grep -B1 -A10 "acl " /etc/named.conf
Unbound Kurulumu
Kurulum kısmı çoğu dağıtımda oldukça basit. Paket deposundan gelen sürümler genellikle yeterince güncel, ancak kritik ortamlar için kaynak koddan derlemeyi de düşünebilirsiniz.
# RHEL/CentOS/AlmaLinux/Rocky Linux
dnf install unbound unbound-utils
# Debian/Ubuntu
apt-get install unbound
# Servis durumunu kontrol et
systemctl status unbound
# Unbound sürümünü doğrula
unbound -V
BIND ile çakışmayı önlemek için geçiş süreci boyunca her iki servisi de aynı anda aynı portta çalıştırmayacaksınız. Bunu göz önünde bulundurarak test ortamında farklı bir port kullanarak Unbound’u ayağa kaldırabilirsiniz.
Temel Yapılandırma Dosyası
Unbound’un ana yapılandırma dosyası /etc/unbound/unbound.conf konumunda bulunuyor. BIND’ın named.conf formatına alışkınsanız sözdizimi biraz farklı gelecek ama birkaç dosya okuyunca mantığını hemen anlıyorsunuz.
server:
# Temel ayarlar
verbosity: 1
interface: 0.0.0.0
interface: ::0
port: 53
# Kaç CPU çekirdeği varsa buna göre ayarla
num-threads: 4
# Cache boyutları (belleğinize göre düzenleyin)
msg-cache-size: 128m
rrset-cache-size: 256m
# İzin verilen istemciler
access-control: 127.0.0.0/8 allow
access-control: 10.0.0.0/8 allow
access-control: 192.168.0.0/16 allow
access-control: 172.16.0.0/12 allow
access-control: 0.0.0.0/0 refuse
# DNSSEC doğrulama
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Güvenlik ayarları
hide-identity: yes
hide-version: yes
qname-minimisation: yes
# Harden ayarları
harden-glue: yes
harden-dnssec-stripped: yes
harden-referral-path: yes
# Prefetch aktif sorgular için cache'i yenile
prefetch: yes
prefetch-key: yes
# Log ayarları
logfile: "/var/log/unbound/unbound.log"
log-queries: no
log-replies: no
# Forwarder yapılandırması (BIND'daki gibi)
forward-zone:
name: "."
forward-addr: 8.8.8.8
forward-addr: 8.8.4.4
forward-first: no
Bu yapılandırmanın BIND’daki options bloğuna denk geldiğini göreceksiniz. En önemli fark DNSSEC’in varsayılan olarak aktif gelmesi.
Özel Alan Adları ve Split-Horizon DNS
Kurumsal ortamlarda en sık karşılaşılan senaryo, iç ağ için özel domain’lerin yönetilmesi. BIND’da view bloklarıyla yapılan split-horizon konfigürasyonunu Unbound’da farklı şekilde ele alıyoruz.
# /etc/unbound/unbound.conf.d/internal-zones.conf
# Yerel stub zone tanımı
stub-zone:
name: "sirket.local"
stub-addr: 192.168.1.10 # İç DNS sunucunuzun adresi
# Authoritative iç zone için local-data kullanımı
local-zone: "internal.example.com." static
local-data: "host1.internal.example.com. A 10.0.1.50"
local-data: "host2.internal.example.com. A 10.0.1.51"
local-data: "db.internal.example.com. A 10.0.1.100"
# Reverse zone için
local-zone: "0.0.10.in-addr.arpa." static
local-data-ptr: "10.0.1.50 host1.internal.example.com."
local-data-ptr: "10.0.1.51 host2.internal.example.com."
Şunu vurgulamak istiyorum: local-data küçük ortamlar için mükemmel ama onlarca, yüzlerce kayıt için yönetmesi zor. Bu durumda stub-zone ile Unbound’u iç authoritative sunucuya yönlendirmek çok daha sağlıklı.
BIND’dan Unbound’a Konfigürasyon Dönüşümü
Bir müşteri ortamında şu BIND yapılandırmasıyla karşılaştım:
# BIND named.conf (eski)
options {
directory "/var/named";
listen-on { any; };
allow-query { 192.168.0.0/16; 10.0.0.0/8; localhost; };
forwarders { 1.1.1.1; 1.0.0.1; };
forward only;
dnssec-validation auto;
recursion yes;
};
Bu yapılandırmanın Unbound karşılığı:
# Unbound unbound.conf (yeni)
server:
interface: 0.0.0.0
port: 53
access-control: 192.168.0.0/16 allow
access-control: 10.0.0.0/8 allow
access-control: 127.0.0.0/8 allow
access-control: 0.0.0.0/0 refuse
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Güvenlik
hide-identity: yes
hide-version: yes
forward-zone:
name: "."
forward-addr: 1.1.1.1
forward-addr: 1.0.0.1
forward-only: yes
Görüldüğü gibi yaklaşık aynı işlevi çok daha temiz bir yapıyla elde ediyoruz.
Geçiş Sürecini Aşamalı Yapmak
Birden sert geçiş yapmak yerine aşamalı bir yaklaşım öneriyorum. Özellikle üretim ortamlarında bu kritik.
1. Aşama: Paralel çalıştırma
# Unbound'u farklı portta başlat (test için)
# /etc/unbound/unbound.conf içinde:
# port: 5353
systemctl start unbound
# Temel testleri yap
dig @127.0.0.1 -p 5353 google.com
dig @127.0.0.1 -p 5353 +dnssec google.com
# DNSSEC doğrulama çalışıyor mu?
dig @127.0.0.1 -p 5353 sigfail.verteiltesysteme.net
# Bu sorgu SERVFAIL dönmeli - DNSSEC doğru çalışıyor
2. Aşama: Konfigürasyonu doğrula
# Unbound konfigürasyonunu syntax kontrol
unbound-checkconf /etc/unbound/unbound.conf
# Servis durumu
systemctl status unbound
# Log'ları takip et
tail -f /var/log/unbound/unbound.log
3. Aşama: Kademeli yük aktarımı
Birden fazla DNS sunucunuz varsa, istemcileri tek tek yeni Unbound sunucusuna yönlendirin. BIND’ı hemen kapatmak yerine birkaç gün standby’da tutun.
# BIND'ı durdur, Unbound'u 53 portuna al
systemctl stop named
# unbound.conf içinde port 53 olduğundan emin ol
systemctl restart unbound
# Temel işlevselliği doğrula
dig @localhost google.com
nslookup internal.example.com localhost
Performans Ayarlaması
Unbound’un varsayılan ayarları çoğu ortam için makul, ancak yüksek trafikli ortamlarda ayarlamalar yapmak gerekiyor.
server:
# Thread sayısı CPU sayısıyla eşleşmeli
num-threads: 8
# Her thread için slap boyutu
msg-cache-slabs: 8
rrset-cache-slabs: 8
infra-cache-slabs: 8
key-cache-slabs: 8
# Büyük ortamlar için cache boyutları
rrset-cache-size: 512m
msg-cache-size: 256m
# Outgoing bağlantı sayısı
outgoing-range: 8192
num-queries-per-thread: 4096
# SO_REUSEPORT kernel desteği varsa
so-reuseport: yes
# Büyük UDP paketleri için
so-rcvbuf: 4m
so-sndbuf: 4m
# Rate limiting (DDoS koruması)
ratelimit: 1000
Bu ayarları uyguladıktan sonra performans metriklerini izlemek için:
# Unbound istatistiklerini görüntüle
unbound-control stats_noreset
# Detaylı istatistikler
unbound-control stats
# Cache doluluk oranını kontrol et
unbound-control stats | grep "cache.count"
# Remote control etkinleştirme (önceden yapılmalı)
unbound-control-setup
DNS-over-TLS Yapılandırması
Modern güvenlik gereksinimleri için DNS-over-TLS, özellikle upstram sorguları şifrelemek istediğinizde faydalı:
# /etc/unbound/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
Monitoring ve Log Yönetimi
Geçiş sonrası sistemin sağlıklı çalıştığını doğrulamak için basit bir izleme scripti:
#!/bin/bash
# /usr/local/bin/check-unbound.sh
LOGFILE="/var/log/unbound-health.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
# Temel sorgu testi
RESULT=$(dig @127.0.0.1 google.com +short +time=2 2>/dev/null)
if [ -z "$RESULT" ]; then
echo "$DATE - HATA: Unbound yanit vermiyor!" >> $LOGFILE
systemctl restart unbound
echo "$DATE - Unbound yeniden baslatildi" >> $LOGFILE
else
# Yanıt süresi kontrolü
LATENCY=$(dig @127.0.0.1 google.com | grep "Query time" | awk '{print $4}')
echo "$DATE - OK: google.com -> $RESULT (${LATENCY}ms)" >> $LOGFILE
fi
# DNSSEC kontrolü
DNSSEC_TEST=$(dig @127.0.0.1 sigfail.verteiltesysteme.net +dnssec 2>/dev/null | grep "SERVFAIL")
if [ -n "$DNSSEC_TEST" ]; then
echo "$DATE - DNSSEC dogrulama calisiyor" >> $LOGFILE
else
echo "$DATE - UYARI: DNSSEC dogrulama sorunlu!" >> $LOGFILE
fi
# İstatistikleri logla
CACHE_COUNT=$(unbound-control stats_noreset 2>/dev/null | grep "total.num.cachehits" | awk -F= '{print $2}')
echo "$DATE - Cache hits: $CACHE_COUNT" >> $LOGFILE
Bu scripti cron’a ekleyin:
# crontab -e
*/5 * * * * /usr/local/bin/check-unbound.sh
Sık Karşılaşılan Sorunlar ve Çözümleri
DNSSEC doğrulama hataları: Bazı eski sunuculara erişimde SERVFAIL alabilirsiniz. Bu genellikle yanlış imzalanmış zone’lardan kaynaklanıyor. Geçici çözüm olarak belirli domain’ler için DNSSEC’i devre dışı bırakabilirsiniz:
server:
domain-insecure: "eskidomain.example.com"
Root anchor güncellemesi: Zaman zaman root trust anchor’ın yenilenmesi gerekiyor:
unbound-anchor -a /var/lib/unbound/root.key
# veya
systemctl restart unbound-anchor
Yüksek bellek kullanımı: Cache boyutlarını gözden geçirin. Bellek kullanımını canlı izlemek için:
unbound-control stats | grep "mem.total"
Yetkisiz erişim denemeleri: access-control: 0.0.0.0/0 refuse satırının konfigürasyonda olduğundan emin olun. Log’larda REFUSED yanıtları görüyorsanız bu normaldir.
systemd-resolved çakışması: Ubuntu ve modern Debian sistemlerinde systemd-resolved port 53’ü tutmuş olabilir:
# systemd-resolved'ı devre dışı bırak
systemctl disable systemd-resolved
systemctl stop systemd-resolved
# /etc/resolv.conf'u güncelle
echo "nameserver 127.0.0.1" > /etc/resolv.conf
Sonuç
BIND’dan Unbound’a geçiş ilk bakışta karmaşık görünse de aşamalı ve planlı yapıldığında oldukça sorunsuz ilerliyor. Deneyimlerime göre çoğu recursive-only DNS ortamında Unbound hem daha az kaynak tüketiyor hem de yönetimi kolaylaştırıyor.
Geçişin başarılı sayılması için şunlara dikkat edin:
- Mevcut BIND yapılandırmasını tam olarak belgelenmeden işe başlamayın
- Önce test ortamında çalıştırın, DNSSEC doğrulamasını mutlaka test edin
- Aşamalı yük aktarımı yapın, BIND’ı birkaç gün standby’da tutun
- İzleme scriptlerini kurmadan canlıya almayın
- Authoritative DNS ihtiyacınız varsa Unbound’u NSD veya PowerDNS ile birleştirin
Unbound’un en güçlü yanı, kurmakla uğraşmak yerine düşünmeye zaman bırakması. Yapılandırma okunabilir, hata mesajları anlaşılır ve topluluk dokümantasyonu güçlü. Bu geçişi yapan çoğu sysadmin geri dönmek istemiyor; ben de onlardan biriyim.
