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 }