天网千帆文件搜索开源项目
TCP 端口扫描模块
谢翰
e@pku.edu.cn
一、开发目的
ftp 文件搜索的第一步就是发现 Internet 上存在 ftp 服务的计算机。由于通常 ftp 服
务都是使用 TCP 21 端口,所以我们发现 ftp 服务的第一个方法就是扫描 Internet 上所有计
算机的 TCP 21 端口是否接受连接。另外,由于 Internet 上的机算机数目巨大,而 ftp 服务
也存在时效性,这就要求我们必须在尽量短的时间内完成扫描。原有的天网 ftp 端口扫描程
序在效率上已经不能满足要求,扫描结果也不够完全,因此有必要开发新的端口扫描程序。
二、实现方法
一般的 TCP 端口扫描都是通过系统调用 connect,如果在一个较短时间内对方主机没有
响应,则认为该主机的该端口不可接受连接。虽然程序可以启动多个进程,每个进程同时发
出多个连接请求,但如果每个连接的超时限制设得很长,则整个扫描过程会很长;如果超时
限制很短,则那些响应较慢的主机可能无法被发现。原来系统的连接超时为 5 秒,针对全国
范围内的 IP 地址进行一次扫描需要 1 个多月。
因此,我们必须考虑一种全新的方法来实现 TCP 端口的扫描。我们首先必须找出原有的
端口扫描方法瓶颈所在。我们发现,如果原有的端口扫描方法是调用 connect,而 connect
所做的事情就是向远程主机发送 TCP 的连接请求信号(SYN),再等待对方的响应。可见其发
送与接收是同步的。如果改用异步的方法:一边不断的向 IP 地址范围内的主机发送 SYN 连
接信号,一边监听发往本机的 IP 数据包。如果某个 IP 地址某端口接受连接,则它会向本机
发来一个 SYN,并确认我们发出的 SYN 信号;如果某个 IP 地址某端口拒绝连接,则它会向
本机发来一个 TCP RST,同时确认我们发出的 SYN 信号;如果某个 IP 地址某端口不可达,
则我们会收到一个 ICMP 不可达报文。这样,我们的发送与接收就成了异步进行,扫描速度
会有质的发跃。
要实现这种设想,我们必须熟悉 IP 协议,TCP 协议以及 ICMP 协议,因为我们必须自行
构造和发送 TCP SYN 信号,并且自行解析收入到的 TCP 包和 ICMP 包。此外,由于网络的数
据包可能会丢失,也可能被重复收到,如果我们只对每个 IP 地址发送一次连接请求是不可
靠的,因此对那些没有响应的地址我们还要多发送几次 SYN。那么,我们就必须记录下那些
已经有响应的地址,在下一轮的发送中略过这些地址。在实现中我们使用了一棵红-黑树(因
为是用 C 语言编写,如果是 C++则用一个向量就可以),用于存放所有的已经有响应的地址。
每接收到一个响应(接受,拒绝,不可达),也要查看该响应的地址是否已经在这棵红-黑
树中,这样就可以防止一个 IP 地址被多次的返回给调用者。
三、模块使用说明
TCP 端口扫描模块只有一个函数接口:tcp_scan。其函数原型如下:
int tcp_scan(const struct addrseg *addrscope, const unsigned short *ports,
unsigned int ifindex, const char *ifname, int resetuid,
scan_info_t info, void *arg);
下面解释一下各个参数的意义。
const struct addrseg *addrscope: 要扫描的地址范围,是一个结点类型为 struct addrseg
的链表,每个结点为一个 IP 地址段。struct addrseg 的定义如下:
评论2