Existem alguns problemas com sua tentativa:
- usando
localhost
significa que conexões são iniciadas a partir do host, não roteadas de outro host. Assim, é necessária a cadeiaOUTPUT
, não a cadeiaPREROUTING
, pois o roteamento não estava envolvido inicialmente. - o IP de origem, que seria
127.0.0.1
, também deve ser alterado quando o destino for alterado. Isso requer uma regraPOSTROUTING
adicional. Uma correspondência-m conntrack --ctstate DNAT
opcional verificará se o primeiroOUTPUT
foi correspondente primeiro e se não é uma tentativa de falsificação. - Pelo menos no Linux
127.0.0.0/8
é tratado especialmente na pilha de roteamento, e o pacote será descartado antes que a regraPOSTROUTING
seja acionada. Para remover o tratamento especial e permitir o roteamento "fora" do bloco127.0.0.0/8
, a interface na qual o redirecionamento ocorrerá deve ter o sinalizadorroute_localnet
definido como 1, ou nenhuma das opções acima será o suficiente.
Como a interface não é conhecida a partir da pergunta, o nome da interface é recuperado da rota e colocado em uma variável. Adapte-o, se necessário. Você também pode usar a all
pseudo-interface para definir o bandeira globalmente.
Então, no final, isso se resume a (como root ou usando sudo
):
iptables -t nat -A OUTPUT -p tcp --dport 9099 -j DNAT --to-destination 172.17.0.2:8080
iptables -t nat -A POSTROUTING -s 127.0.0.0/8 -d 172.17.0.2 -m conntrack --ctstate DNAT -j MASQUERADE
interface=$(ip -o route get 172.17.0.2 | grep -o 'dev [^ ][^ ]*'|sed 's/^dev //')
echo 1 > /proc/sys/net/ipv4/conf/$(interface)/route_localnet
Depois de tudo isso dito, você deve tentar usar um endereço que não seja 127.0.0.0/8
, ainda local para o host. Isso poderia simplificar as coisas, não exigindo route_localnet
(e possivelmente, às vezes, não exigindo a regra adicional POSTROUTING
).