Skip to main content

[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 synscanOPEN: 127.0.0.1:6341       from synscanOPEN: 127.0.0.1:7891       from synscanOPEN: 127.0.0.1:9090       from synscanOPEN: 127.0.0.1:10000      from synscanOPEN: 127.0.0.1:49159      from synscanOPEN: 127.0.0.1:63342      from synscanOPEN: 127.0.0.1:7890       from synscanOPEN: 127.0.0.1:3306       from synscanOPEN: 127.0.0.1:10800      from synscanOPEN: 127.0.0.1:33060      from synscanOPEN: 127.0.0.1:6942       from synscanOPEN: 127.0.0.1:8080       from synscanOPEN: 127.0.0.1:49922      from synscanOPEN: 127.0.0.1:16090      from synscanOPEN: 127.0.0.1:16308      from synscanOPEN: 127.0.0.1:6342       from synscanOPEN: 127.0.0.1:50031      from synscanOPEN: 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:60012127.0.0.1:6341127.0.0.1:7891127.0.0.1:9090127.0.0.1:10000127.0.0.1:49159127.0.0.1:63342127.0.0.1:7890127.0.0.1:3306127.0.0.1:10800127.0.0.1:33060127.0.0.1:6942127.0.0.1:8080127.0.0.1:49922127.0.0.1:16090127.0.0.1:16308127.0.0.1:6342127.0.0.1:50031127.0.0.1:16067