mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-24 12:11:52 +08:00
refactor: 全量替换 WrapperTcpWithTimeout 为 session.DialTCP (Phase 4)
- core/port_scan.go: EnhancedPortScan/connectWithRetry/scanSinglePort 接入 session - core/service_probe.go: SmartPortInfoScanner 持有 session,重连走 session.DialTCP - core/icmp.go: CheckLive/tcpProbeAlive 接入 session - 17 个 service 插件: 内部 helper 函数全部穿透 ctx+session - 移除插件中冗余的手动 TCP 计数(DialTCP 内部已处理) - plugins/core 下已无 WrapperTcpWithTimeout/SafeTCPDial 调用残留
This commit is contained in:
@@ -62,14 +62,14 @@ func (s *AliveScanStrategy) Execute(_ context.Context, session *common.ScanSessi
|
||||
}
|
||||
|
||||
// 执行存活探测
|
||||
s.performAliveScan(info, session.Config, session.State)
|
||||
s.performAliveScan(info, session)
|
||||
|
||||
// 输出统计信息
|
||||
s.outputStats()
|
||||
}
|
||||
|
||||
// performAliveScan 执行存活探测
|
||||
func (s *AliveScanStrategy) performAliveScan(info common.HostInfo, config *common.Config, state *common.State) {
|
||||
func (s *AliveScanStrategy) performAliveScan(info common.HostInfo, session *common.ScanSession) {
|
||||
// 解析目标主机
|
||||
fv := common.GetFlagVars()
|
||||
hosts, err := parsers.ParseIP(info.Host, fv.HostsFile, fv.ExcludeHosts)
|
||||
@@ -90,7 +90,7 @@ func (s *AliveScanStrategy) performAliveScan(info common.HostInfo, config *commo
|
||||
|
||||
|
||||
// 执行存活检测
|
||||
aliveList := CheckLive(hosts, false, config, state) // 使用ICMP探测
|
||||
aliveList := CheckLive(hosts, false, session) // 使用ICMP探测
|
||||
|
||||
// 更新统计信息
|
||||
s.stats.AliveHosts = len(aliveList)
|
||||
|
||||
+12
-8
@@ -2,6 +2,7 @@ package core
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
@@ -39,7 +40,9 @@ var pingErrorKeywords = []string{
|
||||
|
||||
// CheckLive 检测主机存活状态
|
||||
// 支持 ICMP/Ping 探测,并在响应率过低时自动启用 TCP 补充探测
|
||||
func CheckLive(hostslist []string, Ping bool, config *common.Config, state *common.State) []string {
|
||||
func CheckLive(hostslist []string, Ping bool, session *common.ScanSession) []string {
|
||||
config := session.Config
|
||||
state := session.State
|
||||
// 创建局部WaitGroup
|
||||
var livewg sync.WaitGroup
|
||||
|
||||
@@ -68,7 +71,7 @@ func CheckLive(hostslist []string, Ping bool, config *common.Config, state *comm
|
||||
|
||||
// TCP 补充探测:当 ICMP/Ping 响应率过低时自动启用
|
||||
// 这对防火墙过滤 ICMP 的环境特别有用
|
||||
aliveHosts = tcpSupplementaryProbe(hostslist, aliveHosts, config)
|
||||
aliveHosts = tcpSupplementaryProbe(hostslist, aliveHosts, session)
|
||||
|
||||
// 输出存活统计信息
|
||||
printAliveStats(aliveHosts, hostslist)
|
||||
@@ -78,7 +81,7 @@ func CheckLive(hostslist []string, Ping bool, config *common.Config, state *comm
|
||||
|
||||
// tcpSupplementaryProbe TCP 补充探测
|
||||
// 当 ICMP 响应率过低时(<10%),对未响应主机进行 TCP 探测
|
||||
func tcpSupplementaryProbe(allHosts []string, aliveHosts []string, config *common.Config) []string {
|
||||
func tcpSupplementaryProbe(allHosts []string, aliveHosts []string, session *common.ScanSession) []string {
|
||||
totalHosts := len(allHosts)
|
||||
if totalHosts == 0 {
|
||||
return aliveHosts
|
||||
@@ -102,7 +105,7 @@ func tcpSupplementaryProbe(allHosts []string, aliveHosts []string, config *commo
|
||||
common.LogInfo(i18n.Tr("tcp_probe_low_icmp_rate", fmt.Sprintf("%.1f%%", responseRate*100), len(unrespondedHosts)))
|
||||
|
||||
// 执行 TCP 补充探测
|
||||
tcpAliveHosts := runTcpProbeForHosts(unrespondedHosts, config)
|
||||
tcpAliveHosts := runTcpProbeForHosts(unrespondedHosts, session)
|
||||
|
||||
// 合并结果
|
||||
if len(tcpAliveHosts) > 0 {
|
||||
@@ -682,10 +685,10 @@ const tcpProbeThreshold = 0.1 // 10%
|
||||
|
||||
// tcpProbeAlive 使用 TCP 探测主机是否存活
|
||||
// 尝试连接常用端口,任一端口响应即认为存活
|
||||
func tcpProbeAlive(host string) bool {
|
||||
func tcpProbeAlive(session *common.ScanSession, host string) bool {
|
||||
for _, port := range tcpProbeCommonPorts {
|
||||
addr := fmt.Sprintf("%s:%d", host, port)
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", addr, tcpProbeTimeout)
|
||||
conn, err := session.DialTCP(context.Background(), "tcp", addr, tcpProbeTimeout)
|
||||
if err == nil {
|
||||
_ = conn.Close()
|
||||
return true
|
||||
@@ -696,7 +699,8 @@ func tcpProbeAlive(host string) bool {
|
||||
|
||||
// runTcpProbeForHosts 对指定主机列表进行 TCP 补充探测
|
||||
// 返回存活的主机列表
|
||||
func runTcpProbeForHosts(hosts []string, config *common.Config) []string {
|
||||
func runTcpProbeForHosts(hosts []string, session *common.ScanSession) []string {
|
||||
config := session.Config
|
||||
if len(hosts) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -722,7 +726,7 @@ func runTcpProbeForHosts(hosts []string, config *common.Config) []string {
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
if tcpProbeAlive(h) {
|
||||
if tcpProbeAlive(session, h) {
|
||||
mu.Lock()
|
||||
aliveHosts = append(aliveHosts, h)
|
||||
mu.Unlock()
|
||||
|
||||
+13
-9
@@ -1,6 +1,7 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -110,7 +111,9 @@ func (f *failedPortCollector) Count() int {
|
||||
|
||||
// EnhancedPortScan 高性能端口扫描函数
|
||||
// 使用滑动窗口调度 + 自适应线程池 + 流式迭代器
|
||||
func EnhancedPortScan(hosts []string, ports string, timeout int64, config *common.Config, state *common.State) []string {
|
||||
func EnhancedPortScan(hosts []string, ports string, timeout int64, session *common.ScanSession) []string {
|
||||
config := session.Config
|
||||
state := session.State
|
||||
common.LogDebug(fmt.Sprintf("[PortScan] 开始: %d个主机, 线程数=%d", len(hosts), config.ThreadNum))
|
||||
|
||||
// 解析端口和排除端口
|
||||
@@ -179,7 +182,7 @@ func EnhancedPortScan(hosts []string, ports string, timeout int64, config *commo
|
||||
}()
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", taskInfo.host, taskInfo.port)
|
||||
scanSinglePort(taskInfo.host, taskInfo.port, addr, to, &count, collector, failedCollector, config, state)
|
||||
scanSinglePort(taskInfo.host, taskInfo.port, addr, to, &count, collector, failedCollector, session)
|
||||
common.UpdateProgressBar(1)
|
||||
}, state)
|
||||
if err != nil {
|
||||
@@ -263,11 +266,11 @@ func slidingWindowSchedule(iter *SocketIterator, pool *AdaptivePool, wg *sync.Wa
|
||||
}
|
||||
|
||||
// connectWithRetry 带重试的TCP连接 - 只对资源耗尽错误重试
|
||||
func connectWithRetry(addr string, timeout time.Duration, maxRetries int, state *common.State) (net.Conn, error) {
|
||||
func connectWithRetry(ctx context.Context, session *common.ScanSession, addr string, timeout time.Duration, maxRetries int) (net.Conn, error) {
|
||||
var lastErr error
|
||||
|
||||
for attempt := 0; attempt < maxRetries; attempt++ {
|
||||
conn, err := common.WrapperTcpWithTimeout("tcp", addr, timeout)
|
||||
conn, err := session.DialTCP(ctx, "tcp", addr, timeout)
|
||||
|
||||
if err == nil {
|
||||
return conn, nil
|
||||
@@ -281,7 +284,7 @@ func connectWithRetry(addr string, timeout time.Duration, maxRetries int, state
|
||||
}
|
||||
|
||||
// 记录资源耗尽错误
|
||||
state.IncrementResourceExhaustedCount()
|
||||
session.State.IncrementResourceExhaustedCount()
|
||||
|
||||
// 指数退避:第1次等50ms,第2次等150ms
|
||||
if attempt < maxRetries-1 {
|
||||
@@ -344,9 +347,10 @@ func buildServiceLogMessage(addr string, serviceInfo *ServiceInfo, isWeb bool) s
|
||||
}
|
||||
|
||||
// scanSinglePort 扫描单个端口并进行服务识别(重构后的简洁版本)
|
||||
func scanSinglePort(host string, port int, addr string, timeout time.Duration, count *int64, collector *resultCollector, failedCollector *failedPortCollector, config *common.Config, state *common.State) {
|
||||
func scanSinglePort(host string, port int, addr string, timeout time.Duration, count *int64, collector *resultCollector, failedCollector *failedPortCollector, session *common.ScanSession) {
|
||||
config := session.Config
|
||||
// 步骤1:建立连接
|
||||
conn, err := connectWithRetry(addr, timeout, 3, state)
|
||||
conn, err := connectWithRetry(context.Background(), session, addr, timeout, 3)
|
||||
if err != nil {
|
||||
handleConnectionFailure(err, host, port, addr, failedCollector)
|
||||
return
|
||||
@@ -365,7 +369,7 @@ func scanSinglePort(host string, port int, addr string, timeout time.Duration, c
|
||||
if common.IsProxyEnabled() && verifyMethod != "direct" {
|
||||
_ = conn.Close()
|
||||
// 重新建立干净的连接用于服务识别
|
||||
conn, err = connectWithRetry(addr, timeout, 3, state)
|
||||
conn, err = connectWithRetry(context.Background(), session, addr, timeout, 3)
|
||||
if err != nil {
|
||||
handleConnectionFailure(err, host, port, addr, failedCollector)
|
||||
return
|
||||
@@ -378,7 +382,7 @@ func scanSinglePort(host string, port int, addr string, timeout time.Duration, c
|
||||
saveOpenPort(host, port)
|
||||
|
||||
// 步骤3:服务识别(Scanner负责关闭连接,包括探测中可能创建的新连接)
|
||||
scanner := NewSmartPortInfoScanner(host, port, conn, timeout, config)
|
||||
scanner := NewSmartPortInfoScanner(host, port, conn, timeout, config, session)
|
||||
defer scanner.Close()
|
||||
serviceInfo, _ := scanner.SmartIdentify()
|
||||
|
||||
|
||||
+16
-11
@@ -1,6 +1,7 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@@ -70,13 +71,14 @@ type Service struct {
|
||||
|
||||
// Info 定义单个端口探测的上下文信息
|
||||
type Info struct {
|
||||
Address string // 目标IP地址
|
||||
Port int // 目标端口
|
||||
Conn net.Conn // 网络连接
|
||||
Result Result // 探测结果
|
||||
Found bool // 是否成功识别服务
|
||||
config *common.Config // 配置引用
|
||||
readTimeoutMS int // 当前读取超时时间(毫秒)
|
||||
Address string // 目标IP地址
|
||||
Port int // 目标端口
|
||||
Conn net.Conn // 网络连接
|
||||
Result Result // 探测结果
|
||||
Found bool // 是否成功识别服务
|
||||
config *common.Config // 配置引用
|
||||
session *common.ScanSession // 会话引用
|
||||
readTimeoutMS int // 当前读取超时时间(毫秒)
|
||||
}
|
||||
|
||||
// SmartPortInfoScanner 智能服务识别器:保持nmap准确性,优化网络交互
|
||||
@@ -86,24 +88,27 @@ type SmartPortInfoScanner struct {
|
||||
Conn net.Conn
|
||||
Timeout time.Duration
|
||||
info *Info
|
||||
config *common.Config // 配置引用
|
||||
config *common.Config // 配置引用
|
||||
session *common.ScanSession // 会话引用
|
||||
}
|
||||
|
||||
// 预定义的基础探测器已在PortFinger.go中定义,这里不再重复定义
|
||||
|
||||
// NewSmartPortInfoScanner 创建智能服务识别器
|
||||
func NewSmartPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration, config *common.Config) *SmartPortInfoScanner {
|
||||
func NewSmartPortInfoScanner(addr string, port int, conn net.Conn, timeout time.Duration, config *common.Config, session *common.ScanSession) *SmartPortInfoScanner {
|
||||
return &SmartPortInfoScanner{
|
||||
Address: addr,
|
||||
Port: port,
|
||||
Conn: conn,
|
||||
Timeout: timeout,
|
||||
config: config,
|
||||
session: session,
|
||||
info: &Info{
|
||||
Address: addr,
|
||||
Port: port,
|
||||
Conn: conn,
|
||||
config: config,
|
||||
session: session,
|
||||
Result: Result{
|
||||
Service: Service{},
|
||||
},
|
||||
@@ -251,7 +256,7 @@ func (s *SmartPortInfoScanner) reconnectIfNeeded() {
|
||||
}
|
||||
|
||||
// 重新建立连接
|
||||
newConn, err := common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%d", s.Address, s.Port), s.Timeout)
|
||||
newConn, err := s.session.DialTCP(context.Background(), "tcp", fmt.Sprintf("%s:%d", s.Address, s.Port), s.Timeout)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -511,7 +516,7 @@ func (i *Info) Write(msg []byte) error {
|
||||
_ = oldConn.Close()
|
||||
|
||||
// 尝试重新连接 - 支持SOCKS5代理
|
||||
newConn, retryErr := common.WrapperTcpWithTimeout("tcp", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second)
|
||||
newConn, retryErr := i.session.DialTCP(context.Background(), "tcp", fmt.Sprintf("%s:%d", i.Address, i.Port), time.Duration(6)*time.Second)
|
||||
if retryErr != nil {
|
||||
return retryErr
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ func TestSmartPortInfoScanner_Creation(t *testing.T) {
|
||||
}
|
||||
|
||||
// 使用 nil 连接(实际测试中会使用真实连接)
|
||||
scanner := NewSmartPortInfoScanner("127.0.0.1", 80, nil, 3*time.Second, config)
|
||||
scanner := NewSmartPortInfoScanner("127.0.0.1", 80, nil, 3*time.Second, config, nil)
|
||||
|
||||
if scanner == nil {
|
||||
t.Fatal("Scanner 创建失败")
|
||||
|
||||
+12
-8
@@ -141,7 +141,7 @@ func (s *ServiceScanStrategy) Execute(ctx context.Context, session *common.ScanS
|
||||
// performHostScan 执行主机扫描的完整流程
|
||||
func (s *ServiceScanStrategy) performHostScan(ctx context.Context, session *common.ScanSession, info common.HostInfo, ch chan struct{}, wg *sync.WaitGroup) {
|
||||
// 发现目标主机和端口
|
||||
targetInfos, err := s.discoverTargets(info.Host, info, session.Config, session.State)
|
||||
targetInfos, err := s.discoverTargets(info.Host, info, session)
|
||||
if err != nil {
|
||||
common.LogError(err.Error())
|
||||
return
|
||||
@@ -154,9 +154,9 @@ func (s *ServiceScanStrategy) performHostScan(ctx context.Context, session *comm
|
||||
}
|
||||
|
||||
// PrepareTargets 准备目标信息
|
||||
func (s *ServiceScanStrategy) PrepareTargets(info common.HostInfo, config *common.Config, state *common.State) []common.HostInfo {
|
||||
func (s *ServiceScanStrategy) PrepareTargets(info common.HostInfo, session *common.ScanSession) []common.HostInfo {
|
||||
// 发现目标主机和端口
|
||||
targetInfos, err := s.discoverTargets(info.Host, info, config, state)
|
||||
targetInfos, err := s.discoverTargets(info.Host, info, session)
|
||||
if err != nil {
|
||||
common.LogError(err.Error())
|
||||
return nil
|
||||
@@ -215,7 +215,9 @@ func (s *ServiceScanStrategy) LogVulnerabilityPluginInfo(targets []common.HostIn
|
||||
// =============================================================================
|
||||
|
||||
// discoverTargets 发现目标主机和端口
|
||||
func (s *ServiceScanStrategy) discoverTargets(hostInput string, baseInfo common.HostInfo, config *common.Config, state *common.State) ([]common.HostInfo, error) {
|
||||
func (s *ServiceScanStrategy) discoverTargets(hostInput string, baseInfo common.HostInfo, session *common.ScanSession) ([]common.HostInfo, error) {
|
||||
config := session.Config
|
||||
state := session.State
|
||||
// 标准流程:解析目标主机
|
||||
fv := common.GetFlagVars()
|
||||
hosts, err := parsers.ParseIP(hostInput, fv.HostsFile, fv.ExcludeHosts)
|
||||
@@ -229,12 +231,12 @@ func (s *ServiceScanStrategy) discoverTargets(hostInput string, baseInfo common.
|
||||
if len(hosts) > 0 || len(state.GetHostPorts()) > 0 {
|
||||
// 主机存活检测
|
||||
if s.shouldPerformLivenessCheck(hosts, config) {
|
||||
hosts = CheckLive(hosts, false, config, state)
|
||||
hosts = CheckLive(hosts, false, session)
|
||||
common.LogInfo(i18n.Tr("alive_hosts_count_info", len(hosts)))
|
||||
}
|
||||
|
||||
// 端口扫描
|
||||
alivePorts := s.discoverAlivePorts(hosts, config, state)
|
||||
alivePorts := s.discoverAlivePorts(hosts, session)
|
||||
if len(alivePorts) > 0 {
|
||||
targetInfos = s.convertToTargetInfos(alivePorts, baseInfo)
|
||||
}
|
||||
@@ -249,7 +251,9 @@ func (s *ServiceScanStrategy) shouldPerformLivenessCheck(hosts []string, config
|
||||
}
|
||||
|
||||
// discoverAlivePorts 发现存活的端口
|
||||
func (s *ServiceScanStrategy) discoverAlivePorts(hosts []string, config *common.Config, state *common.State) []string {
|
||||
func (s *ServiceScanStrategy) discoverAlivePorts(hosts []string, session *common.ScanSession) []string {
|
||||
config := session.Config
|
||||
state := session.State
|
||||
var alivePorts []string
|
||||
|
||||
// 如果已经有明确指定的host:port,直接使用(让后续SmartIdentify统一验证和识别)
|
||||
@@ -263,7 +267,7 @@ func (s *ServiceScanStrategy) discoverAlivePorts(hosts []string, config *common.
|
||||
|
||||
// 根据扫描模式选择端口扫描方式
|
||||
if len(hosts) > 0 {
|
||||
alivePorts = EnhancedPortScan(hosts, config.Target.Ports, int64(config.Timeout.Seconds()), config, state)
|
||||
alivePorts = EnhancedPortScan(hosts, config.Target.Ports, int64(config.Timeout.Seconds()), session)
|
||||
}
|
||||
|
||||
return alivePorts
|
||||
|
||||
Reference in New Issue
Block a user