Ver Feed RSS

root@blog:/# chmod o+r *

[Dica] Problema Comum no Redirecionando com Iptables (NAT & SNAT) - Parte 1/2

Avaliação: 6 votos, 4,17 média.
Recentemente eu tenho visto muitos posts no Forum de proxy/nat/firewall de pessoas que estão passando pela mesma dificuldade ao tentar realizar um redirecionamento para um servidor. Esse problema é muito comum porque muitas vezes agente não pensa no funcionamento detalhado do roteamento nem do que pode ocorrer ao alterar o destino de um pacote com o DNAT. Não entrarei muito a fundo no lógica de como realizar o redirecionamento, deixo isso pra outro post, mas aqui mostrarei como resolver o problema utilizando algumas regras de iptables.

Muitas pessoas quando projetam (ou não) a rede de uma empresa colocam os servidores web, ftp e arquivos (entre outros) na mesma rede dos clientes. Seja por não saber como criar uma rede segmentada, por não querer gastar dinheiro com mais um switch (o que não é exatamente necessário) e placa de rede ou por simplesmente achar que assim é mais cômodo. A verdade é que esse tipo de ambiente não só dificulta, e muito, a implementação de algumas funcionalidades mas também imposibilita a segmentação do trafego e a realização de bloqueios, implicando em brexas de segurança.

Nessa primeira parte vamos trabalhar com um workaround. Na segunda parte dessa série de post irei mostrar um ambiente "ideal".

Cenário 1
Primeiro temos que entender o cenário utilizado. Como dito anteriormente, muitas pessoas colocam um servidor web dentro da rede interna. Nessa caso trataremos a rede interna como sendo a rede 192.168.1.0/24. Mais especificamente, nesse exemplo, nossos hosts da rede interna são o 192.168.1.1 a 192.168.1.9 e nosso servidor web é o 192.168.1.10.
O que muitas pessoas tentam fazer é redirecionar um acesso ao gateway 192.168.1.254 para o servidor web 192.168.1.10. Como os estes estão na mesma rede lógica ocorre um problema curioso. Fiz essa animação em GIF para que as pessoas possam visualizar melhor o que ocorre:


Aposto que ninguém entendeu!! Vamos explicar:

Passo 1
O host deseja se comunicar com o domínio (digamos www.dominio.com.br). O host realiza a consulta DNS e descobri que www.dominio.com.br está vinculado ao IP 192.168.1.254. Com isso o host preenche os campos do pacote e o envia da seguinte forma:
IP de Origem: 192.168.1.1
IP de Destino: 192.168.1.254


Passo 2
O firewall (192.168.1.254) recebe o pacote do host 192.168.1.1 e consulta suas regras de iptables. Lá ele encontra a seguinte regra:
iptables -t nat -A PREROUTING -s 192.168.1.0/24 -i eth0 -d 192.168.1.254 -p tcp --dport 80 -j DNAT --to 192.168.1.10

Como o tráfego bate com a regra (IP de origem, interface de entrada, IP de destino e porta de destino) o firewall faz o que é mandado DNAT para 192.168.1.10, na animação ele pinta o pacote de azul. Para os que não sabem, o DNAT altera o IP de destino no pacote, ficando da seguinte forma:
IP de Origem: 192.168.1.1
IP de Destino:
192.168.1.10 (DNAT)

Enquanto isso o host 192.168.1.1 tá pensando: "Cade a resposta desse 192.168.1.254??"

Passo 3
O servidor web (192.168.1.10) recebe o pacote do host 192.168.1.1 (que na verdade foi encaminhado pelo Firewall) e processa a requisição HTTP. Ao terminar o procesamento ele devolve o pacote. Mas pra quem que ele devolve?? Pra Origem. E quem é a origem? É só consultar o pacote! De acordo com o que vimos, a origem é 192.168.1.1 (veja o fim do passo 2)! Então o servidor WEB, inocentemente envia o pacote diretamente para o host 192.168.1.1 sem que o DNAT fosse desfeito!
Vamos dar uma olhada no pacote de resposta:
IP de Origem: 192.168.1.10
IP de Destino:
192.168.1.1

