Você deseja usar o alvo REDIRECT do iptables.
iptables -t nat -A OUTPUT -p tcp -d 1.2.3.4 --dport 80 -j REDIRECT
A página de manual iptables especifica uma única opção para REDIRECT que permite alterar a porta.
Essa opção é --to-ports
.
Existe uma maneira de redirecionar o tráfego definido para sair do servidor para outro IP, de volta para o servidor no host local (de preferência como se estivesse vindo do destino original)?
Basicamente, gostaria de poder configurar meu próprio software que escuta, digamos, a porta 80 e recebe o tráfego que foi enviado para dizer, 1.2.3.4.
Então, como um exemplo com algum código. Aqui seria o servidor:
my $server = IO::Socket::INET->new(
LocalAddr => '127.0.0.1',
LocalPort => '80',
Listen => 128,
);
E isso receberia tráfego do seguinte cliente:
my $client = IO::Socket::INET->new(
PeerAddr => 'google.com',
PeerPort => '80',
)
Então, em vez de o cliente estar se conectando ao google.com, ele estaria se conectando ao servidor que estou escutando no host local para o mesmo servidor.
Minha intenção é usar isso para detectar malwares que se conectam a hosts remotos.
Eu não preciso especificamente que o tráfego seja redirecionado para 127.0.0.1, mas ele precisa ser redirecionado para um IP que a mesma máquina possa ouvir.
Editar: Eu tentei o seguinte, e não funciona -
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 127.0.0.1:80
iptables -t nat -A POSTROUTING -j MASQUERADE
Pelo que entendi, você poderia usar o recurso TPROXY iptables e os soquetes IP_TRANSPARENT para obter um redirecionamento totalmente transparente (sem envolver o NAT). Dessa forma, seu aplicativo criará um soquete especial que aceitará tráfego mesmo se o IP de destino for outra caixa e usará as regras iptables para redirecionar o tráfego com a porta de destino 80 na porta 80 da primeira interface local, sem alterá-lo em tudo.
iptables -t mangle -A PREROUTING -i eth0 -p tcp -m tcp -d 1.2.3.4 --dport 80 -j TPROXY --on-port 80
Isso é usado no Squid Proxy para operar no modo totalmente transparente sem fazer qualquer NAT, portanto não alterando um único byte do pacote. Lembre-se que você tem que usar uma tomada especial para isso, senão não funcionará!
Apenas no caso, extrair documentos do Kernel sobre como abrir um soquete tproxy:
fd = socket(AF_INET, SOCK_STREAM, 0);
/* - 8< -*/
int value = 1;
setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
/* - 8< -*/
name.sin_family = AF_INET;
name.sin_port = htons(0xCAFE);
name.sin_addr.s_addr = htonl(0xDEADBEEF);
bind(fd, &name, sizeof(name));