release: prepare 0.2.0 for sing-box 1.14
This commit is contained in:
@@ -1,83 +1,87 @@
|
||||
# singbox_glue / vpn-egressctl
|
||||
|
||||
`vpn-egressctl` — локальный декларативный control plane для шлюза `vpn-egress-gw`.
|
||||
Он получает реквизиты подключения из защищённого Hysteria2 URI, объединяет их с
|
||||
локальной инфраструктурной политикой и полностью генерирует конфигурацию
|
||||
sing-box.
|
||||
`vpn-egressctl` — локальный декларативный control plane для Linux-шлюза
|
||||
`vpn-egress-gw`. Он получает реквизиты подключения из защищённого Hysteria2 URI,
|
||||
объединяет их с локальной инфраструктурной policy и полностью генерирует
|
||||
конфигурацию sing-box.
|
||||
|
||||
Проект намеренно поддерживает только **sing-box 1.13.19**. Версии 1.13.12,
|
||||
другие patch-релизы и вся ветка 1.14 отклоняются до изменения файлов.
|
||||
## Контракт релиза 0.2.0
|
||||
|
||||
## Что решает проект
|
||||
- строго `sing-box 1.14.0`, Linux build с `with_quic` и `with_gvisor`;
|
||||
- HY2XS/Hysteria 2.12.2 использует Gecko как единственный production obfs;
|
||||
- Gecko packet profile фиксирован: `512/1200`;
|
||||
- Salamander принимается только как явно заданный compatibility fallback;
|
||||
- TUN DNS сохраняет прежнюю архитектуру через `dns_mode=disabled` и явное
|
||||
route action `hijack-dns`;
|
||||
- лицензия исходного кода — Mozilla Public License 2.0.
|
||||
|
||||
- IP Hysteria2-сервера отсутствует в `route_exclude_address` и nftables policy.
|
||||
- Смена DNS A-записи не требует перегенерации конфигурации.
|
||||
- Смена credential выполняется одной безопасной командой через stdin.
|
||||
- Перед установкой candidate проверяется реальным `sing-box check`.
|
||||
- Запись атомарна; после неуспешного restart/healthcheck выполняется rollback.
|
||||
- Policy, URI, production config, state и backups имеют `root:root 0600`,
|
||||
защищённые каталоги — `root:root 0700`.
|
||||
- Неизвестные URI/policy-параметры отклоняются, а не игнорируются.
|
||||
- systemd следит за desired state без постоянно работающего Python-процесса.
|
||||
- Отдельный nftables guard блокирует прямой forwarding `eth1 -> eth0`.
|
||||
- `sing-box.service` требует успешного запуска guard через package-managed drop-in.
|
||||
Salamander не является автоматическим fallback: клиент не может согласовать тип
|
||||
obfs с сервером. Production URI HY2XS обязан содержать `obfs=gecko`.
|
||||
|
||||
## Источники состояния
|
||||
## Что обеспечивает проект
|
||||
|
||||
```text
|
||||
/etc/vpn-egress/policy.json
|
||||
/etc/vpn-egress/hysteria2.uri
|
||||
│
|
||||
▼
|
||||
renderer 1.13.19
|
||||
│
|
||||
▼
|
||||
/etc/sing-box/config.json
|
||||
```
|
||||
- endpoint остаётся DNS hostname и не закрепляется как публичный `/32`;
|
||||
- bootstrap DNS привязан к `eth0`, remote DoH идёт через `hy2-out`;
|
||||
- неизвестные URI и policy-параметры отклоняются;
|
||||
- candidate проходит настоящий `sing-box check` до установки;
|
||||
- запись атомарна, после неуспешного restart/healthcheck выполняется
|
||||
same-release rollback;
|
||||
- legacy `last-good` без версии и checksum не используется;
|
||||
- nftables guard блокирует прямой forwarding `eth1 -> eth0`;
|
||||
- systemd path unit применяет изменение URI без постоянного Python-процесса.
|
||||
|
||||
`/etc/sing-box/config.json` является генерируемым артефактом. Редактировать его
|
||||
вручную после миграции нельзя.
|
||||
## Только чистая установка
|
||||
|
||||
Переход с 0.1.0 на 0.2.0 через `apt upgrade` или `dpkg -i` поверх старого пакета
|
||||
не поддерживается и блокируется `preinst`. Старые policy, config, state и backups
|
||||
не мигрируют и не активируются.
|
||||
|
||||
Правильная последовательность: остановить сервисы, оставить anti-leak guard,
|
||||
удалить пакет 0.1.0, архивировать его данные, установить sing-box 1.14.0 и пакет
|
||||
0.2.0, настроить новую policy и применить новый Gecko URI. Полный runbook:
|
||||
[чистая установка](docs/migration.md).
|
||||
|
||||
## Основные команды
|
||||
|
||||
```bash
|
||||
# URI не попадает в argv и shell history.
|
||||
sudo vpn-egressctl import --stdin
|
||||
|
||||
sudo vpn-egressctl check
|
||||
sudo vpn-egressctl diff
|
||||
sudo vpn-egressctl sync
|
||||
sudo vpn-egressctl status
|
||||
sudo vpn-egressctl status --json
|
||||
sudo vpn-egressctl doctor
|
||||
sudo vpn-egressctl rollback
|
||||
```
|
||||
|
||||
Позиционный `vpn-egressctl import 'hysteria2://...'` запрещён специально.
|
||||
URI нельзя передавать позиционным аргументом: secret не должен попадать в argv и
|
||||
shell history.
|
||||
|
||||
## Документация
|
||||
|
||||
- [Архитектура](docs/architecture.md)
|
||||
- [Конфигурация](docs/configuration.md)
|
||||
- [Установка и миграция](docs/migration.md)
|
||||
- [Чистая установка 0.2.0](docs/migration.md)
|
||||
- [Эксплуатация](docs/operations.md)
|
||||
- [Безопасность](docs/security.md)
|
||||
- [Диагностика](docs/troubleshooting.md)
|
||||
- [Контракт sing-box 1.14.0](docs/sing-box-1.14.md)
|
||||
- [Тестирование](docs/testing.md)
|
||||
- [Почему не поддерживается 1.14](docs/sing-box-1.14.md)
|
||||
- [Диагностика](docs/troubleshooting.md)
|
||||
|
||||
## Локальная проверка
|
||||
|
||||
Проект не имеет runtime-зависимостей вне Python stdlib.
|
||||
На Linux:
|
||||
|
||||
```powershell
|
||||
E:\python-31312\python.exe -m compileall -q src tests
|
||||
```bash
|
||||
make check
|
||||
```
|
||||
|
||||
Изолированная Windows-сборка Python в указанном каталоге не добавляет cwd в
|
||||
`sys.path`, поэтому полный тестовый запуск выполняется так:
|
||||
Указанный embedded Python для Windows работает в isolated mode, поэтому пути
|
||||
добавляются явно:
|
||||
|
||||
```powershell
|
||||
E:\python-31312\python.exe -c "import sys,unittest; sys.path[:0]=[r'F:\projects\singbox_glue\src',r'F:\projects\singbox_glue']; s=unittest.defaultTestLoader.discover(r'F:\projects\singbox_glue\tests'); r=unittest.TextTestRunner(verbosity=2).run(s); raise SystemExit(not r.wasSuccessful())"
|
||||
E:\python-31312\python.exe -c "import sys,unittest; sys.path[:0]=[r'F:\projects\singbox_glue',r'F:\projects\singbox_glue\src']; s=unittest.defaultTestLoader.discover('tests',top_level_dir='.'); r=unittest.TextTestRunner(verbosity=2).run(s); raise SystemExit(not r.wasSuccessful())"
|
||||
```
|
||||
|
||||
На Linux достаточно `make check`.
|
||||
## Лицензия
|
||||
|
||||
Версия 0.2.0 распространяется по [Mozilla Public License 2.0](LICENSE).
|
||||
|
||||
Reference in New Issue
Block a user