Thursday, August 30, 2007

Identificando bloqueios de firewalls em redes desconhecidas

Nem sempre é fácil para os administradores de redes identificar onde pacotes estão sendo bloqueados, principalmente em redes desconhecidas e com firewalls sob controle de terceiros. Este artigo explica uma das técnicas que podem ajudar nessa tarefa, explorando um recurso padrão do protocolo IP de forma semelhante ao funcionamento do traceroute.

Recentemente um cliente reclamou que não conseguia conectar-se ao servidor dele, em nenhuma porta. O tempo da conexão sempre expirava (timeout) antes de conectar. Como eu conheço a rede onde ficam os servidores, de início achei improvável que houvesse algum problema 'do lado de cá'.

Entretanto, já vi muita coisa estranha acontecendo, geralmente por culpa de firewalls mal configurados. Nunca cheguei a ver os problemas mais bizarros relatados web afora, como detecção incorreta de path MTU, ou incompatibilidades com dispositivos antigos por causa de recursos 'novos' do TCP (ECN etc). Mas talvez fosse o caso. De qualquer forma, precisávamos diagnosticar onde essas conexões estavam parando.

google-firewall




Diagrama hipotético - desenhado no Dia (GNOME)


E então as ferramentas tracetcp, traceproto ou tcptraceroute vieram ajudar a salvar o dia. São ferramentas simples que podem ser usadas para se detectar firewalls . Há versões para Linux, Windows e, suponho, outros SOs. Para Windows, recomendo o tracetcp. Em Linux, há vários sabores, mas costumo usar o traceproto. O funcinamento é parecido com o do traceroute: (continua abaixo) Como muita gente sabe, o traceroute funciona enviando pacotes UDP para o host de destino, mas com um valor baixo para o campo "TTL" (tempo de vida) do cabeçalho IP.

Para evitar loops, todo roteador IP diminui o valor do TTL de todos pacotes que passem por ele. Se por acaso esse valor chegar em 0 enquanto trafega na rede, o roteador em questão emitirá uma mensagem ICMP informando ao host de origem que o tempo excedeu e descarta o pacote. Assim, o traceroute consegue identificar até onde o pacote passou, olhando a origem dessa mensagem ICMP. Depois repete o processo, porém com um TTL maior.

Incrementar o TTL em um faz com que o roteador seguinte retorne o erro ICMP. Dessa forma, repetindo o processo, o traceroute consegue identificar salto-a-salto todos os roteadores envolvidos no caminho entre o host local e o remoto.

O tracetcp/traceproto/tcptraceroute faz a mesma coisa, mas você escolhe qual porta e protocolo vai usar (UDP, TCP, etc). Assim, se suas conexões estiverem sendo bloqueadas em algum ponto desconhecido, mas isso acontece apenas em algums portas e outras não, usando essas ferramentas é possível dizer com certeza quais roteadores e redes não bloquearam o pacote - já que se o roteador retornou erro, significa que o pacote com certeza chegou até ele. Portanto o problema está dali pra frente :-).

Vou detalhar um exemplo bizarro para ilustrar a questão. Suponha que você trabalhe no Google e tenha acesso direto via SSH ao www.google.com (e claro, acesso aos outros 450.000 servidores também!!), mas ao tentar abrir uma conexão na porta TCP:22, dá timeout. Onde está o problema? Pode ser no modem/roteador da sua casa, no roteador da BrasilTelecom/Telemar/etc/etc... ou no próprio firewall do Google.

Vamos usar o traceproto para identificar qual firewall/roteador provavelmente não está permitindo a sua conexão. (Estou usando -H 1 para simplificar o exemplo, mas lembre que a cada tentativa a rota pode mudar, isso é normal. Eu tive que repetir os testes várias vezes até conseguir uma rota semelhante para os dois casos. Portanto essa técnica funciona melhor para diagnosticar problemas em uma rede pequena sem múltiplos caminhos.)

Primeiro, vejamos uma conexão que funciona (os comentários na segunda coluna são meus):

gfirewall1

Tudo OK:
conexão estabelecida com o host final.

Na figura anterior, o código ITX significa "ICMP Time Exceeded". Quer dizer que o pacote chegou naquele roteador com TTL=0, portanto ocorreu um erro. Na última linha, vemos o código TSA - que significa "TCP SYN ACK" que podemos interpretar como "conexão pronta para ser estabelecida". Note que esses dois códigos não são de uso geral na área de redes, sendo usados pelo tracepoto apenas para mostrar mostrar uma relatório mais compacto.


Agora, vejam uma tentativa de conectar à porta 22:



gfirewall2
Sem resposta ao pedido.
Último roteador respondendo: 4.68.16.3


Percebam que a requisição só recebe resposta (nesse caso, na verdade, uma mensagem ICMP de tempo excedido) de alguns roteadores. Depois disso, nosso pacote parece ser descartado (0.0.0.0 em diante).

Além de verificarmos que há servidores do Google em Nova York (onde pelo que sei os custos de banda de rede são muito baixos), o que esse resultado nos diz? Com alguma imaginação, podemos supor que o próximo salto deveria ser o "4.71.172.86", com nome de "GOOGLE-INC.car1.NewYork1.Level3.net". Mas não recebemos resposta (na realidade, uma mensagem de erro) desse roteador. É possível que este host seja o firewall dropando os pacotes, ou pode ser que o firewall esteja antes dele. Isso condiz, aliás, com o nome do roteador - que aparentemente é o "roteador de borda" do Google para conexões vindas da rede da Level3.

A conclusão desse troubleshooting é que agora você sabe pra quem deve ligar pra ter seu acesso ao SSH do Google liberado outra vez. :-)

No caso do meu cliente que não conseguia se conectar ao servidor dele, o problema era mais simples. Ele usou o tracetcp no Windows e recebeu a seguinte mensagem:

> tracetcp.exe example.com:80 Socket::connect: Connection refused

Ou seja, não apareceu nenhum roteador respondendo. Conclusão: o firewall local da máquina ainda tinha uma regra "escondida" em algum lugar fazendo esses bloqueios, foi só desligar e problema resolvido.

Quem dera eu soubesse essa técnica antes, quando o firewall mal configurado de uma prestadora de serviços de data center do qual éramos clientes freqüentemente bloqueava tráfego de forma obscura e não solicitada. Poderia ter ajudado a resolver o empurra-empurra mais rapidamente.

Espero que isso seja útil para outros colegas sysadmins.

Outras referências: