| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 | package analyticimport (	stdnet "net"	"strings"	"github.com/shirou/gopsutil/v4/net"	"github.com/uozi-tech/cosy/logger")func GetNetworkStat() (data *net.IOCountersStat, err error) {	networkStats, err := net.IOCounters(true)	if err != nil {		return	}	if len(networkStats) == 0 {		return &net.IOCountersStat{}, nil	}	// Get all network interfaces	interfaces, err := stdnet.Interfaces()	if err != nil {		logger.Error(err)		return	}	var (		totalBytesRecv   uint64		totalBytesSent   uint64		totalPacketsRecv uint64		totalPacketsSent uint64		totalErrIn       uint64		totalErrOut      uint64		totalDropIn      uint64		totalDropOut     uint64		totalFifoIn      uint64		totalFifoOut     uint64	)	// Create a map of external interface names	externalInterfaces := make(map[string]bool)	// Identify external interfaces	for _, iface := range interfaces {		// Skip down or loopback interfaces		if iface.Flags&stdnet.FlagUp == 0 ||			iface.Flags&stdnet.FlagLoopback != 0 {			continue		}		// Skip common virtual interfaces by name pattern		if isVirtualInterface(iface.Name) {			continue		}		// Check if this is a physical network interface		if isPhysicalInterface(iface.Name) && len(iface.HardwareAddr) > 0 {			externalInterfaces[iface.Name] = true			continue		}		// Get addresses for this interface		addrs, err := iface.Addrs()		if err != nil {			logger.Error(err)			continue		}		// Skip interfaces without addresses		if len(addrs) == 0 {			continue		}		// Check for non-private IP addresses		for _, addr := range addrs {			ip, ipNet, err := stdnet.ParseCIDR(addr.String())			if err != nil {				continue			}			// Skip virtual, local, multicast, and special purpose IPs			if !isRealExternalIP(ip, ipNet) {				continue			}			externalInterfaces[iface.Name] = true			break		}	}	// Accumulate stats only from external interfaces	for _, stat := range networkStats {		if externalInterfaces[stat.Name] {			totalBytesRecv += stat.BytesRecv			totalBytesSent += stat.BytesSent			totalPacketsRecv += stat.PacketsRecv			totalPacketsSent += stat.PacketsSent			totalErrIn += stat.Errin			totalErrOut += stat.Errout			totalDropIn += stat.Dropin			totalDropOut += stat.Dropout			totalFifoIn += stat.Fifoin			totalFifoOut += stat.Fifoout		}	}	return &net.IOCountersStat{		Name:        "analytic.network",		BytesRecv:   totalBytesRecv,		BytesSent:   totalBytesSent,		PacketsRecv: totalPacketsRecv,		PacketsSent: totalPacketsSent,		Errin:       totalErrIn,		Errout:      totalErrOut,		Dropin:      totalDropIn,		Dropout:     totalDropOut,		Fifoin:      totalFifoIn,		Fifoout:     totalFifoOut,	}, nil}// isVirtualInterface checks if the interface is a virtual one based on name patternsfunc isVirtualInterface(name string) bool {	// Common virtual interface name patterns	virtualPatterns := []string{		"veth", "virbr", "vnet", "vmnet", "vboxnet", "docker",		"br-", "bridge", "tun", "tap", "bond", "dummy",		"vpn", "ipsec", "gre", "sit", "vlan", "virt",		"wg", "vmk", "ib", "vxlan", "geneve", "ovs",		"hyperv", "hyper-v", "awdl", "llw", "utun",		"vpn", "zt", "zerotier", "wireguard",	}	for _, pattern := range virtualPatterns {		if strings.Contains(strings.ToLower(name), pattern) {			return true		}	}	return false}// isPhysicalInterface checks if the interface is a physical network interface// including server, cloud VM, and container physical interfacesfunc isPhysicalInterface(name string) bool {	// Common prefixes for physical network interfaces across different platforms	physicalPrefixes := []string{		"eth",  // Common Linux Ethernet interface		"en",   // macOS and some Linux		"ens",  // Predictable network interface names in systemd		"enp",  // Predictable network interface names in systemd (PCI)		"eno",  // Predictable network interface names in systemd (on-board)		"wlan", // Wireless interfaces		"wifi", // Some wireless interfaces		"wl",   // Shortened wireless interfaces		"bond", // Bonded interfaces		"em",   // Some server network interfaces		"p",    // Some specialized network cards		"lan",  // Some network interfaces	}	// Check for exact matches for common primary interfaces	if name == "eth0" || name == "en0" || name == "em0" {		return true	}	// Check for common physical interface patterns	for _, prefix := range physicalPrefixes {		if strings.HasPrefix(strings.ToLower(name), prefix) {			// Check if the remaining part is numeric or empty			suffix := strings.TrimPrefix(strings.ToLower(name), prefix)			if suffix == "" || isNumericSuffix(suffix) {				return true			}		}	}	return false}// isNumericSuffix checks if a string is a numeric suffix or starts with a numberfunc isNumericSuffix(s string) bool {	if len(s) == 0 {		return false	}	// Check if the first character is a digit	if s[0] >= '0' && s[0] <= '9' {		return true	}	return false}// isRealExternalIP checks if an IP is a genuine external (public) IPfunc isRealExternalIP(ip stdnet.IP, ipNet *stdnet.IPNet) bool {	// Skip if it's not a global unicast address	if !ip.IsGlobalUnicast() {		return false	}	// Skip private IPs	if ip.IsPrivate() {		return false	}	// Skip link-local addresses	if ip.IsLinkLocalUnicast() {		return false	}	// Skip loopback	if ip.IsLoopback() {		return false	}	// Skip multicast	if ip.IsMulticast() {		return false	}	// Check for special reserved ranges	if isReservedIP(ip) {		return false	}	return true}// isReservedIP checks if an IP belongs to special reserved rangesfunc isReservedIP(ip stdnet.IP) bool {	// Handle IPv4	if ip4 := ip.To4(); ip4 != nil {		// TEST-NET-1: 192.0.2.0/24 (RFC 5737)		if ip4[0] == 192 && ip4[1] == 0 && ip4[2] == 2 {			return true		}		// TEST-NET-2: 198.51.100.0/24 (RFC 5737)		if ip4[0] == 198 && ip4[1] == 51 && ip4[2] == 100 {			return true		}		// TEST-NET-3: 203.0.113.0/24 (RFC 5737)		if ip4[0] == 203 && ip4[1] == 0 && ip4[2] == 113 {			return true		}		// Benchmark tests: 198.18.0.0/15 (includes 198.19.0.0/16) (RFC 2544)		if ip4[0] == 198 && (ip4[1] == 18 || ip4[1] == 19) {			return true		}		// Documentation: 240.0.0.0/4 (RFC 1112)		if ip4[0] >= 240 {			return true		}		// CGNAT: 100.64.0.0/10 (RFC 6598)		if ip4[0] == 100 && (ip4[1]&0xC0) == 64 {			return true		}	} else if ip.To16() != nil {		// Documentation prefix (2001:db8::/32) - RFC 3849		if ip[0] == 0x20 && ip[1] == 0x01 && ip[2] == 0x0d && ip[3] == 0xb8 {			return true		}		// Unique Local Addresses (fc00::/7) - RFC 4193		if (ip[0] & 0xfe) == 0xfc {			return true		}		// 6to4 relay (2002::/16) - RFC 3056		if ip[0] == 0x20 && ip[1] == 0x02 {			return true		}		// Teredo tunneling (2001:0::/32) - RFC 4380		if ip[0] == 0x20 && ip[1] == 0x01 && ip[2] == 0x00 && ip[3] == 0x00 {			return true		}		// Deprecated site-local addresses (fec0::/10) - RFC 3879		if (ip[0]&0xff) == 0xfe && (ip[1]&0xc0) == 0xc0 {			return true		}		// Old 6bone addresses (3ffe::/16) - Deprecated		if ip[0] == 0x3f && ip[1] == 0xfe {			return true		}		// ORCHID addresses (2001:10::/28) - RFC 4843		if ip[0] == 0x20 && ip[1] == 0x01 && ip[2] == 0x00 && (ip[3]&0xf0) == 0x10 {			return true		}		// ORCHID v2 addresses (2001:20::/28) - RFC 7343		if ip[0] == 0x20 && ip[1] == 0x01 && ip[2] == 0x00 && (ip[3]&0xf0) == 0x20 {			return true		}	}	return false}
 |