Wyobraź sobie hosta Linux, który kończy VPN i jednocześnie uruchamia kontener w sieci macvlan. LAN to 192.168.60.0/24, kontener ma 192.168.60.210, a klienci VPN przychodzą z 10.95.0.0/24. Klient dociera do usługi, odpowiedź nigdy nie wraca, a każda reguła firewalla na hoście wygląda poprawnie. Ten objaw tworzą dwa odrębne ograniczenia, a naprawa jednego zostawia drugie na miejscu.

Dwa ograniczenia, jeden objaw

Pierwsze ograniczenie to izolacja: sterownik macvlan Dockera nie pozwala kontenerowi rozmawiać z własnym hostem przez interfejs nadrzędny. Ruch między stosem hosta a kontenerem nie ma drogi, niezależnie od tego, jak zapisano trasy na hoście.

Drugie ograniczenie to droga powrotna. Domyślna brama kontenera to zwykle router LAN, więc odpowiedź adresowana do klienta VPN wychodzi przez ten router. Jeśli router nie ma trasy z powrotem do puli VPN, odpowiedź jest gdzieś po drodze odrzucana.

Oba błędy wyglądają z perspektywy klienta identycznie: żądanie, które dociera, i odpowiedź, która nigdy nie przychodzi. Wymagają różnych napraw, a szeroka reguła masquerade może ukryć, która z nich wciąż jest zepsuta. Dlatego pierwszym testem jest przechwycenie po stronie kontenera, a nie kolejna zmiana firewalla. Jeśli żądanie nigdy się tam nie pojawi, działa ograniczenie izolacji.

Zbuduj shim po stronie hosta, wąsko

Drugi interfejs macvlan na hoście, podłączony do tego samego interfejsu nadrzędnego w trybie mostu, daje stosowi hosta własną tożsamość w tym segmencie LAN. Zarezerwuj dla niego adres poza pulą DHCP i poza zakresem kontenera, i przepuszczaj przez niego tylko kontener.

ip link add macvlan-vpn link eth0 type macvlan mode bridge
ip address add 192.168.60.250/32 dev macvlan-vpn
ip link set macvlan-vpn up
ip route add 192.168.60.210/32 dev macvlan-vpn src 192.168.60.250

Pierwsze polecenie tworzy interfejs w trybie mostu, co jest udokumentowanym ustawieniem domyślnym tego sterownika i trybem, którego chcesz dla ruchu między hostem a kontenerem. Drugie przypisuje /32, aby adres nie kolidował z prefiksem LAN, a czwarte wysyła przez shim tylko adres kontenera.

Nie przekierowuj całego LAN przez nowy interfejs. Zwykła trasa połączona pozostaje bez zmian, a trasa hosta jest celowo wąska, aby jeden kontener zyskał drogę bez zmiany zachowania reszty segmentu. Domyślna trasa wskazująca na shim byłaby innym projektem z innymi konsekwencjami. Trzymaj ją konkretną, a promień szkód pozostaje mały.

Te polecenia zmieniają konfigurację sieci na działającym hoście. Na urządzeniu lub zarządzanej platformie użyj obsługiwanego mechanizmu konfiguracji tej platformy, ponieważ interaktywna zmiana w powłoce root może nie przetrwać aktualizacji.

Zdecyduj, jak zachować źródło

Gdy shim jest na miejscu, kontener może dotrzeć do hosta, a pytanie brzmi, jaki adres źródłowy niesie odpowiedź. Zachowanie oryginalnego źródła VPN to czystszy model: kontener widzi prawdziwy adres klienta, a logi i reguły dostępu usługi mogą go używać.

Aby to działało, konfiguracja sieci kontenera musi dla tej drogi wysyłać ruch 10.95.0.0/24 na 192.168.60.250 jako swoją bramę. To obsługiwane ustawienie trasy lub bramy w konfiguracji samego kontenera, a nie sztuczka po stronie hosta. Potwierdź je od wewnątrz kontenera, zamiast zakładać, że ustawienie zaczęło obowiązywać. Domyślna brama, która nadal wskazuje router LAN, będzie dalej wysyłać odpowiedzi w tę samą dziurę.

Jeśli zatwierdzony projekt zamiast tego ukrywa źródła VPN, zawęź tłumaczenie: prawdziwa pula VPN, shim jako interfejs wychodzący oraz konkretny kontener i usługa.

iptables -t nat -A POSTROUTING -s 10.95.0.0/24 -o macvlan-vpn -j SNAT --to-source 192.168.60.250

Dopasuj shim jako interfejs wyjściowy, a nie tunel. Reguła, która nazywa tunel interfejsem wychodzącym, nie pasuje do pakietu zmierzającego do kontenera, i właśnie ten błąd zwykle zawiera takie zestawienie. Trzymaj regułę tak wąską jak zdanie powyżej i przeglądaj ją, gdy pula się zmieni.

Sprawdzaj z klienta, nie z hosta

Żądanie z samego hosta, przypisane do adresu shim, dowodzi, że shim może dotrzeć do kontenera. Nie dowodzi, że kontener może odesłać ruch do zachowanego źródła 10.95.0.x, ponieważ adres źródłowy w tym teście jest adresem samego shim.

curl -sS --interface 192.168.60.250 -o /dev/null -w '%{http_code}\n' http://192.168.60.210:8080/health
sudo tcpdump -ni macvlan-vpn host 192.168.60.210

Pierwsze polecenie testuje odcinek od hosta do kontenera, a drugie pokazuje, co faktycznie przechodzi przez shim, gdy prawdziwy klient VPN wysyła żądanie. Popatrz na adres źródłowy na drodze wejściowej i na to, czy pojawia się odpowiedź o tym samym przepływie.

Na hoście musi być włączone przekazywanie, a ścieżka przekazywania wymaga zezwolenia dla puli VPN do shim na porcie usługi oraz dla ustanowionych odpowiedzi. Reguła INPUT na hoście nie zezwala na przekazywany ruch, i to częsta przyczyna odrzucenia pakietu po tym, jak routing wygląda poprawnie.

Uruchom prawdziwą aplikację z prawdziwymi poświadczeniami, a następnie sprawdź, czy druga, niepowiązana usługa na tym samym kontenerze nadal cię odrzuca. Jeśli jedynym sposobem, aby to zadziałało, było otwarcie każdej reguły przekazywania, projekt nie jest gotowy. Zanotuj też, jaki adres źródłowy zapisała usługa, bo to jego będą od teraz używać jej własne reguły dostępu.

Powiązane artykuły