Проблема
Сервер может быть переустановлен и казаться чистым, но через месяц на нем уже есть сайт, VPN, reverse proxy, мониторинг, временные конфиги и старые backup-файлы.
Большая часть шума в логах - автоматические 404-запросы, но именно по ним видно, какие классы панелей и CMS пытаются найти сканеры.
Решение
Нужно разделять human traffic и scanner noise, контролировать real client IP, мониторить 404 bursts и hash drift критичных конфигов.
Hardening должен быть проверяемым: сайт отвечает 200, VPN transport не тронут, private dashboards закрыты 401, scanner UA режется 403.
Что проверить руками
- Сверить listening ports и service allowlist.
- Проверить, что access log пишет real IP, а не локальный proxy.
- Посмотреть top 404 targets за последние сутки.
- Сравнить hashes nginx/haproxy/ssh/xray с предыдущим baseline.
Безопасный пример кода
Мини-анализатор 404 bursts по nginx access.log. Пример рассчитан на owned/lab-среду и не выполняет вредоносных действий.
from collections import Counter, defaultdict
from datetime import datetime, timedelta, timezone
import re
line_re = re.compile(r'(?P<ip>\S+) .* \[(?P<ts>[^\]]+)\] "\S+ (?P<path>\S+) [^"]+" (?P<status>\d{3})')
window = datetime.now(timezone.utc) - timedelta(minutes=15)
by_ip = defaultdict(Counter)
with open("/var/log/nginx/access.log", encoding="utf-8", errors="ignore") as log:
for line in log:
m = line_re.match(line)
if not m or m.group("status") != "404":
continue
by_ip[m.group("ip")][m.group("path")] += 1
for ip, paths in by_ip.items():
total = sum(paths.values())
if total >= 20:
print(ip, total, paths.most_common(3))
Как это должно попасть в отчёт
- Signals: suspicious IP, 404 burst, changed edge config, inactive service.
- Controls: rate limit, deny sensitive paths, basic auth for private dashboards.
- Retest: normal site/VPN paths work, scanner patterns are blocked.