- DOCS/Operations: current-state SUMMARY of the ENTRY deployment (access, install, egress via Hysteria2, security findings and fixes, risk assessment, commits/backups, open items), the Hysteria chain manifest with an OpenVPN Monitor section, reboot test results, and the plan and rollout records for settings validation and privilege separation. - Link them from README and DOCS/General/Index.md. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
7.3 KiB
План: валидация настроек (п.1) и запуск API не от root (п.2)
Дата: 2026-09-30. Узел: 213.226.125.13 (Alpine, OpenRC). Приложение: /opt/OpenVPN-Monitoring-Simple.
Основание: SUMMARY-ovpn-monitor.md, раздел 6.5 — администратор панели фактически равен root, т.к. Profiler работает от root, а настройки без проверки попадают в server.conf.
Исходные факты
APP_CORE(API, gatherer) root не нужен: читаетopenvpn-status.log, пишет свою SQLite-БД и лог.- Profiler требует root только для: записи
/etc/openvpn/server.conf,rc-service openvpn, чтения PKI-файлов самим OpenVPN. - В коде уже есть fallback
staging/server.conf. - В шаблоне
script-security 2стоит внутри{% if user_defined_cdscripts %}. doasустановлен; конфигурация толькоpermit nopass :wheel.
Пункт 1. Валидация настроек (3 слоя)
Слой A. Схемы (APP_PROFILER/schemas.py) — валидаторы только на *Update-схемах (старые значения из БД не ломают GET).
| Поле | Правило |
|---|---|
port, management_port |
1–65535 |
vpn_network, vpn_netmask |
ipaddress: сеть и корректная маска |
split_routes[] |
CIDR или «сеть маска», нормализация через ipaddress |
dns_servers[] |
IPv4/IPv6 через ipaddress |
public_ip |
IP или hostname по маске, без пробелов и кавычек |
management_interface_address |
только loopback |
tun_mtu / mssfix |
576–9000 / 536–1500 |
connect_script, disconnect_script |
пусто или ^/etc/openvpn/scripts/[A-Za-z0-9_.-]{1,64}$ |
PKI fqdn_ca, fqdn_server |
маска как у username |
PKI easyrsa_dn |
cn_only или org |
PKI req_country |
^[A-Z]{2}$ |
PKI req_province/city/org/ou |
^[A-Za-z0-9 .,_-]{0,64}$ |
PKI req_email |
простая маска email |
PKI key_size |
2048 / 3072 / 4096 |
| PKI сроки | целые в разумных пределах |
Слой B. Скрипты (routers/server.py, до генерации): realpath внутри /etc/openvpn/scripts/, файл существует, владелец root, нет прав записи для group/other.
Слой C. Генератор (services/generator.py): перед записью проверить, что ни одно значение не содержит \n, \r, ", \; иначе ошибка и файл не пишется.
Тесты: невалидные значения (перевод строки в DNS, ../ в скрипте, / в организации, порт 0) → 422; валидный набор → 200 и корректный server.conf.
Пункт 2. Profiler и API не от root
Схема: пользователь ovpmon + маленький root-помощник, сам валидирующий конфиг (защита в глубину: инъекция в конфиг не даёт root даже при обходе слоёв A–C).
- Пользователь и права. Системный
ovpmon. Владелец:/var/lib/ovpmon,/var/log/ovpmon,APP_PROFILER/{easy-rsa,client-config,staging,*.db,profiler.log},APP_CORE/{*.db,*.log}.pki/: каталоги 755,crl.pem644, приватные ключи 600. Код иvenvостаются root-owned./etc/ovpmon/envостаётся root 600. - OpenRC:
command_user="ovpmon:ovpmon"вovpmon-*. - Помощник
/usr/local/sbin/ovpmon-helper(root, 755, Python). Подкоманды без пользовательских аргументов:install-config: читает только/var/lib/ovpmon/staging/server.conf(один раз в память, защита от TOCTOU), проверяет allowlist директив (запрещеныup,down,plugin,route-up,tls-verify,auth-user-pass-verify,learn-address, неизвестные;client-connect/disconnectиscript-security— только со скриптом из/etc/openvpn/scripts/с проверкой владельца и прав), пишет/etc/openvpn/server.confатомарно (root:root 644).service start|stop|restart|statusтолько дляopenvpn.
doas:/etc/doas.d/ovpmon.conf, точныеargsдля каждой подкоманды.- Код Profiler: на хосте
services/process.pyиrouters/server.pyвызываютdoas ovpmon-helper …; ветка контейнера иstagingне меняются. APP_CORE: только смена владельца иcommand_user.- Каталог скриптов:
/etc/openvpn/scripts/root:root 755, по умолчанию пустой.
Порядок
- Бэкап
/etc/openvpn, БД,/etc/init.d/ovpmon-*, код,easy-rsa/. - Слои A–C + тесты, перезапуск Profiler.
- Пользователь,
chown, помощник,doas; ручная проверка помощника. - Переключить
process.pyиserver.pyна помощник. - Переключить init-скрипты на
command_user, перезапускать по одному. - Обновить документацию и SUMMARY, отдельные коммиты.
Проверка (п.2)
ps: Profiler и API подovpmon.- От
ovpmon: нет доступа к/etc/shadow,/root,/etc/hysteria/*.yaml, запись в/etc/openvpnзапрещена. - UI: Initialize PKI, генерация и запись конфига, Start/Stop/Restart OpenVPN, создание/скачивание/отзыв профиля, мониторинг.
- Инъекция директивы в
staging/server.confотвергается помощником,/etc/openvpn/server.confне меняется. - Прямые вызовы
doasс другими аргументами отклоняются. - OpenVPN-клиент подключается и выходит через hel.
- Не сломаны fail2ban, HTTPS 8088,
ip rule 102.
Риски
| Риск | Смягчение |
|---|---|
| Сервис не стартует из-за прав | бэкап, chown до переключения, откат правкой init-скриптов |
| Allowlist блокирует легальный конфиг | первый прогон в режиме проверки без записи; список директив из server.conf.j2 |
Ошибка в doas args |
негативные тесты от ovpmon, запасная root-SSH-сессия |
| Потеря ключей PKI | копия easy-rsa/ перед chown |
Статус
- Пункт 1 — реализован (2026-09-30), см. SUMMARY раздел 6.6 и DOCS/Changes/2026-09-30_Settings_Validation.md.
- Пункт 2 — реализован (2026-09-30), см. IMPLEMENTATION-02-privilege-separation.md и DOCS/Changes/2026-09-30_Privilege_Separation.md.