Linux: Diagnóstico de Conetividade com Comandos Nativos

Neste artigo:

  1. O que já vem instalado — e o que não vem
  2. ip link e ip addr: a placa de rede e o IP
  3. ip route, ip neigh e ip rule: o caminho até fora
  4. ping: tamanhos, contagem e tempos
  5. ss: portas em uso e estatísticas
  6. DNS: getent hosts (NSS) vs resolvectl query
  7. HTTP: curl e wget
  8. Serviços: journalctl -u
  9. Diagnóstico guiado em 60 segundos
  10. Erros Comuns
  11. Checklist
  12. Artigos Relacionados
  13. Fontes Oficiais

“O servidor caiu”. “A aplicação não liga à base de dados”. “A rede está lenta”. Num Linux a que só se entra por SSH, a pergunta decisiva é sempre a mesma: o que já está instalado e que responde a estas perguntas sem instalar nada? A resposta curta: quase tudo. O ip, o ping, o ss, o getent, o resolvectl, o curl e o journalctl fazem parte do sistema de base ou vêm em pacotes que qualquer instalação arrasta consigo . Este artigo é a referência prática desses comandos em Debian/Ubuntu Server: cada secção usa uma ferramenta com exemplos directos, da placa de rede ao HTTP.

1. O que já vem instalado — e o que não vem

O inventário muda conforme a imagem. Num Debian instalado pelo instalador normal, a tarefa “standard” traz traceroute, wget e os utilitários BIND (dig, nslookup). Numa imagem mínima — cloud, container, debootstrap — fica só o essencial:

Ferramenta Pacote Vem por omissão?
ip, ss iproute2 Sim — prioridade important, presente em qualquer instalação
ping iputils-ping Sim — prioridade important
hostname hostname Sim — prioridade required
wget wget Sim nas instalações completas (standard); falta em imagens mínimas
curl curl Optional — presente em quase todas as imagens de servidor, mas não garantido; apt install curl resolve
resolvectl systemd-resolved Sempre que o systemd-resolved corre — Ubuntu por omissão; no Debian stable é um pacote separado, nem sempre activo
dig, nslookup bind9-dnsutils Não em imagens mínimas — standard nas instalações completas
traceroute traceroute Não garantido — standard no Debian completo, optional no Ubuntu
nc netcat-openbsd Não garantido — optional no Debian, important no Ubuntu
mtr mtr-tiny Não — optional, requer instalação
drill ldnsutils Não — optional, alternativa ao dig

A regra prática: escreve os runbooks com o ip/ss/ping/journalctl — funcionam em qualquer máquina, incluindo containers mínimos (o getent também, mas só testa o que a cadeia NSS da máquina tem configurado). O curl e o resolvectl entram a seguir. O nc, mtr e o próprio dig exigem confirmação com command -v nc antes de constarem de um script. O netstat está obsoleto — a própria man page do netstat(8) aponta o ss como substituto (e ip route para o netstat -r, ip -s link para o netstat -i).

O ip link mostra as interfaces que o kernel conhece, ligadas ou não — é o primeiro comando de qualquer diagnóstico porque responde à pergunta “a placa de rede existe e está activa?”:

# ip -br link
lo               UNKNOWN        00:00:00:00:00:00 
enp0s3           UP             08:00:27:f0:95:7f 
ens19            DOWN           08:00:27:aa:bb:cc 

O ip -br (brief) compacta a saída em tabela — suportado em ip addr show, ip link show e ip neigh show, e é a forma mais rápida de ver o estado. Interpretação dos flags: UP significa a interface activada no software e LOWER_UP significa que o driver detecta ligação física (o cabo ligado e a porta do switch activa). UP sem LOWER_UP — ou NO-CARRIER — é cabo desligado, porta do switch desactiva ou interface virtual sem peer. O lo fica em UNKNOWN: é normal, é loopback.

O ip addr junta os endereços:

