2012-03-04 33 views
12

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

我已经使用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安装程序使用SSL/TLS [FTPS],另一个是运行在Linux)的


更新:山姆·米勒问我后我的代码描述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"; 
+0

非常好的问题。 – 2012-03-04 10:54:18

+0

最近我有一个SSL的问题[链接](http://stackoverflow.com/questions/9411506/boosts-asio-ssl-dont-work-in-some-conditions)。命令'openssl s_client -connect server_ip:server_port'帮助我了解原因。也许它会帮助你。 – megabyte1024 2012-03-04 10:58:08

+0

请发布您的代码描述如何设置ssl上下文 – 2012-03-04 16:21:34

回答

9

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

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

因此,这里是我是如何得到这个与升压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()。知道连接已建立,只需读取并写入套接字即可。

+1

另请参阅:http://stackoverflow.com/questions/7786352/ssl-session-resume-on-ftp-transfer-connection-with-openssl – 2012-04-08 07:07:27

+0

您很可能想调用sslSocket2.async_handshake而不是直接调用SSL_connect如果你使用的是异步函数,async_handshake会在内部调用SSL_connect。 – John 2015-03-08 05:20:59