Port Forward mais completo: caçando o fantasma da rede interna

Este artigo explica como entender e resolver um problema que ocorre frequentemente quando se utiliza apenas as regras tipo DNAT para fazer port forward: não se consegue acessar da rede interna pelo IP redirecionado. Avaliando-se o caminho que os pacotes fazem, pode-se fazer o troubleshooting do problema e resolvê-lo de vez.

[ Hits: 18.320 ]

Por: André Sousa em 07/04/2010


Entendendo o problema



"Houston, we have a problem!"

Problema

Um cliente solicitou que fosse feito um redirecionamento das portas 80 e 443 para um servidor web que se encontra na rede interna da empresa, pois os consultores externos iriam iniciar os testes no novo sistema.

No firewall foi adicionada uma regra de redirecionamento (os usuários do IPTables conhecem como DNAT), você testou e está tudo ok!

Ao solicitar o teste por parte do cliente, ele lhe diz que não consegue fazer o acesso.

Causa

A causa deste problema está no percurso em que o pacote percorre quando o servidor responde à requisição de uma estação que está na rede interna.

Observe na figura 1 o caminho que é feito pelo pacote quando há uma requisição de fora da rede interna:

Obs.: Os endereços contidos neste documento são aleatórios, apenas para demonstração.
Linux: Port Forward mais completo: Caçando o fantasma da rede interna.
Figura 1
Neste caso o mesmo caminho é percorrido tanto na ida quanto na volta. O pacote consegue ir e voltar sem nenhum empecilho.

Observe agora na figura 2 como isto ocorre quando a requisição é feita da rede interna:
Linux: Port Forward mais completo: Caçando o fantasma da rede interna.
Figura 2
Podemos verificar que o caminho percorrido é diferente. O servidor não encaminha o pacote de resposta para o seu gateway. Vejamos mais detalhadamente o caminho que o pacote percorre:
  1. A estação solicita conexão (pacote com flag SYN ativado) para o IP 200.254.225.31.
  2. O firewall modifica o destination ip para fazer o port forward (novo destination: 172.15.25.3).
  3. O servidor recebe o SYN packet e responde com pacote de aceite da conexão (pacote com os flags SYN e ACK ativados) para o IP da estação (172.15.25.100).
  4. Na tabela de roteamento do servidor este pacote é redirecionado para o barramento, pois tem como destino um IP da mesma rede que ele está conectado, sem passar pelo gateway.
  5. A estação recebe o pacote SYN/ACK e, após verificar que não está esperando resposta de conexão deste host (172.15.25.3), mas sim do host (200.254.225.31), ele descarta o pacote.
  6. Após o período de timeout da conexão, esta é descartada.

Aplicando uma solução

Uma solução que pode ser utilizada neste caso é criar uma regra que modifique o source address do pacote durante o caminho de ida. Seria como mascarar o pacote que venha da rede interna e tenha destino o IP e porta do servidor.

Vou exemplificar com regras do IPTables. Porém, para um melhor entendimento desta regra, é melhor darmos uma olhada no caminho que o pacote percorre nas chains e tabelas do IPTables.
Linux: Port Forward mais completo: Caçando o fantasma da rede interna.
Figura 3
(fonte: Iptables Tutorial 1.1.19, Chapter 3)

Bom, para o DNAT, utilizamos:

# iptables -p tcp -t nat -A PREROUTING -d 200.254.225.31 --dport 80 -j DNAT --to-destination 172.15.25.3:80

As regras de DNAT são aplicadas na tabela NAT, chain PREROUTING. As de SNAT, na tabela Nat e chain POSTROUTING.

Analisando a figura 3, vemos que quando o pacote chega na chain POSTROUTING, ele já passou pela PREROUTING. Desta forma o seu destination já foi alterado. Então a nossa regra tem que filtrar os pacotes vindo de toda a rede interna (ou um ip dela, a depender do caso) com destino o servidor (dentro da rede interna também) na porta 80, e não o IP 200.254.225.31.

