diff --git a/server/internal/httpapi/clientconfig.go b/server/internal/httpapi/clientconfig.go index 388b71f..8ccbfb4 100644 --- a/server/internal/httpapi/clientconfig.go +++ b/server/internal/httpapi/clientconfig.go @@ -30,11 +30,11 @@ func BuildClientConfig(node *nodes.NodeRow, dpUUID, deriveKey string) ([]byte, e realityPublicKey := node.RealityPBK realityShortID := node.RealityShortID + // Hysteria2 仅在节点确实配置了 hy2 端口时才下发。否则不出 hy2-out: + // 它会指向 REALITY 的 TCP 端口、而服务端又无 Hy2 监听,导致 urltest + // 一直探测一个死成员(connection reset by peer)。 + hy2Enabled := node.Hy2Port.Valid && node.Hy2Port.Int32 > 0 hy2Password := dpcred.DeriveHy2Password(dpUUID, deriveKey) - hy2Port := int32(443) // default - if node.Hy2Port.Valid { - hy2Port = node.Hy2Port.Int32 - } // REALITY outbound (VLESS + REALITY TLS, TCP 443). realityOut := map[string]any{ @@ -77,7 +77,7 @@ func BuildClientConfig(node *nodes.NodeRow, dpUUID, deriveKey string) ([]byte, e "type": "hysteria2", "tag": "hy2-out", "server": host, - "server_port": hy2Port, + "server_port": node.Hy2Port.Int32, "password": hy2Password, "tls": map[string]any{ "enabled": true, @@ -96,14 +96,22 @@ func BuildClientConfig(node *nodes.NodeRow, dpUUID, deriveKey string) ([]byte, e "stack": "system", } + // 代理出站集合:REALITY 必有;Hy2 仅在启用时加入(否则不进配置/探测组)。 + proxyTags := []string{"reality-out"} + proxyOutbounds := []any{realityOut} + if hy2Enabled { + proxyTags = append(proxyTags, "hy2-out") + proxyOutbounds = append(proxyOutbounds, hy2Out) + } + // urltest auto-select outbound. autoBest := map[string]any{ - "type": "urltest", - "tag": "auto", - "outbounds": []string{"reality-out", "hy2-out"}, - "url": "https://www.gstatic.com/generate_204", - "interval": "3m", - "tolerance": 50, + "type": "urltest", + "tag": "auto", + "outbounds": proxyTags, + "url": "https://www.gstatic.com/generate_204", + "interval": "3m", + "tolerance": 50, } // Route: LAN direct, everything else via auto. @@ -137,13 +145,11 @@ func BuildClientConfig(node *nodes.NodeRow, dpUUID, deriveKey string) ([]byte, e cfg := map[string]any{ "log": map[string]any{"level": "warn", "timestamp": true}, "inbounds": []any{tunIn}, - "outbounds": []any{ - realityOut, - hy2Out, + "outbounds": append(proxyOutbounds, autoBest, map[string]any{"type": "block", "tag": "block"}, map[string]any{"type": "direct", "tag": "direct"}, - }, + ), "route": route, "dns": dns, }