mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-27 05:31:53 +08:00
perf: 三阶段性能优化,ICMP 并发提升+TCP 并行探测,端口扫描退避调整,服务探测超时减半
This commit is contained in:
+28
-10
@@ -473,8 +473,12 @@ func icmpalive(host string) bool {
|
|||||||
// RunPing 使用系统Ping命令并发探测主机存活
|
// RunPing 使用系统Ping命令并发探测主机存活
|
||||||
func RunPing(hostslist []string, chanHosts chan string, livewg *sync.WaitGroup) {
|
func RunPing(hostslist []string, chanHosts chan string, livewg *sync.WaitGroup) {
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
// 限制并发数为50
|
// 并发数根据主机数动态调整,上限 200
|
||||||
limiter := make(chan struct{}, 50)
|
concurrency := len(hostslist)
|
||||||
|
if concurrency > 200 {
|
||||||
|
concurrency = 200
|
||||||
|
}
|
||||||
|
limiter := make(chan struct{}, concurrency)
|
||||||
|
|
||||||
// 并发探测
|
// 并发探测
|
||||||
for _, host := range hostslist {
|
for _, host := range hostslist {
|
||||||
@@ -677,20 +681,34 @@ func ArrayCountValueTop(arrInit []string, length int, flag bool) (arrTop []strin
|
|||||||
var tcpProbeCommonPorts = []int{80, 443, 22, 445}
|
var tcpProbeCommonPorts = []int{80, 443, 22, 445}
|
||||||
|
|
||||||
// tcpProbeTimeout TCP 探测超时时间(较短,只做存活判断)
|
// tcpProbeTimeout TCP 探测超时时间(较短,只做存活判断)
|
||||||
const tcpProbeTimeout = 2 * time.Second
|
const tcpProbeTimeout = 1 * time.Second
|
||||||
|
|
||||||
// tcpProbeThreshold TCP 补充探测触发阈值
|
// tcpProbeThreshold TCP 补充探测触发阈值
|
||||||
// 当 ICMP 响应率低于此值时,自动启用 TCP 补充探测
|
// 当 ICMP 响应率低于此值时,自动启用 TCP 补充探测
|
||||||
const tcpProbeThreshold = 0.1 // 10%
|
const tcpProbeThreshold = 0.1 // 10%
|
||||||
|
|
||||||
// tcpProbeAlive 使用 TCP 探测主机是否存活
|
// tcpProbeAlive 使用 TCP 并行探测主机是否存活
|
||||||
// 尝试连接常用端口,任一端口响应即认为存活
|
// 同时连接所有常用端口,任一响应即返回
|
||||||
func tcpProbeAlive(ctx context.Context, session *common.ScanSession, host string) bool {
|
func tcpProbeAlive(ctx context.Context, session *common.ScanSession, host string) bool {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
result := make(chan bool, len(tcpProbeCommonPorts))
|
||||||
for _, port := range tcpProbeCommonPorts {
|
for _, port := range tcpProbeCommonPorts {
|
||||||
addr := fmt.Sprintf("%s:%d", host, port)
|
go func(p int) {
|
||||||
|
addr := fmt.Sprintf("%s:%d", host, p)
|
||||||
conn, err := session.DialTCP(ctx, "tcp", addr, tcpProbeTimeout)
|
conn, err := session.DialTCP(ctx, "tcp", addr, tcpProbeTimeout)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
|
result <- true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result <- false
|
||||||
|
}(port)
|
||||||
|
}
|
||||||
|
|
||||||
|
for range tcpProbeCommonPorts {
|
||||||
|
if <-result {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -709,10 +727,10 @@ func runTcpProbeForHosts(ctx context.Context, hosts []string, session *common.Sc
|
|||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
aliveHosts := make([]string, 0)
|
aliveHosts := make([]string, 0)
|
||||||
|
|
||||||
// 并发控制,避免资源耗尽
|
// 并发控制,根据主机数动态调整,上限 200
|
||||||
concurrency := 50
|
concurrency := len(hosts)
|
||||||
if len(hosts) < concurrency {
|
if concurrency > 200 {
|
||||||
concurrency = len(hosts)
|
concurrency = 200
|
||||||
}
|
}
|
||||||
limiter := make(chan struct{}, concurrency)
|
limiter := make(chan struct{}, concurrency)
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -286,9 +286,9 @@ func connectWithRetry(ctx context.Context, session *common.ScanSession, addr str
|
|||||||
// 记录资源耗尽错误
|
// 记录资源耗尽错误
|
||||||
session.State.IncrementResourceExhaustedCount()
|
session.State.IncrementResourceExhaustedCount()
|
||||||
|
|
||||||
// 指数退避:第1次等50ms,第2次等150ms
|
// 指数退避:200ms → 600ms → 1200ms
|
||||||
if attempt < maxRetries-1 {
|
if attempt < maxRetries-1 {
|
||||||
waitTime := time.Duration(50*(attempt+1)) * time.Millisecond
|
waitTime := time.Duration(200*(1<<uint(attempt))) * time.Millisecond
|
||||||
time.Sleep(waitTime)
|
time.Sleep(waitTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,7 +350,7 @@ func buildServiceLogMessage(addr string, serviceInfo *ServiceInfo, isWeb bool) s
|
|||||||
func scanSinglePort(ctx context.Context, host string, port int, addr string, timeout time.Duration, count *int64, collector *resultCollector, failedCollector *failedPortCollector, session *common.ScanSession) {
|
func scanSinglePort(ctx context.Context, host string, port int, addr string, timeout time.Duration, count *int64, collector *resultCollector, failedCollector *failedPortCollector, session *common.ScanSession) {
|
||||||
config := session.Config
|
config := session.Config
|
||||||
// 步骤1:建立连接
|
// 步骤1:建立连接
|
||||||
conn, err := connectWithRetry(ctx, session, addr, timeout, 3)
|
conn, err := connectWithRetry(ctx, session, addr, timeout, 2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleConnectionFailure(err, host, port, addr, failedCollector)
|
handleConnectionFailure(err, host, port, addr, failedCollector)
|
||||||
return
|
return
|
||||||
@@ -369,7 +369,7 @@ func scanSinglePort(ctx context.Context, host string, port int, addr string, tim
|
|||||||
if common.IsProxyEnabled() && verifyMethod != "direct" {
|
if common.IsProxyEnabled() && verifyMethod != "direct" {
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
// 重新建立干净的连接用于服务识别
|
// 重新建立干净的连接用于服务识别
|
||||||
conn, err = connectWithRetry(ctx, session, addr, timeout, 3)
|
conn, err = connectWithRetry(ctx, session, addr, timeout, 2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handleConnectionFailure(err, host, port, addr, failedCollector)
|
handleConnectionFailure(err, host, port, addr, failedCollector)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
// 默认超时时间常量
|
// 默认超时时间常量
|
||||||
const (
|
const (
|
||||||
defaultTotalWaitMS = 6000 // Nmap 默认等待时间
|
defaultTotalWaitMS = 3000 // 服务探测默认等待时间
|
||||||
defaultIntensity = 7 // 默认探测强度 (1-9)
|
defaultIntensity = 7 // 默认探测强度 (1-9)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -176,8 +176,8 @@ func TestSmartPortInfoScanner_Creation(t *testing.T) {
|
|||||||
// TestDefaultConstants 验证默认常量值
|
// TestDefaultConstants 验证默认常量值
|
||||||
func TestDefaultConstants(t *testing.T) {
|
func TestDefaultConstants(t *testing.T) {
|
||||||
// 验证默认等待时间
|
// 验证默认等待时间
|
||||||
if defaultTotalWaitMS != 6000 {
|
if defaultTotalWaitMS != 3000 {
|
||||||
t.Errorf("defaultTotalWaitMS 应该是 6000,实际是 %d", defaultTotalWaitMS)
|
t.Errorf("defaultTotalWaitMS 应该是 3000,实际是 %d", defaultTotalWaitMS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 验证默认 intensity
|
// 验证默认 intensity
|
||||||
|
|||||||
Reference in New Issue
Block a user