TCP协议
tcp协议是一种面向连接的,可靠的字节流服务。
可靠性:TCP 在传输过程中可以通过校验和,确认和重传机制保证可靠传输
TCP 给数据分节进行排序,并使用累计确认保证数据的顺序不变和非重复
TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制
下面来分析TCP的三次握手与四次挥手
所谓三次握手是指,建立一个TCP连接,需要客户端和服务端总共发送三个包。
第一次握手(SYN=1,seq=x):客户端发送一个TCP的SYN标志位置1的包,指明客户端准备连接服务器的端口,以及初始序列号X,保存在包头的序列号(Sequence Number)字段里。发送完毕后,客户端进入SYN_SEND 状态。
- 其中第一次的序列号是随机的,这样是为了网络安全,如果不是随机产生初始序列号,黑客将会以很容易的方式获取到你与其他主机之间的初始化序列号,并且伪造序列号进行攻击。
第二次握手(SYN=1,ACK=1,seq=y,ACKnum=x+1)
- 服务器发回确认包(ACK)应答,即SYN标志位和ACK标志位均为1.服务器端选择自己ISN序列号,放到Seq域里,同时将确认序号(Acknowledgement Number)设置为客户的ISN加1,即X+1。发送完毕后,服务器进入SYN_RCVD 状态。
第三次握手(ACK=1,ACKnum=y+1)
- 客户端再次发送确认包(ACK),SYN标志位为0,ACK标志位为1,并且把服务器发来ACK的序号字段+1,放在确定字段中发送给对方。发送完毕后,客户端发送完毕后进入ESTABLISHED状态,TCP握手结束。
在TCP握手中可能存在的攻击手段:
- syn Flooding: 当Server(B)收到Client(A)的syn请求报文时,将发送一个(ack,syn)应答报文,同时创建一个控制结构,将其加入到一个队列中,等待对方的ack报文。接收到ack报文后,双方都进入链接状。如果Server在一段时间内没有收到应答消息,则控制块将被释放。在TCP协议软件中,通常对每个端口等待建立链接的数目有一定限制,当队列长度到达设定阈值时,将丢弃后面到达的TCP Syn请求报文。如果攻击者不断发送大量的TCP syn报文,其他用户就无法再链接到被攻击者服务器。
- 防御方法:通过增加连接数目、减小超时时间,可以缓解攻击,但是无法从根本阻止攻击,是DOS的一种,可通过netstat 命令通过查看服务器网络连接情况,如果存在大量syn的连接,则有可能收到了syn flooding攻击。
- Land攻击:利用了TCP连接建立的三次握手过程,通过向一个目标计算机发送一个TCP SYN报文(连接请求报文)而完成对目标计算机的攻击。与正常的TCP SYN报文不同的是,LAND攻击报文的源IP地址和目的IP地址是相同的,都是目标计算机地址,这样目标计算机接受到SYN报文后,就会向该报文的源地址发送一个ACK报文,并建立一个TCP连接控制结构(TCB),而该报文的源地址就是自己,因此,这个ACK报文就发给了自己。这样如果攻击者发送了足够多的SYN报文,则目标计算机的TCB可能会耗尽,最终不能正常服务。这也是一种DOS攻击。可以通过kali linux 提供的如 hping3 实现伪造包的功能。
- 防御措施:可以通过防火墙、路由设备,建立规则,丢掉源地址和目标地址相同的SYN、SYN+ACK和TCP。
- TCP会话劫持:利用TCP会话劫持,可以方便地修改、伪造数据。TCP 通过三次握手建立连接以后,主要采用滑动窗口机制来验证对方发送的数据。如果对方发送的数据不在自己的接收窗口内,则丢弃此数据,这种发送序号不在对方接收窗口的状态称为非同步状态。当通信双方进入非同步状态后,攻击者可以伪造发送序号在有效接收窗口内的报文,也可以截获报文,篡改内容后,再修改发送序号,而接收方会认为数据是有效数据。TCP 劫持的关键在于使通信双方进入非同步状态。有多种方法可以达到此目的。如图2 所示,在主机A 发送syn 请求后,B 发送ack & syn 进行应答,则A 认为连接已经建立。此时,攻击者伪装成A 向B发送一个rst 报文,则B 释放连接,攻击者继续伪装成A 用自己的初始序列号和B 建立新的连接,而A 和B 对此毫不觉察。当攻击者伪装成A 和B 建立连接后,A 和B 就已经进入了非同步状态。利用Telnet 协议的NOP 命令也可以使通信双方进入非同步状态。主机B 接收到NOP 命令后,并不进行任何操作,但确认序列号将会加1。如果攻击者伪装成A 向B 发送大量的NOP 命令,则会造成A 和B 的非同步状态。
- 检测TCP 劫持的关键在于检测非同步状态。如果不断收到在接收窗口之外的数据或确认报文,则可以确定遭到TCP 劫持攻击。或者设置禁止rst报文。
- TCP伪装:主要是需要获取其他客户端的初始序列号进行伪装
- 建立连接时,攻击者需要知道被伪装者的当前初始序列号
- 发送命令时,攻击者需要知道V的响应报文的数据长度。(可以大概计算出来)
四次挥手:tcp连接的拆除需要发送四个包,因此称为四次挥手。客户端或服务器均可发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。
- 第一次握手(FIN=1,seq=x)
- 当发送FIN包,表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕后,(假设发送方式客户端)客户端进入FIN+WAIT_1状态。
- 第二次挥手(ACK=1,ACKnum=X+1)
- 服务器确认客户端的FIN包,发送一个确认包,表明自己接受到了客户端关闭连接的请求,但是还没准备好关闭连接(理论上:有可能还有数据向客户端传送)
- 第三次挥手(FIN=1, seq=y)
- 服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN置为1。发送完毕后,服务器端进入LAST_ACK 状态,等待来自客户端的最后一个ACK。
- 第四次挥手(ACK=1,ACKnum=y+1)
- 客户端接受到来自服务器的关闭请求,发送一个确认包,并进入TIME_WAIT状态,等待可能出现的要求重传ACK包。服务器端接受到这个确认包后,关闭连接,进入CLOSED状态。
- 客户端等待2MSL之后,没有收到服务器端的ACK,认为服务器端已经处于正常关闭连接,于是自己也关闭连接,进入CLOSED状态。
- 第一次握手(FIN=1,seq=x)