【问题标题】:Boost ASIO: SSL handshake() never finishesBoost ASIO:SSL 握手()永远不会完成
【发布时间】:2012-03-22 04:38:03
【问题描述】:

我有一个 C++ 客户端应用程序,它使用 Boost ASIO 与各种服务器建立 SSL 连接。但针对 2 个特定服务器,无法建立 SSL 连接。它挂在对boost::asio::ssl::stream::handshake() 的调用中。

我使用 Wireshark 来观察客户端和服务器之间的对话。有效的 SSL 连接似乎可以做到这一点:

sslsocket.lowest_layer().connect( endpoint, ec );
C ->    SYN    -> S
C <-  SYN ACK  <- S
C ->    ACK    -> S
sslsocket.handshake( SSLSocket::client, ec );
C -> 209 bytes -> S
C <- 690 bytes <- S
C -> 198 bytes -> S
C <- 415 bytes <- S

...此时,ASIO handshake() 调用返回,表明一切正常,SSL 套接字连接工作正常。

但是针对 2 个不同的服务器 [*],握手看起来像这样:

sslsocket.lowest_layer().connect( endpoint, ec );
C ->    SYN    -> S
C <-  SYN ACK  <- S
C ->    ACK    -> S
sslsocket.handshake( SSLSocket::client, ec );
C -> 209 bytes -> S
...2 minute pause...
C <-    RST    <- S

查看这些服务器上的日志文件,似乎在握手中发送了最初的 209 个字节之后,服务器认为 SSL 连接已完全建立。但是客户端仍然处于 Boost ASIO 握手() 调用中,最终在连接重置时返回 ec=104。

所以我想也许有不同类型的 SSL 握手,也许我应该使用一种“更简单”的?

[*] 我知道有人会想知道:导致客户端应用程序出现此问题的服务器之一是 FileZilla Server for Windows setup to use SSL/TLS [FTPS],另一个是在 Linux 上运行的专有服务.)


更新:Sam Miller 要求我发布我的代码来描述如何设置 ssl 上下文:

类(.hpp 文件)包含以下内容:

typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLSocket;
boost::asio::io_service    ioservice;
boost::asio::ssl::context  sslcontext;
SSLSocket                  sslDataSocket;
boost::system::error_code  ec;

构造函数有这些初始化器:

ioservice      ( 2 ),
sslcontext     ( ioservice, boost::asio::ssl::context::sslv23 ),
sslDataSocket  ( ioservice, sslcontext ),

...还有这段代码:

sslcontext.set_options( boost::asio::ssl::context::default_workarounds |
                        boost::asio::ssl::context::verify_none         );

这是建立 SSL 套接字并挂起握手的代码:

std::cout << "connecting SSL socket to endpoint " << buffer << std::endl;
sslDataSocket.lowest_layer().connect( tcpEndpoint, ec );
std::cout << "connect() done, ec=" << ec.value() << std::endl;
if ( ec ) throw "test 1";

std::cout << "starting ssl handshake" << std::endl;
sslDataSocket.handshake( SSLSocket::client, ec );
std::cout << "handshake done, ec=" << ec.value() << std::endl;
if ( ec ) throw "test 2";

【问题讨论】:

  • 非常好的问题。
  • 最近我遇到了 SSL link 的问题。命令openssl s_client -connect server_ip:server_port 帮助我了解了原因。也许它也会帮助你。
  • 请发布您的代码,描述如何设置 ssl 上下文
  • 我已经修改了问题以包含 .hpp 中的行和连接设置。
  • 所以我正在阅读这个问题和答案,试图调试 Boost+OpenSSL 问题。向上滚动到顶部以查看作者是谁。哦,天哪……我一定要丢了。 8年后,我什至不记得自己的问题和答案!为什么 ASIO 和 OpenSSL 这么不友好?

标签: c++ sockets ssl boost-asio


【解决方案1】:

我想通了。这个 SSL 教程 (http://h71000.www7.hp.com/doc/83final/ba554_90007/ch04s03.html) 包含了最终让这个为我工作的关键。引用:

您可以重复使用已建立的 SSL 会话中的信息 创建一个新的 SSL 连接。因为新的 SSL 连接是 重复使用相同的主密钥,可以执行 SSL 握手 更快速。因此,SSL 会话恢复可以减少负载 接受许多 SSL 连接的服务器。

以下是我如何使用 Boost ASIO:

  • 设置正常的 SSL 控制套接字(很多例子,包括这个问题)
  • 当您需要设置第二个 SSL 数据套接字时,请执行以下操作:

    sslSocket2.lowest_layer().connect( tcpEndpoint, ec );
    SSLSocket::impl_type impl1 = sslSocket1.impl();
    SSLSocket::impl_type impl2 = sslSocket2.impl();
    SSL_SESSION *savedSession = SSL_get1_session( impl1->ssl );
    SSL_set_session( impl2->ssl, savedSession );
    SSL_connect( impl2->ssl );

就是这样。此时,无需调用 sslSocket2.handshake()。只需在知道连接已建立的情况下读取和写入套接字即可。

【讨论】:

  • 如果您使用异步函数,您可能希望调用 sslSocket2.async_handshake 而不是直接调用 SSL_connect。 async_handshake 在内部调用 SSL_connect。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-29
相关资源
最近更新 更多