2.5 基于TCP协议的活跃主机发现技术
2.5.1 TCP协议解析
TCP(Transmission Control Protocol,传输控制协议)是一个位于传输层的协议。它是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。TCP的特点是使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答TCP的三次握手SYN+ACK,并最终对对方的SYN执行ACK确认。这种建立连接的方法可以防止产生错误的连接,TCP使用的流量控制协议是可变大小的滑动窗口协议。
TCP三次握手的过程如下:
首先,客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
其次,服务器端收到SYN报文,回应一个SYN(SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
最后,客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据。
图2-3给出了TCP三次握手的过程。
图2-3 TCP三次握手的过程
再来理解一下“端口”的概念。注意这个概念在前面介绍的网络层的ARP协议和ICMP协议中是没有的。“端口”是英文port的意译,可以认为是设备与外界通信交流的出口。端口可分为虚拟端口和物理端口,这里使用的就是虚拟端口,指的是计算机内部或交换机路由器内的端口,不可见。例如计算机中的80端口、21端口、23端口等。
如果将每一台主机比喻成一栋房子,那么一个端口就可以理解为房子的一扇门,通过这扇门,人们就可以进出这栋房子。当然有一点不同的是,端口的数目可以多达65536个。要这么多端口有什么用呢?我们知道,一台拥有IP地址的主机可以提供许多种服务,比如Web服务、FTP服务、SMTP服务等,这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同服务的。
通常情况下,如果一个房子的门是开着的,那么意味着房子里面是有人的,同样道理,如果检测到一台主机的某个端口是开放的,也一样可以知道这台主机是活跃主机。
下面简单介绍一下端口开放的扫描概念,详细的内容将在第3章中进行讲解。如果想知道主机B是否处于活跃状态,就可以向主机B的全部端口(通常并不这样做,而是选择一部分常用的端口)发送连接请求数据包,如果得到回应(注意只要收到了数据包),就可以认为主机B是活跃主机。
2.5.2 使用TCP协议进行主机发现
在Nmap中常用的TCP协议扫描方式有两种,分别是TCP SYN扫描和TCP ACK扫描,这两种扫描方式其实都是利用TCP的三次握手实现的。
1. TCP SYN扫描
Nmap中使用-PS选项来向目标主机发送一个设置了SYN标志的数据包,这个数据包的内容部分为空。通常默认的目标端口是80端口,也可以使用参数来改变目标端口。例如将目标端口改变为22、23、113、35000等,当指定多个端口时,Nmap将会并发地对这些端口进行测试。
目标主机在收到Nmap所发送的SYN数据包之后,会认为Nmap所在主机想要和自己的一个端口建立连接,如果这个端口是开放的,目标主机就会按照TCP三次握手的规定,发回一个SYN/ACK数据包,表示同意建立连接。如果这个端口是关闭的,目标主机就会拒绝这次连接,向Nmap所在主机发送一个RST数据包。图2-4给出SYN扫描的过程。
图2-4 SYN扫描过程
不过,在这个阶段我们并不在乎目标主机的目标端口是否开放,只在乎目标主机是否活跃。在发出SYN数据包之后,只要收到数据包,无论是SYN/ACK数据包还是RST数据包,都意味着目标主机是活跃的。如果没有收到任何数据包,就意味着目标主机不在线。
在Nmap中可以使用-PS参数来实现这种扫描。
命令语法:Nmap -PS[端口1,端口2, ……] [目标]
下面给出一个Nmap扫描60.2.22.35的实例。
Nmap -sn -PS 60.2.22.35
扫描结果如下。
Starting Nmap 7.12 ( https://Nmap.org ) at 2016-09-16 11:12 Nmap scan report for 60.2.22.35 Host is up (0.021s latency). Nmap done: 1 IP address (1 host up) scanned in 1.88 seconds
整个扫描过程中产生的数据包如图2-5所示。
图2-5 一次SYN扫描过程产生的数据包
首先是Nmap所在的主机192.168.0.5向60.2.22.35发送了一个SYN数据包。
Frame 57: 58 bytes on wire (464 bits), 58 bytes captured (464 bits) on interface 0 Ethernet II, Src: 08:10:76:6a:ad:30 (08:10:76:6a:ad:30), Dst: D-LinkIn_b3:87:a9 (d8:fe:e3:b3:87:a9) Internet Protocol Version 4, Src: 192.168.0.5, Dst: 60.2.22.35 Transmission Control Protocol, Src Port: 48222 (48222), Dst Port: 80 (80), Seq: 0, Len: 0 Source Port: 48222 Destination Port: 80 ①
[Stream index: 2] [TCP Segment Len: 0] Sequence number: 0 (relative sequence number) Acknowledgment number: 0 Header Length: 24 bytes Flags: 0x002 (SYN) ② Window size value: 1024 [Calculated window size: 1024] Checksum: 0x5bb1 [validation disabled] Urgent pointer: 0 Options: (4 bytes), Maximum segment size
①表示连接的目标端口为80。
②表示这是一个SYN类型数据包。
如果目标60.2.22.35是活跃主机,而且80端口是开放的,那么按照TCP协议的规定,就会给192.168.0.5发送一个应答,这个应答是SYN/ACK数据包。
Frame 58: 58 bytes on wire (464 bits), 58 bytes captured (464 bits) on interface 0 Ethernet II, Src: D-LinkIn_b3:87:a9 (d8:fe:e3:b3:87:a9), Dst: 08:10:76:6a:ad:30 (08:10:76:6a:ad:30) Internet Protocol Version 4, Src: 60.2.22.35, Dst: 192.168.0.5 Transmission Control Protocol, Src Port: 80 (80), Dst Port: 48222 (48222), Seq: 0, Ack: 1, Len: 0 Source Port: 80 Destination Port: 48222 ① [Stream index: 2] [TCP Segment Len: 0] Sequence number: 0 (relative sequence number) Acknowledgment number: 1 (relative ack number) Header Length: 24 bytes Flags: 0x012 (SYN, ACK) ② Window size value: 17520 [Calculated window size: 17520] Checksum: 0xcc97 [validation disabled] Urgent pointer: 0 Options: (4 bytes), Maximum segment size [SEQ/ACK analysis]
Nmap所在主机在收到这个数据包之后,并不会真的和目标主机建立连接,因为目的只是判断目标主机是否为活跃主机,因此需要结束这次连接,TCP协议中结束连接的方法就是向目标发送一个RST数据包。
Frame 59: 54 bytes on wire (432 bits), 54 bytes captured (432 bits) on interface 0 Ethernet II, Src: 08:10:76:6a:ad:30 (08:10:76:6a:ad:30), Dst: D-LinkIn_b3:87:a9 (d8:fe:e3:b3:87:a9) Internet Protocol Version 4, Src: 192.168.0.5, Dst: 60.2.22.35 Transmission Control Protocol, Src Port: 48222 (48222), Dst Port: 80 (80), Seq: 1, Len: 0 Source Port: 48222
Destination Port: 80 ① [Stream index: 2] [TCP Segment Len: 0] Sequence number: 1 (relative sequence number) Acknowledgment number: 4155732289 Header Length: 20 bytes Flags:0x004 (RST) ② Window size value: 0 [Calculated window size: 0] [Window size scaling factor: -2 (no window scaling used)] Checksum: 0x0e75 [validation disabled] Urgent pointer: 0
①表示这个数据包的目标仍然是60.2.22.35的80端口,但是数据包的格式不再是TCP三次握手中的ACK确认数据包,而是要断开连接的RST数据包,这是因为目的已经达到,此时已经知道目标主机是活跃主机,无须和目标主机完成连接的建立。
下面给出一个目标端口不开放的例子。这里指定连接的端口为目标的10000端口,命令如下。
Nmap -sn -PS 10000 60.2.22.35
扫描的结果如下。
Starting Nmap 7.12 ( https://Nmap.org ) at 2016-09-16 11:34 Nmap scan report for 60.2.22.35 Host is up (0.022s latency). Nmap done: 1 IP address (1 host up) scanned in 1.86 seconds
Nmap所产生的数据包格式如下。
Frame 3742: 58 bytes on wire (464 bits), 58 bytes captured (464 bits) on interface 0 Ethernet II, Src: 08:10:76:6a:ad:30 (08:10:76:6a:ad:30), Dst: D-LinkIn_b3:87:a9 (d8:fe:e3:b3:87:a9) Internet Protocol Version 4, Src: 192.168.0.5, Dst: 60.2.22.35 Transmission Control Protocol, Src Port: 56532 (56532), Dst Port: 10000 (10000), Seq: 0, Len: 0 Source Port: 56532 Destination Port: 10000 [Stream index: 105] [TCP Segment Len: 0] Sequence number: 0 (relative sequence number) Acknowledgment number: 0 Header Length: 24 bytes Flags: 0x002 (SYN) Window size value: 1024 [Calculated window size: 1024] Checksum: 0xac68 [validation disabled] Urgent pointer: 0 Options: (4 bytes), Maximum segment size
60.2.22.35收到了这个SYN数据包,但是它的10000端口并没有开放,因此它会向Nmap所在的主机发回一个应答,表示该端口是关闭的,这个数据包同样也是RST格式的。
Frame 3743: 54 bytes on wire (432 bits), 54 bytes captured (432 bits) on interface 0 Ethernet II, Src: D-LinkIn_b3:87:a9 (d8:fe:e3:b3:87:a9), Dst: 08:10:76:6a:ad:30 (08:10:76:6a:ad:30) Internet Protocol Version 4, Src: 60.2.22.35, Dst: 192.168.0.5 Transmission Control Protocol, Src Port: 10000 (10000), Dst Port: 56532 (56532), Seq: 1, Ack: 1, Len: 0 Source Port: 10000 Destination Port: 56532 [Stream index: 105] [TCP Segment Len: 0] Sequence number: 1 (relative sequence number) Acknowledgment number: 1 (relative ack number) Header Length: 20 bytes Flags: 0x014 (RST, ACK) Window size value: 0 [Calculated window size: 0] [Window size scaling factor: -2 (no window scaling used)] Checksum: 0xc811 [validation disabled] Urgent pointer: 0 [SEQ/ACK analysis]
Nmap收到目标主机发回的应答,也同样可以判断目标主机是活跃主机,也就是说只要收到目标主机的应答,就可以认为目标主机是活跃主机,而无须理会应答的具体内容。
TCP扫描是Nmap扫描技术中最强大的技术之一,很多服务器的防御机制都会屏蔽掉ICMP echo请求数据包,但是任何的服务器都会响应针对其服务的SYN数据包。例如,一个Web服务器的安全机制不可能拒绝发往80端口的SYN数据包,虽然有可能会拒绝ACK数据包。但是要注意的是,很多服务器的安全机制可能会屏蔽掉它提供服务以外的端口,比如Web服务器的安全机制就可能将除80端口以外的所有端口都屏蔽掉,因此当你将一个SYN数据包发往它的22端口时,就可能会石沉大海一样,没有任何的应答,得不到任何有用的信息。而我们又很难对大量主机的所有端口进行扫描,因此在对目标进行扫描时,端口的选择就显得很重要。表2-2列出了TCP扫描中最为常用的14个端口。
表2-2 常见的TCP扫描端口
在利用端口扫描的时,也可以使用这些端口的组合,比如“-PS 22, 80”就是一个不错的选择,但是也要注意“-PS 80, 443”的意义就不大,因为这两个端口对应的分别是http、https服务,如果目标是一个Web服务器,它基本上总是会提供这两个服务,如果不是,那么它一个服务都不会提供。因此,“-PS 80, 443”这个组合很有可能是重复的。
2. TCP ACK扫描
再看另一种类型的TCP协议扫描,这种扫描被称作ACK扫描。实际上它和SYN扫描相当相似,不同之处只在于Nmap发送的数据包中使用TCP/ACK标志位,而不是SYN标志位。按照TCP三次握手的规则,两台主机A和B,只有当A向B发送了SYN数据包之后,B才会回应A一个TCP/ACK数据包。
现在Nmap直接向目标主机发送一个TCP/ACK数据包,目标主机显然无法清楚这是怎么回事,当然也不可能成功建立TCP连接,因此只能向Nmap所在主机发送一个RST标志位的数据包,表示无法建立这个TCP连接,图2-6给出了这样的一次扫描过程。
图2-6 ACK扫描过程
这种ACK扫描的方式同样以80端口作为默认端口,也可以进行指定。如果需要对目标主机采用这种扫描方式,可以使用如下命令。
Nmap -sn -PA 60.2.22.35
扫描的结果如下。
Starting Nmap 7.12 ( https://Nmap.org ) at 2016-09-16 12:07 Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn Nmap done: 1 IP address (0 hosts up) scanned in 3.88 seconds
不过这次扫描显然失败了。在实际情况中,这种类型的扫描很少能成功,造成这种情况的原因是目标主机上的安全机制或者安全设备将这种莫名其妙的TCP/ACK包直接过滤掉了。不过还是可以查看一下这个数据包的格式。
Frame 15315: 54 bytes on wire (432 bits), 54 bytes captured (432 bits) on interface 0 Ethernet II, Src: 08:10:76:6a:ad:30 (08:10:76:6a:ad:30), Dst: D-LinkIn_b3:87:a9 (d8:fe:e3:b3:87:a9) Internet Protocol Version 4, Src: 192.168.0.5, Dst: 60.2.22.35 Transmission Control Protocol, Src Port: 51269 (51269), Dst Port: 80 (80), Seq: 1, Ack: 1, Len: 0 Source Port: 51269 Destination Port: 80 [Stream index: 226] [TCP Segment Len: 0] Sequence number: 1 (relative sequence number) Acknowledgment number: 1 (relative ack number) Header Length: 20 bytes Flags: 0x010 (ACK) Window size value: 1024 [Calculated window size: 1024] [Window size scaling factor: -1 (unknown)] Checksum: 0xa0e8 [validation disabled] Urgent pointer: 0
在Nmap发出数据包之后,并没有收到任何应答,这时存在两种可能,一种是这个数据包被对方的安全机制过滤掉了,因为目标根本没有收到这个数据包,另一种就是目标主机并非活跃主机。Nmap通常会按照第二种情况进行判断,也就是给出一个错误的结论:目标并非活跃主机。