თქვენი ლეპტოპი VPN-შია, dig service.internal.example პასუხობს 10.x მისამართით, და curl მაინც სრულდება Could not resolve host-ით. გვირაბი პრობლემა არ არის: მან dig-ის მოთხოვნა უჩივლელად გადაიტანა. განსხვავება იმაშია, ვინ სვამს კითხვას. dig აგზავნის ერთ მოთხოვნას ერთ სერვერზე, რომელსაც თქვენ ასახელებთ, ხოლო curl გადის ოპერაციული სისტემის ძებნის ჯაჭვში, და ამ ჯაჭვს აქვს საკუთარი წესები იმის შესახებ, რომელი სერვერი იკითხება.

ორი ძებნა ერთი სახელისთვის

dig არის საკუთარი stub resolver. ის კითხულობს /etc/resolv.conf-ს, ირჩევს სახელების სერვერს, აგზავნის ერთ A ან AAAA მოთხოვნას და ბეჭდავს პასუხს. ის მთლიანად გამოტოვებს nsswitch-ს და არაფერი იცის ბმულის დონის იმ მდგომარეობის შესახებ, რომელსაც systemd-resolved ან NetworkManager ამ ფაილის გარეთ ინახავს, და ამიტომ dig-ის პასუხი შეიძლება სწორი იყოს და მაინც არაფერი გითხრათ იმაზე, რასაც თქვენი აპლიკაცია დაინახავს.

აპლიკაციები იძახებენ getaddrinfo-ს, და getaddrinfo გადის უფრო გრძელ ჯაჭვს: nsswitch-ის მოდულების რიგი, შემდეგ მოდული, რომელიც ამუშავებს სახელს, და ბოლოს resolver, რომელიც აგებულია მიმდინარე ბმულის კონფიგურაციიდან. systemd მანქანაზე მოთხოვნა მიდის 127.0.0.53-ზე, და systemd-resolved ირჩევს ზედა დონის სერვერს თითოეული ბმულისთვის tun ინტერფეისზე მიბმული მარშრუტიზაციის დომენის მიხედვით.

ორი ბრძანება ჰყოფს ამ შრეებს გამოცნობის გარეშე:

getent ahosts service.internal.example
resolvectl query service.internal.example

getent იყენებს იმავე გზას, რასაც curl, ამიტომ მუშა dig-ის გვერდით getent-ის წარუმატებლობა ხარვეზს ძებნის პოლიტიკაში ადგენს და არა პაკეტების მარშრუტიზაციაში. resolvectl query ასევე ბეჭდავს ინტერფეისს და ზედა სერვერს, რომელმაც პასუხი მოგვცა, რაც აჩვენებს, გვირაბის ბმულმა თუ ფიზიკურმა ბმულმა მოიგო გადაწყვეტილება.

წაიკითხეთ ის resolver, რომელსაც აპლიკაცია რეალურად იყენებს

/etc/resolv.conf გენერირდება უმეტეს დესკტოპებზე, და VPN კლიენტს აქვს მასთან ურთიერთობის სამი გზა: დაამატოს სახელების სერვერი წინ, გადაწეროს ფაილი, ან თავისი სერვერები გადასცეს NetworkManager-ს და მისცეს დემონს მისი გადაწერის უფლება. მხოლოდ მესამე ნიმუში ინარჩუნებს ბმულის დონის DNS-ს, რადგან სერვერები რჩება ინტერფეისზე მიბმული, ნაცვლად იმისა, რომ ერთ გლობალურ სიაში გაბრტყელდეს.

NetworkManager სისტემებში შედეგი დამოკიდებულია backend-ზე /etc/NetworkManager/NetworkManager.conf-ში:

[main]
dns=systemd-resolved

dns=default-ის შემთხვევაში კლიენტის სერვერები ერწყმის resolv.conf-ს გამარჯვებული რიგით, და კერძო მოთხოვნა მაინც შეიძლება გაიგზავნოს საჯარო resolver-ზე. ბმულების გამგები backend-ით, systemd-resolved ან dnsmasq, გვირაბის სერვერები რჩება გვირაბით შემოფარგლული, და იქ მიდის მხოლოდ მისი მარშრუტიზაციის დომენის შესაბამისი სახელები. ეს შემოფარგლვა არის ის, რასაც split DNS ნიშნავს პრაქტიკაში, და ეს არის ის ნაწილი, რომელიც ყველაზე ხშირად აკლია, როცა კლიენტი აცხადებს, რომ მხარს უჭერს მას.

