feat(client, server): add client name handling and machine ID retrieval
Some checks failed
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Has been cancelled
Build Multi-Platform Binaries / build-frontend (push) Has been cancelled
Some checks failed
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Has been cancelled
Build Multi-Platform Binaries / build-frontend (push) Has been cancelled
This commit is contained in:
@@ -32,7 +32,6 @@ const (
|
||||
reconnectDelay = 5 * time.Second
|
||||
disconnectDelay = 3 * time.Second
|
||||
udpBufferSize = 65535
|
||||
idFileName = "id"
|
||||
)
|
||||
|
||||
// Client 隧道客户端
|
||||
@@ -40,6 +39,7 @@ type Client struct {
|
||||
ServerAddr string
|
||||
Token string
|
||||
ID string
|
||||
Name string // 客户端名称(主机名)
|
||||
TLSEnabled bool
|
||||
TLSConfig *tls.Config
|
||||
DataDir string // 数据目录
|
||||
@@ -64,10 +64,14 @@ func NewClient(serverAddr, token, id string) *Client {
|
||||
log.Printf("Failed to create data dir: %v", err)
|
||||
}
|
||||
|
||||
// ID 优先级:命令行参数 > 机器ID
|
||||
if id == "" {
|
||||
id = loadClientID(dataDir)
|
||||
id = getMachineID()
|
||||
}
|
||||
|
||||
// 获取主机名作为客户端名称
|
||||
hostname, _ := os.Hostname()
|
||||
|
||||
// 初始化日志收集器
|
||||
logger, err := NewLogger(dataDir)
|
||||
if err != nil {
|
||||
@@ -78,6 +82,7 @@ func NewClient(serverAddr, token, id string) *Client {
|
||||
ServerAddr: serverAddr,
|
||||
Token: token,
|
||||
ID: id,
|
||||
Name: hostname,
|
||||
DataDir: dataDir,
|
||||
runningPlugins: make(map[string]plugin.ClientPlugin),
|
||||
logger: logger,
|
||||
@@ -94,27 +99,6 @@ func (c *Client) InitVersionStore() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// getIDFilePath 获取 ID 文件路径
|
||||
func getIDFilePath(dataDir string) string {
|
||||
return filepath.Join(dataDir, idFileName)
|
||||
}
|
||||
|
||||
// loadClientID 从本地文件加载客户端 ID
|
||||
func loadClientID(dataDir string) string {
|
||||
data, err := os.ReadFile(getIDFilePath(dataDir))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
// saveClientID 保存客户端 ID 到本地文件
|
||||
func saveClientID(dataDir, id string) {
|
||||
if err := os.WriteFile(getIDFilePath(dataDir), []byte(id), 0600); err != nil {
|
||||
log.Printf("Failed to save client ID: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// SetPluginRegistry 设置插件注册表
|
||||
func (c *Client) SetPluginRegistry(registry *plugin.Registry) {
|
||||
c.pluginRegistry = registry
|
||||
@@ -181,6 +165,7 @@ func (c *Client) connect() error {
|
||||
authReq := protocol.AuthRequest{
|
||||
ClientID: c.ID,
|
||||
Token: c.Token,
|
||||
Name: c.Name,
|
||||
OS: runtime.GOOS,
|
||||
Arch: runtime.GOARCH,
|
||||
Version: version.Version,
|
||||
@@ -207,11 +192,10 @@ func (c *Client) connect() error {
|
||||
return fmt.Errorf("auth failed: %s", authResp.Message)
|
||||
}
|
||||
|
||||
// 如果服务端分配了新 ID,则更新并保存
|
||||
// 如果服务端分配了新 ID,则更新
|
||||
if authResp.ClientID != "" && authResp.ClientID != c.ID {
|
||||
c.ID = authResp.ClientID
|
||||
saveClientID(c.DataDir, c.ID)
|
||||
c.logf("New ID assigned and saved: %s", c.ID)
|
||||
c.logf("ID updated to: %s", c.ID)
|
||||
}
|
||||
|
||||
c.logf("Authenticated as %s", c.ID)
|
||||
|
||||
133
internal/client/tunnel/machine_id.go
Normal file
133
internal/client/tunnel/machine_id.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package tunnel
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// getMachineID 获取机器唯一标识
|
||||
// 优先级:系统机器ID > MAC地址哈希
|
||||
func getMachineID() string {
|
||||
// 尝试获取系统机器 ID
|
||||
if id := getSystemMachineID(); id != "" {
|
||||
return hashID(id)
|
||||
}
|
||||
|
||||
// 备选:使用主网卡 MAC 地址
|
||||
if id := getMACAddress(); id != "" {
|
||||
return hashID(id)
|
||||
}
|
||||
|
||||
// 都失败则返回空,让服务端生成
|
||||
return ""
|
||||
}
|
||||
|
||||
// getSystemMachineID 获取系统机器 ID
|
||||
func getSystemMachineID() string {
|
||||
switch runtime.GOOS {
|
||||
case "linux":
|
||||
return getLinuxMachineID()
|
||||
case "darwin":
|
||||
return getDarwinMachineID()
|
||||
case "windows":
|
||||
return getWindowsMachineID()
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// getLinuxMachineID 获取 Linux 机器 ID
|
||||
func getLinuxMachineID() string {
|
||||
// 优先读取 /etc/machine-id
|
||||
if data, err := os.ReadFile("/etc/machine-id"); err == nil {
|
||||
return strings.TrimSpace(string(data))
|
||||
}
|
||||
// 备选 /var/lib/dbus/machine-id
|
||||
if data, err := os.ReadFile("/var/lib/dbus/machine-id"); err == nil {
|
||||
return strings.TrimSpace(string(data))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// getDarwinMachineID 获取 macOS 机器 ID (IOPlatformUUID)
|
||||
func getDarwinMachineID() string {
|
||||
cmd := exec.Command("ioreg", "-rd1", "-c", "IOPlatformExpertDevice")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 解析 IOPlatformUUID
|
||||
lines := strings.Split(string(output), "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "IOPlatformUUID") {
|
||||
parts := strings.Split(line, "=")
|
||||
if len(parts) == 2 {
|
||||
uuid := strings.TrimSpace(parts[1])
|
||||
uuid = strings.Trim(uuid, "\"")
|
||||
return uuid
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// getWindowsMachineID 获取 Windows 机器 ID
|
||||
func getWindowsMachineID() string {
|
||||
cmd := exec.Command("reg", "query",
|
||||
`HKLM\SOFTWARE\Microsoft\Cryptography`,
|
||||
"/v", "MachineGuid")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 解析注册表输出
|
||||
lines := strings.Split(string(output), "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "MachineGuid") {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) >= 3 {
|
||||
return fields[len(fields)-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// getMACAddress 获取主网卡 MAC 地址
|
||||
func getMACAddress() string {
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, iface := range interfaces {
|
||||
// 跳过回环和无效接口
|
||||
if iface.Flags&net.FlagLoopback != 0 {
|
||||
continue
|
||||
}
|
||||
if iface.Flags&net.FlagUp == 0 {
|
||||
continue
|
||||
}
|
||||
if len(iface.HardwareAddr) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 返回第一个有效的 MAC 地址
|
||||
return iface.HardwareAddr.String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// hashID 对 ID 进行哈希处理,生成固定长度的客户端 ID
|
||||
func hashID(id string) string {
|
||||
hash := sha256.Sum256([]byte(id))
|
||||
// 取前 16 个字符作为客户端 ID
|
||||
return hex.EncodeToString(hash[:])[:16]
|
||||
}
|
||||
Reference in New Issue
Block a user