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

- 实现固定底部进度条显示,与正常输出分离 - 创建ProgressManager统一管理进度条状态和渲染 - 优化日志级别过滤,默认只显示BASE、INFO、SUCCESS级别 - 修复进度条与并发日志输出的冲突问题 - 重构日志系统以支持动态级别配置和进度条协调 - 改进用户体验,提供清晰、专业的扫描进度反馈 主要改进: * 新增ProgressManager.go实现固定底部进度条 * 修复日志初始化时机,确保级别配置正确生效 * 实现日志输出与进度条的互斥显示机制 * 优化默认日志级别,过滤干扰性调试和错误信息 * 保持向后兼容性,支持用户自定义日志级别
178 lines
4.2 KiB
Go
178 lines
4.2 KiB
Go
package Core
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/shadow1ng/fscan/Common"
|
|
"github.com/shadow1ng/fscan/Common/parsers"
|
|
"golang.org/x/sync/errgroup"
|
|
"golang.org/x/sync/semaphore"
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
// EnhancedPortScan 高性能端口扫描函数
|
|
func EnhancedPortScan(hosts []string, ports string, timeout int64) []string {
|
|
// 解析端口和排除端口
|
|
portList := parsers.ParsePort(ports)
|
|
if len(portList) == 0 {
|
|
Common.LogError("无效端口: " + ports)
|
|
return nil
|
|
}
|
|
|
|
exclude := make(map[int]struct{})
|
|
for _, p := range parsers.ParsePort(Common.ExcludePorts) {
|
|
exclude[p] = struct{}{}
|
|
}
|
|
|
|
// 计算总扫描数量
|
|
totalTasks := 0
|
|
for range hosts {
|
|
for _, port := range portList {
|
|
if _, excluded := exclude[port]; !excluded {
|
|
totalTasks++
|
|
}
|
|
}
|
|
}
|
|
|
|
// 初始化端口扫描进度条
|
|
if totalTasks > 0 && Common.ShowProgress {
|
|
description := Common.GetText("progress_port_scanning")
|
|
Common.InitProgressBar(int64(totalTasks), description)
|
|
}
|
|
|
|
// 初始化并发控制
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
to := time.Duration(timeout) * time.Second
|
|
sem := semaphore.NewWeighted(int64(Common.ThreadNum))
|
|
var count int64
|
|
var aliveMap sync.Map
|
|
g, ctx := errgroup.WithContext(ctx)
|
|
|
|
// 并发扫描所有目标
|
|
for _, host := range hosts {
|
|
for _, port := range portList {
|
|
if _, excluded := exclude[port]; excluded {
|
|
continue
|
|
}
|
|
|
|
host, port := host, port // 捕获循环变量
|
|
addr := fmt.Sprintf("%s:%d", host, port)
|
|
|
|
if err := sem.Acquire(ctx, 1); err != nil {
|
|
break
|
|
}
|
|
|
|
g.Go(func() error {
|
|
defer func() {
|
|
sem.Release(1)
|
|
// 更新端口扫描进度
|
|
Common.UpdateProgressBar(1)
|
|
}()
|
|
|
|
// 连接测试 - 支持SOCKS5代理
|
|
conn, err := Common.WrapperTcpWithTimeout("tcp", addr, to)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer conn.Close()
|
|
|
|
// 记录开放端口
|
|
atomic.AddInt64(&count, 1)
|
|
aliveMap.Store(addr, struct{}{})
|
|
Common.LogInfo("端口开放 " + addr)
|
|
Common.SaveResult(&Common.ScanResult{
|
|
Time: time.Now(), Type: Common.PORT, Target: host,
|
|
Status: "open", Details: map[string]interface{}{"port": port},
|
|
})
|
|
|
|
// 服务识别
|
|
if Common.EnableFingerprint {
|
|
if info, err := NewPortInfoScanner(host, port, conn, to).Identify(); err == nil {
|
|
// 构建结果详情
|
|
details := map[string]interface{}{"port": port, "service": info.Name}
|
|
if info.Version != "" {
|
|
details["version"] = info.Version
|
|
}
|
|
|
|
// 处理额外信息
|
|
for k, v := range info.Extras {
|
|
if v == "" {
|
|
continue
|
|
}
|
|
switch k {
|
|
case "vendor_product":
|
|
details["product"] = v
|
|
case "os", "info":
|
|
details[k] = v
|
|
}
|
|
}
|
|
if len(info.Banner) > 0 {
|
|
details["banner"] = strings.TrimSpace(info.Banner)
|
|
}
|
|
|
|
// 保存服务结果
|
|
Common.SaveResult(&Common.ScanResult{
|
|
Time: time.Now(), Type: Common.SERVICE, Target: host,
|
|
Status: "identified", Details: details,
|
|
})
|
|
|
|
// 记录服务信息
|
|
var sb strings.Builder
|
|
sb.WriteString("服务识别 " + addr + " => ")
|
|
if info.Name != "unknown" {
|
|
sb.WriteString("[" + info.Name + "]")
|
|
}
|
|
if info.Version != "" {
|
|
sb.WriteString(" 版本:" + info.Version)
|
|
}
|
|
|
|
for k, v := range info.Extras {
|
|
if v == "" {
|
|
continue
|
|
}
|
|
switch k {
|
|
case "vendor_product":
|
|
sb.WriteString(" 产品:" + v)
|
|
case "os":
|
|
sb.WriteString(" 系统:" + v)
|
|
case "info":
|
|
sb.WriteString(" 信息:" + v)
|
|
}
|
|
}
|
|
|
|
if len(info.Banner) > 0 && len(info.Banner) < 100 {
|
|
sb.WriteString(" Banner:[" + strings.TrimSpace(info.Banner) + "]")
|
|
}
|
|
|
|
Common.LogInfo(sb.String())
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
}
|
|
|
|
_ = g.Wait()
|
|
|
|
// 收集结果
|
|
var aliveAddrs []string
|
|
aliveMap.Range(func(key, _ interface{}) bool {
|
|
aliveAddrs = append(aliveAddrs, key.(string))
|
|
return true
|
|
})
|
|
|
|
// 完成端口扫描进度条
|
|
if Common.IsProgressActive() {
|
|
Common.FinishProgressBar()
|
|
}
|
|
|
|
Common.LogBase(Common.GetText("scan_complete_ports_found", count))
|
|
return aliveAddrs
|
|
}
|
|
|