fix: https://github.com/komari-monitor/komari/issues/248 使用中文域名进行自动发现无法链接面板

This commit is contained in:
Akizon77
2025-11-04 14:55:48 +08:00
parent 3f945ea1e3
commit 77dbb9e487
5 changed files with 84 additions and 5 deletions

View File

@@ -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)

5
go.mod
View File

@@ -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
)

4
go.sum
View File

@@ -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=

View File

@@ -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()

54
utils/idna.go Normal file
View File

@@ -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
}