mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +08:00

- 添加-rate参数:控制每分钟最大发包次数 - 添加-maxpkts参数:控制整个程序最大发包总数 - 在所有网络操作点集成发包限制检查 - 支持端口扫描、Web检测、服务插件、POC扫描等场景 - 默认不限制,保持向后兼容性
333 lines
10 KiB
Go
333 lines
10 KiB
Go
package common
|
||
|
||
import (
|
||
"fmt"
|
||
"strings"
|
||
"sync"
|
||
"sync/atomic"
|
||
"time"
|
||
|
||
"github.com/shadow1ng/fscan/common/config"
|
||
)
|
||
|
||
/*
|
||
globals.go - 全局配置变量
|
||
|
||
直接定义全局变量,消除base包的双重声明。
|
||
*/
|
||
|
||
var (
|
||
// =============================================================================
|
||
// 核心扫描配置
|
||
// =============================================================================
|
||
|
||
ScanMode string = DefaultScanMode // 扫描模式
|
||
ThreadNum int = DefaultThreadNum // 线程数
|
||
Timeout int64 = DefaultTimeout // 超时时间
|
||
DisablePing bool = false // 禁用ping
|
||
LocalMode bool = false // 本地模式
|
||
LocalPlugin string // 本地插件选择
|
||
AliveOnly bool // 仅存活检测
|
||
DisableBrute bool // 禁用暴力破解
|
||
MaxRetries int = 3 // 最大重试次数
|
||
|
||
// =============================================================================
|
||
// 认证相关配置
|
||
// =============================================================================
|
||
|
||
Username string // 用户名
|
||
Password string // 密码
|
||
Domain string // 域
|
||
Userdict map[string][]string // 用户字典
|
||
Passwords []string // 密码列表
|
||
|
||
// =============================================================================
|
||
// 网络配置
|
||
// =============================================================================
|
||
|
||
HttpProxy string // HTTP代理
|
||
Socks5Proxy string // SOCKS5代理
|
||
WebTimeout int64 = 5 // Web超时时间
|
||
|
||
// =============================================================================
|
||
// 文件路径
|
||
// =============================================================================
|
||
|
||
SshKeyPath string // SSH密钥路径
|
||
PersistenceTargetFile string // Linux持久化目标文件
|
||
WinPEFile string // Windows PE文件
|
||
|
||
// =============================================================================
|
||
// 功能开关
|
||
// =============================================================================
|
||
|
||
NoColor bool // 禁用颜色
|
||
Silent bool // 静默模式
|
||
DisableSave bool // 禁用保存
|
||
DisableProgress bool // 禁用进度条
|
||
Language string = DefaultLanguage // 语言
|
||
LogLevel string = DefaultLogLevel // 日志级别
|
||
|
||
// =============================================================================
|
||
// 高级功能
|
||
// =============================================================================
|
||
|
||
Shellcode string // Shellcode
|
||
LocalPluginsList []string // 本地插件列表
|
||
DnsLog bool // DNS日志
|
||
ForwardShellActive bool // 正向Shell状态
|
||
ReverseShellActive bool // 反向Shell状态
|
||
Socks5ProxyActive bool // SOCKS5代理状态
|
||
|
||
// =============================================================================
|
||
// 端口和服务映射
|
||
// =============================================================================
|
||
|
||
PortMap map[int][]string // 端口到服务映射
|
||
DefaultMap []string // 默认探测器映射
|
||
|
||
// =============================================================================
|
||
// 输出控制
|
||
// =============================================================================
|
||
|
||
Outputfile string = "result.txt" // 输出文件
|
||
OutputFormat string = "txt" // 输出格式
|
||
ShowProgress bool = true // 显示进度条
|
||
StartTime time.Time // 开始时间
|
||
ProgressBar interface{} // 进度条实例
|
||
OutputMutex sync.Mutex // 输出互斥锁
|
||
|
||
// =============================================================================
|
||
// 计数器
|
||
// =============================================================================
|
||
|
||
End int64 // 结束计数器
|
||
Num int64 // 数量计数器
|
||
|
||
// 网络包计数器 - 使用原子操作确保线程安全
|
||
PacketCount int64 // 总发包数量
|
||
TCPPacketCount int64 // TCP包数量总计
|
||
TCPSuccessPacketCount int64 // TCP成功连接包数量
|
||
TCPFailedPacketCount int64 // TCP失败连接包数量
|
||
UDPPacketCount int64 // UDP包数量
|
||
HTTPPacketCount int64 // HTTP请求数量
|
||
|
||
// 发包频率控制变量
|
||
PacketRateStartTime int64 // 当前分钟的开始时间戳
|
||
PacketRateCurrentCount int64 // 当前分钟内的发包数量
|
||
PacketRateMutex sync.Mutex // 发包频率控制互斥锁
|
||
|
||
// =============================================================================
|
||
// 初始化控制
|
||
// =============================================================================
|
||
|
||
initOnce sync.Once // 确保初始化只执行一次
|
||
)
|
||
|
||
// InitGlobalConfig 初始化全局配置
|
||
func InitGlobalConfig() {
|
||
initOnce.Do(func() {
|
||
// 初始化时间
|
||
if StartTime.IsZero() {
|
||
StartTime = time.Now()
|
||
}
|
||
|
||
// 初始化映射和切片
|
||
if Userdict == nil {
|
||
Userdict = make(map[string][]string)
|
||
}
|
||
if PortMap == nil {
|
||
PortMap = make(map[int][]string)
|
||
}
|
||
if DefaultMap == nil {
|
||
DefaultMap = make([]string, 0)
|
||
}
|
||
if Passwords == nil {
|
||
Passwords = make([]string, 0)
|
||
}
|
||
|
||
// 从config模块获取字典和映射
|
||
if serviceDict := config.GetGlobalServiceDict(); serviceDict != nil {
|
||
Userdict = serviceDict.GetAllUserDicts()
|
||
Passwords = serviceDict.GetPasswords()
|
||
}
|
||
|
||
if probeMapping := config.GetGlobalProbeMapping(); probeMapping != nil {
|
||
PortMap = probeMapping.GetAllPortMappings()
|
||
DefaultMap = probeMapping.GetDefaultProbes()
|
||
}
|
||
})
|
||
}
|
||
|
||
// init 自动初始化
|
||
func init() {
|
||
InitGlobalConfig()
|
||
}
|
||
|
||
// POCInfo POC相关信息
|
||
type PocInfo struct {
|
||
Target string
|
||
PocName string
|
||
}
|
||
|
||
var Pocinfo PocInfo
|
||
|
||
// 版本信息
|
||
const version = "2.2.1"
|
||
|
||
// 日志级别常量
|
||
const (
|
||
LogLevelAll = "all"
|
||
LogLevelError = "error"
|
||
LogLevelBase = "base"
|
||
LogLevelInfo = "info"
|
||
LogLevelSuccess = "success"
|
||
LogLevelDebug = "debug"
|
||
LogLevelInfoSuccess = "info,success"
|
||
LogLevelBaseInfoSuccess = "base,info,success"
|
||
)
|
||
|
||
|
||
// LogWithProgress 已在progressmanager.go中定义,此处不重复
|
||
|
||
// =============================================================================
|
||
// 网络包计数器功能
|
||
// =============================================================================
|
||
|
||
// IncrementPacketCount 增加总包计数(原子操作)
|
||
func IncrementPacketCount() int64 {
|
||
return atomic.AddInt64(&PacketCount, 1)
|
||
}
|
||
|
||
// IncrementTCPSuccessPacketCount 增加TCP成功连接包计数(原子操作)
|
||
func IncrementTCPSuccessPacketCount() int64 {
|
||
atomic.AddInt64(&TCPSuccessPacketCount, 1)
|
||
atomic.AddInt64(&TCPPacketCount, 1)
|
||
return atomic.AddInt64(&PacketCount, 1)
|
||
}
|
||
|
||
// IncrementTCPFailedPacketCount 增加TCP失败连接包计数(原子操作)
|
||
func IncrementTCPFailedPacketCount() int64 {
|
||
atomic.AddInt64(&TCPFailedPacketCount, 1)
|
||
atomic.AddInt64(&TCPPacketCount, 1)
|
||
return atomic.AddInt64(&PacketCount, 1)
|
||
}
|
||
|
||
// IncrementUDPPacketCount 增加UDP包计数(原子操作)
|
||
func IncrementUDPPacketCount() int64 {
|
||
atomic.AddInt64(&UDPPacketCount, 1)
|
||
return atomic.AddInt64(&PacketCount, 1)
|
||
}
|
||
|
||
// IncrementHTTPPacketCount 增加HTTP包计数(原子操作)
|
||
func IncrementHTTPPacketCount() int64 {
|
||
atomic.AddInt64(&HTTPPacketCount, 1)
|
||
return atomic.AddInt64(&PacketCount, 1)
|
||
}
|
||
|
||
// GetPacketCount 获取总包计数(原子操作)
|
||
func GetPacketCount() int64 {
|
||
return atomic.LoadInt64(&PacketCount)
|
||
}
|
||
|
||
// GetTCPPacketCount 获取TCP包计数(原子操作)
|
||
func GetTCPPacketCount() int64 {
|
||
return atomic.LoadInt64(&TCPPacketCount)
|
||
}
|
||
|
||
// GetTCPSuccessPacketCount 获取TCP成功连接包计数(原子操作)
|
||
func GetTCPSuccessPacketCount() int64 {
|
||
return atomic.LoadInt64(&TCPSuccessPacketCount)
|
||
}
|
||
|
||
// GetTCPFailedPacketCount 获取TCP失败连接包计数(原子操作)
|
||
func GetTCPFailedPacketCount() int64 {
|
||
return atomic.LoadInt64(&TCPFailedPacketCount)
|
||
}
|
||
|
||
// GetUDPPacketCount 获取UDP包计数(原子操作)
|
||
func GetUDPPacketCount() int64 {
|
||
return atomic.LoadInt64(&UDPPacketCount)
|
||
}
|
||
|
||
// GetHTTPPacketCount 获取HTTP包计数(原子操作)
|
||
func GetHTTPPacketCount() int64 {
|
||
return atomic.LoadInt64(&HTTPPacketCount)
|
||
}
|
||
|
||
// ResetPacketCounters 重置所有包计数器(原子操作)
|
||
func ResetPacketCounters() {
|
||
atomic.StoreInt64(&PacketCount, 0)
|
||
atomic.StoreInt64(&TCPPacketCount, 0)
|
||
atomic.StoreInt64(&TCPSuccessPacketCount, 0)
|
||
atomic.StoreInt64(&TCPFailedPacketCount, 0)
|
||
atomic.StoreInt64(&UDPPacketCount, 0)
|
||
atomic.StoreInt64(&HTTPPacketCount, 0)
|
||
}
|
||
|
||
// =============================================================================
|
||
// 发包频率控制功能
|
||
// =============================================================================
|
||
|
||
// CanSendPacket 检查是否可以发包 - 同时检查频率限制和总数限制
|
||
// 返回值: (可以发包, 错误信息)
|
||
func CanSendPacket() (bool, string) {
|
||
// 检查总数限制
|
||
if MaxPacketCount > 0 {
|
||
currentTotal := atomic.LoadInt64(&PacketCount)
|
||
if currentTotal >= MaxPacketCount {
|
||
return false, fmt.Sprintf("已达到最大发包数量限制: %d", MaxPacketCount)
|
||
}
|
||
}
|
||
|
||
// 检查频率限制
|
||
if PacketRateLimit > 0 {
|
||
PacketRateMutex.Lock()
|
||
defer PacketRateMutex.Unlock()
|
||
|
||
currentTime := time.Now().Unix() / 60 // 当前分钟
|
||
|
||
// 如果是新的分钟,重置计数器
|
||
if PacketRateStartTime != currentTime {
|
||
PacketRateStartTime = currentTime
|
||
atomic.StoreInt64(&PacketRateCurrentCount, 0)
|
||
}
|
||
|
||
// 检查当前分钟的发包数是否超限
|
||
currentCount := atomic.LoadInt64(&PacketRateCurrentCount)
|
||
if currentCount >= PacketRateLimit {
|
||
return false, fmt.Sprintf("已达到每分钟发包频率限制: %d", PacketRateLimit)
|
||
}
|
||
|
||
// 增加当前分钟的发包计数
|
||
atomic.AddInt64(&PacketRateCurrentCount, 1)
|
||
}
|
||
|
||
return true, ""
|
||
}
|
||
|
||
// WaitForPacketLimit 等待直到可以发包 - 智能等待策略
|
||
func WaitForPacketLimit() error {
|
||
maxWaitTime := 60 * time.Second // 最大等待1分钟
|
||
startWait := time.Now()
|
||
|
||
for {
|
||
canSend, reason := CanSendPacket()
|
||
if canSend {
|
||
return nil
|
||
}
|
||
|
||
// 如果是总数限制,直接返回错误
|
||
if MaxPacketCount > 0 && strings.Contains(reason, "最大发包数量") {
|
||
return fmt.Errorf(reason)
|
||
}
|
||
|
||
// 如果等待超时,返回错误
|
||
if time.Since(startWait) > maxWaitTime {
|
||
return fmt.Errorf("等待发包权限超时: %s", reason)
|
||
}
|
||
|
||
// 短暂休眠后重试
|
||
time.Sleep(100 * time.Millisecond)
|
||
}
|
||
} |