Zachowaj lub użyj SNAT na adresach IP klientów VPN na granicy chmury
Zachowanie źródła utrzymuje tożsamość klienta w każdym logu, SNAT utrzymuje małą tabelę routingu. Trzy warunki mówią, czego potrzebuje aplikacja.
Utrzymanie adresu klienta VPN aż do aplikacji sprawia, że każda linia logu i każdy wpis na liście dozwolonych znaczą to samo. Przepisywanie go na granicy chmury upraszcza tabelę routingu i czyni logi mniej użytecznymi. Żaden z wyborów nie jest sam w sobie błędny, a argument, który go rozstrzyga, rzadko dotyczy wydajności. Rozstrzygają trzy warunki: czy aplikacja musi wiedzieć, która osoba się połączyła, czy tkanina chmury zaakceptuje źródło, które zamierzasz wysłać, i kto później weźmie odpowiedzialność za trasę powrotną.
Rozstrzygają trzy warunki
Zacznij od wymagania aplikacji, a nie od diagramu sieci. Jeśli autoryzacja lub audyt zależą od indywidualnego adresu klienta, to jego zachowanie jest wymogiem funkcjonalnym, a tłumaczenie regresją. Jeśli aplikacja musi tylko wiedzieć, że ruch przyszedł ścieżką dostępu zdalnego, wystarczy przetłumaczony adres i jest to znacznie tańsze w utrzymaniu.
Drugi warunek jest mechaniczny. Sieć wirtualna nie ufa automatycznie pakietowi, który twierdzi, że adres nie został przypisany interfejsowi wysyłającemu. Większość tkanin chmury wymusza to na różne sposoby i pod różnymi nazwami, a projekt, który to ignoruje, będzie wyglądał poprawnie na diagramie i po cichu zawiedzie na produkcji.
Trzeci jest organizacyjny. Zachowanie źródeł oznacza, że tabela routingu podsieci aplikacji musi wskazywać z powrotem na bramę dla prefiksu klienta, a każdy zespół, który później doda podsieć, musi utrzymać tę trasę spójną. To jednorazowo mały koszt i koszt powtarzający się w dziesiątkach kont. Zdecyduj, kto go ponosi, zanim obiecasz to zachowanie.
Trasa nie jest pozwoleniem na podszywanie się
Dodanie trasy powrotnej mówi twojej podsieci, dokąd mają trafiać odpowiedzi. Nie mówi tkaninie, że instancja przekazująca te pakiety ma prawo wysyłać je z obcym źródłem. W AWS odpowiednią kontrolą jest sprawdzanie źródła i celu, i jest ono widoczne dla każdej instancji:
aws ec2 describe-instances --instance-ids i-0a1b2c3d4e5f60718 \
--query "Reservations[].Instances[].SourceDestCheck"
aws ec2 modify-instance-attribute --instance-id i-0a1b2c3d4e5f60718 \
--no-source-dest-check
Wyłącz je tylko dla instancji, której udokumentowanym zadaniem jest przekazywanie, i dla niczego innego. Każda maszyna wirtualna aplikacji, która zostawia to sprawdzanie włączone, to o jedną maszynę mniej, której można użyć do wysyłania ruchu z pożyczonym źródłem. Jeśli twoja platforma nie jest AWS, poszukaj równoważnego ustawienia anty-podszywania się lub dozwolonych adresów, zamiast zakładać, że zachowanie się przeniesie.
Szybkie przechwycenie pakietów rozstrzyga pytanie szybciej niż czytanie konsoli. Jeśli odpowiedzi wychodzą, a klient nigdy ich nie widzi, to tkanina odrzuca podrobione źródło, a nie aplikacja zawodzi.
Co kupuje tłumaczenie i ile kosztuje
Przepisanie źródła na bramie usuwa problem trasy powrotnej. Aplikacja widzi jeden adres, do którego już wie, jak dotrzeć, a prefiks klienta nigdy nie musi pojawiać się w tabeli routingu chmury. W Linuksie reguła to jedna linia i warto napisać najwęższą wersję, jaką potrafisz:
sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -s 172.20.8.0/24 -o ens5 -j SNAT --to-source 10.40.3.10
Zwróć uwagę, co aplikacja teraz zapisuje: 10.40.3.10 dla każdego użytkownika, przy każdym połączeniu, na zawsze. Każda lista dozwolonych adresów zbudowana na tej wartości daje teraz dostęp całej populacji dostępu zdalnego, a każdy przegląd incydentu musi wrócić do bramy, aby odpowiedzieć, kto to był.
Rozwiązaniem nie jest porzucenie tłumaczenia, lecz zaprzestanie udawania, że adres jest tożsamością. Noś tożsamość klienta w uwierzytelnionym polu, zapisuj ją na bramie razem z przetłumaczoną krotką i pozwól aplikacji się na niej łączyć. Bez klucza łączenia tłumaczenie zamienia problem sieciowy w trwały problem kryminalistyczny.
Przekaźnik to inny interfejs
Odwrotne proxy przed aplikacją całkowicie omija kwestię trasy routowanej. Proxy otwiera własne połączenie z backendem, więc prefiks klienta nigdy nie musi być trasowalny w sieci wirtualnej, a aplikacja może otrzymać tożsamość w nagłówku, który ustawia proxy.
Ten nagłówek jest wiarygodny tylko wtedy, gdy backend przyjmuje go od proxy i od niczego innego. W terminach nginx oznacza to nazwanie zaufanego partnera wprost, zamiast wierzyć we wszystko, co przychodzi:
set_real_ip_from 10.40.3.10;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
Każdy klient, który może dotrzeć do backendu bezpośrednio, może podrobić ten sam nagłówek, więc backend musi być nieosiągalny poza proxym. To fakt zapory sieciowej, a nie opinia o konfiguracji, i właśnie to założenie ludzie pomijają, kopiując fragment.
Przekaźnik zmienia też to, co kupujesz. Otrzymujesz tożsamość na poziomie aplikacji i naturalne miejsce, by ją zapisywać; rezygnujesz z ogólności, bo każdy nowy protokół potrzebuje własnego wsparcia proxy. Dla usług HTTP ta wymiana jest zwykle dobra, a dla wszystkiego, co nie jest HTTP, zwykle w ogóle nie jest dostępna.
Zapisz, co widzi każda granica
Cokolwiek wybierzesz, przegląd projektu powinien kończyć się jedną tabelą, która nazywa adres źródłowy i dowodliwą tożsamość na każdym skoku. Bez niej pierwszy incydent daje trzy zespoły, z których każdy opisuje innego klienta.
| Boundary | Source the next hop sees | What is actually proven |
|---|---|---|
| Client to gateway | 172.20.8.14 | A certificate or credential was presented |
| Gateway to app subnet, preserved | 172.20.8.14 | The same session, if the return route exists |
| Gateway to app subnet, translated | 10.40.3.10 | Only that traffic came through the gateway |
| Proxy to backend | 10.40.3.10 plus a header | The proxy asserted an identity it authenticated |
Potem wybierz. Zachowaj źródło, gdy autoryzacja aplikacji naprawdę zależy od adresu klienta i możesz wziąć trasę na siebie. Tłumacz, gdy tak nie jest i możesz nieść tożsamość poza pasmem, a do ustawień przekazywania specyficznych dla platformy użyj wskazówek AWS dotyczących instancji przekazujących. Sięgnij po przekaźnik, gdy usługa mówi po HTTP i chcesz, aby tożsamość przestała być adresem.