diff --git a/apps/controller/config.go b/apps/controller/config.go index 2c1e86b..9397e57 100644 --- a/apps/controller/config.go +++ b/apps/controller/config.go @@ -176,10 +176,6 @@ func GetHysteria2Config(c *gin.Context) { vo.Success(config, c) } -func UpdateHysteria2Config(c *gin.Context) { - vo.Fail("managed by orchestrator: use hy2xs-orchestrator reconfigure", c) -} - // ExportHysteria2Config отдаёт оператору фактический серверный конфиг. // // Экспорт работает от исходного YAML, а не от типизированной модели: поля, @@ -200,10 +196,6 @@ func ExportHysteria2Config(c *gin.Context) { c.Data(200, "application/octet-stream", sanitized) } -func ImportHysteria2Config(c *gin.Context) { - vo.Fail("managed by orchestrator: use hy2xs-orchestrator reconfigure", c) -} - func ExportConfig(c *gin.Context) { configs, err := service.ListConfigNotIn([]string{constant.Hysteria2Config}) if err != nil { @@ -267,20 +259,3 @@ func ImportConfig(c *gin.Context) { }() vo.Success(nil, c) } - -func Hysteria2AcmePath(c *gin.Context) { - hysteria2AcmePathVo, err := service.Hysteria2AcmePath() - if err != nil { - vo.Fail(err.Error(), c) - return - } - vo.Success(hysteria2AcmePathVo, c) -} - -func RestartServer(c *gin.Context) { - vo.Fail("managed by orchestrator: use hy2xs-orchestrator reconfigure", c) -} - -func UploadCertFile(c *gin.Context) { - vo.Fail("managed by orchestrator: use hy2xs-orchestrator reconfigure", c) -} diff --git a/apps/controller/hysteria2.go b/apps/controller/hysteria2.go index 6fe2569..a47184a 100644 --- a/apps/controller/hysteria2.go +++ b/apps/controller/hysteria2.go @@ -32,11 +32,3 @@ func Hysteria2Auth(c *gin.Context) { } vo.Hysteria2AuthSuccess(username, c) } - -func Hysteria2ChangeVersion(c *gin.Context) { - vo.Fail("Смена версии Hysteria2 отключена: runtime управляется install-оркестратором HY2XS", c) -} - -func ListRelease(c *gin.Context) { - vo.Success([]string{}, c) -} diff --git a/apps/frontend/src/api/config/index.ts b/apps/frontend/src/api/config/index.ts index 147c86b..b30f9d2 100644 --- a/apps/frontend/src/api/config/index.ts +++ b/apps/frontend/src/api/config/index.ts @@ -5,10 +5,13 @@ import { ConfigsDto, ConfigUpdateDto, ConfigVo, - Hysteria2AcmePathVo, Hysteria2ServerConfig, } from "@/api/config/types"; +// Серверный конфиг Hysteria доступен панели только на чтение и на выгрузку: +// им владеет install-оркестратор. Клиентов записи, импорта, перезапуска и +// загрузки сертификатов здесь нет — соответствующих маршрутов не существует. + export function getHysteria2ConfigApi(): AxiosPromise { return request({ url: "/config/getHysteria2Config", @@ -16,16 +19,6 @@ export function getHysteria2ConfigApi(): AxiosPromise { }); } -export function updateHysteria2ConfigApi( - data: Hysteria2ServerConfig -): AxiosPromise { - return request({ - url: "/config/updateHysteria2Config", - method: "post", - data: data, - }); -} - export function getConfigApi(data: ConfigDto): AxiosPromise { return request({ url: "/config/getConfig", @@ -77,36 +70,3 @@ export function exportHysteria2ConfigApi(): AxiosPromise { }); } -export function importHysteria2ConfigApi(data: FormData): AxiosPromise { - return request({ - url: "/config/importHysteria2Config", - method: "post", - headers: { - "Content-Type": "multipart/form-data", - }, - data: data, - }); -} - -export function hysteria2AcmePathApi(): AxiosPromise { - return request({ - url: "/config/hysteria2AcmePath", - method: "get", - }); -} - -export function restartServerApi(): AxiosPromise { - return request({ - url: "/config/restartServer", - method: "post", - }); -} - -export function uploadCertFileApi(data: FormData): AxiosPromise { - return request({ - url: "/config/uploadCertFile", - method: "post", - data, - headers: { "Content-Type": "multipart/form-data" }, - }); -} diff --git a/apps/frontend/src/api/config/types.ts b/apps/frontend/src/api/config/types.ts index 22d7c5d..eabd3b7 100644 --- a/apps/frontend/src/api/config/types.ts +++ b/apps/frontend/src/api/config/types.ts @@ -340,8 +340,3 @@ export interface Tab { name: string; desc: string; } - -export interface Hysteria2AcmePathVo { - crtPath: string; - keyPath: string; -} diff --git a/apps/frontend/src/lang/package/en.ts b/apps/frontend/src/lang/package/en.ts index 480d8eb..37a16ec 100644 --- a/apps/frontend/src/lang/package/en.ts +++ b/apps/frontend/src/lang/package/en.ts @@ -185,10 +185,6 @@ export default { hysteria2TrafficTime: "Hysteria2 Traffic Time", huiCrtPath: "HY2XS admin CRT File Path", huiKeyPath: "HY2XS admin KEY File Path", - uploadCrtFile: "Upload CRT File", - uploadKeyFile: "Upload KEY File", - restartServer: "Restart Panel", - restartTip: "Restarting, please refresh", useHysteria2Cert: "Use Hysteria2 cert", huiHttps: "Open https on the panel", resetTrafficCron: "Reset traffic schedule task", @@ -237,7 +233,6 @@ export default { addConfigItem: "Add Config Item", hysteria2Version: "Hysteria2 Version", hysteria2Running: "Hysteria2 Status", - hysteria2ChangeVersion: "Change", addOutbound: "Add Outbound", extension: "Extension", listen: "Listen", diff --git a/apps/frontend/src/lang/package/ru.ts b/apps/frontend/src/lang/package/ru.ts index b66c325..4a8cbc4 100644 --- a/apps/frontend/src/lang/package/ru.ts +++ b/apps/frontend/src/lang/package/ru.ts @@ -181,10 +181,6 @@ export default { hysteria2TrafficTime: "Период учёта трафика Hysteria2", huiCrtPath: "Путь к CRT HY2XS admin", huiKeyPath: "Путь к KEY HY2XS admin", - uploadCrtFile: "Загрузить CRT", - uploadKeyFile: "Загрузить KEY", - restartServer: "Перезапустить панель", - restartTip: "Перезапуск, обновите страницу", useHysteria2Cert: "Использовать сертификат Hysteria2", huiHttps: "Включить HTTPS панели", resetTrafficCron: "Расписание сброса трафика", @@ -233,7 +229,6 @@ export default { addConfigItem: "Добавить параметр", hysteria2Version: "Версия Hysteria2", hysteria2Running: "Статус Hysteria2", - hysteria2ChangeVersion: "Сменить", addOutbound: "Добавить outbound", extension: "Расширение", listen: "Адрес прослушивания", diff --git a/apps/frontend/src/views/config/list/index.vue b/apps/frontend/src/views/config/list/index.vue index 9d39c4f..6c18449 100644 --- a/apps/frontend/src/views/config/list/index.vue +++ b/apps/frontend/src/views/config/list/index.vue @@ -7,14 +7,6 @@ {{ $t("common.save") }} - - - - {{ $t("config.restartServer") }} - - { } }; -const handleRestartServer = async () => { - try { - ElMessageBox.confirm(t("config.restartTip"), t("common.warning"), { - confirmButtonText: t("common.confirm"), - cancelButtonText: t("common.cancel"), - type: "warning", - }).then(() => { - restartServerApi(); - ElMessage.success(t("config.restartTip")); - }); - } catch (e) { - /* empty */ - } -}; - onMounted(() => { setConfig(); if (route.query.focus === "huiHttps") { diff --git a/apps/frontend/src/views/hysteria/list/index.vue b/apps/frontend/src/views/hysteria/list/index.vue index 72638ee..5709652 100644 --- a/apps/frontend/src/views/hysteria/list/index.vue +++ b/apps/frontend/src/views/hysteria/list/index.vue @@ -95,28 +95,9 @@ - - - - - - { @@ -1287,33 +1242,6 @@ const setHysteria2Monitor = async () => { state.hysteria2Monitor.running = data.hysteria.running; }; -const uploadCertFile = async (params: UploadRequestOptions) => { - try { - if (!state.dataForm.tls) { - return; - } - if ( - !params.file.name.endsWith(".crt") && - !params.file.name.endsWith(".key") - ) { - ElMessage.error(t("common.fileFormatUnsupported")); - } - if (params.file.size > 1024 * 1024) { - ElMessage.error(t("common.fileTooLarge")); - } - let formData = new FormData(); - formData.append("file", params.file); - const { data } = await uploadCertFileApi(formData); - if (params.file.name.endsWith(".crt")) { - state.dataForm.tls.cert = data; - } else if (params.file.name.endsWith(".key")) { - state.dataForm.tls.key = data; - } - } catch (e) { - /* empty */ - } -}; - onMounted(() => { setConfig(); setHysteria2Monitor(); diff --git a/apps/model/dto/hysteria2.go b/apps/model/dto/hysteria2.go index 4a16c4e..cb44177 100644 --- a/apps/model/dto/hysteria2.go +++ b/apps/model/dto/hysteria2.go @@ -5,7 +5,3 @@ type Hysteria2AuthDto struct { Auth *string `json:"auth" form:"auth" validate:"required"` Tx *int64 `json:"tx" form:"tx" validate:"required"` } - -type Hysteria2VersionDto struct { - Version *string `json:"version" form:"version" validate:"required,min=1,max=10"` -} diff --git a/apps/model/vo/hysteria2.go b/apps/model/vo/hysteria2.go index 84420e1..2f944b5 100644 --- a/apps/model/vo/hysteria2.go +++ b/apps/model/vo/hysteria2.go @@ -30,13 +30,3 @@ func Hysteria2AuthBadRequest(c *gin.Context) { Id: "", }) } - -type Hysteria2UrlVo struct { - Url string `json:"url"` - QrCode []byte `json:"qrCode"` -} - -type Hysteria2AcmePathVo struct { - CrtPath string `json:"crtPath"` - KeyPath string `json:"keyPath"` -} diff --git a/apps/router/config.go b/apps/router/config.go index 7a8e6e4..a7488ff 100644 --- a/apps/router/config.go +++ b/apps/router/config.go @@ -5,6 +5,11 @@ import ( "hy2xs-admin/controller" ) +// Серверный конфиг Hysteria в HY2XS доступен только на чтение и на выгрузку: +// его владелец — install-оркестратор. Маршруты записи (updateHysteria2Config, +// importHysteria2Config), перезапуска панели и загрузки сертификатов удалены, +// а не оставлены заглушками: маршрут, который всегда отвечает «feature +// disabled», вводит в заблуждение и остаётся точкой входа. func initConfigRouter(configApi *gin.RouterGroup) { config := configApi.Group("/config") { @@ -12,13 +17,8 @@ func initConfigRouter(configApi *gin.RouterGroup) { config.GET("/getConfig", controller.GetConfig) config.POST("/listConfig", controller.ListConfig) config.GET("/getHysteria2Config", controller.GetHysteria2Config) - config.POST("/updateHysteria2Config", controller.UpdateHysteria2Config) config.POST("/exportHysteria2Config", controller.ExportHysteria2Config) - config.POST("/importHysteria2Config", controller.ImportHysteria2Config) config.POST("/exportConfig", controller.ExportConfig) config.POST("/importConfig", controller.ImportConfig) - config.GET("/hysteria2AcmePath", controller.Hysteria2AcmePath) - config.POST("/restartServer", controller.RestartServer) - config.POST("/uploadCertFile", controller.UploadCertFile) } } diff --git a/apps/router/hysteria2.go b/apps/router/hysteria2.go index bfe3abd..b99a6ea 100644 --- a/apps/router/hysteria2.go +++ b/apps/router/hysteria2.go @@ -5,17 +5,13 @@ import ( "hy2xs-admin/controller" ) +// Панель HY2XS не управляет жизненным циклом Hysteria: установка, обновление +// и перезапуск выполняются install-оркестратором. Маршрутов updater'а здесь +// нет намеренно — API-контракт не должен обещать операцию, которой у продукта +// принципиально не существует, и не должен нести лишнюю attack surface. func initHysteria2MachineAuthRouter(hysteria2Api *gin.RouterGroup) { hysteria2 := hysteria2Api.Group("/hysteria2") { hysteria2.POST("/auth", controller.Hysteria2Auth) } } - -func initHysteria2Router(hysteria2Api *gin.RouterGroup) { - hysteria2 := hysteria2Api.Group("/hysteria2") - { - hysteria2.POST("/hysteria2ChangeVersion", controller.Hysteria2ChangeVersion) - hysteria2.GET("/listRelease", controller.ListRelease) - } -} diff --git a/apps/router/router.go b/apps/router/router.go index a81d9b7..6c0efb0 100644 --- a/apps/router/router.go +++ b/apps/router/router.go @@ -65,6 +65,5 @@ func Router(router *gin.Engine, huiWebContext *string) { initDashboardRouter(huiAdminApi) initPeerRouter(huiAdminApi) initConfigRouter(huiAdminApi) - initHysteria2Router(huiAdminApi) initLogRouter(huiAdminApi) } diff --git a/apps/service/config.go b/apps/service/config.go index 5cf0dec..fbcc801 100644 --- a/apps/service/config.go +++ b/apps/service/config.go @@ -10,7 +10,6 @@ import ( "hy2xs-admin/model/constant" "hy2xs-admin/model/entity" "net" - "net/url" "os" "strconv" "strings" @@ -54,62 +53,6 @@ func GetHysteria2Config() (bo.Hysteria2ServerConfig, error) { return serverConfig, nil } -func UpdateHysteria2Config(hysteria2ServerConfig bo.Hysteria2ServerConfig) error { - // Значения по умолчанию - config, err := dao.ListConfig("key in ?", []string{constant.HUIWebPort, constant.Hysteria2TrafficStatsSecret}) - if err != nil { - return err - } - - var hUIWebPort string - var trafficStatsSecret string - for _, item := range config { - if *item.Key == constant.HUIWebPort { - hUIWebPort = *item.Value - } else if *item.Key == constant.Hysteria2TrafficStatsSecret { - trafficStatsSecret = *item.Value - } - } - - if hUIWebPort == "" || trafficStatsSecret == "" { - logrus.Errorf("hUIWebPort or trafficStatsSecret is nil") - return errors.New(constant.SysError) - } - - authHttpUrl, err := GetAuthHttpUrl() - if err != nil { - return err - } - - authType := "http" - authHttpInsecure := true - var auth bo.ServerConfigAuth - auth.Type = &authType - var http bo.ServerConfigAuthHTTP - http.URL = &authHttpUrl - http.Insecure = &authHttpInsecure - auth.HTTP = &http - hysteria2ServerConfig.Auth = &auth - if hysteria2ServerConfig.TrafficStats == nil { - hysteria2ServerConfig.TrafficStats = &bo.ServerConfigTrafficStats{} - } - hysteria2ServerConfig.TrafficStats.Secret = &trafficStatsSecret - - yamlConfig, err := yaml.Marshal(&hysteria2ServerConfig) - if err != nil { - return err - } - return dao.UpdateConfig([]string{constant.Hysteria2Config}, map[string]interface{}{"value": string(yamlConfig)}) -} - -func SetHysteria2Config(hysteria2ServerConfig bo.Hysteria2ServerConfig) error { - config, err := yaml.Marshal(&hysteria2ServerConfig) - if err != nil { - return err - } - return dao.UpdateConfig([]string{constant.Hysteria2Config}, map[string]interface{}{"value": string(config)}) -} - func UpsertConfig(configs []entity.Config) error { return dao.UpsertConfig(configs) } @@ -185,31 +128,3 @@ func GetPortAndCert() (int64, string, string, error) { return portInt, crtPath, keyPath, nil } - -func GetAuthHttpUrl() (string, error) { - port, crtPath, keyPath, err := GetPortAndCert() - if err != nil { - return "", err - } - protocol := "http" - if crtPath != "" && keyPath != "" { - protocol = "https" - } - config, err := dao.GetConfig("key = ?", constant.HUIWebContext) - if err != nil { - return "", err - } - webContext := "" - if config.Value != nil && *config.Value != "/" && strings.HasPrefix(*config.Value, "/") { - webContext = *config.Value - } - trafficSecretConfig, err := dao.GetConfig("key = ?", constant.Hysteria2TrafficStatsSecret) - if err != nil { - return "", err - } - authURL := fmt.Sprintf("%s://127.0.0.1:%d%s/hui/hysteria2/auth", protocol, port, webContext) - if trafficSecretConfig.Value != nil && strings.TrimSpace(*trafficSecretConfig.Value) != "" { - authURL = fmt.Sprintf("%s?access_token=%s", authURL, url.QueryEscape(strings.TrimSpace(*trafficSecretConfig.Value))) - } - return authURL, nil -} diff --git a/apps/service/hysteria2.go b/apps/service/hysteria2.go index 1a09a77..cf20227 100644 --- a/apps/service/hysteria2.go +++ b/apps/service/hysteria2.go @@ -2,14 +2,17 @@ package service import ( "errors" - "fmt" + "github.com/sirupsen/logrus" "hy2xs-admin/dao" "hy2xs-admin/model/constant" - "hy2xs-admin/model/vo" "hy2xs-admin/util" ) +// Жизненный цикл Hysteria принадлежит systemd и install-оркестратору. +// Панель умеет только наблюдать состояние: функций Start/Stop/Restart и +// смены версии здесь нет намеренно, а не «временно отключены». + func InitHysteria2() error { if !util.Exists(util.GetHysteria2BinPath()) { return errors.New("systemd-managed hysteria binary not found") @@ -31,58 +34,6 @@ func Hysteria2IsRunning() bool { return err == nil } -func StartHysteria2() error { - return errors.New("managed by orchestrator: use hy2xs-orchestrator reconfigure") -} - -func StopHysteria2() error { - return errors.New("managed by orchestrator: use hy2xs-orchestrator reconfigure") -} - -func RestartHysteria2() error { - return errors.New("managed by orchestrator: use hy2xs-orchestrator reconfigure") -} - func ReleaseHysteria2() error { return nil } - -func Hysteria2AcmePath() (vo.Hysteria2AcmePathVo, error) { - hysteria2AcmePathVo := vo.Hysteria2AcmePathVo{} - hysteria2Config, err := GetHysteria2Config() - if err != nil { - return hysteria2AcmePathVo, err - } - if hysteria2Config.TLS != nil && - hysteria2Config.TLS.Cert != nil && *hysteria2Config.TLS.Cert != "" && - hysteria2Config.TLS.Key != nil && *hysteria2Config.TLS.Key != "" { - if util.Exists(*hysteria2Config.TLS.Cert) && util.Exists(*hysteria2Config.TLS.Key) { - hysteria2AcmePathVo.CrtPath = *hysteria2Config.TLS.Cert - hysteria2AcmePathVo.KeyPath = *hysteria2Config.TLS.Key - return hysteria2AcmePathVo, nil - } - return hysteria2AcmePathVo, errors.New("cert not found") - } else if hysteria2Config.ACME != nil && - hysteria2Config.ACME.Domains != nil && - len(hysteria2Config.ACME.Domains) > 0 && - hysteria2Config.ACME.CA != nil && - *hysteria2Config.ACME.CA != "" && - hysteria2Config.ACME.Dir != nil && - *hysteria2Config.ACME.Dir != "" { - acmeDir := *hysteria2Config.ACME.Dir - for _, domain := range hysteria2Config.ACME.Domains { - crtPath, err := util.FindFile(acmeDir, fmt.Sprintf("%s.crt", domain)) - if err != nil { - continue - } - keyPath, err := util.FindFile(acmeDir, fmt.Sprintf("%s.key", domain)) - if err != nil { - continue - } - hysteria2AcmePathVo.CrtPath = crtPath - hysteria2AcmePathVo.KeyPath = keyPath - return hysteria2AcmePathVo, nil - } - } - return vo.Hysteria2AcmePathVo{}, errors.New("cert not found") -}