目录
TCP协议
tcp报文组成
源端口号(Source Port,16比特)和目的端口号(Destination Port,16比特):分别表示发送方和接收方的端口号。
序号(Sequence Number,32比特):该TCP段中携带的用户数据中第一个字节的编号,编号是以字节为单位的。可以表示4GB数据,足够保证在分组的生命期内不会出现重复的顺序号。
确认号(Acknowledgment Number,32比特):下一个期望接收的字节的顺序号。即表示对顺序号之前的数据已可靠收到的确认
数据偏移(Data Offset,4比特):指示TCP数据开始的位置,也即TCP首部长度,以32比特为单位。
保留(Reserved,6比特)
控制标志(Control Bits,6比特)
URG:紧急数据标志,同时紧急指针指出本TCP段中紧急数据的位置。
ACK:确认字段有效标志,为1,即该报文段包含一个对已被成功接收报文段的确认。如为零,确认字段无效,
PSH:要求马上发送数据,实现PUSH功能。
RST:对TCP连接进行复位,当TCP发生故障时,设置本标志,以使通信双方重新实现同步。还用于拒绝非法数据段和连接请求。
SYN:建立TCP连接,一般SYN=1和ACK=0表示发起/请求建立TCP连接,而 SYN=1和ACK=1表示响应/接收建立TCP连接
FIN:连接释放,置1表示发送方已经没有数据发送了,但是它仍然可以接收数据。
窗口大小(Window Size,16比特):指示接收方滑动窗口的大小,用于实现TCP流量控制,表示接收方愿意接收的字节数量。
校验和(Checksum,16比特):实现对TCP数据的校验。在计算检验和时包括TCP头部、用户数据以及一个TCP伪头部。
伪头部格式:
紧急指针(Urgent Pointer,16比特):当URG位有效时,紧急指针指示紧急数据的结束位置。相对于当前序列号的字节偏移值。
选项(Options,变长:0~40字节):提供了相应的扩展机制,用于实现除TCP基本头部指定功能外的扩展功能。
填充(Padding,变长):总是以0作填充,可确保TCP头部以32比特边界结束。
数据(Data,变长):数据部分用于传送TCP用户数据。
TCP协议中的常见计时器
TCP协议通常包含四种计时器:重传计时器,持续计时器,保活计时器和时间等待计时器。
重传计时器(Retransmission Timer),该计时器用于整个连接期间,用于处理RTO(重传超时)。当一个报文从发送队列发出去后,就启动该计时器,若在RTO之内收到了该报文的ACK,则停止该重传计时器;若t>=RTO都还没有收到报文的ACK,则重传该报文,并清空该重传计时器。
注意:若ACK报文捎带其它信息,则不会为该报文设置重传计时器。
持续计时器(Persistent Timer),用于处理零窗体值的通过,防止"死锁"现象。
假若接收端的TCP要命令发送端的TCP停止发送报文段时,就向发送方发送TCP发送一个报文段,该报文的窗体大小字段为0,这就是零窗体值。发送端的TCP收到该零值窗体值报文后,就会停止向接收端的TCP发送报文,直到接收端的TCP发送一个窗体大小非0的ACK报文为止。。。
当接收端向发送端发送ACK应答的时候,假如该应答在传输的路途中丢失了,发送端并没有收到该应答,不再向接收端发送消息;而接收端却认为自己已经做出了回应,一直处在等待的状态中。此时这种情况就是传说中的"死锁"
为了解决上述的"死锁现象",TCP中存在一个持续计时器。启动后,在未超时期间,若收到了接收端的非0窗体的通知,则停止该计时器;若该持续计时器超时了,则发送TCP就发送一个特殊的探測报文段,该报文段仅包括1B的新数据,该报文不须要确认。探測报文的作用在于提醒对方(目的能够记录在数据部分),重传上次发送方发送的那个ACK报文(即那个非0值窗体的报文)。
注意:TCP规定,接收窗体的rwnd=0,也必须接收这三种报文段:零窗体探測报文段、确认报文段和携带紧急数据的报文段。
保活计时器(Keeplive Timer),防止两端的TCP在连接期间长时间处于空暇状态。一般是server设置的计时器,超时通常设置为2h,当server超过了2h还没有收到客户的任何信息,server就向客户发送过一个探測报文段,若连续发送了10个探測报文段(每个75s一个)还没有响应,就觉得客户出了故障,直接终止这个连接。
时间等待计时器(Time-Wait timer),超时时间=2MSL,max segment lifetime,这个计时器有两个作用:
1).保证在2MSL时间内,server端可以收到最后一个ACK;
2).可以保证之前某些在网络中滞留非常久的发给server的报文不会在本次连接连接关闭后再去骚扰server。
注意:最后两次挥手期间,启动了两种计时器,server向client发送FIN后启动重传计时器;client收到FIN后,向server发送ACK,同一时间也启动Time-Wait计时器(时间长度为2MSL)
TCP三次握手方法建立连接
TCP建立连接是一个不对称的过程,一方处于被动方式,一方处于主动方式,主动方式的客户方要求和被动方式的服务方建立一条传输连接。
1.客户方首先发送一个不包含任何用户数据,只包含一个初始序号x(client-isn), SYN =1 , ACK=0 的SYN报文段
2.服务方接收到了这个报文段,其TCP实体首先检查是否有进程在目的端口出进行侦听,如果没有,就发送RST标志为1的应答,拒绝连接,否则就发送确认号字段为x+1, ACK=1, SYN =1,序号字段为服务方方选择的初始序号y (sever-isn)的SYNACK报文段。同时服务器为该TCP连接分配缓存和变量。
3。客户方发送一个TCP报文段,其中SYN=0,ACK=1,序号字段x+1,确认号字段是y+1。客户方为该TCP连接分配缓存和变量。
建立连接的请求中,标志位SYN都要置为1,在这种请求中会告知MSS段大小,就是本机希望接收TCP包的最大大小。
发送的数据TCP包都有一个序号。它是这么得来的:最初发送SYN时,有一个初始序号,根据RFC的定义,各个操作系统的实现都是与系统时间相关的。之后,序号的值会不断的增加,比如原来的序号是100,如果这个TCP包的数据有10个字节,那么下次的TCP包序号会变成110。
滑动窗口用于加速传输,比如发了一个seq=100的包,理应收到这个包的确认ack=101后再继续发下一个包,但有了滑动窗口,只要新包的seq与没有得到确认的最小seq之差小于滑动窗口大小,就可以继续发。
TCP终止连接过程
参考原文链接:https://blog.csdn.net/qq_37884273/article/details/82188586
1、客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2、服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
3、服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
4、服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
TCP序号猜测
TCP连接的安全性与随机初始序号有关 (ISNs),如果攻击者知道该序号,就可以伪造数据包
问题:
很多操作系统在ISN生成器上的设计过于简单,用当前时间作为种子
RFC793 – 每4微秒ISN增加1
Windows NT 4.0 – ISN = ms * 10 % 2^32
攻击者可以测量目标的ISN生成器,发送NTP请求,访问HTTP, FTP, echo等服务
常见TCP攻击
SYN Flood(DDos)
攻击原理
引用博客:https://blog.csdn.net/qq_34777600/article/details/81946514
攻击者首先伪造地址对服务器发起SYN请求,服务器会回应一个ACK+SYN(可以+请确认)。而真实的IP会认为,我没有发送请求,不作回应。服务器没有收到回应,会重试3-5次并且等待一个SYN Time(一般30秒-2分钟)后,丢弃这个连接。
如果攻击者大量发送这种伪造源地址的SYN请求,服务器端将会消耗非常多的资源来处理这种半连接,保存遍历会消耗非常多的CPU时间和内存,何况还要不断对这个列表中的IP进行SYN+ACK的重试。TCP是可靠协议,这时就会重传报文,默认重试次数为5次,重试的间隔时间从1s开始每次都番倍,分别为1s + 2s + 4s + 8s +16s = 31s,第5次发出后还要等32s才知道第5次也超时了,所以一共是31 + 32 = 63s。
假的syn报文,会占用TCP准备队列63s之久,而半连接队列默认为1024,系统默认不同,可
cat /proc/sys/net/ipv4/tcp_max_syn_backlog c
查看。也就是说在没有任何防护的情况下,每秒发送200个伪造syn包,就足够撑爆半连接队列,从而使真正的连接无法建立,无法响应正常请求。 最后的结果是服务器无暇理睬正常的连接请求—拒绝服务。
攻击细节:
为了提高发送效率在服务端产生更多的SYN等待队列,攻击程序在填充包头时,IP首部和TCP首部都不填充可选的字段,因此IP首部长度恰好是20字节,TCP首部也是20字节,共40字节。
对于以太网来说,最小的包长度数据段必须达到46字节,而攻击报文只有40字节,因此,网卡在发送时,会做一些处理,在TCP首部的末尾,填充6个0来满足最小包的长度要求。这个时候,整个数据包的长度为14字节的以太网头,20字节的IP头,20字节的TCP头,再加上因为最小包长度要求而填充的6个字节的0,一共是60字节。
但这还没有结束。以太网在传输数据时,还有CRC检验的要求。网卡会在发送数据之前对数据包进行CRC检验,将4字节的CRC值附加到包头的最后面。这个时候,数据包长度已不再是40字节,而是变成64字节了,这就是常说的SYN小包攻击,数据包结构如下:
|14字节以太网头部|20字节IP头部|20字节TCP|6字节填充|4字节检验|
|目的MAC|源MAC|协议类型| IP头 |TCP头|以太网填充 | CRC检验 |
到64字节时,SYN数据包已经填充完成,准备开始传输了。攻击数据包很小,远远不够最大传输单元(MTU)的1500字节,因此不会被分片。那么这些数据包就像生产流水线上的罐头一样,一个包连着一个包紧密地挤在一起传输吗?事实上不是这样的。
以太网在传输时,还有前导码(preamble)和帧间距(inter-frame gap)。其中前导码占8字节(byte),即64比特位。前导码前面的7字节都是10101010,1和0间隔而成。但第八个字节就变成了10101011,当主机监测到连续的两个1时,就知道后面开始是数据了。在网络传输时,数据的结构如下:
|8字节前导码|6字节目的MAC地址|6字节源MAC地址|2字节上层协议类型|20字节IP头|20字节TCP头|6字节以太网填充|4字节CRC检验|12字节帧间距|
也就是说,一个本来只有40字节的SYN包,在网络上传输时占的带宽,其实是84字节。
防御策略
cookie源认证:
原理是syn报文首先由DDOS防护系统来响应syn_ack。带上特定的sequence number (记为cookie)。真实的客户端会返回一个ack 并且Acknowledgment number 为cookie+1。 而伪造的客户端,将不会作出响应。这样我们就可以知道那些IP对应的客户端是真实的,将真实客户端IP加入白名单。下次访问直接通过,而其他伪造的syn报文就被拦截。
reset认证:
Reset认证利用的是TCP协议的可靠性,也是首先由DDOS防护系统来响应syn。防护设备收到syn后响应syn_ack,将Acknowledgement number (确认号)设为特定值(记为cookie)。当真实客户端收到这个报文时,发现确认号不正确,将发送reset报文,并且sequence number 为cookie + 1。 而伪造的源,将不会有任何回应。这样我们就可以将真实的客户端IP加入白名单。
TCP首包丢弃:
该算法利用了TCP/IP协议的重传特性,来自某个源IP的第一个syn包到达时被直接丢弃并记录状态(五元组),在该源IP的第2个syn包到达时进行验证,然后放行。
当防御设备接到一个IP地址的SYN报文后:
第一步:接受到syn报文 -> 简单比对该IP是否存在于白名单中: 存在则转发到后端,否则进行第2步
第二步:不存在于白名单中 -> 检查是否是该IP在一定时间段内的首次SYN报文: 不是则进行第3步,是则进行第5步
第三步:不是首次SYN报文 -> 检查是否重传报文: 是重传则转发并加入白名单,不是则丢弃并加入黑名单
第四步:是首次SYN报文 -> 丢弃并等待一段时间以试图接受该IP的SYN重传报文,等待超时则判定为攻击报文加入黑名单。
第五步:tcp三次握手建立连接
首包丢弃方案对用户体验会略有影响,因为丢弃首包重传会增大业务的响应时间,有鉴于此发展出了一种更优的TCP Proxy方案。所有的SYN数据报文由清洗设备接受,按照SYN Cookie方案处理。和设备成功建立了TCP三次握手的IP地址被判定为合法用户加入白名单,由设备伪装真实客户端IP地址再与真实服务器完成三次握手,随后转发数据。而指定时间内没有和设备完成三次握手的IP地址,被判定为恶意IP地址屏蔽一定时间。除了SYN Cookie结合TCP Proxy外,清洗设备还具备多种畸形TCP标志位数据包探测的能力,通过对SYN报文返回非预期应答测试客户端反应的方式来鉴别正常访问和恶意行为。
RST攻击
RST标志位
RST表示复位,用来异常的关闭连接,在TCP的设计中它是不可或缺的。就像上面说的一样,发送RST包关闭连接时,不必等缓冲区的包都发出去(不像上面的FIN包),直接就丢弃缓存区的包发送RST包。而接收端收到RST包后,也不必发送ACK包来确认。
TCP处理程序会在自己认为的异常时刻发送RST包。例如,A向B发起连接,但B之上并未监听相应的端口,这时B操作系统上的TCP处理程序会发RST包。
攻击原理
假设现在有一个合法用户(1.1.1.1)已经同服务器建立了正常的连接,攻击者构造攻击的TCP数据,伪装自己的IP为1.1.1.1,并向服务器发送 一个带有RST位的TCP数据段。服务器接收到这样的数据后,认为从1.1.1.1发送的连接有错误,就会清空缓冲区中建立好的连接。这时,如果合法用户 1.1.1.1再发送合法数据,服务器就已经没有这样的连接了,该用户就必须重新开始建立连接。
一个TCP连接都是四元组,由源IP、源端口、目标IP、目标端口唯一确定一个连接。所以,如果C要伪造A发给B的包,要在上面提到的IP头和TCP头,把源IP、源端口、目标IP、目标端口都填对。这里B作为服务器,IP和端口是公开的,A是我们要下手的目标,IP当然知道,但A的源端口就不清楚了,因为这可能是A随机生成的。当然,如果能够对常见的OS如windows和linux找出生成source port规律的话,还是可以搞定的。
防御策略
使用防火墙将进来的包带RST位的包丢弃
会话劫持
基本原理
会话劫就是在一次正常的通信过程中,黑客作为第三方参与到其中,或者是在数据流(例如基于TCP的会话)里注射额外的信息,或者是将双方的通信模式暗中改变,即从直接联系变成有黑客联系。TCP会话劫持的攻击方式可以对基于TCP的任何应用发起攻击,如HTTP、FTP、Telnet等。对于攻击者来说,所必须要做的就是窥探到正在进行TCP通信的两台主机之间传送的报文,这样攻击者就可以得知该报文的源IP、源TCP端口号、目的IP、目的TCP端号,从而可以得知其中一台主机对将要收到的下一个TCP报文段中seq和ackseq值的要求。在该合法主机收到另一台合法主机发送的TCP报文前,攻击者根据所截获的信息向该主机发出一个带有净荷的TCP报文,如果该主机先收到攻击报文,就可以把合法的TCP会话建立在攻击主机与被攻击主机之间。
两种类型
中间人攻击(Man In The Middle,简称MITM)是一种“间接”的入侵攻击,这种攻击模式是通过各种技术手段将受入侵者控制的一台计算机虚拟放置在网络连接中的两台通信计算机之间,这台计算机就称为“中间人”。
注射式攻击(Injection)不会改变会话双方的通讯流,而是在双方正常的通讯流插入恶意数据。在注射式攻击中,需要实现两种技术:1)IP欺骗,2)预测TCP序列号。对于IP欺骗,有两种情况需要用到:1)隐藏自己的IP地址;2)利用两台机器之间的信任关系实施入侵。在Unix/Linux平台上,可以直接使用Socket构造IP包,在IP头中填上虚假的IP地址,但需要root权限;在Windows平台上,不能使用Winsock,需要使用Winpacp(也可以使用Libnet)。例如在Linux系统,首先打开一个Raw Socket(原始套接字),然后自己编写IP头及其他数据。
两种形式
被动劫持实际上就是在后台监视双方会话的数据流,丛中获得敏感数据
主动劫持将会话当中的某一台主机“踢”下线,然后由攻击者取代并接管会话,这种攻击方法危害非常大,攻击者可以做很多事情,比如“cat etc/master.passwd”(FreeBSD下的Shadow文件)。
TCP协议的序列号
在每一个数据包中,都有两段序列号,它们分别为:
SEQ:当前数据包中的第一个字节的序号
ACK:期望收到对方数据包中第一个字节的序号
双方进行一次正常连接
服务器(Server)
S_SEQ:将要发送的下一个字节的序号
S_ACK:将要接收的下一个字节的序号
S_WIND:接收窗口
客户端(Client)
C_SEQ:将要发送的下一个字节的序号
C_ACK:将要接收的下一个字节的序号
C_WIND:接收窗口
它们之间必须符合下面的逻辑关系,否则该数据包会被丢弃,并且返回一个ACK包(包含期望的序列号)。
C_ACK <= C_SEQ <= C_ACK + C_WIND
S_ACK <= S_SEQ <= S_ACK + S_WIND
如果不符合上边的逻辑关系,就会引申出ACK风暴(Storm)
ACK风暴(Storm)
当会话双方接收到一个不期望的数据包后,就会用自己期望的序列号返回ACK包
而在另一端,这个数据包也不是所期望的,就会再次以自己期望的序列号返回ACK
于是,就这样来回往返,形成了恶性循环,最终导致ACK风暴。
解决办法
先进行ARP欺骗,使双方的数据包“正常”的发送到攻击者这里
然后设置包转发,最后就可以进行会话劫持了,而且不必担心会有ACK风暴出现。
TCP会话劫持过程
假设现在主机A和主机B进行一次TCP会话,C为攻击者,劫持过程如下:
A向B发送一个数据包
SEQ (hex): X ACK (hex): Y
FLAGS: -AP--- Window: ZZZZ,包大小为:60
B回应A一个数据包
SEQ (hex): Y ACK (hex): X+60
FLAGS: -AP--- Window: ZZZZ,包大小为:50
A向B回应一个数据包
SEQ (hex): X+60 ACK (hex): Y+50
FLAGS: -AP--- Window: ZZZZ,包大小为:40
B向A回应一个数据包
SEQ (hex): Y+50 ACK (hex): X+100
FLAGS: -AP--- Window: ZZZZ,包大小为:30
攻击者C冒充主机A给主机B发送一个数据包
SEQ (hex): X+100 ACK (hex): Y+80
FLAGS: -AP--- Window: ZZZZ,包大小为:20
B向A回应一个数据包
SEQ (hex): Y+80 ACK (hex): X+120
FLAGS: -AP--- Window: ZZZZ,包大小为:10
现在,主机B执行了攻击者C冒充主机A发送过来的命令,并且返回给主机A一个数据包;但是,主机A并不能识别主机B发送过来的数据包,所以主机A会以期望的序列号返回给主机B一个数据包,随即形成ACK风暴。
防御策略
首先应该使用交换式网络替代共享式网络,虽然有工具可以在交换环境中实现会话劫持,但还是应该使用交换式网络替代共享式网络,因为这样可以防范最基本的嗅探攻击。
然而,最根本的解决办法是采用加密通讯,使用SSH代替Telnet、使用SSL代替HTTP,或者干脆使用IPSec/VPN, 这样会话劫持就无用武之地了。
其次,监视网络流量,如发现网络中出现大量的ACK包,则有可能已被进行了会话劫持攻击。
TCP的安全性
现在的操作系统一般随机选择 ISN,大大增加了猜测难度和off-path会话劫持的难度。
ISN:
RFC1948中提出了一个较好的初始化序列号ISN随机生成算法。
ISN = M + F(localhost, localport, remotehost, remoteport).
M是一个计时器,这个计时器每隔4毫秒加1。
F是一个Hash算法,根据源IP、目的IP、源端口、目的端口生成一个随机数值。
要保证hash算法不能被外部轻易推算得出,用MD5算法是一个比较好的选择。
TCP是否安全?
On-path攻击者可以看到所有的信息,不需要猜测ISN
可以任意丢袭、篡改、插入数据包
如何增强安全性?
IPSEC、TLS等机制。
IPSEC:
链接:https://blog.csdn.net/NEUChords/article/details/92968314
IPSec(Internet Protocol Security):是一组基于网络层的,应用密码学的安全通信协议族。IPSec不是具体指哪个协议,而是一个开放的协议族。
IPSec协议的设计目标:是在IPV4和IPV6环境中为网络层流量提供灵活的安全服务
TLS:
链接:https://blog.csdn.net/i929664292/article/details/88680518
TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 Hash、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。
TLS 的基本工作方式是,客户端使用非对称加密与服务器进行通信,实现身份验证并协商对称加密使用的密钥,然后对称加密算法采用协商密钥对信息以及信息摘要进行加密通信,不同的节点之间采用的对称密钥不同,从而可以保证信息只能通信双方获取。
例如,在 HTTPS 协议中,客户端发出请求,服务端会将公钥发给客户端,客户端验证过后生成一个密钥再用公钥加密后发送给服务端(非对称加密),双方会在 TLS 握手过程中生成一个协商密钥(对称密钥),成功后建立加密连接。通信过程中客户端将请求数据用协商密钥加密后发送,服务端也用协商密钥解密,响应也用相同的协商密钥。后续的通信使用对称加密是因为对称加解密快,而握手过程中非对称加密可以保证加密的有效性,但是过程复杂,计算量相对来说也大。