nscd ve systemd-resolved ile DNS Önbellek Temizleme
Üretim ortamında bir DNS sorunu yaşadığınızda, genellikle ilk şüphelendiğiniz yer yanlış olur. “Sunucu erişilemez” diyor ama ping atıyorsunuz, IP ile bağlanıyorsunuz, her şey yolunda görünüyor. Sonra saatlerce firewall kurallarına, network konfigürasyonuna bakıyorsunuz ve sonunda fark ediyorsunuz: sorun DNS önbelleğinde. Eski, bozuk ya da güncellenmemiş bir kayıt sisteminizin bir kısmını eski IP’ye yönlendirmeye devam ediyordu. Bu yazıda hem nscd hem de systemd-resolved üzerinde önbellek yönetimini, temizleme yöntemlerini ve gerçek dünya senaryolarında nasıl davranmanız gerektiğini ele alacağım.
DNS Önbelleği Neden Sorun Çıkarır?
DNS önbellekleme temelde iyi bir şeydir. Her sorgu için tekrar tekrar upstream DNS sunucusuna gitmek yerine yerel olarak tutulan kayıtları kullanmak hem gecikmeyi azaltır hem de DNS altyapısı üzerindeki yükü düşürür. Ama bu mekanizma bazı durumlarda başınızı ağrıtabilir.
Klasik senaryo şudur: Bir servisi yeni bir sunucuya taşıdınız, DNS kaydını güncellediniz, TTL süresi de kısa tutulmuş diyelim, ama bazı istemciler hâlâ eski IP’ye bağlanmaya çalışıyor. Ya da tam tersi: bir IP adresi değişti ama önbellekteki pozitif kayıt süresi dolmadı. Bir de negatif önbellekleme var; hiç bulunamayan bir alan adının “yok” cevabı da önbelleğe alınabiliyor ve siz DNS kaydı ekleseniz bile bir süre daha “bulunamadı” hatası almaya devam edebiliyorsunuz.
Linux sistemlerde bu önbelleklemeyi yapan birkaç farklı katman var:
- nscd (Name Service Cache Daemon): Eski okul, sysV tipi servis. Glibc ile entegre çalışır.
- systemd-resolved: Modern sistemlerde varsayılan gelen stub resolver ve önbellek mekanizması.
- dnsmasq: Hem DHCP hem DNS önbellekleme yapan, özellikle router ve NetworkManager tarafından kullanılan araç.
- Bind/Unbound: Kendi başlarına önbellekleme yapan recursive resolver’lar.
Bu yazıda ilk ikisine odaklanacağız çünkü modern bir Ubuntu, Debian, RHEL veya CentOS sistemi kurduğunuzda büyük ihtimalle bu ikisinden biriyle ya da ikisiyle birden karşılaşıyorsunuz.
Sisteminizde Neyin Çalıştığını Öğrenin
Önce bir nefes alıp sisteminizde tam olarak neyin çalıştığını anlamak gerekiyor. Yoksa yanlış servisin önbelleğini temizlemiş olursunuz ve sorun devam eder.
# Çalışan DNS ile ilgili servisleri kontrol et
systemctl status nscd 2>/dev/null
systemctl status systemd-resolved 2>/dev/null
systemctl status dnsmasq 2>/dev/null
# Hangi process 53 portunu dinliyor?
ss -tulnp | grep :53
# Ya da eski usul
netstat -tulnp | grep :53
Sistemin hangi resolver’ı kullandığını anlamak için /etc/resolv.conf dosyasına bakmak tek başına yeterli değil artık. Modern sistemlerde bu dosya çoğu zaman bir symlink.
# resolv.conf'un gerçekte ne olduğunu gör
ls -la /etc/resolv.conf
cat /etc/resolv.conf
# systemd-resolved kullanılıyorsa stub resolver adresi görürsünüz
# 127.0.0.53 bu adresi gördüyseniz systemd-resolved devrededir
Eğer nameserver 127.0.0.53 yazıyorsa systemd-resolved, nameserver 127.0.0.1 yazıyorsa muhtemelen dnsmasq ya da başka bir local resolver devrededir. Direkt bir IP adresi (8.8.8.8 gibi) yazıyorsa yerel önbellekleme muhtemelen kapalıdır.
nscd ile Çalışmak
nscd, yani Name Service Cache Daemon, Linux dünyasının biraz yaşlı ama hâlâ pek çok sistemde hayatta olan bir servisi. RHEL/CentOS ailesi, eski Debian sürümleri ve bazı kurumsal ortamlarda nscd’yi çalışır halde bulabilirsiniz. Özellikle NIS, LDAP entegrasyonu olan ortamlarda nscd tercih ediliyor çünkü sadece DNS değil, passwd, group ve hosts gibi name service veritabanlarını da önbelleğe alıyor.
nscd Önbelleğini Temizleme
En basit yol tüm önbelleği temizlemek için servisi yeniden başlatmaktır:
# Servisi yeniden başlat - tüm önbellek temizlenir
sudo systemctl restart nscd
# Ya da eski init.d yöntemiyle
sudo service nscd restart
Ama bu kaba bir yöntem. Eğer sadece hosts/DNS önbelleğini temizlemek istiyorsanız, diğer önbellekleri (passwd, group gibi) dokunmadan bırakmak için nscd -i komutunu kullanabilirsiniz:
# Sadece hosts önbelleğini temizle
sudo nscd -i hosts
# passwd önbelleğini temizle (LDAP ortamlarında işe yarar)
sudo nscd -i passwd
# group önbelleğini temizle
sudo nscd -i group
# services önbelleğini temizle
sudo nscd -i services
nscd Durumunu İnceleme
Önbelleği temizlemeden önce durumu incelemek bazen sorunun kaynağını anlamanıza yardımcı olur:
# nscd istatistiklerini görüntüle
nscd --statistics
# ya da
nscd -g
Bu komut size her veritabanı için cache hit/miss oranlarını, önbellekteki kayıt sayısını ve pozitif/negatif TTL değerlerini gösterir. Eğer negatif cache hit sayısı yüksekse, bir alan adını “bulunamadı” olarak önbelleğe almış ve bu cevabı tekrar tekrar veriyordur.
nscd Konfigürasyonu
/etc/nscd.conf dosyası nscd’nin davranışını belirler. DNS sorunlarını debug ederken bu dosyayı anlamak önemli:
# nscd konfigürasyonuna bak
cat /etc/nscd.conf | grep -v "^#" | grep -v "^$"
Kritik parametreler şunlar:
- positive-time-to-live hosts: Başarılı DNS sorgularının önbellekte tutulma süresi (saniye)
- negative-time-to-live hosts: Başarısız sorguların önbellekte tutulma süresi
- enable-cache hosts: hosts önbelleğinin aktif olup olmadığı
- check-files hosts:
/etc/hostsdeğiştiğinde önbelleği otomatik temizleyip temizlemeyeceği
Sorun yaşadığınız dönemde geçici olarak debug modunu açabilirsiniz:
# nscd'yi debug modunda başlat (foreground'da çalışır)
sudo nscd -d
systemd-resolved ile Çalışmak
Modern Ubuntu (17.04+), Debian Buster ve üzeri, Fedora, RHEL 8+ gibi sistemlerde artık varsayılan DNS yöneticisi systemd-resolved. Bu araç sadece önbellekleme yapmıyor; DNSSEC doğrulama, DNS-over-TLS, VPN bağlantılarında split-DNS gibi gelişmiş özellikler de sunuyor. Ama bizim için asıl önemli olan önbellek yönetimi.
Temel Önbellek Temizleme
# systemd-resolved önbelleğini temizle
sudo resolvectl flush-caches
# Eski sistemlerde (systemd-resolve komutuyla)
sudo systemd-resolve --flush-caches
Bu kadar. Basit ve etkili. Komut çalıştıktan sonra bir sonraki DNS sorgusunda cache’e gitmek yerine direkt upstream sunucuya gidecek.
Durum ve İstatistik İnceleme
resolvectl komutu nscd’ye göre çok daha zengin bilgi sunuyor:
# Genel durum - hangi interface hangi DNS sunucusunu kullanıyor
resolvectl status
# Sadece belirli bir interface için
resolvectl status eth0
resolvectl status ens3
# Önbellek istatistikleri
resolvectl statistics
resolvectl statistics komutu size şunları gösterir:
- Current Transactions: Şu an devam eden sorgu sayısı
- Total Transactions: Toplam işlenen sorgu
- Current Cache Size: Önbellekteki kayıt sayısı
- Cache Hits: Önbellekten karşılanan sorgu sayısı
- Cache Misses: Upstream’e giden sorgu sayısı
Önbellek temizledikten sonra bu sayıların sıfırlanıp sıfırlanmadığını doğrulayabilirsiniz:
# Temizlemeden önce istatistikleri al
resolvectl statistics
# Önbelleği temizle
sudo resolvectl flush-caches
# İstatistikleri tekrar kontrol et - cache size sıfır olmalı
resolvectl statistics
DNS Sorgu Testi
Önbellek temizlendikten sonra sorgunun gerçekten çalışıp çalışmadığını test etmek için:
# resolvectl ile direkt sorgu yap
resolvectl query google.com
# Belirli bir record type için
resolvectl query -t MX gmail.com
resolvectl query -t AAAA cloudflare.com
# Belirli bir DNS sunucusuna sormak için
resolvectl query --interface=eth0 example.com
DNSSEC Sorunları
Bazen önbellek temizlemenize rağmen sorun devam eder. Bu durumlarda DNSSEC doğrulama hatası olabilir:
# DNSSEC durumunu kontrol et
resolvectl status | grep DNSSEC
# Belirli bir domain için DNSSEC durumu
resolvectl query --legend=true example.com
Eğer DNSSEC doğrulama hatası alıyorsanız ve bunun gerçek bir güvenlik sorunu değil konfigürasyon problemi olduğundan eminseniz, /etc/systemd/resolved.conf dosyasında geçici olarak DNSSEC’i devre dışı bırakabilirsiniz:
sudo nano /etc/systemd/resolved.conf
# DNSSEC=no yapın, sonra:
sudo systemctl restart systemd-resolved
Gerçek Dünya Senaryoları
Senaryo 1: Uygulama Sunucusu Migrasyon Sonrası Eski IP’yi Çözümlüyor
Diyelim ki bir veritabanı sunucusunu yeni bir IP’ye taşıdınız. DNS kaydını güncellediniz, TTL süresi de dolmuş olmalı ama uygulama sunucuları hâlâ eski IP’ye bağlanmaya çalışıyor.
# Önce sistemde ne görüldüğünü kontrol et
dig db.internal.example.com
nslookup db.internal.example.com
# Sistemin /etc/hosts dosyasında statik kayıt var mı diye bak
grep db.internal /etc/hosts
# nscd çalışıyorsa
sudo nscd -i hosts
# systemd-resolved çalışıyorsa
sudo resolvectl flush-caches
# Şimdi tekrar sorgula
dig db.internal.example.com +short
Eğer /etc/hosts dosyasında eski bir kayıt varsa, nscd check-files seçeneği aktif olsa bile önce bunu kontrol etmelisiniz. hosts dosyasındaki bir kayıt her zaman DNS’ten önce gelir.
Senaryo 2: Yeni Eklenen DNS Kaydı Görünmüyor
Bir alan adı oluşturduğunuz ve propagasyonun tamamlandığını düşündüğünüz halde bazı sunuculardan çözümleme yapılamıyor:
# Önce upstream DNS sunucularına direkt sor ve karşılaştır
# Google DNS'e sor
dig @8.8.8.8 yeni-servis.example.com
# Yerel DNS sunucusuna sor
dig @192.168.1.53 yeni-servis.example.com
# Sistemin varsayılanına sor (önbellekli sonuç gelebilir)
dig yeni-servis.example.com
# Eğer upstream'de kayıt var ama sistemde yok, önbelleği temizle
sudo resolvectl flush-caches
# veya
sudo nscd -i hosts
# Negatif önbellek kontrolü - "NXDOMAIN" önbellekte tutulmuş olabilir
resolvectl statistics | grep "Cache"
Senaryo 3: VPN Bağlantısı Sonrası DNS Sorunları
VPN bağlandıktan ya da kesildikten sonra bazı alan adları çözümlenemiyor:
# VPN interface'ini kontrol et
ip addr show
resolvectl status
# VPN bağlantısı kesildi ve eski DNS bilgileri kaldı mı?
resolvectl status | grep -A5 "Link"
# Tüm önbellekleri ve DNS durumunu sıfırla
sudo resolvectl flush-caches
sudo systemctl restart systemd-resolved
# NetworkManager kullanıyorsanız
sudo systemctl restart NetworkManager
Senaryo 4: Container Ortamında DNS Sorunları
Docker veya Kubernetes ortamında çalışan konteynerlerde DNS sorunları yaşandığında, host sistemin DNS’ini temizlemek yetmeyebilir:
# Docker'ın kendi DNS önbelleğini sıfırlamak için
# (Docker kendi embedded DNS sunucusunu kullanıyor - 127.0.0.11)
docker restart <container_name>
# Ya da tüm network stack'ini yeniden başlat
sudo systemctl restart docker
# Host sistemde systemd-resolved'u temizle
sudo resolvectl flush-caches
# Container içinde DNS'i test et
docker exec -it <container_name> nslookup google.com
docker exec -it <container_name> cat /etc/resolv.conf
Sorun Giderme İpuçları
strace ile DNS Çağrılarını İzleme
Hangi kütüphanelerin hangi DNS çağrılarını yaptığını görmek istiyorsanız:
# Bir uygulamanın DNS çağrılarını izle
strace -e trace=network -f -p <PID> 2>&1 | grep -i "connect|send|recv"
# Ya da direkt olarak nss çağrılarını izle
strace -e trace=open,openat curl https://example.com 2>&1 | grep "nss|resolv|nscd"
tcpdump ile DNS Trafiğini İzleme
# DNS sorgularını gerçek zamanlı izle
sudo tcpdump -i any -n port 53
# Belirli bir domain için
sudo tcpdump -i any -n port 53 and host 8.8.8.8
# Daha okunabilir format
sudo tcpdump -i any -n -l port 53 | grep -i "example.com"
Bu yöntemle önbellek temizleme sonrasında gerçekten upstream’e sorgu gidip gitmediğini teyit edebilirsiniz.
Otomatik Önbellek Temizleme Script’i
Üretim ortamında deployment süreçlerine entegre edebileceğiniz basit bir script:
#!/bin/bash
# dns-flush.sh - DNS onbelleklerini temizle
echo "DNS onbellekleri temizleniyor..."
# systemd-resolved kontrolu
if systemctl is-active --quiet systemd-resolved; then
resolvectl flush-caches
echo "[OK] systemd-resolved onbellegi temizlendi"
fi
# nscd kontrolu
if systemctl is-active --quiet nscd; then
nscd -i hosts
echo "[OK] nscd hosts onbellegi temizlendi"
fi
# dnsmasq kontrolu
if systemctl is-active --quiet dnsmasq; then
# dnsmasq SIGHUP sinyaliyle onbellegi temizler
systemctl kill -s SIGHUP dnsmasq
echo "[OK] dnsmasq onbellegi temizlendi"
fi
echo "Tamamlandi. DNS dogrulamasi:"
dig +short ${1:-google.com}
Bu script’i deployment pipeline’ınıza veya Ansible playbook’larınıza ekleyebilirsiniz.
nscd ve systemd-resolved Birlikte Çalışma Durumu
Bazı sistemlerde her ikisi de kurulu olabilir ve bu beklenmedik davranışlara yol açabilir. nscd, systemd-resolved’un 127.0.0.53 adresini bypass edip direkt glibc üzerinden sorgu yapabilir. Bu durumda systemd-resolved önbelleğini temizlemeniz nscd’deki önbelleği etkilemez.
# Her ikisini de kontrol et
systemctl status nscd systemd-resolved
# nscd'nin hangi nameserver'ı kullandığını gör
# nscd glibc'yi kullanır, glibc de /etc/resolv.conf'a bakar
# resolv.conf'ta ne yazıyorsa onu kullanır
cat /etc/resolv.conf
# Eğer her iki servis de çalışıyorsa sırayla temizle
sudo nscd -i hosts && sudo resolvectl flush-caches
Genel tavsiye: Modern sistemlerde nscd’yi devre dışı bırakıp sadece systemd-resolved kullanmak. Özellikle hem nscd hem de systemd-resolved çalışıyorsa, nscd’nin systemd-resolved’un önünde önbellekleme yapması istenmedik davranışlara yol açar.
Kalıcı Çözümler ve Önlemler
Önbellek sorunlarını defalarca yaşamamak için birkaç yapısal değişiklik önerebilirim:
- TTL değerlerini düşürün: Kritik servisler için DNS TTL’ini 60-300 saniye arasında tutun. Özellikle yaklaşan bir migrasyon varsa önceden düşürün.
- Negatif TTL’i azaltın: nscd.conf’ta
negative-time-to-live hostsdeğerini düşük tutun (15-30 saniye), yoksa NXDOMAIN yanıtları uzun süre önbellekte kalır. - Monitoring ekleyin: DNS çözümleme sürelerini ve başarısız sorgu oranlarını izleyin. Bir şeylerin ters gittiğini deployment’tan önce fark edebilirsiniz.
- Deployment script’lerine ekleyin: Her deployment sonrasında DNS önbelleğini temizleme adımını otomatik hale getirin.
- /etc/hosts’u dikkatli kullanın: Test amaçlı eklenen statik kayıtları temizlemeyi unutmayın. Bu kayıtlar DNS değişikliklerini override eder ve çoğu zaman sorunun asıl kaynağı bunlardır.
Sonuç
DNS önbellek sorunları, sysadmin hayatının kaçınılmaz bir parçası. Ama doğru araçları bilirseniz, bu sorunları dakikalar içinde çözebilirsiniz. Özetle hatırlamanız gerekenler:
Sisteminizde nscd mi, systemd-resolved mi çalıştığını bilin. resolvectl flush-caches modern sistemlerde ilk denemeniz gereken komut. nscd -i hosts ise nscd ortamlarında sadece hosts önbelleğini temizlemenin temiz yolu. İkisi birlikte çalışıyorsa her ikisini de temizleyin. Ve sorun devam ediyorsa /etc/hosts dosyasına, TTL değerlerine ve DNSSEC konfigürasyonuna bakın.
DNS sorunlarında paniklemek yerine sistematik ilerlemek, genellikle sizi birkaç komut içinde çözüme ulaştırır. Umarım bu yazı o anlarda işe yarar bir referans olur.
