Diagnosticando "Connection refused"

Diagnosticando "Connection refused"

O que significa "Connection refused"?

Conclusao: O host remoto esta acessivel, mas rejeitou ativamente a conexao naquela porta. Nao e "inacessivel" -- o pacote chegou e foi recusado. A causa mais comum e que nenhum servico esta escutando naquela porta.

Connection refused aparece quando uma requisicao de conexao TCP (SYN) e respondida com um RST (reset) do outro lado. Em outras palavras, o pacote chegou ao host. O proprio host -- ou um dispositivo na frente dele -- respondeu explicitamente "esta porta nao aceitara conexoes".

$ curl http://192.0.2.10:8080
curl: (7) Failed to connect to 192.0.2.10 port 8080 after 3 ms: Couldn't connect to server
$ ssh user@192.0.2.10
ssh: connect to host 192.0.2.10 port 22: Connection refused

No nivel de chamada de sistema, este e o erro ECONNREFUSED. A forma como as aplicacoes reportam varia: ssh mostra "Connection refused" enquanto curl mostra "Couldn't connect to server". A resposta retorna imediatamente (alguns milissegundos), e essa velocidade e a diferenca chave de um timeout, discutido a seguir.

Pre-requisitos

  • SO: Ubuntu / uma distribuicao Linux tipica
  • Alvo: um servico escutando via TCP (SSH / web / DB, etc.)
  • Assumimos que voce tem acesso ao shell tanto no cliente quanto no servidor

Qual a diferenca entre "Connection refused" e um Timeout?

Conclusao: Refused retorna um RST instantaneamente (o host esta vivo); um timeout nao retorna nada (pacotes estao sendo descartados). Essa unica diferenca divide a causa entre "lado do servico" versus "caminho de rede".

A primeira coisa a esclarecer e se voce foi rejeitado ou encontrou silencio. Diferencie-os pela mensagem e pelo tempo de resposta.

Sintoma O que retorna Causas principais
Connection refused TCP RST (instantaneo) Servico parado / porta errada / regra REJECT
Connection timed out Sem resposta (longa espera) Firewall DROP / caminho quebrado / host desligado
$ time nc -zv 192.0.2.10 22
nc: connect to 192.0.2.10 port 22 (tcp) failed: Connection refused

real    0m0.004s

Se a falha retorna em 0.0xx segundos, e refused (o host esta respondendo). Se trava por dez ou mais segundos antes de falhar, e um timeout -- suspeite de um firewall DROP ou problema de caminho. Este artigo cobre o lado refused; para triagem de timeout veja Conectividade de Portas.

Refused significa "o host esta vivo mas a porta me recusou". Se o ping funciona ou nao e irrelevante (ICMP e TCP sao separados; SSH pode funcionar mesmo quando ping falha).

Por que "Connection refused" acontece?

Conclusao: Nove em cada dez vezes, nada esta escutando na porta alvo. A causa se reduz a quatro coisas -- servico parado, porta errada, endereco de escuta errado ou regra REJECT -- e trabalhar de cima para baixo e o mais rapido.

Os caminhos que produzem refused, organizados por causa:

Causa Quando acontece Por onde comecar
Servico parado Crash / falha ao iniciar / nao subiu apos reboot systemctl status
Numero de porta errado Mudanca de config, escutando em porta nao-padrao ss -tlnp
Endereco de escuta errado Vinculado a 127.0.0.1, inacessivel de fora ss -tlnp
Firewall REJECT nftables/iptables rejeita ativamente com RST/ICMP ss + verificar regras

O ponto de partida confiavel e verificar no servidor se algo esta realmente escutando. O erro no lado do cliente sozinho nao consegue diferenciar um servico parado de uma porta errada.

Como verificar se o servico esta ativo?

Conclusao: No servidor, execute ss -tlnp e confirme que a porta alvo esta em LISTEN. Se esta ausente, o servico esta parado ou a porta esta errada. Confirme o estado e a razao com systemctl status e journalctl.

Acesse o servidor e liste as portas em escuta.

$ sudo ss -tlnp
State    Recv-Q   Send-Q   Local Address:Port   Peer Address:Port   Process
LISTEN   0        128            0.0.0.0:22          0.0.0.0:*       users:(("sshd",pid=812,fd=3))
LISTEN   0        511          127.0.0.1:8080        0.0.0.0:*       users:(("node",pid=1043,fd=18))

As opcoes do ss sao -t (TCP), -l (somente LISTEN), -n (numerico, sem resolucao de nome), -p (mostra o processo, precisa de root). Se a porta alvo nao esta nesta lista, nada esta escutando ali, e o cliente ve um refused imediato.

Quando a porta esta ausente, verifique o servico correspondente.

$ systemctl status nginx
x nginx.service - A high performance web server
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
     Active: failed (Result: exit-code) since ...

Active: failed ou inactive (dead) significa que esta parado. Tente inicia-lo e, se falhar, siga a razao nos logs.

$ sudo systemctl start nginx
$ journalctl -u nginx -n 30 --no-pager

Se refused persiste enquanto o servico esta claramente ativo, e quase sempre um endereco de escuta ou porta incompativel. Passe para a proxima secao.

A armadilha do endereco de escuta (o problema do 127.0.0.1)

