fix(fix3): runtime env hardening and public endpoint source-of-truth

This commit is contained in:
2026-04-28 04:45:43 +05:00
parent 96d9bbcece
commit 12c65c8e31
23 changed files with 131 additions and 238 deletions
+27 -26
View File
@@ -8,26 +8,27 @@ import (
"hy2xs-admin/model/bo"
"hy2xs-admin/model/constant"
"hy2xs-admin/proxy"
"net"
"net/url"
"os"
"strconv"
"strings"
"time"
)
func parseListenPort(listen string) (int, error) {
host, port, err := net.SplitHostPort(listen)
if err != nil {
return 0, err
func resolvePublicEndpoint() (string, int, error) {
host := strings.TrimSpace(os.Getenv("HY2XS_PUBLIC_HOST"))
if host == "" || host == "0.0.0.0" {
return "", 0, errors.New("HY2XS_PUBLIC_HOST must be set to public domain or IPv4")
}
if host == "" || port == "" {
return 0, errors.New("invalid listen address")
portRaw := strings.TrimSpace(os.Getenv("HY2XS_PUBLIC_PORT"))
if portRaw == "" {
return "", 0, errors.New("HY2XS_PUBLIC_PORT is required")
}
value, convErr := strconv.Atoi(port)
if convErr != nil || value < 1 || value > 65535 {
return 0, errors.New("invalid listen port")
port, err := strconv.Atoi(portRaw)
if err != nil || port < 1 || port > 65535 {
return "", 0, errors.New("HY2XS_PUBLIC_PORT must be a valid TCP port")
}
return value, nil
return host, port, nil
}
func Hysteria2Auth(conPass string) (int64, string, error) {
@@ -103,11 +104,15 @@ func Hysteria2Kick(ids []int64, kickUtilTime int64) error {
return nil
}
func Hysteria2SubscribeUrl(accountId int64, protocol string, host string) (string, error) {
func Hysteria2SubscribeUrl(accountId int64, protocol string) (string, error) {
account, err := dao.GetAccount("id = ?", accountId)
if err != nil {
return "", err
}
publicHost, publicPort, err := resolvePublicEndpoint()
if err != nil {
return "", err
}
config, err := dao.GetConfig("key = ?", constant.HUIWebContext)
if err != nil {
return "", err
@@ -116,10 +121,10 @@ func Hysteria2SubscribeUrl(accountId int64, protocol string, host string) (strin
if config.Value != nil && *config.Value != "/" && strings.HasPrefix(*config.Value, "/") {
webContext = *config.Value
}
return fmt.Sprintf("%s//%s%s/hui/%s", protocol, host, webContext, url.QueryEscape(*account.ConPass)), nil
return fmt.Sprintf("%s//%s:%d%s/hui/%s", protocol, publicHost, publicPort, webContext, url.QueryEscape(*account.ConPass)), nil
}
func Hysteria2Subscribe(conPass string, clientType string, host string) (string, string, error) {
func Hysteria2Subscribe(conPass string, clientType string) (string, string, error) {
hysteria2Config, err := GetHysteria2Config()
if err != nil {
return "", "", err
@@ -132,6 +137,10 @@ func Hysteria2Subscribe(conPass string, clientType string, host string) (string,
if err != nil {
return "", "", err
}
publicHost, publicPort, err := resolvePublicEndpoint()
if err != nil {
return "", "", err
}
hysteria2Name := "hysteria2"
hysteria2ConfigRemark, err := dao.GetConfig("key = ?", constant.Hysteria2ConfigRemark)
@@ -144,11 +153,6 @@ func Hysteria2Subscribe(conPass string, clientType string, host string) (string,
userInfo := ""
configStr := ""
listenPort, err := parseListenPort(*hysteria2Config.Listen)
if err != nil {
return "", "", err
}
publicHost := strings.Split(host, ":")[0]
if clientType == constant.Shadowrocket || clientType == constant.Clash {
userInfo = fmt.Sprintf("upload=%d; download=%d; total=%d; expire=%d",
*account.Upload,
@@ -160,7 +164,7 @@ func Hysteria2Subscribe(conPass string, clientType string, host string) (string,
Name: hysteria2Name,
Type: "hysteria2",
Server: publicHost,
Port: strconv.Itoa(listenPort),
Port: strconv.Itoa(publicPort),
Password: conPass,
}
@@ -224,7 +228,7 @@ func Hysteria2Subscribe(conPass string, clientType string, host string) (string,
}
}
} else if clientType == constant.V2rayN {
hysteria2Url, err := Hysteria2Url(*account.Id, strings.Split(host, ":")[0])
hysteria2Url, err := Hysteria2Url(*account.Id)
if err != nil {
return "", "", err
}
@@ -234,7 +238,7 @@ func Hysteria2Subscribe(conPass string, clientType string, host string) (string,
return userInfo, configStr, nil
}
func Hysteria2Url(accountId int64, hostname string) (string, error) {
func Hysteria2Url(accountId int64) (string, error) {
hysteria2Config, err := GetHysteria2Config()
if err != nil {
return "", err
@@ -242,13 +246,10 @@ func Hysteria2Url(accountId int64, hostname string) (string, error) {
if hysteria2Config.Listen == nil || *hysteria2Config.Listen == "" {
return "", errors.New("hysteria2 config is empty")
}
port, err := parseListenPort(*hysteria2Config.Listen)
hostname, port, err := resolvePublicEndpoint()
if err != nil {
return "", err
}
if hostname == "" || hostname == "0.0.0.0" {
return "", errors.New("invalid public host")
}
account, err := dao.GetAccount("id = ?", accountId)
if err != nil {