安全断开asio SSL套接字的正确方法是什么? [英] What is the proper way to securely disconnect an asio SSL socket?

查看:1056
本文介绍了安全断开asio SSL套接字的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

A boost-asio SSL / TLS TCP套接字实现为 ssl :: stream c $ c> tcp :: socket :

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

TLS 协议,密码安全关闭涉及交换 close_notify 消息的各方。简单关闭最低层可能会使会话容易受到截断攻击



boost asio ssl async_shutdown总是完成一个错误? @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 上发送SSL close_notify 消息,并等待来自另一端的响应。在 async_shutdown 发送 async_shutdown > close_notify ,以便可以关闭套接字而不等待响应。但是,在当前(1.59)版本的提升 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))
{
// - >不是真正的错误:
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套接字?

解决方案

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



< pre class =lang-cpp prettyprint-override> boost :: system :: error_code ec;
ssl_socket.cancel(ec);
ssl_socket.async_shutdown([] ..){ssl_socket.close();};

注意当前 async_shutdown 操作将被视为完成:




  • A close_notify 已被远程对等体接收。

  • 远程对等体关闭套接字。

  • 操作已取消。 li>


因此,如果资源绑定到套接字或连接的生命周期,则这些资源将保持活动,等待远程对等体采取行动或直到操作被本地取消。但是,安全关闭不需要等待 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 ,并且在完成处理程序将关闭底层传输,使 boost :: asio :: error :: operation_aborted 完成 async_shutdown() c>。如链接答案中所述, 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()操作将显式关闭底层传输,导致正在等待PartyB 的 async_shutdown() close_notify 即将取消。



A boost-asio SSL/TLS TCP socket is implemented as an ssl::stream over a tcp::socket:

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

In the TLS protocol, a cryptographically secure shutdown involves parties exchanging close_notify messages. Simply closing the lowest layer may make the session vulnerable to a truncation attack.

In boost asio ssl async_shutdown always finishes with an error? @Tanner Sansbury describes the SSL shutdown process in detail with a number of scenarios and proposes using an async_shutdown followed by an async_write to disconnect an SSL stream prior to closing the socket:

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

Performing an async_shutdown on an ssl::stream sends an SSL close_notify message and waits for a response from the other end. The purpose of writing to the stream after the async_shutdown is to be notified when async_shutdown has sent the close_notify so that the socket can be closed without waiting for the response. However, in the current (1.59) version of boost the call to async_write fails...

In How to gracefully shutdown a boost asio ssl client? @maxschlepzig proposes shutting down receiver of the underlying TCP socket:

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

This produces a short read error, and async_shutdown is called when it's detected in the error handler:

// 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();
}

Or cancelling the read/write operations on the socket and then calling SSL async shutdown, i.e.:

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

I'm currently using this last method since it works with the current version of boost.

What is the correct/best way to securely disconnect a boost-asio SSL socket?

解决方案

To securely disconnect, perform a shutdown operation and then close the underlying transport once shutdown has complete. Hence, the method you are currently using will perform a secure disconnect:

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

Be aware that the current async_shutdown operation will be considered complete when either:

  • A close_notify has been received by the remote peer.
  • The remote peer closes the socket.
  • The operation has been cancelled.

Hence, if resources are bound to the lifetime of the socket or connection, then these resources will remain alive waiting for the remote peer to take action or until the operation is cancelled locally. However, waiting for a close_notify response is not required for a secure shutdown. If resources are bound to the connection, and locally the connection is considered dead upon sending a shutdown, then it may be worthwhile to not wait for the remote peer to take action:

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

When a client sends a close_notify message, the client guarantees that the client will not send additional data across the secure connection. In essence, the async_write() is being used to detect when the client has sent a close_notify, and within the completion handler, will close the underlying transport, causing the async_shutdown() to complete with boost::asio::error::operation_aborted. As noted in the linked answer, the async_write() operation is expected to fail.

... as the write side of PartyA's SSL stream has closed, the async_write() operation will fail with an SSL error indicating the protocol has been shutdown.

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

The failed async_write() operation will then explicitly close the underlying transport, causing the async_shutdown() operation that is waiting for PartyB's close_notify to be cancelled.

这篇关于安全断开asio SSL套接字的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