XinRoom/go-portScan

GitHub: XinRoom/go-portScan

基于 Go 的高性能端口扫描器,支持 SYN 无状态扫描与 TCP 扫描,内置端口服务指纹和 HTTP 指纹识别,既可命令行使用也可作为库集成到其他项目中。

Stars: 316 | Forks: 42

# go-portScan [![Go 参考](https://pkg.go.dev/badge/github.com/XinRoom/go-portScan.svg)](https://pkg.go.dev/github.com/XinRoom/go-portScan) 高性能端口扫描器 高性能端口扫描器。 ## 功能 - SYN 无状态扫描 - 在内网中 SYN 自动 ARP 检测 - 扫描大地址段时占用低 (通过 iprange) - 扫描地址会被随机打乱 - 高并发性能 (通过 ants) - TCP 扫描 - 端口指纹识别 - HTTP 服务检测 ## 作为库使用 ### 1. SYN 扫描器 ``` package main import ( "github.com/XinRoom/go-portScan/core/host" "github.com/XinRoom/go-portScan/core/port" "github.com/XinRoom/go-portScan/core/port/syn" "github.com/XinRoom/iprange" "github.com/panjf2000/ants/v2" "log" "net" "sync" "time" ) func main() { single := make(chan struct{}) retChan := make(chan port.OpenIpPort, 65535) go func() { for ret := range retChan { log.Println(ret) } single <- struct{}{} }() // 解析端口字符串并且优先发送 TopTcpPorts 中的端口, eg: 1-65535,top1000 ports, err := port.ShuffleParseAndMergeTopPorts("top1000") if err != nil { log.Fatal(err) } // parse ip it, startIp, _ := iprange.NewIter("1.1.1.1/30") // scanner ss, err := syn.NewSynScanner(startIp, retChan, syn.DefaultSynOption) if err != nil { log.Fatal(err) } // port scan func portScan := func(ip net.IP) { for _, _port := range ports { // port ss.WaitLimiter() ss.Scan(ip, _port, port.IpOption{}) // syn 不能并发,默认以网卡和驱动最高性能发包 } } // Pool - ping and port scan var wgPing sync.WaitGroup poolPing, _ := ants.NewPoolWithFunc(50, func(ip interface{}) { _ip := ip.(net.IP) if host.IsLive(_ip.String(), true, 800*time.Millisecond) { portScan(_ip) } wgPing.Done() }) defer poolPing.Release() start := time.Now() for i := uint64(0); i < it.TotalNum(); i++ { // ip索引 ip := make(net.IP, len(it.GetIpByIndex(0))) copy(ip, it.GetIpByIndex(i)) // Note: dup copy []byte when concurrent (GetIpByIndex not to do dup copy) wgPing.Add(1) poolPing.Invoke(ip) } wgPing.Wait() ss.Wait() ss.Close() <-single log.Println(time.Since(start)) } ``` ### 2. TCP 扫描器 ``` package main import ( "github.com/XinRoom/go-portScan/core/host" "github.com/XinRoom/go-portScan/core/port" "github.com/XinRoom/go-portScan/core/port/tcp" "github.com/XinRoom/iprange" "github.com/panjf2000/ants/v2" "log" "net" "sync" "time" ) func main() { single := make(chan struct{}) retChan := make(chan port.OpenIpPort, 65535) go func() { for ret := range retChan { log.Println(ret) } single <- struct{}{} }() // 解析端口字符串并且优先发送 TopTcpPorts 中的端口, eg: 1-65535,top1000 ports, err := port.ShuffleParseAndMergeTopPorts("top1000") if err != nil { log.Fatal(err) } // parse Ip it, _, _ := iprange.NewIter("1.1.1.1/30") // scanner ss, err := tcp.NewTcpScanner(retChan, tcp.DefaultTcpOption) if err != nil { log.Fatal(err) } // port scan func portScan := func(ip net.IP) { for _, _port := range ports { // port ss.WaitLimiter() ss.Scan(ip, _port, port.IpOption{}) // syn 不能并发,默认以网卡和驱动最高性能发包 } } // Pool - ping and port scan var wgPing sync.WaitGroup poolPing, _ := ants.NewPoolWithFunc(50, func(ip interface{}) { _ip := ip.(net.IP) if host.IsLive(_ip.String(), true, 800*time.Millisecond) { portScan(_ip) } wgPing.Done() }) defer poolPing.Release() start := time.Now() for i := uint64(0); i < it.TotalNum(); i++ { // ip索引 ip := make(net.IP, len(it.GetIpByIndex(0))) copy(ip, it.GetIpByIndex(i)) // Note: dup copy []byte when concurrent (GetIpByIndex not to do dup copy) wgPing.Add(1) poolPing.Invoke(ip) } wgPing.Wait() ss.Wait() ss.Close() <-single log.Println(time.Since(start)) } ``` ### 3. HTTP/端口指纹 HTTP Web CMS 指纹 ``` // "github.com/XinRoom/go-portScan/core/port/fingerprint" func ProbeHttpInfo(host string, _port uint16, topScheme string, dialTimeout time.Duration) (httpInfo *port.HttpInfo, banner []byte, isDailErr bool) {} func WebHttpInfo(url2 string, dialTimeout time.Duration) (httpInfo *port.HttpInfo, banner []byte, isDailErr bool) {} // "github.com/XinRoom/go-portScan/core/port/fingerprint/webfinger" func WebFingerIdent(resp *http.Response) (names []string) {} ``` TCP 端口服务指纹 ``` // "github.com/XinRoom/go-portScan/core/port/fingerprint" func PortIdentify(network string, ip net.IP, _port uint16, dailTimeout time.Duration) (serviceName string, banner []byte, isDailErr bool) {} ``` ### 4. 更多信息 查看 [./cmd/go-portScan.go](./cmd/go-portScan.go) ## 命令行构建 普通编译 ``` git clone https://github.com/XinRoom/go-portScan cd go-portScan go get -d -u ./... go build -trimpath -ldflags="-s -w" -tags urfave_cli_no_docs cmd/go-portScan.go ``` Linux 静态链接编译(需要 docker 环境) ``` sh ./build/build_static_alpine.sh ``` 禁用 SYN 模块,只保留 TCP 的编译(以便能在未安装 pcap 的 Windows 机器上运行) ``` go build -trimpath -ldflags="-s -w" -tags urfave_cli_no_docs,nosyn cmd/go-portScan.go ``` ## 命令行用法 `.\go-portScan.exe -ip 1.1.1.1/30 [-p str] [-Pn] [-sT] [-sV] [-httpx] [-rate num] [-rateP num] [-timeout num(ms)]` ``` NAME: PortScan - A new cli application USAGE: PortScan [global options] command [command options] [arguments...] DESCRIPTION: High-performance port scanner COMMANDS: help, h Shows a list of commands or help for one command GLOBAL OPTIONS: --ip value target ip, eg: "1.1.1.1/30,1.1.1.1-1.1.1.2,1.1.1.1-2" --iL value target ip file, eg: "ips.txt" --port value, -p value eg: "top1000,5612,65120,-" (default: "top1000") --Pn no ping probe (default: false) --rateP value, --rp value concurrent num when ping probe each ip (default: 300) --PT use TCP-PING mode (default: false) --sT TCP-mode (default: false) --timeout value, --to value TCP-mode SYN-mode timeout. unit is ms. (default: 800) --sS Use SYN-mode(default: true) --nexthop value, --nh value specified nexthop gw add to pcap dev --rate value, -r value number of packets sent per second. If set -1, TCP-mode is 1000, SYN-mode is 1500(SYN-mode is restricted by the network adapter, 2000=1M) (default: -1) --devices, --ld list devices name (default: false) --sV port service identify (default: false) --httpx http server identify (default: false) --netLive Detect live C-class networks, eg: -ip 192.168.0.0/16,172.16.0.0/12,10.0.0.0/8 (default: false) --maxOpenPort value, --mop value Stop the ip scan, when the number of open-port is maxOpenPort (default: 0) --oCsv value, --oC value output csv file --oFile value, -o value output to file --help, -h show help (default: false) ``` 关键参数说明: ``` --Pn 在目标禁止PING时使用 --rate 在网络不稳定时(互联网)可以适当减少(互联网下建议500~1500) --timeout 在网络不稳定时(互联网)可以适当增加 --nexthop 用于在syn扫描模式下,找不到路由网卡情况时,指定下一跳网关地址(需要是本地网卡上绑定的网关地址) --PT ICMP不通时,使用常见端口的TCP探测主机是否存活 --sV 用于判断端口的服务(主要是探测风险比较大的服务) --netLive 用于抽取网络内6个左右IP进行存活探测 --httpx 用于探测http服务的title等信息 --mop 用于目标组内存在防扫描防火墙的情况,单个IP扫描到开放的端口到达该值就停止对该IP扫描,避免浪费时间(建议值500) ```
标签:ARP探测, C2日志可视化, EVTX分析, Go语言, GraphQL安全矩阵, HTTP服务检测, iprange, SYN扫描, TCP扫描, 二进制发布, 内网探测, 协程池, 域名解析, 安全扫描器, 并发扫描, 开源工具, 指纹识别, 插件系统, 数据统计, 无状态扫描, 日志审计, 检测规则, 程序破解, 端口扫描, 网络安全, 网络资产发现, 隐私保护