实际上,这个主题是phrack 66上的一个文章,我也已经翻译了,正在校对中,等校对完成,就贴出来。如果大家有谁对这个比较感兴趣,我可以share出来,帮我校对,文章比较长;-)
BTW:感谢xixidechengbao同学指出文中的一处笔误,红色标注处;-)
TCP通过让接收方指明从发送方接收的数据字节数(即窗口大小)来进行流量控制。如果窗口为0,将有效的阻止发送方传送数据,直到窗口变为非0为止。
假如之前TCP一方A发送了一个窗口为0的通告,那么另一方B将无法
发送数据,因为A已经没有缓冲区来接受数据了,因此B只能够进行等待。这个时候,A发送一个窗口为非0的窗口更新通告(例如上面的9号报文,实际上就是一个窗口更新通告)。这里有必要说明一下这些窗口通告,这些窗口通告,都是附带在ACK报文中的,不带任何数据信息。TCP不对ACK报文段进行响应,TCP只确认那些包含有数据的ACK报文段。
如果刚才A发送的窗口非0的窗口通告在传输过程中丢失了,那会出现什么情况?
A等待接收数据,因为它已经发送出窗口非0的窗口通告;B在继续等待已经丢失的窗口通告。这样子就形成了死锁。为了避免这种死锁的发生,发送方B应该使用一个坚持定时器(persist timer)来周期性地向接收方A查询,以便发现窗口是否已增大。这些从发送方A发出的报文段称为窗口探查(window probe)。
基于TCP坚持定时器的DoS攻击的思路如上图所示。当三次握手完成之后,攻击者A向被攻击者B发送一个应用请求,被攻击者B肯定要向A进行数据响应。这个时候不同的OS会有不同的行为,这里不再详述,具体的可以查看参考2中的那篇phrack文章。攻击者A在这个时候向被攻击者发送一个窗口为0的窗口通告,这样就表明A现在没有能力继续接收这些数据,需要B进行等待,一直到A向其发送一个非0的窗口通告。
根据上面描述的TCP坚持定时器,被攻击者B会不断的向A发送窗口探测消息。实际上每次窗口探测的时间间隔是呈一个指数级增长,而且窗口探测消息的数量也不是无限制的。在Linux内核中,重传超时定时器和坚持定时器代码逻辑是相同的,只不过是根据参数的不同,动作不同,它们都是通过/proc/sys/net/ipv4/tcp_retries2进行控制。
具体的代码分析,可以阅读参考2,或者是自己看内核代码。
参考:
1. 《TCP/IP详解 卷1:协议》 第22章 TCP的坚持定时器
2.
阅读(3635) | 评论(0) | 转发(0) |