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

- 修复目标地址验证逻辑,支持host:port格式的直接输入 - 优化端口扫描流程,对明确指定的host:port跳过不必要的端口扫描 - 改进主机地址解析,智能识别和处理host:port格式 - 统一端口扫描结果显示,避免显示不一致问题 - 增强用户体验,支持 -h 127.0.0.1:135 等便捷格式
133 lines
3.7 KiB
Go
133 lines
3.7 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 = append(alivePorts, 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
|
||
} |