# ip -br addr
lo               UNKNOWN        127.0.0.1/8 ::1/128
enp0s3           UP             192.168.1.50/24 fe80::2dd2:9ab:5892:352d/64

Sem IP — ou só com fe80:: (IPv6 link-local) — em DHCP, o problema está no servidor DHCP, no VLAN ou no cabo. O ip addr show dev enp0s3 detalha uma interface, incluindo o alcance (scope) de cada endereço: global é utilizável na rede, link só no segmento local.

3. ip route, ip neigh e ip rule: o caminho até fora

O ip route mostra a tabela de routing. A linha que importa é a rota por omissão:

# ip route
default via 192.168.1.1 dev enp0s3 proto dhcp metric 100
192.168.1.0/24 dev enp0s3 proto kernel scope link src 192.168.1.50

Sem linha default, a máquina chega à LAN mas não sai dela — causa clássica de “funciona localmente, não chega à Internet”. Com duas placas de rede (LAN + VPN), duas rotas por omissão em conflito resolvem-se pela métrica: vence a soma mais baixa e o campo metric na saída mostra o valor em jogo.

O ip route get responde directamente a “que rota o kernel escolhe para este destino?” — faz a resolução exacta que um pacote real sofreria, sem enviar nenhum:

# ip route get 8.8.8.8
8.8.8.8 via 192.168.1.1 dev enp0s3 src 192.168.1.50 uid 0

Mostra a decisão de encaminhamento local — interface, gateway e IP de origem escolhidos. Não substitui o traceroute quando a pergunta é “por onde passa o tráfego”: não segue os saltos ao longo do percurso. Com from, oif ou dport, simula cenários — ip route get 8.8.8.8 oif ens19 testa a rota que uma ligação forçada pela segunda placa tomaria. Quando o resultado é Network is unreachable (ou falha sem saída), não existe caminho — e o problema está na tabela de routing, não no destino.

O ip neigh é a tabela ARP/NDP:

# ip neigh
192.168.1.1 dev enp0s3 lladdr aa:bb:cc:dd:ee:ff REACHABLE
192.168.1.60 dev enp0s3 INCOMPLETE

REACHABLE é vizinho confirmado. STALE é apenas a cache a expirar — não é, por si só, prova de falha. INCOMPLETE significa que a resolução ARP ainda está a decorrer (aguarda ou falha ao terminar) e FAILED que as tentativas esgotaram sem resposta — desligado, isolado por VLAN ou simplesmente sem responder; repete antes de concluir. O ip neigh get 192.168.1.1 dev enp0s3 força uma consulta directa a uma entrada.

O ip rule fecha o quadro em sistemas com policy routing (VPN, VRF, marcas de firewall). As três regras de omissão — prioridades 0, 32766 e 32767 — consultam as tabelas local, main e default. Qualquer regra extra que aí apareça redirecciona tráfego por IP de origem, porta ou marca, e é suspeita frequente quando “a rota existe mas o tráfego não sai por ela”:

# ip rule
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

4. ping: tamanhos, contagem e tempos

O ping do iputils tem exit codes definidos que os scripts aproveitam: 0 quando o host respondeu, 1 quando não chegou resposta (ou chegaram menos pacotes do que os pedidos até ao prazo), 2 para outros erros. ping host && echo ok já é um teste automatizável.

Os parâmetros do dia-a-dia:

# ping -c 4 -W 1 192.168.1.1        # 4 pacotes, 1 s de timeout por resposta
# ping -c 10 -i 0.5 nas01           # intervalo de 0,5 s entre pacotes
# ping -c 1 -w 2 8.8.8.8            # sai aos 2 s com ou sem resposta (prazo global)

-c limita a contagem, -i o intervalo (um utilizador normal não pode descer de 2 ms — valores menores exigem root), -w fixa o prazo total do comando e -W o tempo de espera por resposta. O teste de MTU usa o tamanho de pacote:

# ping -s 1400 -M do -c 2 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 1400(1428) bytes of data.
1408 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=8.73 ms

