package common import ( "encoding/json" "sync" "sync/atomic" "time" "github.com/juju/ratelimit" ) /* state.go - 运行时状态管理 可变状态,有明确的所有权和线程安全保护。 所有修改通过方法进行,原子操作保证并发安全。 */ // ============================================================================= // State - 可变运行时状态 // ============================================================================= // State 扫描器运行时状态 - 线程安全 type State struct { // 计数器 - 原子操作 packetCount int64 tcpPacketCount int64 tcpSuccessPacketCount int64 tcpFailedPacketCount int64 udpPacketCount int64 httpPacketCount int64 resourceExhaustedCount int64 // 任务计数 end int64 num int64 // 时间 startTime time.Time // 输出互斥锁 outputMutex sync.Mutex // 限速器 - 统一使用令牌桶算法 icmpLimiter *ratelimit.Bucket // ICMP包限速(秒级平滑) packetLimiter *ratelimit.Bucket // 通用发包限速 icmpInitOnce sync.Once packetInitOnce sync.Once // 运行时目标数据(解析后填充) urls []string hostPorts []string urlsMu sync.RWMutex // Shell状态(插件设置) forwardShellActive int32 // 使用int32以便原子操作 reverseShellActive int32 socks5ProxyActive int32 } // NewState 创建新的状态对象 func NewState() *State { return &State{ startTime: time.Now(), } } // ============================================================================= // 包计数器方法 - 原子操作 // ============================================================================= // IncrementPacketCount 增加总包计数 func (s *State) IncrementPacketCount() int64 { return atomic.AddInt64(&s.packetCount, 1) } // IncrementTCPSuccessPacketCount 增加TCP成功连接包计数 func (s *State) IncrementTCPSuccessPacketCount() int64 { atomic.AddInt64(&s.tcpSuccessPacketCount, 1) atomic.AddInt64(&s.tcpPacketCount, 1) return atomic.AddInt64(&s.packetCount, 1) } // IncrementTCPFailedPacketCount 增加TCP失败连接包计数 func (s *State) IncrementTCPFailedPacketCount() int64 { atomic.AddInt64(&s.tcpFailedPacketCount, 1) atomic.AddInt64(&s.tcpPacketCount, 1) return atomic.AddInt64(&s.packetCount, 1) } // IncrementUDPPacketCount 增加UDP包计数 func (s *State) IncrementUDPPacketCount() int64 { atomic.AddInt64(&s.udpPacketCount, 1) return atomic.AddInt64(&s.packetCount, 1) } // IncrementHTTPPacketCount 增加HTTP包计数 func (s *State) IncrementHTTPPacketCount() int64 { atomic.AddInt64(&s.httpPacketCount, 1) return atomic.AddInt64(&s.packetCount, 1) } // IncrementResourceExhaustedCount 增加资源耗尽错误计数 func (s *State) IncrementResourceExhaustedCount() { atomic.AddInt64(&s.resourceExhaustedCount, 1) } // ============================================================================= // 获取计数器方法 - 原子操作 // ============================================================================= // GetPacketCount 获取总包计数 func (s *State) GetPacketCount() int64 { return atomic.LoadInt64(&s.packetCount) } // GetTCPPacketCount 获取TCP包计数 func (s *State) GetTCPPacketCount() int64 { return atomic.LoadInt64(&s.tcpPacketCount) } // GetTCPSuccessPacketCount 获取TCP成功连接包计数 func (s *State) GetTCPSuccessPacketCount() int64 { return atomic.LoadInt64(&s.tcpSuccessPacketCount) } // GetTCPFailedPacketCount 获取TCP失败连接包计数 func (s *State) GetTCPFailedPacketCount() int64 { return atomic.LoadInt64(&s.tcpFailedPacketCount) } // GetUDPPacketCount 获取UDP包计数 func (s *State) GetUDPPacketCount() int64 { return atomic.LoadInt64(&s.udpPacketCount) } // GetHTTPPacketCount 获取HTTP包计数 func (s *State) GetHTTPPacketCount() int64 { return atomic.LoadInt64(&s.httpPacketCount) } // GetResourceExhaustedCount 获取资源耗尽错误计数 func (s *State) GetResourceExhaustedCount() int64 { return atomic.LoadInt64(&s.resourceExhaustedCount) } // ResetPacketCounters 重置所有包计数器 func (s *State) ResetPacketCounters() { atomic.StoreInt64(&s.packetCount, 0) atomic.StoreInt64(&s.tcpPacketCount, 0) atomic.StoreInt64(&s.tcpSuccessPacketCount, 0) atomic.StoreInt64(&s.tcpFailedPacketCount, 0) atomic.StoreInt64(&s.udpPacketCount, 0) atomic.StoreInt64(&s.httpPacketCount, 0) atomic.StoreInt64(&s.resourceExhaustedCount, 0) } // ============================================================================= // 任务计数器方法 // ============================================================================= // GetEnd 获取结束计数 func (s *State) GetEnd() int64 { return atomic.LoadInt64(&s.end) } // GetNum 获取数量计数 func (s *State) GetNum() int64 { return atomic.LoadInt64(&s.num) } // IncrementEnd 增加结束计数 func (s *State) IncrementEnd() int64 { return atomic.AddInt64(&s.end, 1) } // IncrementNum 增加数量计数 func (s *State) IncrementNum() int64 { return atomic.AddInt64(&s.num, 1) } // SetEnd 设置结束计数 func (s *State) SetEnd(val int64) { atomic.StoreInt64(&s.end, val) } // SetNum 设置数量计数 func (s *State) SetNum(val int64) { atomic.StoreInt64(&s.num, val) } // ============================================================================= // 时间和进度方法 // ============================================================================= // GetStartTime 获取开始时间 func (s *State) GetStartTime() time.Time { return s.startTime } // ============================================================================= // 输出互斥锁方法 // ============================================================================= // LockOutput 锁定输出 func (s *State) LockOutput() { s.outputMutex.Lock() } // UnlockOutput 解锁输出 func (s *State) UnlockOutput() { s.outputMutex.Unlock() } // GetOutputMutex 获取输出互斥锁指针 func (s *State) GetOutputMutex() *sync.Mutex { return &s.outputMutex } // ============================================================================= // ICMP 限速器方法 // ============================================================================= // GetICMPLimiter 获取 ICMP 令牌桶限速器(延迟初始化) func (s *State) GetICMPLimiter(icmpRate float64) *ratelimit.Bucket { s.icmpInitOnce.Do(func() { const ( maxRate = 1.0 * 1024 * 1024 // 1MB/s 基准速率 packetSize = 70 // ICMP 包平均大小 ) adjustedRate := maxRate * icmpRate packetsPerSecond := adjustedRate / float64(packetSize) if packetsPerSecond < 1 { packetsPerSecond = 1 } bucketLimit := int64(packetsPerSecond) packetTime := time.Second / time.Duration(packetsPerSecond) s.icmpLimiter = ratelimit.NewBucketWithQuantum( packetTime, bucketLimit, int64(1), ) }) return s.icmpLimiter } // ============================================================================= // 性能统计导出 // ============================================================================= // PerfStatsData 性能统计数据结构 type PerfStatsData struct { TotalPackets int64 `json:"total_packets"` TCPPackets int64 `json:"tcp_packets"` TCPSuccess int64 `json:"tcp_success"` TCPFailed int64 `json:"tcp_failed"` UDPPackets int64 `json:"udp_packets"` HTTPPackets int64 `json:"http_packets"` ResourceExhausted int64 `json:"resource_exhausted"` ScanDurationMs int64 `json:"scan_duration_ms"` PacketsPerSecond float64 `json:"packets_per_second"` SuccessRate float64 `json:"success_rate"` TargetsScanned int64 `json:"targets_scanned"` } // GetPerfStats 获取性能统计数据 func (s *State) GetPerfStats() PerfStatsData { duration := time.Since(s.startTime) durationMs := duration.Milliseconds() totalPackets := atomic.LoadInt64(&s.packetCount) tcpSuccess := atomic.LoadInt64(&s.tcpSuccessPacketCount) tcpFailed := atomic.LoadInt64(&s.tcpFailedPacketCount) tcpTotal := atomic.LoadInt64(&s.tcpPacketCount) var pps float64 if durationMs > 0 { pps = float64(totalPackets) / (float64(durationMs) / 1000.0) } var successRate float64 if tcpTotal > 0 { successRate = float64(tcpSuccess) / float64(tcpTotal) * 100.0 } return PerfStatsData{ TotalPackets: totalPackets, TCPPackets: tcpTotal, TCPSuccess: tcpSuccess, TCPFailed: tcpFailed, UDPPackets: atomic.LoadInt64(&s.udpPacketCount), HTTPPackets: atomic.LoadInt64(&s.httpPacketCount), ResourceExhausted: atomic.LoadInt64(&s.resourceExhaustedCount), ScanDurationMs: durationMs, PacketsPerSecond: pps, SuccessRate: successRate, TargetsScanned: atomic.LoadInt64(&s.num), } } // GetPerfStatsJSON 获取性能统计 JSON 字符串 func (s *State) GetPerfStatsJSON() string { stats := s.GetPerfStats() data, err := json.Marshal(stats) if err != nil { return "{}" } return string(data) } // ============================================================================= // 运行时目标数据方法 // ============================================================================= // GetURLs 获取URL列表 func (s *State) GetURLs() []string { s.urlsMu.RLock() defer s.urlsMu.RUnlock() return s.urls } // SetURLs 设置URL列表 func (s *State) SetURLs(urls []string) { s.urlsMu.Lock() defer s.urlsMu.Unlock() s.urls = urls } // GetHostPorts 获取主机端口列表 func (s *State) GetHostPorts() []string { s.urlsMu.RLock() defer s.urlsMu.RUnlock() return s.hostPorts } // SetHostPorts 设置主机端口列表 func (s *State) SetHostPorts(hostPorts []string) { s.urlsMu.Lock() defer s.urlsMu.Unlock() s.hostPorts = hostPorts } // ClearHostPorts 清空主机端口列表 func (s *State) ClearHostPorts() { s.urlsMu.Lock() defer s.urlsMu.Unlock() s.hostPorts = nil } // ============================================================================= // Shell状态方法 // ============================================================================= // IsForwardShellActive 检查正向Shell是否活跃 func (s *State) IsForwardShellActive() bool { return atomic.LoadInt32(&s.forwardShellActive) == 1 } // SetForwardShellActive 设置正向Shell活跃状态 func (s *State) SetForwardShellActive(active bool) { if active { atomic.StoreInt32(&s.forwardShellActive, 1) } else { atomic.StoreInt32(&s.forwardShellActive, 0) } } // IsReverseShellActive 检查反向Shell是否活跃 func (s *State) IsReverseShellActive() bool { return atomic.LoadInt32(&s.reverseShellActive) == 1 } // SetReverseShellActive 设置反向Shell活跃状态 func (s *State) SetReverseShellActive(active bool) { if active { atomic.StoreInt32(&s.reverseShellActive, 1) } else { atomic.StoreInt32(&s.reverseShellActive, 0) } } // IsSocks5ProxyActive 检查SOCKS5代理是否活跃 func (s *State) IsSocks5ProxyActive() bool { return atomic.LoadInt32(&s.socks5ProxyActive) == 1 } // SetSocks5ProxyActive 设置SOCKS5代理活跃状态 func (s *State) SetSocks5ProxyActive(active bool) { if active { atomic.StoreInt32(&s.socks5ProxyActive, 1) } else { atomic.StoreInt32(&s.socks5ProxyActive, 0) } } // ============================================================================= // 发包频率控制方法 - 统一使用令牌桶算法 // ============================================================================= // GetPacketLimiter 获取通用发包限速器(延迟初始化) // rateLimit: 每分钟允许的包数,转换为令牌桶的秒级速率 func (s *State) GetPacketLimiter(rateLimit int64) *ratelimit.Bucket { s.packetInitOnce.Do(func() { if rateLimit <= 0 { return } // 将每分钟包数转换为每秒速率 packetsPerSecond := float64(rateLimit) / 60.0 if packetsPerSecond < 1 { packetsPerSecond = 1 } // 令牌填充间隔 fillInterval := time.Second / time.Duration(packetsPerSecond) // 桶容量设为每秒速率的2倍,允许小突发 bucketCapacity := int64(packetsPerSecond * 2) if bucketCapacity < 1 { bucketCapacity = 1 } s.packetLimiter = ratelimit.NewBucketWithQuantum( fillInterval, bucketCapacity, 1, ) }) return s.packetLimiter } // CheckAndIncrementPacketRate 检查并消耗发包令牌 // 返回: (可以发包, 错误) // 使用令牌桶算法,统一与ICMP限速器的实现方式 func (s *State) CheckAndIncrementPacketRate(rateLimit int64) (bool, error) { if rateLimit <= 0 { return true, nil } limiter := s.GetPacketLimiter(rateLimit) if limiter == nil { return true, nil } // 尝试获取一个令牌(非阻塞) if limiter.TakeAvailable(1) < 1 { return false, &PacketLimitError{ Sentinel: ErrPacketRateLimited, Limit: rateLimit, } } return true, nil }