Agora o desastre final! O host 192.168.1.1 recebe o pacote do servidor web (192.168.1.10) sendo que ele esperava uma resposta do firewall 192.168.1.254. Ao ver essa resposta HTTP do host pensa: "Mas que p***a é essa?! Eu não pedi nada pra esse cara! Ele tá doido?!". Ao ver que a resposta está direcionada a ele mas ele não requisitou nada daquilo ele simplesmente descarta o pacote.
Imagine que você ta em casa e pediu um sanduiche do Bobs mas chega na sua casa o entregador do McDonalds e toca seu interfone, você receberia o sanduíche?!
Enquanto isso o host 192.168.1.1 vai ficar esperando a resposta do 192.168.1.254 que nunca irá chegar. Depois de um timeout ele tentará novamente a conexão e o processo se repetirá.

Pois é! Então esse é o problema do redirecionamento com DNAT dentro de um mesma rede. Agora como contornar...


Cenário 2
Inicialmente esse cenário é exatamente igual ao anterior...



Passo 1
O host deseja se comunicar com o domínio (digamos www.dominio.com.br). O host realiza a consulta DNS e descobri que www.dominio.com.br está vinculado ao IP 192.168.1.254. Com isso o host preenche os campos do pacote e o envia da seguinte forma:
IP de Origem: 192.168.1.1
IP de Destino: 192.168.1.254

Passo 2
O firewall (192.168.1.254) recebe o pacote do host 192.168.1.1 e consulta suas regras de iptables. Lá ele encontra as seguintes regras:
iptables -t nat -A PREROUTING -s 192.168.1.0/24 -i eth0 -d 192.168.1.254 -p tcp --dport 80 -j DNAT --to 192.168.1.10
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -d 192.168.1.254 -p tcp --dport 80 -j SNAT --to 192.168.1.254

Como o tráfego bate com as regra (IP de origem, interface de entrada, IP de destino e porta de destino) o firewall faz o que é mandado DNAT para 192.168.1.10 e SNAT para 192.168.1.254, na animação ele pinta o pacote de azul e verde, uma vez que foram realizadas duas alterações no pacote. Para os que não sabem, o SNAT altera o IP de origem no pacote fazendo parecer que a conexão foi iniciada por outro host. Fica da seguinte forma:
IP de Origem: 192.168.1.254 (SNAT)
IP de Destino:
192.168.1.10 (DNAT)

Passo 3
O servidor web (192.168.1.10) recebe o pacote do host 192.168.1.254 (que na verdade foi encaminhado veio do 192.168.1.1) e processa a requisição HTTP. Ao terminar o processamento ele devolve o pacote pra Origem. E quem é a origem? consultando o pacote vemos que temos que devolver para 192.168.1.254 da seguinte forma:
IP de Origem: 192.168.1.10
IP de Destino:
192.168.1.254

Passo 4
O firewall (192.168.1.254) recebe o pacote do servidor web 192.168.1.10. Como ele possui uma tabela de NAT's realizados ele sabe que esse pacote ele precisa ser alterado. Dessa forma ele nem consulta a tabela de regras NAT do iptables, ele simplesmente restaura a origem/destino do pacote e encaminha. O pacote vai ficar da seguinte forma:
IP de Origem: 192.168.1.254
IP de Destino:
192.168.1.1

O host 192.168.1.1 recebe o pacote do firewall 192.168.1.254. Dessa vez ele recebe o que esperava e a conexão é fechada.

Bem, esse é o problema e o workaround. Com certeza muita gente vai criticar essas regras porque existem diversas formas de se fazer isso. Eu mesmo pensei em pelo menos 3, mas achei essa a mais simples para o entendimento de todos.

Assim que possível estarei postando a segunda parte dessa dica que irá apresentar a solução ideal para um ambiente simples com servidores como esse. Assim que eu tiver ânimo de criar outros GIFs desse...

Enquanto isso, dúvidas, reclamações, sugestões, críticas, agradecimentos ou xingamentos... Utilizem os comentários!!

Até mais...

Atualizado 19-10-2009 em 08:48 por Magnun

Categorias
Linux , Dicas

Comentários

