跳到主要内容

[synscan] SYN扫端口

语言自带扫描功能是本语言的一个大亮点。你在使用 yak 的时候,将不会再费心思考虑如何实现一个端口扫描功能,或者如何把 nmap 集成进你想编写的语言中。

什么是 SYN 端口扫描?

  1. 自己维护一套网络栈,拆解 TCP 三次握手
  2. 只进行第一次握手,如果收到了扫描目标的 SYN-ACK 则判定为端口开放
  3. 发送 RST 强行中断握手

本系统工具实现原理基本同 masscan:短时间内把 SYN 数据包都发送出去,检查若干秒内的返回记录。

所以,我们在本扩展包中开放出了 synscan.wait(second) 这个参数配置,可以动态配置想要等待的秒数。

为什么 SYN 扫端口比 TCP 连接扫描更快速?​

直接调用系统接口进行 TCP 连接,系统需要帮忙维护一个 TCP 连接状态。众所周知

  1. 系统可打开的 TCP 连接是有限制的,可配置开放这个限制。
  2. 系统可同时打开的文件描述符也是有限制的,ulimit 可配。

优势​

  1. 不需要进行完整 TCP 连接,系统对 TCP 连接无感知
  2. 资源消耗极低,发包速率取决于系统性能以及网络 IO

弊端​

  1. 频率过高的数据包容易被中间路由丢包,损失准确率
  2. 网络状况越差,丢包概率越大,扫描效果越差

最简单最高效的扫描接口​

核心扫描函数​

  1. fn synscan.Scan(hosts: string, ports: string, vars: ...tools.scanOpt): (chan *tools.SynScanResult, error) 核心扫描函数,参数 hosts 可以支持 IP/IP+掩盖码,域名等;ports 支持端口组,例如 22.443.80,8080-8084,或者 1-65535

扫描额外参数​

  1. fn synscan.outputFile(var_1: string): tools.scanOpt 设置输出的文件,输出文件为 var_1 的值
  2. fn synscan.outputPrefix(var_1: string): tools.scanOpt 设置输出文件内容每一行的前缀,例如 http://,或者 redis:// 等,方便后续处理文件
  3. fn synscan.wait(var_1: float64): tools.scanOpt 全部数据包发送完之后,等待多少时间?单位秒

tools.SynScanResult 扫描结果结构​

type palm/common/yak/yaklib/tools.(SynScanResult) struct {
Fields(可用字段):
// 扫描到的 IP
Host: string

// 这个 IP 开放的端口
Port: int

PtrStructMethods(指针结构方法/函数):
// 展示 SynScanResult demo: `OPEN: 127.0.0.1:6341 from synscan`
func Show()
}

执行案例:最经典/最简单的使用方法​

res, err := synscan.Scan("127.0.0.1", "1-65535")
die(err)

for result := range res {
result.Show()
}

当我们执行完上面脚本之后,我们发现扫描结果如下:

OPEN: 127.0.0.1:60012      from synscan
OPEN: 127.0.0.1:6341 from synscan
OPEN: 127.0.0.1:7891 from synscan
OPEN: 127.0.0.1:9090 from synscan
OPEN: 127.0.0.1:10000 from synscan
OPEN: 127.0.0.1:49159 from synscan
OPEN: 127.0.0.1:63342 from synscan
OPEN: 127.0.0.1:7890 from synscan
OPEN: 127.0.0.1:3306 from synscan
OPEN: 127.0.0.1:10800 from synscan
OPEN: 127.0.0.1:33060 from synscan
OPEN: 127.0.0.1:6942 from synscan
OPEN: 127.0.0.1:8080 from synscan
OPEN: 127.0.0.1:49922 from synscan
OPEN: 127.0.0.1:16090 from synscan
OPEN: 127.0.0.1:16308 from synscan
OPEN: 127.0.0.1:6342 from synscan
OPEN: 127.0.0.1:50031 from synscan
OPEN: 127.0.0.1:16067 from synscan

执行案例:自定义等待时间​

// 扫描本地 1-65535 号端口,全部数据包发送完毕的时候,等待 3.5 秒
res, err := synscan.Scan("127.0.0.1", "1-65535", synscan.wait(3.5))
die(err)

for result := range res {
result.Show()
}

执行案例:输出到文件​

res, err := synscan.Scan("127.0.0.1", "1-65535",
synscan.wait(3.5),
synscan.outputFile("test.txt"),
)
die(err)

for result := range res {
result.Show()
}

当我们执行完上面的代码之后,cat test.txt,我们发现了文件内容结果如下

127.0.0.1:60012
127.0.0.1:6341
127.0.0.1:7891
127.0.0.1:9090
127.0.0.1:10000
127.0.0.1:49159
127.0.0.1:63342
127.0.0.1:7890
127.0.0.1:3306
127.0.0.1:10800
127.0.0.1:33060
127.0.0.1:6942
127.0.0.1:8080
127.0.0.1:49922
127.0.0.1:16090
127.0.0.1:16308
127.0.0.1:6342
127.0.0.1:50031
127.0.0.1:16067