Unbound ile Raspberry Pi’de Yerel DNS Sunucusu Kurulumu
Evde bir Raspberry Pi’niz varsa ve her cihazınızın DNS sorgularının nereye gittiğini merak ediyorsanız, bu yazı tam size göre. Pi-hole gibi reklam engelleme odaklı çözümler yerine, daha temiz ve kontrol edilebilir bir DNS altyapısı kurmak isteyenler için Unbound, gerçekten güzel bir seçenek. Ben bu kurulumu hem ev ağımda hem de küçük ofis ortamlarında birkaç kez uyguladım; her seferinde öğrendiğim bir şeyler oldu.
Neden Unbound?
Çoğu ev ağında modem, DNS çözümleme işini doğrudan Google’ın 8.8.8.8 veya Cloudflare’ın 1.1.1.1 adreslerine yönlendirir. Bu adresler hızlıdır ama her DNS sorgunuz bu şirketlerin sunucularına ulaşır ve teorik olarak hangi sitelere baktığınız kayıt altına alınabilir.
Unbound, recursive DNS resolver olarak çalışır. Yani bir alan adını çözmek için sırasıyla root sunuculara, TLD sunucularına ve yetkili ad sunucularına gider; araya başka bir resolver koymaz. Bu sayede:
- DNS sorgularınız üçüncü taraf resolver’lardan geçmez
- Yanıtlar DNSSEC ile doğrulanabilir
- Yerel cache sayesinde tekrarlayan sorgular çok hızlı yanıt alır
- Yerel alan adları için özel zone tanımlamaları yapabilirsiniz
Pi-hole ile entegre çalışması da mümkün, ancak bu yazıda saf Unbound kurulumuna odaklanacağız.
Donanım ve Sistem Gereksinimleri
Raspberry Pi 3 veya üzeri bu iş için fazlasıyla yeterli. Ben bir Pi 4 (2GB RAM) üzerinde yaklaşık 15 cihazlık bir ağda test ettim, CPU kullanımı %2’yi geçmedi. Hatta Pi Zero 2W bile küçük bir ev ağı için idare eder, ama SSD yerine SD kart kullanıyorsanız write cycle’larına dikkat edin.
İşletim sistemi olarak Raspberry Pi OS Lite (Debian tabanlı, 64-bit) kullanıyorum. Masaüstü ortamına gerek yok, sadece terminal işimizi görür.
Başlamadan önce sistemi güncel tutmak şart:
sudo apt update && sudo apt upgrade -y
sudo apt install unbound -y
Kurulum sonrasında Unbound servisinin durumunu kontrol edin:
sudo systemctl status unbound
İlk kurulumda servis başlamayabilir veya bir hata verebilir, bu normal; henüz yapılandırmayı tamamlamadık.
Root Hints Dosyasını İndirmek
Unbound, recursive çözümleme için DNS hiyerarşisinin tepesindeki root sunucularını bilmek zorunda. Bu bilgi root.hints dosyasında tutuluyor. IANA bu dosyayı düzenli günceller, bu yüzden sisteme ekleyip periyodik olarak yenilemek iyi bir alışkanlık.
sudo wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.root
sudo chown unbound:unbound /var/lib/unbound/root.hints
Bu dosyayı her altı ayda bir güncellemek yeterli. Bunu cron ile otomatize edebilirsiniz:
sudo crontab -e
Aşağıdaki satırı ekleyin:
0 3 1 */6 * wget -O /var/lib/unbound/root.hints https://www.internic.net/domain/named.root && systemctl restart unbound
Ana Yapılandırma Dosyası
Unbound’un ana yapılandırma dosyası /etc/unbound/unbound.conf içinde yer alır, ancak modüler yapı için /etc/unbound/unbound.conf.d/ dizini altında ayrı dosyalar oluşturmak çok daha temiz. Ben her zaman bu yöntemi tercih ediyorum, çünkü ileride bakım yaparken hangi ayarın nerede olduğunu bulmak çok kolaylaşıyor.
Ana yapılandırma dosyasının zaten bu dizini include ettiğini göreceksiniz:
cat /etc/unbound/unbound.conf
Şimdi kendi yapılandırma dosyamızı oluşturalım:
sudo nano /etc/unbound/unbound.conf.d/pi-dns.conf
Aşağıdaki yapılandırmayı yapıştırın:
server:
# Temel ayarlar
verbosity: 1
interface: 0.0.0.0
port: 53
do-ip4: yes
do-ip6: no
do-udp: yes
do-tcp: yes
# Root hints
root-hints: "/var/lib/unbound/root.hints"
# Hangi ağlardan sorgu kabul edileceği
access-control: 127.0.0.0/8 allow
access-control: 192.168.1.0/24 allow
access-control: 0.0.0.0/0 refuse
# Güvenlik ayarları
hide-identity: yes
hide-version: yes
harden-glue: yes
harden-dnssec-stripped: yes
use-caps-for-id: yes
harden-large-queries: yes
# DNSSEC
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Performans
cache-min-ttl: 3600
cache-max-ttl: 86400
prefetch: yes
prefetch-key: yes
num-threads: 4
msg-cache-slabs: 8
rrset-cache-slabs: 8
infra-cache-slabs: 8
key-cache-slabs: 8
rrset-cache-size: 256m
msg-cache-size: 128m
# Private adres aralıkları için sorgu engelleme
private-address: 192.168.0.0/16
private-address: 172.16.0.0/12
private-address: 10.0.0.0/8
private-address: 169.254.0.0/16
private-address: fd00::/8
private-address: fe80::/10
interface: 0.0.0.0 ile tüm arayüzlerden dinliyoruz. Sadece belirli bir arayüzden dinlemek isterseniz, Pi’nin yerel IP’sini yazın, mesela interface: 192.168.1.100.
num-threads: 4 değerini Pi 4’ün çekirdek sayısına göre ayarladım. Pi 3 için 4, Pi Zero 2W için 4 (W işlemcisinin çekirdek sayısı kadar) veya 2 yapabilirsiniz.
access-control bloğunda kendi ağ aralığınızı yazmanız kritik. 192.168.1.0/24 yerine kendi ağ adresinizi koyun.
DNSSEC Güven Çıpasını Oluşturmak
DNSSEC doğrulaması için bir trust anchor dosyası gerekiyor. Unbound bunu kendi başına oluşturabilir:
sudo -u unbound unbound-anchor -a /var/lib/unbound/root.key
Bu komut çalışmazsa ya da hata verirse şunu deneyin:
sudo unbound-anchor -a /var/lib/unbound/root.key
sudo chown unbound:unbound /var/lib/unbound/root.key
Yapılandırmayı Test Etmek ve Servisi Başlatmak
Servisi başlatmadan önce yapılandırmada sözdizimi hatası olup olmadığını kontrol edin. Bu adımı atlamayın, özellikle ilk kurulumlarda küçük bir yazım hatası servisi ayağa kaldırmaz ve neden çalışmadığını anlamak zaman alır.
sudo unbound-checkconf
Çıktı unbound-checkconf: no errors in /etc/unbound/unbound.conf şeklinde olmalı. Hata yoksa servisi başlatın:
sudo systemctl enable unbound
sudo systemctl restart unbound
sudo systemctl status unbound
Şimdi yerel olarak test edelim:
dig @127.0.0.1 google.com
dig @127.0.0.1 cloudflare.com AAAA
ANSWER SECTION kısmında IP adresleri geliyorsa her şey yolunda demektir. DNSSEC doğrulamasını test etmek için:
dig @127.0.0.1 dnssec-failed.org
Bu domain kasıtlı olarak hatalı DNSSEC imzasına sahip. Eğer Unbound düzgün çalışıyorsa SERVFAIL hatası alırsınız, bu aslında istenen davranış.
Yerel Alan Adı Tanımlamaları
Bu kısım benim en çok kullandığım özellik. Ev ağındaki cihazlara IP yerine isimle erişmek, özellikle birden fazla servis çalıştırıyorsanız hayat kurtarıcı.
Yerel zone tanımı için ayrı bir dosya oluşturalım:
sudo nano /etc/unbound/unbound.conf.d/local-zone.conf
server:
# Yerel zone tanımı
local-zone: "home.lan." static
# Raspberry Pi'nin kendisi
local-data: "raspi.home.lan. IN A 192.168.1.100"
local-data-ptr: "192.168.1.100 raspi.home.lan"
# NAS
local-data: "nas.home.lan. IN A 192.168.1.10"
local-data-ptr: "192.168.1.10 nas.home.lan"
# Yazıcı
local-data: "printer.home.lan. IN A 192.168.1.20"
local-data-ptr: "192.168.1.20 printer.home.lan"
# Monitoring sunucusu
local-data: "grafana.home.lan. IN A 192.168.1.100"
local-data-ptr: "192.168.1.100 grafana.home.lan"
.home.lan uzantısını ben tercih ediyorum çünkü .local mDNS ile çakışabiliyor. .internal, .lan, .home de yaygın kullanılan uzantılar.
Değişikliği uygulamak için:
sudo systemctl restart unbound
dig @127.0.0.1 nas.home.lan
Upstream Forwarder Kullanımı (İsteğe Bağlı)
Saf recursive resolver yerine belirli sorgular için upstream forwarder kullanmak isteyebilirsiniz. Örneğin bazı ISP’lerde recursive çözümleme yavaş olabiliyor, ya da DoT (DNS over TLS) ile Cloudflare veya Quad9 gibi gizlilik odaklı servislere yönlendirmek isteyebilirsiniz.
Bunun için yapılandırmaya bir forward zone ekleyin:
sudo nano /etc/unbound/unbound.conf.d/forward-zone.conf
forward-zone:
name: "."
forward-tls-upstream: yes
forward-addr: 9.9.9.9@853#dns.quad9.net
forward-addr: 149.112.112.112@853#dns.quad9.net
forward-addr: 1.1.1.1@853#cloudflare-dns.com
forward-addr: 1.0.0.1@853#cloudflare-dns.com
forward-tls-upstream: yes ile DNS over TLS aktif olur. Port 853 üzerinden şifreli sorgu gönderilir. Bu konfigürasyonu kullanırsanız auto-trust-anchor-file satırını ana konfig dosyanızdan kaldırmanız gerekebilir, çünkü DNSSEC doğrulamasını upstream’e bırakmış olursunuz.
Dikkat: Bu bölümü eklerseniz Unbound artık saf recursive resolver olarak çalışmaz, upstream’e bağımlı hale gelir. Her iki yaklaşımın da yeri var; ihtiyacınıza göre seçin.
Modem/Router Ayarları
Pi’yi DNS sunucusu olarak tüm ağa tanıtmanın en pratik yolu, modemin DHCP ayarlarından DNS adresini değiştirmek. Bu sayede ağa bağlanan her cihaz otomatik olarak Pi’nin IP’sini DNS sunucusu olarak alır.
Modem arayüzünüze girin (genellikle 192.168.1.1), DHCP ayarları altında Primary DNS alanını Pi’nin statik IP’si ile değiştirin. Pi’nin statik IP’si olması kritik, DHCP’den dinamik IP alıyorsa yeniden başlatmada IP değişebilir.
Pi’nin statik IP’sini /etc/dhcpcd.conf dosyasından ayarlayın:
sudo nano /etc/dhcpcd.conf
Dosyanın sonuna ekleyin:
interface eth0
static ip_address=192.168.1.100/24
static routers=192.168.1.1
static domain_name_servers=127.0.0.1
static domain_name_servers=127.0.0.1 satırına dikkat edin. Pi kendi DNS sunucusunu kullanacak, bu döngüsel gibi görünse de Unbound’un çalıştığı durumda sorunsuz çalışır.
Unbound İstatistikleri ve İzleme
Unbound, kendi istatistik arayüzüne sahip. Bunu aktif etmek için yapılandırmaya ekleyin:
sudo nano /etc/unbound/unbound.conf.d/pi-dns.conf
server: bloğuna şunu ekleyin:
statistics-interval: 0
extended-statistics: yes
statistics-cumulative: yes
Sonuna da remote control bloğunu ekleyin:
remote-control:
control-enable: yes
control-interface: 127.0.0.1
control-port: 8953
Ardından kontrol arayüzü için anahtar oluşturun:
sudo unbound-control-setup
sudo systemctl restart unbound
İstatistiklere bakmak için:
sudo unbound-control stats_noreset
Bu çıktı size toplam sorgu sayısı, cache hit oranı, DNSSEC doğrulama sonuçları gibi bilgileri verir. Cache hit oranınız yüksekse (mesela %60 üzeri) Unbound güzel çalışıyor demektir.
Güvenlik Duvarı Ayarları
Pi üzerinde ufw kullanıyorsanız DNS portuna erişim izni verin:
sudo ufw allow from 192.168.1.0/24 to any port 53 proto udp
sudo ufw allow from 192.168.1.0/24 to any port 53 proto tcp
sudo ufw reload
Dışarıdan gelen DNS sorgularına izin vermeyin, Unbound’u açık resolver haline getirmek DDoS amplification saldırılarında istismar edilebilir. Zaten yapılandırma dosyamızda access-control: 0.0.0.0/0 refuse ile bunu engellemiştik, ama güvenlik duvarı katmanı ekstra koruma sağlar.
Sık Karşılaşılan Sorunlar
Servis başlamıyor: Büyük ihtimalle port 53 başka bir servis tarafından kullanılıyor. Raspberry Pi OS’de systemd-resolved çalışıyor olabilir.
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved
sudo systemctl restart unbound
Sorgular zaman aşımına uğruyor: Root sunucularına erişimde sorun olabilir. Forward zone tanımladıysanız upstream sunucuya erişimi kontrol edin. Firewall üzerinde 853 portuna izin verildiğinden emin olun.
Yerel alan adları çözümlenmiyor: local-zone tanımında nokta kontrolü önemli. home.lan. ifadesindeki sondaki nokta unutulursa çalışmaz.
Cache çok büyük büyüdü: Pi’de RAM kısıtlıysa rrset-cache-size ve msg-cache-size değerlerini düşürün. Pi Zero için 64m ve 32m ile başlamak daha mantıklı.
Logları Takip Etmek
Unbound logları syslog’a gider. Gerçek zamanlı izlemek için:
sudo journalctl -u unbound -f
Belirli bir domain için sorgu gelip gelmediğini görmek isterseniz, yapılandırmada verbosity: 2 yapın ve log’ları inceleyin. Üretimde verbosity’i 1’de bırakmak daha iyi, 2 çok fazla log üretir.
Sonuç
Raspberry Pi üzerine kurulan Unbound, ev ve küçük ofis ağları için gerçekten sağlam bir DNS altyapısı sağlıyor. Birkaç haftalık çalışmadan sonra cache hit oranının yükseldiğini ve genel tarama deneyiminin iyileştiğini fark edeceksiniz, özellikle tekrar ziyaret ettiğiniz sitelerde fark belirgin.
Bu kurulumun üzerine inşa edebileceğiniz birçok şey var: Pi-hole entegrasyonu ile reklam engelleme, Prometheus exporter ile Grafana dashboard, ya da birden fazla Pi ile DNS failover kurulumu. Ama önce temeli sağlam atmak gerekiyor, bu yüzden yukarıdaki adımları uygulayıp bir süre izleyin.
Sorgu istatistiklerinizi periyodik olarak kontrol edin, root.hints dosyasını güncel tutun ve Pi’nin statik IP’sinin değişmediğinden emin olun. Bu üç temel bakımı yaparsanız sistem yıllarca sorunsuz çalışır.
