96 lines
5.2 KiB
Markdown
96 lines
5.2 KiB
Markdown
# Архитектура
|
||
|
||
## Границы ответственности
|
||
|
||
Hysteria2 URI содержит переносимые реквизиты: auth, hostname/ports, SNI,
|
||
`insecure`, тип obfs и obfs password. Новые production-установки HY2XS получают
|
||
Gecko URI. Salamander остаётся явно согласуемым compatibility fallback.
|
||
|
||
`policy.json` хранит локальную инфраструктуру: `eth0`, `eth1`, TUN CIDR и MTU,
|
||
route exclusions, таблицу 2022, marks, NFQUEUE, DNS, bandwidth и healthcheck.
|
||
Renderer никогда не патчит старый JSON, а строит полный deterministic config из
|
||
typed model.
|
||
|
||
## Поток применения
|
||
|
||
```text
|
||
URI + policy
|
||
│
|
||
├─ strict validation
|
||
├─ exact 1.14.0 + build-tag gate
|
||
├─ renderer_1_14_0
|
||
└─ sing-box check на private candidate
|
||
│
|
||
current отсутствует ── current существует
|
||
│ │
|
||
│ provenance gate
|
||
│ │
|
||
│ unchanged ───── changed
|
||
│ │ │
|
||
│ ▼ ├─ versioned last-good backup
|
||
│ state.json │
|
||
└────────────────────────────────┼─ atomic replace
|
||
├─ systemctl restart
|
||
└─ bounded healthcheck
|
||
```
|
||
|
||
Первое применение после чистой установки не создаёт `last-good`: предыдущего
|
||
управляемого конфига нет. При следующих изменениях backup разрешён только если
|
||
SHA установленного config совпадает со state этого же релиза и sing-box 1.14.0.
|
||
Побайтовое совпадение с candidate не доказывает ownership: существующий config
|
||
без такого state отклоняется и не «усыновляется» контроллером.
|
||
|
||
## Gecko и DNS
|
||
|
||
Renderer добавляет для Gecko `min_packet_size=512` и
|
||
`max_packet_size=1200`. Эти параметры являются частью локального HY2XS
|
||
compatibility profile и не читаются из URI.
|
||
|
||
Renderer явно задаёт штатный для sing-box 1.14.0 `dns_mode=hijack`. Поле
|
||
`dns_address` не задаётся: sing-box выводит IPv4 DNS address `172.19.0.2` как
|
||
следующий адрес после `172.19.0.1/30`, автоматически связывает его с DNS module
|
||
и при `auto_redirect=true` устанавливает nftables DNAT для TCP/UDP 53. Поэтому
|
||
отдельного route action `hijack-dns` в generated config нет.
|
||
|
||
Bootstrap UDP DNS привязан к `eth0`; remote DoH использует detour `hy2-out`.
|
||
Собственный outbound sing-box исключается из auto-redirect по output mark, что
|
||
необходимо подтвердить privileged Linux acceptance без bootstrap recursion.
|
||
|
||
Platform hijack не создаёт DNS listener на локальном LAN-адресе шлюза: трафик к
|
||
такому адресу попадает в kernel `local` table раньше пользовательских rules.
|
||
Если DHCP должен выдавать сам gateway как DNS server, требуется отдельный
|
||
listener/service, который не входит в контракт 0.2.0.
|
||
|
||
## Endpoint routing
|
||
|
||
Hysteria outbound хранит hostname и `bind_interface=eth0`, а его
|
||
`domain_resolver` указывает на bootstrap DNS через `eth0`. Публичный IP сервера
|
||
не добавляется в `route_exclude_address`; смена A-записи не требует изменения
|
||
policy.
|
||
|
||
## Файловая модель
|
||
|
||
```text
|
||
/etc/vpn-egress/ root:root 0700
|
||
├── policy.json root:root 0600
|
||
└── hysteria2.uri root:root 0600
|
||
|
||
/var/lib/vpn-egress/ root:root 0700
|
||
├── state.json без секретов, 0600
|
||
├── last-good.json содержит secrets, 0600
|
||
├── last-good.meta.json версия и SHA-256, 0600
|
||
└── backups/ config + соседний .meta, 0700/0600
|
||
|
||
/etc/sing-box/config.json root:root 0600
|
||
```
|
||
|
||
Metadata не обеспечивает доверие от root-компрометации. Её задача — исключить
|
||
случайное смешивание релизов и повреждённых backup-файлов.
|
||
|
||
## Граница установки
|
||
|
||
0.2.0 не содержит кода миграции 0.1.0. `debian/preinst` отклоняет установку
|
||
поверх любого другого релиза, а `postinst` отклоняет legacy policy/state или
|
||
unmanaged `/etc/sing-box/config.json`. Same-release reinstall 0.2.0 допускается,
|
||
если state и config согласованы.
|