mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-26 13:11:53 +08:00
feat: 自适应并发调度 — 网络探测 + AIMD + 参数智能推导
扫描前自动探测网络环境(RTT、丢包率、fd limit),基于探测数据 推导 6 个关键参数,替代硬编码默认值: - Timeout: median_RTT + 4σ(覆盖 99.9% 正常连接) - ModuleThreadNum: target_concurrency / 30 - MaxRetries: ceil(log(0.01)/log(loss_rate))(全失败概率 <1%) - ICMPRate: 环境基准 × fd 系数 - PocNum: 跟随 ModuleThreadNum - DisablePing: 已有 ICMP 权限降级机制 线程池从单信号(资源耗尽率)升级为 AIMD + 慢启动: - 慢启动:target/4 起步,500ms 翻倍 - 稳态 AIMD:健康 +5%,拥塞 ×0.5 - 双信号:资源耗尽率 + RTT 趋势(双 EMA) 用户 -t 显式指定时作为 ceiling,探测仍调整其他参数。 测试:单元 + 边界 + 集成 + 真实网络,core 包 580+ 用例全通过。
This commit is contained in:
+20
-10
@@ -187,13 +187,12 @@ func EnhancedPortScan(ctx context.Context, hosts []string, ports string, timeout
|
||||
totalTasks := iter.Total()
|
||||
session.LogDebug(i18n.Tr("port_scan_debug_total_tasks", totalTasks))
|
||||
|
||||
// 使用传入的配置
|
||||
// 并发参数(已由 EnvironmentProfile.TuneConfig 调整过)
|
||||
threadNum := config.ThreadNum
|
||||
|
||||
// 大规模扫描警告和线程数自动调整
|
||||
// 大规模扫描额外约束
|
||||
if totalTasks > 100000 {
|
||||
session.LogInfo(i18n.Tr("large_scan_notice", totalTasks, len(hosts), len(portList)))
|
||||
// 如果任务数超过100万且线程数大于300,自动降低线程数
|
||||
if totalTasks > 1000000 && threadNum > 300 {
|
||||
oldThreadNum := threadNum
|
||||
threadNum = 300
|
||||
@@ -211,14 +210,14 @@ func EnhancedPortScan(ctx context.Context, hosts []string, ports string, timeout
|
||||
// 初始化并发控制
|
||||
to := time.Duration(timeout) * time.Second
|
||||
adaptiveTO := NewAdaptiveTimeout(to)
|
||||
metrics := &ScanMetrics{}
|
||||
var count atomic.Int64
|
||||
collector := newResultCollector(stream)
|
||||
failedCollector := &failedPortCollector{}
|
||||
var wg sync.WaitGroup
|
||||
|
||||
session.LogDebug(i18n.Tr("port_scan_debug_pool_create", threadNum))
|
||||
// 创建自适应线程池(支持动态调整)
|
||||
pool, err := NewAdaptivePool(threadNum, func(task interface{}) {
|
||||
pool, err := NewAdaptivePool(threadNum, threadNum, func(task interface{}) {
|
||||
taskInfo, ok := task.(portScanTask)
|
||||
if !ok {
|
||||
return
|
||||
@@ -228,9 +227,9 @@ func EnhancedPortScan(ctx context.Context, hosts []string, ports string, timeout
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
scanSinglePort(ctx, taskInfo.host, taskInfo.port, taskInfo.addr, adaptiveTO, &count, collector, failedCollector, session)
|
||||
scanSinglePort(ctx, taskInfo.host, taskInfo.port, taskInfo.addr, adaptiveTO, metrics, &count, collector, failedCollector, session)
|
||||
common.UpdateProgressBar(1)
|
||||
}, state)
|
||||
}, metrics)
|
||||
if err != nil {
|
||||
session.LogError(i18n.Tr("thread_pool_create_failed", err))
|
||||
if stream != nil {
|
||||
@@ -242,7 +241,7 @@ func EnhancedPortScan(ctx context.Context, hosts []string, ports string, timeout
|
||||
defer pool.Release()
|
||||
|
||||
session.LogDebug(i18n.GetText("port_scan_debug_schedule_start"))
|
||||
// 滑动窗口调度:维护固定数量的"飞行中"任务
|
||||
// 滑动窗口调度
|
||||
slidingWindowSchedule(iter, pool, &wg, threadNum)
|
||||
session.LogDebug(i18n.GetText("port_scan_debug_schedule_done"))
|
||||
|
||||
@@ -482,17 +481,28 @@ func buildWebServiceURL(addr string, serviceInfo *ServiceInfo) string {
|
||||
}
|
||||
|
||||
// scanSinglePort 扫描单个端口并进行服务识别(重构后的简洁版本)
|
||||
func scanSinglePort(ctx context.Context, host string, port int, addr string, adaptiveTO *AdaptiveTimeout, count *atomic.Int64, collector *resultCollector, failedCollector *failedPortCollector, session *common.ScanSession) {
|
||||
func scanSinglePort(ctx context.Context, host string, port int, addr string, adaptiveTO *AdaptiveTimeout, metrics *ScanMetrics, count *atomic.Int64, collector *resultCollector, failedCollector *failedPortCollector, session *common.ScanSession) {
|
||||
config := session.Config
|
||||
timeout := adaptiveTO.Timeout()
|
||||
// 步骤1:建立连接
|
||||
start := time.Now()
|
||||
conn, err := connectWithRetry(ctx, session, addr, timeout, 2)
|
||||
if err != nil {
|
||||
rtt := time.Since(start)
|
||||
switch {
|
||||
case isResourceExhaustedError(err):
|
||||
metrics.RecordExhausted()
|
||||
case isTimeoutError(err):
|
||||
metrics.RecordTimeout()
|
||||
default:
|
||||
metrics.RecordRefused(rtt)
|
||||
}
|
||||
handleConnectionFailure(err, host, port, addr, failedCollector)
|
||||
return
|
||||
}
|
||||
adaptiveTO.Record(time.Since(start))
|
||||
rtt := time.Since(start)
|
||||
metrics.RecordConnect(rtt)
|
||||
adaptiveTO.Record(rtt)
|
||||
|
||||
// 步骤1.5:代理连接深度验证(防止透明代理/全回显代理的假连接问题)
|
||||
valid, verifyMethod := verifyProxyConnectionDeep(conn, addr, session)
|
||||
|
||||
Reference in New Issue
Block a user