Encaminhando pacotes da interface de loopback com o roteamento baseado em política

3

Eu tenho a seguinte regra de iptables:

iptables -t mangle -A PREROUTING -p udp -m udp --dport 10000 -j MARK --set-xmark 0x4/0xffffffff

que define fwmark 4 em todos os pacotes udp com a porta de destino 10000. Encaminho para um encapsulamento (sem qualquer nat) com roteamento baseado em política:

[root@localhost ~]# ip rule
0:  from all fwmark 0x4/0x4 lookup 87 
32765:  from all lookup local 
32766:  from all lookup main 
32767:  from all lookup default 
[root@localhost ~]# ip route show table 87
default dev tunnel  scope link 

Tudo funciona corretamente se o pacote vem de uma NIC normal ( eth0 etc.), mas os pacotes que trafegam na interface de loopback ( lo , por exemplo, pacotes gerados com socat -u - UDP:localhost:10000 ) parecem pular a decisão de roteamento após a corrente PREROUTING , e ser recebido pelo host local (que de fato responde com um pacote de porta ICMP inacessível sobre a interface lo ).

Esse comportamento é esperado? Se sim, como posso resolver isso? Eu preciso que os pacotes não tenham caminhos diferentes para diferentes dispositivos de entrada, pois eu quero usar lo para testar meu conjunto de regras iptables mais complexo (isto é, uma regra extra com nat não será uma solução para mim).

    
por Lorenzo Pistone 29.09.2014 / 18:46

1 resposta

2

Existem algumas coisas envolvidas aqui.

A saída da caixa local usa a tabela OUTPUT , não PREROUTING . PREROUTING é para o tráfego que passa pela caixa.

A regra iptables somente coincide quando um pacote é enviado. Quando o cliente abre uma conexão, ele precisa se ligar a um endereço antes que um único pacote seja gerado. Quando ele liga, ele escolhe o endereço de origem de acordo com as regras de roteamento, sem consultar o iptables.

Quando você testa usando 127.0.0.1 como destino e envia o pacote, ele tenta enviar usando 127.0.0.1 como o endereço de origem, que por padrão o kernel não permite ser roteado.

Se você corrigir esse problema, você terá outro problema quando o pacote deixar a interface e tiver um endereço de origem que o sistema remoto não saiba como retornar.

Assim, a solução é 3 coisas:

1) Adicione a regra à tabela OUTPUT:

iptables -t mangle -A OUTPUT -p udp -m udp --dport 10000 -j MARK --set-xmark 0x4/0xffffffff

2) Ativar roteamento de localnet com:

sysctl -w net.ipv4.conf.$iface.route_localnet=1

onde $iface é sua interface de túnel.

3) Adicione uma regra MASQUERADE para que o endereço de origem do tráfego que sai da interface seja reescrito:

iptables -t nat -A POSTROUTING -o $iface -m addrtype --src-type LOCAL -j MASQUERADE

No entanto, observe que, ao testar o envio de tráfego para 127.0.0.1 , é provável que você encontre problemas. Nada está reescrevendo o endereço de destino, portanto, ele está sendo encaminhado para fora $iface com um destino de 127.0.0.1 . O sistema remoto provavelmente rejeitará esse tráfego.

    
por 29.09.2014 / 19:11