«O servidor não responde.» Antes de culpar a aplicação, a rede ou a firewall, há uma pergunta que se responde em segundos: a porta está aberta? O nc — o netcat — responde-lhe numa linha e ainda monta ouvintes, transfere ficheiros e fala com serviços em protocolo escrito à mão. Não é por acaso que lhe chamam o canivete suíço do TCP/IP.
Seguimos a ordem do vídeo: -z e -v, intervalos de portas e -n, ouvintes com -l, -p e -k, transferência de ficheiros, -u e -w, e HTTP à mão. No fim, o ângulo defensivo: reconhecer, com ss e lsof, um nc à escuta ou uma shell reversa que não deviam estar na máquina.
Veja o guia em vídeo
Prefere ver antes de experimentar? No canal HJFR-IT no YouTube mostramos o nc (netcat) opção a opção, com o resultado de cada comando no ecrã — narrado em português e com legendas.
O que faz o nc
O nc lê e escreve dados em bruto numa ligação TCP ou UDP, sem interpretar nada: o que entra pelo teclado (ou por um pipe) sai pela rede, e o que chega da rede sai no ecrã. Tem dois modos — cliente, que se liga a um destino e a uma porta, e ouvinte (-l), que espera ligações.
nc [opções] DESTINO PORTA # cliente: liga-se a DESTINO:PORTA
nc -l [opções] [-p] PORTA # ouvinte: espera ligações em PORTA
No Debian e no Ubuntu, o nc é normalmente a variante netcat-openbsd, a usada aqui; a netcat-traditional e o ncat (projeto Nmap) diferem em pormenores.
Testar uma porta: -z e -v
O -z (zero I/O) manda o nc só verificar se a ligação se estabelece, sem enviar dados; o -v (verbose) mostra o resultado.
$ nc -zv srv-web01 443
Connection to srv-web01 (192.0.2.10) 443 port [tcp/https] succeeded!
$ nc -zv srv-web01 8080
nc: connect to srv-web01 port 8080 (tcp) failed: Connection refused
Responde à pergunta clássica do diagnóstico — o serviço está a atender, ou o problema está pelo caminho? —, desde que saiba ler as três respostas:
- succeeded — aberta: o handshake TCP completou-se e há um processo à escuta.
- Connection refused — fechada: a máquina respondeu com um RST, mas não há serviço. O problema não é a rede.
- timed out (com
-w) — filtrada: ninguém respondeu, quase sempre por causa de uma firewall.
Em scripts, basta o código de saída: 0 se a ligação teve êxito, 1 se falhou.
Varrer um intervalo de portas
O nc aceita um intervalo, separado por um traço, e testa as portas uma a uma:
$ nc -zv srv-web01 20-25 2>&1
nc: connect to srv-web01 port 20 (tcp) failed: Connection refused
nc: connect to srv-web01 port 21 (tcp) failed: Connection refused
Connection to srv-web01 (192.0.2.10) 22 port [tcp/ssh] succeeded!
nc: connect to srv-web01 port 23 (tcp) failed: Connection refused
nc: connect to srv-web01 port 24 (tcp) failed: Connection refused
nc: connect to srv-web01 port 25 (tcp) failed: Connection refused
Só a 22, o ssh, atende — assim se confirma o que um servidor expõe. O 2>&1 junta ao stdout as mensagens do -v, que vão para o stderr, para as podermos filtrar num pipe. E varrer portas faz-se apenas em máquinas suas ou com autorização explícita: em sistemas alheios é intrusivo e pode ter consequências legais.
Sem DNS: -n
Com -n, o nc não resolve nomes nem traduz portas em serviços: é mais rápido e não depende de um DNS que pode estar avariado. Daí o [tcp/*]:
$ nc -zvn 192.0.2.10 20-25 2>&1 | grep succeeded
Connection to 192.0.2.10 22 port [tcp/*] succeeded!
Correr um ouvinte: -l, -p e -k
Com -l (listen), uma máquina espera ligações numa porta — o lado servidor; noutra, o nc sem -l liga-se — o lado cliente. O que se escreve num lado aparece no outro: é a base de quase tudo o que o netcat faz.
# no srv-web01 (ouvinte)
$ nc -lv -p 9000
Listening on 0.0.0.0 9000
Connection received on 192.0.2.25 51560
# no hjfr (cliente)
$ nc srv-web01 9000
olá do hjfr
-p PORTA— com-l, a porta de escuta (a openbsd aceita tambémnc -l 9000, mas-l -pfunciona em todas); sem-l, a porta de origem do cliente.-k— o ouvinte não termina com a primeira ligação e aceita a seguinte. Prático, e perigoso se ficar esquecido.
Transferir ficheiros entre máquinas
Se o cano liga dois terminais, podemos empurrar um ficheiro por ele: no destino, o nc ouve e a saída vai para um ficheiro (>); na origem, o nc é alimentado pelo ficheiro (<). O -N fecha a ligação no fim — sem ele, os dois lados ficam à espera de um Ctrl+C.
$ nc -l -p 9000 > recebido.tar.gz # no destino
$ nc -N srv-web01 9000 < backup.tar.gz # na origem
# o mesmo par com pipes: uma pasta inteira, sem ficheiro intermédio
$ nc -l -p 9000 | tar xzvf - # no destino
$ tar czf - site/ | nc -N srv-web01 9000 # na origem
É prático num laboratório, mas o nc simples não cifra nem verifica nada: confirme com sha256sum dos dois lados e, em redes não confiáveis, use scp ou rsync sobre ssh.
UDP e tempos limite: -u e -w
-u: serviços UDP
O -u passa de TCP para UDP, necessário para serviços como o DNS (53):
$ nc -zvu srv-web01 53
Connection to srv-web01 (192.0.2.10) 53 port [udp/domain] succeeded!
Cautela: o UDP não tem handshake. O nc só sabe que a porta está fechada se voltar um ICMP port unreachable; o silêncio quer dizer «aberta ou filtrada». Para ter a certeza, fale o protocolo — por exemplo, dig @192.0.2.10 example.com.
-w: não ficar pendurado
O -w define um tempo limite em segundos. Sem ele, uma porta filtrada deixa o nc pendurado enquanto o núcleo retransmite o SYN — no Linux, perto de dois minutos:
$ nc -zv -w 3 srv-web01 3306
nc: connect to srv-web01 port 3306 (tcp) timed out: Operation now in progress
É essencial em scripts. E repare: o MySQL está à escuta, mas a firewall descarta o tráfego da rede local — à escuta não é o mesmo que acessível.
Falar HTTP à mão
Como o nc é um cano em cru, podemos escrever nós o protocolo. Um pedido HTTP mínimo — um GET e uma linha em branco — devolve a resposta crua, com cabeçalhos e o início da página:
$ printf 'GET / HTTP/1.0\r\n\r\n' | nc srv-web01 80
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)
Content-Type: text/html
Connection: close
<!DOCTYPE html>
...
É didático e um bom diagnóstico quando o curl esconde pormenores: o nc mostra tudo, tal como vai na rede (para HTTPS, use openssl s_client). O mesmo princípio dá o banner grabbing — no SSH, é o servidor que fala primeiro:
$ nc -v -w 2 srv-web01 22
Connection to srv-web01 (192.0.2.10) 22 port [tcp/ssh] succeeded!
SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.5
Nos seus servidores, serve para inventariar as versões expostas — e o Server: acima mostra que convém esconder a do nginx (server_tokens off;).
nc em cibersegurança
Uma ferramenta de dupla utilização. O nc que valida uma firewall serve a um atacante para reconhecimento ou para manter acesso. A regra é a do vídeo: testar só sistemas seus ou com autorização explícita, de preferência escrita e com âmbito definido.
Validar firewalls e segmentação. Depois de cada alteração de regras, confirme a partir de cada segmento de rede que só respondem as portas previstas. Com -z, -w e o código de saída, um pequeno script torna a verificação repetível e deteta portas abertas sem aviso.
Reconhecer um nc que não devia lá estar. Numa máquina comprometida, o netcat surge como ouvinte inesperado (bind shell) ou como ligação de saída para um IP externo (shell reversa). O sudo ss -tlnp mostra os sockets à escuta e o processo dono — um nc numa porta alta, com backlog 1, é alarme. O sudo ss -tnp state established revela o sinal clássico de uma shell reversa: uma sh com os descritores 0, 1 e 2 num socket. O lsof -nP -i acrescenta o utilizador; se for www-data, suspeite da aplicação web. Não mate os processos à pressa: registe as saídas, preserve /proc/<PID>, isole a máquina e siga o procedimento de resposta a incidentes.
Experimente no simulador interativo
O simulador recria um laboratório com o posto aluno@hjfr (192.0.2.25) e o servidor srv-web01 (192.0.2.10), com uma firewall a bloquear a 3306 e dois processos que não deviam lá estar. Cada comando desenha a ligação pacote a pacote e mostra os sockets do servidor por dentro; no terminal, as linhas com barra dourada são o ecrã do servidor. Demonstrar tudo percorre a sequência pela ordem do vídeo, Anterior e Seguinte avançam ao seu ritmo, os botões de cada grupo executam uma opção e Repor estado volta ao início.
Erros comuns e boas práticas
- Esquecer o
-wem scripts: uma porta filtrada prende o nc durante minutos. Ponha sempre um tempo limite. - Ler «succeeded» em UDP como certeza: só quer dizer que não chegou nenhum erro.
- Confundir fechada com filtrada: refused é falta de serviço; timed out aponta para uma firewall.
- Enviar dados sensíveis em claro: o nc não cifra. Fora do laboratório, use
scpoursyncsobre ssh. - Deixar ouvintes esquecidos: um
nc -lka correr é uma porta aberta que ninguém vigia; confirme comss -tlnp. - Varrer o que não é seu: sem autorização explícita, um varrimento de portas é intrusivo e pode ter consequências legais.
Conclusão
O nc faz uma coisa simples — ler e escrever dados numa ligação — e daí tira o resto: -zv, intervalos e -n para testar portas, -l, -p e -k para ouvir, redirecionamentos para ficheiros, -u, -w e protocolos à mão. Use-o só onde tem autorização. Para ver o outro lado das ligações, junte-lhe o comando ss, que mostra os sockets da própria máquina, e o comando tcpdump, que mostra os pacotes tal como passam na rede.
Workshop — Linha de Comandos Linux
Quer passar da leitura à prática, com exercícios reais e acompanhamento? No workshop Linha de Comandos Linux da HJFR trabalha estes e outros comandos da série — da administração do dia a dia à resposta a incidentes.
Este artigo faz parte da série «Comandos Linux, um a um» do blog HJFR — fique atento aos próximos comandos.
