From 77dbb9e48753aeefc43a8c171b76ea6137628544 Mon Sep 17 00:00:00 2001 From: Akizon77 Date: Tue, 4 Nov 2025 14:55:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20https://github.com/komari-monitor/komari?= =?UTF-8?q?/issues/248=20=E4=BD=BF=E7=94=A8=E4=B8=AD=E6=96=87=E5=9F=9F?= =?UTF-8?q?=E5=90=8D=E8=BF=9B=E8=A1=8C=E8=87=AA=E5=8A=A8=E5=8F=91=E7=8E=B0?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E9=93=BE=E6=8E=A5=E9=9D=A2=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/autodiscovery.go | 11 ++++++++- go.mod | 5 ++-- go.sum | 4 ++-- server/websocket.go | 15 ++++++++++++ utils/idna.go | 54 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 utils/idna.go diff --git a/cmd/autodiscovery.go b/cmd/autodiscovery.go index 7a46a33..5cf10e6 100644 --- a/cmd/autodiscovery.go +++ b/cmd/autodiscovery.go @@ -12,6 +12,7 @@ import ( "path/filepath" "github.com/komari-monitor/komari-agent/cmd/flags" + "github.com/komari-monitor/komari-agent/utils" ) // AutoDiscoveryConfig 自动发现配置结构体 @@ -109,6 +110,14 @@ func registerWithAutoDiscovery() error { if len(endpoint) > 0 && endpoint[len(endpoint)-1] == '/' { endpoint = endpoint[:len(endpoint)-1] } + + // 转换中文域名为 ASCII 兼容编码 + endpoint, err = utils.ConvertIDNToASCII(endpoint) + if err != nil { + log.Printf("Warning: Failed to convert IDN to ASCII: %v", err) + // 继续使用原始 endpoint,可能在某些情况下仍能工作 + } + registerURL := fmt.Sprintf("%s/api/clients/register?name=%s", endpoint, url.QueryEscape(hostname)) // 创建HTTP请求 @@ -120,7 +129,7 @@ func registerWithAutoDiscovery() error { // 设置请求头 req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", flags.AutoDiscoveryKey)) - + // 添加Cloudflare Access头部 if flags.CFAccessClientID != "" && flags.CFAccessClientSecret != "" { req.Header.Set("CF-Access-Client-Id", flags.CFAccessClientID) diff --git a/go.mod b/go.mod index ba63b28..e11a46c 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/rhysd/go-github-selfupdate v1.2.3 github.com/shirou/gopsutil/v4 v4.25.6 github.com/spf13/cobra v1.9.1 + golang.org/x/net v0.38.0 golang.org/x/sys v0.33.0 gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 ) @@ -34,7 +35,7 @@ require ( github.com/ulikunitz/xz v0.5.9 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect golang.org/x/crypto v0.39.0 // indirect - golang.org/x/net v0.38.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.13.0 // indirect + golang.org/x/sync v0.15.0 // indirect + golang.org/x/text v0.26.0 // indirect ) diff --git a/go.sum b/go.sum index eb643db..53436e6 100644 --- a/go.sum +++ b/go.sum @@ -84,8 +84,8 @@ golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAG golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/server/websocket.go b/server/websocket.go index 9385204..c90e110 100644 --- a/server/websocket.go +++ b/server/websocket.go @@ -14,6 +14,7 @@ import ( "github.com/komari-monitor/komari-agent/dnsresolver" "github.com/komari-monitor/komari-agent/monitoring" "github.com/komari-monitor/komari-agent/terminal" + "github.com/komari-monitor/komari-agent/utils" "github.com/komari-monitor/komari-agent/ws" ) @@ -22,6 +23,13 @@ func EstablishWebSocketConnection() { websocketEndpoint := strings.TrimSuffix(flags.Endpoint, "/") + "/api/clients/report?token=" + flags.Token websocketEndpoint = "ws" + strings.TrimPrefix(websocketEndpoint, "http") + // 转换中文域名为 ASCII 兼容编码 + if convertedEndpoint, err := utils.ConvertIDNToASCII(websocketEndpoint); err == nil { + websocketEndpoint = convertedEndpoint + } else { + log.Printf("Warning: Failed to convert WebSocket IDN to ASCII: %v", err) + } + var conn *ws.SafeConn defer func() { if conn != nil { @@ -155,6 +163,13 @@ func establishTerminalConnection(token, id, endpoint string) { endpoint = strings.TrimSuffix(endpoint, "/") + "/api/clients/terminal?token=" + token + "&id=" + id endpoint = "ws" + strings.TrimPrefix(endpoint, "http") + // 转换中文域名为 ASCII 兼容编码 + if convertedEndpoint, err := utils.ConvertIDNToASCII(endpoint); err == nil { + endpoint = convertedEndpoint + } else { + log.Printf("Warning: Failed to convert Terminal WebSocket IDN to ASCII: %v", err) + } + // 使用与主 WS 相同的拨号策略 dialer := newWSDialer() diff --git a/utils/idna.go b/utils/idna.go new file mode 100644 index 0000000..73c74b3 --- /dev/null +++ b/utils/idna.go @@ -0,0 +1,54 @@ +package utils + +import ( + "net/url" + "strings" + + "golang.org/x/net/idna" +) + +// ConvertIDNToASCII 将包含国际化域名(IDN)的 URL 转换为 ASCII 兼容编码(ACE)格式 +// 例如: "https://中文域名.com" -> "https://xn--fiq228c.com" +func ConvertIDNToASCII(urlStr string) (string, error) { + // 解析 URL + parsedURL, err := url.Parse(urlStr) + if err != nil { + return urlStr, err + } + + // 转换主机名为 Punycode + asciiHost, err := idna.ToASCII(parsedURL.Hostname()) + if err != nil { + return urlStr, err + } + + // 如果有端口,需要保留 + if parsedURL.Port() != "" { + parsedURL.Host = asciiHost + ":" + parsedURL.Port() + } else { + parsedURL.Host = asciiHost + } + + return parsedURL.String(), nil +} + +// ConvertHostToASCII 将主机名(可能包含端口)转换为 ASCII 兼容编码格式 +// 例如: "中文域名.com:8080" -> "xn--fiq228c.com:8080" +func ConvertHostToASCII(host string) (string, error) { + // 分离主机名和端口 + var hostname, port string + if idx := strings.LastIndex(host, ":"); idx != -1 { + hostname = host[:idx] + port = host[idx:] + } else { + hostname = host + } + + // 转换为 ASCII + asciiHost, err := idna.ToASCII(hostname) + if err != nil { + return host, err + } + + return asciiHost + port, nil +}