Небольшой defensive-инструмент для разбора OpenSSH authentication logs и
первичной корреляции подозрительных входов. Он нормализует события из
auth.log, secure и текстового вывода journald, строит сводку и выделяет
последовательности, которые стоит проверить во время triage.
Инструмент не объявляет каждый неудачный вход атакой: finding создаётся только после достижения явно заданного порога в ограниченном временном окне.
- неуспешные и успешные входы через password, public key и keyboard-interactive;
- попытки входа под несуществующими пользователями;
- IPv4 и IPv6 источники;
- несколько файлов за один запуск или поток из stdin;
- RFC 3164 timestamps (
Feb 8 10:00:00) и ISO 8601 journald timestamps.
| Rule ID | Механизм | Порог по умолчанию | Severity |
|---|---|---|---|
ssh_brute_force |
серия отказов с одного IP | 5 за 5 минут | high |
ssh_password_spray |
один IP перебирает разных пользователей | 4 пользователя за 5 минут | high |
ssh_distributed_account_attack |
один аккаунт атакуют разные IP | 4 IP за 5 минут | high |
ssh_success_after_failures |
успешный вход после серии отказов с той же пары IP/user | 5 отказов за 5 минут | critical |
Последнее правило — сигнал для срочной проверки, а не автоматическое доказательство компрометации: легитимный пользователь также может несколько раз ошибиться и затем войти.
git clone https://github.com/fant3k/ssh-log-analyzer.git
cd ssh-log-analyzer
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install .
ssh-log-analyzer --versionПроект использует только Python standard library и не имеет runtime-зависимостей.
ssh-log-analyzer sample_logs/example_auth.log --year 2026Fixture использует только зарезервированные для документации IP-диапазоны. Ожидаемый результат: 20 строк, 19 authentication events и 5 findings, покрывающих все четыре правила.
Один файл:
ssh-log-analyzer /var/log/auth.logРотированные файлы анализируются вместе:
ssh-log-analyzer /var/log/auth.log.1 /var/log/auth.logПоток journald:
journalctl -u ssh --since today -o short-iso | ssh-log-analyzer -Если syslog-строки относятся не к текущему году, его нужно указать явно:
ssh-log-analyzer archived-auth.log --year 2025ssh-log-analyzer /var/log/auth.log \
--json-out reports/ssh-analysis.json \
--csv-out reports/ssh-findings.csvJSON содержит версию схемы, summary, top IP/users и findings. Нормализованные события по умолчанию не записываются, поскольку usernames и IP могут быть чувствительными. Для локального расследования их можно добавить явно:
ssh-log-analyzer /var/log/auth.log \
--json-out reports/with-events.json \
--include-eventsssh-log-analyzer /var/log/auth.log \
--window-minutes 10 \
--brute-force-threshold 8 \
--spray-user-threshold 6 \
--distributed-ip-threshold 5--fail-on-findings возвращает exit code 2, если найден хотя бы один сигнал.
Это позволяет использовать анализатор в локальном pipeline без смешивания
ошибки запуска и обнаруженного события.
ssh_log_analyzer/
parser.py OpenSSH parsing и нормализация
detection.py window-based correlation rules
models.py типизированные events, findings и result
reporting.py console, JSON и CSV
cli.py аргументы, входные лимиты и orchestration
sample_logs/ синтетический безопасный fixture
tests/ unit и CLI integration tests
scripts/test.shТесты проверяют реальные варианты OpenSSH-строк, IPv4/IPv6, оба формата timestamp, каждое правило корреляции, временные окна, отчёты, CLI и защитный лимит числа строк. GitHub Actions повторяет проверки на Python 3.9, 3.11 и 3.13.
- это triage-инструмент, а не SIEM и не замена ручному расследованию;
- RFC 3164 не содержит год — он задаётся через
--year; - ISO timestamps приводятся к UTC, RFC 3164 остаются в локальном времени хоста;
- нестандартные сообщения, изменённые дистрибутивом, могут потребовать нового parser rule;
- NAT, bastion hosts и общие egress IP необходимо учитывать при интерпретации;
- severity отражает приоритет проверки, а не доказанный impact.
