Neden iç ana makine adları dig’de çözülüyor ama curl’de VPN’de başarısız oluyor
dig yanıt veriyor ama curl ana makineyi çözemediğini bildiriyor. İki arama zincirini karşılaştırın, sonra nsswitch’i, bağlantı başına DNS’i veya yanlış arama sonekini düzeltin.
Dizüstü bilgisayarınız VPN’de, dig service.internal.example 10.x adresiyle yanıt veriyor ve curl hâlâ Could not resolve host ile çıkıyor. Tünel sorun değil: dig sorgusunu şikâyet etmeden taşıdı. Fark, soruyu kimin sorduğunda. dig, sizin adlandırdığınız tek bir sunucuya tek bir sorgu gönderir; curl ise işletim sisteminin arama zincirinden geçer ve bu zincirin hangi sunucuya sorulacağına dair kendi kuralları vardır.
Aynı ad için iki arama
dig kendi stub resolver’ıdır. /etc/resolv.conf dosyasını okur, bir ad sunucusu seçer, tek bir A veya AAAA sorgusu gönderir ve yanıtı yazdırır. nsswitch’i tamamen atlar ve systemd-resolved ya da NetworkManager’ın bu dosyanın dışında tuttuğu bağlantı başına durumu bilmez; bu yüzden bir dig yanıtı doğru olabilir ve yine de uygulamanızın ne göreceği hakkında size hiçbir şey söylemez.
Uygulamalar getaddrinfo’yu çağırır ve getaddrinfo daha uzun bir zincirden geçer: nsswitch modül sırası, sonra adı işleyen modül ve son olarak geçerli bağlantı yapılandırmasından kurulan resolver. systemd makinesinde sorgu 127.0.0.53’e gider ve systemd-resolved, tun arayüzüne bağlı yönlendirme alan adına göre her bağlantı için bir üst sunucu seçer.
İki komut bu katmanları tahmin etmeden ayırır:
getent ahosts service.internal.example
resolvectl query service.internal.example
getent, curl ile aynı yolu kullanır; bu yüzden çalışan bir dig’in yanındaki getent hatası, arızayı paket yönlendirmesinde değil arama politikasında konumlandırır. resolvectl query ayrıca yanıtı veren arayüzü ve üst sunucuyu da yazdırır; bu, kararı tünel bağlantısının mı yoksa fiziksel bağlantının mı kazandığını gösterir.
Uygulamanın gerçekte kullandığı resolver’ı okuyun
/etc/resolv.conf çoğu masaüstünde üretilir ve bir VPN istemcisinin onunla etkileşime girmesinin üç yolu vardır: bir ad sunucusunu öne eklemek, dosyanın üzerine yazmak veya sunucularını NetworkManager’a verip daemon’un dosyayı yeniden yazmasına izin vermek. Bağlantı başına DNS’i yalnızca üçüncü desen korur, çünkü sunucular tek bir global listeye düzleştirilmek yerine bir arayüze bağlı kalır.
NetworkManager sistemlerinde sonuç /etc/NetworkManager/NetworkManager.conf içindeki backend’e bağlıdır:
[main]
dns=systemd-resolved
dns=default ile istemcinin sunucuları kazanan sırayla resolv.conf’a birleştirilir ve özel bir sorgu yine de genel resolver’a gidebilir. Bağlantıları anlayan bir backend ile, systemd-resolved veya dnsmasq, tünelin sunucuları tünele sınırlı kalır ve oraya yalnızca onun yönlendirme alan adıyla eşleşen adlar gider. Bu sınırlama, split DNS’in pratikte anlamı olan şeydir ve bir istemci bunu desteklediğini iddia ettiğinde en sık eksik olan parçadır.
Herhangi bir şeyi değiştirmeden önce durumu okuyun:
resolvectl status
resolvectl dns tun0
tun arayüzünün bir DNS sunucusu ve özel sonek için bir yönlendirme alan adıyla listelendiğini, ~internal.example olarak gösterildiğini görmek istersiniz. Bağlantıda sunucu olmaması istemcinin hiçbir şey göndermediği anlamına gelir. Alan adı olmayan bir sunucu, sorguların ya hepsinin oraya gittiği ya da hiçbirinin gitmediği anlamına gelir, istemciye bağlı olarak, ve ikisi de split DNS değildir.
nsswitch’in aramayı çok erken bitirdiği yer
Standart bir masaüstü satırı şöyle görünür:
hosts: files mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns myhostname
mdns4_minimal multicast DNS ile ilgilenir ve .local ile biten her ada hak iddia eder. api.infra.svc.cluster.local gibi bir Kubernetes hizmeti de .local ile biter. mDNS modülü NOTFOUND bildirdiğinde, [NOTFOUND=return] eylemi dns modülüne devam etmek yerine tüm aramayı bitirir, bu yüzden ad hiçbir zaman VPN resolver’ına gönderilmez. dig dosyayı tamamen atlar ve iki aracın anlaşmazlığının tam nedeni budur.
Bu, bu sorundaki en keskin karşıtlıktır ve VPN’inizden eski bir yapılandırma dosyasındaki tek bir sözcüğe indirgenir. Eylemi [NOTFOUND=continue] olarak değiştirmek, mDNS’i yazıcılar ve yerel aygıtlar için korurken DNS’in adı görmesini sağlar. Satırı hosts: files dns ile değiştirmek de çalışır ve daha kabaca: gerçekte kullandığınız yazıcı için .local çözümlemesini düşürür.
Tam olarak tek bir ağda yaşayan adlar
Özel bölgeler tam olarak tek bir yerde yetkilidir. ip-10-0-4-31.eu-west-1.compute.internal gibi bir AWS adı o bölgenin VPC resolver’ı üzerinden yanıtlanır ve yalnızca VPN uç noktanız kaynakla aynı bölgede olduğu sürece. Frankfurt’taki bir uç noktaya bağlanın, İrlanda’dan bir compute.internal adı sorgulayın ve hiçbir yerel ayar yardımcı olmaz: kaydı tutan bölge oradan erişilebilir değildir.
Arama alan adları ayna görüntüsünü üretir. Çıplak service, resolver’ın geçerli saydığı sonekle tamamlanır ve bir VPN bağlantısıyla yerel alan adı kurumsal olanı yenebilir. Tahmini ortadan kaldırmak için sonda nokta ile sorgulayın, getent ahosts service.internal.example., ve bu çalışırken kısa ad başarısız oluyorsa düzeltme tüneldeki arama alan adıdır, sunucu adresi değil.
Yönetilen istemciler sistem resolver’ının üstüne üçüncü bir katman ekler. Bir Windows VPN profili kendi ad çözümleme politikasını, uygulama başına kuralları ve tünel kapalıyken bile geçerli olan bir NRPT tablosunu taşıyabilir. Kendi DNS önbelleğine sahip uygulamalar, .NET ve Java çalışma zamanlarında yaygın olarak, zincir düzeltildikten çok sonra bile eski bir hatayı korur. Apple istemcileri split DNS’i resolv.conf yerine DNS ayarlarındaki eşleşme alan adlarıyla yapılandırır ve Chromium ya da Firefox güvenli DNS modunda genel adlar için sistem resolver’ını atlayabilir. Microsoft’un VPN ad çözümleme başvurusu bu politika katmanının Windows tarafını anlatır.
Hangi katmanın düzeltileceğine karar verin
Düzeltmeleri sırayla denemek yerine semptomdan katmana doğru ilerleyin:
| Symptom | What it means | Check first |
|---|---|---|
| dig answers, getent fails | lookup chain, not the packet path | nsswitch line and resolvectl status |
| Timeout rather than NXDOMAIN | private resolver unreachable through the tunnel | resolvectl dns tun0, route to that address |
| NXDOMAIN | an authority answered and does not know the name | zone owner, endpoint region |
| FQDN works, short name fails | search suffix mismatch | resolvectl domain on the tun link |
| getent works, app fails | app cache or its own resolver | restart the app, check secure DNS |
İki satır ağırlığın çoğunu taşır. Zaman aşımı bir erişilebilirlik sorunudur: özel resolver tünel üzerinden yanıt vermiyor, bu yüzden adresine giden yolu ve bağlantıdaki DNS sunucusunun düşündüğünüz sunucu olup olmadığını kontrol edin. NXDOMAIN bir yetki sorunudur: bir şey yanıt verdi ve adı bilmiyor, bu da bölgeye, bölgeye ya da sorguyu hiç almaması gereken bir resolver’a işaret eder.
Son satır, insanların kaçırdığı satırdır çünkü iki yarı da başarı gibi görünür. FQDN’den farklı çözülen kısa bir ad bir sonek uyuşmazlığıdır ve tüneli yeniden bağlamak istemcinin hangi soneki gönderdiğini değiştirmez.
Bir yapılandırma dosyasını düzenlemeden önce durumu kaydedin, böylece düzenlemenin bir şey yapıp yapmadığını söyleyebilirsiniz:
resolvectl status > before.txt
getent ahosts service.internal.example >> before.txt
Kontrolleri bu sırayla çalıştırın ve başarısız olan ilkinde durun. getent ve resolvectl query uyuşmalıdır; getent başarısız olurken dig yanıt veriyorsa arama zincirinde kalın ve yönlendirmeye dokunmayın. resolvectl status tun arayüzünde bir DNS sunucusu ve yönlendirme alan adı göstermelidir. nsswitch, test ettiğiniz sonek için NOTFOUND ile erken dönmemelidir. Ad, uç noktanızın bağlı olduğu ağda yetkili olmalıdır ve sonda nokta ile test edilmelidir. Uygulama kendi önbelleğini veya güvenli DNS geçersiz kılmasını tutmamalıdır.
Yalnızca başarısız olan ilk katmanı düzeltin, sonra aynı komutları yeniden çalıştırın. Aynı anda iki değişiklik, hangisinin önemli olduğunu söylemenizi engeller ve sonraki kesinti incelemeye sıfırdan başlar.