TCP 半连接的攻击的原理及防范
说起安全,不得不说一下当前最为流行的一种 D.o.S 的攻击方式,从目前看来,这种攻击仍然是危害性相当大,并且没有办法彻底防范的一种攻击方式。而且,凡是基于 TCP 的高层应用,都有可能受到这种致命的。
在“可靠的”传输层,在这里打上引号,是因为传输层并不是真正的可靠的,而只是相对的。为什么这么说呢,因为在 2 端的通信中,如果由于通信链路的故障,或者是某一端的故障,造成了通信的异常,那么另一端是不能主动地了解到的。打个比方说,这就好比是我汇钱给张三,用的是中国邮政的普通汇款,由于种种的原因,他们把钱在路上搞丢了,但是这个时候我并不知道钱丢了,我还在一直等张三给我打电话,告诉我钱是否到了,如果 2 个月之后,张三还是没有来电话,说钱已经收到了,按照常理来说,一个半月之前就应该收到了,那没办法,我只得再给张三汇钱,如果这次又搞丢了,我还得再汇,直到张三打电话告诉我,钱已经到了,那么可能对于张三来说,这个传输是可靠的,因为不管丢了多少次,终究他是收到了他想要的东西,但是对于我来说,我不能把丢的钱找回来,也不能自己去监视中国邮政到底是把我的钱搞丢了,还是被他们塞进自己的腰包了,我所知道的仅仅是“张三没有收到钱”,我需要再给他寄一次。
由此可以看出,TCP 的传输并不是可靠的,它存在一个等待和重传的机制,一旦数据在网络上发生丢失,它会依赖于 ACK / SYN 这些东西来进行一个重传,而且,TCP 处理程序中存在一个计时器,如果计时器发生超时,那么它就认为数据已经丢了(当然不会像上边的例子中说的是 2 个月),再去重传,那么既然要去重传,就要保证将来一旦发生超时,TCP 处理程序还能把丢失的东西找回来,那么,TCP 处理程序在收到连接请求的时候,就会要在内存中开辟一片区域来,保存 SYN 以及数据着一系列的东西。
好,现在了解到了 TCP 的可靠与不可靠的方面,现在来说一下 TCP 的 3 次握手,这个在以前的文章中已经写过了,在这里就不再多说了,在正常情况下,3 次握手的步骤如下:
ISN
A ——————-> B
SYN/ACK
A <——————- B
ACK
A ——————-> B
在 A 向 B 发出 TCP 请求的时候,它发出一个随机的 ISN (Initial Sequence Number),B 收到后给 A 回复一个 ACK = ISN + 1,同时再回复一个自己的 SYN 号,接着会保存 A 发来的这些信息,同时再内存中开辟缓冲区进行保存,然后 A 再给 B 回复一个 ACK。经历过这三次之后,一个端到端的 TCP 连接已经建立起来了,这是正常的情况。但是,考虑这种情况,如果在 A 向 B 发出请求,B 给 A 回复并且开辟了资源之后,A 不再进行第三次的回复,会怎么办?这就好比说,张三收到钱了,也不给我打电话,我一等 2 个月,按照常理的话张三早该收到钱了,但是他还没来电话,没办法,我只有再去汇钱了,那么如果每一次都这样,我这里的钱是不是很快就汇完了?TCP 中也是这样,如果 A 一直在向B 发起 TCP 请求,B 也按照正常情况进行响应了,但是 A 不进行第三次的握手,造成半连接,那么 B 分配出去的内存资源就一直这么耗着,直到资源耗尽。
对于这种攻击,似乎是没有办法防范的,因为 TCP 的三次握手是协议规定死的,所有使用 TCP 协议的软件都必须遵循其规定,否则无法通信。但是,有一种办法,似乎可以防范,那就是限制通信源的 TCP 并发连接数,例如:如果 A 在 1 秒钟之内连续产生 100 个 TCP 半连接,那么 B 就丢弃 A 所有的 TCP 信息,并且在一定时间内不再响应攻击者的释放内存资源。这看起来似乎似乎一种行之有效的办法,可是实际并非这么简单,因为在第三层的 IP 协议是一个不可靠的协议,它的源地址可以被伪造,如果一个攻击者制造大量的伪造源地址来对受害者进行攻击,而每一个 IP 地址的 TCP 半连接只建立 3~5 次,这个时候如何防范?
基于此,一种新型的防御方式产生了—— TCP Cookie,TCP Cookie 技术针对 TCP 协议的软肋,做出了一些改进。仍以上面的通信过程为例,在 A 向 B 发出一个 TCP 请求之后,B 并不立即为 A 的 TCP 请求分配资源,而是利用 A 发来的连接信息计算出一个 Cookie 值——取 Client 端的 IP、端口,以及 Server 端的 IP、端口,再进行一种散列算法,得到一个 Cookie,取该 Cookie 的前 24 位作为 SYN 值对对方进行回复。当对方对这个 SYN/ACK 再次进行 ACK (ACK=SYN+1)回复的时候,利用某种算法和这个 ACK 来倒推回原来的 Cookie,如果在一定范围内符合,即认为是合法的 TCP 请求,对它进行响应,如果不符合,则认为其是非法的 TCP 请求,丢弃。为什么说是一定范围内呢,因为 Cookie 的变化和时间有关,那么在 TCP 超时之内的所有的 ACK 都应该是合法的,那么在倒推回去的时候,只要得到的 Cookie 和原来的 Cookie 在一个合法的时间段内相符,就认为是合法的。
这种 TCP Cookie 技术并不是无懈可击的,首先,如果攻击者大量地伪造 IP 地址进行半连接攻击,受害者会忙于计算原来的 Cookie 值而造成资源耗尽,另外,由于并发连接数太多,会造成受害者的带宽耗尽,同样也会造成拒绝服务攻击(D.o.S 可不管是耗尽资源还是耗尽带宽,它只要让受害者的服务不能正常提供即可),带宽总是有限的,所以不管怎么防范,只要 D.o.S 攻击威力足够大,任何的防范方法都不能奏效。所以想要防范 D.o.S,还是厚道些做人,不要惹火黑客,否则在遭到攻击的时候,除了拔网线,恐怕再没有别的办法了。
在“可靠的”传输层,在这里打上引号,是因为传输层并不是真正的可靠的,而只是相对的。为什么这么说呢,因为在 2 端的通信中,如果由于通信链路的故障,或者是某一端的故障,造成了通信的异常,那么另一端是不能主动地了解到的。打个比方说,这就好比是我汇钱给张三,用的是中国邮政的普通汇款,由于种种的原因,他们把钱在路上搞丢了,但是这个时候我并不知道钱丢了,我还在一直等张三给我打电话,告诉我钱是否到了,如果 2 个月之后,张三还是没有来电话,说钱已经收到了,按照常理来说,一个半月之前就应该收到了,那没办法,我只得再给张三汇钱,如果这次又搞丢了,我还得再汇,直到张三打电话告诉我,钱已经到了,那么可能对于张三来说,这个传输是可靠的,因为不管丢了多少次,终究他是收到了他想要的东西,但是对于我来说,我不能把丢的钱找回来,也不能自己去监视中国邮政到底是把我的钱搞丢了,还是被他们塞进自己的腰包了,我所知道的仅仅是“张三没有收到钱”,我需要再给他寄一次。
由此可以看出,TCP 的传输并不是可靠的,它存在一个等待和重传的机制,一旦数据在网络上发生丢失,它会依赖于 ACK / SYN 这些东西来进行一个重传,而且,TCP 处理程序中存在一个计时器,如果计时器发生超时,那么它就认为数据已经丢了(当然不会像上边的例子中说的是 2 个月),再去重传,那么既然要去重传,就要保证将来一旦发生超时,TCP 处理程序还能把丢失的东西找回来,那么,TCP 处理程序在收到连接请求的时候,就会要在内存中开辟一片区域来,保存 SYN 以及数据着一系列的东西。
好,现在了解到了 TCP 的可靠与不可靠的方面,现在来说一下 TCP 的 3 次握手,这个在以前的文章中已经写过了,在这里就不再多说了,在正常情况下,3 次握手的步骤如下:
ISN
A ——————-> B
SYN/ACK
A <——————- B
ACK
A ——————-> B
在 A 向 B 发出 TCP 请求的时候,它发出一个随机的 ISN (Initial Sequence Number),B 收到后给 A 回复一个 ACK = ISN + 1,同时再回复一个自己的 SYN 号,接着会保存 A 发来的这些信息,同时再内存中开辟缓冲区进行保存,然后 A 再给 B 回复一个 ACK。经历过这三次之后,一个端到端的 TCP 连接已经建立起来了,这是正常的情况。但是,考虑这种情况,如果在 A 向 B 发出请求,B 给 A 回复并且开辟了资源之后,A 不再进行第三次的回复,会怎么办?这就好比说,张三收到钱了,也不给我打电话,我一等 2 个月,按照常理的话张三早该收到钱了,但是他还没来电话,没办法,我只有再去汇钱了,那么如果每一次都这样,我这里的钱是不是很快就汇完了?TCP 中也是这样,如果 A 一直在向B 发起 TCP 请求,B 也按照正常情况进行响应了,但是 A 不进行第三次的握手,造成半连接,那么 B 分配出去的内存资源就一直这么耗着,直到资源耗尽。
对于这种攻击,似乎是没有办法防范的,因为 TCP 的三次握手是协议规定死的,所有使用 TCP 协议的软件都必须遵循其规定,否则无法通信。但是,有一种办法,似乎可以防范,那就是限制通信源的 TCP 并发连接数,例如:如果 A 在 1 秒钟之内连续产生 100 个 TCP 半连接,那么 B 就丢弃 A 所有的 TCP 信息,并且在一定时间内不再响应攻击者的释放内存资源。这看起来似乎似乎一种行之有效的办法,可是实际并非这么简单,因为在第三层的 IP 协议是一个不可靠的协议,它的源地址可以被伪造,如果一个攻击者制造大量的伪造源地址来对受害者进行攻击,而每一个 IP 地址的 TCP 半连接只建立 3~5 次,这个时候如何防范?
基于此,一种新型的防御方式产生了—— TCP Cookie,TCP Cookie 技术针对 TCP 协议的软肋,做出了一些改进。仍以上面的通信过程为例,在 A 向 B 发出一个 TCP 请求之后,B 并不立即为 A 的 TCP 请求分配资源,而是利用 A 发来的连接信息计算出一个 Cookie 值——取 Client 端的 IP、端口,以及 Server 端的 IP、端口,再进行一种散列算法,得到一个 Cookie,取该 Cookie 的前 24 位作为 SYN 值对对方进行回复。当对方对这个 SYN/ACK 再次进行 ACK (ACK=SYN+1)回复的时候,利用某种算法和这个 ACK 来倒推回原来的 Cookie,如果在一定范围内符合,即认为是合法的 TCP 请求,对它进行响应,如果不符合,则认为其是非法的 TCP 请求,丢弃。为什么说是一定范围内呢,因为 Cookie 的变化和时间有关,那么在 TCP 超时之内的所有的 ACK 都应该是合法的,那么在倒推回去的时候,只要得到的 Cookie 和原来的 Cookie 在一个合法的时间段内相符,就认为是合法的。
这种 TCP Cookie 技术并不是无懈可击的,首先,如果攻击者大量地伪造 IP 地址进行半连接攻击,受害者会忙于计算原来的 Cookie 值而造成资源耗尽,另外,由于并发连接数太多,会造成受害者的带宽耗尽,同样也会造成拒绝服务攻击(D.o.S 可不管是耗尽资源还是耗尽带宽,它只要让受害者的服务不能正常提供即可),带宽总是有限的,所以不管怎么防范,只要 D.o.S 攻击威力足够大,任何的防范方法都不能奏效。所以想要防范 D.o.S,还是厚道些做人,不要惹火黑客,否则在遭到攻击的时候,除了拔网线,恐怕再没有别的办法了。