赞
踩
TCP报头中一共有六个标志位:URG/ACK/PSH/RST/SYN/FIN。
SYN
TCP三次握手中,如果A是发起端,则A就对服务器发一个SYN报文。表示建立连接。
ACK
收到数据或请求后发送响应时发送ACK报文。
RST
关闭异常连接
FIN
TCP四次挥手时,表示关闭连接
PSH
发送端需要发送一段数据,这个数据需要接收端一收到就进行向上交付。而接收端在收到PSH标志位有效的数据时,迅速将数据交付给应用层。所以PSH又叫急迫比特。
但是现在已经不需要将数据交付给应用层了,因为这些效果在TCP栈已经可以自行处理这些问题了。
URG
URG成为紧急指针,意为URG位有效的数据包,是一个紧急需要处理的数据包,需要接收端在接收到之后迅速处理。
说了这么多,是不是发现PSH与URG的效果相似,但是聪明的计算机网络创建者会将两个相同的标志位放入一起吗?很明显不会,所以PSH和URG的区别是什么?
首先,PSH与URG的相似之处在于二者所在的数据包都是急需接收端处理的报文。
不同之处在于PSH位有效时,当前的数据还会被发送到接收端的缓冲区,并刷新缓冲区,将当前缓冲区中所有数据都交付给上一层——应用层。
PSH位就是用来通告接收方立即将收到的报文连同TCP接收缓存里的数据递交应用进程处理,一般会出现在发送方封装最后一个应用字段的TCP报文中,针对TCP交互式应用,则只要封装有应用字段的TCP报文,均会将PSH位置1。当然,应用程序的开发者,可以根据需要,在某个应用功能模块或某个应用操作中,将所有封装应用字段的TCP报文PSH位置1,以提高交互双方的处理效率,这在理论上应该也是可行的。
URG位有效的数据包也是在当前报文需要接收端立即处理,但是当前报文不需要经过接收端的缓冲区,直接越过缓冲区,交付往接收端的应用层。
借鉴:https://blog.csdn.net/sinat_36118270/article/details/73927628
RST标志位
正常关闭连接的时候使用FIN,但是如果是关闭异常连接,则使用RST,发送RST包。与FIN包存在两点不同:
RST不必等缓冲区的包都发出去,直接就丢弃缓存区的包发送RST包。而FIN需要先处理完缓存区的包
接收端收到RST包后,也不必发送ACK包来确认。而FIN需要ACK包确认
1)A向B发起连接,但B之上并没有应用监听相应的端口,这时B操作系统上的TCP处理程序会发RST包。
2)请求超时
有89、27两台主机。主机89向主机27发送了一个SYN,表示希望连接8888端口,主机27回应了主机89一个SYN表示可以连接。但是主机89却很不友好,莫名其妙的发送了一个RST表示我不想连接你了。
后来经过排查发现,在主机89上的程序在建立了socket之后,用setsockopt的SO_RCVTIMEO选项设置了recv的超时时间为100ms。而我们看上面的抓包结果表示,从主机89发出SYN到接收SYN的时间多达110ms。(从15:01:27.799961到15:01:27.961886, 小数点之后的单位是微秒)。因此主机89上的程序认为接收超时,所以发送了RST拒绝进一步发送数据。
3)在一个已关闭的socket上收到数据
比如,AB正常建立连接了,正在通讯时,A向B发送了FIN包要求关连接,B发送ACK后,网断了,A通过若干原因放弃了这个连接(例如进程重启)。网通了后,B又开始发数据包,A收到后表示压力很大,不知道这野连接哪来的,就发了个RST包强制把连接关了,B收到后会出现connect reset by peer错误。
4)字节流接收不完全
关于TCP,我想我们在教科书里都读到过一句话,'TCP是一种可靠的连接'。 而这可靠有这样一种含义,那就是操作系统接收到的来自TCP连接中的每一个字节,我都会让应用程序接收到。如果应用程序不接收怎么办?RST。
打开一个socket然后连接一个服务器并发送5000个字节。刚才我们看服务器的代码,每次只接收4096个字节,那么就是说客户端发送的剩下的4个字节服务端的应用程序没有接收到,服务器端的socket就被关闭掉,这种情况下服务器就会向客户端发送了一个RST,断开连接
A和服务器B之间建立了TCP连接,此时C伪造了一个TCP包发给B,使B异常的断开了与A之间的TCP连接,就是RST攻击了。
那么伪造什么样的TCP包可以达成目的呢?
1)假定C伪装成A发过去的包,这个包如果是RST包的话,毫无疑问,B将会丢弃与A的缓冲区上所有数据,强制关掉连接。
2)如果发过去的包是SYN包,那么,B会表示A已经发疯了(与OS的实现有关),正常连接时又来建新连接,B主动向A发个RST包,并在自己这端强制关掉连接。
这两种方式都能够达到复位攻击的效果。似乎挺恐怖,然而关键是,如何能伪造成A发给B的包呢?这里有两个关键因素,源端口和序列号。
一个TCP连接都是四元组,由源IP、源端口、目标IP、目标端口唯一确定一个连接。所以,如果C要伪造A发给B的包,要在上面提到的IP头和TCP头,把源IP、源端口、目标IP、目标端口都填对。这里B作为服务器,IP和端口是公开的,A是我们要下手的目标,IP当然知道,但A的源端口就不清楚了,因为这可能是A随机生成的。当然,如果能够对常见的OS如windows和linux找出生成source port规律的话,还是可以搞定的。
序列号问题是与滑动窗口对应的,伪造的TCP包里需要填序列号,如果序列号的值不在A之前向B发送时B的滑动窗口内,B是会主动丢弃的。所以我们要找到能落到当时的AB间滑动窗口的序列号。这个可以暴力解决,因为一个sequence长度是32位,取值范围0-4294967296,如果窗口大小像上图中我抓到的windows下的65535的话,只需要相除,就知道最多只需要发65537(4294967296/65535=65537)个包就能有一个序列号落到滑动窗口内。RST包是很小的,IP头+TCP头也才40字节,算算我们的带宽就知道这实在只需要几秒钟就能搞定。
那么,序列号不是问题,源端口会麻烦点,如果各个操作系统不能完全随机的生成源端口,或者黑客们能通过其他方式获取到source port,RST攻击易如反掌,后果很严重
借鉴:https://blog.csdn.net/erlib/article/details/50132307
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。