最后更新:2022-07-21 15:59:19 手机定位技术交流文章
参考:
WebSocket基本
心跳检测
首先,客户端启动协议升级请求。 您可以看到标准HTTP消息格式被使用,只支持GET方法。
关键请求的主要意义如下:
Connection: Upgrade:表示要升级协议Upgrade: websocket升级到Websocket协议。Sec-WebSocket-Version: 13Websocket的版本。 如果服务器不支持此版本,则需要返回Sec-WebSocket-Version标题包含服务端支持的版本编号。Sec-WebSocket-Key对服务后端的第一次响应Sec-WebSocket-Accept它支持, 提供基本的保护, 例如恶意连接, 或不意连接.注意,上面请求省略了部分非重点请求首部。由于是标准的HTTP请求,类似Host、Origin、Cookie等请求首部会照常发送。在握手阶段,可以通过相关请求首部进行 安全限制、权限校验等。
服务端返回内容如下,州代码101表示协议更改。 在协议升级时,随后的数据交互将遵循新的协议。
Sec-WebSocket-Accept根据第一个客户端请求Sec-WebSocket-Key计算出来。
计算公式为:
Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。伪代码如下:
核查以前的返回结果:
客户端和服务端数据的交换不能被排除在数据帧格式的定义中,因此,在实际解释数据交换之前,让我们先看看下一个WebSocket数据帧格式。
WebSocket客户端、服务端通信的最小单位是帧(frame),由1个或多个帧组成一条完整的消息(message)。
本节的重点是解释数据框架的格式。
下面给出了WebSocket数据帧的统一格式。对于熟悉TCP/IP协议的学生,不应该对这个图不熟悉。
FIN、RSV1各占据1比特,opcode占据4比特。对于以前的格式概览图,这里是一个逐字说明。如果有任何不明确的点,请参阅协议规格,或消息交换。
FIN:1个比特。
如果是1,表示这是消息(message)的最后一个分片(fragment),如果是0,表示不是是消息(message)的最后一个分片(fragment)。
RSV1, RSV2, RSV3: 每个数值为一位.
一般情况下全为0。当客户端、服务端协商采用WebSocket扩展时,这三个标志位可以非0,且值的含义由扩展进行定义。如果出现非零的值,且并没有采用WebSocket扩展,连接出错。
口号:4位。
操作代码,Opcode的值决定了应该如何解析后续的数据载荷(data payload)。如果操作代码是不认识的,那么接收端应该断开连接(fail the connection)。可选的操作代码如下:
面具:1片。
表示是否要对数据载荷进行掩码操作。从客户端向服务端发送数据时,需要对数据进行掩码操作;从服务端向客户端发送数据时,不需要对数据进行掩码操作。
如果服务端接收的数据没有加密,服务端需要切断连接。
如果 Mask是1,那么 Masking-key中定义了一个 masking 键,这个 masking 键用于反加密数据负载。 所有客户端发送数据帧到服务端,所有 masks是1。
下面对加密的算法和应用进行了说明.
负载长度: 数据负载的长度,单位为字节,为7个数字,或7+16个数字,或1+64个数字。
假设数Payload length === x,如果
此外,如果payload length占用了多个字节的话,payload length的二进制表达采用网络序(big endian,重要的位在前)。
Masking-key:0或4字节(32位)
所有从客户端传送到服务端的数据帧,数据载荷都进行了掩码操作,Mask为1,且携带了4字节的Masking-key。如果Mask为0,则没有Masking-key。
注: 负载数据的长度不包括面具键的长度.
Payload data:(x+y) 字节
载荷数据:包括了扩展数据、应用数据。其中,扩展数据x字节,应用数据y字节。
扩展数据:如果扩展没有在协商中使用,扩展数据为0字节。所有扩展必须说明扩展数据的长度,或者如何计算扩展数据的长度。此外,在握手阶段,必须很好地商讨如何使用延长期限.如果扩展数据存在,那么负载数据长度必须包括扩展数据的长度。
应用程序数据:任何应用程序数据,在扩展数据之后(如果存在一个扩展数据),占有数据框架的其余部分。 数据的载入长度减少了扩展数据的长度以取得应用数据的长度。
一旦WebSocket客户端或服务端建立连接,随后的操作基于数据帧传输。
WebSocketBaseopcode用来区分操作类型。 例如0x8表示断开连接,0x0-0x2表示数据交互。
WebSocket中的每个消息可以分成多个数据帧。 当一个WebSocket接收器接收一个数据帧时,它基于FIN值来确定消息的最后数据帧是否收到。
FIN=1表示当前数据帧是消息的最后数据帧,此时接收机收到了完整的消息并能够处理消息。 FIN=0,接收机还需要继续监测接收的其余数据帧。
此外,opcode在数据交换场景中, 表示数据类型.0x01表示文本,0x02表示二进制。而0x00比较特殊,表示延续帧(continuation frame),顾名思义,就是完整消息对应的数据帧还没接收完。
直接看例子更形象些。下面例子来自 MDN ,可以很好地演示数据的分片。客户端向服务端两次发送消息,服务端收到消息后回应客户端,这里主要看客户端往服务端发送的消息。
第一条消息
FIN=1表示当前消息的最后数据帧。 该消息可以在服务端接收当前数据帧后处理。 opcode=0x1表示客户端正在发送文本类型。
第二条消息
为了保持客户端与服务端之间的实时双向通信,WebSocket需要确保客户端与服务端之间的TCP通道保持不变,然而,在没有数据输入的长期中,如果它们保持长期,则包含的连接资源可能会被浪费。
但不排除有些场景,客户端、服务端虽然长时间没有数据往来,但仍需要保持连接。这个时候,可以采用心跳来实现。
网球和网球的操作与WebSocket的两个控制框架相符,opcode分别是0x9、0xA。
前面提到了,Sec-WebSocket-Key/Sec-WebSocket-Accept其主要作用是提供基本保护,减少恶意连接和意外连接。
作用大致归纳如下:
强调Sec-WebSocket-Key/Sec-WebSocket-Accept转换,它只能带来基本的安全,但连接是否安全,数据是否安全,客户/服务器是否合法,客户/服务器是否合法,实际上没有真正的保证。
在WebSocket协议中,数据加密用于增强协议安全性,但数据加密并不是为了保护数据本身,因为算法本身是开放的,操作并不复杂。 除了加密通道本身,似乎没有许多有效的方法来保护通信安全。
因此,为什么引入加密计算,除了增加计算机上的计算量外,似乎没有很多好处(这也是许多学生的问题)。
答案还是两个字:安全。但并不是为了防止数据泄密,而是为了防止早期版本的协议中存在的代理缓存污染攻击(proxy cache poisoning attacks)等问题。
最初的建议是加密数据,基于安全和效率考虑,最后通过了妥协解决方案:数据负载被解码。
需要注意的是,这里只是限制了浏览器对数据载荷进行掩码处理,但是坏人完全可以实现自己的WebSocket客户端、服务端,不按规则来,攻击可以照常进行。
然而,如果把这个限制添加到浏览器中,会大大增加攻击的难度和攻击的影响范围。 没有这个限制,你可以通过简单的在互联网上放置一个渔场,以供骗子访问,在短时间内发动大规模攻击。
本文由 在线网速测试 整理编辑,转载请注明出处。