Docs/ Segurança/ Proteger seu servidor sh0

Proteger seu servidor sh0

Os mesmos conselhos onde quer que seu servidor esteja hospedado: nenhum passo específico de provedor, apenas o que roda na própria máquina.

Visão geral

O sh0 protege o que serve (HTTPS, segredos criptografados, papéis), mas o servidor que o hospeda é seu. A maioria dos servidores comprometidos não é invadida pela aplicação: entra-se por SSH com uma senha adivinhada, ou por uma porta que ninguém queria expor. Este guia fecha essas portas, na ordem que nunca deixa você do lado de fora. O sh0 verifica os mesmos pontos para você, em tempo real, na página Segurança do servidor do painel e com sudo sh0 doctor.

Antes de começar

Mantenha sua sessão SSH atual aberta até o fim e teste cada mudança a partir de uma NOVA sessão. No seu computador, verifique se a sua chave abre uma sessão sem senha:

bash
ssh -o PasswordAuthentication=no root@SERVER_IP

Se essa sessão pedir uma senha, você ainda não tem chave no servidor. Instale uma e teste novamente:

bash
ssh-copy-id root@SERVER_IP

SSH: só chaves

Um servidor que aceita senhas SSH pode ser adivinhado, e root é a primeira conta testada. Quando a sua chave funcionar, recuse senhas:

bash
cat > /etc/ssh/sshd_config.d/00-sh0-hardening.conf <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
EOF
Note
O nome do arquivo começa com 00- de propósito: o sshd mantém o PRIMEIRO valor que lê, e muitas imagens trazem um 50-cloud-init.conf que reativa as senhas. Um arquivo chamado 99-… seria ignorado sem aviso.

Valide e depois recarregue. Nunca reinicie o sshd com um arquivo que o sshd -t recusa; uma recarga mantém as sessões abertas. O serviço se chama ssh no Debian e no Ubuntu, sshd nos demais.

bash
sshd -t && systemctl reload ssh

Verifique o valor efetivo para root a partir de um endereço externo e abra uma nova sessão com a sua chave antes de fechar a atual:

bash
sshd -T -C user=root,host=check.invalid,addr=203.0.113.1 | grep -Ei '^(passwordauthentication|kbdinteractiveauthentication|permitrootlogin) '

Firewall e a armadilha do Docker

Libere SSH, HTTP, HTTPS e a porta do painel, depois ative o ufw. Se o SSH escuta em uma porta diferente da 22, libere essa porta primeiro.

bash
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443
ufw allow 9000/tcp
ufw --force enable

A porta 9000 continua aberta enquanto os endereços *.sh0.app chegarem diretamente ao seu servidor. Feche-a (sh0 serve --bind 127.0.0.1) somente quando o painel for servido no próprio domínio com HTTPS.

Warning
O ufw não vê as portas publicadas pelo Docker: o Docker grava as próprias regras iptables antes das do ufw, então um banco de dados publicado na 5432 continua acessível pela Internet com o ufw ativo. O Docker reserva uma cadeia ao administrador, DOCKER-USER. A regra abaixo só deixa passar, a partir da interface pública, as respostas às conexões abertas pelo servidor, e um pequeno serviço a reaplica a cada inicialização do Docker:
bash
cat > /usr/local/sbin/sh0-docker-user <<'EOF'
#!/bin/sh
# Docker-published ports: from the public interface, only replies get through.
IF=$(ip -o route get 1.1.1.1 | sed -n 's/.* dev \([^ ]*\).*/\1/p')
[ -n "$IF" ] || exit 1
iptables -C DOCKER-USER -i "$IF" -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN 2>/dev/null ||
  iptables -I DOCKER-USER 1 -i "$IF" -m conntrack --ctstate RELATED,ESTABLISHED -j RETURN
iptables -C DOCKER-USER -i "$IF" -j DROP 2>/dev/null ||
  iptables -I DOCKER-USER 2 -i "$IF" -j DROP
EOF
chmod 755 /usr/local/sbin/sh0-docker-user
cat > /etc/systemd/system/sh0-docker-user.service <<'EOF'
[Unit]
Description=sh0: filter Docker-published ports (DOCKER-USER)
After=docker.service
Requires=docker.service
PartOf=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/sh0-docker-user

[Install]
WantedBy=docker.service
EOF
systemctl daemon-reload
systemctl enable --now sh0-docker-user
iptables -S DOCKER-USER

Para manter uma porta publicada acessível, adicione uma exceção antes da regra DROP em /usr/local/sbin/sh0-docker-user:

bash
iptables -I DOCKER-USER 2 -i "$IF" -p tcp -m conntrack --ctorigdstport 5432 -j RETURN

Se o seu provedor oferece um firewall de rede na frente do servidor, seja qual for, use-o também: libere 22, 80, 443 (e 9000 enquanto depender de *.sh0.app) e recuse o resto. Ele filtra antes que o tráfego chegue à máquina, Docker incluído.

fail2ban

Com apenas chaves, as tentativas não são perigosas, mas enchem os logs. O fail2ban bloqueia os endereços que insistem:

bash
apt-get install -y fail2ban python3-systemd
cat > /etc/fail2ban/jail.d/sh0-sshd.local <<'EOF'
[sshd]
enabled = true
backend = systemd
journalmatch = _COMM=sshd + _COMM=sshd-session
maxretry = 5
findtime = 10m
bantime = 1h
EOF
systemctl enable fail2ban
systemctl restart fail2ban
fail2ban-client status sshd

Atualizações e reinicializações

Instale as atualizações de segurança e deixe o sistema instalá-las automaticamente:

bash
apt-get update && apt-get upgrade
apt-get install -y unattended-upgrades && dpkg-reconfigure -plow unattended-upgrades

Quando o kernel ou uma biblioteca essencial é atualizado, a correção só vale após uma reinicialização (/var/run/reboot-required existe). Planeje-a em um horário de pouco tráfego: o sh0 inicia novamente com o sistema.

O painel com HTTPS

Sem domínio próprio, o painel é servido em HTTP sem criptografia e a senha do proprietário atravessa a rede sem proteção. Aponte um registro DNS A para o servidor e depois:

bash
sh0 panel-domain set panel.example.com

Deixar o instalador fazer

Em um servidor novo, o instalador aplica os passos de SSH, firewall e fail2ban acima quando solicitado. Fica desativado por padrão; em um terminal, o instalador também faz a pergunta (sem resposta em 30 segundos, é não).

bash
curl -fsSL https://get.sh0.dev | bash -s -- --harden
Note
O passo SSH só é executado se uma chave autorizada for encontrada para a conta com que você está conectado; caso contrário, é recusado, com o motivo, e os outros passos são executados mesmo assim. O sshd -t valida o arquivo antes de qualquer recarga, e o sshd nunca é reiniciado.

Verificar o resultado

A página Segurança do servidor do painel (proprietário e administradores) mostra essas verificações em tempo real, com a correção abaixo de cada aviso; um ponto na navegação indica um aviso ativo. A partir de um terminal no servidor:

bash
sudo sh0 doctor