Administração Linux
Redes no Linux: ip, roteamento, DNS, sockets, firewalls e túneis SSH
Intermediário9 min de leituraAtualizado
Esta página foi traduzida do inglês com a ajuda de IA e conferida com o original. Ler a versão em inglês
Problemas de rede costumam ser diagnosticados na ordem errada, e é por isso que demoram tanto. Este guia percorre a pilha do mesmo jeito que um pacote — interface, endereço, rota, nome, porta — e mostra o comando moderno para inspecionar cada camada. Depois aborda firewalls com o nftables e seus front ends, o valor de diagnóstico do curl e do dig e os truques de túnel SSH que fazem você passar por um bastion host.
O que você vai aprender
- Inspecionar e configurar interfaces, endereços e rotas com o comando ip
- Explicar como um nome vira um endereço e depurar a resolução com dig e resolvectl
- Listar sockets em escuta e estabelecidos com ss e chegar ao processo dono de cada um
- Escrever e inspecionar regras de firewall com nftables, ufw ou firewalld
- Isolar uma falha de conectividade camada por camada e acessar um serviço privado por um túnel SSH
A maioria dos problemas de rede no Linux acaba sendo uma de cinco coisas: a interface não tem endereço, não existe rota até o destino, o nome não resolve, nada está escutando na porta ou um firewall está descartando o pacote. Conhecer essa lista, e ter um comando para cada item, transforma uma tarde de tentativa e erro em uma verificação de cinco minutos.
As ferramentas também mudaram. ifconfig, netstat, route e arp vinham do pacote net-tools, que está sem manutenção e não aparece nas instalações padrão; ip e ss, do iproute2, tomaram o lugar deles e mostram coisas que as ferramentas antigas não enxergam. Este guia usa os comandos modernos, cita os nomes antigos uma vez para você conseguir ler documentação mais velha e parte do princípio de que o host é um Debian, Ubuntu ou da família RHEL atual.
As camadas com que você realmente lida
Você não precisa do modelo completo de sete camadas para trabalhar bem, mas quatro níveis são inevitáveis no diagnóstico do dia a dia:
- Enlace — uma interface de rede com um endereço MAC, conectada a um segmento. É a camada do
ip link. O ARP (ip neigh) mapeia endereços IP para endereços MAC dentro de um segmento. - Rede — endereços IP e rotas. Levar um pacote deste host até um destino é trabalho do
ip addre doip route. - Transporte — portas TCP e UDP, conexões, sockets em escuta. É a camada do
ss. - Aplicação — HTTP, DNS, TLS.
curl,dig,openssl s_client.
Um endereço é escrito com o comprimento do prefixo: 10.0.3.17/24 significa que os primeiros 24 bits identificam a rede, então de 10.0.3.0 a 10.0.3.255 é tudo local e o resto precisa passar por um roteador. Errar esse número produz aquele sintoma enlouquecedor em que alguns destinos funcionam e outros não.
Três faixas privadas — 10.0.0.0/8, 172.16.0.0/12 e 192.168.0.0/16 — são reservadas para uso interno e nunca são roteadas na internet pública, e é por isso que VPCs na nuvem e redes domésticas se parecem tanto. 127.0.0.0/8 é o loopback, que existe inteiramente dentro do kernel. Endereços IPv6 aparecem ao lado dos IPv4 na maioria das redes modernas; endereços fe80::/10 são link-local, válidos em um único segmento, e sempre levam um sufixo %interface quando você os usa.
Interfaces, endereços e rotas
$ ip -brief addr
lo UNKNOWN 127.0.0.1/8 ::1/128
eth0 UP 10.0.3.17/24 fe80::5054:ff:fe12:3456/64
$ ip route
default via 10.0.3.1 dev eth0 proto dhcp src 10.0.3.17 metric 100
10.0.3.0/24 dev eth0 proto kernel scope link src 10.0.3.17
A flag -brief dá a visão resumida; ip addr puro acrescenta MTU, flags e tempos de validade. Leia a tabela de roteamento do prefixo mais específico para o menos específico: o kernel escolhe o prefixo correspondente mais longo, de modo que 10.0.3.0/24 cuida do segmento local e default pega todo o resto, enviando-o para o gateway 10.0.3.1.
ip route get responde à pergunta diretamente e poupa você de apertar os olhos:
$ ip route get 93.184.216.34
93.184.216.34 via 10.0.3.1 dev eth0 src 10.0.3.17 uid 1000
Alterações feitas com ip são imediatas e se perdem no reboot, o que as torna ideais para testes e inadequadas para configuração:
sudo ip link set eth0 up
sudo ip addr add 10.0.3.200/24 dev eth0
sudo ip route add 10.50.0.0/16 via 10.0.3.254
sudo ip addr flush dev eth0 # careful: this drops your SSH session
A configuração persistente fica a cargo do gerenciador que a distribuição usa: YAML do netplan em /etc/netplan/ no Ubuntu Server, perfis de conexão do NetworkManager (nmcli) em desktops e servidores Fedora e da família RHEL, ou arquivos .network do systemd-networkd em imagens mínimas.
sudo netplan try # applies with an automatic rollback after 120 s
nmcli con mod eth0 ipv4.addresses 10.0.3.17/24 ipv4.gateway 10.0.3.1 ipv4.method manual
nmcli con up eth0
O netplan try e o rollback do NetworkManager existem porque uma alteração de endereço errada em um host remoto deixa você trancado do lado de fora. Use-os, ou agende um reboot antes de fazer a mudança.
Resolução de nomes
Os programas não chamam o DNS diretamente. Eles chamam o resolver da biblioteca C, que consulta o /etc/nsswitch.conf para decidir a ordem das fontes — normalmente files (ou seja, /etc/hosts), depois um stub resolver local e, por fim, o DNS. Portanto, o /etc/hosts tem prioridade sobre o DNS, o que faz dele ao mesmo tempo um jeito útil de sobrescrever valores e uma causa frequente de "só funciona naquele servidor".
Em sistemas que rodam o systemd-resolved — o padrão no Ubuntu e, cada vez mais, em outras distribuições —, o /etc/resolv.conf é um link simbólico para um arquivo stub que aponta para 127.0.0.53. Editá-lo à mão não adianta nada: ele é regerado. Consulte a configuração real:
$ resolvectl status | sed -n '1,12p'
Global
Protocols: LLMNR=resolve -mDNS +DNSOverTLS DNSSEC=no/unsupported
Link 2 (eth0)
Current Scopes: DNS
DNS Servers: 10.0.0.2 10.0.0.3
DNS Domain: internal.example.com
$ resolvectl query api.internal.example.com
api.internal.example.com: 10.0.4.21
O dig é a ferramenta para interrogar o próprio DNS, passando totalmente por fora da biblioteca:
dig +short api.example.com # just the answer
dig api.example.com A +noall +answer # the answer section with TTLs
dig @1.1.1.1 example.com MX # ask a specific server
dig +trace example.com # follow delegation from the root
dig -x 93.184.216.34 # reverse lookup
Vale a pena internalizar a distinção feita no FAQ acima: o dig diz o que o DNS responde; o getent hosts name diz o que as suas aplicações vão receber. Quando os dois discordam, a resposta está no /etc/hosts, no nsswitch.conf ou no stub resolver, não na zona.
O cache traz sua própria dose de confusão. O TTL de um registro define por quanto tempo os resolvers podem manter a resposta antiga, então uma mudança que "ainda não propagou" normalmente é só um TTL que ainda não expirou. Limpe o cache local com sudo resolvectl flush-caches e consulte o servidor autoritativo com dig @ns1.example.com antes de concluir que algo está quebrado.
Portas e sockets
O ss substitui o netstat e é muito mais rápido em hosts com muita carga. As flags que vale decorar são -l (em escuta), -t/-u (TCP/UDP), -n (numérico, sem resolução de nomes) e -p (processo dono, exige root).
$ sudo ss -ltnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=1842,fd=5))
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1201,fd=6))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=980,fd=3))
A coluna de endereço local é a primeira coisa a ler quando um serviço está inacessível. 127.0.0.1:5432 só aceita conexões do próprio host; 0.0.0.0:80 aceita de qualquer lugar, em qualquer interface; [::]:80 é o equivalente em IPv6, e no Linux um socket vinculado a [::] normalmente também aceita conexões IPv4. Vincular um serviço ao loopback e colocá-lo atrás de um reverse proxy é um bom padrão, e é exatamente o que o guia da stack LAMP faz com o PHP-FPM.
Outras formas úteis:
ss -tan state established # current TCP connections
ss -tn dst 10.0.4.21 # connections to one host
ss -s # summary counters by protocol
ss -tlnp 'sport = :8080' # who owns port 8080
Em um socket em escuta, Recv-Q é o número de conexões aguardando para serem aceitas; um valor que continua diferente de zero significa que a aplicação não está aceitando rápido o bastante. Em um socket estabelecido, as filas mostram os bytes não lidos e não confirmados, e é assim que você identifica um leitor travado.
Portas abaixo de 1024 são privilegiadas: só o root, ou um processo com CAP_NET_BIND_SERVICE, pode fazer bind nelas. É por isso que servidores de aplicação escutam na 8080 e um proxy ou uma unidade socket do systemd cuida da 80 e da 443.
Firewalls
Os kernels modernos filtram com o nftables, que substituiu o iptables. A maioria dos administradores o controla por meio de um front end.
O ufw (Debian e Ubuntu) é minimalista de propósito:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH # named application profile
sudo ufw allow 80,443/tcp
sudo ufw allow from 10.0.0.0/8 to any port 5432 proto tcp
sudo ufw enable
sudo ufw status verbose
O firewalld (família RHEL) organiza as regras em zonas, e cada zona se aplica a um conjunto de interfaces ou origens:
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --add-service=https --permanent
sudo firewall-cmd --zone=public --add-port=8080/tcp --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
A flag --permanent grava a regra em disco sem aplicá-la; sem ela, a regra é aplicada sem ser salva. Fazer as duas coisas e depois --reload é a sequência confiável — e a forma que vale apenas em runtime é uma verdadeira proteção quando você edita regras por SSH, porque um reboot desfaz o erro.
Mesmo que você use um front end, vale a pena entender como escrever regras do nftables diretamente:
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
iif lo accept
ip protocol icmp accept
tcp dport { 22, 80, 443 } accept
tcp dport 5432 ip saddr 10.0.0.0/8 accept
}
}
Leia de cima para baixo: o padrão é descartar, respostas a conexões iniciadas por este host são aceitas graças ao connection tracking, o loopback não tem restrições, e ficam abertas três portas mais uma porta de banco de dados restrita por origem. sudo nft list ruleset mostra o que está carregado, e o /etc/nftables.conf junto com systemctl enable nftables torna tudo persistente.
Dois cuidados. Primeiro, sempre libere o SSH antes de definir uma política padrão de negação, e mantenha uma segunda sessão aberta. Segundo, em um ambiente de nuvem existe um segundo firewall — um security group ou uma ACL de rede — totalmente fora da máquina; um pacote bloqueado ali nunca chega ao host, e nada no nft list ruleset vai dar qualquer pista disso.
Diagnosticando de fora para dentro
O ping testa a alcançabilidade via ICMP, que muitas redes e a maioria dos load balancers de nuvem bloqueiam de propósito, então um ping que falha prova muito pouco. Estes comandos provam mais:
curl -sS -o /dev/null -w '%{http_code} %{time_total}s\n' https://example.com/health
curl -v --connect-timeout 3 https://api.internal:8443/status
curl --resolve api.example.com:443:10.0.4.21 https://api.example.com/ # bypass DNS, test one backend
openssl s_client -connect example.com:443 -servername example.com </dev/null | head -20
mtr -rwc 20 10.0.4.21 # traceroute plus per-hop loss, over 20 cycles
tcpdump -ni eth0 'tcp port 5432 and host 10.0.4.21'
O curl -v é o diagnóstico mais valioso desta lista porque narra cada etapa: resolução DNS, conexão TCP, handshake TLS com a cadeia de certificados, requisição e cabeçalhos de resposta. O ponto em que ele para diz qual camada falhou. Um travamento em "Trying 10.0.4.21:443" é um firewall descartando pacotes em silêncio; um "Connection refused" imediato significa que o pacote chegou e nada estava escutando — problemas muito diferentes com o mesmo sintoma visível para o usuário.
O tcpdump é o último recurso, e o definitivo: se você vê o SYN sair e nenhum SYN-ACK voltar, o problema está além deste host. Grave a captura em um arquivo com -w capture.pcap quando precisar analisá-la com calma.
SSH como encanamento de rede
Além de logins, o SSH encaminha conexões TCP, e é assim que você chega a um banco de dados ou a uma interface de administração que não está exposta publicamente.
# Local forward: localhost:15432 on my laptop -> db.internal:5432, via the bastion
ssh -N -L 15432:db.internal:5432 [email protected]
psql -h 127.0.0.1 -p 15432 -U app orders
# SOCKS proxy: a browser can then reach anything the bastion can
ssh -N -D 1080 [email protected]
# Jump host in one hop, without an agent on the bastion
ssh -J [email protected] [email protected]
-N significa "nenhum comando remoto": você ganha um túnel, sem shell. Coloque os detalhes uma única vez em ~/.ssh/config e a complexidade some:
Host bastion
HostName bastion.example.com
User alice
IdentityFile ~/.ssh/id_ed25519
Host db
HostName db.internal
User alice
ProxyJump bastion
LocalForward 15432 db.internal:5432
O agent forwarding (-A) é prático e arriscado: o root do host intermediário pode usar o seu agente para se autenticar em outros lugares como se fosse você. O ProxyJump chega ao mesmo resultado sem expor o agente e deveria ser a escolha padrão.
Uma ordem de operações
Quando algo não consegue alcançar outra coisa, avance de dentro para fora e pare na primeira falha:
- Está escutando, e em qual endereço?
sudo ss -ltnp | grep :<port>. - Responde localmente?
curl -v http://127.0.0.1:<port>/. Se não responder, o problema é a aplicação — confira os logs dela comjournalctl -u, como descrito em processos e systemd. - O nome resolve, e para o endereço certo?
getent hosts <name>edig +short <name>. - Existe uma rota?
ip route get <address>. - O firewall do host permite?
sudo nft list ruleset,ufw status,firewall-cmd --list-all. - Algo fora do host está bloqueando? Security groups da nuvem, ACLs de rede, um proxy corporativo. Teste a partir de uma terceira máquina no mesmo segmento para separar as regras do host das regras da rede.
- O que dizem os pacotes?
tcpdumpnas duas pontas, se você chegar até aqui.
Erros comuns
- Fazer bind em
127.0.0.1e esperar acesso remoto. Confira o endereço local nossantes de mexer no firewall. - Editar o
/etc/resolv.confquando osystemd-resolvedo gerencia. O arquivo é regerado; configure o resolver em vez disso. - Confiar no
pingcomo teste de alcançabilidade. O ICMP é filtrado em muitos ambientes; teste a porta de verdade comcurlounc -vz. - Aplicar uma política de firewall de negação por padrão sem uma regra para o SSH. Adicione primeiro a regra de liberação, depois a política, e mantenha uma segunda sessão aberta.
- Configurar um endereço com
ip addr adde dar o trabalho por encerrado. Ele some no próximo boot; grave-o no netplan, no NetworkManager ou no systemd-networkd. - Esquecer o firewall do lado da nuvem. Metade dos chamados de "a porta está aberta, mas não consigo conectar" termina em um security group.
- Ignorar o IPv6. Um nome com registros A e AAAA pode ser acessado via IPv6, onde suas regras de firewall ou seu roteamento podem ser completamente diferentes. Teste separadamente com
curl -4ecurl -6.
Principais conclusões
- Diagnostique na ordem das camadas — interface, endereço, rota, nome, porta, firewall — e pare na primeira coisa que falhar.
ip addr,ip routeeip route getsubstituemifconfigeroute; as alterações feitas comipsão imediatas e, por design, não persistentes.- A resolução passa pelo
nsswitch.confe possivelmente por um stub resolver, então ogetent hostsreflete o que as aplicações enxergam, enquanto odigreflete o que o DNS diz. ss -ltnpe a coluna de endereço local respondem à maioria dos casos de "serviço inacessível" antes mesmo de o firewall entrar na história.- O nftables é o filtro do kernel; ufw e firewalld são front ends convenientes, e um security group da nuvem é um segundo firewall, invisível.
- O
curl -vnarra DNS, TCP, TLS e HTTP em um único comando, e otcpdumpencerra discussões sobre se os pacotes chegaram mesmo a sair. ssh -L,-DeProxyJump, escritos uma única vez em~/.ssh/config, dão a você acesso seguro a serviços privados sem expô-los.
Fontes e leituras complementares
Perguntas frequentes
- Por que o ifconfig não existe no meu servidor?
- O pacote net-tools, que fornecia ifconfig, netstat, route e arp, está sem manutenção há anos e não é mais instalado por padrão. Os substitutos vêm do iproute2: ip addr no lugar do ifconfig, ip route no lugar do route, ip neigh no lugar do arp e ss no lugar do netstat. Eles entendem recursos que o net-tools nunca aprendeu, como vários endereços por interface e roteamento por política, então aprenda os nomes novos em vez de instalar o pacote antigo.
- O serviço está rodando, mas não consigo acessá-lo de outra máquina. Por onde começo?
- Verifique em qual endereço ele está escutando antes de culpar a rede. Rode ss -ltnp e olhe a coluna de endereço local: 127.0.0.1:8080 só aceita conexões locais, enquanto 0.0.0.0:8080 aceita qualquer uma. Se o bind estiver correto, teste com curl a partir do próprio servidor, depois de fora, depois confira o firewall do host e, por fim, algum security group da nuvem. Avançar para fora nessa ordem isola a camada com problema em poucos minutos.
- Por que o dig retorna uma resposta quando o ping não consegue resolver o mesmo nome?
- O dig consulta um servidor DNS diretamente e ignora o resto do mecanismo de resolução. Programas comuns passam pela biblioteca C, que consulta o /etc/nsswitch.conf e, portanto, o /etc/hosts, o mDNS e qualquer stub resolver local antes do DNS ou no lugar dele. Use getent hosts nome para reproduzir exatamente o que uma aplicação enxerga; se os dois divergirem, o problema está na configuração, não no DNS.
- Qual a diferença entre o redirecionamento de porta SSH local e o remoto?
- O redirecionamento local, ssh -L, abre uma porta na sua máquina e encaminha as conexões, através do servidor SSH, até um destino que esse servidor consegue alcançar — o jeito habitual de chegar a um banco de dados que só escuta em uma rede privada. O redirecionamento remoto, ssh -R, abre uma porta no servidor SSH e traz as conexões de volta para a sua máquina, expondo algo local ao lado remoto. Em quase todos os casos, o que você quer é o local.