Diagnosticando "Connection refused"

Diagnosticando "Connection refused"

O que significa "Connection refused"?

Conclusão: O host remoto está acessível, mas rejeitou ativamente a conexão naquela porta. Não é "inacessível" -- o pacote chegou e foi recusado. A causa mais comum é que nenhum serviço está escutando naquela porta.

Connection refused aparece quando uma requisição de conexão TCP (SYN) é respondida com um RST (reset) do outro lado. Em outras palavras, o pacote chegou ao host. O próprio host -- ou um dispositivo na frente dele -- respondeu explicitamente "esta porta não aceitará conexões".

$ 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 nível de chamada de sistema, este é o erro ECONNREFUSED. A forma como as aplicações reportam varia: ssh mostra "Connection refused" enquanto curl mostra "Couldn't connect to server". A resposta retorna imediatamente (alguns milissegundos), e essa velocidade é a diferença chave de um timeout, discutido a seguir.

Pré-requisitos

  • SO: Ubuntu / uma distribuição Linux típica
  • Alvo: um serviço escutando via TCP (SSH / web / DB, etc.)
  • Assumimos que você tem acesso ao shell tanto no cliente quanto no servidor

Qual a diferença entre "Connection refused" e um Timeout?

Conclusão: Refused retorna um RST instantaneamente (o host está vivo); um timeout não retorna nada (pacotes estão sendo descartados). Essa única diferença divide a causa entre "lado do serviço" versus "caminho de rede".

A primeira coisa a esclarecer é se você foi rejeitado ou encontrou silêncio. Diferencie-os pela mensagem e pelo tempo de resposta.

Sintoma O que retorna Causas principais
Connection refused TCP RST (instantâneo) Serviço 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, é refused (o host está respondendo). Se trava por dez ou mais segundos antes de falhar, é 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 está vivo mas a porta me recusou". Se o ping funciona ou não é irrelevante (ICMP e TCP são separados; SSH pode funcionar mesmo quando ping falha).

Por que "Connection refused" acontece?

Conclusão: Nove em cada dez vezes, nada está escutando na porta alvo. A causa se reduz a quatro coisas -- serviço parado, porta errada, endereço de escuta errado ou regra REJECT -- e trabalhar de cima para baixo é o mais rápido.

Os caminhos que produzem refused, organizados por causa:

Causa Quando acontece Por onde começar
Serviço parado Crash / falha ao iniciar / não subiu após reboot systemctl status
Número de porta errado Mudança de config, escutando em porta não-padrão ss -tlnp
Endereço de escuta errado Vinculado a 127.0.0.1, inacessível de fora ss -tlnp
Firewall REJECT nftables/iptables rejeita ativamente com RST/ICMP ss + verificar regras

O ponto de partida confiável é verificar no servidor se algo está realmente escutando. O erro no lado do cliente sozinho não consegue diferenciar um serviço parado de uma porta errada.

Como verificar se o serviço está ativo?

Conclusão: No servidor, execute ss -tlnp e confirme que a porta alvo está em LISTEN. Se está ausente, o serviço está parado ou a porta está errada. Confirme o estado e a razão 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 opções do ss são -t (TCP), -l (somente LISTEN), -n (numérico, sem resolução de nome), -p (mostra o processo, precisa de root). Se a porta alvo não está nesta lista, nada está escutando ali, e o cliente vê um refused imediato.

Quando a porta está ausente, verifique o serviço 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 está parado. Tente iniciá-lo e, se falhar, siga a razão nos logs.

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

Se refused persiste enquanto o serviço está claramente ativo, é quase sempre um endereço de escuta ou porta incompatível. Passe para a próxima seção.

A armadilha do endereço de escuta (o problema do 127.0.0.1)

Conclusão: Um serviço vinculado a 127.0.0.1:port é acessível do próprio servidor, mas sempre refused de fora. Sempre verifique se a coluna Local Address em ss -tlnp é 127.0.0.1 ou 0.0.0.0 (ou ::).

Este é o clássico caso de "o serviço está rodando mas não consigo acessá-lo de fora". Veja a saída 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. Acessível de fora.
  • 127.0.0.1:8080 -> somente loopback. curl localhost:8080 no servidor funciona, mas qualquer acesso externo ou de outro host é refused.

Se funciona no servidor e é refused de fora, esta é quase certamente a causa. Altere o endereço de bind da aplicação (geralmente uma configuração 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 padrão. Abri-los para conexões externas deve ser feito junto com uma revisão de autenticação e firewall -- não basta abrir para 0.0.0.0.

Quando o firewall é a causa (REJECT vs DROP)

Conclusão: Um firewall configurado com REJECT retorna RST/ICMP, produzindo Connection refused; DROP descarta o pacote, produzindo um timeout. Se você vê refused, suspeite de uma regra REJECT explícita.

Um firewall pode negar tráfego de duas formas, e o sintoma no cliente difere.

  • REJECT: sinaliza explicitamente a negação (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 você vê refused, um firewall estilo DROP (o deny padrão do ufw é DROP) geralmente não é o culpado. Ainda assim, verifique se há uma regra REJECT explícita.

# 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 àquela porta, ela é a origem do refused. Decida se a regra é necessária e remova-a se não for. Se você usa ufw, veja Troubleshooting ufw e SSH para confirmar e restaurar regras de permissão.

Atalho: se uma conexão loopback no servidor (curl 127.0.0.1:port) funciona e apenas o acesso externo é refused, a causa é o endereço de escuta ou o firewall. Se é refused mesmo no servidor, restrinja a um serviço parado ou porta errada.

Como fazer triagem pelo lado do cliente

Conclusão: Quando você não consegue acessar o servidor, use nc -zv para testar apenas a alcançabilidade e diferenciar refused de timeout. ss -tn também mostra até onde o handshake chegou.

Quando você não consegue acessar o servidor imediatamente, faça uma verificação mínima 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 está respondendo mas a porta está fechada. Se deu timed out, suspeite do caminho ou de um firewall DROP, e vá para Conectividade de Portas em vez deste artigo.

Observar o estado TCP após uma tentativa de conexão mostra até onde o handshake chegou.

$ ss -tn dst 192.0.2.10

Se permanece em SYN-SENT, nenhuma resposta voltou (família timeout). Com refused, a conexão nunca se estabelece e falha imediatamente.

Execute varreduras de portas e verificações de alcançabilidade apenas em hosts que você possui ou está autorizado a testar. Evite varreduras em hosts de terceiros sem permissão.

Checklist quando ainda falha

Conclusão: Refused confirma "host vivo, porta rejeitando". Trabalhe na ordem serviço -> porta -> endereço de escuta -> regra REJECT, e a causa se reduz a uma dessas quatro.

  • [ ] Você diferenciou refused (instantâneo) de timed out (longa espera)?
  • [ ] No servidor, ss -tlnp mostrou a porta alvo em LISTEN?
  • [ ] Se não há LISTEN, você verificou a razão da parada com systemctl status / journalctl -u?
  • [ ] O Local Address é 127.0.0.1 (acesso externo precisa de 0.0.0.0 etc.)?
  • [ ] O número da porta confere entre o cliente e o listener?
  • [ ] Existe uma regra REJECT para aquela porta em nft list ruleset / iptables -L?
  • [ ] Uma conexão loopback no servidor (curl 127.0.0.1:port) funciona (se sim, a causa é externa)?

Próximas leituras