Wiesz już jak wybrać pakiety do modyfikacji. By skompletować naszą regułę, musimy poinformować jeszcze kernel co zrobić z pasującymi pakietami.
Chcesz prowadzić Źródłowy NAT, czyli zmieniać adresy źródłowe
połączeń na coś innego. Dzieje się to w łańcuchu POSTROUTING, tuż
przed tym jak pakiety zostają wysłane; jest to bardzo ważny szczegół,
ponieważ oznacza że cokolwiek innego na tej maszynie oglądając ten pakiet
(routing, filtrowanie pakietów) będzie widziało go w stanie
jeszcze niezmienionym. Oznacza to, że można również używać opcji
'-o'.
Źródłowy NAT wykonuje się przez wpisanie '-j SNAT',
i dodanie opcji '--to-source', która określa adres lub grupę
docelowych adresów IP; opcjonalnie można również wskazać numer lub
zakres numerów portów (ale tylko dla protokołów TCP i UDP).
## Zmień adres źródłowy na 1.2.3.4.
# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4
## Zmień adres źródłowy na 1.2.3.4, 1.2.3.5 lub 1.2.3.6
# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4-1.2.3.6
## Zmień adresy źródłowy 1.2.3.4, porty z zakresu 1-1023
# iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to 1.2.3.4:1-1023
Jest to specjalizowana odmiana Źródłowego NATu: powinna być używana tylko jeśli masz dynamicznie przydzielany adres IP, tak jak podczas wdzwaniania się (jeśli masz statycznie przydzielony IP, użyj SNAT tak jak opisano to powyżej).
Nie musisz podawać adresów źródłowych by wykonać maskaradę: użyje ona adresu źródłowego interfejsu przez który pakiety będą opuszczały maszynę. Ale co ważniejsze, jeśli połączenie wdzwaniane zostanie zamknięte, połączenia (które i tak już zostały zerwane) zostaną zapomniane, co oznacza mniej zgrzytów w momencie gdy ponownie się wdzwonisz z nowym IP.
## Maskaraduj wszystko wychodzące przez ppp0.
# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
Wykonywany jest w łańcuchu PREROUTING, zaraz po tym jak pakiet
zostaje odebrany, co oznacza że cokolwiek innego na tej maszynie
będzie pracować z pakietem (routing, filtrowanie pakietów), zobaczy
go już skierowanego do 'prawdziwego' adresu docelowego. Oznacza to
również, że można również używać opcji '-i' (interfejs
wejściowy).
Docelowy NAT wskazuje się przez podanie opcji '-j DNAT' i
'--to-destination' która określa pojedyńczy adres lub zakres adresów IP;
opcjonalnie można wskazać port lub zakres portów (ale tylko dla
protokołów TCP i UDP).
## Zmień adresy docelowe na 5.6.7.8
# iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 5.6.7.8
## Zmień adresy docelowe 5.6.7.8, 5.6.7.9 lub 5.6.7.10
# iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 5.6.7.8-5.6.7.10
## Zmień adresy docelowe ruchu WWW na 5.6.7.8, port 8080
# iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 \
-j DNAT --to 5.6.7.8:8080
Jest to specjalizowany przypadek DNAT: dodano go dla wygodny, ponieważ jest to dokładnie to samo co wykonanie DNAT na adres interfejsu wejściowego.
## Wyślij przychodzący ruch WWW na port 80 do naszego transparentnego proxy (squida)
# iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 \
-j REDIRECT --to-port 3128
Zwróć uwagę na to, że squid musi zostać skonfigurowany tak by wiedział że jest transparentnym proxy!
Jest trochę różnych subtelności w NAT z którymi większość użytkowników nigdy nie będzie miała do czynienia. Są one tu udokumentowane dla ciekawskich.
W momencie gdy poda się zakres adresów IP, są one wybierane na podstawie ostatnio używanego IP dla połączeń o których kod wie. Daje to coś na kształt prymitywnego rozkładania obciążenia.
Możesz użyć celu '-j ACCEPT' by pozwolić na przejście
połączenia bez wykonania NAT.
Domyślnym zachowaniem jest zmiana połączenia tylko na tyle ile potrzeba, w granicach reguły podanej przez użytkownika. Oznacza to że nie będziemy remapować portów jeśli wprost tego nie zażądano, chyba że będzie to konieczne.
Nawet gdy dla danego połączenia nie wykonuje się NAT, może się okazać że zostanie wykonana translacja adresu źródłowego, w związku z tym że jest już jakieś połączenie używające tego portu. Rozważmy następujący przykład maskarady, który jest dosyć powszechny:
Kiedy odbywa się takie mapowanie, porty dzielone są na trzy klasy:
Port nie zostanie nigdy zmapowany w tym przypadku do innej klasy.
Jeśli nie istnieje sposób by unikalnie zmapować połączenie na żądanie użytkownika, zostanie ono odrzucone. Dotyczy to również pakietów nie sklasyfikowanych jako część istniejącego połączenia, ponieważ są zniekształcone, maszyna wyczerpała pamięć itd.
Możesz stworzyć reguły NAT które mapują pakiety do tego samego zakresu; kod NAT jest na tyle mądry by uniknąć konfliktów. Oznacza to że dwie reguły mapujące adresy źródłowe 192.168.1.1 i 192.168.1.2 na 1.2.3.4 będzą działać poprawnie.
Co więcej, możesz mapować nawet na realne, używane adresy IP dopóki przechodzą one przez maszynę mapującą. Jeśli masz zatem przydzieloną sieć (1.2.3.0/24), ale masz jedną sieć wewnętrzną używającą tych adresów i jedną używającą zakresu adresów prywatnych 192.168.1.0/24, możesz po prostu wykonać NAT na adresy źródłowe 192.168.1.0/24 do sieci 1.2.3.0, bez strachu że coś rozsypie:
# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 \
-j SNAT --to 1.2.3.0/24
Ta sama logika dotyczy adresów używanych przez samą maszynę prowadzącą NAT: tak właśnie działa maskarada (współdzieląc adres interfejsu pomiędzy pakiety maskaradowane a 'prawdziwe' pakiety wychodzące z tej maszyny).
Co więcej, możesz mapować te same pakiety na wiele maszyn docelowych, i będą one współdzielone. Na przykład, jeśli nie chcesz mapować niczego na 1.2.3.5 możesz napisać:
# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 \
-j SNAT --to 1.2.3.0-1.2.3.4 --to 1.2.3.6-1.2.3.254
Kod wykonujący NAT pozwala na wstawianie reguł wykorzystujących cel DNAT do łańcucha OUTPUT, ale nie jest to w pełni obsługiwane w wersji 2.4 (może być, ale wymaga to nowych opcji konfigurujących, testowania i trochę kodu do dopiania, więc jeśli ktoś nie zleci tego Rusty'emu nie spodziewałbym się tego szybko).
Aktualne ograniczenie polega na tym, że możesz zmieniać tylko adres docelowy na maszynę lokalną (tzn. '-j DNAT --to 127.0.0.1'), a nie na dowolną inną, ponieważ odpowiedzi nie będą prawidłowo tłumaczone.