EQVPS
PainelComeçar

Como verificar as portas abertas de um VPS: o que está escutando, o que a internet vê e a surpresa do Docker

Veja cada porta em que o seu servidor escuta, descubra o processo por trás dela, escaneie o servidor de fora como um atacante faria e feche o que não precisa. Inclui a porta do Docker que continua aberta mesmo com o firewall ligado. Cada número foi medido num servidor Ubuntu 24.04 novo.

Uma porta aberta e esquecida é a forma clássica de entrar num servidor: um banco de dados num endereço público, um painel de depuração, um container que publicou uma porta que ninguém queria publicar. A verificação leva um minuto quando você conhece dois comandos e uma armadilha. Fizemos tudo abaixo num servidor Ubuntu 24.04 novo da nossa imagem e o escaneamos a partir de uma segunda máquina, então as saídas são as que você verá no seu próprio servidor.

1. O que está escutando

O comando é ss. As letras significam TCP, UDP, sockets em escuta, portas numéricas e nome do processo:

sudo ss -tulpn

Num servidor novo ele imprime seis linhas:

Netid State  Local Address:Port  Process
udp   UNCONN    127.0.0.54:53    systemd-resolve
udp   UNCONN 127.0.0.53%lo:53    systemd-resolve
tcp   LISTEN    127.0.0.54:53    systemd-resolve
tcp   LISTEN 127.0.0.53%lo:53    systemd-resolve
tcp   LISTEN       0.0.0.0:22    sshd
tcp   LISTEN          [::]:22    sshd

A coluna que importa é Local Address. Ela diz quem pode se conectar:

EndereçoQuem alcança
127.0.0.1:… ou 127.0.0.53Só programas neste servidor
0.0.0.0:…Qualquer um por IPv4, salvo bloqueio do firewall
[::]:…Qualquer um por IPv6 (e normalmente IPv4 também)
10.0.0.5:… (um endereço específico)Qualquer um que alcance esse endereço

Ou seja, o servidor novo expõe exatamente uma coisa: SSH na porta 22, por IPv4 e IPv6. O resolvedor DNS em 127.0.0.53 é privado.

Para listar só o que a internet poderia ver, filtre os endereços de loopback:

sudo ss -tlnp | awk 'NR>1 && $4 !~ /^(127\.|\[::1\])/ {print $4, $6}'

Rode isso depois de cada instalação. Instalamos nginx, Docker e um pequeno app em Python, e a lista cresceu de 2 para 10 linhas, incluindo um docker-proxy em 0.0.0.0:8081 e um socket do containerd numa porta localhost aleatória.

2. Qual processo ocupa uma porta

Quando uma porta está ocupada e você quer saber por quem:

sudo lsof -i :80 -P -n
sudo fuser 80/tcp
sudo ss -tlnp 'sport = :80'

O lsof é o mais legível. Para o nginx ele listou um processo mestre como root e um worker como www-data, ambos em *:80, para IPv4 e IPv6. O fuser imprime só os PIDs, útil em scripts. Se precisar liberar a porta, pare o serviço em vez de matar o PID, senão o systemd o reinicia: sudo systemctl stop nginx.

3. O que a internet vê

O ss mostra a visão do servidor. A visão da internet pode ser diferente, porque há um firewall no meio ou porque um serviço está ligado a 127.0.0.1. Para ver o quadro real, escaneie o servidor de outra máquina, o seu notebook ou um segundo servidor. A ferramenta é o nmap (apt install nmap, ou o instalador de nmap.org no Windows e no macOS).

nmap your-server-ip
nmap -p- your-server-ip
nmap -p 22,80,443,3306 your-server-ip

A primeira forma verifica as 1.000 portas mais comuns, a segunda todas as 65.535, a terceira uma lista. No nosso servidor novo, antes de qualquer firewall:

Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
Nmap done: 1 IP address (1 host up) scanned in 6.83 seconds

O scan completo das 65.535 portas levou 8,9 segundos e achou a mesma porta única. Portas fechadas respondem na hora com um reset, por isso escaneá-las é rápido.

Três estados importam:

  • open: um programa aceitou a conexão. Essa é a sua superfície de ataque.
  • closed: o servidor respondeu que nada escuta ali. Seguro, mas confirma que o servidor existe e o que ele não roda.
  • filtered: sem resposta. Um firewall descartou o pacote. O scanner não sabe se há um serviço por trás.

Para uma única porta sem instalar nada, nc -zv ip-do-servidor 443 informa succeeded ou refused, e fica parado até o tempo limite numa porta filtrada. Para UDP, acrescente -sU ao nmap e espere lentidão; no nosso servidor as três portas UDP comuns, 53, 123 e 161, estavam closed.

Uma observação sobre os planos NAT: pela internet só chega a porta SSH que redirecionamos para você. Um scan do endereço compartilhado mostra a nossa borda, não o seu servidor, e as outras portas são inacessíveis, seja o que for que escute nelas. Num plano com IPv4 próprio, cada porta aberta é sua para gerenciar.

4. Feche o que não precisa

Três maneiras, da melhor à mais ampla.

