mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-22 03:10:42 +08:00
fix: 修复实机测试发现的可靠性问题 (v2.2.0-rc.1)
- UDP 插件在 -p 指定端口时被跳过 - Redis exploit 无超时保护 / readReply 吞没非超时错误 - service_probe 连接丢失后静默成功 - SNMP 探测成功但终端无输出 - SSH 爆破不稳定 (并发过高 + 自适应超时过短 + 限流误判) - 进度条 isActive 竞态 新增 Config.ModuleTimeout() 协议级超时下限 (≥3s) 新增 ErrorTypeThrottle 限流错误分类
This commit is contained in:
@@ -21,6 +21,8 @@ const (
|
||||
defaultIntensity = 7 // 默认探测强度 (1-9)
|
||||
)
|
||||
|
||||
var errConnLost = errors.New("connection lost and reconnect failed")
|
||||
|
||||
// sslSecondProbes SSL服务二次探测的探针名称
|
||||
var sslSecondProbes = []string{"TerminalServerCookie", "TerminalServer"}
|
||||
|
||||
@@ -527,7 +529,7 @@ var defaultReadTimeoutMS = WrTimeout * 1000
|
||||
// Write 写入数据到连接
|
||||
func (i *Info) Write(msg []byte) error {
|
||||
if i.Conn == nil {
|
||||
return nil
|
||||
return errConnLost
|
||||
}
|
||||
|
||||
// 设置写入超时
|
||||
@@ -570,7 +572,7 @@ func (i *Info) Write(msg []byte) error {
|
||||
// Read 从连接读取响应
|
||||
func (i *Info) Read() ([]byte, error) {
|
||||
if i.Conn == nil {
|
||||
return nil, nil
|
||||
return nil, errConnLost
|
||||
}
|
||||
|
||||
// 设置读取超时(使用动态超时)
|
||||
|
||||
+15
-4
@@ -186,10 +186,8 @@ func (s *ServiceScanStrategy) performHostScan(ctx context.Context, session *comm
|
||||
ep.TuneConfig(config, session)
|
||||
}
|
||||
|
||||
// 仅在默认端口扫描时调度 UDP 插件(用户指定 -p 时跳过,避免不相关的 UDP 探测拖慢扫描)
|
||||
if config.Target.Ports == "" || config.Target.Ports == "all" {
|
||||
s.dispatchUDPPlugins(ctx, session, hosts, info, config, ch, wg)
|
||||
}
|
||||
// UDP 插件调度:默认端口模式全量调度,用户指定 -p 时只调度端口有交集的 UDP 插件
|
||||
s.dispatchUDPPlugins(ctx, session, hosts, info, config, ch, wg)
|
||||
s.scanHostBatch(ctx, session, hosts, info, pluginsToRun, isCustomMode, ch, wg)
|
||||
}
|
||||
|
||||
@@ -271,9 +269,22 @@ func (s *ServiceScanStrategy) dispatchUDPPlugins(ctx context.Context, session *c
|
||||
return
|
||||
}
|
||||
|
||||
// 用户指定 -p 时,只调度端口有交集的 UDP 插件
|
||||
var userPorts map[int]bool
|
||||
if config.Target.Ports != "" && config.Target.Ports != "all" {
|
||||
parsed := parsers.ParsePort(config.Target.Ports)
|
||||
userPorts = make(map[int]bool, len(parsed))
|
||||
for _, p := range parsed {
|
||||
userPorts[p] = true
|
||||
}
|
||||
}
|
||||
|
||||
for _, host := range hosts {
|
||||
for _, pluginName := range udpPlugins {
|
||||
for _, port := range plugins.GetPluginPorts(pluginName) {
|
||||
if userPorts != nil && !userPorts[port] {
|
||||
continue
|
||||
}
|
||||
target := baseInfo
|
||||
target.Host = host
|
||||
target.Port = port
|
||||
|
||||
+8
-31
@@ -7,7 +7,6 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -58,17 +57,14 @@ func DetectHTTPSchemeContext(ctx context.Context, host string, port int, config
|
||||
}
|
||||
|
||||
// 第二步:尝试国密TLS握手(GM TLS fallback)
|
||||
// 抑制 gmtls 库的 fmt.Println("handshake error") 噪声输出
|
||||
gmConn, gmErr := suppressGMTLSStdout(func() (net.Conn, error) {
|
||||
return gmtls.DialWithDialer(
|
||||
tlsDialer,
|
||||
"tcp", addr,
|
||||
&gmtls.Config{
|
||||
GMSupport: gmtls.NewGMSupport(),
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
)
|
||||
})
|
||||
gmConn, gmErr := gmtls.DialWithDialer(
|
||||
tlsDialer,
|
||||
"tcp", addr,
|
||||
&gmtls.Config{
|
||||
GMSupport: gmtls.NewGMSupport(),
|
||||
InsecureSkipVerify: true,
|
||||
},
|
||||
)
|
||||
|
||||
if gmErr == nil {
|
||||
_ = gmConn.Close()
|
||||
@@ -503,22 +499,3 @@ func hasMalformedURLPort(host string) bool {
|
||||
return strings.Contains(host, ":")
|
||||
}
|
||||
|
||||
// suppressGMTLSStdout 抑制 gmtls 库硬编码的 fmt.Println("handshake error") 输出
|
||||
// gmtls/conn.go:1304 在握手失败时直接 Println 到 os.Stdout,无法通过 API 关闭
|
||||
var gmtlsStdoutMu sync.Mutex
|
||||
|
||||
func suppressGMTLSStdout(fn func() (net.Conn, error)) (net.Conn, error) {
|
||||
gmtlsStdoutMu.Lock()
|
||||
orig := os.Stdout
|
||||
devNull, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0)
|
||||
if err == nil {
|
||||
os.Stdout = devNull
|
||||
}
|
||||
conn, dialErr := fn()
|
||||
os.Stdout = orig
|
||||
if devNull != nil {
|
||||
_ = devNull.Close()
|
||||
}
|
||||
gmtlsStdoutMu.Unlock()
|
||||
return conn, dialErr
|
||||
}
|
||||
|
||||
@@ -708,12 +708,8 @@ func TestIsWebServiceByFingerprint_Priority(t *testing.T) {
|
||||
|
||||
// TestDetectHTTPScheme 测试HTTP/HTTPS协议智能检测
|
||||
func TestDetectHTTPScheme(t *testing.T) {
|
||||
// 设置WebTimeout避免测试超时
|
||||
cfg := common.GetGlobalConfig()
|
||||
oldTimeout := cfg.Network.WebTimeout
|
||||
cfg := common.NewConfig()
|
||||
cfg.Network.WebTimeout = 2 * time.Second
|
||||
defer func() { cfg.Network.WebTimeout = oldTimeout }()
|
||||
|
||||
session := common.NewScanSession(cfg, common.NewState(), common.GetFlagVars())
|
||||
|
||||
t.Run("HTTPS服务器检测", func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user