diff --git a/cmd/sysmonitord/main.go b/cmd/sysmonitord/main.go index 51a59c3..d0c78c8 100644 --- a/cmd/sysmonitord/main.go +++ b/cmd/sysmonitord/main.go @@ -50,7 +50,7 @@ func main() { log.Fatalf("[启动错误]下载配置失败: %v", err) } - CenterServerURL := determineServerURL(officialCfg, userCfg) + CenterServerURL := determineServerURL(userCfg) log.Println("[启动流程] 2/6: 初始化白名单判定引擎...") wlManager := whitelist.NewManager(officialCfg, userCfg) @@ -168,7 +168,7 @@ func main() { log.Println("[守护进程] 已成功停止,安全退出程序。") } -func determineServerURL(officialCfg config.OfficialConfig, userCfg config.UserConfig) string { +func determineServerURL(userCfg config.UserConfig) string { // 服务器地址仅从用户配置获取(符合 ARCHITECTURE.md 规范) if userCfg.Connection.CenterServerURL != "" { return userCfg.Connection.CenterServerURL diff --git a/internal/agent/identity.go b/internal/agent/identity.go new file mode 100644 index 0000000..49d2a98 --- /dev/null +++ b/internal/agent/identity.go @@ -0,0 +1,101 @@ +package agent + +import ( + "fmt" + "net" + "os" + "runtime" + "strings" +) + +type Identity struct { + Hostname string `json:"hostname"` + MACAddr string `json:"mac_addr"` + AgentID string `json:"agent_id"` + IPAddr string `json:"ip_addr"` + OS string `json:"os"` + Arch string `json:"arch"` + PID int `json:"pid"` +} + +func GetIdentity() (*Identity, error) { + hostname, err := os.Hostname() + if err != nil { + return nil, fmt.Errorf("[Agent]获取主机名失败: %v", err) + } + + mac, err := getPrimaryMAC() + if err != nil { + return nil, fmt.Errorf("[Agent]获取MAC地址失败: %v", err) + } + + ips, err := getIPAddrs() + if err != nil { + return nil, fmt.Errorf("[Agent]获取IP地址失败: %v", err) + } + + AgentID := generateAgentID(hostname, mac) + + return &Identity{ + Hostname: hostname, + MACAddr: mac, + IPAddr: ips[0], + AgentID: AgentID, + OS: runtime.GOOS, + Arch: runtime.GOARCH, + PID: os.Getpid(), + }, nil +} + +func getPrimaryMAC() (string, error) { + interfaces, err := net.Interfaces() + if err != nil { + return "", fmt.Errorf("[Agent]获取网络接口失败: %v", err) + } + + for _, iface := range interfaces { + if iface.Flags&net.FlagLoopback != 0 { + continue // 跳过回环接口 + } + + mac := iface.HardwareAddr.String() + if mac == "" { + continue // 跳过没有MAC地址的接口 + } + + if iface.Flags&net.FlagUp != 0 { + return mac, nil // 返回第一个活动接口的MAC地址 + } + } + + for _, iface := range interfaces { + if iface.Flags&net.FlagLoopback == 0 && iface.HardwareAddr.String() != "" { + return iface.HardwareAddr.String(), nil // 返回第一个非回环接口的MAC地址 + } + } + return "", fmt.Errorf("[Agent]未找到有效的网络接口") +} + +func getIPAddrs() ([]string, error) { + var ips []string + + addrs, err := net.InterfaceAddrs() + if err != nil { + return nil, fmt.Errorf("[Agent]获取IP地址失败: %v", err) + } + + for _, addr := range addrs { + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + ips = append(ips, ipnet.IP.String()) + } + } + } + + return ips, nil +} + +func generateAgentID(hostname, mac string) string { + macFormat := strings.ToLower(strings.ReplaceAll(mac, ":", "")) + return fmt.Sprintf("%s-%s", hostname, macFormat) +} diff --git a/internal/network/client.go b/internal/network/client.go index 320f1b7..b74fadc 100644 --- a/internal/network/client.go +++ b/internal/network/client.go @@ -3,14 +3,17 @@ package network import ( "encoding/json" "log" + "net/url" "sync" "time" "github.com/gorilla/websocket" + "github.com/wuko233/sysmonitord/internal/agent" ) type ClientConfig struct { ServerURL string + AgentID string SendInterval time.Duration BufferSize int } @@ -24,20 +27,33 @@ type WSClient struct { stopChan chan struct{} handler MessageHandler reconnectDelay time.Duration // 指数退避延迟 + agentIdentity *agent.Identity } func NewWSClient(cfg ClientConfig) *WSClient { if cfg.BufferSize == 0 { cfg.BufferSize = 100 } + + agentIdentity, err := agent.GetIdentity() + if err != nil { + log.Fatalf("[网络] 获取代理身份信息失败: %v", err) + } + cfg.AgentID = agentIdentity.AgentID + return &WSClient{ config: cfg, sendChan: make(chan Packet, cfg.BufferSize), stopChan: make(chan struct{}), reconnectDelay: 1 * time.Second, // 初始延迟 1秒 + agentIdentity: agentIdentity, } } +func (c *WSClient) GetAgentIdentity() *agent.Identity { + return c.agentIdentity +} + // SetHandler 设置消息处理器 func (c *WSClient) SetHandler(handler MessageHandler) { c.handler = handler @@ -93,9 +109,9 @@ func (c *WSClient) sendRaw(packet Packet) { func (c *WSClient) connectionLoop() { const ( - initialDelay = 1 * time.Second - maxDelay = 60 * time.Second - backoffFactor = 2.0 + initialDelay = 1 * time.Second + maxDelay = 60 * time.Second + backoffFactor = 2.0 ) for { @@ -183,7 +199,9 @@ func (c *WSClient) closeConn() { } func (c *WSClient) connect() error { - conn, _, err := websocket.DefaultDialer.Dial(c.config.ServerURL, nil) + serverURL := c.buildURL() + + conn, _, err := websocket.DefaultDialer.Dial(serverURL, nil) if err != nil { return err } @@ -203,3 +221,19 @@ func (c *WSClient) connect() error { log.Printf("[网络] 成功连接到服务器: %s", c.config.ServerURL) return nil } + +func (c *WSClient) buildURL() string { + u, err := url.Parse(c.config.ServerURL) + if err != nil { + log.Printf("[网络] 解析服务器URL失败: %v", err) + return c.config.ServerURL + } + + q := u.Query() + + q.Set("agent_id", c.config.AgentID) + + u.RawQuery = q.Encode() + + return u.String() +}