PowerDNS Recursor ile Özyinelemeli DNS Sunucu Kurulumu ve Yönetimi

DNS altyapısı kurulurken en sık atlanan adımlardan biri özyinelemeli (recursive) DNS’in doğru yapılandırılmasıdır. Bir authoritative DNS sunucusu sadece kendi zone’larını yanıtlar, ama recursive bir sunucu istemciler adına tüm DNS ağacını dolaşarak cevabı bulur. İşte bu noktada PowerDNS Recursor devreye giriyor. Hem performansı hem de yapılandırma esnekliği açısından BIND veya Unbound’a güçlü bir alternatif olan Recursor, özellikle kurumsal ortamlarda ve ISP altyapılarında tercih edilen bir çözüm haline geldi.

PowerDNS Recursor Nedir ve Neden Kullanmalısınız?

PowerDNS ekosistemi iki ayrı bileşenden oluşur: pdns (authoritative sunucu) ve pdns-recursor (özyinelemeli sunucu). Bu ikisini birbirine karıştırmak çok yaygın bir hata. Recursor, istemcilerden gelen DNS sorgularını alır, kök sunuculardan başlayarak yanıtı bulur, önbelleğe alır ve istemciye döndürür.

Neden PowerDNS Recursor tercih edersiniz?

  • Yüksek performans: Çok çekirdekli sistemlerde thread başına işlem yapısıyla saniyede milyonlarca sorgu işleyebilir
  • Lua scripting: İstek ve yanıtları gerçek zamanlı olarak manipüle edebilirsiniz
  • Split-horizon DNS: Aynı alan adına farklı ağlardan farklı yanıtlar döndürebilirsiniz
  • DNS filtering: Malware domain’lerini, reklam sunucularını kolayca engelleyebilirsiniz
  • Geniş metrik desteği: Prometheus, Graphite gibi sistemlerle kolayca entegre olur
  • RPZ (Response Policy Zones): Kurumsal güvenlik politikalarını DNS katmanında uygulayabilirsiniz

Kurulum

Ubuntu/Debian tabanlı sistemlerde kurulum son derece basit:

# APT repository ekleyelim
curl -o /etc/apt/trusted.gpg.d/pdns.asc https://repo.powerdns.com/FD380FBB-pub.asc

cat > /etc/apt/sources.list.d/pdns.list << EOF
deb [arch=amd64] http://repo.powerdns.com/ubuntu focal-rec-49 main
EOF

cat > /etc/apt/preferences.d/pdns << EOF
Package: pdns-*
Pin: origin repo.powerdns.com
Pin-Priority: 600
EOF

apt update && apt install -y pdns-recursor

CentOS/RHEL sistemler için:

# PowerDNS repo dosyasını oluştur
cat > /etc/yum.repos.d/powerdns.repo << EOF
[pdns]
name=PowerDNS Repository
baseurl=http://repo.powerdns.com/centos/$basearch/$releasever/rec-49
enabled=1
gpgcheck=1
gpgkey=https://repo.powerdns.com/FD380FBB-pub.asc
EOF

dnf install -y pdns-recursor
systemctl enable --now pdns-recursor

Temel Yapılandırma

Ana yapılandırma dosyası /etc/powerdns/recursor.conf veya /etc/pdns-recursor/recursor.conf konumunda bulunur. Dağıtıma göre değişebilir, systemctl cat pdns-recursor komutuyla servis tanımına bakıp dosya konumunu teyit edin.

Temel bir kurumsal yapılandırma şöyle görünür:

# /etc/pdns-recursor/recursor.conf

# Hangi adreslerde dinleyeceğimiz
local-address=0.0.0.0
local-port=53

# Kaç thread çalıştıralım (CPU çekirdek sayısıyla eşleştirin)
threads=4

# Hangi ağlardan sorgu kabul edeceğiz
allow-from=127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16

# Önbellek boyutu (kayıt sayısı)
max-cache-entries=1000000

# Negatif önbellek TTL (saniye)
max-negative-ttl=300

# Minimum TTL (çok kısa TTL'leri engeller)
min-ttl=0

# Servfail önbelleği
max-packetcache-entries=500000

# Loglama
loglevel=4
quiet=no
log-common-errors=yes

# İstatistik soketi
socket-dir=/var/run/pdns-recursor

# DNS-over-TCP için
tcp-timeout=2

# EDNS buffer size
edns-outgoing-bufsize=1232

Yapılandırmayı test edip servisi yeniden başlatın:

# Syntax kontrolü
pdns_recursor --config-check

# Servisi yeniden başlat
systemctl restart pdns-recursor

# Durumu kontrol et
systemctl status pdns-recursor

# Test sorgusu at
dig @127.0.0.1 google.com A

