SSD Nodes Learn Hosting plans →
Przewodniki Matt ConnorAutor: Matt Connor · Zaktualizowano 2026-08-28

DNS nie działa przez WireGuard: jak naprawić błędy

Tunel WireGuard jest aktywny, ale nazwy nie są rozwiązywane lub zapytania wyciekają poza sieć VPN. Zidentyfikuj jeden z trzech typów awarii DNS i zastosuj poprawne rozwiązanie.

Dlaczego DNS przestaje działać w momencie nawiązania tunelu WireGuard

DNS przez WireGuard zawodzi na trzy sposoby, a każdy z nich wymaga innego rozwiązania. Rozwiązywanie nazw nie działa w ogóle, zapytania wychodzą poza tunel lub menedżer usług DNS klienta nadpisuje ustawienia kilka sekund po uruchomieniu interfejsu. Problem prawie nigdy nie leży w samym tunelu. Przyczyną jest pojedyncza linia wskazująca klientowi, z którego serwera DNS korzystać, oraz routing decydujący o tym, jak pakiety do tego serwera są przesyłane.

WireGuard przesyła pakiety IP i nie posiada wiedzy o DNS (systemie nazw domenowych, usłudze zamieniającej nazwy takie jak example.com na adresy IP). Linia DNS = w bloku [Interface] klienta nie jest ustawieniem WireGuard. Jest ona odczytywana przez wg-quick, skrypt powłoki uruchamiający interfejs, a następnie wg-quick modyfikuje konfigurację DNS klienta podczas działania tunelu i przywraca ją przy wg-quick down. Każdy z poniższych problemów wynika zatem z błędów routingu lub wg-quick, a nie z kwestii kryptograficznych. Jeśli tunel nie został jeszcze zestawiony, należy zacząć od własnego serwera WireGuard VPN na VPS i wrócić do tej strony później.

Przed przystąpieniem do konfiguracji DNS należy upewnić się, że tunel działa poprawnie.

sudo wg show
ping -c 3 10.8.0.1
ping -c 3 1.1.1.1

Polecenie wg show powinno wyświetlić peer z niedawnym latest handshake, a oba pingi powinny otrzymywać odpowiedź. Jeśli ping 1.1.1.1 kończy się przekroczeniem czasu oczekiwania, problem dotyczy przekierowania lub NAT (network address translation), a nie DNS, więc zmiany w konfiguracji serwera nazw nie pomogą. Jeśli pingi działają, ale przepustowość spada po rozpoczęciu przesyłania rzeczywistego ruchu, jest to odrębny problem, a wolne działanie WireGuard prawie zawsze wynika z MTU, a nie z przyczyn opisanych na tej stronie. Każdy przykład tutaj używa 10.8.0.0/24 jako podsieci tunelu oraz 10.8.0.1 jako adresu tunelu serwera. Należy podstawić własne wartości.

Pierwsza awaria: brak rozwiązywania nazw, ponieważ resolver nie odpowiada

Objaw jest precyzyjny. ping 1.1.1.1 działa, a curl https://example.com zwraca następujący wynik:

curl: (6) Could not resolve host: example.com

Należy odpytać resolver tunelu bezpośrednio z poziomu klienta. Narzędzie dig pochodzi z pakietu dnsutils w systemach Ubuntu i Debian.

dig +short @1.1.1.1 example.com
dig +short @10.8.0.1 example.com

Pierwsze polecenie zwraca adres, co dowodzi, że pakiety docierają do Internetu przez tunel. Drugie nie zwraca nic i wyświetla ;; communication timed out; no servers could be reached. To cała diagnoza: klient jest skierowany na 10.8.0.1, a 10.8.0.1 nie odpowiada na porcie UDP 53.

Przyczyną są dwa stany. Albo na serwerze nie działa żaden resolver, albo firewall serwera odrzuca zapytanie, zanim dotrze ono do celu. Należy sprawdzić oba te aspekty na serwerze.

sudo ss -ulnp | grep ':53'
sudo nft list ruleset

Działający i poprawnie powiązany resolver wyświetla linię z 10.8.0.1:53 lub 0.0.0.0:53. W systemie Ubuntu niespodzianką jest zazwyczaj 127.0.0.53:53: to nasłuchujący stub systemd-resolved, który wiąże się z adresem pętli zwrotnej i jest celowo nieosiągalny z innych maszyn. Skierowanie klienta VPN na serwer, którego jedynym resolverem jest ten stub, powoduje dokładnie taki przekroczenie czasu oczekiwania.

Rozwiązaniem jest resolver nasłuchujący na adresie tunelu oraz reguła firewalla zezwalająca partnerom na dostęp do niego.

