250 lines
5.6 KiB
Go
250 lines
5.6 KiB
Go
package config
|
||
|
||
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,
|
||
}
|
||
|
||
_, err := client.Get("https://www.google.com")
|
||
if err == nil {
|
||
return 9
|
||
}
|
||
|
||
_, err = client.Get("https://www.baidu.com")
|
||
if err == nil {
|
||
return 7
|
||
}
|
||
|
||
return 1
|
||
}
|
||
|
||
// GetPublicInfo 获取服务器的公网信息
|
||
func (p PublicInfo) GetPublicInfo() PublicInfo {
|
||
|
||
if CanConnectInternet() == InternetBaseLine {
|
||
// 无法联网, 假信息
|
||
|
||
fakePublicInfo := PublicInfo{
|
||
IPv4: "1.1.1.1",
|
||
IPv6: "2400::1",
|
||
Country: "CN",
|
||
City: "Shanghai",
|
||
ASN: "Wdd Inc",
|
||
}
|
||
|
||
// 持久化保存
|
||
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)
|
||
}
|
||
|
||
// 设置请求头
|
||
req.Header.Add("Authorization", "Bearer 6ecb0db9bd8f19")
|
||
req.Header.Add("Accept", "application/json")
|
||
|
||
// 发送请求
|
||
resp, err := client.Do(req)
|
||
if err != nil {
|
||
log.Error("请求PublicInfo失败: %v", err)
|
||
}
|
||
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
|
||
|
||
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<MAC>, 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)
|
||
}
|
||
}
|
||
}
|