Conclusao: Um servico vinculado a 127.0.0.1:port e acessivel do proprio servidor, mas sempre refused de fora. Sempre verifique se a coluna Local Address em ss -tlnp e 127.0.0.1 ou 0.0.0.0 (ou ::).

Este e o classico caso de "o servico esta rodando mas nao consigo acessa-lo de fora". Veja a saida anterior novamente.

LISTEN   0   128       0.0.0.0:22       ...   sshd
LISTEN   0   511     127.0.0.1:8080     ...   node
  • 0.0.0.0:22 -> escutando em todas as interfaces. Acessivel de fora.
  • 127.0.0.1:8080 -> somente loopback. curl localhost:8080 no servidor funciona, mas qualquer acesso externo ou de outro host e refused.

Se funciona no servidor e e refused de fora, esta e quase certamente a causa. Altere o endereco de bind da aplicacao (geralmente uma configuracao de bind / listen / host) para 0.0.0.0 ou o IP alvo, depois reinicie.

# Funciona no servidor (loopback alcanca)
$ curl -sS http://127.0.0.1:8080/ >/dev/null && echo OK

# Refused de fora / outro host
$ curl http://192.0.2.10:8080/
curl: (7) Failed to connect ... Couldn't connect to server

Bancos de dados (PostgreSQL / MySQL, etc.) frequentemente fazem bind em 127.0.0.1 por padrao. Abri-los para conexoes externas deve ser feito junto com uma revisao de autenticacao e firewall -- nao basta abrir para 0.0.0.0.

Quando o firewall e a causa (REJECT vs DROP)

Conclusao: Um firewall configurado com REJECT retorna RST/ICMP, produzindo Connection refused; DROP descarta o pacote, produzindo um timeout. Se voce ve refused, suspeite de uma regra REJECT explicita.

Um firewall pode negar trafego de duas formas, e o sintoma no cliente difere.

  • REJECT: sinaliza explicitamente a negacao (TCP RST ou ICMP port-unreachable) -> o cliente recebe um Connection refused imediato
  • DROP: descarta silenciosamente o pacote -> o cliente espera e recebe um timeout

Portanto, quando voce ve refused, um firewall estilo DROP (o deny padrao do ufw e DROP) geralmente nao e o culpado. Ainda assim, verifique se ha uma regra REJECT explicita.

# Inspecionar regras nftables
$ sudo nft list ruleset | grep -i -E 'reject|dport'

# Em sistemas usando iptables
$ sudo iptables -L -n -v --line-numbers
Chain INPUT (policy ACCEPT)
num  target  prot  ...  destination
1    REJECT  tcp   ...  tcp dpt:8080 reject-with tcp-reset

Se uma regra REJECT ... reject-with tcp-reset corresponde aquela porta, ela e a origem do refused. Decida se a regra e necessaria e remova-a se nao for. Se voce usa ufw, veja Troubleshooting ufw e SSH para confirmar e restaurar regras de permissao.

Atalho: se uma conexao loopback no servidor (curl 127.0.0.1:port) funciona e apenas o acesso externo e refused, a causa e o endereco de escuta ou o firewall. Se e refused mesmo no servidor, restrinja a um servico parado ou porta errada.

Como fazer triagem pelo lado do cliente

Conclusao: Quando voce nao consegue acessar o servidor, use nc -zv para testar apenas a alcancabilidade e diferenciar refused de timeout. ss -tn tambem mostra ate onde o handshake chegou.

Quando voce nao consegue acessar o servidor imediatamente, faca uma verificacao minima do cliente.

# Testa apenas se a porta conecta (-z: sem dados enviados, -v: verbose)
$ nc -zv 192.0.2.10 22

Se Connection refused retorna instantaneamente, o host esta respondendo mas a porta esta fechada. Se deu timed out, suspeite do caminho ou de um firewall DROP, e va para Conectividade de Portas em vez deste artigo.

Observar o estado TCP apos uma tentativa de conexao mostra ate onde o handshake chegou.

$ ss -tn dst 192.0.2.10

Se permanece em SYN-SENT, nenhuma resposta voltou (familia timeout). Com refused, a conexao nunca se estabelece e falha imediatamente.

Execute varreduras de portas e verificacoes de alcancabilidade apenas em hosts que voce possui ou esta autorizado a testar. Evite varreduras em hosts de terceiros sem permissao.

Checklist quando ainda falha

Conclusao: Refused confirma "host vivo, porta rejeitando". Trabalhe na ordem servico -> porta -> endereco de escuta -> regra REJECT, e a causa se reduz a uma dessas quatro.

  • [ ] Voce diferenciou refused (instantaneo) de timed out (longa espera)?
  • [ ] No servidor, ss -tlnp mostrou a porta alvo em LISTEN?
  • [ ] Se nao ha LISTEN, voce verificou a razao da parada com systemctl status / journalctl -u?
  • [ ] O Local Address e 127.0.0.1 (acesso externo precisa de 0.0.0.0 etc.)?
  • [ ] O numero da porta confere entre o cliente e o listener?
  • [ ] Existe uma regra REJECT para aquela porta em nft list ruleset / iptables -L?
  • [ ] Uma conexao loopback no servidor (curl 127.0.0.1:port) funciona (se sim, a causa e externa)?

Proximas leituras