წაიკითხეთ მდგომარეობა, სანამ რამეს შეცვლით:

resolvectl status
resolvectl dns tun0

გსურთ დაინახოთ tun ინტერფეისი ჩამოთვლილი DNS სერვერით და კერძო სუფიქსის მარშრუტიზაციის დომენით, ნაჩვენები როგორც ~internal.example. ბმულზე სერვერის არარსებობა ნიშნავს, რომ კლიენტმა არაფერი გაგზავნა. დომენის გარეშე სერვერი ნიშნავს, რომ მოთხოვნები ან ყველა მიდის იქ, ან არც ერთი, კლიენტის მიხედვით, და არც ერთი არ არის split DNS.

სად წყვეტს nsswitch ძებნას ნაადრევად

სტანდარტული დესკტოპის ხაზი ასე გამოიყურება:

hosts: files mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] dns myhostname

mdns4_minimal ამუშავებს multicast DNS-ს და ითხოვს ყველა სახელს, რომელიც .local-ით მთავრდება. Kubernetes სერვისი, როგორიცაა api.infra.svc.cluster.local, ასევე .local-ით მთავრდება. როცა mDNS მოდული იტყობინება NOTFOUND-ს, [NOTFOUND=return] მოქმედება ამთავრებს მთელ ძებნას იმის ნაცვლად, რომ გადავიდეს dns მოდულზე, ამიტომ სახელი არასოდეს იგზავნება VPN resolver-ზე. dig მთლიანად გვერდს უვლის ფაილს, და ზუსტად ამიტომ არ თანხმდებიან ეს ორი ხელსაწყო.

ეს არის ამ პრობლემის ყველაზე მკვეთრი კონტრასტი, და ის მთავრდება ერთ სიტყვაზე კონფიგურაციის ფაილში, რომელიც თქვენს VPN-ზე ძველია. მოქმედების [NOTFOUND=continue]-ზე შეცვლა ინარჩუნებს mDNS-ს პრინტერებისა და ლოკალური მოწყობილობებისთვის, და საშუალებას აძლევს DNS-ს დაინახოს სახელი. ხაზის hosts: files dns-ით ჩანაცვლება ასევე მუშაობს და უფრო უხეშია: ის ამოღებს .local გარჩევას პრინტერისთვის, რომელსაც რეალურად იყენებთ.

სახელები, რომლებიც ზუსტად ერთ ქსელში ცხოვრობენ

კერძო ზონები ავტორიტეტულია ზუსტად ერთ ადგილას. AWS სახელი, როგორიცაა ip-10-0-4-31.eu-west-1.compute.internal, პასუხდება იმ რეგიონის VPC resolver-ის მეშვეობით, და მხოლოდ მანამ, სანამ თქვენი VPN საბოლოო წერტილი იმავე რეგიონშია, როგორც რესურსი. დაუკავშირდით ფრანკფურტის საბოლოო წერტილს, იკითხეთ ირლანდიის compute.internal სახელი, და არც ერთი ლოკალური პარამეტრი არ დაგეხმარებათ: ზონა, რომელიც ინახავს ჩანაწერს, იქიდან მიუწვდომელია.

ძებნის დომენები ქმნიან სარკისებურ სურათს. შიშველი service ივსება იმ სუფიქსით, რომელსაც resolver მიზანშეწონილად თვლის, და VPN ბმულით ლოკალურ დომენს შეუძლია კორპორატიულის დამარცხება. იკითხეთ ბოლოში წერტილით, რომ გამოცნობა მოიხსნას, getent ahosts service.internal.example., და თუ ეს მუშაობს, სანამ მოკლე სახელი ვერ მუშაობს, შესწორება არის გვირაბზე არსებული ძებნის დომენი, და არა სერვერის მისამართი.

მართული კლიენტები ამატებენ მესამე შრეს სისტემის resolver-ის ზემოთ. Windows VPN პროფილს შეუძლია ატაროს საკუთარი სახელების გარჩევის პოლიტიკა, თითოეული აპლიკაციის წესები და NRPT ცხრილი, რომელიც ძალაშია მაშინაც, როცა გვირაბი გამორთულია. საკუთარი DNS ქეშის მქონე აპლიკაციები, ჩვეულებრივი .NET და Java გარემოებში, დიდხანს ინახავს მოძველებულ წარუმატებლობას ჯაჭვის გამართვის შემდეგაც. Apple-ის კლიენტები split DNS-ს აყენებენ DNS პარამეტრებში არსებული დამთხვევის დომენებით და არა resolv.conf-ით, ხოლო Chromium ან Firefox დაცული DNS რეჟიმში შეიძლება გვერდს უვლიდეს სისტემის resolver-ს საჯარო სახელებისთვის. Microsoft-ის VPN სახელების გარჩევის ცნობარი აღწერს ამ პოლიტიკის შრის Windows მხარეს.

გადაწყვიტეთ, რომელი შრე გამოასწოროთ

იმუშავეთ სიმპტომიდან შრისკენ, ნაცვლად იმისა, რომ შესწორებები რიგრიგობით სცადოთ:

SymptomWhat it meansCheck first
dig answers, getent failslookup chain, not the packet pathnsswitch line and resolvectl status
Timeout rather than NXDOMAINprivate resolver unreachable through the tunnelresolvectl dns tun0, route to that address
NXDOMAINan authority answered and does not know the namezone owner, endpoint region
FQDN works, short name failssearch suffix mismatchresolvectl domain on the tun link
getent works, app failsapp cache or its own resolverrestart the app, check secure DNS

ორი სტრიქონი ატარებს ძირითად სიმძიმეს. დროის ამოწურვა ხელმისაწვდომობის პრობლემაა: კერძო resolver არ პასუხობს გვირაბის გავლით, ამიტომ შეამოწმეთ მარშრუტი მის მისამართამდე და ის, არის თუ არა ბმულის DNS სერვერი ის, რაც გგონიათ. NXDOMAIN ავტორიტეტის პრობლემაა: რაღაცამ უპასუხა და არ იცის სახელი, რაც მიუთითებს ზონაზე, რეგიონზე ან resolver-ზე, რომელსაც არასოდეს უნდა მიეღო მოთხოვნა.

ბოლო სტრიქონი ის არის, რომელსაც ხალხი გამოტოვებს, რადგან ორივე ნახევარი წარმატებას ჰგავს. მოკლე სახელი, რომელიც FQDN-ისგან განსხვავებულად იხსნება, სუფიქსის შეუსაბამობაა, და გვირაბის ხელახლა დაკავშირება არ შეცვლის იმას, თუ რა სუფიქსს აგზავნის კლიენტი.

დააფიქსირეთ მდგომარეობა, სანამ კონფიგურაციის ფაილს შეასწორებთ, რომ შემდეგ შეძლოთ თქვათ, შეცვალა თუ არა რამე შესწორებამ:

resolvectl status > before.txt
getent ahosts service.internal.example >> before.txt

შეასრულეთ შემოწმებები ამ რიგით და გაჩერდით პირველ წარუმატებელზე. getent და resolvectl query უნდა ემთხვეოდეს; თუ getent ვერ მუშაობს, სანამ dig პასუხობს, დარჩით ძებნის ჯაჭვში და არ შეეხოთ მარშრუტიზაციას. resolvectl status უნდა აჩვენოს DNS სერვერი და მარშრუტიზაციის დომენი tun ინტერფეისზე. nsswitch არ უნდა დაბრუნდეს ნაადრევად NOTFOUND-ით შესამოწმებელი სუფიქსისთვის. სახელი უნდა იყოს ავტორიტეტული იმ ქსელში, რომელზეც დაკავშირებულია თქვენი საბოლოო წერტილი, შემოწმებული ბოლოში წერტილით. აპლიკაცია არ უნდა ინახავდეს საკუთარ ქეშს ან დაცული DNS-ის გადაფარვას.

შეასწორეთ მხოლოდ პირველი წარუმატებელი შრე, შემდეგ კვლავ შეასრულეთ იგივე ბრძანებები. ორი ცვლილება ერთდროულად გიშლით ხელს თქვათ, რომელი იყო მნიშვნელოვანი, და შემდეგი ავარია გამოძიებას ნულიდან იწყებს.

დაკავშირებული სტატიები