C++ - WebSockets 是不是强制加密,如何获得“明文”?

Posted

技术标签:

【中文标题】C++ - WebSockets 是不是强制加密,如何获得“明文”?【英文标题】:C++ - Do WebSockets enforce encryption, how to get "plaintext"?C++ - WebSockets 是否强制加密,如何获得“明文”? 【发布时间】:2016-10-19 23:57:16 【问题描述】:

我的朋友正在学习如何在他的网络服务器上使用 WebSockets,所以我决定尝试学习如何将我的 HTTP/1.1 连接升级到成功工作的 WebSockets!但是我在新的 websocket 协议上发送数据,但我检索到的信息是加密/压缩等。

所以我的问题是

    数据是否加密/压缩? 如何检索明文? WebSockets 是否类似于 TCP 连接? (我知道 WebSockets 是建立在 HTTP 上的,它是建立在 TCP 上的)但我知道它们支持双向流,所以我有点想会收到明文。

代码:(这根本没有调试,因为我只是快速启动它以连接到我发现与 Fiddler 搞乱的 WebSocket 回显服务器)

    int main()

WSADATA WsaData =  0 ;
WSAStartup(MAKEWORD(2, 2), &WsaData);

addrinfo hints =  0 , *results = nullptr;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_INET;

getaddrinfo("echo.websocket.org", "80", &hints, &results);

SOCKET hSocket = socket(results->ai_family, results->ai_socktype, results->ai_protocol);
connect(hSocket, results->ai_addr, static_cast<int>(results->ai_addrlen));

std::string SendBuffer;
SendBuffer = "GET http://echo.websocket.org HTTP/1.1\r\n";
SendBuffer += "Host: echo.websocket.org\r\n";
SendBuffer += "Upgrade: websocket\r\n";
SendBuffer += "Connection: Upgrade\r\n";
SendBuffer += "Origin: http://www.websocket.org\r\n";
SendBuffer += "Sec-WebSocket-Key: BBw/08+HrO3UfLPU/jeq1g==\r\n";
SendBuffer += "Sec-WebSocket-Version: 13\r\n";
SendBuffer += "Sec-WebSocket-Protocol: chat\r\n\r\n";


char RecvBuffer[1024], MessageBuffer[50];
int ReturnCode = 0;
ReturnCode = send(hSocket, SendBuffer.c_str(), SendBuffer.length(), 0);
ReturnCode = recv(hSocket, RecvBuffer, 5000, 0);

ReturnCode = send(hSocket, "Hello!", 7, 0);
ReturnCode = recv(hSocket, MessageBuffer, 50, 0);


    return 0;

WebSocket 协议-升级响应:

HTTP/1.1 101 Web Socket Protocol Handshake
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Headers: x-websocket-extensions
Access-Control-Allow-Headers: x-websocket-version
Access-Control-Allow-Headers: x-websocket-protocol
Access-Control-Allow-Origin: http://www.websocket.org
Connection: Upgrade
Date: Wed, 19 Oct 2016 23:54:17 GMT
Sec-WebSocket-Accept: 6+RXVMNG1sZqeIs/Y1tlISzHAFI=
Server: Kaazing Gateway
Upgrade: websocket

向 WebSocket 响应发送数据:

\x2\x3\ê

【问题讨论】:

tools.ietf.org/html/rfc6455 “http 是建立在 tcp 上的”也不正确。 HTTP 不需要 TCP。 你说的web sockets是建立在http上是什么意思?我认为这是一个独立的协议。 @Newton 我只是指它是 HTTP 之上的一层。 (这是我提到的,但措辞不佳) @xaxxon 不需要它,但实际上没有其他实现。 HTTP 需要流式传输,而 TCP 是 Internet 上唯一常用的传输方式。 每个 SO 问题一个问题,拜托。 【参考方案1】:

请阅读RFC 6455,它定义了 WebSocket 协议。特别是section 5: Data Framing 和section 6: Sending and Receiving Data。

WebSocket 不是纯文本协议。它实际上是一个使用框架消息的二进制协议,可能包含文本数据:

成功握手后,客户端和服务器在本规范中称为“消息”的概念单元中来回传输数据。在网络上,一条消息由一个或多个帧组成。 WebSocket 消息不一定对应于特定的网络层框架,因为分段消息可能会被中介合并或拆分。

一个框架有一个关联的类型。属于同一消息的每个帧都包含相同类型的数据。广义上讲,有文本数据(被解释为 UTF-8 [RFC3629] 文本)、二进制数据(其解释由应用程序决定)和控制帧(不打算为应用程序携带数据)的类型而是用于协议级别的信令,例如表示应该关闭连接)。此版本的协议定义了六种帧类型,并保留了十种以供将来使用。

您的代码根本没有考虑到这一点。就您的套接字代码而言,唯一的纯文本部分是初始 HTTP 升级握手。握手完成后,您必须改为发送和接收带框的二进制消息。不幸的是,取景过程有点复杂。

您最好的选择是根本不手动实现 WebSocket,而是使用现有的 WebSocket 库,例如 libwebsockets、WebSocket++、easywsclient 等。

【讨论】:

【参考方案2】:

在您的升级响应中,您明确告诉服务器您允许压缩:

SendBuffer += "Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n";

如果您不想压缩,请删除 permessage-deflate 扩展名。

https://en.wikipedia.org/wiki/DEFLATE

【讨论】:

对不起,我忘记删除了,(我删除了它但它仍然不是plaintxt)

以上是关于C++ - WebSockets 是不是强制加密,如何获得“明文”?的主要内容,如果未能解决你的问题,请参考以下文章

engine.io 是不是支持安全的 WebSockets wss?

用于 Windows CE/Mobile 的 C++ 中的 HTTP Websockets 客户端库

在 C++ 中是不是可以强制执行字符串文字函数参数?

强制转换为布尔值是检查是不是存在与键匹配的 unordered_map 值的有效方法吗? C++

如何强制eJabberd将加密的消息存储到数据库(mod_mam)而不是将消息存储为纯文本?

非阻塞 Websockets C++ 奇怪的延迟