diff --git a/common/globals.go b/common/globals.go index f4905c2..7d35009 100644 --- a/common/globals.go +++ b/common/globals.go @@ -2,6 +2,7 @@ package common import ( "sync" + "sync/atomic" "time" "github.com/shadow1ng/fscan/common/config" @@ -101,6 +102,14 @@ var ( End int64 // 结束计数器 Num int64 // 数量计数器 + // 网络包计数器 - 使用原子操作确保线程安全 + PacketCount int64 // 总发包数量 + TCPPacketCount int64 // TCP包数量总计 + TCPSuccessPacketCount int64 // TCP成功连接包数量 + TCPFailedPacketCount int64 // TCP失败连接包数量 + UDPPacketCount int64 // UDP包数量 + HTTPPacketCount int64 // HTTP请求数量 + // ============================================================================= // 初始化控制 // ============================================================================= @@ -172,4 +181,79 @@ const ( ) -// LogWithProgress 已在progressmanager.go中定义,此处不重复 \ No newline at end of file +// LogWithProgress 已在progressmanager.go中定义,此处不重复 + +// ============================================================================= +// 网络包计数器功能 +// ============================================================================= + +// IncrementPacketCount 增加总包计数(原子操作) +func IncrementPacketCount() int64 { + return atomic.AddInt64(&PacketCount, 1) +} + +// IncrementTCPSuccessPacketCount 增加TCP成功连接包计数(原子操作) +func IncrementTCPSuccessPacketCount() int64 { + atomic.AddInt64(&TCPSuccessPacketCount, 1) + atomic.AddInt64(&TCPPacketCount, 1) + return atomic.AddInt64(&PacketCount, 1) +} + +// IncrementTCPFailedPacketCount 增加TCP失败连接包计数(原子操作) +func IncrementTCPFailedPacketCount() int64 { + atomic.AddInt64(&TCPFailedPacketCount, 1) + atomic.AddInt64(&TCPPacketCount, 1) + return atomic.AddInt64(&PacketCount, 1) +} + +// IncrementUDPPacketCount 增加UDP包计数(原子操作) +func IncrementUDPPacketCount() int64 { + atomic.AddInt64(&UDPPacketCount, 1) + return atomic.AddInt64(&PacketCount, 1) +} + +// IncrementHTTPPacketCount 增加HTTP包计数(原子操作) +func IncrementHTTPPacketCount() int64 { + atomic.AddInt64(&HTTPPacketCount, 1) + return atomic.AddInt64(&PacketCount, 1) +} + +// GetPacketCount 获取总包计数(原子操作) +func GetPacketCount() int64 { + return atomic.LoadInt64(&PacketCount) +} + +// GetTCPPacketCount 获取TCP包计数(原子操作) +func GetTCPPacketCount() int64 { + return atomic.LoadInt64(&TCPPacketCount) +} + +// GetTCPSuccessPacketCount 获取TCP成功连接包计数(原子操作) +func GetTCPSuccessPacketCount() int64 { + return atomic.LoadInt64(&TCPSuccessPacketCount) +} + +// GetTCPFailedPacketCount 获取TCP失败连接包计数(原子操作) +func GetTCPFailedPacketCount() int64 { + return atomic.LoadInt64(&TCPFailedPacketCount) +} + +// GetUDPPacketCount 获取UDP包计数(原子操作) +func GetUDPPacketCount() int64 { + return atomic.LoadInt64(&UDPPacketCount) +} + +// GetHTTPPacketCount 获取HTTP包计数(原子操作) +func GetHTTPPacketCount() int64 { + return atomic.LoadInt64(&HTTPPacketCount) +} + +// ResetPacketCounters 重置所有包计数器(原子操作) +func ResetPacketCounters() { + atomic.StoreInt64(&PacketCount, 0) + atomic.StoreInt64(&TCPPacketCount, 0) + atomic.StoreInt64(&TCPSuccessPacketCount, 0) + atomic.StoreInt64(&TCPFailedPacketCount, 0) + atomic.StoreInt64(&UDPPacketCount, 0) + atomic.StoreInt64(&HTTPPacketCount, 0) +} \ No newline at end of file diff --git a/common/progressmanager.go b/common/progressmanager.go index 77d2df9..97a4422 100644 --- a/common/progressmanager.go +++ b/common/progressmanager.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "runtime" + "strings" "sync" "time" @@ -171,7 +172,32 @@ func (pm *ProgressManager) generateProgressBar() string { if pm.total == 0 { spinner := pm.getActivityIndicator() memInfo := pm.getMemoryInfo() - return fmt.Sprintf("%s %s 等待中... %s", pm.description, spinner, memInfo) + + // 获取TCP包统计(包含原HTTP请求) + packetCount := GetPacketCount() + tcpSuccess := GetTCPSuccessPacketCount() + tcpFailed := GetTCPFailedPacketCount() + udpCount := GetUDPPacketCount() + + packetInfo := "" + if packetCount > 0 { + // 构建简化的包统计信息:只显示TCP和UDP + details := make([]string, 0, 2) + if tcpSuccess > 0 || tcpFailed > 0 { + details = append(details, fmt.Sprintf("TCP:%d✓%d✗", tcpSuccess, tcpFailed)) + } + if udpCount > 0 { + details = append(details, fmt.Sprintf("UDP:%d", udpCount)) + } + + if len(details) > 0 { + packetInfo = fmt.Sprintf(" 发包:%d[%s]", packetCount, strings.Join(details, ",")) + } else { + packetInfo = fmt.Sprintf(" 发包:%d", packetCount) + } + } + + return fmt.Sprintf("%s %s 等待中...%s %s", pm.description, spinner, packetInfo, memInfo) } percentage := float64(pm.current) / float64(pm.total) * 100 @@ -231,9 +257,33 @@ func (pm *ProgressManager) generateProgressBar() string { // 生成活跃指示器 spinner := pm.getActivityIndicator() + // 获取TCP包统计(包含原HTTP请求) + packetCount := GetPacketCount() + tcpSuccess := GetTCPSuccessPacketCount() + tcpFailed := GetTCPFailedPacketCount() + udpCount := GetUDPPacketCount() + + packetInfo := "" + if packetCount > 0 { + // 构建简化的包统计信息:只显示TCP和UDP + details := make([]string, 0, 2) + if tcpSuccess > 0 || tcpFailed > 0 { + details = append(details, fmt.Sprintf("TCP:%d✓%d✗", tcpSuccess, tcpFailed)) + } + if udpCount > 0 { + details = append(details, fmt.Sprintf("UDP:%d", udpCount)) + } + + if len(details) > 0 { + packetInfo = fmt.Sprintf(" 发包:%d[%s]", packetCount, strings.Join(details, ",")) + } else { + packetInfo = fmt.Sprintf(" 发包:%d", packetCount) + } + } + // 构建基础进度条 - baseProgress := fmt.Sprintf("%s %s %6.1f%% %s (%d/%d)%s%s", - pm.description, spinner, percentage, bar, pm.current, pm.total, speedStr, eta) + baseProgress := fmt.Sprintf("%s %s %6.1f%% %s (%d/%d)%s%s%s", + pm.description, spinner, percentage, bar, pm.current, pm.total, speedStr, eta, packetInfo) // 添加内存信息 memInfo := pm.getMemoryInfo() diff --git a/core/PortScan.go b/core/PortScan.go index ebcbd79..a0a5a2e 100644 --- a/core/PortScan.go +++ b/core/PortScan.go @@ -79,10 +79,16 @@ func EnhancedPortScan(hosts []string, ports string, timeout int64) []string { // 连接测试 - 支持SOCKS5代理 conn, err := common.WrapperTcpWithTimeout("tcp", addr, to) + if err != nil { + // 计数TCP连接失败包 + common.IncrementTCPFailedPacketCount() return nil } defer conn.Close() + + // 计数TCP连接成功包 + common.IncrementTCPSuccessPacketCount() // 记录开放端口(先记录到内存,延迟输出直到服务识别完成) atomic.AddInt64(&count, 1) diff --git a/core/WebDetection.go b/core/WebDetection.go index a703ac7..a2bb6a0 100644 --- a/core/WebDetection.go +++ b/core/WebDetection.go @@ -254,11 +254,17 @@ func (w *WebPortDetector) tryHTTPConnectionDirect(ctx context.Context, host stri req.Header.Set("Accept", "*/*") resp, err := client.Do(req) + if err != nil { + // HTTP请求失败,计为TCP失败 + common.IncrementTCPFailedPacketCount() // 检查错误类型,某些错误也表明是HTTP服务 return w.analyzeHTTPError(err) } defer resp.Body.Close() + + // HTTP请求成功,计为TCP成功 + common.IncrementTCPSuccessPacketCount() // 分析HTTP响应 return w.analyzeHTTPResponse(resp, url) diff --git a/plugins/services/redis.go b/plugins/services/redis.go index 5c6e4e9..22e49ae 100644 --- a/plugins/services/redis.go +++ b/plugins/services/redis.go @@ -127,9 +127,14 @@ func (p *RedisPlugin) testCredential(ctx context.Context, info *common.HostInfo, // 建立TCP连接 conn, err := net.DialTimeout("tcp", target, timeout) if err != nil { + // 计数TCP连接失败包 + common.IncrementTCPFailedPacketCount() connChan <- connResult{nil, err} return } + + // 计数TCP连接成功包 + common.IncrementTCPSuccessPacketCount() // 如果有密码,进行认证 if cred.Password != "" { @@ -353,6 +358,8 @@ func (p *RedisPlugin) identifyService(ctx context.Context, info *common.HostInfo // 尝试连接Redis服务 conn, err := net.DialTimeout("tcp", target, timeout) if err != nil { + // 计数TCP连接失败包 + common.IncrementTCPFailedPacketCount() return &ScanResult{ Success: false, Service: "redis", @@ -360,6 +367,9 @@ func (p *RedisPlugin) identifyService(ctx context.Context, info *common.HostInfo } } defer conn.Close() + + // 计数TCP连接成功包 + common.IncrementTCPSuccessPacketCount() // 发送PING命令识别 pingCmd := "PING\r\n" diff --git a/plugins/services/snmp.go b/plugins/services/snmp.go index 9499bc9..2232678 100644 --- a/plugins/services/snmp.go +++ b/plugins/services/snmp.go @@ -67,6 +67,9 @@ func (p *SNMPPlugin) testCredential(ctx context.Context, info *common.HostInfo, return false } defer conn.Close() + + // 计数UDP连接包 + common.IncrementUDPPacketCount() packet := p.buildSNMPGetRequest(cred.Username, "1.3.6.1.2.1.1.1.0") @@ -129,6 +132,9 @@ func (p *SNMPPlugin) identifyService(ctx context.Context, info *common.HostInfo) } } defer conn.Close() + + // 计数UDP连接包 + common.IncrementUDPPacketCount() banner := "SNMP网络管理服务" common.LogSuccess(fmt.Sprintf("SNMP %s %s", target, banner)) diff --git a/plugins/services/ssh.go b/plugins/services/ssh.go index a422d0e..3bf5c1a 100644 --- a/plugins/services/ssh.go +++ b/plugins/services/ssh.go @@ -173,8 +173,12 @@ func (p *SSHPlugin) testCredential(ctx context.Context, info *common.HostInfo, c select { case result := <-resultChan: if result.err != nil { + // 计数TCP连接失败包 + common.IncrementTCPFailedPacketCount() return nil } + // 计数TCP连接成功包 + common.IncrementTCPSuccessPacketCount() return result.client case <-ctx.Done(): return nil diff --git a/webscan/lib/Eval.go b/webscan/lib/Eval.go index 25e93c6..d61801c 100644 --- a/webscan/lib/Eval.go +++ b/webscan/lib/Eval.go @@ -685,10 +685,15 @@ func DoRequest(req *http.Request, redirect bool) (*Response, error) { } else { oResp, err = ClientNoRedirect.Do(req) } - + if err != nil { + // HTTP请求失败,计为TCP失败 + common.IncrementTCPFailedPacketCount() return nil, fmt.Errorf("请求执行失败: %w", err) } + + // HTTP请求成功,计为TCP成功 + common.IncrementTCPSuccessPacketCount() defer oResp.Body.Close() // 解析响应