Um belo dia você foi testar a aplicação que está desenvolvendo e descobriu que ela não responde como deveria. As consultas que ela enviava para o banco não retornam nada, e o navegador está calado.
Por onde começar? Bom, hoje você irá partir para um troubleshooting de rede. Existem várias situações e abordagens que envolvem esse assunto, mas iremos abordar a seguinte: o cliente será a máquina de aplicação. Você se conectará a ela e ao servidor que roda o banco. Imaginemos que são duas VMs.
Considerando que você já confirmou que a aplicação está no ar e a configuração de rede está igual a quando tudo estava rodando, neste host as coisas não mudaram.
Iremos agora para o servidor. Conecte-se a ele via ssh e começamos por aí as investigações, ok?
Infra:
Temos dois hosts envolvidos, um rodando a aplicação e o outro rodando o servidor de banco, um MySQL , por exemplo.
Perguntas que vamos buscar responder:
- O serviço do banco está no ar?
- A porta do serviço está estabelecendo conexão?
- Os hosts envolvidos comunicam-se por meio da rede?
- O cliente consegue conectar-se à porta do serviço?
- Tem certeza? Então prove! 😉
__________________________________________________________________________________________________
– Informações em mãos: Para compreender melhor o troubleshooting, é importante termos alguns dados em mente, isso vai nos ajudar a identificar o que precisamos testar e analisar do ambiente. Segue a lista:
– Nome do serviço: mysql
– Nome do processo: mysqld
– Porta padrão referente ao serviço: 3306,
*obs: Vamos considerar que o serviço esteja rodando na porta padrão
– ips envolvidos:
cliente: 10.200.0.216
servidor: 10.200.0.82
__________________________________________________________________________________________________
Vamos considerar que ..
- A comunicação entre o cliente e o servidor se dá por endereço IP, e não por nome. Se fosse por nome, teríamos que verificar se a resolução de nome está correta. Por isso, os exemplos que trabalharemos utilizam os endereços IP.
- As configurações básicas de rede dos hosts estão corretas, ou seja, estão na mesma rede.
- A porta que o MySQL está usando é a 3306
——————————————————-
1. Servidor
Partiremos primeiro para a máquina que roda o serviço. Nela, vamos verificar se:
1.0 Acessando o servidor:
ssh username@10.200.0.82
Obs: Lembrando que esse usuário precisa ter permissão para executar os comandos listados neste artigo.
1.1 Serviço está no ar?
Listaremos os processos que estão rodando no servidor e filtraremos pelo nome do serviço ou processo, como no exemplo:
Aqui temos dois processos listados. O que nós queremos é o que está sendo executado pelo user mysql, cujo PID é o 24231. Nessa linha, temos diversas informações pertinentes, inclusive a porta que o serviço está rodando: 3306. Certo? Então temos agora o valor do pid e da porta do serviço, e vamos precisar desses dados para a próxima ação:
1.2. A porta do serviço está “LISTEN” ou “ESTABLISHED” e conecta “localhost”?
Estado das conexões
- LISTEN: O socket está escutando as conexões de entrada
- ESTABLISHED: O socket tem uma conexão estabelecida
Escutando?
Conectando?
1.3. O servidor alcança o host cliente?
Entendendo os comandos:
1. ps -efww|grep -v grep|egrep mysl:
As opções:
– e: Seleciona todos os processos existentes no momento
– f: Adiciona algumas colunas na saída do comando
– ww: Limita a largura da saída para o tamanho do terminal
grep -v grep: Remove do nosso filtro o processo que contenha a palavra grep
egrep mysql: Agora sim, filtra da lista de todos os processos aquele que contenha a palavra mysql. egrep; é o mesmo que grep -E, –extended-rgex
2. lsof -nPi4:3306 -ap24231:
As opções:
-n: Não resolva os nomes dos hosts – O comando roda mais rápido
-P: Não resolva os nomes das portas – Estamos buscando pelo número da porta
-i4:Seleciona a lista dos arquivos de rede que contenham endereço de Internet com a versão ipv4
– :3306: e que tenham como porta 3306
-a: O Lsof trabalha por padrão com a lógica OR. Utilizando essa opção, usaremos a AND, ou seja, me traga todas as conexões ipv4 com a porta 3306 e/and com o ip 24231
-p: Aceita como parâmetro um ip; no nosso caso, é o ip 24231
3. nc -vz 127.0.0.1 3306
As opções:
-v: Ativa a verbosidade – Se não colocarmos, não teremos nenhuma saída
-z: Faz com que o nc apenas realize um scan à procura de daemons sem precisar conectar
4. ping -c3 10.200.0.216:
Opção:
-c count: Envia a quantidade de pacotes ECHO REQUEST indicada no “count”
Conclusão da etapa:
1.1 – Verificamos que o serviço está no ar e conhecemos o seu pid e porta.
1.2 – Confirmamos que a sua porta do serviço está estabelecendo conexão.
1.3 – Também confirmamos que o servidor consegue se comunicar com o nosso cliente.
Agora, vamos realizar testes do lado do cliente. Vamos lá:
—————————————————————————————————————————————-
2. Cliente
2.1 O cliente alcança o servidor?
Testaremos a comunicação entre os hosts utilizando a ferramenta ping, como no exemplo abaixo:
2.1.1 Usando o comando ping:
Aqui temos uma pegadinha.
Pingamos o servidor e ele não respondeu (e isso poderia acontecer com o nosso último teste). Alguns poderiam concluir que não está ocorrendo comunicação entre os hosts, porém não é raro encontrar servidores com firewall configurados para não responderem aos echo-requests – “mensagens ICMP enviadas pelo ping, nas quais aguardam a mensagem de resposta echo-replay”.
Logo, após esse passo, não é seguro concluir que não há comunicação entre o cliente e o servidor. Para isso, precisamos realizar mais um teste.
*OBS: Sendo assim, no teste da etapa anterior, no qual rodamos o comando ping -c3 [ip_do cliente], também devemos adotar o passo abaixo:
2.2 Conecta na porta do serviço desejado?
Vamos realizar uma conexão na porta 3306, ou seja, em vez de usarmos o protocolo ICMP que o ping trabalha, usaremos o TCP. Então, qualquer possível regra de firewall que impeça mensagens “echo replay” não vão mais interferir nesse teste.
2.3 Usando outra ferramenta para o mesmo fim: o nmap irá realizar um “port scan” para nós agora.
Entendendo o comando:
A opção “PS” faz uma requisição para o servidor enviando um pacote TCP com a flag SYN, mas interrompe o processo “conhecido como three-way-handshake*” no meio do caminho, pois a ideia nesse caso é apenas verificar se o host é alcançável e se a porta do serviço está aberta.
*three-way-handshake: falaremos sobre esse processo em outro artigo.
Conclusão da etapa
2.1 – Fizemos o teste mais usado para verificar a conectividade entre hosts.
2.2 – Testamos a conectividade entre hosts simulando uma conexão.
2.3 – Mais uma maneira de simular uma conexão e ter certeza da possibilidade de comunicação entre os hosts em questão.
—————————————————————————————————————————————-
3. Servidor
Por fim, vamos colher os logs em tempo real para confirmar que o cliente ‘x’ está alcançando o servidor e se conectando à porta do serviço, para que não reste dúvidas de que está tudo funcionando como esperado no que se refere à rede.
3.1 Colhendo logs em tempo real do fluxo vindo do cliente:
– Abra dois terminais, um logado no cliente e outro no servidor, e execute os comandos abaixo:
No servidor, rodaremos o comando:
Do cliente, iremos enviar pacotes tcp para a porta 3306
No terminal do servidor, veremos que ele recebeu os pacotes. Segue uma parte da saída:
Toda vez que o cliente rodar o comando “nc -vz 10.20.0.82 3306”, você poderá acompanhar no terminal do servidor os pacotes chegando em “tempo real”.
Destacando: 10.200.0.216.58954 > 10.200.0.82.3306
cliente > servidor.[porta]
Entendendo o comando tcpdump:
Analisa o tráfego de redes. Com uma expressão, conseguimos filtrar o tráfego que contenha as características que desejamos. Podemos filtrar por host, porta etc. A saída pode não ser lá essas belezuras, mas com um pouco de conhecimento sobre redes e a ferramenta, já conseguimos obter as informações de que precisamos, o que no nosso caso seria:
Precisamos de uma prova irrefutável e em tempo real de que um determinado cliente (10.200.0.216 ) está conseguindo se conectar ao servidor na porta 3306 (10.200.0.82.3306). Para isso, construímos aquela expressão:
Opções usadas:
– não resolva o nome de portas/serviços e hosts = -n
– escute na sua interface eth1, = -i eth1
Expressão:
– o tráfego que tenha como host fonte o ip 10.200.0.216 = src host 10.200.0.216
– e que tenha como porta de destino a 3306 = and port 3306
Nesse filtro que criamos, estamos sendo bem específicos. Isso nos ajuda a adquirir uma prova mais consistente.
Conclusão da etapa
3.1 – Presenciamos a troca de dados entre os hosts em tempo real
__________________________________________________________________________________________________
Resumo
Para verificar a comunicação entre hosts, podemos usar o velho comando ping, mas já sabemos que é possível encontrar barreiras “invisíveis”. Experimente pingar uma máquina Windows, um desktop mesmo – em geral, o firewall dá uma “sacaneada”.
Vá de nc ou nmap, pois podemos utilizar mensagens tcp para simular uma requisição para conexão. Logo, se o servidor está no ar, ele nos responderá.
Digo o mesmo quando precisamos testar a conectividade das portas dos serviços, nc e nmap resolvem bem.
Para listar as conexões em portas específicas, poderíamos ter usado o netstat ou ss, mas para aumentar a precisão usaríamos o grep. Então, escolhi o lsof porque com ele podermos indicar a porta da conexão (3306). Além disso, a maioria das pessoas que conheço usa o netstat, então preferi variar.
Analisar pacotes de rede: é sempre bom ter certeza quanto ao tráfego de redes. Temos o tcpdump para ajudar, então use. Parece complicado, mas estamos trabalhando em outro artigo para resolver isso.
Fica assim:
- Verificar a comunicação entre hosts: nc ou nmap
- Conectividade das portas de serviços: nc ou nmap
- Listar as conexões em portas específicas: lsof
- Analisar pacotes de rede: tcpdump
E é isso, pessoal!
Espero ter conseguido expor a utilidade das ferramentas. Não expliquei a fundo cada uma delas para deixar o artigo bem prático e fácil de lembrar na hora de um “aperto”.
Se surgir alguma dúvida ou sugestão, é só usar os campos abaixo.
Até a próxima!