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
NXDOMAINdö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:
yesyaparsanız tek bir thread sorguları dağıtır, yüksek trafiktenodaha iyidir - reuseport:
yesyapı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.