优化自适应扫描系统 & 修复 POC 调度问题
测试构建 / 代码检查 (push) Has been cancelled
测试构建 / 单元测试和构建 (push) Has been cancelled
测试构建 / 构建验证 (push) Has been cancelled

自适应扫描优化:
- target/ceiling 分离,自适应池可向上探索而非锁死在 target
- assessHealth 阈值按网络环境区分(LAN 收紧 / Internet 放宽)
- RTT 漂移时动态压低 target,配合 AIMD 双重降速
- 去掉 semaphore 双层流控,由 ants pool 统一反压
- 探测端口从 3 个扩充到 8 个,减少 RTT 采样偏差
- computeRetries 按环境调整目标概率和上限

Bug 修复:
- AdaptivePool.Wait() 加 10 分钟超时,防止 goroutine 卡死时永久挂起
- CEL 环境初始化失败后允许重试(sync.Once → sync.Mutex + 标志位)
- CAS 自旋加 runtime.Gosched() 退避,减少高并发下 CPU 空转
- -full 模式下 web 插件跳过 IsMarkedWebService 检查 #588
- 不确定服务补做 HTTP 回退探测,覆盖自定义框架漏网场景
- POC sets 纯字面量值跳过 CEL 编译,消除大量误报错误日志
This commit is contained in:
ZacharyZcR
2026-06-13 12:39:24 +08:00
parent 15a7670ba2
commit 45ebe7040e
15 changed files with 798 additions and 104 deletions
+25 -25
View File
@@ -101,10 +101,9 @@ func (c *resultCollector) GetAll() []string {
// portScanTask 端口扫描任务(轻量级,用于滑动窗口调度)
type portScanTask struct {
host string
port int
addr string // 预格式化的 host:port,避免 fmt.Sprintf 热路径分配
semaphore chan struct{} // 完成时释放窗口槽位
host string
port int
addr string // 预格式化的 host:port,避免 fmt.Sprintf 热路径分配
}
// failedPortInfo 失败端口信息
@@ -216,20 +215,22 @@ func EnhancedPortScan(ctx context.Context, hosts []string, ports string, timeout
failedCollector := &failedPortCollector{}
var wg sync.WaitGroup
ceiling := config.ThreadCeiling
if ceiling < threadNum {
ceiling = threadNum
}
netEnv := NetworkEnv(config.DetectedNetworkEnv)
session.LogDebug(i18n.Tr("port_scan_debug_pool_create", threadNum))
pool, err := NewAdaptivePool(threadNum, threadNum, func(task interface{}) {
pool, err := NewAdaptivePool(threadNum, ceiling, func(task interface{}) {
taskInfo, ok := task.(portScanTask)
if !ok {
return
}
defer func() {
<-taskInfo.semaphore // 释放窗口槽位
wg.Done()
}()
defer wg.Done()
scanSinglePort(ctx, taskInfo.host, taskInfo.port, taskInfo.addr, adaptiveTO, metrics, &count, collector, failedCollector, session)
common.UpdateProgressBar(1)
}, metrics)
}, metrics, netEnv)
if err != nil {
session.LogError(i18n.Tr("thread_pool_create_failed", err))
if stream != nil {
@@ -242,7 +243,7 @@ func EnhancedPortScan(ctx context.Context, hosts []string, ports string, timeout
session.LogDebug(i18n.GetText("port_scan_debug_schedule_start"))
// 滑动窗口调度
slidingWindowSchedule(iter, pool, &wg, threadNum)
slidingWindowSchedule(iter, pool, &wg)
session.LogDebug(i18n.GetText("port_scan_debug_schedule_done"))
// 收集结果
@@ -287,30 +288,21 @@ func EnhancedPortScan(ctx context.Context, hosts []string, ports string, timeout
}
// slidingWindowSchedule 滑动窗口调度器
// 核心思想:维护固定数量的"飞行中"任务,一个完成立即补充新的
// 优势:避免任务队列堆积,内存使用恒定
func slidingWindowSchedule(iter *SocketIterator, pool *AdaptivePool, wg *sync.WaitGroup, windowSize int) {
// 使用信号量控制窗口大小
semaphore := make(chan struct{}, windowSize)
// ants.PoolWithFunc.Invoke 在池满时阻塞,天然提供反压,无需额外 semaphore
func slidingWindowSchedule(iter *SocketIterator, pool *AdaptivePool, wg *sync.WaitGroup) {
for {
host, port, ok := iter.Next()
if !ok {
break
}
// 获取窗口槽位(阻塞直到有空位)
semaphore <- struct{}{}
wg.Add(1)
task := portScanTask{
host: host,
port: port,
addr: net.JoinHostPort(host, fmtPort(port)),
semaphore: semaphore,
host: host,
port: port,
addr: net.JoinHostPort(host, fmtPort(port)),
}
if err := pool.Invoke(task); err != nil {
<-semaphore
wg.Done()
}
}
@@ -725,6 +717,14 @@ func processServiceResult(ctx context.Context, host string, port int, addr strin
details := buildServiceDetails(port, serviceInfo)
isWeb := IsWebServiceByFingerprint(serviceInfo)
// 指纹既不匹配 webKeywords 也不匹配 nonWebKeywords(不确定区间)
// 补做一次 HTTP 探测,覆盖自定义 HTTP 框架等漏网场景
if !isWeb && !isDefinitelyNonWeb(serviceInfo) {
if tryHTTPFallbackDetection(ctx, host, port, addr, config, session) {
isWeb = true
}
}
if isWeb {
details["is_web"] = true
}