feat(license): сервер лицензий lic.zetit.ru — кабинет, онлайн-активация и защита

- bj-license-server: активация по коду и продление токенов (API /v1), кабинет
  администратора (клиенты, лицензии, установки, журнал, администраторы)
- защита: доверенные IP установок, jail fail2ban api/admin, раздел «Защита»
  с режимом обороны, белым списком и сроками блокировок (root-помощник fw-apply)
- доступ к кабинету: свой адрес вместо /admin, вход только из белого списка,
  второй фактор — TOTP или подтверждение в «ЗЕТИТ Ключ» (push/код)
- deploy/license: unit-файлы, fail2ban, path/timer помощника; контракт API в docs

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
zuevav
2026-09-15 19:41:11 +03:00
parent 586ffb3a31
commit 86aa452ed6
19 changed files with 4659 additions and 99 deletions
+11
View File
@@ -0,0 +1,11 @@
[Unit]
Description=Bridge&Join — команды защиты из кабинета сервера лицензий
[Path]
PathChanged=/var/lib/bj-license/fw-control.json
PathChanged=/var/lib/bj-license/allow-ips.txt
PathChanged=/var/lib/bj-license/trusted-ips.txt
Unit=bj-license-fw.service
[Install]
WantedBy=multi-user.target
+7
View File
@@ -0,0 +1,7 @@
[Unit]
Description=Bridge&Join — применение защиты сервера лицензий (белый список, режим обороны, команды fail2ban)
After=fail2ban.service
[Service]
Type=oneshot
ExecStart=/opt/bj-license/bj-license-server fw-apply -dir /var/lib/bj-license
+11
View File
@@ -0,0 +1,11 @@
[Unit]
Description=Bridge&Join — статус защиты сервера лицензий раз в 30 секунд (и восстановление правил после перезагрузки)
[Timer]
OnBootSec=30s
OnUnitActiveSec=30s
AccuracySec=5s
Unit=bj-license-fw.service
[Install]
WantedBy=timers.target
+22
View File
@@ -0,0 +1,22 @@
[Unit]
Description=Bridge&Join — сервер лицензирования (lic.zetit.ru)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=bj-license
Group=bj-license
ExecStart=/opt/bj-license/bj-license-server serve -addr 127.0.0.1:8091 -data /var/lib/bj-license/state.json -key /etc/bj-license/license.priv -keyid main
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/bj-license
ReadOnlyPaths=/etc/bj-license
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,6 @@
# fail2ban: перебор паролей кабинета сервера лицензий bj
# (строки пишет bj-license-server в журнал systemd; IP клиента берётся из X-Real-IP nginx).
[Definition]
failregex = ^.*login failed: user=".*" ip=<HOST>$
ignoreregex =
journalmatch = _SYSTEMD_UNIT=bj-license-server.service
@@ -0,0 +1,5 @@
# fail2ban: перебор кодов активации и токенов API сервера лицензий bj.
[Definition]
failregex = ^.*api denied: (unknown_code|bad_token) ip=<HOST>$
ignoreregex =
journalmatch = _SYSTEMD_UNIT=bj-license-server.service
@@ -0,0 +1,30 @@
# Сервер лицензий lic.zetit.ru: блокировка IP на уровне файрвола.
# Вход в кабинет: не блокируется только белый список администраторов (раздел «Защита»).
[bj-license-admin]
enabled = true
backend = systemd
filter = bj-license-admin
port = http,https
maxretry = 10
findtime = 10m
bantime = 1h
ignorecommand = /opt/bj-license/bj-license-server fw-ignore -dir /var/lib/bj-license <ip> admin
# API активации и продления: не блокируются адреса установок, успешно активировавших или продливших
# лицензию (trusted-ips.txt), и белый список администраторов (allow-ips.txt).
[bj-license-api]
enabled = true
backend = systemd
filter = bj-license-api
port = http,https
maxretry = 10
findtime = 10m
bantime = 1h
ignorecommand = /opt/bj-license/bj-license-server fw-ignore -dir /var/lib/bj-license <ip> api
[sshd]
enabled = true
maxretry = 5
findtime = 10m
bantime = 1h