Proteja um servidor Ubuntu novo antes de colocar aplicações nele
Siga isso no seu próprio servidor. Comece grátis, sem cartão
Um servidor Ubuntu novo de qualquer provedor de nuvem vem com uma conta (root), um jeito de entrar (uma senha ou uma chave que o provedor gerou pra você), e nenhuma regra de firewall de forma alguma. Isso é tranquilo pelos primeiros cinco minutos enquanto você está se orientando, mas não é um servidor em que você deveria rodar nada ainda. Qualquer coisa escaneando a internet por portas SSH abertas vai encontrar ele em horas, e uma conta root acessível por senha é exatamente o que eles estão esperando encontrar. No final deste guia você vai ter um usuário não-root com a própria chave SSH, login root e autenticação por senha ambos desativados, um firewall que só deixa passar as portas que você de fato usa, o fail2ban observando tentativas de força bruta, atualizações de segurança se aplicando sozinhas, e uma checklist curta pra confirmar que tudo isso de fato entrou em vigor.
O que você vai precisar
- Um servidor Ubuntu 24.04 LTS novo de qualquer provedor, com as credenciais SSH root iniciais dele (uma senha ou uma chave gerada pelo provedor).
- O seu próprio par de chaves SSH na sua máquina (
ssh-keygen -t ed25519se você ainda não tiver um). - Um nome de usuário não-root que você quer criar no servidor (este guia usa
deploy). - Cerca de vinte minutos, a maior parte gasta lendo saída em vez de digitando.
Passo 1: crie um usuário sudo não-root
Rodar tudo como root significa que um único comando digitado errado, um script comprometido, ou uma chave vazada entrega a máquina inteira. Uma conta separada com sudo te dá a mesma capacidade de administrar o servidor, mas só quando você pede deliberadamente, e é a conta que a Railyard (ou qualquer ferramenta de deploy) realmente vai usar depois.
Como root:
adduser deploy
usermod -aG sudo deploy
adduser te guia por definir uma senha e alguns detalhes opcionais; usermod -aG sudo adiciona a conta nova ao grupo sudo, que no Ubuntu já está configurado pra conceder direitos administrativos completos.
Cheque se funcionou: rode id deploy e confirme que sudo aparece na lista de grupos. Depois su - deploy seguido de sudo whoami deve pedir a senha do usuário deploy e imprimir root.
Passo 2: copie a sua chave SSH e teste o login
Antes de tocar em qualquer coisa no sshd_config, faça o login baseado em chave funcionar pro usuário novo e confirme isso a partir de uma janela de terminal totalmente nova, enquanto a sua sessão root original continua aberta como rede de segurança.
O jeito fácil, a partir da sua própria máquina:
ssh-copy-id deploy@YOUR_SERVER_IP
Se ssh-copy-id não estiver disponível, faça manualmente como o usuário deploy no servidor:
mkdir -p ~/.ssh
echo "ssh-ed25519 AAAA... your-public-key-here" >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Agora, numa segunda janela de terminal, sem fechar a sua sessão root existente, tente logar como o usuário novo:
ssh deploy@YOUR_SERVER_IP
Você deve ver ele te colocar direto num shell como deploy (pode pedir a própria senha da sua chave se você definiu uma, mas não uma senha pra conta). Se isso falhar por qualquer motivo, corrija agora, ainda a partir da sua sessão root original. Não avance pro próximo passo até isso funcionar.
Passo 3: desative o login root e a autenticação por senha
Com o login baseado em chave confirmado, o acesso root e a autenticação por senha não são mais portas que você precisa manter abertas, e deixar elas abertas é exatamente o que a maioria dos scanners automáticos de SSH está sondando.
Edite /etc/ssh/sshd_config:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
Antes de recarregar qualquer coisa, cheque se o arquivo é sintaticamente válido:
sudo sshd -t
Se isso voltar limpo, recarregue o serviço (no Ubuntu a unit do systemd se chama ssh, não sshd):
sudo systemctl reload ssh
Cheque se funcionou a partir de um terceiro terminal, novo (de novo, mantenha a sua sessão funcional aberta): ssh root@YOUR_SERVER_IP deve ser recusado de cara, e ssh deploy@YOUR_SERVER_IP com a senha errada deve falhar imediatamente sem nenhum prompt de senha, já que a autenticação por senha está totalmente desligada. O seu login original baseado em chave como deploy deve continuar funcionando exatamente como antes.
Passo 4: configure o ufw
Um firewall que nega tudo por padrão, e depois permite explicitamente só as portas que você está usando, significa que uma porta que você esqueceu de fechar (ou um serviço que você instalou e esqueceu) não fica acessível da internet só porque por acaso está escutando.
sudo apt update
sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
22/tcp mantém o SSH acessível (você pode usar sudo ufw allow OpenSSH em vez disso se preferir o perfil de aplicação nomeado), 80/tcp e 443/tcp cobrem HTTP puro e HTTPS pra o que quer que você vá eventualmente implantar. Se você sabe que não vai servir nada por HTTP, você pode remover a regra 80/tcp, embora a maioria das configurações de TLS ainda usem a porta 80 brevemente pra emissão de certificado.
Cheque se funcionou: sudo ufw status verbose deve mostrar Status: active, Default: deny (incoming), allow (outgoing), e as três regras que você acabou de adicionar listadas como ALLOW.
Passo 5: instale e configure o fail2ban
Mesmo com a autenticação por senha desligada, a sua porta SSH ainda aceita tentativas de conexão, e um fluxo constante de tentativas automáticas de login enche os seus logs e queima um pouco de CPU sem motivo. O fail2ban observa o log de autenticação e bane temporariamente IPs que falham a autenticação demais vezes.
sudo apt install fail2ban
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
A própria convenção do fail2ban é deixar o jail.conf intocado (ele é sobrescrito em upgrades de pacote) e colocar as suas mudanças no jail.local, que é lido depois e tem prioridade. Abra /etc/fail2ban/jail.local e confirme que a seção sshd está assim:
[sshd]
enabled = true
port = ssh
maxretry = 5
bantime = 1h
findtime = 10m
Isso bane um IP por uma hora depois de cinco tentativas falhas dentro de uma janela de dez minutos. Depois ative e inicie o serviço:
sudo systemctl enable --now fail2ban
Cheque se funcionou: sudo fail2ban-client status sshd deve mostrar a jail rodando, com contadores pra endereços atualmente falhando e atualmente banidos.
Passo 6: ative upgrades de segurança automáticos
A maioria das invasões de servidor não são zero-days, são vulnerabilidades conhecidas em pacotes que ninguém teve tempo de atualizar. O unattended-upgrades aplica patches de segurança automaticamente, num horário agendado, sem você precisar lembrar de entrar via SSH e rodar apt upgrade.
sudo apt install unattended-upgrades
O Ubuntu já vem com isso com atualizações de segurança já ativadas pro release atual depois de instalado. Confirme (e ajuste se precisar) os dois arquivos de configuração:
/etc/apt/apt.conf.d/20auto-upgrades deve conter:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
/etc/apt/apt.conf.d/50unattended-upgrades lista quais origens de pacote têm permissão de auto-atualizar; o repositório de segurança do seu release está incluído por padrão.
Cheque se funcionou: sudo unattended-upgrade --dry-run --debug imprime o que ele faria na próxima execução sem de fato mudar nada. Depois que o serviço rodar de verdade (ele checa uma vez por dia), /var/log/unattended-upgrades/unattended-upgrades.log mostra o que ele instalou.
Passo 7: defina o fuso horário e o hostname do servidor
Esse não é sobre atacantes, é sobre a sua própria sanidade depois: timestamps de log que correspondem ao seu próprio relógio, e um hostname que te diz qual servidor você está olhando quando você tem mais de um aberto em abas de terminal diferentes.
sudo timedatectl set-timezone America/Montreal
sudo hostnamectl set-hostname myapp-server-01
Troque pelo fuso horário IANA e hostname que fizerem sentido pra você; timedatectl list-timezones lista os valores válidos se você não tiver certeza do nome exato.
Cheque se funcionou: timedatectl mostra o fuso horário que você definiu em “Time zone”, e hostnamectl mostra o hostname novo em “Static hostname”.
Passo 8: verificação final
Antes de considerar o servidor pronto, saia completamente e confirme que a configuração inteira se sustenta a partir de um ponto zero, não só da sessão que você manteve aberta o tempo todo:
- Abra um terminal totalmente novo e rode
ssh deploy@YOUR_SERVER_IP. Você deve entrar num shell usando só a sua chave, sem prompt de senha. ssh root@YOUR_SERVER_IPa partir desse mesmo terminal novo deve ser recusado.sudo ufw status verboseainda mostraactivecom exatamente as portas que você pretende ter abertas.sudo fail2ban-client status sshdmostra a jail rodando.sudo whoamicomo o usuáriodeployainda retornarootdepois de um prompt de senha.
Se cada um desses passar, o servidor está num estado razoável pra colocar algo nele.
O caminho mais rápido: faça isso com a Railyard
Nada das etapas acima é algo que a Railyard faz por você. Ela não toca no sshd_config, não configura ufw nem fail2ban, e não vai definir o seu fuso horário. O que ela precisa de um servidor que você já protegeu do jeito de cima é limitado: o usuário SSH tem sudo sem senha, as portas 22, 80 e 443 são acessíveis da internet (exatamente as regras que você acabou de adicionar), e o servidor tem pelo menos 1 GB de RAM (2 GB ou mais se você também estiver fazendo build de imagens de aplicação nele).
Um detalhe que vale corrigir antes de conectar um servidor: a combinação padrão de adduser mais usermod -aG sudo do Passo 1 ainda pede a senha do deploy toda vez que ele roda sudo, e a Railyard precisa que isso aconteça sem prompt. Adicione um drop-in de sudoers pra isso:
echo "deploy ALL=(ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/deploy
sudo chmod 440 /etc/sudoers.d/deploy
A partir daí: Servers → Add a server → Bring your own server, aponte pro IP desse servidor com a chave privada correspondente à chave pública que você copiou no Passo 2. Essa chave privada é usada uma vez pra instalação e não é armazenada. O servidor aparece no seu painel em alguns minutos, pronto pra receber o deploy de uma aplicação.
Se você preferir não provisionar uma máquina manualmente de forma alguma, a Railyard também consegue criar um servidor direto na sua própria conta de nuvem (DigitalOcean, Vultr, Hetzner, AWS ou OVH) e configurar ele automaticamente, aparecendo no seu painel do mesmo jeito. Qualquer um dos dois caminhos ainda deixa o hardening acima como sua responsabilidade de manter em vigor: a Railyard automatiza o deploy de aplicação, releases sem downtime, e gerenciamento de banco de dados e backup em cima de um servidor que já está protegido, é um caminho mais rápido além das ferramentas de deploy, não além do próprio hardening.
Resolução de problemas
Você ficou trancado de fora depois de desativar a autenticação por senha. Isso acontece quando PasswordAuthentication no é recarregado antes do login baseado em chave ser de fato confirmado funcionando. Se o seu provedor oferece um console web ou modo de recuperação, use ele pra logar localmente e ou reative PasswordAuthentication yes temporariamente ou corrija a chave em ~/.ssh/authorized_keys, depois teste de novo a partir de um terminal novo antes de desativar de novo.
O ufw está bloqueando uma porta que a sua aplicação precisa. Se algo que você implanta depois precisa de uma porta além de 22, 80 e 443 (um banco de dados que você expõe intencionalmente, uma porta de aplicação diferente), adicione ela explicitamente: sudo ufw allow 5432/tcp, depois cheque de novo com sudo ufw status verbose. Geralmente é mais seguro manter bancos de dados totalmente fora da internet pública e alcançar eles através de uma rede privada em vez disso, ao invés de abrir outra porta.
O fail2ban baniu o seu próprio IP. Se você digita uma senha errada algumas vezes enquanto testa (ou testa a partir de um script que tenta rápido de novo), o fail2ban pode banir o IP de onde você está trabalhando. Desbane a partir de uma sessão que ainda está conectada, ou do console do servidor: sudo fail2ban-client set sshd unbanip YOUR_IP.
Você consegue entrar via SSH pelo próprio console do servidor mas não pela internet. A maioria dos provedores de nuvem tem a própria camada de firewall no nível de rede (um “security group” ou “cloud firewall”) na frente do servidor, separado do ufw. Se uma porta está aberta no ufw mas ainda inacessível, cheque as configurações de firewall do provedor também, os dois precisam permitir as mesmas portas pro tráfego passar.
Perguntas frequentes
Eu preciso fazer isso se o meu provedor já tem o próprio firewall? Sim. O firewall de rede de um provedor é uma primeira camada útil, mas não te dá SSH só por chave, não bane tentativas de força bruta, e não vai corrigir um pacote vulnerável pra você. Trate o ufw como uma segunda camada, não um substituto.
Pra qual porta eu deveria mover o SSH? Você não precisa mover ela. Depois que o login root e a autenticação por senha estão desligados e o fail2ban está observando, a porta 22 não é um ponto fraco significativo, um scanner achando uma porta 22 aberta não consegue fazer muito sem uma chave válida. Mover o SSH pra uma porta não padrão principalmente só reduz o ruído de log de scans automáticos; se você fizer isso, lembre de atualizar tanto a diretiva Port do sshd_config quanto a regra correspondente do ufw, e teste a porta nova antes de fechar a 22.
Com que frequência eu deveria atualizar o servidor? O unattended-upgrades aplica patches de segurança diariamente por conta própria, que cobre as atualizações que mais importam. Ainda vale rodar sudo apt update && sudo apt upgrade manualmente de vez em quando pra atualizações de pacote não relacionadas a segurança, e reiniciar depois de uma atualização de kernel pra o novo de fato carregar.
Eu ainda preciso do fail2ban se a autenticação por senha já está desligada? Ainda vale rodar. Ele reduz o ruído de log e o custo (pequeno) de recursos de tentativas de conexão falhas constantes, e aplica a mesma proteção a qualquer outro serviço que você adicionar uma jail pra depois, não só o SSH.
Isso se aplica a releases LTS mais novos do Ubuntu também? A abordagem geral (um usuário sudo não-root, SSH só por chave, ufw, fail2ban, upgrades automáticos) se mantém pra outros releases LTS recentes do Ubuntu; os comandos e caminhos de arquivo neste guia são o que é atual pro 24.04. Se você está num release diferente, vale uma checagem rápida contra a própria documentação atual do Ubuntu por qualquer coisa que tenha mudado antes de fixar um passo de hardening no lugar.
Nenhuma dessas etapas leva muito tempo por conta própria, e depois que elas estão feitas você não precisa pensar nelas de novo até o próximo servidor. O que você ganha com isso é uma máquina onde um scanner perdido encontra uma porta trancada em vez de uma aberta, e essa é a base de onde todo servidor que roda algo real deveria partir.
Por que escolhem o Railyard para isso
- Sua própria conta de cloud. Faça deploy no DigitalOcean, Hetzner, Vultr, AWS, OVHcloud, ou em qualquer servidor Linux via SSH, cobrado direto pelo seu provedor, sem markup.
- Um preço fixo por equipe. O Free é grátis para sempre: um servidor mais um servidor de banco de dados, três apps, sem cartão. O Pro custa US$19 por mês para até cinco servidores e apps ilimitados. O Team custa US$49 por mês com servidores ilimitados. Sem cobrança por app, por deploy, por assento ou por gigabyte.
- Templates de um clique. Faça deploy de apps open source, como bancos de dados, analytics e ferramentas de dev, no seu próprio servidor em um clique.
- Bancos de dados gerenciados. Postgres, MySQL e Redis com backups programados, verificados por restauração, e recuperação point-in-time.
- Push-to-deploy. Faça deploy a partir do GitHub, GitLab ou da CLI, com HTTPS automático e releases sem downtime.