O -s define os bytes de dados (56 por omissão — “64 bytes” na saída são os 56 + 8 do cabeçalho ICMP). Com -M do, o ping fixa o bit DF: se -s 1472 passa e 1473 falha com “Message too long”, o caminho tem MTU 1500 — e o problema de “ficheiros grandes falham, pequenos passam” fica identificado. No sumário final, o campo mdev mede a variabilidade do RTT: um mdev alto com média boa é jitter — mau sinal para voz e para bases de dados.

5. ss: portas em uso e estatísticas

O ss substitui o netstat — mostra mais estados TCP e lê directamente o kernel. A combinação mais usada lista o que está em escuta:

# ss -tulpn
Netid  State   Recv-Q  Send-Q   Local Address:Port   Peer Address:Port  Process
tcp    LISTEN  0       128          0.0.0.0:22           0.0.0.0:*      users:(("sshd",pid=812,fd=3))
tcp    LISTEN  0       511                *:80                 *:*      users:(("nginx",pid=1044,fd=6))
tcp    LISTEN  0       4096         127.0.0.53:53          0.0.0.0:*      users:(("systemd-resolve",pid=690,fd=17))

Leitura directa: 127.0.0.1:5432 em escuta significa que o PostgreSQL só aceita ligações locais — “responde no servidor, não de outra máquina” é este campo, e a correcção está na configuração do serviço (0.0.0.0 para todas as interfaces), não na rede. O users:((...)) identifica o processo e o PID directamente.

Filtros rápidos: ss -tlnp sport = :443 isola a porta 443 e ss -tn state established dst 192.168.1.0/24 lista sessões activas para uma subrede. O ss -s resume a caixa de estatísticas — útil quando há dezenas de milhares de sockets:

# ss -s
Total: 184
TCP:   24 (estab 12, closed 0, orphaned 0, timewait 8)

Transport Total     IP        IPv6
RAW     1         0         1
UDP     5         3         2
TCP     24        12        12
INET    30        15        15
FRAG    0         0         0

estab é o número de ligações estabelecidas (lido do SNMP CurrEstab). Um valor que sobe sem explicação pode indicar uma fuga de ligações na aplicação. Em containers mínimos sem ss, os mesmos dados vivem em /proc/net/dev (contadores de bytes, erros e drops por interface — o formato está documentado em proc_net(5)) e em /sys/class/net/<iface>/ — para a interface do exemplo, /sys/class/net/enp0s3/: operstate dá o estado RFC 2863 (up, down, dormant, …), carrier dá 1/0 para o link físico, speed a velocidade em Mbit/s e mtu o MTU. É o mesmo que o ip/ss leem, em ficheiros de texto puro.

6. DNS: getent hosts (NSS) vs resolvectl query

Aqui vive a distinção que resolve metade dos falsos diagnósticos de DNS: há dois mecanismos de resolução na mesma máquina.

O getent hosts consulta o NSS — a cadeia em /etc/nsswitch.conf (hosts: files resolve ... dns): /etc/hosts, módulos do systemd-resolved, DNS. É o teste certo para “a aplicação consegue resolver este nome?” — com uma distinção: a man page do getent(1) diz que getent hosts passa a chave ao gethostbyname2(3); quem quiser o caminho exacto das aplicações — getaddrinfo(3) com AF_UNSPEC, IPv4 e IPv6 — usa getent ahosts. E nem isso reproduz aplicações que trazem resolvedor próprio. Sem resposta, sai com o exit code 2:

# getent hosts fileserver01
192.168.1.10    fileserver01

O resolvectl query passa pelo systemd-resolved directamente — responde por DNS, MulticastDNS ou LLMNR, mostra o protocolo usado, a interface e a validação DNSSEC, e consulta os servidores reais em vez do stub:

# resolvectl query www.kbase.pt
www.kbase.pt: 188.114.96.5
              188.114.97.5

-- Information acquired via protocol DNS in 12.3ms.
-- Data is authenticated: no

