Ubuntu Segurança do Servidor
Um servidor ligado à internet começa a receber tentativas de invasão em minutos: robôs testam senhas no SSH o dia inteiro, em todos os endereços. Esta aula transforma um servidor recém-criado num servidor protegido, em um roteiro que leva uns 15 minutos.
- Os princípios que guiam toda decisão de segurança.
- O roteiro dos primeiros 15 minutos num servidor novo, passo a passo.
- Como endurecer o SSH sem se trancar para fora.
- Como o
fail2banbloqueia quem erra a senha muitas vezes. - Onde olhar para saber quem tentou entrar.
Antes, leia SSH, Firewall (ufw) e Usuários e Grupos. Nesta aula, a Ana acabou de criar uma máquina na nuvem chamada servidor, com IP 192.168.0.20. O provedor entregou acesso como root, com senha.
Os princípios
| Princípio | Na prática |
|---|---|
| Menor privilégio | Cada pessoa e cada programa só tem o acesso de que precisa. Ninguém trabalha como root; usa-se sudo quando necessário. |
| Menos portas, menos risco | Todo serviço aberto é uma porta de entrada. Desinstale o que não usa e feche o resto no firewall. |
| Atualizado sempre | A maioria das invasões explora falhas que já têm correção. Atualizações de segurança devem ser automáticas. |
| Defesa em camadas | Chave SSH + firewall + fail2ban. Se uma camada falhar, a próxima segura. |
| Registrar e revisar | Logs mostram quem tentou entrar. Backups permitem voltar atrás (veja Backup). |
Os primeiros 15 minutos num servidor novo
Siga na ordem. Os passos 1 e 2 são feitos como root, no acesso que o provedor entregou. Do passo 3 em diante, a Ana usa o próprio usuário.
Servidores criados a partir de imagens de nuvem costumam vir com o idioma C.UTF-8, que é inglês. É normal; os comandos são os mesmos.
-
Atualize tudo. A imagem do provedor pode ter semanas de atraso. Conecte com
ssh root@192.168.0.20e rode:#> apt update && apt full-upgrade -y #> ls /var/run/reboot-required /var/run/reboot-required « o arquivo existe: reinicie #> reboot
Se o arquivo
/var/run/reboot-requiredexistir, uma atualização (normalmente do kernel) só vale depois de reiniciar. Veja Atualizações. -
Crie um usuário administrador. Trabalhar como root é perigoso: um erro de digitação não tem nenhuma barreira.
- adduser
- Cria o usuário, a pasta pessoal e pede a senha.
- ana
- O nome do novo usuário.
#> adduser ana info: Adding user `ana' ... info: Selecting UID/GID from range 1000 to 59999 ... info: Adding new group `ana' (1000) ... info: Adding new user `ana' (1000) with group `ana (1000)' ... info: Creating home directory `/home/ana' ... info: Copying files from `/etc/skel' ... New password: « nada aparece enquanto você digita Retype new password: passwd: password updated successfully Changing the user information for ana Enter the new value, or press ENTER for the default Full Name []: Ana Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n] y info: Adding new user `ana' to supplemental / extra groups `users' ... info: Adding user `ana' to group `users' ... #> usermod -aG sudo ana #> groups ana ana : ana sudo users
O
usermod -aG sudo anacoloca a ana no gruposudo, que pode administrar o sistema. O-aé essencial: sem ele, a ana sairia de todos os outros grupos (veja Usuários e Grupos). -
Entre com chave SSH. No seu computador (o notebook), crie uma chave e copie a parte pública para o servidor:
$ ssh-keygen -t ed25519 -C "ana@notebook" $ ssh-copy-id ana@192.168.0.20 $ ssh ana@192.168.0.20
Se o último comando entrou sem pedir a senha da conta (no máximo a senha da chave), a chave funciona. Detalhes em SSH.
-
Endureça o SSH. Vamos proibir o login do root e o login por senha. Mas não edite o arquivo principal: crie um arquivo seu em
/etc/ssh/sshd_config.d/.# Configuração de segurança do SSH PermitRootLogin no PasswordAuthentication no KbdInteractiveAuthentication no MaxAuthTries 3 AllowUsers ana
Opção O que faz PermitRootLogin noNinguém entra direto como root. Robôs sempre tentam "root". PasswordAuthentication noSó entra quem tem uma chave. Adivinhar senha deixa de funcionar. KbdInteractiveAuthentication noFecha outra forma de pedir senha (o "teclado interativo"). MaxAuthTries 3Derruba a conexão após 3 tentativas erradas. AllowUsers anaSó a ana pode entrar por SSH, mesmo que existam outros usuários. $ sudo nano /etc/ssh/sshd_config.d/10-seguranca.conf $ sudo sshd -t $ sudo sshd -T | grep -E "^(permitrootlogin|passwordauthentication) " permitrootlogin no passwordauthentication no $ sudo systemctl restart ssh
- sshd -t
- test: confere se a configuração tem erro, sem aplicar nada. Sem saída = sem erros.
- sshd -T
- Mostra a configuração efetiva, já juntando todos os arquivos.
- systemctl restart ssh
- Aplica. Quem já está conectado continua conectado.
Por que "10-" no nome do arquivo?No SSH, vale a primeira vez que uma opção aparece. Os arquivos de
sshd_config.dsão lidos em ordem alfabética, antes do resto. Em servidores de nuvem, costuma existir um50-cloud-init.confcomPasswordAuthentication yes. Com o nome começando por10-, o seu arquivo é lido antes e vence. Osshd -Tconfirma qual valor ficou.Teste num segundo terminal antes de sairMantenha a sessão atual aberta. Abra outro terminal no notebook e rode
ssh ana@192.168.0.20. Só feche a primeira sessão quando a segunda entrar. Teste também que o root foi barrado:ssh root@192.168.0.20deve responderPermission denied (publickey). -
Ligue o firewall, liberando o SSH primeiro (detalhes em Firewall (ufw)):
$ sudo ufw allow OpenSSH Rules updated Rules updated (v6) $ sudo ufw enable Command may disrupt existing ssh connections. Proceed with operation (y|n)? y Firewall is active and enabled on system startup
-
Instale o fail2ban (explicado na próxima seção):
$ sudo apt install fail2ban -y $ sudo systemctl enable --now fail2ban
-
Confirme as atualizações automáticas de segurança. No Ubuntu Server, o
unattended-upgradesjá vem instalado. Confira se está ligado:$ cat /etc/apt/apt.conf.d/20auto-upgrades APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; « 1 = ligado
Se o arquivo não existir ou tiver
"0", rodesudo dpkg-reconfigure -plow unattended-upgradese responda Yes. -
Acerte o fuso horário, para os logs mostrarem a hora certa:
$ sudo timedatectl set-timezone America/Sao_Paulo $ date Thu Oct 15 10:45:12 -03 2026
-
Veja o que está aberto para a rede. Cada linha é um programa escutando uma porta:
$ sudo ss -tulpn Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process udp UNCONN 0 0 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=512,fd=16)) udp UNCONN 0 0 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=512,fd=14)) tcp LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=512,fd=15)) tcp LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1043,fd=3),("systemd",pid=1,fd=104)) tcp LISTEN 0 4096 [::]:22 [::]:* users:(("sshd",pid=1043,fd=4),("systemd",pid=1,fd=105))Endereços
127.0.0.xsó aceitam conexões do próprio servidor;0.0.0.0e[::]aceitam de qualquer lugar. Aqui, só o SSH está exposto, como deve ser. Se aparecer algo que você não reconhece, descubra o que é (veja ip, ping, ss) e desinstale se não precisar.
fail2ban: banir quem insiste
Mesmo com login só por chave, robôs continuam tentando, enchendo os logs. O fail2ban lê os registros, conta as falhas de cada IP e, quando passa do limite, cria uma regra de firewall que bloqueia aquele IP por um tempo.
| Termo | Significado |
|---|---|
| jail ("cadeia") | Uma proteção para um serviço. A jail sshd protege o SSH; o pacote do Ubuntu já a deixa ligada. |
maxretry | Quantas falhas são toleradas. |
findtime | Em quanto tempo essas falhas são contadas. |
bantime | Por quanto tempo o IP fica bloqueado. |
ignoreip | Endereços que nunca são bloqueados (o seu, por exemplo). |
Configurar
Nunca edite o jail.conf, que é substituído nas atualizações. Crie um jail.local, que tem prioridade:
[DEFAULT] # 5 falhas em 10 minutos = 1 hora de bloqueio maxretry = 5 findtime = 10m bantime = 1h # nunca bloquear o próprio servidor nem a rede do escritório ignoreip = 127.0.0.1/8 ::1 192.168.0.0/24 [sshd] enabled = true
$ sudo nano /etc/fail2ban/jail.local $ sudo systemctl restart fail2ban $ sudo fail2ban-client status Status |- Number of jail: 1 `- Jail list: sshd
Ver quem foi bloqueado
$ sudo fail2ban-client status sshd Status for the jail: sshd |- Filter | |- Currently failed: 2 | |- Total failed: 57 | `- File list: /var/log/auth.log `- Actions |- Currently banned: 1 « IPs bloqueados agora |- Total banned: 4 `- Banned IP list: 203.0.113.45
Dependendo de onde o fail2ban lê os registros, a linha File list pode aparecer como Journal matches. O resultado é o mesmo.
Desbloquear um IP
$ sudo fail2ban-client set sshd unbanip 203.0.113.45 1 « 1 IP desbloqueado
Quem tentou entrar?
Formas diferentes de investigar os acessos ao SSH:
| Pergunta | Comando |
|---|---|
| Quem está conectado agora? | who ou w |
| Últimos logins com sucesso | last -n 10 (no 26.04, vem no pacote wtmpdb) |
| Tentativas que falharam | sudo grep "Failed\|Invalid user" /var/log/auth.log | tail |
| Tudo do SSH desde ontem | sudo journalctl -u ssh --since yesterday |
| IPs que mais tentaram | veja abaixo |
$ sudo grep "Invalid user" /var/log/auth.log | tail -2
2026-10-15T10:51:33.402871-03:00 servidor sshd-session[2231]: Invalid user admin from 203.0.113.45 port 40122
2026-10-15T10:51:35.118203-03:00 servidor sshd-session[2233]: Invalid user oracle from 203.0.113.45 port 40130
$ sudo grep "Invalid user" /var/log/auth.log | grep -oE "from [0-9.]+" | sort | uniq -c | sort -nr | head -3
41 from 203.0.113.45
12 from 198.51.100.7
3 from 192.0.2.88
Robôs testam nomes comuns (admin, oracle, test). Com AllowUsers ana e login só por chave, todas essas tentativas falham. O segundo comando junta grep, sort e uniq para contar tentativas por IP.
AppArmor: limitar o que cada programa pode fazer
O AppArmor vem ligado no Ubuntu. Ele dá a programas como o navegador e o servidor web uma lista do que podem acessar. Mesmo que um programa seja invadido, ele não consegue sair dessa lista.
$ sudo aa-status | head -4 apparmor module is loaded. 119 profiles are loaded. 33 profiles are in enforce mode. « enforce = regras aplicadas /usr/bin/man
Você raramente precisa mexer nele. O importante é não desligá-lo quando um tutorial da internet mandar; prefira entender qual regra está bloqueando, em sudo journalctl -k | grep apparmor.
Boas práticas no dia a dia
- Não rode scripts da internet sem ler.
curl https://site/instalar.sh | sudo bashexecuta como root um código que você não viu. Baixe, leia, depois rode. - Proteja a chave privada com uma senha (o
ssh-keygenpergunta) e nunca a copie para o servidor. - Um usuário por pessoa. Não compartilhe a conta da ana; crie outra e remova quando a pessoa sair.
- Serviços como usuários próprios, nunca como root (veja Criar um Serviço).
- Backup fora do servidor. Um invasor que apaga o servidor também apaga o backup que está nele.
- Revise de tempos em tempos:
sudo ss -tulpn,sudo ufw status,sudo fail2ban-client status sshde as atualizações (veja Manutenção).
Quando não funciona
$ ssh ana@192.168.0.20 ana@192.168.0.20: Permission denied (publickey).
O que aconteceu: o servidor agora só aceita chave, e a sua chave não está em /home/ana/.ssh/authorized_keys, ou as permissões da pasta .ssh estão abertas demais.
Como resolver: se a primeira sessão ainda está aberta, use-a para conferir: ls -la ~/.ssh (a pasta deve ser drwx------ e o arquivo -rw-------). Se você se trancou para fora, entre pelo console web do provedor e, temporariamente, volte PasswordAuthentication yes no seu arquivo de configuração.
$ sudo sshd -t /etc/ssh/sshd_config.d/10-seguranca.conf: line 2: Bad configuration option: PermitRotLogin /etc/ssh/sshd_config.d/10-seguranca.conf: terminating, 1 bad configuration options
O que aconteceu: erro de digitação no nome da opção ("Rot" em vez de "Root").
Como resolver: corrija a linha indicada e rode sudo sshd -t de novo. Nunca reinicie o SSH antes de o teste passar.
O que aconteceu: você errou a senha (ou um script errou por você) mais vezes que o maxretry. A conexão fica tentando e não responde.
Como resolver: entre por outro IP (a rede do celular, por exemplo) ou pelo console do provedor e rode sudo fail2ban-client set sshd unbanip SEU_IP. Depois, coloque o seu IP fixo em ignoreip.
O que aconteceu: outro arquivo de sshd_config.d, lido antes do seu, define o valor contrário. Ou o SSH não foi reiniciado.
Como resolver: sudo grep -ri "permitrootlogin\|passwordauthentication" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/ mostra todos os lugares. Ajuste o nome do seu arquivo para ser lido primeiro e confira com sudo sshd -T.
Referência
| Comando | Para quê |
|---|---|
sudo adduser NOME + sudo usermod -aG sudo NOME | Criar um administrador |
ssh-keygen -t ed25519 + ssh-copy-id | Login por chave |
sudo sshd -t / sudo sshd -T | Testar / ver a configuração efetiva do SSH |
sudo systemctl restart ssh | Aplicar mudanças do SSH |
sudo ufw allow OpenSSH + sudo ufw enable | Firewall |
sudo fail2ban-client status sshd | IPs bloqueados |
sudo fail2ban-client set sshd unbanip IP | Desbloquear |
sudo dpkg-reconfigure -plow unattended-upgrades | Ligar atualizações automáticas |
sudo ss -tulpn | Portas abertas |
sudo aa-status | Estado do AppArmor |
sudo journalctl -u ssh --since today | Acessos ao SSH |
Exercícios
1. Proibir o root
Complete a linha de configuração do SSH:
2. Testar antes de aplicar
Complete o comando que confere a configuração do SSH sem aplicá-la:
3. Adicionar ao grupo sudo
Complete para colocar o usuário joao no grupo sudo sem tirá-lo dos outros grupos:
4. Por que o arquivo se chama 10-seguranca.conf e não seguranca.conf?
5. O que o fail2ban faz quando um IP passa do maxretry dentro do findtime?
Resumo
- Servidor novo: atualize, crie um usuário com sudo, entre por chave, endureça o SSH, ligue o firewall e o fail2ban.
- Configure o SSH num arquivo próprio em
sshd_config.d; teste comsshd -te confira comsshd -T. - Sempre teste o acesso num segundo terminal antes de fechar o primeiro.
- O fail2ban bloqueia IPs que erram demais; configure-o no
jail.local. - Revise portas abertas, bloqueios e logins com frequência.