mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00

问题: - 使用 ./fscan -h 127.0.0.1:22 时没有显示端口开放信息 - 直接跳到漏洞扫描阶段,缺少端口发现过程的可见性 - 原因:预设host:port直接return,跳过了EnhancedPortScan调用 修复方案: - 新增 validatePresetPorts 方法 - 对预设的host:port也执行端口验证和服务识别 - 调用 EnhancedPortScan 显示完整的端口开放信息 修复前: [0ms] 开始主机扫描 → [0ms] 存活端口数量: 1 → [0ms] 开始漏洞扫描 修复后: [0ms] 开始主机扫描 → [5ms] 端口开放 127.0.0.1:22 [ssh] → [5ms] 开始漏洞扫描 效果: - 保持了统一的扫描流程显示 - 用户能看到端口连通性验证过程 - 预设端口也显示服务识别结果
160 lines
4.4 KiB
Go
160 lines
4.4 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
|
||
|
||
// 如果已经有明确指定的host:port,验证连通性并显示端口信息
|
||
if len(common.HostPort) > 0 {
|
||
alivePorts = p.validatePresetPorts(common.HostPort)
|
||
alivePorts = common.RemoveDuplicate(alivePorts)
|
||
common.LogBase(i18n.GetText("scan_alive_ports_count", len(alivePorts)))
|
||
common.HostPort = nil
|
||
return alivePorts
|
||
}
|
||
|
||
// 根据扫描模式选择端口扫描方式
|
||
if len(hosts) > 0 {
|
||
alivePorts = EnhancedPortScan(hosts, common.Ports, common.Timeout)
|
||
common.LogBase(i18n.GetText("scan_alive_ports_count", len(alivePorts)))
|
||
}
|
||
|
||
// UDP端口特殊处理(当前仅支持SNMP的161端口)
|
||
udpPorts := p.handleUDPPorts(hosts)
|
||
if len(udpPorts) > 0 {
|
||
alivePorts = append(alivePorts, udpPorts...)
|
||
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
|
||
}
|
||
|
||
// handleUDPPorts 处理UDP端口的特殊逻辑
|
||
func (p *PortDiscoveryService) handleUDPPorts(hosts []string) []string {
|
||
var udpPorts []string
|
||
|
||
// 检查是否包含SNMP端口161
|
||
portList := parsers.ParsePort(common.Ports)
|
||
hasPort161 := false
|
||
for _, port := range portList {
|
||
if port == 161 {
|
||
hasPort161 = true
|
||
break
|
||
}
|
||
}
|
||
|
||
// 如果端口列表包含161,则为每个主机添加UDP 161端口
|
||
if hasPort161 {
|
||
for _, host := range hosts {
|
||
udpPorts = append(udpPorts, fmt.Sprintf("%s:161", host))
|
||
}
|
||
if len(udpPorts) > 0 {
|
||
common.LogBase(i18n.GetText("scan_snmp_udp_ports_added"))
|
||
}
|
||
}
|
||
|
||
return udpPorts
|
||
}
|
||
|
||
// validatePresetPorts 验证预设的host:port并显示端口信息(模拟端口扫描过程)
|
||
func (p *PortDiscoveryService) validatePresetPorts(hostPorts []string) []string {
|
||
var validPorts []string
|
||
|
||
for _, hostPort := range hostPorts {
|
||
// 解析host:port
|
||
hostParts := strings.Split(hostPort, ":")
|
||
if len(hostParts) != 2 {
|
||
continue
|
||
}
|
||
|
||
host := hostParts[0]
|
||
port := hostParts[1]
|
||
|
||
// 模拟单端口扫描,显示端口开放信息和服务识别
|
||
mockHosts := []string{host}
|
||
portResult := EnhancedPortScan(mockHosts, port, common.Timeout)
|
||
|
||
// 如果端口验证成功,添加到结果中
|
||
if len(portResult) > 0 {
|
||
validPorts = append(validPorts, portResult...)
|
||
}
|
||
}
|
||
|
||
return validPorts
|
||
} |