iptables REDIRECT funciona apenas para o primeiro pacote

1

Eu preciso redirecionar todos os pacotes UDP com a porta de destino 15000 para a porta 15001 se o pacote contiver, por exemplo, a string test . Eu tenho essas duas regras simples:

iptables -t nat -A PREROUTING -i eth0 -p udp --dport 15000 -m string --string 'test' --algo bm -j LOG --log-prefix='[netfilter] '
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 15000 -m string --string 'test' --algo bm -j REDIRECT --to-ports 15001

Os comportamentos estranhos:

  • se o primeiro pacote contiver test string, o redirecionamento será feito para todos os pacotes da conexão;
  • se o primeiro pacote da conexão não contiver test , o redirecionamento nunca será feito, mesmo que um pacote subseqüente contenha test

No entanto, todos os pacotes que correspondem à regra são registrados corretamente.

Eu tentei adicionar também as informações da faixa à regra:

-m state --state NEW,ESTABLISHED

mas o comportamento é o mesmo. Algumas ideias?

Este é o conjunto de regras iptables completo:

tabela de filtros:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination  

tabela nat:

Chain PREROUTING (policy ACCEPT)
 target     prot opt source               destination         
 LOG        udp  --  anywhere             anywhere             udp dpt:15000 STRING match  "test" ALGO name bm TO 65535 LOG level warning prefix "[netfilter] "
 REDIRECT   udp  --  anywhere             anywhere             udp dpt:15000 STRING match  "test" ALGO name bm TO 65535 redir ports 15001

 Chain INPUT (policy ACCEPT)
 target     prot opt source               destination         

 Chain OUTPUT (policy ACCEPT)
 target     prot opt source               destination         

 Chain POSTROUTING (policy ACCEPT)

tabela de mangle:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination  

tabela bruta:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
    
por MirkoBanchi 06.12.2015 / 14:50

2 respostas

3

As regras da tabela nat sempre funcionam apenas para o primeiro pacote em conexão. Pacotes subseqüentes da mesma conexão nunca atravessam a lista de regras nat e são suportados apenas pelo código conntrack

Como o UDP é sem conexão, a "conexão" aqui é definida simplesmente por endereços, portas e tempo limite. Assim, se o segundo pacote UDP com a mesma porta e endereço de origem e a mesma porta e endereço de destino chegar dentro do tempo limite, o Linux acredita que pertence à "conexão" estabelecida e não avalia a tabela de regras nat para ela, reutilizando o veredicto emitido para anterior pacote.

Veja aqui: link

    
por 06.12.2015 / 15:17
3

Isso é causado pelo fato de o iptables aplicar rastreamento de conexão em PREROUTING chain. Sempre que uma nova conexão é feita, o iptables consultará o cache conntrack. Se uma correspondência for encontrada, nenhuma regra será aplicada na tabela nat.

Se você quiser desabilitar esse comportamento, desative NOTRACK target na tabela bruta.

Por favor, note que isso se aplica mesmo para UDP (que é um protocolo sem conexão). O primeiro pacote é considerado como conexão de abertura NEW e o outro é uma resposta ESTABLISHED .

Encontrei uma postagem relacionada no serverfault .

    
por 06.12.2015 / 15:09