Przekierowanie portu iptables nie działa dla localhost

54

Chcę przekierować cały ruch z portu 443 na port wewnętrzny 8080. Korzystam z tej konfiguracji dla iptables:

iptables -t nat -I PREROUTING --source 0/0 --destination 0/0 -p tcp \
         --dport 443 -j REDIRECT --to-ports 8080

Działa to dla wszystkich klientów zewnętrznych. Ale jeśli próbuję uzyskać dostęp do portu 443 z tej samej maszyny, otrzymam błąd odmowy połączenia.

wget https://localhost

Jak mogę rozszerzyć regułę iptables, aby przekierowywać również ruch lokalny?

Chris
źródło
Ten temat zawiera bardziej ogólną odpowiedź: serverfault.com/questions/380447/iptables-preroute-localhost
Jeroen
1
Czy ktoś z rep może dodać ukośnik odwrotny do polecenia przed podziałem wiersza?
Ciro Santilli 18 改造 中心 法轮功 六四 事件

Odpowiedzi:

68

PREROUTING nie jest używany przez interfejs pętli zwrotnej, musisz również dodać regułę OUTPUT:

iptables -t nat -I PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8080
iptables -t nat -I OUTPUT -p tcp -o lo --dport 443 -j REDIRECT --to-ports 8080
Andy
źródło
3
Nie ma potrzeby stosowania pierwszej reguły. Lokalnie generowane pakiety nie przechodzą przez łańcuch PREROUTING.
Khaled,
9
Dodałem początkową regułę ze względu na komplementację, ponieważ chce on również przekierowywać ruch zewnętrzny. Reguła nie potrzebuje źródła / miejsca docelowego, jeśli mówią, że akceptują tylko wszystkie adresy IP
Andy,
przepraszam, nie widziałem twojej odpowiedzi, kiedy odpowiedziałem.
Andy,
Cześć Andy, wciąż otrzymuję połączenie z server.com | <ip> |: 443 ... nie powiodło się: połączenie odrzucone.
Chris
Cześć Chris, czy to połączenie z hostem lokalnym | 127.0.0.1 | 443, czy to domena? Jeśli to drugie i uruchamiasz go z serwera, możesz mieć wewnętrzny problem z routingiem. Możesz dwukrotnie sprawdzić, próbując wget server.com:8080 (chociaż zakładam, że przyczyną przekierowania portów jest to, że jest zablokowany zewnętrznie?). Mój własny VPC ma ten problem, jednak można by to obejść, definiując domenę jako 127.0.0.1 w pliku / etc / hosts.
Andy,
10

Aby przekierować pakiety z hosta lokalnego na inny komputer, reguła:

 iptables -t nat -A OUTPUT -o lo -d 127.0.0.1 -p tcp --dport 443 -j DNAT  --to-destination 10.x.y.z:port

będzie działać, ALE musisz także włączyć tę opcję w jądrze:

sysctl -w net.ipv4.conf.all.route_localnet=1

Bez tego ustawienia jądra nie będzie działać.


źródło
To też by działało. Myślę, że robienie tego wszystkiego w iptables jest czystsze.
quadruplebucky
W rzeczywistości ustawienie jądra jest potrzebne, jeśli miejsce docelowe znajduje się na innym komputerze, na linii maszyny wirtualnej lub na komputerze zdalnym.
nie jest tak, jeśli masz dwie zasady, jak sugerował powyżej Andy.
quadruplebucky
Przepraszam, mówiłem o sprawie przekazania na inną maszynę, na której DNAT nie działa. Szukałem tej odpowiedzi na rozwiązanie problemu, gdy próbowałem przekazać coś, co wydawało się, że łączy się z hostem lokalnym z kontenerem na tej samej maszynie. np. uruchomienie serwera nazw w kontenerze dla zapytań lokalnych.
W rzeczywistości jest to zależne od wersji jądra> = 3.6.
quadruplebucky
3

Co powiesz na to?

iptables -t nat -A WYJŚCIE -d 127.0.0.1 -p tcp --port 443 -j REDIRECT - na port 8080

Athanasios
źródło
2

Powiedziałeś, że otrzymujesz błąd odmowy połączenia . Oznacza to, że nie ma lokalnego procesu nasłuchującego na porcie, z którym próbujesz się połączyć! Aby sprawdzić procesy nasłuchiwania, użyj polecenia:

$ sudo netstat -lnp | grep 8080

Po zastosowaniu reguły powinieneś mieć proces nasłuchujący na porcie 8080, aby się połączyć.

Wydaje się, że zamiast tego powinieneś mieć następującą zasadę:

$ iptables -t nat -I OUTPUT --source 0/0 --destination 0/0 -p tcp
                                       --dport 443 -j REDIRECT --to-ports 8080

Pamiętaj, że wysyłasz z lokalnego hosta. Musisz przekierować pakiet wyjściowy.

Khaled
źródło
1
Dziękuję za odpowiedź. Proces nasłuchuje na porcie 8080. Dlatego chcę przekierować cały ruch do tego portu.
Chris
Czy jesteś pewien, że proces nasłuchuje również na interfejsie pętli? Może nasłuchiwać tylko na interfejsie fizycznym. Zazwyczaj twój serwer będzie musiał słuchać 0.0.0.0 zamiast, powiedzmy, 192.168.10.0
MrMajestyk