Adicionar 101-Hardening-Linux-Servers.MD
This commit is contained in:
commit
d2bc5eab4d
1 changed files with 328 additions and 0 deletions
328
101-Hardening-Linux-Servers.MD
Normal file
328
101-Hardening-Linux-Servers.MD
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
# Guia de Hardening do Servidor Linux
|
||||
|
||||
> **Sobre este documento:** Template explicativo das etapas de hardening aplicadas em servidores Ubuntu 24.04 LTS. Substitua os valores entre `<ANGULARES>` pelos dados do servidor alvo antes de executar.
|
||||
|
||||
---
|
||||
|
||||
## Variáveis a Substituir
|
||||
|
||||
| Placeholder | Descrição | Exemplo |
|
||||
|-------------|-----------|---------|
|
||||
| `<USUARIO_ADMIN>` | Nome do usuário administrador a criar | `deploy`, `sysadmin` |
|
||||
| `<SEU_EMAIL>` | E-mail do responsável (usado como comentário na chave SSH) | `admin@empresa.com` |
|
||||
| `<CHAVE_PUBLICA_SSH>` | Chave pública SSH ed25519 do seu laptop | `ssh-ed25519 AAAA...` |
|
||||
| `<IP_DO_SERVIDOR>` | IP público do servidor | `203.0.113.10` |
|
||||
| `<CHAVE_PUBLICA_WG>` | Chave pública WireGuard gerada no servidor | resultado de `wg pubkey` |
|
||||
| `<IP_TUNEL_VPN>/<PREFIXO>` | IP atribuído ao servidor dentro da VPN | `10.14.0.2/16` |
|
||||
| `<ENDPOINT_VPN>` | Endereço do servidor VPN (hostname:porta) | `servidor.vpn.com:51820` |
|
||||
| `<CHAVE_PUBLICA_PEER_VPN>` | Chave pública do servidor VPN (fornecida pelo provedor) | resultado do painel da VPN |
|
||||
| `<DNS_PRIMARIO>` | DNS primário fornecido pelo provedor VPN | `1.1.1.1` |
|
||||
| `<DNS_SECUNDARIO>` | DNS secundário fornecido pelo provedor VPN | `8.8.8.8` |
|
||||
|
||||
---
|
||||
|
||||
## 1. Criação do Usuário Admin
|
||||
|
||||
```bash
|
||||
useradd -m -s /bin/bash -G sudo <USUARIO_ADMIN>
|
||||
echo "<USUARIO_ADMIN>:$(openssl rand -base64 32)" | chpasswd
|
||||
mkdir -p /home/<USUARIO_ADMIN>/.ssh
|
||||
chmod 700 /home/<USUARIO_ADMIN>/.ssh
|
||||
echo "<CHAVE_PUBLICA_SSH>" > /home/<USUARIO_ADMIN>/.ssh/authorized_keys
|
||||
chmod 600 /home/<USUARIO_ADMIN>/.ssh/authorized_keys
|
||||
chown -R <USUARIO_ADMIN>:<USUARIO_ADMIN> /home/<USUARIO_ADMIN>/.ssh
|
||||
echo "<USUARIO_ADMIN> ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/<USUARIO_ADMIN>
|
||||
chmod 440 /etc/sudoers.d/<USUARIO_ADMIN>
|
||||
```
|
||||
|
||||
**Motivo:** Servidores recém-provisionados têm apenas o usuário `root` ativo. Login direto como root é um vetor de ataque comum — bots fazem brute force em root 24/7. Criamos um usuário dedicado com chave SSH (ed25519), desabilitamos senha e bloqueamos login root no passo seguinte. O arquivo `/etc/sudoers.d/<USUARIO_ADMIN>` garante privilégios de administração sem precisar de senha (NOPASSWD), seguro pois a única forma de acesso é via chave SSH.
|
||||
|
||||
---
|
||||
|
||||
## 2. Atualização do Sistema e Instalação de Ferramentas
|
||||
|
||||
```bash
|
||||
apt-get update -qq
|
||||
apt-get upgrade -y -qq
|
||||
apt-get install -y ufw fail2ban unattended-upgrades wireguard wireguard-tools
|
||||
```
|
||||
|
||||
**Motivo:** Manter o sistema atualizado fecha vulnerabilidades conhecidas (CVEs). As ferramentas instaladas formam a base do hardening:
|
||||
- `ufw`: firewall simplificado sobre iptables
|
||||
- `fail2ban`: bane IPs após tentativas de força bruta
|
||||
- `unattended-upgrades`: atualizações de segurança automáticas
|
||||
- `wireguard`/`wireguard-tools`: VPN moderna e performática
|
||||
|
||||
---
|
||||
|
||||
## 3. Firewall UFW
|
||||
|
||||
```bash
|
||||
ufw --force reset
|
||||
ufw default deny incoming # bloqueia tudo que entra
|
||||
ufw default allow outgoing # permite tudo que sai
|
||||
ufw default deny forward # bloqueia pacotes roteados
|
||||
ufw allow 22/tcp # permite SSH
|
||||
ufw allow out on wg0 # permite tráfego VPN saindo
|
||||
ufw allow in on wg0 # permite tráfego VPN entrando
|
||||
ufw allow out 51820/udp # permite UDP para o endpoint VPN
|
||||
ufw --force enable
|
||||
```
|
||||
|
||||
**Motivo:** A política `deny incoming` fecha todas as portas por padrão — apenas o que for explicitamente permitido entra. A porta 22 é a única entrada permitida. As regras do `wg0` e porta `51820/udp` são necessárias para o túnel WireGuard funcionar.
|
||||
|
||||
> **Atenção:** Verifique se está conectado ao servidor via SSH antes de habilitar o UFW. Execute os comandos em sequência e confirme que a porta 22 está liberada **antes** de rodar `ufw enable`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Hardening SSH
|
||||
|
||||
Arquivo: `/etc/ssh/sshd_config`
|
||||
|
||||
```
|
||||
PermitRootLogin no # bloqueia login direto como root
|
||||
PubkeyAuthentication yes # permite autenticação por chave
|
||||
PasswordAuthentication no # desabilita senha (força uso de chave)
|
||||
PermitEmptyPasswords no # bloqueia senhas vazias
|
||||
KbdInteractiveAuthentication no
|
||||
AllowUsers <USUARIO_ADMIN> # apenas o usuário admin pode fazer login
|
||||
MaxAuthTries 3 # máximo 3 tentativas antes de desconectar
|
||||
MaxSessions 5 # limita sessões simultâneas
|
||||
LoginGraceTime 30 # 30s para autenticar, depois desconecta
|
||||
ClientAliveInterval 300 # detecta conexões mortas em 5 minutos
|
||||
ClientAliveCountMax 2
|
||||
X11Forwarding no # desabilita X11 (desnecessário em servidor)
|
||||
AllowAgentForwarding no # desabilita SSH agent forwarding
|
||||
AllowTcpForwarding no # desabilita port forwarding via SSH
|
||||
PermitTunnel no # desabilita criação de túneis SSH
|
||||
LogLevel VERBOSE # log detalhado para auditoria
|
||||
```
|
||||
|
||||
```bash
|
||||
# Faça backup antes de aplicar
|
||||
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d)
|
||||
|
||||
sshd -t # valida a config antes de aplicar
|
||||
systemctl reload ssh # recarrega sem derrubar conexões ativas
|
||||
```
|
||||
|
||||
**Motivo:** Cada linha desabilitada remove uma superfície de ataque. `AllowUsers <USUARIO_ADMIN>` garante que mesmo que outro usuário seja criado indevidamente, ele não consegue fazer SSH. `LogLevel VERBOSE` registra a impressão digital de chave em cada conexão, útil para forense.
|
||||
|
||||
> **Atenção:** Teste o login com o novo usuário em uma **segunda sessão SSH** antes de fechar a sessão atual. Se algo estiver errado, você ainda consegue corrigir.
|
||||
|
||||
---
|
||||
|
||||
## 5. Hardening do Kernel (sysctl)
|
||||
|
||||
Arquivo: `/etc/sysctl.d/99-hardening.conf`
|
||||
|
||||
```bash
|
||||
# Anti-spoofing: verifica se o IP de origem faz sentido pela interface
|
||||
net.ipv4.conf.all.rp_filter = 1
|
||||
net.ipv4.conf.default.rp_filter = 1
|
||||
|
||||
# Desabilita source routing (permite manipular o caminho dos pacotes)
|
||||
net.ipv4.conf.all.accept_source_route = 0
|
||||
net.ipv6.conf.all.accept_source_route = 0
|
||||
|
||||
# Ignora ICMP redirects (evita ataques de roteamento)
|
||||
net.ipv4.conf.all.accept_redirects = 0
|
||||
net.ipv4.conf.all.secure_redirects = 0
|
||||
net.ipv6.conf.all.accept_redirects = 0
|
||||
|
||||
# Não envia ICMP redirects
|
||||
net.ipv4.conf.all.send_redirects = 0
|
||||
|
||||
# Loga pacotes "marcianos" (IPs impossíveis/suspeitos)
|
||||
net.ipv4.conf.all.log_martians = 1
|
||||
|
||||
# Proteção contra SYN flood (ataque de negação de serviço)
|
||||
net.ipv4.tcp_syncookies = 1
|
||||
net.ipv4.tcp_syn_retries = 2
|
||||
net.ipv4.tcp_synack_retries = 2
|
||||
net.ipv4.tcp_max_syn_backlog = 4096
|
||||
|
||||
# Desabilita IP forward (máquina não é roteador)
|
||||
net.ipv4.ip_forward = 0
|
||||
|
||||
# Ignora ping broadcast (mitigação ataque Smurf)
|
||||
net.ipv4.icmp_echo_ignore_broadcasts = 1
|
||||
|
||||
# Desabilita IPv6 (se não utilizado no ambiente)
|
||||
net.ipv6.conf.all.disable_ipv6 = 1
|
||||
|
||||
# Restringe acesso a ponteiros do kernel e dmesg
|
||||
kernel.dmesg_restrict = 1
|
||||
kernel.kptr_restrict = 2
|
||||
|
||||
# Restringe ptrace (evita que processos inspecionem outros)
|
||||
kernel.yama.ptrace_scope = 1
|
||||
|
||||
# Desabilita core dumps de binários SUID
|
||||
fs.suid_dumpable = 0
|
||||
|
||||
# ASLR máximo: randomiza endereços de memória
|
||||
kernel.randomize_va_space = 2
|
||||
```
|
||||
|
||||
```bash
|
||||
sysctl -p /etc/sysctl.d/99-hardening.conf # aplica imediatamente
|
||||
```
|
||||
|
||||
**Motivo:** Configurações padrão do kernel são permissivas por compatibilidade. Cada parâmetro fecha um vetor específico: `rp_filter` previne IP spoofing, SYN cookies protegem contra flood, `kptr_restrict` impede que atacantes usem vazamentos de ponteiros do kernel para exploits locais.
|
||||
|
||||
> **Nota:** Se o servidor for um roteador ou usar IPv6, ajuste `ip_forward` e `disable_ipv6` de acordo.
|
||||
|
||||
---
|
||||
|
||||
## 6. fail2ban
|
||||
|
||||
Arquivo: `/etc/fail2ban/jail.local`
|
||||
|
||||
```ini
|
||||
[DEFAULT]
|
||||
bantime = 3600 # bane por 1 hora
|
||||
findtime = 600 # janela de 10 minutos para contar tentativas
|
||||
maxretry = 3 # 3 falhas = banido
|
||||
|
||||
[sshd]
|
||||
enabled = true
|
||||
port = ssh
|
||||
maxretry = 3
|
||||
bantime = 86400 # SSH: bane por 24 horas
|
||||
```
|
||||
|
||||
```bash
|
||||
systemctl enable fail2ban
|
||||
systemctl restart fail2ban
|
||||
```
|
||||
|
||||
**Motivo:** Bots fazem brute force SSH 24/7. O fail2ban monitora os logs e bane automaticamente IPs que excedem as tentativas. O `bantime` de 24h para SSH é mais agressivo que o padrão (1h) porque ataques SSH são persistentes e os IPs usados não são reutilizados rapidamente.
|
||||
|
||||
---
|
||||
|
||||
## 7. Desabilitação de Serviços Desnecessários
|
||||
|
||||
```bash
|
||||
systemctl disable --now ModemManager # gerenciador de modem (sem uso em servidor)
|
||||
systemctl disable --now fwupd # atualizações de firmware (interface desktop)
|
||||
systemctl disable --now snapd # sistema de pacotes snap (desnecessário)
|
||||
systemctl disable --now udisks2 # montagem de discos (desnecessário)
|
||||
```
|
||||
|
||||
**Motivo:** Cada serviço rodando é uma superfície de ataque potencial. Serviços de desktop como `ModemManager` e `udisks2` não têm função em um servidor Linux headless. Menos código rodando = menos vulnerabilidades expostas.
|
||||
|
||||
> **Dica:** Use `systemctl list-units --type=service --state=running` para auditar todos os serviços ativos e desabilitar outros que não sejam necessários ao ambiente.
|
||||
|
||||
---
|
||||
|
||||
## 8. VPN WireGuard com Killswitch
|
||||
|
||||
### Geração de chaves
|
||||
|
||||
```bash
|
||||
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
|
||||
chmod 600 /etc/wireguard/private.key
|
||||
cat /etc/wireguard/public.key # registre esta chave no painel do provedor VPN
|
||||
```
|
||||
|
||||
### Arquivo de configuração
|
||||
|
||||
`/etc/wireguard/wg0.conf` (permissão 600):
|
||||
|
||||
```ini
|
||||
[Interface]
|
||||
Address = <IP_TUNEL_VPN>/<PREFIXO>
|
||||
PrivateKey = <conteúdo de /etc/wireguard/private.key>
|
||||
DNS = <DNS_PRIMARIO>, <DNS_SECUNDARIO>
|
||||
|
||||
# ── Killswitch ──────────────────────────────────────────────────────────
|
||||
# Regra 1: respostas de conexões ENTRANTES (ex: SSH) saem pelo eth0
|
||||
PostUp = ip rule add from <IP_DO_SERVIDOR> table main priority 100
|
||||
|
||||
# Regra 2: bloqueia qualquer tráfego de saída que não seja:
|
||||
# - pelo tunnel wg0
|
||||
# - pacotes marcados pelo WireGuard (os próprios pacotes UDP cifrados)
|
||||
# - respostas ESTABLISHED/RELATED (replies de conexões recebidas)
|
||||
# - endereços LOCAL (loopback)
|
||||
PostUp = iptables -I OUTPUT ! -o %i \
|
||||
-m mark ! --mark $(wg show %i fwmark) \
|
||||
-m conntrack ! --ctstate ESTABLISHED,RELATED \
|
||||
-m addrtype ! --dst-type LOCAL \
|
||||
-j REJECT
|
||||
|
||||
PreDown = ip rule del from <IP_DO_SERVIDOR> table main priority 100
|
||||
PreDown = iptables -D OUTPUT ! -o %i \
|
||||
-m mark ! --mark $(wg show %i fwmark) \
|
||||
-m conntrack ! --ctstate ESTABLISHED,RELATED \
|
||||
-m addrtype ! --dst-type LOCAL \
|
||||
-j REJECT
|
||||
|
||||
[Peer]
|
||||
PublicKey = <CHAVE_PUBLICA_PEER_VPN>
|
||||
AllowedIPs = 0.0.0.0/0
|
||||
Endpoint = <ENDPOINT_VPN>
|
||||
PersistentKeepalive = 25
|
||||
```
|
||||
|
||||
### Ativar no boot
|
||||
|
||||
```bash
|
||||
systemctl enable wg-quick@wg0
|
||||
wg-quick up wg0
|
||||
```
|
||||
|
||||
**Como funciona o killswitch:**
|
||||
- **VPN UP:** todo tráfego novo vai pelo `wg0` (tunnel). A regra `ip rule from <IP_DO_SERVIDOR> table main` garante que respostas SSH saiam pelo `eth0` (não pelo tunnel), mantendo acesso ao servidor.
|
||||
- **VPN cai:** o `wg0` permanece up mas não encaminha pacotes. A regra iptables `REJECT` bloqueia qualquer tentativa de sair pelo `eth0`. Nenhum dado vaza para fora da VPN.
|
||||
- `PersistentKeepalive = 25`: mantém o tunnel ativo através de NATs e firewalls.
|
||||
|
||||
### Verificação pós-ativação
|
||||
|
||||
```bash
|
||||
wg show # status do tunnel (handshake, bytes transferidos)
|
||||
curl https://api.ipify.org # deve retornar o IP do provedor VPN, não o IP real do servidor
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resumo do Estado Final (preencher após execução)
|
||||
|
||||
| Item | Antes | Depois |
|
||||
|------|-------|--------|
|
||||
| Firewall | Inativo | UFW ativo, deny all |
|
||||
| Login root SSH | Permitido | Bloqueado |
|
||||
| Autenticação SSH | Senha + chave | Chave apenas |
|
||||
| fail2ban | Não instalado | Ativo |
|
||||
| Serviços rodando | _(contar antes)_ | _(contar depois)_ |
|
||||
| IP externo | `<IP_DO_SERVIDOR>` | IP do provedor VPN |
|
||||
| Killswitch VPN | N/A | Ativo via iptables |
|
||||
| Kernel hardening | Padrão permissivo | sysctl endurecido |
|
||||
|
||||
---
|
||||
|
||||
## Comandos de Manutenção
|
||||
|
||||
```bash
|
||||
# Status da VPN
|
||||
wg show
|
||||
systemctl status wg-quick@wg0
|
||||
|
||||
# Reiniciar VPN
|
||||
wg-quick down wg0 && wg-quick up wg0
|
||||
|
||||
# Status do firewall
|
||||
ufw status verbose
|
||||
|
||||
# IPs banidos pelo fail2ban
|
||||
fail2ban-client status sshd
|
||||
|
||||
# Logs SSH (últimas 50 linhas)
|
||||
journalctl -u ssh -n 50 --no-pager
|
||||
|
||||
# Conectar ao servidor (do seu laptop)
|
||||
ssh <USUARIO_ADMIN>@<IP_DO_SERVIDOR>
|
||||
|
||||
# Auditar serviços rodando
|
||||
systemctl list-units --type=service --state=running
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue