gpt4 book ai didi

c++ - SSL_Read() 返回 SSL_ERROR_ZERO_RETURN 但 ERR_get_error() 为 0

转载 作者:太空宇宙 更新时间:2023-11-03 15:08:10 28 4
gpt4 key购买 nike

我正在编写一个非阻塞 Websocket 客户端,并在 TLS 层使用 OpenSSL。我能够连接到远程服务器,完成 TLS 握手,发送升级请求,获得升级确认响应,然后在 TLS 层与 SSL_ERROR_ZERO_RETURN 断开连接之前获得实际的 websocket 响应。

SSL_get_error(...) 返回:6//SSL_ERROR_ZERO_RETURN

ERR_error_string(ERR_get_error(), nullptr) 返回:error:00000000:lib(0):func(0):reason(0)

根据我的理解,ERR_get_error() 应该弹出并返回错误队列中的第一个错误,而 SSL_get_error() 返回 的最后一个错误SSL_* 函数。我不明白为什么 SSL_get_error() 会返回错误值,但 ERR_get_error() 不会。根据之前的 Stack Overflow Question , SSL_get_error() 不调用 ERR_get_error()

以下代码被重复调用(因为它是一个非阻塞套接字):

ERR_clear_error();
int ret = SSL_read(...);
if (ret > 0) {
// read bytes from socket
} else {
int err_code = SSL_get_error(ssl_session_, ret);
if (err_code == SSL_ERROR_ZERO_RETURN || err_code == SSL_ERROR_SYSCALL || err_code == SSL_ERROR_SSL) {
sprintf("Disconnected: %d %s", err_code, ERR_error_string(ERR_get_error(), nullptr));
// Disconnect Code
}
}

我有两个问题:

  1. 为什么我没有得到 ERR_get_error() 的错误值?

  2. 为什么我在建立 TLS 和 Websocket session 后这么快就断开连接?

编辑 1

我用wireshark抓取了客户端和服务器之间的数据包。我确认 TLS 握手、websocket 升级和初始服务器响应成功。我注意到在初始服务器响应之后,我的客户端从服务器收到了一个 Encrypted Alert 21,我认为这是一个 fatal error ,并解释了为什么 TLS session 立即终止并且我的 SSL 错误队列为空(虽然它可能是客户端问题,我不认为这是最近操作的结果),并且有点解释了我在 SSL_Read 之后得到的 SSL_ERROR_ZERO_RETURN 值。

我不确定 Encrypted Alert 21 包含什么内容。这可能是我正在使用的证书(自签名)。需要进一步调查。

最佳答案

好吧,问题的根本原因已经确定,但是跳过了很多环节并且浪费了时间才到达那里。我能够通过使用 OpenSSL 方法获取主 key 来解密 SSL 流量,SSL_SESSION_get_master_key() , 以及 Wireshark 的客户端 Hello 的随机值。

SSL_Connect后输出主 key 的相关代码:

ERR_clear_error();
int ret = SSL_connect(ssl_ptr);
if (ret > 0) {
SSL_SESSION * ssl_session = SSL_get_session(ssl_ptr);
if(ssl_session != NULL) {
unsigned char master_key_buf[256];
size_t outlen = sizeof(master_key_buf);
size_t buf_size = SSL_SESSION_get_master_key(ssl_session, master_key_buf, outlen);
if(outlen > 0) {
char hex_encoded_master_buf[513];
// hex encode the master key
for(size_t i = 0; i < buf_size; ++i) {
sprintf(&hex_encoded_master_buf[2*i], "%02x", master_key_buf[i]);
}
hex_encoded_master_buf[(2*buf_size)] = '\0';
// log out the hex-encoded master key in master buf here
}
}
}

使用 NSS Key Log CLIENT_RANDOM在 wireshark 中格式化以解密捕获的 SSL 流量,我能够检查上述 Encrypted Alert 21,它最终只是一个 WebSocket FIN 和 close_notify。

事实证明,根本原因是在握手期间,我的 WSS 升级请求消息确实包含正确的 header ,但我实际上是在发送垃圾负载。这是在发送消息时使用消息缓冲区的 sizeof 而不是 strlen 设置大小的情况。服务器本来可以很好地解析升级消息并成功完成握手,但下次检查其套接字时,它会在等待 WSS 消息时读入垃圾。这导致了 websocket 连接的突然关闭。

总结一下,回答我原来的两个问题:

  1. 为什么我没有得到 ERR_get_error() 的错误值?

连接在服务器端被终止,错误队列将包含客户端的错误,但至少在 SSL/TLS 层没有错误。

  1. 为什么在建立 TLS 和 Websocket session 后我很快就断开连接了?

我的初始升级请求包含一个有效的 Websocket 升级请求,后面有垃圾数据。 Server 解析 Websocket Upgrade Request 并确认升级,开始回传数据。下次服务器检查其套接字时,它仍然具有与原始 Websocket 升级请求一起发送的垃圾值。由于服务器未将其识别为有效的 Websocket 消息或其他任何与此相关的消息,因此它决定使用 close_notify 终止连接。

关于c++ - SSL_Read() 返回 SSL_ERROR_ZERO_RETURN 但 ERR_get_error() 为 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50223224/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com