Jak wykonać przekierowanie portu z jednego adresu IP na inny adres IP w tej samej sieci?

77

Chciałbym zrobić coś NATw iptables. Aby wszystkie pakiety przychodzące 192.168.12.87i 80przesyłane były do 192.168.12.77portu 80.

Jak to zrobić za pomocą iptables?

Lub

Jakieś inne sposoby na osiągnięcie tego samego?

sob
źródło
@Matthewlfe, Z jakiegoś powodu muszę przekazać wszystkie żądania apache z (192.168.12.87) do (192.168.12.77).
sob.
1
@Matthewlfe, mam dwa serwery produkcyjne. Jeden jest połączony z publicznym statycznym adresem IP. Z powodu niektórych problemów z łącznością nie mogę połączyć się z DB i innymi systemami 192.168.12.87. Muszę więc przekazać całą prośbę do 192.168.12.77.
sob.
@lain, nie jestem zaznajomiony z iptables. I widziałem kilka przykładów. Ale wydaje się, że wymagają dwóch sieci Ethernet. Link: revsys.com/writings/quicktips/nat.html
sob.
Możesz również użyć trybu proxy w konfiguracji serwera WWW, aby wysyłać żądania do 192.168.12.77 z 192.168.12.87 (jeśli twój serwer go obsługuje)
krisFR

Odpowiedzi:

74

Te reguły powinny działać, przy założeniu, że iptablesdziałają na serwerze 192.168.12.87:

#!/bin/sh

echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -F
iptables -t nat -F
iptables -X

iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.12.77:80
iptables -t nat -A POSTROUTING -p tcp -d 192.168.12.77 --dport 80 -j SNAT --to-source 192.168.12.87

Musisz DNAT przychodzić z ruchu na porcie 80, ale musisz także SNAT z powrotem ruch.


Alternatywa (i najlepsze podejście IMHO):

W zależności od tego, jaki jest Twój serwer WWW (Apache, NGinx), powinieneś rozważyć serwer proxy HTTP na serwerze front-end (192.168.12.87):

krisFR
źródło
Działa tak długo, jak ufw jest wyłączony, nawet jeśli port zezwala na ufw, ale jeśli ufw jest włączony, to przekazywanie nie działa, jakiś pomysł?
Sudhir N
1
Świetne pytanie z doskonałą odpowiedzią. Innym przypadkiem użycia, który jest przydatny, jest potrzeba tymczasowego przekierowania całego ruchu przychodzącego do jednej usługi, powiedzmy squid, do innego adresu IP / portu, aby wykonać pewne czynności konserwacyjne w stosunku do oryginalnej usługi bez konieczności ponownej konfiguracji wszystkich klientów! Bardzo przydatne!
PF4Publiczny
3
„ale będziesz musiał także ZNISZCZYĆ ruch”. -> Uratowałeś mi dzień. Dziękuję
obayhan
To rozwiązanie nie działa dla mnie. Muszę przekazać z eth0 do sieci wirtualnej (virb0), z której korzysta gość KVM. Próbowałem dodać opcje -i i -o, ale opcja -o nie jest dozwolona w przypadku trasy wstępnej. Jakieś sugestie?
lostiniceland
Uważaj na to rozwiązanie. Całkowicie straciłem dostęp do mojego zdalnego komputera.
Sören,
28

Pozornie oczywistym powodem, dla którego pozornie iptables -t nat -A PREROUTING -d 192.168.12.87 -p tcp --dport 80 -j DNAT --to-destination 192.168.12.77nie będzie działać, jest sposób kierowania pakietów zwrotnych.

Możesz skonfigurować reguły, które spowodują, że pakiety wysyłane do 192.168.12.87 będą po prostu NATowane do 192.168.12.77, ale 192.168.12.77 wyśle ​​odpowiedzi bezpośrednio z powrotem do klienta. Odpowiedzi te nie będą przechodzić przez host, na którym reguła iptables wykonuje translację NAT, stąd pakiety w jednym kierunku są tłumaczone, ale pakiety w drugim kierunku nie.

