Existem alguns problemas com sua tentativa:
- usando
localhostsignifica 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 regraPOSTROUTINGadicional. Uma correspondência-m conntrack --ctstate DNATopcional verificará se o primeiroOUTPUTfoi 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 regraPOSTROUTINGseja 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_localnetdefinido 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 ).