mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00
feat: 实现进度条网络包统计功能,支持TCP成功失败分类
- 新增全局原子操作包计数器,支持TCP成功/失败、UDP分类统计 - 端口扫描TCP连接区分成功失败计数,提供准确的网络活动监控 - HTTP请求统一归类到TCP统计,简化显示逻辑 - 进度条实时显示发包统计:发包:总数[TCP:成功✓失败✗,UDP:数量] - 服务插件TCP/UDP连接同步计数,确保统计完整性 - 使用原子操作保证高并发环境下计数准确性
This commit is contained in:
parent
a7ea2f5198
commit
a36767c158
@ -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中定义,此处不重复
|
||||
// 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)
|
||||
}
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
// 解析响应
|
||||
|
Loading…
Reference in New Issue
Block a user