Istnieją trzy podejścia do rozwiązania tego problemu.

  1. Na pierwszym hoście nie tylko wykonuj DNAT, ale także SNAT, aby ruch powrotny był wysyłany z powrotem przez pierwszy host. Reguła może wyglądać mniej więcej takiptables -t NAT -A POSTROUTING -d 192.168.12.77 -p tcp --dport 80 -j SNAT --to-source 192.168.12.87
  2. Czerp inspirację z równoważenia obciążenia DSR i DNAT pakietów w warstwie Ethernet zamiast w warstwie IP. Zastępując docelowy adres MAC pakietów adresem MAC 192.168.12.77 i wysyłając go w sieci Ethernet bez dotykania warstwy IP, 192.168.12.77 może mieć 192.168.12.87 skonfigurowany na fikcyjnym interfejsie, a zatem być w stanie zakończyć połączenie TCP ze znanym klientowi adresem IP serwera.
  3. Użyj naiwnego (ale nie działającego) rozwiązania na pierwszym hoście. Następnie obsłuż pakiety zwrotne na drugim hoście, wykonując SNAT dla ruchu powrotnego. Reguła może wyglądaćiptables -t nat -A OUTPUT -p tcp --sport 80 -j SNAT --to-source 192.168.12.87

Każde z tych trzech rozwiązań ma wady, więc musisz dokładnie rozważyć, czy naprawdę potrzebujesz tego konkretnego przekazywania.

  1. Użycie SNAT spowoduje utratę adresu IP klienta, więc host nr 2 będzie myślał, że wszystkie połączenia pochodzą od 192.168.12.87. Dodatkowo wykorzystasz przepustowość hosta numer 1 dla wszystkich pakietów odpowiedzi, co przy innych podejściach byłoby bardziej bezpośrednie.
  2. Podejście DSR przerwie wszelką inną komunikację między dwoma węzłami. Podejście DSR jest naprawdę odpowiednie tylko wtedy, gdy adres serwera nie jest podstawowym adresem IP żadnego z hostów. Każdy host musi mieć podstawowy adres IP, który nie jest adresem DSR.
  3. Używanie śledzenia połączenia na jednym hoście do tłumaczenia w jednym kierunku i śledzenia połączenia na innym hoście w celu tłumaczenia w drugim kierunku jest po prostu brzydkie i istnieją różne sposoby, w jakie może się zepsuć. Na przykład, jeśli numery portów są modyfikowane przez NAT na dowolnym hoście, nie ma możliwości ich rekonstrukcji. Nie jest również pewne, że śledzenie połączenia będzie działać poprawnie, jeśli pierwszy pakiet, który zobaczy, to SYN-ACK zamiast ACK.

Myślę, że spośród trzech podejść pierwszy jest tym, który najprawdopodobniej zadziała. Więc jeśli nie musisz znać adresów IP klienta, polecam to.

Możesz także całkowicie zapomnieć o NAT i nie próbować rozwiązać problemu na warstwie MAC lub IP. Możesz przejść aż do warstwy HTTP i poszukać tam rozwiązania. W takim przypadku rozwiązaniem jest serwer proxy HTTP. Jeśli zainstalujesz serwer proxy HTTP 192.168.12.87 i odpowiednio go skonfigurujesz, możesz poprosić go o przesłanie dalej żądań do 192.168.12.77 i przesłanie odpowiedzi z powrotem. Dodatkowo może wstawić nagłówek X-Forwarded-For zachowujący oryginalny adres IP klienta. Serwer 192.168.12.77 należy następnie skonfigurować tak, aby ufał nagłówkowi X-Forwarded-For z 192.168.12.87.

kasperd
źródło
Dziwię się, że -j MASQUERADEnie wspomniano tutaj; czy to nie jest zwykłe podejście w przypadku DNAT?
remram
3
@remram wspomniałem SNATzamiast MASQUERADE, ponieważ tak mówi dokumentacja. Dokładne sformułowanie w dokumentacji to:It should only be used with dynamically assigned IP (dialup) connections: if you have a static IP address, you should use the SNAT target.
kasperd