fscan/Core/PortDiscoveryService.go
ZacharyZcR 6c93129cb1 refactor: 重构扫描器架构优化代码复用和性能
主要改进:
- 创建BaseScanStrategy基础类提取通用功能,减少60%代码重复
- 新增PortDiscoveryService分离端口发现逻辑,提升职责清晰度
- 优化插件匹配算法,从O(n×m×p)降至O(n×p)复杂度
- 修复插件适用性判断逻辑错误,确保精确端口匹配
- 完善国际化支持,新增21个i18n消息定义
- 代码行数显著减少:LocalScanner(-50%)、ServiceScanner(-42%)、WebScanner(-44%)

技术优化:
- 组合模式替代继承,提升扩展性
- 策略模式实现插件过滤器,支持Local/Service/Web类型
- 服务分离提升可测试性和维护性
- 性能优化减少嵌套循环和重复计算

确保漏洞扫描插件列表与实际执行插件保持精确一致。
2025-08-07 09:16:03 +08:00

98 lines
2.8 KiB
Go

package core
import (
"fmt"
"github.com/shadow1ng/fscan/common"
"github.com/shadow1ng/fscan/common/i18n"
"github.com/shadow1ng/fscan/common/parsers"
"strings"
)
/*
PortDiscoveryService.go - 端口发现服务
负责主机存活检测、端口扫描等端口发现相关功能,
从ServiceScanner中分离出来提高代码可维护性。
*/
// PortDiscoveryService 端口发现服务
type PortDiscoveryService struct{}
// NewPortDiscoveryService 创建端口发现服务
func NewPortDiscoveryService() *PortDiscoveryService {
return &PortDiscoveryService{}
}
// DiscoverTargets 发现目标主机和端口
func (p *PortDiscoveryService) DiscoverTargets(hostInput string, baseInfo common.HostInfo) ([]common.HostInfo, error) {
// 解析目标主机
hosts, err := parsers.ParseIP(hostInput, common.HostsFile, common.ExcludeHosts)
if err != nil {
return nil, fmt.Errorf(i18n.GetText("parse_error_target_failed"), err)
}
var targetInfos []common.HostInfo
// 主机存活性检测和端口扫描
if len(hosts) > 0 || len(common.HostPort) > 0 {
// 主机存活检测
if p.shouldPerformLivenessCheck(hosts) {
hosts = CheckLive(hosts, false)
common.LogBase(i18n.GetText("scan_alive_hosts_count", len(hosts)))
}
// 端口扫描
alivePorts := p.discoverAlivePorts(hosts)
if len(alivePorts) > 0 {
targetInfos = p.convertToTargetInfos(alivePorts, baseInfo)
}
}
return targetInfos, nil
}
// shouldPerformLivenessCheck 判断是否需要执行存活性检测
func (p *PortDiscoveryService) shouldPerformLivenessCheck(hosts []string) bool {
return common.DisablePing == false && len(hosts) > 1
}
// discoverAlivePorts 发现存活的端口
func (p *PortDiscoveryService) discoverAlivePorts(hosts []string) []string {
var alivePorts []string
// 根据扫描模式选择端口扫描方式
if len(hosts) > 0 {
alivePorts = EnhancedPortScan(hosts, common.Ports, common.Timeout)
common.LogBase(i18n.GetText("scan_alive_ports_count", len(alivePorts)))
}
// 合并额外指定的端口
if len(common.HostPort) > 0 {
alivePorts = append(alivePorts, common.HostPort...)
alivePorts = common.RemoveDuplicate(alivePorts)
common.HostPort = nil
common.LogBase(i18n.GetText("scan_alive_ports_count", len(alivePorts)))
}
return alivePorts
}
// convertToTargetInfos 将端口列表转换为目标信息
func (p *PortDiscoveryService) convertToTargetInfos(ports []string, baseInfo common.HostInfo) []common.HostInfo {
var infos []common.HostInfo
for _, targetIP := range ports {
hostParts := strings.Split(targetIP, ":")
if len(hostParts) != 2 {
common.LogError(i18n.GetText("parse_error_invalid_target_format", targetIP))
continue
}
info := baseInfo
info.Host = hostParts[0]
info.Ports = hostParts[1]
infos = append(infos, info)
}
return infos
}