feat: 增强目标解析功能支持host:port格式

- 修复目标地址验证逻辑,支持host:port格式的直接输入
- 优化端口扫描流程,对明确指定的host:port跳过不必要的端口扫描
- 改进主机地址解析,智能识别和处理host:port格式
- 统一端口扫描结果显示,避免显示不一致问题
- 增强用户体验,支持 -h 127.0.0.1:135 等便捷格式
This commit is contained in:
ZacharyZcR 2025-08-12 17:20:35 +08:00
parent cc4f55374a
commit 2703ddd9ed
2 changed files with 68 additions and 11 deletions

View File

@ -197,11 +197,31 @@ func (tp *TargetParser) parseHosts(input *TargetInput) ([]string, []error, []str
}
}
// 去重和验证
// 去重和验证同时分离host:port格式
hosts = tp.removeDuplicateStrings(hosts)
validHosts := make([]string, 0, len(hosts))
hostPorts := make([]string, 0)
for _, host := range hosts {
// 检查是否为host:port格式
if strings.Contains(host, ":") {
if h, portStr, err := net.SplitHostPort(host); err == nil {
// 验证端口号
if port, portErr := strconv.Atoi(portStr); portErr == nil && port >= MinPort && port <= MaxPort {
// 验证主机部分
if valid, hostErr := tp.validateHost(h); valid {
// 这是有效的host:port组合添加到hostPorts
hostPorts = append(hostPorts, host)
continue
} else if hostErr != nil {
warnings = append(warnings, fmt.Sprintf("无效主机端口组合: %s - %s", host, hostErr.Error()))
continue
}
}
}
}
// 作为普通主机验证
if valid, err := tp.validateHost(host); valid {
validHosts = append(validHosts, host)
} else if err != nil {
@ -209,6 +229,11 @@ func (tp *TargetParser) parseHosts(input *TargetInput) ([]string, []error, []str
}
}
// 将找到的hostPorts合并到输入结果中通过修改input结构
if len(hostPorts) > 0 {
input.HostPort = append(input.HostPort, hostPorts...)
}
// 检查目标数量限制
if len(validHosts) > tp.options.MaxTargets {
warnings = append(warnings, fmt.Sprintf("主机数量超过限制,截取前%d个", tp.options.MaxTargets))
@ -404,8 +429,26 @@ func (tp *TargetParser) parseHostList(hostStr string) ([]string, error) {
}
hosts = append(hosts, rangeHosts...)
default:
// 单个IP或域名
hosts = append(hosts, item)
// 检查是否为host:port格式
if strings.Contains(item, ":") {
if _, portStr, err := net.SplitHostPort(item); err == nil {
// 验证端口号
if port, portErr := strconv.Atoi(portStr); portErr == nil && port >= MinPort && port <= MaxPort {
// 这是有效的host:port格式但在这里仍然作为主机处理
// 在后续的processHostPorts函数中会被正确处理
hosts = append(hosts, item)
} else {
// 端口无效,作为普通主机处理
hosts = append(hosts, item)
}
} else {
// 不是有效的host:port格式作为普通主机处理
hosts = append(hosts, item)
}
} else {
// 单个IP或域名
hosts = append(hosts, item)
}
}
}
@ -695,6 +738,19 @@ func (tp *TargetParser) validateHost(host string) (bool, error) {
return false, fmt.Errorf("主机地址为空")
}
// 检查是否为host:port格式
if strings.Contains(host, ":") {
// 可能是host:port格式尝试分离
if h, portStr, err := net.SplitHostPort(host); err == nil {
// 验证端口号
if port, portErr := strconv.Atoi(portStr); portErr == nil && port >= MinPort && port <= MaxPort {
// 递归验证主机部分(不包含端口)
return tp.validateHost(h)
}
}
// 如果不是有效的host:port格式继续按普通主机地址处理
}
// 检查是否为IP地址
if ip := net.ParseIP(host); ip != nil {
return tp.validateIP(ip)

View File

@ -60,6 +60,15 @@ func (p *PortDiscoveryService) shouldPerformLivenessCheck(hosts []string) bool {
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)
@ -73,14 +82,6 @@ func (p *PortDiscoveryService) discoverAlivePorts(hosts []string) []string {
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
}