A ilusão do sshd_config: como realmente garantir a segurança da autenticação SSH no cPanel/CloudLinux#
Quem trabalha na trincheira da administração de sistemas de alto nível (SysAdmin / SRE) sabe que o dia a dia é repleto de falsas sensações de segurança. Recentemente, liderei uma auditoria de hardening (Evento de origem: #3104798) em nossos servidores cPanel executando CloudLinux. O objetivo era elementar: desativar a autenticação por senha (PasswordAuthentication no) e forçar o uso exclusivo de chaves criptográficas SSH.
O que parecia ser uma simples alteração de configuração revelou uma inconsistência brutal entre o que está declarado no arquivo /etc/ssh/sshd_config e a realidade operacional do daemon SSH em execução.
Quando o arquivo e as APIs enganam você#
Inicialmente, as alterações de configuração foram disparadas usando os utilitários de linha de comando nativos do cPanel via WHM API 1 (whmapi1):
# 1. Verificar a configuração do SSHD registrada pelo WHM
whmapi1 listsshdconfig
# 2. Desabilitar a autorização de senhas via API do WHM
whmapi1 setserviceconfig service=sshd key=PasswordAuthentication value=no
O Problema Técnico: Embora a chamada retorne sucesso e o arquivo principal /etc/ssh/sshd_config reflita a alteração, o servidor pode continuar aceitando conexões de senha. Isso ocorre devido a três fatores do ecossistema:
- Arquivos Drop-in (
sshd_config.d/): Versões modernas do OpenSSH carregam de forma modular os arquivos contidos em/etc/ssh/sshd_config.d/*.conf. Se um arquivo (como50-cloudlinux.confou diretrizes injetadas por provedores de cloud no bootstrap) declararPasswordAuthentication yes, essa instrução sobrescreve a diretiva declarada no/etc/ssh/sshd_configprincipal dependendo da ordem doInclude. - Injeção via Cloud-Init: Serviços de provisionamento de nuvem reescrevem diretivas no boot, restaurando a autenticação por senha silenciosamente.
- Limitações da API WHM: O
whmapi1edita o arquivo básico, mas muitas vezes falha em varrer os drop-ins conflitantes ou reiniciar o serviço com o sinal de recarga (SIGHUP) adequado.
Como encontrar arquivos drop-in conflitantes#
Para auditar se existem arquivos de configuração ocultos interferindo nas regras globais do SSH:
# Listar todos os arquivos drop-in ativos
ls -la /etc/ssh/sshd_config.d/
# Buscar pela diretiva de autenticação em todos os arquivos de configuração do SSH
grep -r -i "PasswordAuthentication" /etc/ssh/sshd_config.d/
# Verificar a declaração da diretiva Include no arquivo principal
grep -i "^Include" /etc/ssh/sshd_config
# Script rápido para mapear os arquivos e seus valores declarados
for f in /etc/ssh/sshd_config.d/*.conf; do
echo "=== Arquivo: $f ==="
grep -i "PasswordAuthentication" "$f" 2>/dev/null || echo "(diretiva ausente)"
done
Procedimento de correção passo a passo#
Caso você identifique discrepâncias, siga o fluxo seguro de correção abaixo:
1. Backup de segurança obrigatório#
Antes de salvar qualquer alteração no daemon SSH, faça cópias de segurança de toda a árvore de configurações para evitar quebras graves que impeçam o acesso ao servidor:
# Backup do arquivo principal
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d)
# Backup do diretório drop-in
sudo cp -r /etc/ssh/sshd_config.d/ /root/sshd_config.d.bak.$(date +%Y%m%d)/
# Backup unificado em tarball
sudo tar czf /root/ssh-backup-$(date +%Y%m%d).tar.gz /etc/ssh/
2. Configuração de chaves SSH (máquina local para o servidor)#
Antes de banir senhas, certifique-se de que sua chave pública está devidamente autorizada no servidor.
No seu computador pessoal (cliente):
# Gerar par de chaves usando o algoritmo seguro ED25519
ssh-keygen -t ed25519 -C "[email protected]"
# Copiar a chave pública gerada para o servidor remoto
ssh-copy-id -p 22 usuario@ip-do-servidor
Teste o login sem senha abrindo um terminal de testes:
ssh -p 22 usuario@ip-do-servidor
3. Limpeza de drop-ins e configurações conflitantes#
Acesse o servidor como root. Se encontrar ocorrências de PasswordAuthentication yes nos diretórios drop-in, edite-os definindo o valor correto ou remova-os se forem lixo redundante:
# Alterar todas as ocorrências de PasswordAuthentication nos drop-ins para "no"
sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config.d/*.conf 2>/dev/null || true
No arquivo principal /etc/ssh/sshd_config, garanta a desativação:
sudo sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
4. Hardening adicional de segurança do SSHD#
Aproveite para garantir que outras diretrizes essenciais de segurança estejam ativas:
# Desabilitar login direto do root por senha
PermitRootLogin prohibit-password
# Forçar autenticação por chave pública
PubkeyAuthentication yes
# Desativar autenticação interativa de teclado que burla o PasswordAuthentication
ChallengeResponseAuthentication no
# Limitar tentativas de login inválido por conexão
MaxAuthTries 3
# Tempo de tolerância para finalizar a autenticação
LoginGraceTime 30
5. Validação de sintaxe#
Nunca reinicie o serviço SSH sem validar a integridade da sintaxe:
sudo sshd -t
Se este comando retornar qualquer erro de configuração, não reinicie o SSH! Investigue a linha apontada no log.
6. Teste seguro em sessão separada (prevenção de lockout)#
Regra de Ouro do SysAdmin: Nunca feche a sessão SSH ativa atual. Com a sessão atual aberta, abra um novo terminal em sua máquina e execute o seguinte teste de conexão simulada:
# Forçar uma conexão de teste rápida via chave pública
ssh -o "BatchMode=yes" -o "ConnectTimeout=5" usuario@ip-do-servidor echo "Conexão Segura OK"
Se a resposta for "Conexão Segura OK", o seu acesso por chave está funcionando perfeitamente.
7. Aplicação e reinicialização do daemon#
Agora sim, reinicie o SSH para carregar a nova configuração em memória:
sudo systemctl restart sshd
Validando o estado efetivo em memória (one-liner correto)#
A forma definitiva de auditar o servidor é interrogar o daemon carregado em memória usando o utilitário sshd -T (modo de teste estendido). Ele resolve todos os includes recursivos de arquivos .conf e imprime o estado final operacional.
Use o one-liner Bash correto abaixo para validação:
# Validar se o PasswordAuthentication está desligado de fato
sshd -T | grep -qi '^passwordauthentication no$' && echo "CONFORME: Senhas desabilitadas." || echo "ATENÇÃO: Senhas ainda habilitadas!"
Para listar os parâmetros reais do SSHD associados à segurança:
sshd -T | grep -iE "^(passwordauthentication|pubkeyauthentication|permitrootlogin|challengeresponseauthentication|usepam)"
Verificação de logs do SSH#
Para certificar-se de que ataques de força bruta de senhas estão sendo bloqueados e depurar logins, monitore os logs de autenticação do sistema (/var/log/auth.log em distros Debian/Ubuntu ou /var/log/secure em RHEL/CloudLinux):
# Monitorar logs de autenticação do SSH em tempo real
tail -f /var/log/secure | grep sshd
# Listar as últimas 20 tentativas de login inválidas ou usuários inexistentes
sudo grep -i "failed\|invalid" /var/log/secure | tail -20
# Verificar conexões bem-sucedidas por chaves públicas
sudo grep -i "accepted publickey" /var/log/secure | tail -20
Procedimento de rollback de emergência#
Se por acaso você perder acesso ou o serviço SSH falhar na inicialização, acesse a VPS por meio do terminal de console de emergência do provedor (VNC/IPMI) e reverta a configuração:
# 1. Limpar arquivos de configuração do SSH modificados
sudo rm -rf /etc/ssh/sshd_config.d/
sudo rm -f /etc/ssh/sshd_config
# 2. Restaurar backups criados no início do procedimento
sudo cp /etc/ssh/sshd_config.bak.* /etc/ssh/sshd_config
sudo cp -r /root/sshd_config.d.bak.*/ /etc/ssh/sshd_config.d/
# 3. Validar sintaxe
sudo sshd -t
# 4. Iniciar o serviço
sudo systemctl restart sshd
Script de auditoria SSH completo#
Abaixo está o script completo para validação automática de conformidade SSH:
audit-ssh.sh — Script de auditoria avançada SSHGist ↗Ver código
#!/bin/bash
# audit-ssh.sh - Auditoria avançada de conformidade e segurança SSH
set -euo pipefail
# 0. Checagem e elevação de privilégios para leitura das configurações e chaves do SSH
if [ "${EUID:-$(id -u)}" -ne 0 ]; then
echo "⚠️ Aviso: Este script requer privilégios de root para inspecionar as chaves do host e drop-ins (/etc/ssh/)."
if command -v sudo >/dev/null 2>&1; then
echo " Elevando execução com sudo..."
exec sudo bash "$0" "$@"
else
echo "❌ Erro: sudo indisponível e usuário não é root. Execute como root." >&2
exit 1
fi
fi
echo "=== INICIANDO AUDITORIA SSH ==="
echo ""
# 1. Estado Efetivo em Memória
echo "[1] Verificando Parâmetros Efetivos (sshd -T):"
if SSHD_OUT=$(sshd -T 2>&1); then
PASS_AUTH=$(echo "$SSHD_OUT" | grep -i "^passwordauthentication" | awk '{print $2}' || echo "desconhecido")
if [ "$PASS_AUTH" = "no" ]; then
echo " ✅ PasswordAuthentication: NO (Seguro)"
else
echo " ❌ PasswordAuthentication: $PASS_AUTH (Inseguro - Aceita senha)"
fi
ROOT_LOGIN=$(echo "$SSHD_OUT" | grep -i "^permitrootlogin" | awk '{print $2}' || echo "desconhecido")
if [ "$ROOT_LOGIN" = "no" ] || [ "$ROOT_LOGIN" = "prohibit-password" ]; then
echo " ✅ PermitRootLogin: $ROOT_LOGIN (Seguro)"
else
echo " ⚠️ PermitRootLogin: $ROOT_LOGIN (Inseguro - Recomenda-se desabilitar root por senha)"
fi
CHALLENGE=$(echo "$SSHD_OUT" | grep -i "^challengeresponseauthentication" | awk '{print $2}' || echo "desconhecido")
if [ "$CHALLENGE" = "no" ]; then
echo " ✅ ChallengeResponseAuthentication: NO (Seguro)"
else
echo " ⚠️ ChallengeResponseAuthentication: $CHALLENGE (Risco de bypass de senha via PAM)"
fi
else
echo " ❌ Falha ao executar sshd -T:"
echo "$SSHD_OUT" | sed 's/^/ /'
fi
# 2. Drop-ins e Conflitos em sshd_config.d/
echo ""
echo "[2] Verificando Arquivos Drop-in e Includes:"
DROPINS_COUNT=$(find /etc/ssh/sshd_config.d/ -maxdepth 1 -type f -name "*.conf" 2>/dev/null | wc -l | tr -d ' ' || echo 0)
echo " Total de drop-ins ativos: $DROPINS_COUNT"
CONFLICT_LINES=$(grep -rnEI '^[[:space:]]*PasswordAuthentication' /etc/ssh/sshd_config.d/ 2>/dev/null || true)
if [ -n "$CONFLICT_LINES" ]; then
CONFLICTS=$(echo "$CONFLICT_LINES" | wc -l | tr -d ' ')
echo " ⚠️ Encontrados $CONFLICTS conflitos de PasswordAuthentication nos drop-ins:"
echo "$CONFLICT_LINES" | sed 's/^/ /'
else
echo " ✅ Nenhum conflito de diretiva de senha em drop-ins."
fi
echo ""
echo "=== AUDITORIA CONCLUÍDA ==="Este artigo foi útil?
Deixe uma reação rápida para apoiar o conteúdo:
Este post está licenciado sob CC BY-NC.



Comentários
Participe da discussão abaixo.
0 comentários