fix(admin): различать достижимость Traffic Stats API и соответствие профилю
Признак на странице конфигурации отвечал только на вопрос «достучится ли админка», поэтому 0.0.0.0 показывался как норма — хотя внутренний control plane при нём опубликован на всех интерфейсах, а оркестратор такой конфигурации не создаёт. Состояний теперь четыре: канон профиля, wildcard, не-канонический loopback и недостижимый адрес. Backend не тронут: он по-прежнему отвечает только на вопрос достижимости — превращать лишнюю публикацию в отказ обслуживания значило бы отключить всех пиров. Исправлено ложное утверждение в его комментарии: пустой хост `:36712` в Go означает все интерфейсы, а не loopback. Удалены мёртвые фразы common.wait/enableSuccess/disableSuccess — остатки операций запуска, остановки и смены версии Hysteria, которых у панели нет.
This commit is contained in:
@@ -32,6 +32,7 @@ rc3](2026-09-02-v1.0.0-rc3-preflight-findings.md) и сверка Hysteria-ин
|
||||
| ADM-HY2-08 | Мёртвые остатки прежней архитектуры | P4 | закрыт |
|
||||
| GATE-03 | Гейт освобождения admission-замка проверял форму, а не замок | P3 | закрыт |
|
||||
| DOC-03 | Отчёт rc3 не называл, к какому дереву относятся выводы | P3 | закрыт |
|
||||
| DIAG-01 | Панель считала wildcard нормальным состоянием control plane | P3 | закрыт |
|
||||
|
||||
ROT-01 и ADM-HY2-01…08 пришли внешним разбором; уточнения ниже — при проверке
|
||||
его выводов по коду и исходникам upstream. Три из них меняли предложенное
|
||||
@@ -149,6 +150,43 @@ LAN, публичный адрес), `apps/service/config_traffic_stats_test.go`
|
||||
|
||||
---
|
||||
|
||||
## DIAG-01 — панель считала wildcard нормальным состоянием control plane
|
||||
|
||||
Найдено при перепроверке фикса ADM-HY2-01 и относится только к диагностике: на
|
||||
data plane не влияет.
|
||||
|
||||
Первая версия признака на странице конфигурации отвечала на вопрос
|
||||
«достучится ли админка» и молчала по второму, не менее важному, — «тот ли это
|
||||
адрес, который создаёт оркестратор»:
|
||||
|
||||
```ts
|
||||
host === "" || host === "127.0.0.1" || host === "0.0.0.0"
|
||||
```
|
||||
|
||||
`0.0.0.0` — не loopback, а wildcard: внутренний control plane при нём
|
||||
опубликован на всех интерфейсах, и при `HY2XS_FIREWALL_MODE=external|off` его не
|
||||
прикрывает ничто. Оркестратор такой конфигурации не создаёт, значит она
|
||||
появилась правкой руками — и диагностический экран обязан это назвать, а не
|
||||
показывать как норму. Официальная документация Traffic Stats API отдельно
|
||||
предупреждает об ограничении доступа к этому listener'у.
|
||||
|
||||
Там же обнаружилась вторая неточность, уже в моей формулировке: **пустой хост
|
||||
(`:36712`) — тоже wildcard, а не loopback.** В Go `:port` означает все
|
||||
интерфейсы; комментарий в `parseTrafficStatsPort` утверждал обратное. На
|
||||
поведение это не влияло (wildcard включает loopback, поэтому обмен состоится),
|
||||
но описание контракта было ложным и исправлено.
|
||||
|
||||
**Как закрыто.** Backend не тронут: он по-прежнему отвечает ровно на вопрос
|
||||
достижимости, и превращать лишнюю публикацию в отказ обслуживания нельзя — это
|
||||
отключило бы всех пиров. Разделены понятия на стороне панели:
|
||||
|
||||
| адрес | состояние | что показано |
|
||||
| --- | --- | --- |
|
||||
| `127.0.0.1` | `canonical` | без пометки |
|
||||
| `0.0.0.0`, пустой хост | `wildcard` | предупреждение: API доступен, но слушает все интерфейсы |
|
||||
| `127.0.0.x` | `nonCanonicalLoopback` | предупреждение: доступен, но оркестратор такого не создаёт |
|
||||
| прочее | `unreachable` | ошибка: доступ пиров уже не работает |
|
||||
|
||||
## ADM-HY2-02 — JSON-журнал не разбирался ни одной строкой
|
||||
|
||||
Юнит запускает Hysteria с `HYSTERIA_LOG_FORMAT=json`. Разбор складывал запись
|
||||
@@ -370,4 +408,7 @@ go test -race ./service/... -count=1
|
||||
6. открыть страницу журнала Hysteria: записи разобраны, контекст виден,
|
||||
секретов нет;
|
||||
7. добавить в конфиг секцию вне профиля (например `resolver`) и открыть страницу
|
||||
конфигурации: секция обязана попасть в «расхождение конфигурации».
|
||||
конфигурации: секция обязана попасть в «расхождение конфигурации»;
|
||||
8. заменить `trafficStats.listen` на `0.0.0.0:36712`: продукт продолжает
|
||||
работать, а страница конфигурации показывает предупреждение о публикации на
|
||||
всех интерфейсах.
|
||||
|
||||
@@ -378,7 +378,18 @@ trafficStats.listen слушает 192.168.1.10, а админка обраща
|
||||
API только по loopback. ...Верните 127.0.0.1 через `hy2xs-orchestrator reconfigure`
|
||||
```
|
||||
|
||||
Страница конфигурации показывает тот же адрес и помечает его как не-loopback.
|
||||
Страница конфигурации показывает тот же адрес и называет его состояние. Ответов
|
||||
три, и они означают разное:
|
||||
|
||||
| адрес | что показано | что это значит |
|
||||
| --- | --- | --- |
|
||||
| `127.0.0.1:36712` | без пометки | канон production-профиля |
|
||||
| `0.0.0.0:36712`, `:36712` | предупреждение | API достижим, но опубликован на всех интерфейсах; при `HY2XS_FIREWALL_MODE=external\|off` его не прикрывает ничто |
|
||||
| `127.0.0.5:36712` | предупреждение | достижим, но оркестратор такого не создаёт — конфиг правили руками |
|
||||
| `192.168.1.10:36712` | ошибка | панель до него не достучится, доступ пиров уже не работает |
|
||||
|
||||
Пустой хост в `listen` — это не loopback: в Go `:36712` означает все интерфейсы,
|
||||
ровно как `0.0.0.0`.
|
||||
|
||||
### Дашборд показывает «состояние службы неизвестно»
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
27. живая сессия, которой в базе больше ничего не соответствует (пир удалён либо его `auth_id` заменён импортом, а разрыв в тот момент не удался), завершается очередным циклом учёта — не позднее 30 секунд
|
||||
28. превышение `maxDevices` живыми сессиями устраняется тем же циклом: после неудавшегося разрыва при снижении лимита повтор формы даёт успех без `/kick`, и единственный механизм схождения здесь — cron
|
||||
29. смена секрета пира меняет его `auth_id`: клиент со старым секретом теряет доступ не позднее 30 секунд даже в том случае, когда `/kick` прошёл успешно, а соединение зарегистрировалось после него
|
||||
30. `trafficStats.listen` слушает `127.0.0.1`; конфиг с не-loopback адресом админка отвергает с явным сообщением, а не молча ходит на loopback
|
||||
30. `trafficStats.listen` слушает `127.0.0.1`; конфиг с не-loopback адресом админка отвергает с явным сообщением, а не молча ходит на loopback. Страница конфигурации различает три состояния адреса: канон профиля, достижимый но опубликованный шире необходимого (`0.0.0.0`, пустой хост, прочий loopback) и недостижимый
|
||||
31. `hysteria-server.service` запущен с `HYSTERIA_DISABLE_UPDATE_CHECK=1`: внешних запросов проверки версии при старте нет
|
||||
32. дашборд различает «служба остановлена» и «состояние службы неизвестно»; доступность Traffic Stats API показывается независимо от ответа systemd
|
||||
33. страница журнала Hysteria показывает разобранные `level`/`time`/`msg` и структурный контекст, а не сырой JSON
|
||||
|
||||
Reference in New Issue
Block a user