终于可以把TCP讲清楚了
TCP半开攻击(伪造客户端发送SYN、伪造服务器发送RST)
TCP劫持攻击
TCP劫持下的反弹Shell注入攻击
此篇Blog是对TCP建立会话、释放链接时的详解;全篇硬核,还请读者耐心品味
术语说明:
SYN:Synchronize Sequence Numbers,同步序列编号 seq:sequence,序列号 ACk:acknowledge,确认号 存在于TCP数据包结构中的flags字段中 flags中有SYN、FIN、ACK、PSH、RST、URG ack:acknowledge sequence,确认序列号 FIN:finish,完成;用于在释放TCP链接时使用TCP的数据包结构
源目端口:端口号的引入用于区分不同的流量,区分不同的服务,如HTTP为80,HTTPS为443等…
序号:保证数据的有序性,为数据分段重组时有效
确认序列号:是期望收到对方下一个报文的第一个数据字节的序号
首部长度:用于记录头部的字节数,因为存在MTU等数据分段, 记录整个包头的大小
数据偏移:指出TCP报文的数据距离TCP报文段的起始处有多远
flags
URG:告诉系统此报文段中有紧急数据 ACK:确认包,用于在连接状态时的确认机制 PSH:推送,一端的应用进程希望立即就能收到对方的响应 RST:复位,表明TCP连接中出现严重的差错,必须立即释放连接,重新建立会话 SYN:同步,同步位请求 FIN:终止,用于释放连接窗口:通知接收方,发送本报文你需要有多大的空间来接受
检验和:校验首部和数据这两部分;
紧急指针:指出本报文段中的紧急数据的字节数;
选项:长度可变,定义一些其他的可选的参数。
过程说明
第一次握手:建立连接时,客户端发送SYN=1到服务器,seq=x;并进入SYN_SENT状态,等待服务器确认;
第一个包说明了如下两件事 a.我想要和你通信; b.你可以用哪个序列号作为起始数据段来回应我第二次握手:服务器收到SYN包,必须确认客户的SYN,发送一个确认信号ACK=1,还要发送确认序列号ack=x+1,同时自己也发送一个SYN=1,即SYN+ACK包,seq=y,此时服务器进入SYN_RECV状态;
第二个包说明了如下两件事 a.我已经收到你的请求了,你可以传输数据了; b.你要用哪个序列号作为起始数据段来回应我第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认信号ACK=1,以及确认序列号ack=y+1,seq为第一次发送包的x加上1,此包发送完毕后,至此客户端和服务器进ESTABLISHED(TCP连接成功)状态,完成三次握手;
第三个包说明一件事 我已收到回复,我现在要开始传输实际数据了过程说明:
客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送
这个包告诉服务器两件事 我想终止这次会话,关闭我的发送数据的能力 我没有数据要向你发送了,但是我还是可以接受你发来的数据包的服务器B收到这个FIN,它发回一个确认信号ACK,确认序号ack为收到的序号加1;和SYN一样,一个FIN将占用一个序号
这个包告诉客户端一件事 我已经收到你想释放链接的请求了服务器B关闭与客户端A的连接,发送一个FIN给客户端A
这个包告诉客户端两件事 我也想终止这次会话,关闭我的发送数据的能力 我没有数据要向你发送了,但是我还是可以接受你发来的数据包的,注意此时C已经不能发送数据包了,但是可以发送确认信号,即ACK并不是真实的数据,其是不携带数据的客户端A发回ACK报文确认,并将确认序号ack设置为收到序号加1
这个告诉服务器一件事 我收到你也想终止此次会话的想法了,至此会话被释放关于三次握手与四次挥手还存在大量的知识、如计时器、状态、漏洞;上面的内容只是前菜,下面开始硬菜部分
结论:
两次 导致信息不匹配
四次 把TCP会话重复发送,浪费带宽资源,没有意义
举例:
如果是两次握手
C发给S的SYN因为网络原因没有送到,C就会重发SYN,而重发的过程中,S收到了C之前发送的SYN,建立完成了,当会话释放后,后发送的SYN这时到了S上,S以为是一个新的连接请求,那么又会进行会话的建立;造成错误连接S给C发送ACK确认的报文由于网络原因没有送到,因为是两次连接,没有后续C的确认,则S认为已经建立好连接;但是C这边没有收到ACK,它认为会话并没有建立完成,会重发SYN,这样就会导致信息不匹配如果是四次握手
client给server发送SYN同步报文; server收到SYN后,给client回复ACK确认报文; server给client发送SYN同步报文; client给server发送ACK确认报文。第2.3步之间,server和client没有任何的数据交互,分开发送相当于多发了一次TCP报文段,SYN和ACK标识只是TCP报头的一个标识位。很明显,这两步可以合并,从而提高连接的速度和效率
SYN,ACK种是不携带数据的, SYN是用来同步序列号的 ACK是用来确认收到的SYN的,用于确认包的概述:SYN洪范基于TCP连接的三次握手的半连接,属于DOS攻击,即拒绝服务
详细:
攻击者伪造不存在的主机IP 向服务器发送大量的SYN包,服务器维护一个未连接队列并发送回复,但是攻击者不发送第三次握手的ack,即对服务器的未连接队列造成负载,浪费CPU和内存;使服务器的缓存造成溢出,即不能处理正常的SYN请求;在半连接存活时间内有大量的半连接就会造成服务器无法服务现象
解决
1、具有SYN proxy(SYN代理)功能的防火墙 2、加快淘汰无效SYN请求 3、SYN Cookie SYN Cookie是对TCP服务器端的三次握手协议作一些修改,专门用来防范SYN Flood攻击的一种手段。它的原理是,在TCP服务器收到TCP SYN包并返回TCP SYN+ACK包时,不分配一个专门的数据区,而是根据这个SYN包计算出一个cookie值。在收到TCP ACK包时,TCP服务器在根据那个cookie值检查这个TCP ACK包的合法性。如果合法,再分配专门的数据区进行处理未来的TCP连接
未连接队列
在TCP的三次握手中服务器端维护一个未连接队列,收到客户端发来的SYN后开设一个条目,此条目表明收到了SYN包,并向客户端发送确认,正在等待客户的确认包,这个连接的状态在服务器就处于SYN_Recv;当后来收到确认后,就会删除这个条目,至此进入eatablished状态TIME_WAIT状态
TIME_WAIT状态存在有两个原因。
<1>可靠终止TCP连接。
如果最后一个ACK报文因为网络原因被丢弃,此时server因为没有收到ACK而超时重传FIN报文,处于TIME_WAIT状态的client可以继续对FIN报文做回复,向server发送ACK报文。
<2>保证让迟来的TCP报文段有足够的时间被识别和丢弃。
连接结束了,网络中的延迟报文也应该被丢弃掉,以免影响立刻建立的新连接。
TCP叫做面向连接的可靠传输协议
总结
1.发送方必须把已发送的数据包保留在缓冲区; 2.并为每个已发送的数据包启动一个超时定时器; 3.如在定时器超时之前收到了对方发来的应答信息(可能是对本包的应答,也可以是对本包后续包的应答),则释放该数据包占用的缓冲区; 4.否则,重传该数据包,直到收到应答或重传次数超过规定的最大次数为止。 5.接收方收到数据包后,先进行CRC校验,如果正确则把数据交给上层协议,然后给发送方发送一个累计应答包,表明该数据已收到,如果接收方正好也有数据要发给发送方,应答包也可放在数据包中捎带过去。说到拥塞控制,不如先来看看如果没有拥塞会怎么样?
可见,死锁导致的吞吐量为0,将会十分可怕,整个TCP队列、会话全部终止,网络瘫痪
目的:为了防止过多的数据注入到网络中,防止过载情况的产生
代价:
需要获得网络内部流量分布的信息。在实施拥塞控制之前,还需要在结点之间交换信息和各种命令,以便选择控制的策略和实施控制。这样就产生了额外的开销。拥塞控制还需要将一些资源分配给各个用户单独使用,使得网络资源能更好的实现共享
术语解释
cwnd:拥塞窗口 滑动窗口: 1、是传输层进行流控的一种措施,接收方通过通告发送方自己的窗口大小,从而控制发送方的发送速度,从而达到防止发送方发送速度过快而导致自己被淹没的目的; 2、TCP的滑动窗口解决了端到端的流量控制问题,允许接受方对传输进行限制,直到它拥有足够的缓冲空间来容纳更多的数据 拥塞窗口: 1、也看做是发送端用来进行流量控制的窗口 2、是发送方维护的一个的状态变量,它会根据网络的拥塞程度动态变化的 3、与发送窗口 swnd 和接收窗口 rwnd 是约等于的关系,那么由于入了拥塞窗口的概念后,此时发送窗口的值是swnd = min(cwnd, rwnd),也就是拥塞窗口和接收窗口中的最小值 拥塞窗口cwnd 变化的规则:详情关于下面要提到的慢开始、拥塞避免 只要网络中没有出现拥塞,cwnd 就会增大; 但网络中出现了拥塞,cwnd 就减少; ssthresh:慢开始门限 在慢开始的过程中,由于cwnd慢慢试探的增长(指数增长),达到ssthresh时,进行拥塞避免,即加法增大(线性的增大) 慢开始 由于不清楚网络的负载情况,从小到大以指数的增长方式慢慢探测; 缺点: a.需要获得网络内部流量分布的信息,浪费可用的网络容量,额外开销; b.由于要估算ssthresh(慢开始门限),耗时较长拥塞避免 当cwnd(拥塞窗口) = ssthresh时,开始以线性增长的模式加法增大 缺点:只能使网络不易出现拥塞 无论是慢启动算法还是拥塞避免算法,只要判断网络出现拥塞,就要把慢启动开始门限(ssthresh)设置为发送窗口的一半(>=2);cwnd设置为1,然后再使用慢启动算法,这样做的目的能迅速的减少网络当中的数据传输,使发生拥塞的路由器能够把队列中堆积的分组处理完毕。拥塞窗口是按照线性的规律增长
快重传 当等待TCP的重传计时器过长时,连续收到三个重复确认后,就立即发送未被确认的data详细解释:
上图中,M3这个数据由于一些网络的原因,可能丢失或延迟等问题,没有送到接收方这一侧,此时,对于M3这个数据之后的数据再发送时,接受方将不会在进行确认ACK的回应,而是重复确认未到达数据M3之前的一个数据M2;当发送方连续收到三个重复的ACK后,就会理解重传收到ACK的数据的后一个数据M3
快恢复 当出现快重传的情况时,不进行慢启动,因为这样会使数据传输的效率降低;此时将cwnd置为ssthresh的一半,然后进行加法增大,如下图AIMD
乘法减小:无论慢/拥,网络超时 直接将cwnd=1;ssthresh减半
加法增大:当慢启动找到慢启动门限值后,缓慢增大cwnd,即线性的缓慢增大,防止过早的拥塞
问题
为什么需要快重传与快恢复?
当个别报文段丢失后,其实此时并没有发生拥塞,若想当然的运行慢启动,就会降低网络传输的效率
1.慢启动阶段(slow start):发送方一开始便向网络发送多个报文段,直至达到接收方通告的窗口大小为止。当发送方和接收方处于同一个局域网时,这种方式是可以的。但是如果在发送方和接收方之间存在多个路由器和速率较慢的链路时,就有可能出现一些问题。一些中间路由器必须缓存分组,并有可能耗尽存储器的空间 2.拥塞避免阶段(congestion avoidance):当发现超时或长时间未收到数据包时,则表示有丢包事件,此时网络已发生拥塞现象,此时要进行相应的拥塞控制;将慢启动阈值设置为当前拥塞窗口的一半;如检测到超时,拥塞窗口就被置为1如果拥塞窗口小于或等于慢启动阈值,TCP重新进人慢启动阶段;如果拥塞窗口大于慢启动阈值,TCP执行拥塞避免算法 3.快速重传阶段(fast retransmit):当TCP源端收到到三个相同的ACK副本时,即认为有数据包丢失,则源端重传丢失的数据包,而不必等待RTO超时;同时将ssthresh设置为当前cwnd值的一半,并且将cwnd减为原先的一半 4.快速恢复阶段(fast recovery) :当”旧”数据包离开网络后,才能发送”新”数据包进入网络,即同一时刻在网络中传输的数据包数量是恒定的。如果发送方收到一个重复的ACK(连续收到三个相同的数据包),则认为已经有一个数据包离开了网络,此时将cwnd置为ssthresh的一半,然后进行加法增大,即以线性增长的方式慢慢的增大cwnd概述:
1.重传计时器:为了控制丢失的报文段或丢弃的报文段,也就是对报文段确认的等待时间 2.坚持计时器:专门为对付零窗口通知而设立的 3.保活计时器:每当服务器收到客户的信息,就将keeplive timer复位,超时通常设置2小时,若服务器超过2小时还没有收到来自客户的信息,就发送探测报文段,若发送了10个探测报文段(没75秒发送一个)还没收到响应,则终止连接 4.时间等待计时器:在连接终止期使用,当TCP关闭连接时,并不认为这个连接就真正关闭了,在时间等待期间,连接还处于一种中间过度状态。这样就可以时重复的fin报文段在到达终点后被丢弃,这个计时器的值通常设置为一格报文段寿命期望值的两倍。重传计数器 60s
1、当计时器截至时间之前收到了报文的确认,撤销计时器 2、计时器时间没有收到确认信号,重发报文,并将计时器复位 TCP在发送一份数据后,启动重传定时器,在经过若干时间后如果没有收到ACK,则重传该数据,这个时间间隔通常下: 1s, 3s, 6s, 12s, 24, 48s, 和多个64s 这个指数关系被称为指数退避。TCP会一直尝试重传该数据,在9分钟以后放弃。坚持计时器 门限60s
前提:当接收端的窗口值为0时,那么当接收端的确认报文丢失后,由于窗口值为0,则接收端在等待发送端发送数据,发送端等待着接收端发送确认,至此,造成死锁 那么当发送端得知接收端的窗口大小为0时,启动坚持计时器;在这个时间内,还是没有收到确认,就主动发送探测报文 探测报文:1Byte、一个序号、不需要被确认;只是用于提醒接收端,让其重新发送确认报文 如果还是没有回应,重发探测报文,计时器时间加倍,知道增大到60s,之后就以60s的周期发送,直到窗口重新打开TCP规定,即使窗口大小为0,必须接收的三种报文: 零窗口探测报文、确认报文、携带紧急数据的报文
保活计时器 2h
目的:用来防止两个TCP之间的连接出现长时期的空闲 cilent出现故障时,这个会话就处于空闲的打开状态,此时S会向C发送探测报文,如果连续发送了10个探测报文(每75s一个)都没有反应,则S主动断开连接时间等待计时器(Time_Wait) 2MSL(最大报文段生存时间)
MSL:报文最大生存时间,任何报文在网络上超过MSL之后,将直接被丢弃 C收到S的FIN后,进入Time_Wait,时间设置为2MSL 中间过度状态 1、保证2MSL时间内S可以收到最后一个ACK 2、保证之前由于网络原因的一些报文不会再关闭之后再次骚扰S,因为网络中数据包到达目的的时间是不确定的延迟应答计时器
延迟应答也被成为捎带ACK,延迟应答是为了提高网络传输的效率 服务端收到客户端的数据后, 不是立刻回ACK给客户端, 而是等一段时间(一般最大200ms); 这样如果服务端要是有数据需要发给客户端,那么这个ACK就和服务端的数据一起发给客户端了,这样比立即回给客户端一个ACK节省了一个数据包