Página 2 de 2 PrimeiroPrimeiro 12
  1. Avatar de Magnun
    To achando que o Irado vai ter que tratar mal uma porrada de gente por um tempo pra conseguir sua reputação de volta...
  2. Avatar de irado
    ROTFL - rss..
    é que vcs não tem ido ao orkut - risos - eu distribuo uns "mimos" por lá (rss)

    legal saber que o GUS-BR vem pra cá, isso vai ser ótimo. Parabéns pra todos vcs
    ps: apesar que.. bem.. rss.. tô mais ligado no CentOS.
  3. Avatar de ivangalves
    Muito bom seu post Magnun ta de parabens.... Continue assim, e repito as palavras de nosso amigo irado : (quando crescer quero ser assim, conhecedor DE VERDADE).
  4. Avatar de skarllot
    Ótimo seu post, facílimo de entender.
    Finalmente entendi e consegui resolver o problema aqui :)

    Só tem uma correção: no cenário 2 a regra de POSTROUTING não deve se basear no destino 192.168.1.254 pois o destino foi alterado pela regra DNAT anterior.
    Atualizado 18-06-2009 em 10:50 por skarllot
  5. Avatar de Não Registrado
    Depois de dias de pesquisa enfim entendi.

    Vitor
  6. Avatar de Crushing
    Sei que o post é antigo mas se alguém puder ajudar agradeço... fiz as regras corretamente, tal e qual descrito aqui. O problema é que parece que o connection tracking não funciona nesse caso, o meu servidor web está respondendo para o gateway porém o mesmo não encaminha para o host que fez a requisição.

    Alguma luz? Desde já agradeço a qualquer resposta.
  7. Avatar de skarllot
    [QUOTE=Crushing;bt8541]Sei que o post é antigo mas se alguém puder ajudar agradeço... fiz as regras corretamente, tal e qual descrito aqui. O problema é que parece que o connection tracking não funciona nesse caso, o meu servidor web está respondendo para o gateway porém o mesmo não encaminha para o host que fez a requisição.

    Alguma luz? Desde já agradeço a qualquer resposta.[/QUOTE]

    Acredito que basicamente é assim:
    Rede Interna -- eth0 -- [ Firewall ] -- eth1 -- Internet

    iptables -t nat -A POSTROUTING -s $RedeInterna -o eth1 -j SNAT --to $IpExterno
    iptables -t nat -A PREROUTING -d $IpExterno --dport $PortaExterna -j DNAT --to $IpInterno:$PortaInterna
  8. Avatar de Biondi
    Bom dia Pessoal,


    Esta semana tive um problema semelhante e por essa razão cheguei a esse tópico. Como é um assunto que causa uma certa confusão, resolvi compartilhar a solução que encontrei, pode ser que ajude alguém.


    Cenário:


    Foi desenvolvido um portal de vendas para acesso aos vendedores externos pela Web, mas era necessário que os usuários da rede interna também alcançassem esse servidor Web de dentro da rede, utilizando o IP externo.




    A solução encontrada está funcionando 100%:


    IP_externo - IP publico da sua internet
    IP_interno - Ip da sua rede que esta configurado no seu servidor de aplicacao
    Porta_da_aplicação - (no caso é um servidor WEB que responde em uma porta não padrão)


    Adicione no seu firewall Iptables as linhas a seguir:


    1) Para que o pacote alcance o destino:


    $IPTABLES -t nat -A PREROUTING -d IP_externo -p tcp --dport Porta_da_aplicacao -j DNAT --to IP-interno:Porta_da_aplicacao


    2) Para que o pacote retorne para a máquina de origem:




    $IPTABLES -t nat -A POSTROUTING -d IP-interno -p tcp --dport Porta_da_aplicacao -j SNAT --to IP_externo


    Seu Firewall deve conter a linha abaixo para ativar o roteamento de pacotes, caso contrario adicione no inicio do arquivo, antes das regras de roteamento.


    echo 1 > /proc/sys/net/ipv4/ip_forward




    *Para esta regra funcionar adequadamente, seu IP Público deve ser Fixo
Página 2 de 2 PrimeiroPrimeiro 12

+ Enviar Comentário