package host_info import ( "agent-wdd/log" "encoding/json" "fmt" "io" "net" "net/http" "regexp" "time" ) // 能够联网,就大于这个数字 外网9 国内7 不能联网1 未知0 const InternetBaseLine = 1 // 定义响应数据结构体 type IPInfo struct { IP string `json:"ip"` City string `json:"city"` Region string `json:"region"` Country string `json:"country"` Loc string `json:"loc"` Org string `json:"org"` Postal string `json:"postal"` Timezone string `json:"timezone"` } // Gather 获取网络相关的信息 func (network *Network) Gather() { log.Info("Gathering INFO => NETWORK !") // 能够联网 network.Internet = CanConnectInternet() // 获取公网的相关信息 network.Public = network.Public.GetPublicInfo() //获取本机网卡相关的内容 network.Interfaces = GetInterfaces() } // GetInterfaces 获取本机网卡相关的内容 func GetInterfaces() []Interface { interfaces := []Interface{} // 获取所有网卡信息 netInterfaces, err := net.Interfaces() // log.Info("all network interfaces: %v", netInterfaces) if err != nil { log.Error("获取网卡信息失败: %v", err) return interfaces } for _, netInterface := range netInterfaces { // 过滤掉没有地址的网卡 addrs, err := netInterface.Addrs() if err != nil || len(addrs) == 0 { continue } // 检查网卡名称是否有效 if !isValidNICName(netInterface.Name) { continue } // 创建 Interface 对象 iface := Interface{ Name: netInterface.Name, MAC: netInterface.HardwareAddr.String(), MTU: netInterface.MTU, } // 获取 IPv4 和 IPv6 地址 for _, addr := range addrs { ipNet, ok := addr.(*net.IPNet) if !ok { continue } if ipNet.IP.To4() != nil { iface.IPv4 = ipNet.IP.String() } else if ipNet.IP.To16() != nil { iface.IPv6 = ipNet.IP.String() } } interfaces = append(interfaces, iface) } return interfaces } func (network *Network) SaveConfig() { ConfigCache.Agent.Network = *network SaveConfig() } // CanConnectInternet 判定主机能够上网 外网为9 国内为7 不能上网为1 func CanConnectInternet() int { // 读取 config 文件,判定能否上网 internetCode := ConfigCache.Agent.Network.Internet if internetCode == 0 { // 没有相关的信息,需要重新判定 internetCode = judgeCanConnectInternet() // 持久化保存 ConfigCache.Agent.Network.Internet = internetCode } return internetCode } // judgeCanConnectInternet 请求网址判定主机能否上网 请求 www.google.com 如果请求正常 返回9 如果超时三秒 请求baidu.com,如果没有错误返回7 如果错误返回1 func judgeCanConnectInternet() int { client := http.Client{ Timeout: 3 * time.Second, } results := make(chan int, 2) go func() { _, err := client.Get("https://www.google.com") if err == nil { results <- 9 } else { results <- 1 } }() go func() { _, err := client.Get("https://www.baidu.com") if err == nil { results <- 7 } else { results <- 1 } }() maxResult := 1 for i := 0; i < 2; i++ { result := <-results if result > maxResult { maxResult = result } } return maxResult } // GetPublicInfo 获取服务器的公网信息 func (p PublicInfo) GetPublicInfo() PublicInfo { // 无法联网, 假信息 fakePublicInfo := PublicInfo{ IPv4: "1.1.1.1", IPv6: "2400::1", Country: "CN", City: "Shanghai", ASN: "Wdd Inc", Timezone: "Asia/Shanghai", } if CanConnectInternet() == InternetBaseLine { // 持久化保存 ConfigCache.Agent.Network.Public = fakePublicInfo return fakePublicInfo } // 可以联网 // 创建带有超时的HTTP客户端 client := &http.Client{ Timeout: 3 * time.Second, } // 创建新的请求对象 req, err := http.NewRequest("GET", "https://ipinfo.io", nil) if err != nil { log.Error("创建请求失败: %v", err) return fakePublicInfo } // 设置请求头 req.Header.Add("Authorization", "Bearer 6ecb0db9bd8f19") req.Header.Add("Accept", "application/json") // 发送请求 resp, err := client.Do(req) if err != nil { log.Error("请求PublicInfo失败: %s", err.Error()) return fakePublicInfo } defer resp.Body.Close() // 检查响应状态码 if resp.StatusCode != http.StatusOK { log.Error("非200状态码: %d", resp.StatusCode) } // 读取响应体 body, err := io.ReadAll(resp.Body) if err != nil { log.Error("读取响应失败: %v", err) } // 解析JSON数据 var info IPInfo if err := json.Unmarshal(body, &info); err != nil { log.Error("JSON解析失败: %v", err) } // 打印解析结果 // log.Info("IP信息:\n%+v\n", info) // 保存信息 p.IPv4 = info.IP p.ASN = info.Org p.Country = info.Country p.City = info.City p.Timezone = info.Timezone ConfigCache.Agent.Network.Public = p return p } func isValidNICName(name string) bool { // 定义传统命名规则正则表达式 // eth0, eth1, wlan0, wlan1 等 traditionalPattern := `^(eth|wlan)[0-9]+$` // 定义现代命名规则正则表达式 // 支持 eno1, ens3, enp0s3, enx, wlp2s0 等格式 modernPattern := `^(en|wl)(o[0-9]+|s[0-9]+|p[0-9]+s[0-9]+|x[0-9a-fA-F]{12})$` // 编译正则表达式 traditionalRegex := regexp.MustCompile(traditionalPattern) modernRegex := regexp.MustCompile(modernPattern) // 检查是否匹配传统命名或现代命名规则 return traditionalRegex.MatchString(name) || modernRegex.MatchString(name) } func main() { // 测试用例 testCases := []string{ "eth0", // 传统以太网命名 "wlan1", // 传统无线网卡命名 "eno1", // 板载网卡 "ens3", // 插槽网卡 "enp0s3", // PCI网卡 "enx0a1b2c3d4e5f", // 基于MAC地址的命名 "wlp2s0", // 无线PCI网卡 "eth", // 无效:缺少数字 "enp0", // 无效:不符合现代规则 "abc123", // 无效:完全不匹配 } for _, tc := range testCases { if isValidNICName(tc) { fmt.Printf("%s: 有效网卡名称\n", tc) } else { fmt.Printf("%s: 无效网卡名称\n", tc) } } }