For debugging reasons I want sometimes to capture traffic and analyze it. One option to do that was to configure OpenSSL or boost::asio::ssl to keep the transport untouched. I couldn't find anything in the API.
If you can configure both ends of your connection you can use a null cipher. When you create your boost::asio::ssl::stream
configure it with only ciphers that do not encrypt. This can be done with the OpenSSL API by passing the encapsulated OpenSSL pointer:
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslSocket(io, ssl);
SSL_set_cipher_list(sslSocket.native_handle(), "eNULL");
SSL_set_options(sslSocket.native_handle(), SSL_OP_NO_COMPRESSION);
The SSL_set_cipher_list()
call sets the allowed ciphers, and "eNULL"
matches the ciphers with no encryption (see OpenSSL ciphers). The SSL_set_options()
call turns off compression which has nothing to do with encryption but it's easier to view traffic on the wire without compression. SSL_OP_NO_COMPRESSION
may only be available with OpenSSL 0.9.9 or later. If you are using an earlier OpenSSL version, this page has a workaround to disable compression. It is sufficient to disable compression on one side of the connection.
eNULL
ciphers are never enabled by default so you will need to explicitly configure both ends. If you configure only one end then handshaking will fail. You can set up a simple test server with the OpenSSL s_server
command like this:
openssl s_server -accept 8443 -cert server.pem -key server.pem -cipher eNULL
Adding the -debug
flag will also dump the protocol and you should be able to see plaintext if your client has compression disabled.
Here's a proof of concept client that will talk to the above s_server
command (verify_none
mode used for simplicity, upgrade mode to prevent MITM attacks):
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
int main() {
boost::asio::io_service io;
boost::asio::ssl::context ssl(io,boost::asio::ssl::context::sslv23);
ssl.set_verify_mode(boost::asio::ssl::context::verify_none);
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslSocket(io, ssl);
SSL_set_cipher_list(sslSocket.native_handle(), "eNULL");
SSL_set_options(sslSocket.native_handle(), SSL_OP_NO_COMPRESSION);
boost::asio::ip::tcp::resolver resolver(io);
boost::asio::ip::tcp::resolver::query query("localhost", "8443");
boost::asio::ip::tcp::resolver::iterator endpoint = resolver.resolve(query);
boost::system::error_code error = boost::asio::error::host_not_found;
while (error && endpoint != boost::asio::ip::tcp::resolver::iterator())
{
sslSocket.lowest_layer().close();
sslSocket.lowest_layer().connect(*endpoint++, error);
}
sslSocket.handshake(boost::asio::ssl::stream_base::client);
boost::asio::write(sslSocket, boost::asio::buffer("how now brown cow\n"));
sslSocket.shutdown(error);
return 0;
}
I don't know how to tell asio to turn off encryption when using boost::asio::ssl::stream as the socket object. However, I have used Wireshark before to look at the SSL data coming in and going out over the wire. Wireshark provides the capability to add an RSA key file that it uses to decrypt the data and thus ends up displaying the original data in a window.
To specify the key file, bring up Wireshark and select Edit / Preferences to bring up the preferences dialog box. At the bottom of the left hand side of the window, there should be Protocols. Click on that to show all the protocols. Next, select SSL. On the right hand side of the window you should now see an RSA keys list Edit... button. Click on that button to bring up the window to specify the key file. You will need to have the key file, I/P address, and port number for each server or client that you are talking to.
Wireshark can be downloaded from this link.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With