fscan/Core/AliveScanner.go
ZacharyZcR 78f81610cd feat: 实现存活探测模式(-ao)支持快速主机存活状态检测
新增功能:
- 添加-ao参数启用存活探测模式,专注于ICMP ping检测
- 实现AliveScanner专用扫描器,提供详细统计信息
- 集成到Scanner架构,支持与其他扫描模式无缝切换
- 完善i18n国际化支持,覆盖中英文界面

技术实现:
- 新增core/AliveScanner.go实现专用存活检测逻辑
- 扩展Scanner.go选择策略支持存活探测模式
- 优化目标解析和错误处理机制
- 提供成功率、耗时等详细扫描统计

使用场景:
- 快速批量主机存活性验证
- 网络拓扑发现前期探测
- 大规模网络资产盘点预检
2025-08-07 09:28:11 +08:00

160 lines
4.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package core
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/common/i18n"
"github.com/shadow1ng/fscan/common/parsers"
"strings"
"sync"
"time"
)
/*
AliveScanner.go - 存活探测扫描器
专门用于主机存活探测仅执行ICMP/Ping检测
快速识别网络中的存活主机,不进行端口扫描。
*/
// AliveScanStrategy 存活探测扫描策略
type AliveScanStrategy struct {
*BaseScanStrategy
startTime time.Time
stats AliveStats
}
// AliveStats 存活探测统计信息
type AliveStats struct {
TotalHosts int // 总主机数
AliveHosts int // 存活主机数
DeadHosts int // 死亡主机数
ScanDuration time.Duration // 扫描耗时
SuccessRate float64 // 成功率
}
// NewAliveScanStrategy 创建新的存活探测扫描策略
func NewAliveScanStrategy() *AliveScanStrategy {
return &AliveScanStrategy{
BaseScanStrategy: NewBaseScanStrategy("存活探测", FilterNone),
startTime: time.Now(),
}
}
// Name 返回策略名称
func (s *AliveScanStrategy) Name() string {
return i18n.GetText("scan_strategy_alive_name")
}
// Description 返回策略描述
func (s *AliveScanStrategy) Description() string {
return i18n.GetText("scan_strategy_alive_desc")
}
// Execute 执行存活探测扫描策略
func (s *AliveScanStrategy) Execute(info common.HostInfo, ch *chan struct{}, wg *sync.WaitGroup) {
// 验证扫描目标
if info.Host == "" {
common.LogError(i18n.GetText("parse_error_target_empty"))
return
}
// 输出存活探测开始信息
common.LogBase(i18n.GetText("scan_alive_start"))
// 执行存活探测
s.performAliveScan(info)
// 输出统计信息
s.outputStats()
}
// performAliveScan 执行存活探测
func (s *AliveScanStrategy) performAliveScan(info common.HostInfo) {
// 解析目标主机
hosts, err := parsers.ParseIP(info.Host, common.HostsFile, common.ExcludeHosts)
if err != nil {
common.LogError(i18n.GetText("parse_error_target_failed", err))
return
}
if len(hosts) == 0 {
common.LogError(i18n.GetText("parse_error_no_hosts"))
return
}
// 初始化统计信息
s.stats.TotalHosts = len(hosts)
s.stats.AliveHosts = 0
s.stats.DeadHosts = 0
// 显示扫描信息
if len(hosts) == 1 {
common.LogBase(i18n.GetText("scan_alive_single_target", hosts[0]))
} else {
common.LogBase(i18n.GetText("scan_alive_multiple_targets", len(hosts), hosts[0]))
}
// 清空之前的存活主机记录
AliveHosts = nil
for k := range ExistHosts {
delete(ExistHosts, k)
}
// 执行存活检测
aliveList := CheckLive(hosts, false) // 使用ICMP探测
// 更新统计信息
s.stats.AliveHosts = len(aliveList)
s.stats.DeadHosts = s.stats.TotalHosts - s.stats.AliveHosts
s.stats.ScanDuration = time.Since(s.startTime)
if s.stats.TotalHosts > 0 {
s.stats.SuccessRate = float64(s.stats.AliveHosts) / float64(s.stats.TotalHosts) * 100
}
}
// outputStats 输出详细统计信息
func (s *AliveScanStrategy) outputStats() {
// 输出分隔线
common.LogBase("=" + strings.Repeat("=", 60))
// 输出扫描结果摘要
common.LogBase(i18n.GetText("scan_alive_summary_title"))
// 基础统计
common.LogBase(i18n.GetText("scan_alive_total_hosts", s.stats.TotalHosts))
common.LogBase(i18n.GetText("scan_alive_hosts_found", s.stats.AliveHosts))
common.LogBase(i18n.GetText("scan_alive_dead_hosts", s.stats.DeadHosts))
common.LogBase(i18n.GetText("scan_alive_success_rate", s.stats.SuccessRate))
common.LogBase(i18n.GetText("scan_alive_duration", s.stats.ScanDuration.Round(time.Millisecond)))
// 如果有存活主机,显示详细列表
if s.stats.AliveHosts > 0 {
common.LogBase("")
common.LogBase(i18n.GetText("scan_alive_hosts_list"))
for i, host := range AliveHosts {
common.LogSuccess(fmt.Sprintf(" [%d] %s", i+1, host))
}
}
// 输出分隔线
common.LogBase("=" + strings.Repeat("=", 60))
}
// PrepareTargets 存活探测不需要准备扫描目标
func (s *AliveScanStrategy) PrepareTargets(info common.HostInfo) []common.HostInfo {
// 存活探测不需要返回目标列表,因为它不进行后续扫描
return nil
}
// GetPlugins 存活探测不使用插件
func (s *AliveScanStrategy) GetPlugins() ([]string, bool) {
return []string{}, false
}
// IsPluginApplicable 存活探测不适用任何插件
func (s *AliveScanStrategy) IsPluginApplicable(plugin common.ScanPlugin, targetPort int, isCustomMode bool) bool {
return false
}