Nazwy przestają się rozwiązywać w momencie połączenia VPN, a ping do publicznego adresu nadal odpowiada i status zapory nie pokazuje niczego, co wyglądałoby źle. W polityce nic się nie zmieniło; zmieniło się to, że pojawił się nowy interfejs, a domyślna odmowa obejmuje go od pierwszego pakietu. UFW decyduje według kierunku i interfejsu, więc reguła napisana dla łącza bezprzewodowego nie mówi nic o ruchu wychodzącym z tunelu. Naprawa to garść wąskich reguł zastosowanych w określonej kolejności.

Objaw pojawia się dopiero po wstaniu tunelu

Polityka domyślnej odmowy robi dokładnie to, co jej kazano: wszystko bez pasującej reguły jest odrzucane, na każdym istniejącym interfejsie. Tunel nie istniał, gdy pisano reguły, więc żadna z nich nie może go objąć, a odmowa, która zawsze tam była, dotyczy teraz rozwiązywania nazw. Bezpośredni ruch do dosłownego adresu nadal może działać, gdy obejmuje go szersze zezwolenie, i dlatego ping do publicznego resolvera się udaje, a wyszukiwanie nazwy zawodzi. Luka to reguła dla interfejsu, którego polityka nigdy nie widziała.

To wyjaśnia też, dlaczego awaria odwraca się czysto: zdejmij tunel i nazwy znów się rozwiązują, bo zapytanie wraca do interfejsu, który ma reguły. Polityka, która zawodzi tylko przy wstałym tunelu, nie jest problemem DNS, a dostrajanie samego resolvera marnuje tu najwięcej czasu. Przeczytaj listę interfejsów, zanim przeczytasz konfigurację resolvera.

Trzy kierunki, trzy różne zestawy reguł

Jedna sesja dotyka reguł w więcej niż jednym kierunku, a tunel dodaje drugi interfejs do niemal każdego z nich. Uporządkowanie ruchu najpierw według kierunku i interfejsu czyni resztę mechaniczną, bo każdy wiersz poniżej potrzebuje własnej reguły na własnym miejscu. Przykłady używają tun0 i puli 10.8.0.0/24, więc zastąp nazwy i zakresy tymi z własnego wyjścia klienta.

DirectionExample packetRule that admits itWritten on
Client to the pushed resolverA DNS query to 10.8.0.1Destination port 53 over the tunnelThe client's tun0
Client to the VPN serverA handshake to the server's public addressServer address and port on the physical linkThe client's physical interface
Server to a serviceSSH from the pool to port 22Source pool, destination port, tunnel interfaceThe server's tun0
Anyone to the listenerThe VPN listener itself1194/udp on the public sideThe server's public interface

Dwa wiersze są często mylone, bo oba wspominają tunel. Reguła dla resolvera zezwala na ruch, który klient wysyła do tunelu, natomiast reguła dla SSH zezwala na ruch, który serwer z niego odbiera; żyją na różnych maszynach i zawodzą niezależnie. Najczęściej zapominany wiersz to drugi, bo klient w ogóle nie może zbudować tunelu, dopóki jego ruch do publicznego adresu serwera nie jest dozwolony. Pracuj od góry do dołu, a każda awaria ma jedną możliwą przyczynę.

Wepchnięty resolver potrzebuje własnej reguły

Czy tunel niesie DNS, zależy od tego, co wysyła serwer. Serwer, który wypycha opcję resolvera, instaluje prywatny adres w konfiguracji klienta, a ten adres jest trasowalny tylko przez tunel. Jeśli serwer nic nie wypycha, klient zachowuje resolver, który już miał, a reguły poniżej nie mają czego zezwalać. Sprawdź wypchnięty stan i bieżący wynik zapytania, zanim cokolwiek napiszesz:

dig +short @10.8.0.1 example.com
resolvectl status tun0
sudo ufw status numbered

Wyjście statusu podaje używany resolver i łącze, do którego jest przypisany, a wyszukiwanie trasy za nim pokazuje, który interfejs przeniósłby zapytanie na ten adres. Gdy resolver siedzi na innym łączu, problem jest wcześniejszy niż zapora i żadna reguła nie pomoże. Gdy oba zgadzają się co do tunelu, potrzebne są dwie reguły, bo UDP niesie większość zapytań, a TCP przejmuje, gdy odpowiedź jest ucięta. Zapisz obie wartości, bo to one będą nazywane przez reguły:

sudo ufw allow out on tun0 to 10.8.0.1 port 53 proto udp comment 'pushed resolver'
sudo ufw allow out on tun0 to 10.8.0.1 port 53 proto tcp comment 'truncated answers'

Otwórz drogę zewnętrzną przed wewnętrzną

Klient musi dotrzeć do publicznego adresu serwera, zanim powstanie tunel, więc reguła na to siedzi na łączu fizycznym i musi być na miejscu pierwsza. Polityka, która zezwala resolverowi, ale zapomina o serwerze, zostawia klienta całkowicie niezdolnym do zbudowania tunelu, a ten objaw zwykle zwala się na kill switch. Potem zezwól usługom, których naprawdę chciałeś przez tunel, po jednej wąskiej regule naraz, zamiast otwierać interfejs w całości. Wąskie reguły są powodem, dla którego odmowa może zostać na miejscu.

sudo ufw allow out to 198.51.100.10 port 1194 proto udp comment 'vpn server'
sudo ufw allow out on tun0 to any port 443 proto tcp comment 'web through tunnel'

Kolejność ma znaczenie podczas testów, bo pierwsza reguła jest tym, co w ogóle pozwala tunelowi wstać. Dodaj ją, połącz się i potwierdź, że tunel wstał, zanim dodasz regułę usługi, bo zrobienie obu naraz oznacza, że awaria nie mówi ci nic o tym, która połowa jest zła. Zastąp adres dokumentacyjny powyżej punktem końcowym, dla którego skonfigurowany jest klient.

Zakończ stronę klienta, rozłączając się celowo. Odmowa powinna nadal odrzucać ruch, który celowo wykluczyłeś, bo resolver, który odpowiada przy wstałym tunelu, pokrywa tylko połowę polityki, która w razie wątpliwości odmawia.

Klient, który się łączy, nie jest jeszcze dopuszczony

Serwer ma swój własny kierunek do rozważenia, a klient, który kończy uzgadnianie, nadal nie dociera do niczego, co działa na serwerze, dopóki serwer go nie dopuści. Reguła publicznego listenera pozwala tunelowi tylko istnieć; nie wpuszcza ruchu tunelu. Na serwerze to dwie reguły plus jedno sprawdzenie, czy usługa naprawdę nasłuchuje:

sudo ufw allow 1194/udp comment 'openvpn listener'
sudo ufw limit in on tun0 from 10.8.0.0/24 to any port 22 proto tcp comment 'admin over tunnel'
ss -ltn | grep ':22'

Pula w regule musi być równa zakresowi, który przydziela serwer, a numer tunelu musi odpowiadać temu, który utworzył serwer, bo reguła dla innego interfejsu jest nieodróżnialna od braku reguły. limit jest celowe dla portu administracyjnego, bo ogranicza powtarzane połączenia zamiast przyjmować je bez limitu. Sprawdzenie listenera oddziela zamknięty port od odrzuconego pakietu, które z punktu widzenia klienta wyglądają identycznie. Reguły numerowane też nie są całym obrazem: reguły before UFW i każda ręcznie zapisana linia nftables pasują wcześniej i nadal mogą odrzucić pakiet, który lista zdaje się dopuszczać.

Powiązane artykuły