安全断开 asio SSL 套接字的正确方法是什么?

2023-12-26

A boost-asioSSL/TLS TCP 套接字实现为ssl::stream over a tcp::socket:

boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;

In the TLS https://www.rfc-editor.org/rfc/rfc5246协议,加密安全关闭涉及各方交换close_notify消息。简单地关闭最低层可能会使会话容易受到截断攻击 https://en.wikipedia.org/wiki/Transport_Layer_Security#Truncation_attack.

In boost asio ssl async_shutdown 总是以错误结束? https://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error/25703699#25703699@Tanner Sansbury 通过多种场景详细描述了 SSL 关闭过程,并建议使用async_shutdown随后是一个async_write在关闭套接字之前断开 SSL 流:

ssl_socket.async_shutdown(...);
const char buffer[] = "";
async_write(ssl_socket, buffer, [](...) { ssl_socket.close(); }) 

执行一个async_shutdown on an ssl::stream发送 SSLclose_notify消息并等待另一端的响应。之后写入流的目的async_shutdown时将被通知async_shutdown已发送close_notify这样就可以关闭套接字而无需等待响应。然而,在当前(1.59)版本中boost http://www.boost.org/打电话给async_write失败...

In 如何优雅地关闭 boost asio ssl 客户端? https://stackoverflow.com/questions/22575315/how-to-gracefully-shutdown-a-boost-asio-ssl-client@maxschlepzig 建议关闭底层 TCP 套接字的接收器:

ssl_socket.lowest_layer()::shutdown(tcp::socket::shutdown_receive);

这会产生一个short read错误,以及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-asioSSL 套接字?


要安全断开连接,请执行关闭操作,然后在关闭完成后关闭底层传输。因此,您当前使用的方法将执行安全断开连接:

boost::system::error_code ec;
ssl_socket.cancel(ec);
ssl_socket.async_shutdown([](...) { ssl_socket.close(); };

请注意,当前async_shutdown当出现以下任一情况时,操作将被视为完成:

  • A close_notify已被远程对等点接收。
  • 远程对等方关闭套接字。
  • 该操作已被取消。

因此,如果资源绑定到套接字或连接的生命周期,那么这些资源将保持活动状态,等待远程对等方采取操作或直到操作在本地取消。然而,等待一个close_notify安全关闭不需要响应。如果资源绑定到连接,并且本地连接在发送关闭消息后被视为已死,那么不等待远程对等方采取操作可能是值得的:

ssl_socket.async_shutdown(...);
const char buffer[] = "";
async_write(ssl_socket, boost::asio::buffer(buffer),
    [](...) { ssl_socket.close(); })

当客户端发送一个close_notify消息时,客户端保证客户端不会通过安全连接发送额外的数据。从本质上讲,async_write()用于检测客户端何时发送了close_notify,并在完成处理程序中,将关闭底层传输,导致async_shutdown()完成与boost::asio::error::operation_aborted。如中所述链接答案 https://stackoverflow.com/a/25703699/1053968, the async_write()操作预计会失败。

...作为写入面PartyA的 SSL 流已关闭,async_write()操作将失败并出现 SSL 错误,指示协议已关闭。

if ((error.category() == boost::asio::error::get_ssl_category())
     && (SSL_R_PROTOCOL_IS_SHUTDOWN == ERR_GET_REASON(error.value())))
{
  ssl_stream.lowest_layer().close();
}

失败的async_write()然后操作将显式关闭底层传输,导致async_shutdown()正在等待的操作PartyB's close_notify被取消。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

安全断开 asio SSL 套接字的正确方法是什么? 的相关文章

随机推荐