Ligar ao localhost. Se só programas do servidor usam um serviço, faça-o escutar em 127.0.0.1. Iniciamos um pequeno app web com --bind 127.0.0.1 8080: o ss o mostrou em 127.0.0.1:8080 e o nmap de fora informou 8080/tcp closed. Para bancos de dados esse é o padrão correto: Redis, MySQL e PostgreSQL escutam em localhost de fábrica no Ubuntu, e nossos guias de Redis e MySQL mantêm assim.

Parar o serviço. sudo systemctl disable --now nome remove o listener de vez. Confirme com ss que ele sumiu.

Ligar o firewall. Libere primeiro o SSH, depois o que você serve, e então ative:

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw enable
sudo ufw status verbose

O scan de fora mudou completamente:

Not shown: 997 filtered tcp ports (no-response)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8081/tcp open  blackice-icecap
Nmap done: 1 IP address (1 host up) scanned in 10.18 seconds

Cada porta não liberada passou de closed para filtered, e o scan completo das 65.535 portas passou a levar 110 segundos em vez de 8,9. Mais tempo por porta para o scanner, menos informação sobre o seu servidor. Nosso guia do UFW trata de limite de taxa, liberar um único IP e IPv6.

Mas olhe a terceira linha.

5. A surpresa do Docker

A porta 8081 continuou aberta com o firewall ligado e sem regra que a liberasse. Essa porta pertence a um container que iniciamos com docker run -p 8081:80 nginx:alpine. O Docker acrescenta suas próprias regras ao firewall do kernel, e elas são avaliadas antes das do ufw. A regra que ele escreveu no nosso servidor:

-A DOCKER ! -i docker0 -p tcp --dport 8081 -j DNAT --to-destination 172.17.0.2:80

Qualquer pacote para a porta 8081 é encaminhado para o container antes que o ufw tenha voz. Todo container com -p ou uma entrada em ports: faz isso, e o ss mostra honestamente como docker-proxy em 0.0.0.0:8081.

A correção é publicar só no localhost:

docker rm -f web
docker run -d --name web -p 127.0.0.1:8081:80 nginx:alpine

No Compose, escreva "127.0.0.1:8081:80" em ports:. Depois da mudança, o ss mostrou 127.0.0.1:8081, a regra do Docker ganhou -d 127.0.0.1/32 e o scan de fora informou 8081/tcp filtered. Coloque o nginx como proxy reverso na frente para o lado público, com HTTPS, para que as únicas portas abertas no servidor sejam 22, 80 e 443.

Checklist depois de cada mudança

  1. sudo ss -tulpn: cada linha com 0.0.0.0 ou [::] é algo que você quis expor?
  2. nmap ip-do-servidor do seu notebook: as portas abertas batem?
  3. Um banco de dados, cache ou painel de administração num endereço público: mova hoje para 127.0.0.1 ou para trás do firewall.
  4. Cada entrada ports: do Docker: começa com 127.0.0.1: se não for a porta web pública?
  5. SSH exposto a todos: acrescente fail2ban ou login só por chave.

No Windows Server, a mesma verificação é Get-NetTCPConnection -State Listen, e as regras ficam no Firewall do Windows. Todo plano Linux, a partir do Nano de $3, tem uma versão com endereço IPv4 próprio, e nela o que você vê no ss é o que o mundo vê, menos o seu firewall.

Perguntas frequentes

Quais portas ficam abertas num VPS novo?

Na nossa imagem Ubuntu 24.04, uma: SSH na porta 22. Só o resolvedor DNS local em 127.0.0.53 e 127.0.0.54 também escuta, e a internet não chega até ele. Um scan das 65.535 portas TCP a partir de outra máquina encontrou exatamente uma porta aberta.

Qual é a diferença entre uma porta closed e filtered?

Closed quer dizer que o servidor respondeu que nada escuta ali, então o scanner sabe na hora. Filtered quer dizer nenhuma resposta, que é o que um firewall faz ao descartar pacotes. Os dois deixam intrusos de fora, mas filtered também esconde quais serviços existem e deixa um scan completo cerca de doze vezes mais lento no nosso servidor.

Por que o ss mostra uma porta que o nmap diz estar closed?

O serviço escuta só em 127.0.0.1, o endereço de loopback. Programas no próprio servidor conseguem conectar; ninguém de fora. No ss, veja a coluna Local Address: 127.0.0.1:8080 é privado, 0.0.0.0:8080 ou [::]:8080 é acessível pela internet se o firewall permitir.

Ativei o ufw, por que a porta do Docker continua aberta?

O Docker escreve suas próprias regras de firewall, avaliadas antes das do ufw. Um container iniciado com -p 8081:80 ficou acessível de fora no nosso servidor com o ufw ativo e sem regra para a 8081. Publique em localhost, -p 127.0.0.1:8081:80, e coloque nginx ou Caddy na frente para o lado público.

Como verifico uma porta do meu computador?

Rode nc -zv ip-do-servidor 443 para uma porta, ou instale o nmap e rode nmap ip-do-servidor para as mil portas mais comuns. Num plano NAT só a sua porta SSH redirecionada responde pela internet; o resto é inacessível por design.

Comentários

Nenhum comentário ainda. Seja o primeiro.

Deixe um comentário

Os comentários são moderados antes de aparecerem.