Em sistemas com systemd-resolved, o /etc/resolv.conf é normalmente um symlink para /run/systemd/resolve/stub-resolv.conf — que aponta os clientes ao stub 127.0.0.53. A leitura do ficheiro não diz quais são os servidores DNS a montante: esses aparecem no resolvectl status, por interface, com a origem (DHCP, ficheiro de rede, resolved.conf):

# resolvectl status enp0s3
Link 2 (enp0s3):
    Current Scopes: DNS
         Protocols: +IPv4 +IPv6
 Current DNS Server: 192.168.1.1
        DNS Servers: 192.168.1.1

O fluxo de diagnóstico fica assim: getent hosts falha mas resolvectl query funciona: suspeita primeiro da cadeia NSS — confere a entrada hosts: no /etc/nsswitch.conf e o nome exacto que a aplicação consulta (um nome fora do /etc/hosts da máquina explica metade destes casos). Ambos falham: o DNS é o principal suspeito — testa o 192.168.1.1 com ping, compara com um servidor externo e confirma no resolvectl status que os servidores estão de pé. Numa máquina sem systemd-resolved, o /etc/resolv.conf é o ficheiro clássico — até 3 nameserver, consultados por ordem. Sem entradas, o resolver consulta a máquina local. Para ver o servidor a responder isoladamente, o drill (pacote ldnsutils) ou o dig/nslookup (pacote bind9-dnsutils) interrogam um servidor específico com @servidor — nenhum vem em imagens mínimas.

7. HTTP: curl e wget

O curl confirma que, passada a porta, a aplicação responde:

# curl -s -o /dev/null -w '%{http_code}\n' http://intranet01/
200

200 é o serviço a responder, 401/403 é porta aberta com autenticação em falta e 404 é caminho inexistente. Timeout ou recusa remete para os comandos anteriores — o TCP pode estar bem e a aplicação mal. Duas medidas de tempo separam rede de aplicação:

# curl -s -o /dev/null -w 'connect=%{time_connect} total=%{time_total}\n' --connect-timeout 5 http://intranet01/
connect=0.002 total=0.041

O --connect-timeout limita só o estabelecimento TCP/TLS (útil para distinguir “não abre ligação” de “resposta lenta”) e -m limita a transferência inteira. O -I pede só cabeçalhos, e -L segue redireccionamentos — um 301 que nunca resolve é o sintoma clássico de HTTP→HTTPS mal configurado. Com proxy na rede, --proxy http://proxy01:8080 separa erros de proxy de erros de destino. O wget cobre o mesmo teste mínimo sem corpo nem saída:

# wget -q --spider http://intranet01/ && echo OK
OK

--spider verifica a existência do recurso sem o descarregar, e o -q silencia o resto. O exit code do wget serve os scripts da mesma forma que o do ping.

8. Serviços: journalctl -u

A última pergunta do diagnóstico é “o serviço arrancou e que erros deu?” — e a resposta vive no journal:

# journalctl -u nginx.service -n 50 --no-pager
# journalctl -u systemd-networkd -b          # só o boot actual
# journalctl -u nginx.service -f             # seguir em tempo real

O -u filtra por unidade systemd, o -n limita as linhas (10 por omissão), o -b restringe ao arranque actual e o --no-pager evita o pager em sessões SSH registadas em log. Num problema de rede de um serviço específico — “não liga à base de dados” — esta é a fonte que diz se o serviço sequer tentou, qual endereço usou e que erro recebeu. O systemctl status nginx.service acrescenta as últimas linhas do journal ao estado da unidade num só comando.

9. Diagnóstico guiado em 60 segundos

A ordem de cima para baixo — cada passo confirma o anterior antes de continuar:

