Аудит безопасности Linux-сервера + опциональный watchdog. Без баз сигнатур.
櫓 — Сторожевая башня. Видит всё. Молчит до угрозы.
Парный проект к GORONIN. Goronin — активный страж-ловушка (浪人 ронин). Yagura — наблюдательная башня (櫓): аудит конфигурации + поведенческий watchdog. Хорошо стоят вместе.
curl -sSL https://raw.githubusercontent.com/kitay-sudo/yagura/main/install.sh | sudo bashСейчас репо приватный — нужен PAT с правом Contents: Read на этот репозиторий:
export GITHUB_TOKEN=github_pat_xxxxx
curl -sSL -H "Authorization: Bearer $GITHUB_TOKEN" \
https://raw.githubusercontent.com/kitay-sudo/yagura/main/install.sh \
| sudo GITHUB_TOKEN="$GITHUB_TOKEN" bash
sudo GITHUB_TOKEN=...обязательно —sudoпо умолчанию сбрасывает env, и токен внутри скрипта пропадёт.
Свежая установка:
- Поставится
python3+python3-venv(если их нет на хосте). - Создастся venv в
/opt/yagura/venv/, скачается архив с GitHub, установятся зависимости. - Зарегистрируется wrapper
/usr/local/bin/yagura. - Запустится интерактивный мастер: выбор AI-провайдера (опционально) → scan → меню harden → предложение запустить watchdog с Telegram-алертами.
Обновление (если /etc/yagura/config.yml уже есть):
tool/синхронизируется с новой версией.yagura-watch.serviceперезапускается с новым кодом — wizard не запускается, конфиг и baseline сохраняются.
YAGURA_VERSION=v0.5.0 curl -sSL ... | sudo YAGURA_VERSION=v0.5.0 GITHUB_TOKEN=... bash📖 Подробное объяснение для пользователей — что приходит в Telegram, сколько стоит AI, как удалить — в HOW_IT_WORKS.md.
| Подсистема | Что |
|---|---|
| Collectors | psutil + парсинг /etc/passwd, /etc/shadow, sshd_config, iptables -S, systemctl, dpkg/rpm, cron, sysctl, хеши критичных файлов. ~30–60 секунд на полный сбор. |
| Analyzers | 18+ scan-правил: PermitRootLogin, PasswordAuth без fail2ban, default ACCEPT в iptables, ASLR off, NOPASSWD-сюдо, BD-листенеры на 0.0.0.0, cron с curl ... | bash, systemd-юниты из /tmp и т.д. → Security Score 0–100. |
| AI (опционально) | Claude / GPT-4o / Gemini пишет короткий разбор отчёта простым языком. Твой ключ, твой счёт. |
| Harden | Меню исправлений с preview / apply / rollback. Каждое применение пишет rollback-команду в harden_history. |
| Watch | systemd-сервис yagura-watch — раз в 5 мин сравнивает состояние с baseline и шлёт алерты в Telegram при отклонениях. ~0.1% CPU. |
Один Python-инструмент в venv. Никакого eBPF, никаких ядерных модулей, никаких баз сигнатур.
Scan-режим: yagura scan → собрал данные → проанализировал → нарисовал Rich-отчёт + сохранил markdown в /var/log/yagura/report-YYYY-MM-DD-HHMM.md. Не висит в памяти после завершения.
Watch-режим: yagura watch start сохраняет baseline в /var/lib/yagura/baseline.json и регистрирует systemd-юнит. Демон раз в N минут (по умолчанию 5) делает легковесную проверку — сравнивает листенеры, cron, systemd-units, UID-0 юзеров, hash критичных файлов с baseline, плюс эвристики (cryptominer, reverse-shell). Найдено отклонение → Telegram-алерт + (опционально) AI-обогащение для HIGH/CRITICAL.
Состояние: /etc/yagura/config.yml (mode 0600), /var/lib/yagura/baseline.json, /var/log/yagura/. Системный wrapper в /usr/local/bin/yagura.
Исходящий трафик: Telegram Bot API (если включён watch) + API выбранного AI-провайдера (если AI настроен). Входящих соединений у Yagura нет — Telegram-связь односторонняя, бот не принимает команды.
yagura # полный wizard: scan + harden + watch offer
yagura health # компактный дашборд: watch, uptime, последние алерты, last scan, AI, baseline
yagura help # алиас --help
yagura version
yagura scan # только аудит
yagura scan --json # JSON-вывод для скриптов
yagura scan --report-only # сохранить только markdown без интерактива
yagura harden # меню harden (использует свежий scan)
yagura harden --apply-all # все recommended без подтверждений (dangerous)
yagura harden rollback <id> # откатить применённое изменение
yagura watch start # baseline + systemd-юнит + старт
yagura watch stop # остановить + disable
yagura watch status # systemctl status + последние 10 алертов
yagura watch logs # journalctl -u yagura-watch -f
yagura baseline show # текущий baseline (JSON)
yagura baseline reset # пересобрать baseline (после планового деплоя)
yagura baseline diff # что изменилось vs baseline
yagura whitelist list
yagura whitelist add port 8080
yagura whitelist add process /opt/myapp/bin/server
yagura whitelist add ssh-ip 1.2.3.4
yagura whitelist remove port 8080
yagura report # последний markdown-отчёт
yagura report list # все сохранённые
yagura report show 2026-04-28
yagura config show # текущий config.yml
yagura config edit # открыть в $EDITOR
yagura config set ai.model claude-sonnet-4-6
yagura config set watch.interval_minutes 1 # тест/отладка (default: 5)
yagura uninstall # откатить ВСЕ harden + удалить systemd-юнит + cleanupВсе команды требуют root (читают /etc/shadow, дёргают systemctl и iptables).
yagura health можно запускать без root — но без root не увидишь статус yagura-watch.service через systemctl.
/etc/yagura/config.yml (создаётся wizard'ом, mode 0600):
version: 1
ai:
provider: claude # claude | openai | gemini | none
api_key: sk-ant-...
model: "" # пусто = провайдер default
watch:
enabled: true
interval_minutes: 5
telegram:
bot_token: "123:ABC..."
chat_id: "987654321"
rules_disabled: [] # ID правил которые юзер выключил
whitelist:
ports: [22, 80, 443]
processes:
- /usr/sbin/sshd
- /usr/sbin/nginx
ssh_ips:
- 1.2.3.4
harden_history:
- id: ssh.disable_root
applied_at: "2026-04-28T14:23:11Z"
rollback_cmd: "sed -i ... && systemctl restart sshd"Baseline в отдельном файле — /var/lib/yagura/baseline.json.
| ID | Severity | Правило |
|---|---|---|
| SSH-001 | CRITICAL | PermitRootLogin yes в sshd_config |
| SSH-002 | HIGH | PasswordAuthentication yes + порт 22 + нет fail2ban |
| SSH-003 | CRITICAL | Юзеры с пустым паролем в /etc/shadow |
| SSH-004 | MEDIUM | >50 неудачных SSH-попыток за сутки |
| FW-001 | HIGH | Нет активного firewall (ufw/firewalld/iptables/nftables) |
| FW-002 | HIGH | Default policy iptables INPUT = ACCEPT |
| NET-001 | HIGH | Сервис слушает 0.0.0.0 на портах БД (3306/5432/27017/6379/...) |
| NET-002 | CRITICAL | Listener из /tmp, /dev/shm, /var/tmp |
| USR-001 | CRITICAL | Несколько UID 0 в /etc/passwd |
| USR-002 | MEDIUM | Sudo NOPASSWD для не-системных юзеров |
| PKG-001 | LOW | Не установлен fail2ban |
| PKG-002 | LOW | Не установлен unattended-upgrades / dnf-automatic |
| PKG-003 | MEDIUM | Доступны >5 обновлений |
| KER-001 | MEDIUM | net.ipv4.tcp_syncookies = 0 |
| KER-002 | HIGH | kernel.randomize_va_space = 0 (ASLR off) |
| CRON-001 | HIGH | Cron-job содержит curl ... | bash или base64 |
| CRON-002 | MEDIUM | Cron-job из /tmp или /home/* |
| SVC-001 | CRITICAL | systemd-юнит с ExecStart из /tmp, /dev/shm, /var/tmp |
| ID | Severity | Описание |
|---|---|---|
| W-NET-001 | HIGH | Появился listener которого не было в baseline |
| W-PROC-001 | HIGH | Процесс из /tmp, /dev/shm, /var/tmp появился в listener'ах |
| W-PROC-002 | MEDIUM | CPU процесса >80% устойчиво + сетевые соединения (cryptominer) |
| W-PROC-003 | CRITICAL | bash/sh/python/perl/nc имеет ESTABLISHED наружу (reverse-shell) |
| W-FILE-001 | CRITICAL | Хеш /etc/passwd, /etc/shadow, /etc/sudoers, sshd_config, authorized_keys изменился |
| W-CRON-001 | HIGH | Появился новый cron-job |
| W-CRON-002 | CRITICAL | Cron с curl | bash / wget | sh / base64 |
| W-SVC-001 | HIGH | Появился новый enabled systemd-юнит |
| W-USR-001 | CRITICAL | Новый аккаунт с UID 0 |
| W-USR-002 | HIGH | В /etc/sudoers или sudoers.d/ добавлен новый юзер |
Самоисключения: W-SVC-001 не алертит на собственные юниты с префиксом yagura- (напр. yagura-watch.service). AI-промпт для алертов знает про артефакты Yagura и помечает их как ложные срабатывания.
Cooldown: один и тот же алерт подавляется на 1 час, чтобы не спамить Telegram.
После yagura watch start нужно проверить что детект и Telegram-доставка реально работают. Самый простой тест — открыть «подозрительный» listener:
# 1. Свежий baseline — на нём НЕТ порта 8888
sudo yagura baseline reset
# 2. Уменьши интервал проверки до 1 минуты (по умолчанию 5)
sudo yagura config set watch.interval_minutes 1
sudo systemctl restart yagura-watch.service
# 3. Открой listener в фоне
nohup python3 -m http.server 8888 > /tmp/test-listener.log 2>&1 &
echo "PID: $!"
# 4. Жди ~1 минуту — в Telegram должен прийти алерт W-NET-001 (HIGH)
sudo yagura watch logs # увидишь tick в реальном времени
# 5. Убей listener и верни интервал
kill $!
sudo yagura config set watch.interval_minutes 5
sudo systemctl restart yagura-watch.serviceЕсли алерт не пришёл за 2 минуты:
- проверь
yagura health— разделwatchдолжен бытьactive (running) - проверь
yagura config show—watch.telegram.bot_tokenиchat_idнепустые - проверь логи:
sudo yagura watch logs— там должна быть строка[INFO] tick: N alerts
Аналогично можно протестировать W-CRON-001 ((crontab -l; echo "* * * * * echo test") | crontab -) или W-USR-002 (новый юзер в sudoers с NOPASSWD).
- Telegram-связь односторонняя: бот только шлёт сообщения, не принимает команды. Это не вектор атаки.
- API-ключи хранятся в
/etc/yagura/config.ymlсchmod 0600. Никуда не отправляются кроме API провайдера. - AI вызывается только: 1) во время
scan(если ключ настроен), 2) на HIGH/CRITICAL алерт в watch. На LOW/MEDIUM не тратим API-кредиты. sudoнужен потому что: чтение/etc/shadow, парсинг sudoers,iptables -S, запись в/etc/ssh/sshd_configпри harden, регистрация systemd-юнита для watch.- Каждое harden-действие имеет rollback-команду.
yagura uninstallоткатит всё и удалит саму Yagura.
- Ubuntu 20.04+ / Debian 11+ / CentOS Stream 9 / Rocky Linux 9 / Arch (с systemd)
- Ядро 3.10+ (используется только polling через
psutil, без eBPF) - Python 3.10+ с пакетом
venv(на Debian/Ubuntu это отдельныйpythonX.Y-venv, install.sh ставит автоматически)
Без systemd scan и harden работают, watch start выдаст предупреждение и не установит юнит.
Команда yagura health на хостах без systemd показывает watch: n/a вместо статуса сервиса.
- больше harden-actions:
PasswordPolicy,LoginDefs, AppArmor profiles - опциональный eBPF-collector для real-time детекций
- web-dashboard (read-only, локальный) для просмотра истории алертов
- multi-server: один CLI собирает отчёты с N серверов через ssh
История изменений по версиям — в CHANGELOG.md.
MIT — см. LICENSE.
Yagura развивается на энтузиазме. Если оказался полезен:
- USDT (TRC20):
TF9F2FPkreHVfbe8tZtn4V76j3jLo4SeXM - TON:
UQBl88kXWJWyHkDPkWNYQwwSCiCAIfA2DiExtZElwJFlIc1o
После доната напиши @kitay9 в Telegram свой ник — добавлю в стену чести на лендинге.