package vo // Страница конфигурации показывает ТО, ЧТО НАПИСАНО В ФАЙЛЕ. // // Что было. Панель отдавала браузеру внутреннюю модель серверного конфига // целиком, а frontend накладывал ответ на полный объект значений по умолчанию // (`DeepRequired` + merge). В результате экран отвечал не на вопрос // // что реально написано в /etc/hysteria/config.yaml? // // а на вопрос // // как выглядел бы конфиг, если недостающие куски заполнить дефолтами UI? // // Разница не косметическая. Отсутствующая секция `trafficStats` показывалась // как `:9999`; `speedTest: false` и `disableUDP: false` — валидные явные // значения — считались отсутствующими и прятали свои вкладки; // `ignoreClientBandwidth` (самостоятельная опция верхнего уровня) показывался // только внутри секции bandwidth и при её отсутствии исчезал вместе с ней; // `masquerade.string.statusCode` (число 200..599 у upstream) рисовался // переключателем. То есть экран, существующий ради диагностики расхождений, // эти расхождения скрывал. // // Второе свойство прежнего ответа: он вёз в браузер секреты. `auth` и // `trafficStats.secret` были закрыты `json:"-"`, но пароль обфускации, токены // ACME DNS, учётные данные outbound-прокси и masquerade — нет. Скачиваемый // экспорт того же конфига при этом их вырезает. Читающий экран не имеет права // быть щедрее выгрузки. // // Поэтому ответ описан отдельным типом. Он показывает production-профиль HY2XS // — то, чем реально управляет оркестратор, — и отдельно перечисляет секции, // которых в профиле нет. Полный документ по-прежнему доступен санитизированной // выгрузкой. // // Указатель означает «в файле этого нет». Это единственный способ отличить // отсутствие от значения: `false`, `0` и пустая строка — законные значения. // Hysteria2ProfileVo — конфигурация Hysteria в терминах production-профиля. type Hysteria2ProfileVo struct { Listen *string `json:"listen"` Auth *Hysteria2ProfileAuthVo `json:"auth"` Tls *Hysteria2ProfileTlsVo `json:"tls"` Acme *Hysteria2ProfileAcmeVo `json:"acme"` Obfs *Hysteria2ProfileObfsVo `json:"obfs"` Bandwidth *Hysteria2ProfileBandwidthVo `json:"bandwidth"` IgnoreClientBandwidth *bool `json:"ignoreClientBandwidth"` Congestion *Hysteria2ProfileCongestionVo `json:"congestion"` Quic *Hysteria2ProfileQuicVo `json:"quic"` TrafficStats *Hysteria2ProfileTrafficStatsVo `json:"trafficStats"` // Drift — секции верхнего уровня, которых production-профиль не описывает. // // Считается по СЫРОМУ YAML, а не по типизированной модели: секция, о // которой HY2XS не знает вовсе, обязана быть замечена именно как // расхождение, а не потеряна при разборе. Drift []string `json:"drift"` } // Hysteria2ProfileAuthVo — способ допуска пиров. // // URL показывается санитизированным: это единственный канал допуска, и знать // его порт и путь оператору нужно, а machine token — нет. type Hysteria2ProfileAuthVo struct { Type *string `json:"type"` Url *string `json:"url"` Insecure *bool `json:"insecure"` } type Hysteria2ProfileTlsVo struct { Cert *string `json:"cert"` Key *string `json:"key"` SniGuard *string `json:"sniGuard"` ClientCA *string `json:"clientCA"` } // Hysteria2ProfileAcmeVo — выпуск сертификата. // // DnsConfigKeys перечисляет ИМЕНА параметров DNS-провайдера без значений: сам // факт «токен задан» диагностичен, а значение — это ключ от DNS-зоны. type Hysteria2ProfileAcmeVo struct { Domains []string `json:"domains"` Email *string `json:"email"` Ca *string `json:"ca"` Dir *string `json:"dir"` ListenHost *string `json:"listenHost"` Type *string `json:"type"` DnsProvider *string `json:"dnsProvider"` DnsConfigKeys []string `json:"dnsConfigKeys"` } // Hysteria2ProfileObfsVo — обфускация. // // Пароль не возвращается: он входит в клиентскую ссылку, и оператор получает // его там, где он нужен. Здесь диагностичен только факт, что пароль задан. type Hysteria2ProfileObfsVo struct { Type *string `json:"type"` PasswordSet bool `json:"passwordSet"` MinPacketSize *int `json:"minPacketSize"` MaxPacketSize *int `json:"maxPacketSize"` } type Hysteria2ProfileBandwidthVo struct { Up *string `json:"up"` Down *string `json:"down"` DisableLossCompensation *bool `json:"disableLossCompensation"` } type Hysteria2ProfileCongestionVo struct { Type *string `json:"type"` BbrProfile *string `json:"bbrProfile"` } type Hysteria2ProfileQuicVo struct { InitStreamReceiveWindow *uint64 `json:"initStreamReceiveWindow"` MaxStreamReceiveWindow *uint64 `json:"maxStreamReceiveWindow"` InitConnReceiveWindow *uint64 `json:"initConnReceiveWindow"` MaxConnReceiveWindow *uint64 `json:"maxConnReceiveWindow"` MaxIdleTimeout *string `json:"maxIdleTimeout"` MaxIncomingStreams *int64 `json:"maxIncomingStreams"` DisablePathMTUDiscovery *bool `json:"disablePathMTUDiscovery"` DisableStatelessReset *bool `json:"disableStatelessReset"` } // Hysteria2ProfileTrafficStatsVo — внутренний control plane. // // `listen` показывается ровно так, как записан в файле: именно расхождение // этого адреса с loopback выключает лимит устройств, учёт трафика и // принудительное отключение разом, и увидеть его оператор должен здесь. type Hysteria2ProfileTrafficStatsVo struct { Listen *string `json:"listen"` SecretSet bool `json:"secretSet"` }