TCP三次握手

关键词含义

参考链接:https://blog.csdn.net/qzcsu/article/details/72861891

  • SYN(Synchronize Sequence Numbers)请求,大写的SYN表示标识符,seq(Sequence Number)数据序列号

    PS:一个SYN包就是仅SYN标记为1的TCP包(可以通过查TCP包头部了解),只有服务端收到客户端发来的 SYN包,才可建立连接,除此没有别的办法建立连接,要是防火墙丢弃所有的发往外网的SYN包,那么就不能让任何主机主动建立连接

  • ACK(Acknowledgement)确认标志符,ack(Acknowledgement Number)确认编号,在服务器接收了SYN请求之后,将ack设置为上一步seq随机产生的x+1,seq设置为y为数据序列编号,此时服务端向客户端发送数据,进入SYN_RECV状态,此时称为半连接状态

  • 最后一步客户端再次确认,此时不需要SYN,将ACK置为1(此时不用SYN),将seq置为x+1,将ack置为y+1发向服务端

    ACK包就是仅ACK标记为1的TCP包,,需要注意的是当三次握手完成,连接建立以后,TCP连接的每个包都会设置ACK(TCP中的只要是数据,即使是一个字节,比如SYN也是需要确认的)

TCP报文格式

TCP报文内部包含内容:

  • 源端口和目的端口,各占2个字节,确认一条唯一的TCP连接,TCP在发送数据前需要确认连接的建立,这里指的是保存双方的信息,(port和IP等信息)
  • 序号(4个字节):表示发送的数据字节流,对每个字节编号,确认TCP传输的顺序性,例如,一段报文的序号字段值是301,而携带的数据共有100字段,显然下一个报文段(如果还有的话)数据序号应该从401开始
  • 确认序号(4个字节):发送方期待接收的下一个序号,接收成功后的数据字节序列号+1,只有ACK=1时才有效
  • 数据偏移,占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远
  • 保留,占6位,保留今后使用,目前一般都是0
  • 紧急URG,当URG=1表明紧急指针字段有效,告诉系统此报文段有紧急数据
  • 确认ACK,仅当ACK=1时,确认号字段才有效,TCP规定,在连接建立后所有报文的传输都必须把ACK置1
  • 推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望再键入一个命令后立即能收到
  • ACK:确认序号的标志,ACK=1表示确认号有效,ACK=0,表示报文不含确认序号信息
  • SYN:连接确认的标志,用于建立连接,SYN=1表示请求连接
  • FIN:结束连接标志(断开连接),用于释放连接,为1时表示关闭本方连接

三次握手简单过程

  • 第一次握手:客户端主动打开连接,并向服务端发送一个SYN报文
  • 第二次握手:服务端收到SYN报文之后,会应答一个ACK报文,告诉客户端我知道你打开了,并发送一个SYN报文,告诉客户端我也打开连接了
  • 第三次握手:客户端收到SYN报文后,知道服务端打开了,然后回应一个ACK报文

三次握手过程图

过程图的解释

  • 客户端发起连接以后,通过设置一个随机数初始化seq,如果这里设置为1000,此时的ACK = 0,SYN=1
  • 服务端收到客户端的连接请求后,也给B设置一个随机数,比如这里设置为2000,表示你的请求我已经收到,我这边(待发送的数据流就从这个数开始),服务端将ACK标志位设为1,ack设置为客户端的seq+1(表示需要的下一个数据从这个数字开始)
  • 客户端收到服务端的回复后,它将seq设置为第一次往服务端发送的随机数x+1,表示你的回复我收到了,我这边(待发送的数据流从这个数字开始),此时ack是服务端的seq+1,此时不需要SYN,但是不代表SYN=0,SYN标志位在第一次握手时就已经设置为1了,后续没有改变这个值
  • 服务端在收到客户端发来的一个ACK,连接就建立好了

每一次握手的目的

  • 第一次握手,客户端发送网络包,服务端收到了,服务端可以得出结论:客户端的发送能力、服务端的接收能力正常
  • 第二次握手,服务端发送网络包,客户端收到了,客户端可以得出结论:服务端的发送能力、接收能力是正常的。客户端的接收能力、发送能力是正常的,但是此时服务器不能确认客户端的接收能力是否正常的
  • 第三次握手,客户端发送网络包,服务端收到了。服务端能得到的结论:客户端的接收、 发送能力正常,服务器自己的发送、接收能力正常。

为什么需要三次握手,客户端为什么还需要最后一次发送确认

参考链接:https://blog.csdn.net/u010918487/article/details/87207531

