TCP三次握手和四次挥手过程原理及扩展(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Back_Light_F/article/details/82924585

【1】TCP如何保证可靠性传输?

  1.   在传递数据之前,会有三次握手来建立连接
  2. 应用数据被分割成TCP认为最合适的数据库(按字节编号,合理分片),这和UDP完全不同,应用程序产生的数据报长度保持不变。(将数据截断为合理的长度)
  3. 当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段。(超时重发)
  4. 当RCPU收到发自TCP连接的另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒。(对于收到的请求,给出确认响应)(之所以推迟,可能是要对包做完整校验)
  5. TCP将保持它首部和数据的校验和。这是一个端到端的校验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段。(校验出包有错,丢弃报文段,不给出响应,TCP发送数据端,超时会重发数据)
  6. 既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据进行重新排序,将收到的数据以正确的顺序交给应用层。(对失序数据进行重新排序,然后才交给应用层)
  7. 既然IP数据报会发生重复,TCP的接收端必须丢弃重复的数据。(对于重复数据,能够丢弃重复数据)
  8. TCP还能提供流量控制。TCP连接的每一方都有固定大小的缓冲空间。TCP的接收端只允许另一端发送接收端缓冲区所能接纳的数据。这将防止较快主机致使较慢主机的缓存区溢出。TCP使用的流量控制协议是可变大小的滑动窗口协议。
  9. TCP还能提供拥塞控制。当网络拥塞时,减少数据的发送。

【2】TCP建立连接之后怎么保持连接(检测连接断没断)?

         两种技术可以运用。一种是由TCP协议层实现的Keepalive机制另一种是由应用层自己实现的HeartBeat心跳包

               1.在TCP中有一个Keep-alive的机制可以检测死连接,原理很简单:当连接闲置一定的时间(参数可以设置,默认是两小时)之后,TCP协议会向对方发送一个keepalive探针包(包内没有数据),对方再收到包以后,如果连接一切正常,应该回复一个ACK;如果连接出现错误了(例如对方重启了,连接状态丢失),则应当回复一个RST;如果对方没有回复,那么,服务器每隔一定的时间(参数可以设置)再发送keepalive探针包。如果连续多个包(参数值可以设置)都被无视了,说明连接断开了。

              2.心跳包之所以叫心跳包是因为:它向心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端好活着。事实上这是为了表示长连接,至于这个包的内容,是没有什么特殊规定的,不过一般都是很小的包,或者只包含包头的一个空包。由应用程序自己发送心跳包来检测连接的健康性。客户端可以在一个Timer中或者低级别的线程中定时向服务器发送一个短小精悍的包,并等待服务器的回应,客户端程序在一定时间内没有收到服务器回应即认为连接不可用,同样,服务器在一定时间内没有收到客户端的心跳包则认为客户端已经掉线。

【3】TCP三次握手有哪些漏洞?

  1.      SYN Flood攻击   : 

            SYN Flood是DDOS攻击的方式之一,这是一种利用TCP协议缺陷,发送大量伪造的TCP连接请求,从而使得被攻击方资源耗尽(CPU满负荷或内存不足)的攻击方式。

            要明白这种攻击的基本原理,还是要从TCP连接建立的过程开始说起(上篇文章已经详细说明过,这里再概述一下):

            首先,请求端(客户端)发送一个包含SYN标志的TCP报文,SYN即同步(Synchronize),同步报文会指明客户端所使用的端口号以及TCP连接的初始化序列号。

           第二步:服务器在收到客户端的SYN报文后,将返回一个SYN+ACK的报文,表示客户端的请求被接受,同时TCP序列号加一,ACK即确认(Acknowledgment)。

          第三步:客户端也返回一个确认报文ACK给服务器端,同时TCP序列号被加一,到此一个TCP连接完成。

          以上的连接过程在TCP协议中被称为三次握手。

          问题就出现在TCp连接的三次握手中,假设一个用户向服务器发送了SYN报文后突然死机或者掉线,那么服务器在发出SYN+ACK应答报文后是无法收到客户端的ACK报文的(第三次握手无法完成),这种情况下服务器一般会不停的重试(再次发送SYN+ACK给客户端)并等待一段时间后丢失这个未完成的连接,这段时间的长度我们成为SYN Timeout(大约为30秒~2分钟);一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,但是如果有一个恶意的攻击者发送大量伪造原IP地址的攻击报文,发送到服务器端,服务器端将为了维护一个非常大的半连接队列而消耗非常多的CPU时间和内存。服务器端也将忙于处理攻击者伪造的TCP连接请求而无暇顾及客户端的正常请求(毕竟在这种时候客户端的正常请求比例非常之小),此时从正常客户的角度来看,服务器失去响应,这种情况我们称作:服务器端受到了SYN Flood攻击(SYN洪水攻击)。

       原理:攻击者首先伪造地址对服务器发起SYN请求,服务器回应(AYN+ACK)包,而真实的IP会认为,我没有发请求,不作回应。服务器没有收到回应,这样的话,服务器不知道(SYN+ACK)是否发送成功,默认情况下会重试5此(tcp_syn_retries)。这样的话,对于服务器的内存、带宽都有很大的消耗。攻击者如果处于公网,可以伪造IP的话,对于服务器就很难根据IP来判断攻击者,给防护带来很大的困难。

    解决办法: 

     第一种是缩短SYN Timeout时间:由于SYN Flood攻击的效果取决于服务器上保持的SYN半连接数,这个值=SYN攻击的频度*SYN Timeout,所以通过缩短从接收到SYN报文到确定这个报文无效并丢弃该连接的时间,例如设置为20秒以下(过低的SYN  Timeout设置可能会影响客户的正常访问),可以成倍的降低服务器的负荷。

    第二种方式是设置SYN Cookie:就是给每一个请求连接的IP地址分配一个Cookie,如果短时间内连续受到某个IP的重复SYN报文,就认定是受到了攻击,以后这个IP地址来的包会被丢弃。

上述两种方法只能对付比较原始的SYN Flood攻击,缩短SYN Timeout时间仅在对方攻击频度不高的情况下生效,SYN Cookie更依赖于对方使用真实的IP地址,如果攻击者以数万/秒的速度发送SYN报文,同时利用随机改写IP报文中的源地址,以上的方法将毫无用武之地。例如SOCK_RAW返回的套接字通过适量的设置可以自己完全控制IP头的内容从而实现IP欺骗。

  第三种方法是SYN Cache技术:此种技术在收到SYN时不急着去分配系统资源,而是先回应一个ACK报文,并在一个专用的Hash表中(Cache)中保存这种半开连接,直到收到正确的ACK报文再去分配资源。

  第四种方法是使用硬件防火墙:SYN Flood攻击很容易就被防火墙拦截

  【扩展】DDOS攻击的原理,如何防止DDOS攻击?

    DDOS是英文Distributed Dential of Service的缩写,意为“分布式拒绝服务”。

      当前主要有两种流行的DDOS攻击:

      1.SYN Flood攻击:上文已经介绍过。

      2.TCP全连接攻击:这种攻击是为了绕过常规防火墙的检查而设计的,一般情况下,常规防火墙大多具备过滤Land等DOS攻击的能力,但是对于正常的TCP连接时放过的,很多网络服务程序(如:IIS、Apache等Web服务器)能接受的TCP连接数是有限的,一旦有大量的TCP连接,则会导致网站访问非常缓慢甚至无法访问。TCP全连接攻击就是通过许多僵尸主机不断的与受害服务器建立大量的TCP连接,直到服务器的内存等资源耗尽而被拖垮,从而造成拒绝服务。这种攻击的特点是可绕过一般防火墙的防护而达到攻击目的。缺点是需要找很多僵尸主机,并且由于僵尸主机的IP是暴露的,因此容易被跟踪。

    解决办法:

  1.   限制SYN流量: 用户在路由器上分配SYN的最大流量来限制SYN封包所能占有的最高频宽,这样,当出现大量的超过所限定的SYN流量时,说明不是正常的网络访问,而是有黑客入侵。
  2. 定期扫描:定期扫描现有的网络主节点,清查可能存在的安全漏洞,对新出现的漏洞及时进行清理。
  3. 在骨干节点配置防火墙:防火墙本身能抵御DDOS攻击和其他一些攻击。在发现受到攻击的时候,可以将攻击导向一些牺牲主机,这样可以保护真正的主机不被攻击。
  4. 用足够的机器承受黑客攻击:这是一种较为理想的应对策略。如果用户拥有足够的容量和足够的资源给黑客攻击,在它不断访问用户、夺取用户资源时,自己的资源也在逐渐耗失,或许未等用户被攻击死,黑客已经无力支招了。不过此方法需要投入的资金比较多,平时大多数设备处于空闲状态。
  5. 过滤不必要的服务和端口:可以使用Inexpress、Express、Forwarding等工具来过滤不必要的服务和端口,即在路由器上过滤假IP。

3.Land攻击:Land攻击利用了TCP连接建立的三次握手过程,通过向一个目标主机发送一个用于建立请求连接的TCP SYN报文而是按对目标主机的攻击。与正常的TCP SYN报文不同的是:Land攻击报文的源IP地址和目的IP地址是相同的,都是目标主机的IP地址。这样目标主机在接收到这个SYN报文后,就会向该报文的源地址发送一个ACK报文,并建立一个TCP连接控制结构,而该报文的源地址就是自己。由于目的IP地址和源IP地址是相同的,都是目标主机的IP地址,因此这个ACK报文就发给了目标主机本身。这样如果攻击者发送了足够多的SYN报文,则目标计算机的TCB可能会耗尽,最终不能正常服务。

 【4】如果客户端发起握手请求,服务端无法立刻建立连接应该回应什么?

             RST报文,表示重置,重新建立连接。

【5】TCP与UDP的区别(或各自的优缺点),以及各自的用途和使用领域。

        1.基于连接VS无连接

           TCP是面向连接的协议,而UDP是无连接的协议。这意味着当一个客户端和一个服务器通过TCP发送数据之前,必须先建立连接,建立连接的过程即TCP三次握手。

      2.可靠性

         TCP提供交付保证,这意味着一个使用TCP协议发送的消息是保证交付给客户端的,如果消息再传输过程中丢失,那么它将重发。UDP是不可靠的,它不提供任何交付的保证,一个数据包在运输过程中可能会丢失。

     3.有序性

       消息到达网络的另一端可能是无序的,TCP协议将会为你排好序,UDP不提供任何有序性的保证。

  4.速度

      TCP速度比较慢,UDP速度比较快。因为TCP必须创建连接,以保证消息的可靠交付和和有序性,它需要做比UDP更多的事。这就是为什么UDP更适合对速度比较敏感的引用。TCP适合传输大量数据,UDP适合传输少量数据。

    5.重量级VS轻量级

    TCP是重量级的协议,UDP则是轻量级的协议。一个TCP数据报的报头大小最少是20字节,UDP数据报的报头固定是8个字节。TCP报头好包含序列号,ACK号,数据偏移量,保留,控制位,窗口,紧急指针,可选项,填充项,校验位,源端口和目的端口:

     而UDP报头只包含长度、源端口号、目的端口金和校验和:

     6.流量控制和拥塞控制

         TCP有流量控制和拥塞控制。UDP没有流量控制和拥塞控制。

    7.TCP面向字节流,UDP面向报文的

        TCP是字节流的协议,无记录边界。

        UDP发送的乜咯数据报是记录型的数据报,所谓的记录型数据报就是接收进程可以识别接收到的数据报的记录边界。

   8.TCP只能单播,不能发送广播和组播;UDP可以组播

         TCP应用场景:效率要求相对低,但是对准确性要求相对高的场景,因为传输中需要对数据确认、重发、排序等操作,相比之下效率没有UDP高。如:文件传输、邮件传输、远程登录。

        UDP应用场景:效率要求相对高,对准确性要求相对较低的场景。例如:QQ聊天等即时通讯,广播通信。

【6】为什么TCP比UDP安全,但还有很多用UDP?

  1. 无需建立连接(减少延迟)
  2. 无需维护连接状态
  3. 头部开销小,一个TCP数据报的报头大小最少是20字节,UDP数据报的报头固定是8个字节。
  4. 应用层能更好的控制要发送的数据和发送时间。UDP没有拥塞控制,因此网络中的拥塞不会影响主机的发送频率。某些实时应用要求以稳定的速度发送数据,可以容忍一些数据的丢失,但不允许有较大的延迟,而UDP正好满足这些应用的需求。

【7】TCP如何实现流量控制和拥塞控制的?TCP是怎么做错误处理的?

         流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。利用滑动窗口机制可以很方便的在TCP连接上实现对发送方的流量控制。原理就是运用TCP报文段中的窗口大小字段来控制,发送方的发送窗口大小不可以大于接收发回的窗口大小。

        所谓滑动窗口协议主要有两点:

              1.“窗口”对应的是一段可以被发送者发送的字节序列,其连续的范围称之为“窗口”;

              2.“滑动”则是指这段“允许发送的范围”是可以随着发送的过程而变化的,方式就是按顺序“滑动”。

             例子:1.TCP协议的两端分别为发送者A和接收者B,由于是全双工协议,因此A和B应该分别维护着一个独立的发送缓冲区和接收缓冲区,由于对等性(A发B收和B发A收),我们以A发送B接收的情况作为例子;

                       2.发送窗口是发送缓存中的一部分,是可以被TCP协议发送的那部分,其实应用层需要发送的所有数据都被放进了发送者的数据缓冲区;

                      3.发送窗口中相关的有四个概念:已发送并收到确认的数据(不再发送窗口和发送缓冲区之内)、已发送但未收到确认的数据(位于发送窗口之中)、允许发送但尚未发送的数据以及发送窗口外发送缓冲区内暂时不允许发送的数据。

                      4.每次成功发送数据之后,发送窗口就会在发送缓冲区中按顺序移动,将新的数据包含到窗口中准备发送。

        几种拥塞控制方法: 慢开始和拥塞避免、快重传和快恢复

【8】TCP滑动窗口协议,窗口过大或过小有什么影响?

         滑动窗口的大小对网络性能有很大的影响。

         如果滑动窗口过小,极端的情况下就是停止等待协议,发一个报文等一个ACK,会造成通信效率下降。

         如果滑动窗口过大,网络容易拥塞,容易造成接收端的缓存不够而溢出,容易产生丢包现象,则需要多次发生重复非数据,消耗了网络带宽。

【9】在流量控制的过程中,必须考虑传输效率

         1.Nagle算法:

                   Nagle算法是为了避免网络中存在太多的小包(协议头比例非常大)造成拥塞。Nagle算法就是为了尽可能发送大块数据,避免网络中充斥着许多小数据块。

                  Nagle算法要求一个TCP连接上最多只能有一个未被确认的小分组,在该分组的确认到达之前不能发送其他小分组,因此它事实上是一个扩展的停-等协议,只不过它是基于包停-等的,而不是基于字节停-等的。

                  在TCP的实现中广泛使用Nagle算法。算法如下:若发送应用进程把要发送的数据逐个字节的送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面到达的数据字节都缓存起来。当发送方收到第一个数据字符的确认后,再把发送缓存中的所有数据组装成一个报文段发送出去,同时继续对随后到达的数据进行缓存。只有在收到对前一个报文段的确认后才能继续发送下一个报文段。当数据到达较快而网络速率较慢时,用这样的方法可以明显的减少所用的网络带宽。Nagle算法还规定,当到达的数据已达到发送窗口大小的一半或已达到报文段的最大长度时,就立即发送一个报文段。

                它主要的职责就是数据的累积,实际上有三个门槛:

                           1.缓冲区中的字节数达到了一定量(超过阈值MSS)

                           2.等待了一定的时间(一般的Nagle算法都是等待200ms)

                           3.紧急数据发送

     2.糊涂窗口综合症:

               另一个问题叫做糊涂窗口综合症,有时也会使TCP的性能变坏。设想一种情况:TCP接收方的缓存已满,而交互式的应用进程一次只从接收缓存中读取1个字节(这样就使接受缓存空间仅腾出1个字节),然后向发送方发送确认,并把窗口设置为1个字节(但发送的数据报是40字节长)。接着,发送方又发来1个字节的数据(这里,发送方发送的IP数据报是41字节长)。接收方发回确认,仍然将窗口设置为1个字节。这样进行下去,使网络的效率很低。

             要解决这个问题,可以让接收方等待一段时间,使得或接收缓存已有足够空间容纳一个最长的报文段,或者等到接收缓存已有一半空闲的空间。只要出现这两种情况之一,接收方就发出确认报文,并向发送方通知当前的窗口大小。此外,发送方也不要发送太小的报文段,而是把数据积累成足够大的报文段,或达到接收方缓存的空间的一半大小。这两种方法可以配合使用。使得在发送方不发送很小的报文段的同时,接收方也不要在缓存刚刚有了一点小的空间就急忙把这个很小的窗口大小信息通知给发送方。

【10】TCP黏包

           TCP报文粘连就是:本来发送的是多个TCP报文,但是在接收端收到的却是一个报文,把多个报文合成了一个报文。

           TCP报文粘连的原因:“粘包”可能发生在发送端,也可能发生在接收端。在流传输中出现。UDP不会出现粘包,因为它有消息边界(两段数据间是有界限的)

          1.由Nagle算法造成的发送端的粘包

                 Nagle算法在上文已经介绍过了,这里就不在赘述。

         2.接收端接收不及时造成的接收端粘包

               TCP会把接收到的数据存在自己的缓冲区中,然后通知应用层取数据,当应用层由于某些原因不能及时把TCP的数据取出来,就会造成TCP缓冲区中存放了几段数据,产生报文粘连的现象。

      TCP报文粘连的解决办法:
              1.关闭Nagle算法。在socket选项中,TCP_NODELAY表示是否使用Nagle算法。

              2.接收端尽可能快速的从缓冲区取数据。

              3.可以在发送的数据中,添加一个表示数据的开头和结尾的字符,在收到消息后,通过这些字符来处理报文粘连。

猜你喜欢

转载自blog.csdn.net/Back_Light_F/article/details/82924585