fix(admin): считать достижимым только тот адрес Traffic Stats API, который админка действительно опрашивает
Проверка принимала любой ip.IsLoopback(), то есть считала рабочим и 127.0.0.5. Это неверно: слушатель на конкретном адресе принимает соединения только на него, а слой proxy обращается строго к http://127.0.0.1:<port>. bind 127.0.0.5:38712 -> dial 127.0.0.1:38712 -> connection refused bind 0.0.0.0:38713 -> dial 127.0.0.1:38713 -> connected Такой адрес выглядел локальным, ломал контур доступа целиком (лимит устройств fail-closed => не подключается никто) и не вызывал у админки ни одного возражения. Принимаются ровно 127.0.0.1, 0.0.0.0 и пустой хост. IPv6-wildcard не принимается сознательно: соединение он принял бы, но HY2XS объявлен IPv4-only, а зависеть в ответе «достучусь» от net.ipv6.bindv6only нельзя. На странице конфигурации мягкое состояние nonCanonicalLoopback убрано: прочий loopback — это ошибка, а не предупреждение. Осталось три состояния: канон профиля, wildcard, недостижим. Свойство закреплено тестом с настоящими сокетами, а гейт приёмки запрещает возврат IsLoopback() и требует негативного случая 127.0.0.5 в тестах.
This commit is contained in:
@@ -2051,6 +2051,37 @@ run_access_revocation_acceptance() {
|
||||
# прочитанного адреса, а называет расхождение.
|
||||
code_has apps/service/config.go -F -- 'func assertTrafficStatsHostReachable' \
|
||||
|| fail "acceptance: the admin backend accepts any Traffic Stats host silently"
|
||||
# Проверяется СЕМАНТИКА, а не наличие функции.
|
||||
#
|
||||
# Первая версия принимала любой `ip.IsLoopback()`, и это неверно: слушатель на
|
||||
# конкретном адресе принимает соединения только на него, поэтому
|
||||
# `bind 127.0.0.5:36712` + `dial 127.0.0.1:36712` даёт connection refused.
|
||||
# Такой адрес выглядит «локальным», а control plane при нём уже не работает —
|
||||
# то есть отказ авторизации всем пирам без единой подсказки о причине.
|
||||
! code_has apps/service/config.go -F -- 'IsLoopback()' \
|
||||
|| fail "acceptance: the Traffic Stats host check is back to any loopback address"
|
||||
"$BUN_BIN" -e '
|
||||
const source = require("node:fs").readFileSync("apps/service/config.go", "utf8");
|
||||
const start = source.indexOf("func assertTrafficStatsHostReachable");
|
||||
if (start < 0) throw new Error("assertTrafficStatsHostReachable is missing");
|
||||
const rest = source.slice(start + 1);
|
||||
const end = rest.indexOf("\nfunc ");
|
||||
const body = (end < 0 ? rest : rest.slice(0, end))
|
||||
.split("\n")
|
||||
.filter((line) => !/^\s*\/\//.test(line))
|
||||
.join("\n");
|
||||
// Принимается ровно три формы: канон, IPv4-wildcard и пустой хост (тот же
|
||||
// wildcard). Всё остальное, включая прочие адреса loopback, недостижимо.
|
||||
for (const accepted of [`"127.0.0.1"`, `"0.0.0.0"`]) {
|
||||
if (!body.includes(accepted)) {
|
||||
throw new Error("the reachable host " + accepted + " is no longer accepted explicitly");
|
||||
}
|
||||
}
|
||||
' || fail "acceptance: the Traffic Stats host must be matched exactly"
|
||||
# Негативный случай закреплён тестом: без него правило выглядит произвольным
|
||||
# ужесточением, и следующий читатель вернёт IsLoopback обратно.
|
||||
code_has apps/service/config_traffic_stats_test.go -F -- '127.0.0.5' \
|
||||
|| fail "acceptance: the unreachable loopback address is not pinned by a test"
|
||||
|
||||
log_step "Acceptance: the systemd state has three values, not two"
|
||||
# util.Exec выбрасывает вывод при ненулевом коде, а `systemctl is-active`
|
||||
|
||||
Reference in New Issue
Block a user