目录
主机信息识别系统设计思路
1. 分层收集架构
2. 智能推断引擎
3. 性能优化设计
4. 健壮性保障
5. 核心设计理念
注意事项
代码分析
调用和初始化
通过MAC地址收集信息
获取MAC地址厂商
基于MAC地址的厂商推断信息
通过DNS查询收集信息
检查缓存
DNS反查询
通过网络特征分析收集信息
私有地址识别
特殊地址识别
格式化返回结果
源代码
其它
主机信息识别系统设计思路
1. 分层收集架构
- 三层信息收集:MAC层 → DNS层 → 网络层
- 优先级设计:DNS解析覆盖MAC推断,确保最可靠信息优先
- 置信度累积:每层成功分析增加置信度,量化识别可靠性
2. 智能推断引擎
- 规则驱动:基于MAC厂商库和主机名模式的规则匹配
- 多级条件判断:虚拟化→网络设备→服务器→消费设备的推断链条
- 动态覆盖机制:高优先级信息自动覆盖低优先级推断
3. 性能优化设计
- 缓存机制:线程安全的DNS缓存,避免重复查询
- 资源共享:指针类型数据库,多个实例共享同一厂商库
- 状态隔离:每次分析前重置状态,确保结果独立性
4. 健壮性保障
- 防御性编程:全面的输入验证和错误处理
- 优雅降级:信息不足时提供有意义的置信度提示
- 模块化扩展:易于添加新的厂商标识和识别规则
5. 核心设计理念
- 渐进式识别:从基础硬件信息到详细系统推断
- 多源信息融合:结合MAC、DNS、IP特征综合判断
- 置信度驱动:基于可信度动态调整输出信息粒度
注意事项
并发过大可能导致MAC地址和主机信息无法输出
代码分析
调用和初始化
collector := NewHostInfo() InfoResult := collector.GetHostInfoBatch(datas)// HostInfo 主机信息结构体 type HostInfo struct { IP string MAC string Hostname string Vendor string //设备厂商 DeviceType string //设备类型 OSLikely string //可能的操作系统 Confidence int //置信度(1-100) macDB *MACVendorDB //MAC厂商数据库 dnsCache sync.Map //DNS缓存 } // MACVendorDB MAC厂商数据库 type MACVendorDB struct { vendors map[string]string //在结构体中定义了一个map类型的字段,以vendors命名 } // NewMACVendorDB 创建厂商数据库(创建一个构造函数,返回类型是指针) func NewMACVendorDB() *MACVendorDB { // 1. 创建空的MACVendorDB实例 db := &MACVendorDB{ vendors: make(map[string]string), //初始化 vendors 字段为一个空的 map } // 2. 调用initVendors()填充数据 db.initVendors() // 3. 返回包含完整数据的db return db // 现在db.vendors包含了所有厂商映射 } // initVendors 初始化常见厂商OUI,m为接收者,MACVendorDB为接收者类型 // 通过db.initVendors()调用时,db就相当于参数传入m func (m *MACVendorDB) initVendors() { //定义MACVendorDB结构体里vendors的值 m.vendors = map[string]string{ // 虚拟化 ...... // 网络设备厂商 ...... // 手机和消费设备 ...... // 服务器 ...... // 消费设备 ...... // 常见网络设备 ...... // 更多手机厂商 ...... } } // NewHostInfo 创建HostInfo实例 func NewHostInfo() *HostInfo { return &HostInfo{ macDB: NewMACVendorDB(), } } // GetHostInfoBatch 批量获取主机信息 func (h *HostInfo) GetHostInfoBatch(datas []HostInfoResult) map[string]string { results := make(map[string]string) for _, data := range datas { info := h.GetHostInfo(data.IP, data.MAC) results[data.IP] = info } return results }//其它模块调用GetHostInfoBatch方法 collector := NewHostInfo() InfoResult := collector.GetHostInfoBatch(datas)// NewHostInfo 创建HostInfo实例 func NewHostInfo() *HostInfo { return &HostInfo{ macDB: NewMACVendorDB(), } }在其它模块使用GetHostInfoBatch方法前要先调用NewHostInfo()进行初始化确保macDB不是nil
collector := NewHostInfo() // 相当于: // collector = HostInfo{ // macDB: &MACVendorDB{vendors: map[...]...}, // 已初始化 // dnsCache: sync.Map{}, // 自动初始化 // // 其他字段都是零值,但不会导致崩溃 // }HostInfo结构体:
type HostInfo struct { IP string MAC string // 字符串,零值""不会崩溃 Hostname string // 字符串,零值""不会崩溃 Vendor string // 字符串,零值""不会崩溃 DeviceType string // 字符串,零值""不会崩溃 OSLikely string // 字符串,零值""不会崩溃 Confidence int // 整数,零值0不会崩溃 macDB *MACVendorDB // ⚠️ 指针类型,零值nil会崩溃! dnsCache sync.Map // 结构体,零值是可用的 }只有macDB必须初始化,因为:
- 它是指针类型,零值是
nil - 方法中直接使用了
h.macDB.GetVendor()
// GetHostInfoBatch 批量获取主机信息 func (h *HostInfo) GetHostInfoBatch(datas []HostInfoResult) map[string]string { results := make(map[string]string) for _, data := range datas { info := h.GetHostInfo(data.IP, data.MAC) results[data.IP] = info } return results }初始化以后,通过 InfoResult := collector.GetHostInfoBatch(datas) 可以调用该方法,因为collector := NewHostInfo()返回的是*HostInfo类型,所以正好符合GetHostInfoBatch方法的接收者类型*HostInfo。
通过MAC地址收集信息
// GetVendor 获取MAC地址厂商 func (m *MACVendorDB) GetVendor(mac string) string { if len(mac) < 8 { return "" } prefix := strings.ToUpper(mac[:8]) // mac[:8] 取前8个字符,如 "00:0C:29",strings.ToUpper() 转为大写,确保大小写一致 if vendor, exists := m.vendors[prefix]; exists { //查看目标MAC地址是否常见厂商的MAC地址库中 return vendor } return "unknown" } // inferFromMAC 基于MAC地址推断详细信息 func (h *HostInfo) inferFromMAC() { mac := h.MAC vendor := h.Vendor // 如果已经通过主机名识别了具体的系统类型,则不再覆盖 if h.OSLikely == "Windows" || h.OSLikely == "Linux" || h.OSLikely == "macOS" { // 只调整设备类型,不覆盖系统类型 //从上到下依次检查每个 case 的条件,第一个为true的条件会被执行,执行完后退出整个switch if h.DeviceType == "unknown" { switch { case h.isVirtualizationMAC(mac): h.DeviceType = "Virtual Machine" case h.isNetworkDeviceMAC(mac): h.DeviceType = "Network Device" case h.isServerMAC(mac): h.DeviceType = "Server" case h.isConsumerDeviceMAC(mac): h.DeviceType = "End Device" } } return } // 虚拟化环境识别 if h.isVirtualizationMAC(mac) { h.DeviceType = "Virtual Machine" switch { case strings.Contains(vendor, "VMware"): h.OSLikely = "VMware Guest" case strings.Contains(vendor, "VirtualBox"): h.OSLikely = "VirtualBox Guest" case strings.Contains(vendor, "QEMU"): h.OSLikely = "KVM/QEMU Guest" case strings.Contains(vendor, "HyperV"): h.OSLikely = "Hyper-V Guest" default: h.OSLikely = "Virtualized OS" } h.Confidence += 20 return } // 网络设备识别 if h.isNetworkDeviceMAC(mac) { h.DeviceType = "Network Device" switch { case strings.Contains(vendor, "Cisco"): h.OSLikely = "Cisco IOS" case strings.Contains(vendor, "Huawei"): h.OSLikely = "Huawei VRP" case strings.Contains(vendor, "H3C"): h.OSLikely = "H3C Comware" case strings.Contains(vendor, "Dell"): h.OSLikely = "Dell OS" default: h.OSLikely = "Embedded Network OS" } h.Confidence += 15 return } // 服务器识别 if h.isServerMAC(mac) { h.DeviceType = "Server" switch { case strings.Contains(vendor, "Dell"): h.OSLikely = "Server OS (Dell)" case strings.Contains(vendor, "HP"): h.OSLikely = "Server OS (HP)" case strings.Contains(vendor, "IBM"): h.OSLikely = "Server OS (IBM)" case strings.Contains(vendor, "Supermicro"): h.OSLikely = "Server OS" default: h.OSLikely = "Linux/Windows Server" } h.Confidence += 10 return } // 消费设备 - 更精确的系统推断 if h.isConsumerDeviceMAC(mac) { h.DeviceType = "End Device" switch { case strings.Contains(vendor, "Apple"): h.OSLikely = "macOS/iOS" case strings.Contains(vendor, "Samsung"): h.OSLikely = "Android/Windows" case strings.Contains(vendor, "Honor"): h.OSLikely = "Android" case strings.Contains(vendor, "ZTE"): h.OSLikely = "Android/Windows" case strings.Contains(vendor, "Xiaomi"): h.OSLikely = "Android" case strings.Contains(vendor, "Intel"): h.OSLikely = "Windows/Linux" case strings.Contains(vendor, "D-Link"): h.OSLikely = "Embedded OS" default: h.OSLikely = "Various OS" } h.Confidence += 5 return } // 默认推断 h.DeviceType = "Network Device" h.OSLikely = "Unknown OS" } // 辅助方法 func (h *HostInfo) isValidMAC(mac string) bool { _, err := net.ParseMAC(mac) // 尝试解析MAC地址 return err == nil // 如果没有错误,说明格式正确 } // collectByMAC 通过MAC地址收集信息 func (h *HostInfo) collectByMAC() { if h.MAC == "" { return } // 验证MAC地址格式 if !h.isValidMAC(h.MAC) { h.Vendor = "invalid-mac" h.Confidence = 0 return } // 获取厂商信息 vendor := h.macDB.GetVendor(h.MAC) h.Vendor = vendor // 基于MAC推断设备类型和操作系统 h.inferFromMAC() // MAC地址本身提供基础置信度 h.Confidence += 30 }获取MAC地址厂商
// GetVendor 获取MAC地址厂商 func (m *MACVendorDB) GetVendor(mac string) string { if len(mac) < 8 { return "" } prefix := strings.ToUpper(mac[:8]) // mac[:8] 取前8个字符,如 "00:0C:29",strings.ToUpper() 转为大写,确保大小写一致 if vendor, exists := m.vendors[prefix]; exists { //查看目标MAC地址是否常见厂商的MAC地址库中 return vendor } return "unknown" }基于MAC地址的厂商推断信息
//辅助函数 func (h *HostInfo) isVirtualizationMAC(mac string) bool { virtualPrefixes := []string{"00:0C:29", "00:50:56", "08:00:27", "52:54:00", "00:15:5D"} return h.macHasPrefix(mac, virtualPrefixes) } //辅助函数 func (h *HostInfo) isNetworkDeviceMAC(mac string) bool { networkPrefixes := []string{"AA:BB:CC", "00:1C:0E", "00:26:BB", "00:1D:0F", "00:24:E8", "00:1A:A9", "00:1B:21", "7C:00:4D", "3C:FF:D8"} return h.macHasPrefix(mac, networkPrefixes) } //辅助函数 func (h *HostInfo) isServerMAC(mac string) bool { serverPrefixes := []string{"00:1C:42", "00:0E:0C", "00:1A:64", "00:21:5A", "00:14:38"} return h.macHasPrefix(mac, serverPrefixes) } //辅助函数 func (h *HostInfo) isConsumerDeviceMAC(mac string) bool { consumerPrefixes := []string{ "34:23:BA", "8C:85:90", "64:66:B3", // Apple "38:65:04", "E0:0A:F6", "E2:CD:F8", // 手机设备 "34:BB:1F", "64:09:80", // Xiaomi "0C:5A:9E", "30:B6:37", "5C:3C:27", // Samsung "88:30:8A", "F0:98:9D", // Apple "00:1B:2F", "00:1E:65", "00:23:12", "00:26:4A", // 其他消费设备 } return h.macHasPrefix(mac, consumerPrefixes) } //检查MAC地址前缀是否匹配指定前缀列表 func (h *HostInfo) macHasPrefix(mac string, prefixes []string) bool { for _, prefix := range prefixes { if strings.HasPrefix(strings.ToUpper(mac), prefix) { return true } } return false } // inferFromMAC 基于MAC地址推断详细信息 func (h *HostInfo) inferFromMAC() { mac := h.MAC vendor := h.Vendor // 虚拟化环境识别 if h.isVirtualizationMAC(mac) { h.DeviceType = "Virtual Machine" //从上到下依次检查每个 case 的条件,第一个为true的条件会被执行,执行完后退出整个switch switch { //根据之前获取的厂商来推断可能的操作系统 case strings.Contains(vendor, "VMware"): h.OSLikely = "VMware Guest" case strings.Contains(vendor, "VirtualBox"): h.OSLikely = "VirtualBox Guest" case strings.Contains(vendor, "QEMU"): h.OSLikely = "KVM/QEMU Guest" case strings.Contains(vendor, "HyperV"): h.OSLikely = "Hyper-V Guest" default: h.OSLikely = "Virtualized OS" } h.Confidence += 20 return } // 网络设备识别 if h.isNetworkDeviceMAC(mac) { h.DeviceType = "Network Device" switch { case strings.Contains(vendor, "Cisco"): h.OSLikely = "Cisco IOS" case strings.Contains(vendor, "Huawei"): h.OSLikely = "Huawei VRP" case strings.Contains(vendor, "H3C"): h.OSLikely = "H3C Comware" case strings.Contains(vendor, "Dell"): h.OSLikely = "Dell OS" default: h.OSLikely = "Embedded Network OS" } h.Confidence += 15 return } // 服务器识别 if h.isServerMAC(mac) { h.DeviceType = "Server" switch { case strings.Contains(vendor, "Dell"): h.OSLikely = "Server OS (Dell)" case strings.Contains(vendor, "HP"): h.OSLikely = "Server OS (HP)" case strings.Contains(vendor, "IBM"): h.OSLikely = "Server OS (IBM)" case strings.Contains(vendor, "Supermicro"): h.OSLikely = "Server OS" default: h.OSLikely = "Linux/Windows Server" } h.Confidence += 10 return } // 消费设备 - 更精确的系统推断 if h.isConsumerDeviceMAC(mac) { h.DeviceType = "End Device" switch { case strings.Contains(vendor, "Apple"): h.OSLikely = "macOS/iOS" case strings.Contains(vendor, "Samsung"): h.OSLikely = "Android/Windows" case strings.Contains(vendor, "Honor"): h.OSLikely = "Android" case strings.Contains(vendor, "ZTE"): h.OSLikely = "Android/Windows" case strings.Contains(vendor, "Xiaomi"): h.OSLikely = "Android" case strings.Contains(vendor, "Intel"): h.OSLikely = "Windows/Linux" case strings.Contains(vendor, "D-Link"): h.OSLikely = "Embedded OS" default: h.OSLikely = "Various OS" } h.Confidence += 5 return } // 默认推断 h.DeviceType = "Network Device" h.OSLikely = "Unknown OS" }func (h *HostInfo) macHasPrefix(mac string, prefixes []string) bool { for _, prefix := range prefixes { //检查MAC地址前缀是否匹配指定前缀列表 if strings.HasPrefix(strings.ToUpper(mac), prefix) { return true } } return false }1.strings.ToUpper(mac)
mac := "00:0c:29:ab:cd:ef" // 原始MAC,可能包含小写 upperMac := strings.ToUpper(mac) // 转为 "00:0C:29:AB:CD:EF"作用:确保MAC地址是大写格式,避免大小写不匹配
2.strings.HasPrefix(string, prefix)
strings.HasPrefix("00:0C:29:AB:CD:EF", "00:0C:29") // true strings.HasPrefix("00:0C:29:AB:CD:EF", "00:50:56") // false作用:检查字符串是否以指定的前缀开头
通过DNS查询收集信息
// 主机名分析 func (h *HostInfo) analyzeHostname(hostname string) { lowerHostname := strings.ToLower(hostname) //将主机名统一转为小写,避免大小写匹配问题 // 过滤掉无意义的主机名 if hostname == "bogon" || hostname == "localhost" || strings.Contains(lowerHostname, "localdomain") { h.Hostname = "unknown" return } // 基于主机名的系统识别 - 主机名分析具有最高优先级 switch { case strings.Contains(lowerHostname, "win-") || strings.Contains(lowerHostname, "windows") || strings.Contains(lowerHostname, "pc-") || strings.Contains(lowerHostname, "desktop"): h.DeviceType = "Windows Host" h.OSLikely = "Windows" h.Confidence += 15 // 主机名识别置信度更高 case strings.Contains(lowerHostname, "ubuntu") || strings.Contains(lowerHostname, "debian") || strings.Contains(lowerHostname, "centos") || strings.Contains(lowerHostname, "redhat") || strings.Contains(lowerHostname, "fedora") || strings.Contains(lowerHostname, "linux"): h.DeviceType = "Linux Host" h.OSLikely = "Linux" h.Confidence += 15 case strings.Contains(lowerHostname, "mac") || strings.Contains(lowerHostname, "apple"): h.DeviceType = "Apple Device" h.OSLikely = "macOS" h.Confidence += 15 case strings.Contains(lowerHostname, "router") || strings.Contains(lowerHostname, "rt-"): h.DeviceType = "Router" h.OSLikely = "Embedded OS" h.Confidence += 10 case strings.Contains(lowerHostname, "switch") || strings.Contains(lowerHostname, "sw-"): h.DeviceType = "Switch" h.OSLikely = "Embedded OS" h.Confidence += 10 case strings.Contains(lowerHostname, "firewall") || strings.Contains(lowerHostname, "fw-"): h.DeviceType = "Firewall" h.OSLikely = "Embedded OS" h.Confidence += 10 case strings.Contains(lowerHostname, "server") || strings.Contains(lowerHostname, "srv-"): h.DeviceType = "Server" h.OSLikely = "Linux/Windows Server" h.Confidence += 10 case strings.Contains(lowerHostname, "vm") || strings.Contains(lowerHostname, "virtual"): h.DeviceType = "Virtual Machine" h.OSLikely = "Virtualized OS" h.Confidence += 10 case strings.Contains(lowerHostname, "dc"): h.DeviceType = "Domain Controller" h.OSLikely = "Windows Server" h.Confidence += 15 default: // 如果主机名包含特定模式但未匹配上述情况,保持原有推断 } } // collectByDNS DNS查询 func (h *HostInfo) collectByDNS() { if h.IP == "" { return } // 检查缓存 if cached, ok := h.dnsCache.Load(h.IP); ok { if hostname, ok := cached.(string); ok && hostname != "" { h.Hostname = hostname h.Confidence += 15 // 基于主机名进一步分析 - 这里会覆盖之前的MAC推断 h.analyzeHostname(hostname) return } } // DNS反向查询 names, err := net.LookupAddr(h.IP) if err == nil && len(names) > 0 { hostname := names[0] if len(hostname) > 0 && hostname[len(hostname)-1] == '.' { hostname = hostname[:len(hostname)-1] } h.Hostname = hostname h.dnsCache.Store(h.IP, hostname) h.Confidence += 15 // 基于主机名进一步分析 - 这里会覆盖之前的MAC推断 h.analyzeHostname(hostname) } }检查缓存
// 检查缓存 if cached, ok := h.dnsCache.Load(h.IP); ok { if hostname, ok := cached.(string); ok && hostname != "" { h.Hostname = hostname h.Confidence += 15 // 基于主机名进一步分析 - 这里会覆盖之前的MAC推断 h.analyzeHostname(hostname) return } }作用:检查DNS缓存中是否已经有这个IP的主机名记录,如果有就直接使用,避免重复的DNS查询。
// h.dnsCache 是一个 sync.Map(线程安全的map) // h.IP 是要查询的IP地址,如 "192.168.1.1" cached, ok := h.dnsCache.Load(h.IP)Load(h.IP):从缓存中尝试获取该IP对应的值- 返回值:
cached:缓存的值(类型是interface{},需要类型断言)ok:是否找到缓存(bool类型)
if ..., ok:如果找到缓存(ok为true),执行if块内的代码
DNS反查询
// DNS反向查询 names, err := net.LookupAddr(h.IP) if err == nil && len(names) > 0 { hostname := names[0] if len(hostname) > 0 && hostname[len(hostname)-1] == '.' { hostname = hostname[:len(hostname)-1] } h.Hostname = hostname h.dnsCache.Store(h.IP, hostname) h.Confidence += 15 // 基于主机名进一步分析 - 这里会覆盖之前的MAC推断 h.analyzeHostname(hostname) }作用:通过IP地址反向查询主机名,然后对获得的主机名进行处理和分析。
names, err := net.LookupAddr(h.IP) //dns反向查询功能:执行PTR记录查询,通过IP地址查找对应的主机名
返回值:
names:主机名数组(一个IP可能对应多个主机名)err:错误信息,如果为nil表示查询成功
示例:
h.IP = "192.168.1.1" names, err := net.LookupAddr("192.168.1.1") // 可能返回: names = ["win10-pc.local."], err = nilhostname := names[0] // 取第一个主机名 if len(hostname) > 0 && hostname[len(hostname)-1] == '.' { hostname = hostname[:len(hostname)-1] // 去掉末尾的点 }问题:DNS查询返回的主机名通常以点结尾(FQDN格式)
// DNS返回的原始格式: "win10-pc.local." // 有点 "router.domain.com." // 有点 // 处理后的格式: "win10-pc.local" // 去掉点 "router.domain.com" // 去掉点h.Hostname = hostname h.dnsCache.Store(h.IP, hostname)存入DNS缓存
h.dnsCache.Store("192.168.1.1", "win10-pc.local") //进行dns缓存为后续相同IP的查询提供缓存
通过网络特征分析收集信息
//私有地址识别 func (h *HostInfo) isPrivateIP(ip net.IP) bool { _, private24, _ := net.ParseCIDR("10.0.0.0/8") _, private20, _ := net.ParseCIDR("172.16.0.0/12") _, private16, _ := net.ParseCIDR("192.168.0.0/16") return private24.Contains(ip) || private20.Contains(ip) || private16.Contains(ip) } // collectByNetworkAnalysis 网络特征分析 func (h *HostInfo) collectByNetworkAnalysis() { if h.IP == "" { return } ip := net.ParseIP(h.IP) if ip == nil { return } // 私有地址空间识别 if h.isPrivateIP(ip) { h.Confidence += 5 } // 特殊地址识别 switch h.IP { case "127.0.0.1", "::1": h.DeviceType = "Local Host" h.OSLikely = "Local OS" h.Confidence = 100 case "0.0.0.0": h.DeviceType = "Any Interface" h.Confidence = 100 case "255.255.255.255": h.DeviceType = "Broadcast" h.Confidence = 100 } }私有地址识别
//私有地址识别 func (h *HostInfo) isPrivateIP(ip net.IP) bool { _, private24, _ := net.ParseCIDR("10.0.0.0/8") _, private20, _ := net.ParseCIDR("172.16.0.0/12") _, private16, _ := net.ParseCIDR("192.168.0.0/16") return private24.Contains(ip) || private20.Contains(ip) || private16.Contains(ip) }作用:检查给定的IP地址是否属于私有地址范围(内网IP)。
10.0.0.0/8 - A类私有网络
_, private24, _ := net.ParseCIDR("10.0.0.0/8")- 范围:10.0.0.0 - 10.255.255.255
- 掩码:255.0.0.0
- 容量:约1677万个IP
- 用途:大型企业内网
172.16.0.0/12 - B类私有网络
_, private20, _ := net.ParseCIDR("172.16.0.0/12")- 范围:172.16.0.0 - 172.31.255.255
- 掩码:255.240.0.0
- 容量:约104万个IP
- 用途:中型网络
192.168.0.0/16 - C类私有网络
_, private16, _ := net.ParseCIDR("192.168.0.0/16")- 范围:192.168.0.0 - 192.168.255.255
- 掩码:255.255.0.0
- 容量:约6.5万个IP
- 用途:家庭和小型办公室网络
net.ParseCIDR() 函数
// 返回值:IP, *IPNet, error _, private24, _ := net.ParseCIDR("10.0.0.0/8")- 第一个返回值:基础IP(这里用
_忽略) - 第二个返回值:
*IPNet网络对象,用于检查IP包含关系 - 第三个返回值:错误(这里用
_忽略,假设格式正确)
IPNet.Contains() 方法
private24.Contains(ip) // 检查ip是否在10.0.0.0/8网段内特殊地址识别
// 特殊地址识别 switch h.IP { case "127.0.0.1", "::1": h.DeviceType = "Local Host" h.OSLikely = "Local OS" h.Confidence = 100 case "0.0.0.0": h.DeviceType = "Any Interface" h.Confidence = 100 case "255.255.255.255": h.DeviceType = "Broadcast" h.Confidence = 100 }格式化返回结果
// formatResult 格式化返回结果 func (h *HostInfo) formatResult() string { if h.Confidence > 100 { h.Confidence = 100 } // 根据置信度调整输出 if h.Confidence < 30 { return fmt.Sprintf("信息不足 (置信度: %d%%)", h.Confidence) } // 标准信息输出 parts := []string{} //创建一个空的字符串切片 if h.Vendor != "unknown" { parts = append(parts, fmt.Sprintf("厂商: %s", h.Vendor)) } if h.DeviceType != "unknown" { parts = append(parts, fmt.Sprintf("类型: %s", h.DeviceType)) } if h.OSLikely != "Unknown OS" { parts = append(parts, fmt.Sprintf("系统: %s", h.OSLikely)) } if h.Hostname != "unknown" { parts = append(parts, fmt.Sprintf("主机名: %s", h.Hostname)) } if len(parts) > 0 { return fmt.Sprintf("%s (置信度: %d%%)", strings.Join(parts, ", "), h.Confidence) } return fmt.Sprintf("未知设备 (置信度: %d%%)", h.Confidence) }源代码
直接给出最终的源代码
https://github.com/yty0v0/ReconQuiver/blob/main/internal/discovery/utils/hostinfo.go
其它
在我写完针对多协议端口扫描和主机探测的工具后,希望通过文章整理用到的知识点,非常欢迎各位大佬指正文章内容的错误和工具的问题。
这里附上工具链接 https://github.com/yty0v0/ReconQuiver