# 1. A placa de rede tem link?                    (cabo, driver)
ip -br link
# 2. Tem IP e prefixo?
ip -br addr
# 3. A rota por omissão existe e aponta ao gateway certo?
ip route show default
# 4. O gateway responde?
ping -c 2 -W 1 192.168.1.1
# 5. Chega ao exterior pelo caminho certo?
ip route get 8.8.8.8 && ping -c 2 -W 1 8.8.8.8
# 6. O nome resolve (como a aplicação resolve)?
getent hosts fileserver01
# 7. O servidor DNS real responde?
resolvectl query fileserver01
# 8. O serviço SMB está à escuta neste servidor? (ss só vê sockets locais)
ss -tlnp | grep :445\ncurl -s -o /dev/null -w '%{http_code}\n' http://fileserver01/
# 9. O serviço está vivo e que erros dá?
journalctl -u smb.service -n 20 --no-pager

Interpretação directa: falha no 1-2 = problema local (cabo, driver, DHCP). Passa o 1-2 e falha o 3-4 = rota ou gateway. Passa o 4-5 e falha o 6 = DNS (compara os dois mecanismos da secção 6). Passa o 6-7 e falha o 8 = firewall ou serviço parado — o ss -tlnp no próprio servidor confirma a escuta, e o journalctl fecha o caso. Nota: o ping a um host sem resposta ICMP não prova falha — alguns filtram ICMP. Testa a porta do serviço.

10. Erros Comuns

Problema Causa provável Solução
Interface com UP mas sem LOWER_UP Cabo desligado, porta do switch desactiva, VLAN sem porta no switch Verificar cabo/switch; /sys/class/net/<iface>/carrier confirma (1 = link)
ping funciona mas as aplicações falham ICMP filtrado a meio do caminho, ou problema de porta/DNS Testar a porta real com ss/curl; não usar o ping como prova de serviço
getent hosts devolve um IP, o dig/resolvectl query devolve outro /etc/hosts ou outro módulo NSS tem prioridade sobre o DNS Comparar a cadeia hosts: de /etc/nsswitch.conf; corrigir a entrada em /etc/hosts
resolvectl query falha mas o getent hosts funciona cache do resolved sobre uma entrada de /etc/hosts recente (o resolved também o lê por omissão — a cache é a diferença) Repetir com resolvectl flush-caches; se persistir, compara a entrada no /etc/hosts
Serviço acessível localmente mas não de outra máquina Escuta em 127.0.0.1 em vez de 0.0.0.0/:: ss -tlnp no servidor e corrigir o endereço de escuta no serviço
ip route get devolve Network is unreachable Sem rota para o destino (ou tabela errada com policy routing) Confirmar ip route e ip rule; verificar a rota por omissão
ss -tulpn não mostra o PID Consola sem privilégios suficientes para ver os processos alheios Correr como root (o ss -p só mostra processos do mesmo utilizador)
curl devolve 000 e sai sem mensagem Sem resposta HTTP antes do timeout — sem rota, firewall a descartar ou serviço em baixo (o 000 diz ‘sem resposta’; lê a mensagem de erro e o exit code do curl para a causa exacta) Repetir com -v e --connect-timeout 5; isolar TCP com os passos anteriores

11. Checklist

  • [ ] Placa de rede activa com link físico: ip -br link (UP + LOWER_UP)
  • [ ] IP e prefixo correctos: ip -br addr (IPv4 global; sem 169.254.x.x)
  • [ ] Rota por omissão presente: ip route (default via …)
  • [ ] Gateway responde: ping -c 2 -W 1 <gateway>
  • [ ] Caminho até fora correcto: ip route get 8.8.8.8
  • [ ] Nome resolve como a aplicação resolve: getent hosts <nome>
  • [ ] DNS real responde: resolvectl query <nome> (ou resolvectl status)
  • [ ] Porta em escuta no servidor: ss -tlnp sport = :<porta>
  • [ ] Porta acessível de fora: curl -s -o /dev/null -w '%{http_code}'
  • [ ] Serviço sem erros no journal: journalctl -u <serviço> -n 20 --no-pager

Artigos Relacionados

Fontes Oficiais