iptables DNAT do loopback

2

Estou tentando entender as limitações de usar o iptables DNAT com endereços de loopback. Considere que temos um aplicativo que pode se conectar apenas a 127.0.0.1; A solução óbvia para fazer com que o servidor e o cliente funcionem em nós diferentes é usar o NAT da seguinte forma:

Certifique-se de que todos os pacotes de saída tenham o endereço IP do host principal do cliente:

iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source <CLIENT_IP>

Agora vamos tentar enganar o cliente e a DNAT como uma conexão com o mundo exterior:

iptables -t nat -A OUTPUT -d 127.0.0.1/32 -p tcp -m tcp --dport <SERVICE_PORT> -j DNAT --to-destination <SERVER_IP>

Infelizmente, isso simplesmente não funciona. Ao tentar se conectar ao programa 127.0.0.1:<SERVICE_PORT> , apenas fica pendurado em connect syscall. O interessante é que não consigo ver nenhum pacote SYN em nenhuma interface ( tcpdump -qn -i any port <SERVICE_PORT> ), no entanto, vejo os contadores de pacotes aumentarem ao olhar para as estatísticas do iptables ( iptables -nvL -t nat ).

Pesquisando na solução Encontrei uma opção de compilação do kernel CONFIG_IP_NF_NAT_LOCAL , que foi usada nos kernels 2.6.0-2.6.10 para resolver o problema de usar o NAT com conexões localmente originadas. Infelizmente, a atual árvore do kernel git contém informações para as versões 2.6.11 e posteriores, então eu acabei aqui.

Olhando ainda, encontrei este tópico , referente a correções de algum DNAT em problemas de loopback em 2.6.11; um dos patches remove a opção CONFIG_IP_NF_NAT_LOCAL build e ativa o código incondicionalmente ( aqui está o diff real ).

No entanto, o estado atual deste problema não é claro para mim. Eu gostaria de encontrar algumas explicações ou referências provando que isso é um bug do kernel ou algum recurso não tão bem documentado. Eu sei que o roteamento de rede 127.0.0.0/8 é tratado pelo kernel de uma maneira especial, mas a partir da documentação do iptables é claro que a cadeia de saída de tabela nat é o único lugar que faz sentido para esse tipo de regras e não declara exceções ou qualquer tipo de notas sobre a rede 127/8.

Por favor, abstenha-se de aconselhar algumas soluções alternativas com ferramentas de terceiros, eu já tenho alguns, eu só quero ter alguma explicação porque esta configuração exata não funciona e porque não deve funcionar. Qualquer exemplo de como este DNAT pode ser feito com qualquer outra regra do iptables é bem-vindo.

A configuração acima foi testada no Debian squeeze e wheezy, com kernels 2.6.32, 3.1.0, 3.2.0.

    
por artyom 26.02.2012 / 19:05

1 resposta

1

Cavar um pouco mais fundo revela alguma confirmação de que o comportamento mencionado é totalmente correto.

De acordo com a RFC 5735, a rede 127.0.0.0/8 não deve ser roteada fora do próprio host:

127.0.0.0/8 - This block is assigned for use as the Internet host loopback address. A datagram sent by a higher-level protocol to an address anywhere within this block loops back inside the host. This is ordinarily implemented using only 127.0.0.1/32 for loopback. As described in [RFC1122], Section 3.2.1.3, addresses within the entire 127.0.0.0/8 block do not legitimately appear on any network anywhere.

RFC 1700 , página 5 também declara que estes endereços «nunca devem aparecer fora de um host ».

RFC 1812, seção 5.3.7 Filtragem de endereços marciana declara que «o roteador NÃO DEVE encaminhar , exceto em uma interface de loopback, qualquer pacote que tenha um endereço de origem na rede 127, que é exatamente o meu caso.

Com relação a essas referências, presumo que o caso do primeiro post seja uma característica, e o comportamento oposto seria uma violação de padrões.

    
por 27.02.2012 / 15:45