mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-21 19:00:42 +08:00
133 lines
3.0 KiB
Go
133 lines
3.0 KiB
Go
package core
|
|
|
|
import (
|
|
"sort"
|
|
"sync"
|
|
)
|
|
|
|
// highPriorityPorts 高价值端口优先级表
|
|
// 数字越小优先级越高,用户最关心这些服务能快速出结果
|
|
var highPriorityPorts = map[int]int{
|
|
80: 1, // HTTP
|
|
443: 2, // HTTPS
|
|
22: 3, // SSH
|
|
3389: 4, // RDP
|
|
445: 5, // SMB
|
|
3306: 6, // MySQL
|
|
1433: 7, // MSSQL
|
|
6379: 8, // Redis
|
|
21: 9, // FTP
|
|
23: 10, // Telnet
|
|
8080: 11, // HTTP-Alt
|
|
8443: 12, // HTTPS-Alt
|
|
5432: 13, // PostgreSQL
|
|
27017: 14, // MongoDB
|
|
1521: 15, // Oracle
|
|
5900: 16, // VNC
|
|
25: 17, // SMTP
|
|
110: 18, // POP3
|
|
143: 19, // IMAP
|
|
53: 20, // DNS
|
|
}
|
|
|
|
// SocketIterator 流式生成 host:port 组合
|
|
// 设计原则:O(1) 内存,按需生成
|
|
// 使用端口喷洒策略:Port1全IP -> Port2全IP -> ...
|
|
// 优势:流量分散,避免单IP限速
|
|
type SocketIterator struct {
|
|
hosts []string
|
|
ports []int
|
|
hostIdx int
|
|
portIdx int
|
|
total int64
|
|
mu sync.Mutex
|
|
}
|
|
|
|
// NewSocketIterator 创建流式迭代器
|
|
// 自动对端口进行智能排序:高价值端口优先,让用户更快看到有意义的结果
|
|
func NewSocketIterator(hosts []string, ports []int, exclude map[int]struct{}) *SocketIterator {
|
|
validPorts := filterExcludedPorts(ports, exclude)
|
|
sortedPorts := sortPortsByPriority(validPorts)
|
|
return &SocketIterator{
|
|
hosts: hosts,
|
|
ports: sortedPorts,
|
|
total: int64(len(hosts)) * int64(len(sortedPorts)),
|
|
}
|
|
}
|
|
|
|
// sortPortsByPriority 智能排序端口
|
|
// 策略:高价值端口优先,其余按数字升序
|
|
func sortPortsByPriority(ports []int) []int {
|
|
if len(ports) <= 1 {
|
|
return ports
|
|
}
|
|
|
|
result := make([]int, len(ports))
|
|
copy(result, ports)
|
|
|
|
sort.Slice(result, func(i, j int) bool {
|
|
pi, pj := result[i], result[j]
|
|
priI, okI := highPriorityPorts[pi]
|
|
priJ, okJ := highPriorityPorts[pj]
|
|
|
|
// 都有优先级:按优先级排序
|
|
if okI && okJ {
|
|
return priI < priJ
|
|
}
|
|
// 只有一个有优先级:有优先级的排前面
|
|
if okI {
|
|
return true
|
|
}
|
|
if okJ {
|
|
return false
|
|
}
|
|
// 都没有优先级:按端口号升序
|
|
return pi < pj
|
|
})
|
|
|
|
return result
|
|
}
|
|
|
|
// Next 返回下一个 host:port 组合,ok=false 表示迭代结束
|
|
// 端口喷洒顺序:先遍历所有IP的同一端口,再换下一个端口
|
|
func (it *SocketIterator) Next() (string, int, bool) {
|
|
it.mu.Lock()
|
|
defer it.mu.Unlock()
|
|
|
|
// 空输入或迭代结束
|
|
if len(it.hosts) == 0 || it.portIdx >= len(it.ports) {
|
|
return "", 0, false
|
|
}
|
|
|
|
host := it.hosts[it.hostIdx]
|
|
port := it.ports[it.portIdx]
|
|
|
|
// 端口喷洒:先遍历所有IP,再换端口
|
|
it.hostIdx++
|
|
if it.hostIdx >= len(it.hosts) {
|
|
it.hostIdx = 0
|
|
it.portIdx++
|
|
}
|
|
|
|
return host, port, true
|
|
}
|
|
|
|
// Total 返回总任务数(用于进度条)
|
|
func (it *SocketIterator) Total() int64 {
|
|
return it.total
|
|
}
|
|
|
|
// filterExcludedPorts 过滤排除的端口
|
|
func filterExcludedPorts(ports []int, exclude map[int]struct{}) []int {
|
|
if len(exclude) == 0 {
|
|
return ports
|
|
}
|
|
result := make([]int, 0, len(ports))
|
|
for _, p := range ports {
|
|
if _, excluded := exclude[p]; !excluded {
|
|
result = append(result, p)
|
|
}
|
|
}
|
|
return result
|
|
}
|