Forward Zones: Dahili DNS Entegrasyonu

Kurumsal ortamlarda en sık ihtiyaç duyulan senaryo şu: İnternet domainleri için normal recursive çözümleme yapılırken, şirket içi domainler için başka bir DNS sunucusuna yönlendirme yapılması. Örneğin corp.sirket.local sorguları Active Directory DNS sunucusuna gönderilmeli.

recursor.conf içinde forward zone tanımı:

# Tek bir forward zone için
forward-zones=corp.sirket.local=192.168.1.10:53

# Birden fazla zone için virgülle ayırın
forward-zones=corp.sirket.local=192.168.1.10:53,dev.sirket.local=192.168.1.20:53

# Veya ayrı bir dosyaya taşıyın (daha temiz yönetim)
forward-zones-file=/etc/pdns-recursor/forward-zones.conf

/etc/pdns-recursor/forward-zones.conf dosyasının içeriği:

# Syntax: zone=sunucu_ip:port
# Nokta ile başlayan zone tanımları "recursive" forward anlamına gelir
# Yani hedef sunucu da recursive çözümleme yapar

corp.sirket.local=192.168.1.10:53
dev.sirket.local=192.168.1.20:53
10.in-addr.arpa=192.168.1.10:53

# Yükleme dengeleme için birden fazla sunucu
# Her satırda aynı zone'u farklı sunucuyla tanımlayabilirsiniz
staging.sirket.local=192.168.2.10:53
staging.sirket.local=192.168.2.11:53

Önemli not: forward-zones ile forward-zones-recurse arasındaki farka dikkat edin. forward-zones kullandığınızda hedef sunucunun authoritative olduğu varsayılır (RD biti set edilmez). forward-zones-recurse kullandığınızda ise hedef sunucuya recursive sorgu gönderilir. Active Directory veya başka bir recursive sunucuya yönlendiriyorsanız forward-zones-recurse kullanın.

Lua Scripting ile DNS Manipülasyonu

PowerDNS Recursor’un en güçlü özelliklerinden biri Lua scripting desteğidir. Gerçek zamanlı olarak DNS sorgularına müdahale edebilir, kural tabanlı yönlendirmeler yapabilir, hatta basit bir DNS firewall kurabilirsiniz.

recursor.conf içinde Lua scriptini etkinleştirin:

lua-dns-script=/etc/pdns-recursor/dns-policy.lua

Örnek bir Lua scripti:

-- /etc/pdns-recursor/dns-policy.lua

-- Engellenmesi gereken domainler listesi
local blocked_domains = {
    ["malware.example.com"] = true,
    ["phishing.example.net"] = true,
    ["ads.doubleclick.net"] = true,
}

-- Yönlendirme tablosu: belirli domainleri farklı IP'ye çevir
local redirects = {
    ["internal.corp.local"] = "10.0.1.50",
    ["api.corp.local"] = "10.0.1.51",
}

function preresolve(dq)
    local qname = dq.qname:toString()
    
    -- Engelli domain kontrolü
    if blocked_domains[qname] then
        dq.rcode = pdns.NXDOMAIN
        dq.appliedPolicy.policyKind = pdns.policykinds.Drop
        return true
    end
    
    -- Yönlendirme kontrolü
    if redirects[qname] and dq.qtype == pdns.A then
        dq:addAnswer(pdns.A, redirects[qname], 300)
        return true
    end
    
    return false
end

function postresolve(dq)
    -- NXDOMAIN yanıtlarını logla
    if dq.rcode == pdns.NXDOMAIN then
        pdnslog("NXDOMAIN: " .. dq.qname:toString() .. " from " .. dq.remoteaddr:toString())
    end
    
    return false
end

pdnslog("DNS policy script yuklendi")

Bu script ile:

  • Belirli domainlere gelen sorgular anında NXDOMAIN döndürür
  • Bazı dahili domainler doğrudan belirtilen IP’ye yönlendirilir
  • NXDOMAIN yanıtları loglanır

Scripti güncelledikten sonra servisi yeniden başlatmak yerine sadece scripti yeniden yükleyebilirsiniz:

rec_control reload-lua-script /etc/pdns-recursor/dns-policy.lua

Response Policy Zones (RPZ) ile Kurumsal DNS Güvenliği

RPZ, DNS katmanında güvenlik politikaları uygulamak için geliştirilmiş bir standarttır. Malware domainleri, botnet C&C sunucuları gibi zararlı adreslerin listesini bir zone olarak alıp tüm sorgulara uygulayabilirsiniz. Bu listeler genellikle threat intelligence firmalarından abonelik şeklinde alınır ama ücretsiz alternatifleri de mevcuttur.

recursor.conf içinde RPZ yapılandırması:

