Un socket TCP SSL / TLS boost-asio
se implementa como una ssl::stream
en un tcp::socket
boost::asio::ssl::stream ssl_socket;
En el protocolo TLS , un cierre criptográficamente seguro implica que las partes intercambien mensajes close_notify
. Simplemente cerrar la capa más baja puede hacer que la sesión sea vulnerable a un ataque de truncamiento .
In boost asio ssl async_shutdown siempre termina con un error? @Tanner Sansbury describe el proceso de cierre SSL en detalle con una serie de escenarios y propone utilizar async_shutdown
seguido de async_write
para desconectar un flujo SSL antes de cerrar el socket:
ssl_socket.async_shutdown(...); const char buffer[] = ""; async_write(ssl_socket, buffer, [](...) { ssl_socket.close(); })
La ejecución de un async_shutdown
en un ssl::stream
envía un mensaje SSL close_notify
y espera una respuesta del otro extremo. El propósito de escribir en la transmisión después de async_shutdown
es recibir una notificación cuando async_shutdown
ha enviado close_notify
para que el socket se pueda cerrar sin esperar la respuesta. Sin embargo, en la versión actual (1.59) de boost, la llamada a async_write
falla …
En Cómo cerrar con gracia un cliente asio ssl? @maxschlepzig propone cerrar el receptor del socket TCP subyacente:
ssl_socket.lowest_layer()::shutdown(tcp::socket::shutdown_receive);
Esto produce un error de short read
, y se llama a async_shutdown
cuando se detecta en el controlador de errores:
// 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(); }
O cancelar las operaciones de lectura / escritura en el socket y luego llamar a SSL async shutdown, es decir:
boost::system::error_code ec; ssl_socket.cancel(ec); ssl_socket.async_shutdown([](...) { ssl_socket.close(); };
Actualmente estoy usando este último método ya que funciona con la versión actual de boost
.
¿Cuál es la mejor / la mejor forma de desconectar de forma segura un socket SSL de boost-asio
?
Para desconectar de forma segura, realice una operación de apagado y luego cierre el transporte subyacente una vez que se haya completado el apagado. Por lo tanto, el método que esté utilizando realizará una desconexión segura:
boost::system::error_code ec; ssl_socket.cancel(ec); ssl_socket.async_shutdown([](...) { ssl_socket.close(); };
Tenga en cuenta que la operación actual async_shutdown
se considerará completa cuando:
close_notify
ha recibido un close_notify
. Por lo tanto, si los recursos están ligados a la duración del socket o la conexión, estos recursos permanecerán vivos esperando que el par remoto actúe o hasta que la operación se cancele localmente. Sin embargo, no es necesario esperar una respuesta close_notify
para un cierre seguro. Si los recursos están vinculados a la conexión, y localmente la conexión se considera muerta al enviar un cierre, entonces puede valer la pena no esperar a que el par remoto tome medidas:
ssl_socket.async_shutdown(...); const char buffer[] = ""; async_write(ssl_socket, boost::asio::buffer(buffer), [](...) { ssl_socket.close(); })
Cuando un cliente envía un mensaje close_notify
, el cliente garantiza que el cliente no enviará datos adicionales a través de la conexión segura. En esencia, el async_write()
se usa para detectar cuándo el cliente ha enviado un close_notify
, y dentro del controlador de finalización, cerrará el transporte subyacente, haciendo que el async_shutdown()
complete con boost::asio::error::operation_aborted
. Como se señala en la respuesta vinculada , se espera que falle la operación async_write()
.
… ya que el lado de escritura de la transmisión SSL de PartyA se ha cerrado, la operación
async_write()
fallará con un error de SSL que indica que el protocolo se ha apagado.if ((error.category() == boost::asio::error::get_ssl_category()) && (SSL_R_PROTOCOL_IS_SHUTDOWN == ERR_GET_REASON(error.value()))) { ssl_stream.lowest_layer().close(); }
La
async_write()
fallidaasync_write()
cerrará explícitamente el transporte subyacente, provocando que la operaciónasync_shutdown()
que está esperando que close_notify declose_notify
se cancele.