主要原因:防止已经失效的连接请求报文段突然传回服务端而产生错误的场景,当客户端发送连接请求,但是因为请求报文并未收到确认(可能是因为丢包、或者延迟),所以客户端会再发送一次连接请求,这次连接请求收到确认,就会建立连接,数据传输完成后,会释放连接。

  • 正常情况(丢包),客户端发出的两个连接请求报文段,其中第一个丢失,第二个到达了服务端,没有“已失效的连接请求报文段”。

  • 产生异常,客户端发送的前一个连接请求报文段只是在某些网络结点长时间滞留,延误到连接释放以后的某个时间才到达服务端,本来这个请求连接报文应该当成失效报文处理,但是服务端在收到此失效连接请求报文后,误认为是客户端重新发送的连接请求,服务端会向客户端你发送“请求报文段”(同意建立连接)。

    如果没有三次握手机制,只要服务端发出确认,连接就建立了,此时客户端并没有发送新的请求连接,因此不会理会服务端的确认,更不会向服务端发送数据,但是服务端以为连接已经建立,一直在等待客户端发来数据,这样造成服务端的资源浪费。

    采用三次握手机制,在上述现象中,服务端一直没有收到客户端的确认就知道客户端没有要求建立连接,这样减少了服务端的资源浪费。

三次握手过程中可以携带数据吗?

参考链接:https://blog.csdn.net/weixin_34198797/article/details/90687285

RFC793文档(TCP传输协议规范)里带有SYN标志的过程中包是不可以携带数据的(第三次握手过程,不需要SYN),所以可以确认前两次握手时不能携带数据的(此时连接还没建立完成,逻辑上也不允许),所以主要还是分析第三次握手是否可以携带数据。

在RFC793文档中(上图的第二句话),"Data or control which were queue for transmission may be include",可能包含等待的数据和控件。

因此,标准表示,第三次握手是可以携带数据。

假设第一次握手可以携带数据,会带来的影响

当第一次握手携带数据,如果有人恶意攻击服务器,那他每次都在第一次握手的SYN报文中放入大量的数据,因为攻击者不理会服务器的接收、发送能力是否正常,然后一直重复发送大量的SYN报文,这使得服务器需要花费很多时间、内存来接收这些报文。第一次握手可以存放数据的话,这会使得服务器更容易受到攻击(参考以下的SYN泛洪攻击)!

而对于第三次握手来说,客户端已经处于established状态,也就是,对于客户端来说,已经建立了连接,也已经知道服务器的接收、发送能力是正常了(此时客户端自己打开了连接,也知道服务端打开了连接),所以可以携带数据,服务端收到来自客户端的ACK报文,连接就建立起来了,也能接收这个数据包。

SYN Flood Attack 原理

参考连接:https://blog.csdn.net/weixin_43312097/article/details/108222477

SYN Flooing Attack (也称SYN 泛洪攻击)是一种典型的拒绝服务型攻击,使被攻击主机或网络不能良好的提供服务,间接达到攻击的目的。

SYN泛洪攻击就是客户端在短时间内伪造大量不存在的IP地址,并向服务端不断发送SYN报文,请求连接,服务端回复SYN+ACK报文,并等待客户端返回一个ACK报文确认,由于客户端的地址是伪造的并不存在,所以服务端等不到ACK确认,就会不断重发SYN和ACK报文直至超时。

并且服务端会消耗大量的内存和CPU资源,去维护这些来自客户端伪造的SYN包长时间占用半连接队列。虽然一般的主机都有超时机制和默认重传次数,但由于端口的半连接状态队列的长度是有限的,最终会导致受害主机资源耗尽,从而收到的正常SYN请求因为队列已满而被丢弃,引起网络拥塞甚至系统瘫痪。

服务端为什么容易受到SYN泛洪攻击?

服务端的资源分配是在第二次握手时分配的,而客户端的资源时在完成第三次握手时分配的,(查看上述三次握手的目的),所以服务端容易收到SYN泛洪攻击。

SYN cookie抵御SYN Flood Attack原理

参考链接:https://blog.csdn.net/qq_34777600/article/details/81946514

TCP SYN cookie 机制对 SYN Flooding Attack 攻击起到了一定防范作用。它的原理是在客户端收到 SYN 并返回 SYN+ACK 时不分配一个专门的数据区用于存放这些半连接状态的 SYN 包,而是根据这个 SYN 计算一个 cookie 值,将这个 cookie 值作为将要返回的 SYN+ACK 包的初始序列号。在收到客户端返回的 ACK 报文时,根据报文头部信息获取 cookie 值,与返回的确认序列号(初始序列号+1)进行对比,检查这个ACK报文的合法性,如果相同,则是一个正常连接,然后分配资源,建立连接。

真实的客户端会返回一个ack 并且Acknowledgment number (ack的值)为cookie+1。 但伪造的客户端,将不会作出响应。
这样我们就可以知道哪些IP对应的客户端是真实的,将真实客户端IP加入白名单,下次访问直接通过,而其他伪造的syn报文就被拦截。

posted @ 2021-03-11 13:49  简约的信仰  阅读(215)  评论(0编辑  收藏  举报