SDN:优雅的间歇性访问限制
目的:设有一台PC机(Host1),一台Web服务器(Host2)提供简单的静态网页访问服务。通过RYU控制网络流,限制PC访问服务器的频率,如两次访问的间隔不能低于5秒。
应用场景: ①为 付费用户 和 免费用户 提供差异化服务 ②小型站点、个人站点、未做优化站点的负载缓解 ③……
在详细了解TCP三次握手、四次挥手、RST强制重置,以及HTTP包交互全程的基础上,本项目达成了以下特色:
限制访问时,返回给PC友好的WEB页面提示,而不是仅仅通过流表把包丢弃,以及由此导致的PC用户浏览器持续等待、多次TCP重传、多次HTTP尝试。
本项目中,由于TCP重传机制的特殊性,控制器不对握手和挥手等TCP控制交互阶段进行控制,只对HTTP报文进行控制。控制器伪装了服务器的角色,好似第三方劫持会话。
对于80目的端口的TCP控制交互报文,控制器通过packet-out让其顺利转发。
当正常访问时,控制器通过packet-out让HTTP请求顺利转发,同时下一条从服务器到PC的反向流表;
当限制访问时,控制器通过: ①提取计算Seq、提取计算Ack、设置bits协议标志位、设置window_size来构造一个TCP报文; ②同时依照HTTP协议构造一个web页面数据包(访问限制提示页面) ③构造Ip包 ④构造Ethernet帧
然后按照HTTP -> TCP -> IP -> Ethernet 的顺序层层封装,将其发回给PC,PC即可显示限制访问的提示页面。一般情况下还不算完,此时虽然PC浏览器退出了等待状态,但是PC、服务器双方的TCP连接仍然保持,仍在占用资源。
由此,我通过巧妙构造TCP协议字段和HTTP协议字段,利用TCP挥手阶段的RST机制,让PC端向服务器主动发起RST报文,随后PC端和服务器会各自强制断开连接。
到此,一次优雅的访问限制圆满结束,PC、服务器的资源都不被持续占用,用户也不用茫然地等待,同时能得到友好的提示! 具体细节,详见下方的各项解析,以及下文的实验演示中的截图。(可放大观看)
TCP这个孩子非常执着,无论是握手阶段、数据通信阶段,还是挥手阶段,只要没有收到ACK,就会以“翻番”的时间间隔去重发数据包,1、2、4、8、16、32秒……。
开发过程中,我观察到如果单纯以丢包作为限制手段,TCP会持续握手握上五分钟之久!并且会持续下去。平日里我们看到的TCP报告连接失败,可能是对方积极地使用RST给了我们失败的指示。
因此,如果单纯地丢包,会导致PC浏览器持续处于等待网页的状态,即使我们设置限制间隔为一分钟,但其实一分钟过后自动打开的网页,是属于“同一次”访问。
RST协议字段在我这个项目中,可谓是一个神器,它是一个TCP协议字段,会让通信双方各自强制关闭连接。RST常出现在连接本身出现严重差错、通信对端端口不可达、在已关闭的socket上收到数据等情况。
在这里,我们利用了“连接本身出现严重差错”这一条:
在HTTP响应数据包中,我们给TCP设置一个错误的Ack和一个正确的Seq,使得PC发起HTTP Request的超时重传,此时RYU会再次响应带有错误Ack却有正确Seq的响应,这就导致了PC端发现连接出现严重差错,中断连接!
经我分析,由于RYU第一次的响应是正常的通信过程,所以PC重传的HTTP Request中,TCP Ack已经累积递增,然后RYU的第二次响应中,有正确的Seq,说明已经是收到了重传的HTTP Request,按理说它的TCP Ack应该累积递增,但是却没有,而仍然是我们设定的错误Ack。 这就产生了矛盾!
因此PC端就主动发起了RST连接中断,特插图如下: