Bir DNS sunucusu kurmak kulağa karmaşık gelebilir, ama aslında BIND ile bu iş oldukça sistematik bir şekilde ilerliyor. Yıllarca “neden kendi DNS sunucumu çalıştırayım ki?” diye düşündüm, ta ki production ortamında bir üçüncü taraf DNS sağlayıcısının çökmesiyle birlikte tüm servislerimin erişilemez hale geldiği güne kadar. O günden bu yana kendi BIND kurulumumu çalıştırıyorum ve bu konuda edindiğim deneyimi sizinle paylaşmak istiyorum.
BIND Nedir ve Neden Kullanmalıyız?
BIND (Berkeley Internet Name Domain), dünyanın en yaygın kullanılan açık kaynaklı DNS sunucu yazılımıdır. İnternetin omurgasını oluşturan DNS altyapısının büyük bir kısmı hâlâ BIND üzerine kurulu. ISC (Internet Systems Consortium) tarafından geliştirilen bu yazılım, hem küçük ofis ağlarında hem de büyük ölçekli kurumsal altyapılarda güvenle kullanılabiliyor.
Kendi DNS sunucunuzu çalıştırmanın size sağladığı avantajlar şunlar:
- Tam kontrol: Hangi kayıtların ne zaman değişeceğine siz karar verirsiniz, propagasyon süresi beklemenize gerek kalmaz
- Gizlilik: DNS sorgularınız üçüncü tarafların sunucularından geçmez
- Özelleştirme: Split-horizon DNS, iç ağ için farklı yanıtlar gibi gelişmiş senaryoları uygulayabilirsiniz
- Maliyet: Yüksek sorgu hacminde ücretli DNS servislerine kıyasla ciddi tasarruf sağlar
- Öğrenme fırsatı: DNS’in gerçekte nasıl çalıştığını en iyi şekilde kendi sunucunuzu kurarak öğrenirsiniz
Kurulum Öncesi Hazırlık
Başlamadan önce birkaç şeyi netleştirmemiz gerekiyor. Bu yazıda Ubuntu 22.04 LTS üzerinde çalışacağız, ancak CentOS/RHEL kullanıcıları için paket adlarını ve servis yönetimini ayrıca belirteceğim.
Sunucunuzun hostname ve IP yapılandırması doğru olmalı. Önce bunları kontrol edelim:
# Hostname kontrolü
hostname -f
# IP adresini kontrol et
ip addr show
# /etc/hosts dosyasını düzenle
sudo nano /etc/hosts
# Şöyle bir satır ekle:
# 192.168.1.10 ns1.example.com ns1
Firewall tarafında UDP ve TCP 53 numaralı portları açmanız gerekiyor. DNS öncelikli olarak UDP kullanır ama büyük yanıtlar için TCP’ye düşer:
# UFW ile port açma (Ubuntu)
sudo ufw allow 53/tcp
sudo ufw allow 53/udp
sudo ufw reload
# firewalld ile (CentOS/RHEL)
sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --reload
BIND Kurulumu
Ubuntu/Debian sistemlerde kurulum oldukça basit:
# Paket listesini güncelle
sudo apt update
# BIND9 ve yardımcı araçları kur
sudo apt install -y bind9 bind9utils bind9-doc dnsutils
# Servis durumunu kontrol et
sudo systemctl status bind9
# Sistem başlangıcında otomatik başlatmayı etkinleştir
sudo systemctl enable bind9
CentOS/RHEL sistemlerde ise:
# BIND kurulumu
sudo dnf install -y bind bind-utils
# Servis adı farklı: named
sudo systemctl enable named
sudo systemctl start named
sudo systemctl status named
Kurulum tamamlandıktan sonra temel dizin yapısını inceleyelim. Yapılandırma dosyaları genellikle /etc/bind/ altında bulunur:
- /etc/bind/named.conf: Ana yapılandırma dosyası
- /etc/bind/named.conf.options: Genel seçenekler
- /etc/bind/named.conf.local: Yerel zone tanımları
- /etc/bind/named.conf.default-zones: Varsayılan zone’lar
- /var/cache/bind/: Zone veri dosyaları ve cache
- /var/log/named/: Log dosyaları
Temel Yapılandırma: named.conf.options
İlk olarak genel seçenekleri ayarlayalım. Bu dosya BIND’ın davranışını genel olarak belirler:
sudo nano /etc/bind/named.conf.options
Dosyanın içeriğini şu şekilde düzenleyin:
options {
directory "/var/cache/bind";
# Hangi IP'lerden sorgu kabul edileceği
# Sadece localhost ve iç ağ için
listen-on { 127.0.0.1; 192.168.1.10; };
listen-on-v6 { ::1; };
# Recursive sorgu yapabilecek ağlar
allow-recursion {
127.0.0.1;
192.168.1.0/24;
};
# Zone transferi için izin verilen sunucular
allow-transfer { none; };
# Forwarder DNS sunucuları (bilinmeyen sorgular için)
forwarders {
8.8.8.8;
8.8.4.4;
1.1.1.1;
};
# Forward only modu - kendi recursive lookup yapmaz
# forward only;
# DNSSEC doğrulama
dnssec-validation auto;
# Version bilgisini gizle (güvenlik)
version "not available";
# Query logging (başlangıçta açık bırak, sonra kapat)
querylog yes;
};
Bu yapılandırmada dikkat etmeniz gereken birkaç nokta var. allow-recursion direktifi çok önemli: Eğer bunu yanlış yapılandırırsanız, sunucunuz açık bir DNS resolver haline gelir ve DDoS saldırılarında kullanılır. Sadece güvendiğiniz ağları buraya ekleyin.
forwarders bölümü, BIND’ın kendi zone’larında bulamadığı sorguları nereye yönlendireceğini belirtir. Google ve Cloudflare DNS’ini ekledim ama siz iç ağınızdaki başka bir DNS sunucusunu da kullanabilirsiniz.
İlk Zone Oluşturma: Forward Zone
Şimdi gerçek bir senaryo üzerinden ilerleyelim. Diyelim ki example.local adında bir iç ağ domain’i yönetiyoruz. Önce zone tanımını named.conf.local dosyasına ekleyelim:
sudo nano /etc/bind/named.conf.local
# Forward zone tanımı
zone "example.local" {
type master;
file "/etc/bind/zones/db.example.local";
allow-update { none; };
};
# Reverse zone tanımı (192.168.1.0/24 için)
zone "1.168.192.in-addr.arpa" {
type master;
file "/etc/bind/zones/db.192.168.1";
allow-update { none; };
};
Zone dosyalarını tutacağımız dizini oluşturalım:
sudo mkdir -p /etc/bind/zones
sudo chown bind:bind /etc/bind/zones
Forward Zone Dosyası Oluşturma
Forward zone dosyası, domain adlarını IP adreslerine çevirir. Bu dosyayı oluşturalım:
sudo nano /etc/bind/zones/db.example.local
; example.local Forward Zone Dosyası
; Son güncelleme: 2024-01-15
$TTL 604800
; SOA (Start of Authority) kaydı
@ IN SOA ns1.example.local. admin.example.local. (
2024011501 ; Serial (YYYYMMDDSS formatı)
3600 ; Refresh - slave ne sıklıkta senkronize etsin
1800 ; Retry - başarısız senkronizasyon sonrası bekleme
604800 ; Expire - slave ne kadar süre geçerli saysın
86400 ) ; Negative Cache TTL
; Name Server kayıtları
@ IN NS ns1.example.local.
@ IN NS ns2.example.local.
; A kayıtları (hostname -> IP)
ns1 IN A 192.168.1.10
ns2 IN A 192.168.1.11
gateway IN A 192.168.1.1
; Sunucular
web1 IN A 192.168.1.20
web2 IN A 192.168.1.21
db1 IN A 192.168.1.30
db2 IN A 192.168.1.31
mail IN A 192.168.1.40
vpn IN A 192.168.1.50
; CNAME kayıtları (alias)
www IN CNAME web1.example.local.
ftp IN CNAME web1.example.local.
smtp IN CNAME mail.example.local.
imap IN CNAME mail.example.local.
; MX kayıtları (mail sunucuları)
@ IN MX 10 mail.example.local.
; TXT kayıtları
@ IN TXT "v=spf1 mx -all"
SOA kaydındaki Serial numarası çok önemli. Bu numarayı her zone güncellemesinde artırmanız gerekiyor, aksi takdirde slave sunucular güncellemeleri almaz. Ben genellikle YYYYMMDDSS formatını kullanıyorum: yıl, ay, gün ve o gün kaçıncı değişiklik olduğu.
Reverse Zone Dosyası Oluşturma
Reverse zone, IP adreslerini domain adlarına çevirir (PTR kayıtları). Özellikle mail sunucuları için kritik öneme sahip:
sudo nano /etc/bind/zones/db.192.168.1
; 192.168.1.0/24 Reverse Zone Dosyası
$TTL 604800
@ IN SOA ns1.example.local. admin.example.local. (
2024011501
3600
1800
604800
86400 )
; Name Server kayıtları
@ IN NS ns1.example.local.
@ IN NS ns2.example.local.
; PTR kayıtları (IP son okteti -> hostname)
10 IN PTR ns1.example.local.
11 IN PTR ns2.example.local.
20 IN PTR web1.example.local.
21 IN PTR web2.example.local.
30 IN PTR db1.example.local.
31 IN PTR db2.example.local.
40 IN PTR mail.example.local.
50 IN PTR vpn.example.local.
Yapılandırma Doğrulama ve Servisi Başlatma
Zone dosyalarını oluşturduktan sonra sözdizimi kontrolü yapmak şart. Bunu atlamayın; bir hata bütün DNS servisini çökertebilir:
# Ana yapılandırma dosyasını kontrol et
sudo named-checkconf
# Forward zone dosyasını kontrol et
sudo named-checkzone example.local /etc/bind/zones/db.example.local
# Reverse zone dosyasını kontrol et
sudo named-checkzone 1.168.192.in-addr.arpa /etc/bind/zones/db.192.168.1
# Hata yoksa servisi yeniden başlat
sudo systemctl restart bind9
# Servis durumunu kontrol et
sudo systemctl status bind9
named-checkconf hiçbir çıktı vermeden tamamlanırsa her şey yolunda demektir. named-checkzone ise başarılı olduğunda “OK” çıktısı verir.
DNS Sorgularını Test Etme
Kurulumun doğru çalıştığını test etmek için dig ve nslookup araçlarını kullanacağız:
# Forward lookup testi
dig @127.0.0.1 web1.example.local
# Kısa çıktı için
dig @127.0.0.1 web1.example.local +short
# Reverse lookup testi
dig @127.0.0.1 -x 192.168.1.20
# MX kaydı sorgulama
dig @127.0.0.1 example.local MX
# SOA kaydı sorgulama
dig @127.0.0.1 example.local SOA
# NS kayıtlarını sorgula
dig @127.0.0.1 example.local NS
# nslookup ile test
nslookup web1.example.local 127.0.0.1
nslookup 192.168.1.20 127.0.0.1
dig çıktısında dikkat etmeniz gereken yerler: ANSWER SECTION kısmında beklediğiniz kayıtlar görünmeli, status alanında NOERROR yazmalı.
Güvenlik Sertleştirmesi
Temel kurulum çalışır hale geldi, ama güvenlik tarafında yapabileceğimiz birkaç önemli iyileştirme var.
BIND kullanıcısını kısıtlayın:
# BIND'ın chroot ortamında çalışmasını sağla
# /etc/default/named dosyasını düzenle
sudo nano /etc/default/named
# Şu satırı ekle veya değiştir:
OPTIONS="-u bind -4"
# -4 sadece IPv4, IPv6 kullanmıyorsanız eklemenizi öneririm
Rate limiting yapılandırması – DNS amplification saldırılarına karşı:
sudo nano /etc/bind/named.conf.options
options bloğuna şunu ekleyin:
# Rate limiting - DDoS koruması
rate-limit {
responses-per-second 15;
window 5;
log-only no;
errors-per-second 5;
nxdomains-per-second 5;
slip 2;
};
# Recursion sadece belirli ağlardan
recursion yes;
allow-recursion {
127.0.0.1;
192.168.1.0/24;
# İzin verilen ek ağlar buraya
};
# Zone transferi varsayılan olarak kapalı
allow-transfer { none; };
# Sunucu bilgilerini gizle
version "DNS";
hostname none;
server-id none;
Log Yapılandırması
Sorun giderme ve güvenlik izleme için log yapılandırması önemli. /etc/bind/named.conf dosyasına logging bloğu ekleyelim:
sudo nano /etc/bind/named.conf
Dosyanın sonuna ekleyin:
logging {
channel default_log {
file "/var/log/named/named.log" versions 5 size 20m;
print-time yes;
print-severity yes;
print-category yes;
severity dynamic;
};
channel security_log {
file "/var/log/named/security.log" versions 5 size 20m;
print-time yes;
print-severity yes;
print-category yes;
severity info;
};
channel query_log {
file "/var/log/named/query.log" versions 10 size 50m;
print-time yes;
severity info;
};
category default { default_log; };
category security { security_log; };
category queries { query_log; };
category lame-servers { null; };
};
Log dizinini oluşturun:
sudo mkdir -p /var/log/named
sudo chown bind:bind /var/log/named
sudo chmod 755 /var/log/named
# Servisi yeniden başlat
sudo systemctl restart bind9
# Log dosyasını izle
sudo tail -f /var/log/named/named.log
Yaygın Sorunlar ve Çözümleri
Yıllar içinde en sık karşılaştığım sorunları ve çözümlerini paylaşayım.
Servis başlamıyor: İlk yapmanız gereken şey log dosyalarını ve systemd journal’ını kontrol etmek:
sudo journalctl -u bind9 -n 50
sudo cat /var/log/named/named.log
En yaygın sebep zone dosyasındaki sözdizimi hatasıdır. named-checkconf ve named-checkzone komutlarını çalıştırın.
Sorgular yanıt vermiyor: Firewall kurallarını ve BIND’ın hangi arayüzde dinlediğini kontrol edin:
# BIND'ın 53. portu dinlediğini doğrula
sudo ss -tlnup | grep named
sudo netstat -tlnup | grep named
# Firewall kurallarını listele
sudo ufw status verbose
Serial numarası güncellemesi unutuldu: Zone dosyasını değiştirip serial numarasını artırmadan servisi yeniden başlatırsanız slave sunucular güncellemeyi almaz. Bu durumda önce serial numarasını artırın, sonra servisi yeniden yükleyin:
# Servisi yeniden başlatmadan zone'u yeniden yükle
sudo rndc reload example.local
# Tüm zone'ları yeniden yükle
sudo rndc reload
# Cache'i temizle
sudo rndc flush
Zone transferi çalışmıyor (Slave sunucu için): Master sunucunun allow-transfer direktifinde slave sunucunun IP’si olmalı. Slave tarafında zone tanımı şöyle olmalı:
zone "example.local" {
type slave;
file "/var/cache/bind/db.example.local";
masters { 192.168.1.10; };
};
Bakım ve İzleme
Günlük operasyonlarda işinize yarayacak birkaç komut daha:
# BIND istatistiklerini görüntüle
sudo rndc stats
cat /var/run/named/named.stats
# Belirli bir domain için cache'i temizle
sudo rndc flushname web1.example.local
# BIND'ı durdurmadan yapılandırmayı yeniden yükle
sudo rndc reconfig
# Tüm zone'ları listele
sudo rndc zonestatus
# Sorgu istatistiklerini görüntüle
sudo rndc querylog on
Zone güncellemelerini otomatize etmek için küçük bir script yazabilirsiniz. Her zone değişikliğinde serial numarasını unutmamak için:
#!/bin/bash
# update_zone.sh - Zone dosyası güncelleme scripti
ZONE_FILE="/etc/bind/zones/db.example.local"
TODAY=$(date +%Y%m%d)
CURRENT_SERIAL=$(grep -E "^s+[0-9]{10}" $ZONE_FILE | awk '{print $1}')
CURRENT_DATE=${CURRENT_SERIAL:0:8}
if [ "$TODAY" = "$CURRENT_DATE" ]; then
SEQ=$((${CURRENT_SERIAL:8:2} + 1))
NEW_SERIAL="${TODAY}$(printf '%02d' $SEQ)"
else
NEW_SERIAL="${TODAY}01"
fi
sudo sed -i "s/$CURRENT_SERIAL/$NEW_SERIAL/" $ZONE_FILE
echo "Serial güncellendi: $CURRENT_SERIAL -> $NEW_SERIAL"
# Doğrulama ve reload
sudo named-checkzone example.local $ZONE_FILE && sudo rndc reload example.local
Sonuç
BIND kurulumu başta göz korkutucu görünebilir, ama sistematik yaklaştığınızda oldukça anlaşılır bir yapısı var. Bu yazıda ele aldığımız konuları özetleyecek olursak:
- BIND’ı Ubuntu/CentOS üzerine kurma
named.conf.optionsile genel yapılandırma- Forward ve reverse zone dosyaları oluşturma
- Güvenlik sertleştirmesi ve rate limiting
- Log yapılandırması
- Sorun giderme teknikleri
Bir sonraki adım olarak DNSSEC implementasyonunu, Dynamic DNS yapılandırmasını veya Split-horizon DNS kurulumunu incelemenizi öneririm. Özellikle split-horizon, iç ağ ve dış ağ için farklı DNS yanıtları gereken durumlarda çok işe yarıyor.
Unutmayın ki DNS altyapınız ne kadar kritik olursa olsun, yedekli bir yapı kurmak şart. En az bir slave DNS sunucusu olmadan production ortamına geçmeyin. Bir sunucu çöktüğünde tüm domain erişiminizin gitmesini istemezsiniz, bunu zor yoldan öğrenmek çok acı verici olabiliyor.