- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 12
ssl_transport.md
qb-io provides robust support for secure TCP communication through SSL/TLS, leveraging the OpenSSL library. This allows you to encrypt data streams, ensuring confidentiality and integrity for your networked applications.
Prerequisites:
- The QB_IO_WITH_SSLCMake option must be ON during the build of the QB framework.
- The OpenSSL library (development headers and libraries) must be installed and accessible on your system.
qb-io extends its standard TCP components with SSL/TLS capabilities:
- 
qb::io::tcp::ssl::socket(fromqb/io/tcp/ssl/socket.h)- 
Purpose: This class is your secure TCP socket. It wraps a standard qb::io::tcp::socketand transparently layers SSL/TLS encryption and decryption over it using an OpenSSLSSL*handle.
- 
Key Functionality: Manages the SSL handshake process (client-side connect(), server-side afteraccept()). All data passed through itsread()andwrite()methods is automatically encrypted/decrypted.
- 
Initialization: Before connecting or accepting, an ssl::socketmust be associated with an OpenSSL context (SSL_CTX*) via itsinit(SSL_CTX* ctx)method or by being constructed/assigned from an already SSL-enabled socket.
- 
Advanced Access: ssl_handle()provides direct access to the underlyingSSL*object if you need fine-grained control over OpenSSL settings.
 
- 
Purpose: This class is your secure TCP socket. It wraps a standard 
- 
qb::io::tcp::ssl::listener(fromqb/io/tcp/ssl/listener.h)- Purpose: This class acts as a secure TCP server, listening for incoming connections and performing the server-side SSL/TLS handshake.
- 
Functionality: It requires an SSL_CTX*configured with the server's certificate and private key. Whenaccept()is called, it first accepts a standard TCP connection and then establishes the SSL/TLS session over it, returning a fully securedqb::io::tcp::ssl::socketready for communication.
- 
Initialization: Call init(SSL_CTX* ctx)with a server-configured SSL context before invokinglisten().
 
- 
SSL Context Creation Helpers (in qb/io/tcp/ssl/socket.hnamespaceqb::io::ssl)- 
qb::io::ssl::create_client_context(const SSL_METHOD* method): Simplifies creating anSSL_CTX*suitable for SSL/TLS clients (e.g., usingTLS_client_method()).
- 
qb::io::ssl::create_server_context(const SSL_METHOD* method, const std::string& cert_path, const std::string& key_path): Creates anSSL_CTX*for servers, loading the server's certificate and private key from the specified PEM-encoded files.
- 
Note: The caller is responsible for freeing the returned SSL_CTX*usingSSL_CTX_free()when it's no longer needed (typically managed by the actor or class that owns the listener/socket).
 
- 
- 
Secure TCP Transport: qb::io::transport::stcp(fromqb/io/transport/stcp.h)- 
Purpose: This is the specialized qb::io::streamimplementation for secure TCP. It usesqb::io::tcp::ssl::socketas its underlying I/O mechanism.
- 
Base Class: Inherits from qb::io::stream<qb::io::tcp::ssl::socket>.
- 
Key Behavior: Its read()method is aware of OpenSSL's internal buffering. After performing a socket read, it callsSSL_pending()to check if OpenSSL has already decrypted and buffered additional data. If so, it performs further reads from the SSL layer to ensure all application data is retrieved promptly and not left in OpenSSL's internal buffers.
 
- 
Purpose: This is the specialized 
For actor-based development or other asynchronous classes, qb-io provides qb::io::use<> helper templates (in qb/io/async.h) to simplify integration:
- 
use<MyActor>::tcp::ssl::client<ServerActor = void>: Base for an actor that acts as an SSL/TLS client.
- 
use<MyActor>::tcp::ssl::acceptor: Base for an actor that accepts incoming SSL/TLS connections.
- 
use<MyActor>::tcp::ssl::server<SessionActor>: A comprehensive base for an actor that acts as an SSL/TLS server, combining an acceptor and managingSessionActorinstances for each client.
- 
use<MyActor>::tcp::ssl::io_handler<SessionActor>: If you need more custom server logic, this provides the session management part for SSL sessions.
These helpers ensure that the correct secure transport (transport::stcp) and socket (tcp::ssl::socket) types are used automatically.
- 
Certificates: Obtain or generate your server certificate (.pemfile) and corresponding private key (.pemfile). For testing, self-signed certificates can be created using OpenSSL command-line tools (seetest-io/system/CMakeLists.txtfor an example command:openssl req -x509 ...).
- 
SSL Context (SSL_CTX): In your server actor (or main setup code):#include <qb/io/tcp/ssl/socket.h> // For create_server_context, SSL_CTX_free // ... other necessary includes ... SSL_CTX* _server_ssl_ctx = nullptr; // Typically a member of your server/acceptor actor // In constructor or onInit of your server/acceptor actor: const char* my_cert_path = "path/to/your/server_cert.pem"; const char* my_key_path = "path/to/your/server_key.pem"; _server_ssl_ctx = qb::io::ssl::create_server_context(TLS_server_method(), my_cert_path, my_key_path); if (!_server_ssl_ctx) { // Handle error: Failed to create context or load certificate/key files throw std::runtime_error("Server SSL context creation failed. Check paths and OpenSSL errors."); } // Remember to free the context, e.g., in the actor's destructor: // if (_server_ssl_ctx) { SSL_CTX_free(_server_ssl_ctx); _server_ssl_ctx = nullptr; } 
- 
Acceptor/Server Actor: Inherit from qb::io::use<MyAcceptor>::tcp::ssl::acceptororqb::io::use<MyServer>::tcp::ssl::server<MySession>.
- 
Initialize Listener Transport: Before listening, associate the SSL_CTXwith the listener's transport:// Inside your acceptor/server actor's onInit (after creating _server_ssl_ctx): this->transport().init(_server_ssl_ctx); 
- 
Listen: Call this->transport().listen_v4(port, host);(orlisten_v6,listen(uri)).
- 
Start Accepting: Call this->start();(method from theqb::io::asyncbase likeasync::input).
- 
Handle New Secure Connections: Implement on(accepted_socket_type&& new_secure_socket)(for acceptors) oron(IOSession& new_secure_session)(for combined servers). The accepted socket/session will be anssl::socketor a session class usingtransport::stcp.
(Reference Example: test-async-io.cpp (SSL test), test-session-text.cpp (Secure test).**)
- 
SSL Context (SSL_CTX): In your client actor (or setup code):#include <qb/io/tcp/ssl/socket.h> // For create_client_context, SSL_CTX_free // ... other necessary includes ... SSL_CTX* _client_ssl_ctx = nullptr; // Typically a member of your client actor // In constructor or onInit of your client actor: _client_ssl_ctx = qb::io::ssl::create_client_context(TLS_client_method()); if (!_client_ssl_ctx) { throw std::runtime_error("Client SSL context creation failed."); } // Optional: Configure server certificate verification (recommended for production) // SSL_CTX_set_verify(_client_ssl_ctx, SSL_VERIFY_PEER, nullptr); // custom_verify_callback can be nullptr // if (!SSL_CTX_load_verify_locations(_client_ssl_ctx, "/path/to/ca_bundle.pem", nullptr)) { // // Handle error loading CA certificates // } // Remember to free the context in the actor's destructor. 
- 
Client Actor: Inherit from qb::io::use<MyClient>::tcp::ssl::client.
- 
Initialize Client Transport: Before connecting, associate the SSL_CTX:// Inside your client actor's onInit (after creating _client_ssl_ctx): this->transport().init(_client_ssl_ctx); 
- 
Connect: Use the transport's connect methods, e.g., this->transport().connect_v4(host, port, sni_hostname);orthis->transport().n_connect(endpoint, sni_hostname);. Providing thesni_hostnameis important for Server Name Indication. For fully asynchronous connection (usingn_connect), you'll typically useqb::io::async::tcp::connect<qb::io::tcp::ssl::socket>(uri_or_endpoint, sni_hostname, connect_callback_lambda);.
- 
Handshake: The SSL handshake occurs as part of the connection process.
- For blocking connect, it completes before returning.
- For non-blocking n_connect(or when usingasync::tcp::connect), theconnect_callback_lambdareceives the TCP-connectedssl::socket. You then typically callthis->transport() = std::move(accepted_socket); this->switch_protocol<MyProtocol>(*this); this->start(); this->transport().connected();wheretransport().connected()finalizes the SSL handshake.
 
- For blocking 
- 
Communicate Securely: Once connected and the handshake is complete, use *this << ...;orin()/out()methods as with regular TCP. Thetransport::stcphandles encryption/decryption.
(Reference Example: test-async-io.cpp (SSL test), test-session-text.cpp (Secure test).**)
By following these patterns, you can seamlessly integrate SSL/TLS encryption into your QB applications, enhancing their security.
(Next: QB-IO: Utilities**)