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:
@@ -563,16 +563,22 @@ describe("страница конфигурации Hysteria", () => {
|
||||
// интерфейсы, а не loopback.
|
||||
expect(source).toMatch(/host === "" \|\| host === "0\.0\.0\.0"/);
|
||||
|
||||
for (const state of ["canonical", "wildcard", "nonCanonicalLoopback", "unreachable"]) {
|
||||
for (const state of ["canonical", "wildcard", "unreachable"]) {
|
||||
expect(source).toContain(state);
|
||||
}
|
||||
|
||||
// Три разные новости — три разные фразы, и ни одна не потеряна в словарях.
|
||||
// Прочие адреса loopback — это НЕ «слегка не тот адрес», а
|
||||
// недостижимость: слушатель на конкретном адресе принимает соединения
|
||||
// только на него, поэтому bind 127.0.0.5 + dial 127.0.0.1 даёт connection
|
||||
// refused. Отдельного мягкого состояния для них быть не должно.
|
||||
expect(source).not.toContain("nonCanonicalLoopback");
|
||||
expect(source).not.toMatch(/127\\\.\\d/);
|
||||
|
||||
// Две разные новости — две разные фразы, и ни одна не потеряна в словарях.
|
||||
for (const dictionary of [ru, en] as const) {
|
||||
const hysteria = (dictionary as any).hysteria ?? {};
|
||||
expect(typeof hysteria.trafficStatsUnreachable).toBe("string");
|
||||
expect(typeof hysteria.trafficStatsWildcard).toBe("string");
|
||||
expect(typeof hysteria.trafficStatsNonCanonical).toBe("string");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user