boost-asio
的 SSL/TLS TCP 套接字是通过在 tcp::socket
上实现一个 ssl::stream
来完成的:boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
在TLS协议中,加密安全关闭涉及各方交换
close_notify
消息。简单地关闭最低层可能会使会话容易受到截断攻击的影响。在boost asio ssl async_shutdown always finishes with an error?中,@Tanner Sansbury详细描述了SSL关闭过程,并提出在关闭套接字之前使用
async_shutdown
后跟async_write
来断开SSL流的建议。ssl_socket.async_shutdown(...);
const char buffer[] = "";
async_write(ssl_socket, buffer, [](...) { ssl_socket.close(); })
执行
ssl::stream
上的 async_shutdown
会发送 SSL close_notify
消息并等待对端响应。在 async_shutdown
后向流写入内容的目的是为了在未等待响应即可关闭套接字时得到通知。然而,在当前 (1.59) 版本的 boost 中,调用 async_write
失败...在 如何优雅地关闭 boost asio ssl 客户端? 中,@maxschlepzig 建议关闭底层 TCP 套接字的接收器。
ssl_socket.lowest_layer()::shutdown(tcp::socket::shutdown_receive);
这会产生一个“短读取”错误,并且在错误处理程序中检测到时调用“async_shutdown”函数:
// const boost::system::error_code &ec
if (ec.category() == asio::error::get_ssl_category() &&
ec.value() == ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ))
{
// -> not a real error:
do_ssl_async_shutdown();
}
取消套接字上的读/写操作,然后调用SSL异步关闭,即:
boost::system::error_code ec;
ssl_socket.cancel(ec);
ssl_socket.async_shutdown([](...) { ssl_socket.close(); };
目前我正在使用这种方法,因为它与当前版本的boost
兼容。
如何正确/最佳地安全断开boost-asio
SSL套接字?
close_notify
通知,你并不需要回复一个。 - user207421close_notify
后,无需等待接收到它。 - kenba