// Copyright 2023 GoEdge CDN goedge.cdn@gmail.com. All rights reserved. Official site: https://goedge.cn . //go:build plus && packet package networksecurity import ( "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" teaconst "github.com/TeaOSLab/EdgeNode/internal/const" "github.com/TeaOSLab/EdgeNode/internal/events" "github.com/TeaOSLab/EdgeNode/internal/monitor" "github.com/TeaOSLab/EdgeNode/internal/remotelogs" "github.com/TeaOSLab/EdgeNode/internal/utils" "github.com/TeaOSLab/EdgeNode/internal/utils/goman" "github.com/TeaOSLab/EdgeNode/internal/utils/netpackets" "github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/maps" "runtime" "time" ) var SharedManager = NewManager() func init() { if !teaconst.IsMain { return } events.On(events.EventLoaded, func() { nodeConfig, _ := nodeconfigs.SharedNodeConfig() if nodeConfig != nil { go SharedManager.Apply(nodeConfig.NetworkSecurityPolicy) } }) events.On(events.EventQuit, func() { go SharedManager.Apply(nil) }) goman.New(func() { var ticker = time.NewTicker(1 * time.Minute) for range ticker.C { SharedManager.Upload() } }) } type Manager struct { listener *netpackets.Listener isRunning bool policy *nodeconfigs.NetworkSecurityPolicy totalTCPPacketsMinutely uint64 totalUDPPacketsMinutely uint64 totalICMPPacketsMinutely uint64 } func NewManager() *Manager { return &Manager{} } // Apply 应用配置 // 非线程安全 func (this *Manager) Apply(policy *nodeconfigs.NetworkSecurityPolicy) { if this.policy != nil && this.policy.IsSame(policy) { return } this.policy = policy if policy == nil || policy.Status == nodeconfigs.NetworkSecurityStatusOff || (policy.Status == nodeconfigs.NetworkSecurityStatusAuto && runtime.NumCPU() < 8) { if this.listener != nil { remotelogs.Println("NETWORK_SECURITY_MANAGER", "stop") this.listener.Stop() } this.isRunning = false return } if this.listener == nil { this.listener = netpackets.NewListener() // References: // - https://biot.com/capstats/bpf.html // - https://www.ibm.com/docs/en/qsip/7.4?topic=queries-berkeley-packet-filters // - https://www.tcpdump.org/manpages/tcpdump.1.html if Tea.IsTesting() || utils.IsDebugEnv() { // dev environment this.listener.SetBPF("(tcp or udp or icmp) and not net 127 and not net ::1") } else { this.listener.SetBPF("(tcp or udp or icmp) and not src net 127 and not src net 192.168 and not src net 172.16 and not src net ::1 and not src net 10") } this.listener.AddFilter(this) } if !this.isRunning { this.isRunning = true remotelogs.Println("NETWORK_SECURITY_MANAGER", "start") err := this.listener.Start() // long run function if err != nil { remotelogs.Error("NETWORK_SECURITY_MANAGER", "start listener failed: "+err.Error()) } this.isRunning = false } } func (this *Manager) FilterMeta(meta *netpackets.PacketMeta) { switch meta.LayerType { case netpackets.LayerTypeTCP: // 这里不需要试用atomic,因为数据不需要那么精确 this.totalTCPPacketsMinutely++ case netpackets.LayerTypeUDP: this.totalUDPPacketsMinutely++ case netpackets.LayerTypeICMPv4, netpackets.LayerTypeICMPv6: this.totalICMPPacketsMinutely++ } } func (this *Manager) Upload() { if !this.isRunning { return } monitor.SharedValueQueue.Add(nodeconfigs.NodeValueItemNetworkPackets, maps.Map{ "tcpInPPS": this.totalTCPPacketsMinutely / 60, "udpInPPS": this.totalUDPPacketsMinutely / 60, "icmpInPPS": this.totalICMPPacketsMinutely / 60, }) this.totalTCPPacketsMinutely = 0 this.totalUDPPacketsMinutely = 0 this.totalICMPPacketsMinutely = 0 }