# Yerel RPZ zone dosyası
rpzFile(/etc/pdns-recursor/rpz-blocklist.zone, policy=NXDOMAIN)

# Veya uzak bir zone transferiyle
# lua-dns-script ile birlikte kullanılabilir

Basit bir RPZ zone dosyası:

# /etc/pdns-recursor/rpz-blocklist.zone
$TTL 300
@ IN SOA localhost. admin.localhost. 2024010101 3600 600 86400 300
  IN NS localhost.

; Engelli domainler - CNAME . ile NXDOMAIN döndürülür
malware-site.example.com   IN CNAME .
phishing.badsite.net       IN CNAME .
*.malware-cdn.org          IN CNAME .

; Tüm istekleri belirli bir IP'ye yönlendir (walled garden)
adult-content.example.com  IN CNAME rpz-passthru.

Metrikler ve İzleme

Üretim ortamında DNS performansını izlemek kritik önem taşır. PowerDNS Recursor, rec_control aracıyla zengin metrikler sunar:

# Genel istatistikler
rec_control get-all

# Önbellek doluluk oranı
rec_control get cache-hits
rec_control get cache-misses

# Şu an devam eden sorgular
rec_control get concurrent-queries

# Ortalama sorgu süresi (microsecond)
rec_control get questions

# Önbelleği temizle (dikkatli kullanın, tüm önbellek silinir)
rec_control wipe-cache

# Sadece belirli bir domain'i önbellekten sil
rec_control wipe-cache google.com

# Şu an önbellekte olan kayıt sayısı
rec_control get cache-entries

# Servis istatistiklerini sıfırla
rec_control reset-network-statistics

Prometheus ile entegrasyon için prometheus-pdns-exporter paketini kullanabilirsiniz ya da PowerDNS’in kendi web API’sini aktif edebilirsiniz:

# recursor.conf içine ekleyin
webserver=yes
webserver-address=127.0.0.1
webserver-port=8082
webserver-password=gizli-sifre
api-key=api-anahtariniz

Ardından metriklere HTTP üzerinden ulaşabilirsiniz:

curl -s http://127.0.0.1:8082/api/v1/servers/localhost/statistics 
  -H "X-API-Key: api-anahtariniz" | python3 -m json.tool | head -50

Yüksek Erişilebilirlik ve Performans Optimizasyonu

Kurumsal ortamlarda tek bir DNS sunucusu yeterli değildir. İki veya daha fazla Recursor örneği çalıştırıp önlerinde basit bir load balancer (HAProxy, keepalived) kurabilirsiniz.

Performans için dikkat edilmesi gereken recursor.conf parametreleri:

  • threads: CPU çekirdek sayısına eşitleyin, ama hyperthreading varsa fiziksel çekirdek sayısını kullanın
  • max-cache-entries: RAM’in yaklaşık %25’ini bu önbelleğe ayırabilirsiniz. 1 milyon kayıt yaklaşık 200MB RAM kullanır
  • pdns-distributes-queries: yes yaparsanız tek bir thread sorguları dağıtır, yüksek trafikte no daha iyidir
  • reuseport: yes yapın, işletim sistemi kernel seviyesinde yük dengelemesi yapar
  • max-tcp-clients: Yüksek trafikli ortamlarda artırın, varsayılan 128
  • network-timeout: Upstream sunuculara ne kadar bekleyeceğinizi belirler, varsayılan 1500ms
# Performans odaklı ek ayarlar
threads=8
pdns-distributes-queries=no
reuseport=yes
max-tcp-clients=512
network-timeout=1500
max-cache-entries=2000000
max-packetcache-entries=1000000

# Outgoing query için kaynak port randomization
socket-dir=/var/run/pdns-recursor

DNS sunucunuzu stres testine tabi tutmak için dnsperf aracını kullanabilirsiniz:

# dnsperf kurulumu
apt install -y dnsperf

# Sorgu listesi oluştur
cat > /tmp/dns-queries.txt << EOF
google.com A
github.com A
cloudflare.com AAAA
amazon.com MX
microsoft.com TXT
EOF

# Stres testi: 10 saniye boyunca saniyede 10000 sorgu
dnsperf -s 127.0.0.1 -d /tmp/dns-queries.txt -t 10 -Q 10000

Gerçek Dünya Senaryosu: Ofis Ağında Merkezi DNS Filtreleme

Diyelim ki 200 kişilik bir şirkette çalışıyorsunuz. Şirket politikası olarak sosyal medya sitelerine çalışma saatlerinde erişimi kısıtlamak, zararlı siteleri engellemek ve AD entegrasyonunu sağlamak istiyorsunuz.

İşte bu senaryonun tam yapılandırması:

