Ktoś przekierowuje 1723, klient dociera do serwera, zaczyna się uwierzytelnianie i nagle wszystko się zatrzymuje bez błędu. Naturalny wniosek to błędne hasło, więc hasło wpisuje się trzy razy. Przekierowanie było w porządku i dane logowania były w porządku. Zepsuł się drugi protokół, którego przekierowanie nigdy nie obejmowało, oraz domyślne ustawienie jądra, które po cichu przestało w nim pomagać.

Przekierowanie nigdy nie było problemem

Reguła przekierowania portu opisuje ruch TCP lub UDP. Nie opisze ładunku, który w połowie sesji przechodzi na inny protokół IP, a PPTP robi dokładnie to.

Dlatego połączenie wygląda zdrowo aż do momentu zawieszenia. Część, którą reguła portu może rządzić, powiodła się, a część, której rządzić nie może, to właśnie ta, która zawiodła.

TCP do sterowania, GRE do danych

Połączenie jest negocjowane przez TCP 1723. Gdy już stoi, ładunek przechodzi do GRE, protokołu IP 47, który w ogóle nie niesie numerów portów. Reguła oparta na portach nie ma czego dopasować.

GRE niesie natomiast identyfikator wywołania w swoim nagłówku, a translator NAT musi przepisywać to pole spójnie w obu kierunkach, inaczej dwie połowy sesji przestają się zgadzać. Przepisany jeden kierunek, a drugi nie, daje sesję, która się uwierzytelnia, a potem odrzuca każdy pakiet danych. Dokładnie taki jest kształt objawu: sukces, potem cisza.

Goły GRE bez PPTP nie wymaga takiego przepisywania, dlatego zwykły tunel GRE może działać przez router, który zawodzi dla klienta PPTP na tej samej drodze.

Cztery moduły i sysctl, który je wyłączył

Dwa moduły obsługują ramkowanie, nf_conntrack_proto_gre i nf_nat_proto_gre. Kolejne dwa obsługują identyfikator wywołania, nf_conntrack_pptp i nf_nat_pptp. Wczytanie ostatniego wciąga pozostałe przez zależności, więc lista modułów powinna pokazywać wszystkie cztery.

Starsze instrukcje używają przedrostka ip_ z ery 2.6. Te polecenia mogą wyglądać, jakby działały, nie wczytując niczego, więc sprawdzaj listę wczytanych, a nie kod wyjścia.

Wczytanie ich już nie wystarcza. Od Linuksa 4.7 sysctl net.netfilter.nf_conntrack_helper ma domyślnie 0, co wyłącza automatyczne przypisywanie pomocników nowym strumieniom. Router może mieć wszystkie moduły i nadal nic nie tłumaczyć. Sprawdź wartość efektywną, zanim znów spojrzysz na listę modułów.

Albo włącz automatyczne przypisywanie z powrotem globalnie, albo podłącz pomocnika do strumieni, które go potrzebują, a resztę zostaw w spokoju:

iptables -t raw -A PREROUTING -p tcp --dport 1723 -j CT --helper pptp

Druga opcja jest lepsza. Ogranicza zachowanie do ruchu PPTP, zamiast ponownie włączać automatyczne przypisywanie na całym routerze.

Otwieranie protokołu, który nie ma portów

Reguła zapory, która pozwala na 1723, nie mówi nic o protokole 47. W firewalld zezwól na protokół w strefie zwróconej do klienta. W zwykłym iptables przyjmij protokół gre w łańcuchu wejścia.

Potem przechwyć po obu stronach. Pakiety wychodzące od klienta bez nadchodzących odpowiedzi oznaczają, że droga powrotna jest filtrowana, a to inna usterka niż odrzucone dane logowania.

Po połączeniu limit rozmiaru

GRE wstawia nagłówek, a PPP w nim dodaje więcej, więc działające łącze zgłasza MTU znacznie poniżej 1500. Małe odpowiedzi się wczytują, a duże zacinają, co wygląda na drugi, niepowiązany problem pojawiający się w chwili rozwiązania pierwszego.

Odczytaj MTU na adapterze PPP klienta i uzgodnij ją z własnym wyliczeniem routera zamiast obniżać liczby, aż coś zadziała. Pakiety pełnego rozmiaru, które wychodzą, a nic nie wraca, wskazują na ten limit, a nie na tłumaczenie.

Naprawa ścieżki przywraca użytkownika do pracy i nie czyni PPTP dobrym wyborem. MS-CHAPv2 i RC4 są dawno przestarzałe, więc traktuj wczytanie modułów jako tymczasową poprawkę i zaplanuj przejście na utrzymywany protokół.

Powiązane artykuły