SSL/TLS
SSL (Secure Sockets Layer) e TLS (Transport Layer Security) são dois protocolos de segurança amplamente utilizados na internet para proteger as comunicações entre dispositivos. Ambos são baseados em certificados de segurança e chaves criptográficas, que são usados para criptografar e decifrar os dados transmitidos.
A principal diferença entre SSL e TLS é que TLS é uma versão atualizada e aprimorada do SSL. O SSL foi originalmente criado pela Netscape nos anos 1990 como uma maneira de proteger as comunicações na internet. No entanto, com o tempo, problemas de segurança foram encontrados no SSL, levando ao desenvolvimento do TLS como substituto.
Atualmente, SSLv2 e SSLv3 são considerados inseguros e devem ser desabilitados. A maioria dos sistemas usa TLS 1.2 como mínimo, com TLS 1.3 como versão preferida por ser mais rápida e segura. O Asio suporta TLS 1.3 via OpenSSL 1.1.1+.
Asio SSL
A biblioteca Asio SSL fornece uma API que permite aos desenvolvedores criar e gerenciar conexões seguras usando TLS. Ela inclui funções para realizar handshakes SSL/TLS, criptografar e decifrar dados e verificar a validade de certificados de segurança.
Para usar SSL/TLS com Asio, inclua <asio/ssl.hpp> (standalone) ou <boost/asio/ssl.hpp> (Boost.Asio) e vincule com a biblioteca OpenSSL.
Exemplo: cliente SSL/TLS assíncrono (abordagem moderna)
O padrão moderno usa async_handshake() em vez do handshake síncrono:
#include <asio.hpp>
#include <asio/ssl.hpp>
#include <iostream>
#include <string>
namespace ssl = asio::ssl;
using tcp = asio::ip::tcp;
int main()
{
asio::io_context io_context;
// Use 'tls_client' para conexões de cliente (ou 'tls' para uso genérico)
// Evite 'sslv23' — está depreciado
ssl::context ctx(ssl::context::tls_client);
// Opções de segurança: desabilitar protocolos antigos e vulneráveis
ctx.set_options(
ssl::context::default_workarounds
| ssl::context::no_sslv2
| ssl::context::no_sslv3
| ssl::context::single_dh_use);
// Verificação de certificado do servidor (recomendado em produção)
ctx.set_verify_mode(ssl::verify_peer);
ctx.set_default_verify_paths();
// Socket SSL sobre TCP
ssl::stream<tcp::socket> socket(io_context, ctx);
// Resolver e conectar ao host
tcp::resolver resolver(io_context);
auto endpoints = resolver.resolve("exemplo.com", "443");
asio::connect(socket.lowest_layer(), endpoints);
// SNI (Server Name Indication) — necessário para servidores que hospedam
// múltiplos certificados no mesmo IP
SSL_set_tlsext_host_name(socket.native_handle(), "exemplo.com");
// Handshake assíncrono (abordagem recomendada)
socket.async_handshake(ssl::stream_base::client,
[&socket](const asio::error_code& ec) {
if (ec) {
std::cerr << "Erro no handshake: " << ec.message() << '\n';
return;
}
std::cout << "Handshake TLS bem-sucedido!\n";
// Enviar dados após o handshake
std::string request = "GET / HTTP/1.1\r\nHost: exemplo.com\r\n\r\n";
asio::async_write(socket, asio::buffer(request),
[](const asio::error_code& ec, std::size_t bytes) {
if (!ec)
std::cout << "Enviados " << bytes << " bytes\n";
});
});
io_context.run();
return 0;
}
Atenção:
asio::ssl::context::sslv23está depreciado. Usessl::context::tls(genérico),ssl::context::tls_client(para clientes) oussl::context::tls_server(para servidores).
Exemplo: servidor SSL/TLS assíncrono
#include <asio.hpp>
#include <asio/ssl.hpp>
#include <iostream>
#include <memory>
namespace ssl = asio::ssl;
using tcp = asio::ip::tcp;
class SessaoSSL : public std::enable_shared_from_this<SessaoSSL>
{
public:
SessaoSSL(tcp::socket socket, ssl::context& ctx)
: socket_(std::move(socket), ctx) {}
void iniciar()
{
auto self = shared_from_this();
// Handshake assíncrono como servidor
socket_.async_handshake(ssl::stream_base::server,
[self](const asio::error_code& ec) {
if (!ec) self->ler();
});
}
private:
void ler()
{
auto self = shared_from_this();
socket_.async_read_some(asio::buffer(dados_),
[self](const asio::error_code& ec, std::size_t n) {
if (!ec) self->escrever(n);
});
}
void escrever(std::size_t n)
{
auto self = shared_from_this();
asio::async_write(socket_, asio::buffer(dados_, n),
[self](const asio::error_code& ec, std::size_t) {
if (!ec) self->ler();
});
}
ssl::stream<tcp::socket> socket_;
char dados_[1024];
};
int main()
{
asio::io_context ctx_io;
ssl::context ctx_ssl(ssl::context::tls_server);
ctx_ssl.set_options(
ssl::context::default_workarounds
| ssl::context::no_sslv2
| ssl::context::no_sslv3
| ssl::context::single_dh_use);
ctx_ssl.use_certificate_chain_file("server.crt");
ctx_ssl.use_private_key_file("server.key", ssl::context::pem);
ctx_ssl.use_tmp_dh_file("dh2048.pem");
tcp::acceptor acceptor(ctx_io, {tcp::v4(), 443});
std::function<void()> aceitar;
aceitar = [&]() {
acceptor.async_accept(
[&](const asio::error_code& ec, tcp::socket socket) {
if (!ec)
std::make_shared<SessaoSSL>(std::move(socket), ctx_ssl)->iniciar();
aceitar(); // aceita a próxima conexão
});
};
aceitar();
ctx_io.run();
return 0;
}
TLS 1.3
O TLS 1.3 está disponível no Asio através do OpenSSL 1.1.1 ou superior. Para restringir a versões modernas:
ssl::context ctx(ssl::context::tls);
// Permitir apenas TLS 1.2 e 1.3 (desabilitar versões antigas)
ctx.set_options(
ssl::context::no_sslv2
| ssl::context::no_sslv3
| ssl::context::no_tlsv1
| ssl::context::no_tlsv1_1);
Dica: TLS 1.3 oferece handshake mais rápido (1-RTT e até 0-RTT para reconexões), forward secrecy obrigatório e remoção de algoritmos criptográficos obsoletos. Prefira TLS 1.3 sempre que possível.
Compilando com suporte a SSL
# Standalone Asio com OpenSSL
g++ -std=c++20 servidor.cpp -o servidor -pthread -lssl -lcrypto -DASIO_STANDALONE
# Boost.Asio com OpenSSL
g++ -std=c++20 servidor.cpp -o servidor -pthread -lssl -lcrypto -lboost_system