# /etc/pdns-recursor/recursor.conf - Ofis ortamı için tam yapılandırma

local-address=10.0.0.2
local-port=53
allow-from=10.0.0.0/8, 172.16.0.0/12

# AD entegrasyonu
forward-zones-file=/etc/pdns-recursor/forward-zones.conf
forward-zones-recurse=sirket.local=10.0.0.10:53

# Güvenlik ve filtreleme
lua-dns-script=/etc/pdns-recursor/office-policy.lua

# Performans
threads=4
max-cache-entries=500000
reuseport=yes

# Loglama ve API
loglevel=4
webserver=yes
webserver-address=127.0.0.1
webserver-port=8082
api-key=ofis-dns-api-2024

Lua policy scripti:

-- /etc/pdns-recursor/office-policy.lua

-- Mesai saatleri dışında (18:00-09:00) sosyal medya serbest
-- Mesai içinde engelli
local social_media = {
    ["facebook.com"] = true,
    ["www.facebook.com"] = true,
    ["instagram.com"] = true,
    ["www.instagram.com"] = true,
    ["twitter.com"] = true,
    ["x.com"] = true,
    ["tiktok.com"] = true,
    ["www.tiktok.com"] = true,
}

-- Her zaman engelli siteler
local always_blocked = {
    ["gambling-site.com"] = true,
    ["adult-content.net"] = true,
}

function preresolve(dq)
    local qname = dq.qname:toString()
    
    -- Her zaman engelli
    if always_blocked[qname] then
        dq.rcode = pdns.NXDOMAIN
        return true
    end
    
    -- Mesai saati kontrolü (09:00 - 18:00, Pazartesi-Cuma)
    local hour = os.date("*t").hour
    local wday = os.date("*t").wday -- 1=Pazar, 7=Cumartesi
    
    if wday >= 2 and wday <= 6 and hour >= 9 and hour < 18 then
        if social_media[qname] then
            -- Mesai saatinde sosyal medya engeli
            dq.rcode = pdns.NXDOMAIN
            pdnslog("Engellendi (mesai): " .. qname .. " - " .. dq.remoteaddr:toString())
            return true
        end
    end
    
    return false
end

Bu yapılandırmayla:

  • Mesai saatlerinde sosyal medya erişimi engellenir
  • Her zaman zararlı siteler bloklanır
  • AD domain sorguları şirket içi DNS’e yönlendirilir
  • Tüm engelleme işlemleri loglanır

Sorun Giderme

Karşılaşılan yaygın sorunlar ve çözümleri:

# Servis başlamıyorsa detaylı log
journalctl -u pdns-recursor -f

# Port çakışması kontrolü (başka bir DNS servisi çalışıyor mu?)
ss -ulnp | grep :53
# systemd-resolved çakışıyor olabilir
systemctl disable --now systemd-resolved

# Sorgu takibi - hangi upstream sunucuya gidiyor?
rec_control trace-regex ".*google.*"
# Birkaç sorgu attıktan sonra trace'i kapat
rec_control trace-regex ""

# Önbellek içeriğine bakma
rec_control dump-cache /tmp/cache-dump.txt
cat /tmp/cache-dump.txt | grep "google.com"

# DNSSEC doğrulama sorunu varsa
# recursor.conf içine:
# dnssec=off
# veya belirli bir domain için:
dnssec-disabled-algorithms=5,7

systemd-resolved çakışması Ubuntu sistemlerde çok sık yaşanır. Eğer 53 portunu başka bir servis kullanıyorsa recursor başlamaz. systemd-resolved servisini devre dışı bırakıp /etc/resolv.conf dosyasını elle düzenlemeniz gerekir.

Sonuç

PowerDNS Recursor, özellikle kurumsal ortamlar için son derece güçlü ve esnek bir özyinelemeli DNS çözümüdür. Temel kullanımı nispeten kolay olsa da gerçek gücünü Lua scripting, RPZ desteği ve zengin API’si ile ortaya koyar.

Bir sysadmin olarak benim pratiğimde en değerli özellikler şunlar oldu: forward zones ile AD entegrasyonu kurmak artık saatlerce uğraşmayı gerektirmiyor, Lua scriptleriyle DNS katmanında güvenlik politikaları uygulamak NGFW lisansı almaktan çok daha ucuz bir çözüm sunuyor ve rec_control aracıyla anlık sorun giderme hayatı ciddi kolaylaştırıyor.

Üretim ortamında mutlaka en az iki Recursor örneği çalıştırın, metriklerinizi izleme sisteminize bağlayın ve Lua scriptlerinizi versiyon kontrolüne alın. DNS altyapısı çöktüğünde her şey çöker, bu yüzden bu servise gereken önemi göstermeyi ihmal etmeyin.

Yorum yapın