Aposto que você já se deparou com o erro: Connection Refused. Seja no Cassandra, no Oracle, no MySQL ou em outros serviços. Mas você sabe exatamente o que ele significa? É o que vamos discutir aqui.
Conhecer um pouco de Linux nos ajuda a entender os problemas que enfrentamos em banco de dados e é uma disciplina importante para DBAs.
No Linux uma porta está com status LISTEN quando o serviço estiver aceitando conexões. Normalmente isso quer dizer que seu serviço está UP, funcionando normalmente e aceitando requisições. Ou seja, você starta seu MySQL, PostgreS, Cassandra e estes serviços começam a ouvir em determinadas portas, 3306, 5432 e 9042 respectivamente (portas defaults) (alguns serviços vão ouvir em mais de uma).
Temos duas opções (que eu conheço) uma é o netstat e outra é o ss (que vai substituindo o netstat aos poucos nas novas distribuições de Linux)
Vamos precisar de duas ferramentas para nosso pequeno lab. Eu vou usar uma imagem docker do Rocky Linux 8.
docker run -it rockylinux:8
Nesse caso ele vem sem essas opções. Então caso você também não tenha o netstat ou nc (netcat), basta fazer:
yum install -y nc
yum install -y net-tools
Primeiro, vamos ver quais portas o nosso server está ouvindo:
[root@3d40b542898d /]# netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
[root@3d40b542898d /]#
No meu caso, nenhuma porta LISTEN. Mas podemos usar o nc para simular um serviço ouvindo em determinada porta. Por exemplo, vamos simular um serviço ouvindo na porta 3306 ( o “&” é para jogar o processo para background e devolver o prompt).
[root@3d40b542898d /]# nc -lv 3306 &
[1] 75
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Listening on 0.0.0.0:3306
[root@3d40b542898d /]#
Agora podemos consultar as portas LISTEN e veremos nosso processo lá:
[root@3d40b542898d /]# netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 75/nc
Há algumas formas de testar esse acesso, a que eu mais uso é com o telnet. Você precisa instalá-lo e em seguida basta fazer: telnet IP/hostname porta
Também pode ser usado o netcat (nc): nc -vnz IP/hostname porta
Aproveitando o meu container, vou verificar os IPs que ele tem:
[root@3d40b542898d /]# ifconfig | grep inet
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
inet 127.0.0.1 netmask 255.0.0.0
Consigo então fazer o teste assim:
[root@3d40b542898d /]# nc -vnz 172.17.0.2 3306
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Connected to 172.17.0.2:3306.
Se você repetiu meus passos até aqui, o processo que estava ouvindo na porta 3306 finaliza quando recebe a conexão. Ou seja, nosso container não está mais ouvindo na porta 3306.
[1]+ Done nc -lv 3306
Mas simular agora nosso server ouvindo em outra porta, a 5432.
[root@3d40b542898d /]# nc -lv 5432 &
[1] 82
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Listening on 0.0.0.0:5432
E vamos testar a conexão na mesma porta 3306.
[root@3d40b542898d /]# nc -vnz 172.17.0.2 3306
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Connection refused.
[root@3d40b542898d /]#
Agora sim recebemos nosso “connection refused”.
Por fim, quando alguma coisa, que pode ser firewall local, network ACL, security group e afins, impede essa conexão não vemos sucesso nem erro. A conexão simplesmente fica esperando um determinado tempo e depois retorna o erro de timeout.
Então para os casos de timeout, você deve verificar se há alguma dessas camadas impedindo a conexão. Porém, se você recebe Connection Refused, o acesso está liberado, mas você não chegou na porta certa.
Bom, o problema aqui não é tão complicado. A gente precisa ter em mente que nossos serviços podem ouvir em determinada interface (você verá o IP da interface) ou em todas as interfaces (você verá 0.0.0.0).
Antes vou descrever brevemente algumas características das interfaces no Linux. Normalmente encontramos pelo menos duas interfaces, uma chamada loopback, ou simplesmente lo. Ela terá o endereço 127.0.0.1 e só aceita conexões locais, vindas do próprio servidor. Sua segunda interface se chamará eth0, ens5 ou algum outro parecido. Nesta outra interface você normalmente encontrará o seu IP interno.
[root@host1 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 65535
inet 172.17.0.3 netmask 255.255.0.0 broadcast 172.17.255.255
…
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
Dito isso, vejamos a diferença. Com o nc no container chamado host1, vou
[root@host1 /]# nc -l 127.0.0.1 3306 &
[root@host1 /]# nc -l 172.17.0.3 5432 &
[root@host1 /]# nc -l 9042 &
Veja como ficou. 9042 com 0.0.0.0 significa que ouve em todas as interfaces e as portas 3306 e 5432 em uma interface específica.
[root@host1 /]# netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:9042 0.0.0.0:* LISTEN 77/nc
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 71/nc
tcp 0 0 172.17.0.3:5432 0.0.0.0:* LISTEN 74/nc
O que esperamos agora: toda requisição externa na porta 3306, deve retornar Connection Refused, já que a loopback só aceita conexões locais. Vou testar a conexão a partir do meu container app.
[root@app /]# nc -vnz 172.17.0.3 3306
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Connection refused.
Por outro lado, conexões externas na porta 5432 e 9042 devem funcionar corretamente:
[root@app /]# nc -vnz 172.17.0.3 5432
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Connected to 172.17.0.3:5432.
[root@app /]# nc -vnz 172.17.0.3 9042
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Connected to 172.17.0.3:9042.
Por último, vamos testar a conexão local na 3306. E cuidado com o termo conexão local, veja que só funciona com a interface 127.0.0.1 e não com a 172.17.0.3.
[root@host1 /]# nc -vnz 172.17.0.3 3306
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Connection refused.
[root@host1 /]# nc -vnz 127.0.0.1 3306
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Connected to 127.0.0.1:3306.
Como pudemos ver, se uma aplicação tenta se conectar em um servidor na porta em que ele esteja ouvindo, a conexão é estabelecida com sucesso.
Se você tentar uma porta que o server não esteja ouvindo, o retorno é Connection Refused. Caso a porta devesse estar UP, você precisa investigar a saúde do seu serviço.
E por fim, a Connection Timeout aparece quando entre o cliente e o servidor há algum bloqueio for firewall ou equivalente. Nesse caso você deve investigar qual a camada que está bloqueando e fazer a liberação.
Espero que tenham gostado do conteúdo. Até a próxima.
Tag:linux
Olá Pessoal, Estou escrevendo para deixar registrado (publicamente) como acessar interfaces de serviços web rodando em uma subnet privada da AWS, como um EMR, Spark ou NiFi, por exemplo. Aqui usaremos o cenário ja exposto em outro post (Como instalar …