sudo apt update && sudo apt install -y unbound
printf 'server:\n  interface: 10.8.0.1\n  access-control: 10.8.0.0/24 allow\n' \
  | sudo tee /etc/unbound/unbound.conf.d/wireguard.conf
sudo systemctl restart unbound
sudo ss -ulnp | grep '10.8.0.1:53'

Następnie należy otworzyć port wyłącznie dla ruchu tunelowego. W przypadku nftables należy dodać te dwie linie do łańcucha input w pliku /etc/nftables.conf i przeładować konfigurację za pomocą sudo systemctl reload nftables.

udp dport 53 iifname "wg0" accept
tcp dport 53 iifname "wg0" accept

W przypadku ufw, polecenie sudo ufw allow in on wg0 to any port 53 wykonuje to samo zadanie. Nigdy nie należy otwierać portu 53 dla publicznego Internetu. Otwarty resolver rekurencyjny zostanie wykryty przez skanery w ciągu kilku dni i wykorzystany do wzmacniania ataków typu denial of service, a dostawca usług zauważy ten ruch szybciej niż administrator.

Należy ponownie uruchomić dig +short @10.8.0.1 example.com z poziomu klienta. Adres w wyniku oznacza, że ścieżka do resolvera działa, więc klient musi go teraz tylko użyć. Należy dodać odpowiednią linię do bloku [Interface] klienta i zrestartować interfejs za pomocą sudo wg-quick down wg0 && sudo wg-quick up wg0.

[Interface]
PrivateKey = <client private key>
Address = 10.8.0.2/32
DNS = 10.8.0.1

Awaria druga: wycieki DNS, ponieważ tunel dzielony nie kieruje ruchu do resolvera

Ten przypadek jest groźniejszy, ponieważ wszystko wydaje się działać poprawnie. Nazwy są rozwiązywane, strony się ładują, a zapytania przesyłane są otwartym tekstem przez sieć lokalną, której nie chciano obdarzyć zaufaniem.

Przyczyną są dwie konfiguracje. Pierwszą jest klient z AllowedIPs = 0.0.0.0/0, ::/0 bez linii DNS =. wg-quick instaluje domyślną trasę we własnej tablicy routingu i dodaje regułę z suppress_prefixlength 0, która celowo utrzymuje bardziej szczegółowe trasy lokalne, aby maszyna mogła nadal komunikować się z drukarką. Resolver, o którym klient dowiedział się przez DHCP, zazwyczaj router pod adresem 192.168.1.1, pasuje do jednej z tych tras lokalnych. Ruch sieciowy przechodzi przez tunel. Sieć lokalna nadal otrzymuje pełną listę wyszukiwanych nazw.

Drugą przyczyną jest tunel dzielony: AllowedIPs = 10.8.0.0/24 z DNS = 9.9.9.9. Ponieważ 9.9.9.9 nie znajduje się wewnątrz AllowedIPs, klient nie posiada trasy do niego przez tunel, więc zapytanie opuszcza interfejs przez łącze lokalne, dokładnie tak jak w pierwszym przypadku.

Należy sprawdzić, który resolver faktycznie odpowiada. whoami.akamai.net to publiczna nazwa testowa, która odpowiada adresem IP rekurencyjnego resolvera, który wysłał zapytanie, co pozwala porównać tę odpowiedź z publicznym adresem serwera.

resolvectl status
dig +short whoami.akamai.net
sudo tcpdump -ni any -c 10 port 53

resolvectl status wyświetla jeden blok dla każdego łącza. Jeśli blok dla łącza ethernet lub bezprzewodowego nadal pokazuje Current DNS Server: 192.168.1.1, podczas gdy blok wg0 nie pokazuje nic, oznacza to wyciek. dig +short whoami.akamai.net zwracający adres domowego łącza szerokopasmowego zamiast adresu serwera potwierdza to z drugiej strony. Linia tcpdump stanowi ostateczny dowód: poprawna konfiguracja kieruje każdy pakiet na porcie 53 do wg0, a wyciek kieruje je do wlan0 lub enp3s0.

Naprawa składa się z dwóch części i obie są wymagane. Należy ustawić DNS na adres znajdujący się wewnątrz tunelu i upewnić się, że adres ten mieści się w AllowedIPs.

[Interface]
Address = 10.8.0.2/32
DNS = 10.8.0.1

[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 10.8.0.0/24, 10.20.0.0/16

10.8.0.1 znajduje się wewnątrz 10.8.0.0/24, więc zapytanie jest szyfrowane i wysyłane do serwera. W przypadku konieczności użycia publicznego resolvera w tunelu dzielonym, należy dodać go jako trasę hosta: AllowedIPs = 10.8.0.0/24, 9.9.9.9/32. Pakiety są wtedy przesyłane przez tunel, choć sieć lokalna nadal może zidentyfikować wybranego dostawcę na podstawie wcześniejszych sesji. Uruchomienie własnego resolvera eliminuje ten problem.

Przypisywanie resolvera to jedna z widocznych różnic między samodzielnie skonfigurowanym WireGuard a skoordynowaną siecią mesh. Jest to część kompromisu opisanego w WireGuard w porównaniu z Tailscale. Uruchomienie samodzielnie utrzymywanego serwera sterującego Headscale zapewnia tę koordynację bez przekazywania materiału kluczy zewnętrznemu podmiotowi. Jeśli to ostatnie stwierdzenie budzi obawy, należy pamiętać, że Tailscale nigdy nie przechowuje kluczy szyfrujących ruch, a trafniejsze pytanie brzmi: co przejęty serwer koordynacyjny lub skradzione konto tożsamości może dodać do sieci.

Trzecia awaria: konflikt resolvconf i systemd-resolved na klientach Linux

Klienci macOS, Windows, iOS oraz Android stosują DNS = za pośrednictwem oficjalnej aplikacji i rzadko sprawiają problemy. W systemie Linux ustawienie to jest wprowadzane przez skrypt powłoki, który musi odgadnąć, który z kilku dostępnych menedżerów rozwiązywania nazw jest używany.

Pierwsza awaria jest wyraźna. sudo wg-quick up wg0 zatrzymuje się z błędem:

resolvconf: command not found

wg-quick odwołuje się do resolvconf, a ten plik binarny nie jest zainstalowany. Należy zainstalować implementację współpracującą z systemd-resolved, a następnie ponownie uruchomić interfejs.

sudo apt install -y openresolv
sudo systemctl restart systemd-resolved
sudo wg-quick down wg0 && sudo wg-quick up wg0
resolvectl status wg0

Druga awaria jest cicha i to ona pochłania najwięcej czasu. Interfejs uruchamia się, resolvectl status wg0 poprawnie wyświetla DNS Servers: 10.8.0.1, a wyszukiwania nadal trafiają do starego mechanizmu rozwiązywania nazw. systemd-resolved utrzymuje oddzielną listę serwerów DNS dla każdego łącza i wybiera łącze dla każdego zapytania. Dopóki jedno z łączy nie zostanie oznaczone jako domyślna trasa dla nazw, system nadal używa serwera DNS łącza bezprzewodowego, ponieważ to łącze posiada domenę wyszukiwania, a Twoje nie.

Ustaw serwer DNS i zadeklaruj domyślną trasę w tym samym kroku. %i rozwija się do nazwy interfejsu, więc ten blok działa bez zmian na każdym interfejsie.

[Interface]
Address = 10.8.0.2/32
PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~.
PostDown = resolvectl revert %i

Usuń linię DNS =, gdy używasz PostUp w ten sposób, ponieważ w przeciwnym razie dwa mechanizmy zapisują stan serwera DNS, a tylko jeden z nich czyści go po zakończeniu pracy. Argument ~. jest kluczowy: oznacza on wg0 jako domenę routingu dla każdej nazwy, dzięki czemu systemd-resolved wysyła wszystkie zapytania tam, zamiast wybierać łącze dla każdego zapytania. Zweryfikuj to.

resolvectl status wg0

Poprawne wyjście zawiera DNS Servers: 10.8.0.1 oraz Default Route: yes. Jeśli Default Route wskazuje na no, oznacza to, że część resolvectl domain nie została wykonana i powrócono do wyboru łącza.

Warto wspomnieć o jeszcze jednym przypadku. Jeśli /etc/resolv.conf jest rzeczywistym plikiem, a nie dowiązaniem symbolicznym do /run/systemd/resolve/stub-resolv.conf, oznacza to, że zarządza nim inny proces, zazwyczaj NetworkManager lub środowisko uruchomieniowe kontenerów. Uruchom ls -l /etc/resolv.conf przed rozpoczęciem jakiegokolwiek debugowania, ponieważ narzędzie, które nadpisuje ten plik przy każdej zmianie sieci, cofnie Twoje zmiany w najmniej odpowiednim momencie.

Aktualizacja: własny serwer DNS z filtrowaniem przez tunel

Gdy zapytania są poprawnie przesyłane przez tunel, serwer DNS na jego końcu staje się punktem kontrolnym. Uruchomienie AdGuard Home w tym miejscu zapewnia każdemu podłączonemu urządzeniu filtrowanie na podstawie list blokad oraz dziennik zapytań, bez konieczności instalacji oprogramowania klienckiego czy konfiguracji poszczególnych urządzeń. Oficjalny skrypt instalacyjny, zweryfikowany w lipcu 2026, składa się z jednej linii.

curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v

Kreator konfiguracji przy pierwszym uruchomieniu nasłuchuje na porcie 3000. Należy uzyskać do niego dostęp przez tunel pod adresem http://10.8.0.1:3000, zamiast otwierać ten port publicznie. W kreatorze należy ustawić adres nasłuchiwania DNS oraz adres panelu administracyjnego na 10.8.0.1. Jeśli unbound z pierwszej awarii nadal zajmuje ten sam adres, należy go najpierw zatrzymać za pomocą sudo systemctl disable --now unbound, ponieważ dwa procesy nie mogą powiązać portu UDP 53 z tym samym adresem, a drugi z nich zakończy działanie z błędem listen udp 10.8.0.1:53: bind: address already in use.

Konfiguracje klientów nie wymagają zmian, jeśli wskazują już na DNS = 10.8.0.1. Dziennik zapytań będzie teraz pokazywał każde wyszukiwanie z każdego węzła, co jest świadomą decyzją dotyczącą prywatności, a nie darmowym zyskiem: przenosisz zaufanie z dostawcy internetu na siebie i to Ty musisz dbać o aktualizacje tego serwera. Serwer wystawiony na działanie internetu wymaga najpierw wdrożenia podstawowych zabezpieczeń, które opisano w pierwsze dziesięć minut na nowym VPS.

FAQ

Dlaczego tunel WireGuard łączy się, ale nazwy nie są rozwiązywane?

Tunel przesyła pakiety i nie obsługuje nazw, więc działający tunel przy niedziałającym rozwiązywaniu nazw oznacza, że używany resolver nie odpowiada. Przeprowadź test za pomocą dig +short @10.8.0.1 example.com z poziomu klienta. Odpowiedź communication timed out oznacza, że albo żaden resolver nie nasłuchuje na tym adresie tunelu (często dlatego, że stub systemd-resolved wiąże się tylko z 127.0.0.53), albo firewall serwera odrzuca ruch UDP na porcie 53 przychodzący na wg0. Najpierw napraw nasłuchiwanie, a następnie otwórz port wyłącznie dla wg0.

Jak sprawdzić, czy DNS wycieka poza WireGuard?

Uruchom sudo tcpdump -ni any -c 10 port 53 na kliencie i obserwuj kolumnę interfejsu podczas przeglądania stron. Każdy pakiet powinien być widoczny na wg0. Jeśli pojawiają się one na interfejsie bezprzewodowym lub ethernet, zapytania są wysyłane otwartym tekstem. dig +short whoami.akamai.net pozwala uzyskać drugą opinię, ponieważ odpowiada publicznym adresem tego resolvera rekurencyjnego, który wysłał zapytanie; odpowiedź inna niż adres Twojego serwera potwierdza wyciek.

Czy potrzebuję linii DNS =, jeśli używam split tunnel?

Tak, a adres resolvera musi również znajdować się wewnątrz AllowedIPs, w przeciwnym razie klient nie będzie miał do niego trasy. Przy AllowedIPs = 10.8.0.0/24 resolver pod adresem 10.8.0.1 jest objęty tunelem, a zapytanie jest szyfrowane. Publiczny resolver, taki jak 9.9.9.9, nie jest objęty tunelem, więc zapytanie wychodzi przez łącze lokalne, nawet jeśli linia DNS wygląda na poprawną.

Dlaczego resolvectl pokazuje właściwy serwer, ale zapytania trafiają gdzie indziej?

systemd-resolved utrzymuje listę resolverów dla każdego łącza i wybiera łącze dla każdego zapytania, więc poprawny wpis na wg0 jest ignorowany, jeśli inne łącze posiada domyślną trasę dla nazw. Dodaj PostUp = resolvectl dns %i 10.8.0.1; resolvectl domain %i ~. do bloku [Interface] klienta i usuń linię DNS =. Wtedy resolvectl status wg0 powinno wskazywać Default Route: yes.

Którego klienta naprawić najpierw, gdy kilka nie działa?

Napraw jednego klienta Linux, ponieważ jest to jedyna platforma, która pokazuje mechanizm działania. resolvectl status oraz tcpdump informują, który resolver odpowiedział i który interfejs obsłużył pakiet. Aplikacje mobilne i desktopowe stosują te same wartości DNS oraz AllowedIPs bez widocznej konfiguracji, więc gdy klient Linux będzie poprawnie skonfigurowany, będziesz kopiować ustawienia, których poprawność została już zweryfikowana.