Проблема
Сервер легко выглядит 'достаточно закрытым' сразу после ручного hardening, но через несколько недель drift возвращает старые настройки: новый sshd_config fragment, забытый admin user, лишний service unit, открытый debug listener.
Без verification team memory заменяет контроль. Это работает до первого срочного релиза, emergency fix или смены админа.
Решение
Полезно описывать hardening не только словами, но и проверками: ssh settings, firewall posture, listening ports, package policy, service allowlist, cron/systemd persistence surface, file permissions и логирование.
Зрелый подход хранит исключения рядом с baseline: кто владелец, почему отклонение принято, до какого срока и каким compensating control оно покрыто.
Что проверить руками
- Собрать baseline по SSH, sudo, firewall, services, packages, logging и backups.
- Сравнить desired state с фактическим listening surface и enabled units.
- Для каждого отклонения записать owner, reason и expiry.
- Проверять drift по расписанию, а не только после инцидента.
Типичные ошибки
- Считать hardening finished state вместо continuous verification.
- Смешивать production exceptions с 'временно оставили так'.
- Опираться только на manual review без повторяемого baseline.
Defensive checklist
- Baseline выражен в проверках, а не только в тексте.
- Exceptions имеют owner и expiry.
- Listening surface и enabled units сверяются регулярно.
- Retest после изменений подтверждает, что нужный сервис работает, а drift не вырос.
Безопасный пример кода
Быстрый baseline-check для SSH и listening surface. Пример рассчитан на owned/lab-среду и показывает инженерную логику проверки, а не эксплуатационную цепочку.
#!/usr/bin/env bash
set -euo pipefail
echo "[*] ssh hardening"
sshd -T | egrep 'permitrootlogin|passwordauthentication|pubkeyauthentication'
echo "[*] externally listening sockets"
ss -tulpen | awk 'NR == 1 || $5 !~ /127.0.0.1|::1/'
echo "[*] enabled services"
systemctl list-unit-files --type=service --state=enabled
Как это должно попасть в отчёт
- Baseline: desired settings, current state, exception registry.
- Evidence: command outputs, config fragments, service inventory.
- Retest: hardened settings survive reboot, deploy and routine maintenance.