Segue a regra:

# iptables -p tcp -t nat -A POSTROUTING -s 172.15.25.0/100 -d 172.15.25.3 --dport 80 -j SNAT --to-source 200.254.225.31

Após isto, basta permitirmos o tráfego do pacote na tabela filter, chain FORWARD e pronto, está tudo funcionando corretamente. Segue a regra:

# iptables -p tcp -t filter -A FORWARD -s 172.15.25.0/100 -d 172.15.25.3 --dport 80 -j ACCEPT

Veja como ficou o novo desenho na figura 4:
Linux: Port Forward mais completo: Caçando o fantasma da rede interna.
Figura 4
Notem que agora a estação recebe o pacote SYN/ACK do mesmo IP que ele havia solicitado antes.

Esta lógica pode ser utilizada para demais ferramentas de firewall, bastando estudar antes como o pacote trafega dentro dele para assim gerar as regras necessárias. O resto, a lógica é a mesma.

Obs.: Este artigo foi publicado originalmente por mim em:
   

Páginas do artigo
   1. Entendendo o problema
Outros artigos deste autor
Nenhum artigo encontrado.
Leitura recomendada

Endian Firewall - Solução completa para um servidor de internet

Script de Firewall com redirecionamento de portas em Linux Debian

Squid + iptables (método ninja)

Incrementando seu Firewall com o Layer 7 Filter

Entendendo a teoria do iptables

  
Comentários
[1] Comentário enviado por grandmaster em 07/04/2010 - 18:44h

Legal para a galera conhecer o funcionamento.

--
Renato de Castro Henriques
ITILv3 Foundation Certified
CobiT Foundation 4.1 Certified ID: 90391725
http://www.renato.henriques.nom.br


[2] Comentário enviado por rogeriojlle em 07/04/2010 - 22:53h

Muito boa essa sua dica, boa mesmo, aqui no meu trabalho, chegamos ao mesmo resultado colocando todos os servidores que esperam conexões tanto da rede local quanto da internet numa faixa de ip diferente das duas "zonas" ,mas acho que é o que a maioria das pessoas fazem.

[3] Comentário enviado por invoid em 08/04/2010 - 09:06h

Pois é, quando se conhece e acompanha o andamento das coisas fica mais fácil e mais elegante resolver as coisas! É só ir buscar!

Valeu pelas opiniões!!!

[4] Comentário enviado por elgio em 08/04/2010 - 10:45h

Finalmente um artigo sobre este assunto. Ótima contribuição.

Este assunto tem sido abordado diversas vezes em tópicos e a dúvida sobre este tipo de nat é muito recorrente.

No tópico http://www.vivaolinux.com.br/topico/netfilter-iptables/Redirecionamento-de-portas-2/ o problema é explicado - sem os desenhos deste artigo :-D em em http://www.vivaolinux.com.br/topico/Squid-Iptables/Problema-com-redirect-em-Iptables/ a solução com duplo nat é oferecida como solução a um problema.

Este problema também pode ser resolvido, de forma mais fácil e direta, com o programa rinetd. Ele, parecido com o inetd, pode ficar escutando em uma porta e todos os dados que recebe nesta porta ele os repassa ao IP e porta que fora configurado.

Em outro post (http://www.vivaolinux.com.br/topico/netfilter-iptables/Problema-para-acessar-NAT-internamente - são realmente MUITOS sobre isto) eu cito novamente a solução do duplo nat e a do rinetd. Anderson creio que foi o primeiro a falar sobre o rinetd em sua dica http://www.vivaolinux.com.br/dica/Redirecionamento-de-portas-com-rinetd

Em outro (mais um, são DEZENAS e dezenas) post http://www.vivaolinux.com.br/topico/Squid-Iptables/Redirecionar-portas-entre-servidores creio que está a resposta mais completa, seja na melhor resposta, seja pelo post 16 com o uso do rinetd (que acobou sendo usado pelo autor do post)

[5] Comentário enviado por joaoacabamundo em 08/04/2010 - 10:54h

Cara parabéns, eu estava precisando resolver um problema deste tipo aqui na empresa e fiquei apanhando há quase 20 dias.

Abraços

[6] Comentário enviado por amado2vezes em 08/04/2010 - 11:16h

Cara valeu pela dica era o que ue precisava!

A solução eu ja tinha colocado nas regras do iptables mais fazendo uma revisão percebi minha o missão.

Os cliente de fora conseguiam acessar nosso aplicativo, mas nós só conseguiamos se fosse colocado o ip interno com a porta, não funcionava com o ip publico.

O motivo eu descobri depois de dar uma olhada neste seu artigo.
Minha regra diz que o que vier pela eth1(ip publico) redirecione para o servidor do aplicativo, mas não especifiquei que tambem o que vier pela eth0(ip interno) tambem fosse redirecionado, foi aí que achei o problema.

Valeu!

[7] Comentário enviado por fernandoborges em 09/04/2010 - 11:14h

Minha opinião é que o artigo foi completamente esclarecedor. Excelente, parabéns!

[8] Comentário enviado por beleza em 10/04/2010 - 17:16h

legal!

[9] Comentário enviado por invoid em 11/04/2010 - 22:40h

Fico muito grato pelos comentários, pois assim sei que realmente fui útil para os demais!

Estou trabalhando em outro artigo relacionado a firewall, e assim que estiver pronto postarei para vocês!

Abraços, e realmente muito obrigado a todos que colaboraram!

André Sousa

[10] Comentário enviado por dalveson em 27/04/2010 - 15:51h

André Sousa, me desculpa mais nao entendi direito, tenho a mesma situação porem com a porta do apache 8080, tenho que redirecionar do servidor linux para um servidor da rede onde roda o banco de dados, porem internamente nao consigo acessar, somente externamente como eu faria para resolver:
essa é a regra que uso para liberar o acesso externo atualmente:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 8080 -j DNAT --to-destination IP:8080

[11] Comentário enviado por invoid em 28/04/2010 - 10:54h

Olá dalveson!

Além desta regra, você precisa inserir a regra de SNAT, para que ele possa fazer o caminho inverso do pacote (veja figura 2).

Veja a regra abaixo:

iptables -p tcp -t nat -A POSTROUTING -s 172.15.25.0/24 -d 172.15.25.3 --dport 80 -j SNAT --to-source 200.254.225.31

Só precisa modificar os dados relativos a sua rede, servidor e a porta (que no seu caso é 8080). Com isto, o pacote já voltará pelo seu gateway e a tradução dos ips será feita corretamente.

Abraços e me informa se conseguiu ok?

André
http://www.andresousa.org/
andre@andresousa.org

[12] Comentário enviado por dalveson em 03/05/2010 - 09:40h

Fale André
Pow brother segui os procedimentos porem nao deu certo, a regra que eu adicioneio ao script de firewall foi a seguinte:

iptables -p tcp -t nat -A POSTROUTING -s minha_rede/24 -d IP_FRIO_SRV_Banco_de_dados --dport 8080 -j SNAT --to-source IP_quente_SRV_linux

abraços

[13] Comentário enviado por renato_pacheco em 05/01/2011 - 15:35h

Tenho q elogiar... seu artigo ficou show! Eu já sabia desse fato, mas nunca havia testado.

Costumo ajudar muitas pessoas aki no VOL com esse tipo d problema, mas nem sempre sabemos como tá o cenário da rede do colega e nem sempre funcionava quando eu ajudava. Talvez eu não explicava o funcionamento, apenas passava o comando pra pessoa executar...

O q importa é q agora, baseado no seu artigo, posso comprovar como q o SNAT funfa!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts