Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenSSL: accept TLS connection and then transfer to another process

We have a (Linux) server running two processes, A and B. Currently, clients establish a connection to process A, which then passes the resulting socket's file descriptor to process B, allowing process B to use the existing fd/socket to communicate seamlessly with the client. The client and process B then perform a TLS handshake and continue talking on the resulting TLS connection.

(I'm leaving out a lot of details here, but yes, there is a good reasons for having process A act as an intermediary instead of just connecting to process B directly)

Now, because of <long complicated story involving new client applications and websockets> it looks like we may have to perform the TLS handshake in process A, and then transfer the established TLS connection to process B.

Is that possible? The underlying socket's file descriptor can be copied (we do that already), and at least in theory, the internal TLS state data could also be copied and used to reconstruct the TLS connection in process B, effectively taking over the connection.

But does OpenSSL expose any facility like that? I found the function d2i_SSL_SESSION which seems to do something similar for an OpenSSL session object, but being quite new to OpenSSL, I'm not sure if that is sufficient. There are sessions, context, BIO's and a bunch of other complicated-sounding terms involved. How much would have to be serialized and transferred to process B for this to work? And how would it be done in practice?

The switchover is required to be 100% transparent to the client: it must simply perform an SSL handshake against a given IP/port, and then continue talking on the resulting socket, with no knowledge of the fact that one process accepts the connection and performs the TLS handshake, and another then handles all subsequent communication.

like image 868
jalf Avatar asked Sep 14 '12 14:09

jalf


2 Answers

Sharing SSL context across processes is indeed possible. However, then the SSL-session-context would need to reside in a shared memory location which is accessible to both the processes (since for specific reasons unknown) we want the actual handshake to be done in process A and do the data I/O in process B.

First step is to register the call-backs for SSL_CTX_sess_set_new_cb(ctx, shared_ctx_new_cb); SSL_CTX_sess_set_get_cb(ctx, shared_ctx_get_cb); SSL_CTX_sess_set_remove_cb(ctx, shared_ctx_remove_cb);

Ensure appropriate SSL-session-context always get created in shared memory (or atleast returns a serialized and ready to use addressable pointers to SSL_SESSION

To (de)serialize the SSL_SESSION 'C' struct use the available API d2i_SSL_SESSION(...) and i2d_SSL_SESSION(...)

A working project using this approach an sample code at https://github.com/varnish/hitch/blob/master/src/shctx.c

like image 100
Piyush Dewnani Avatar answered Oct 01 '22 00:10

Piyush Dewnani


I haven't tried this on practice, but as far as I remember after the connection is created on socket level it is initialized by openssl and then you read/write with SSL_read and SSL_write. They accept socket fd as parameter. The connection itself (from SSL side) is represented with SSL_CTX SSL structs.

So in theory that sounds possible, but as I said I have never tried it in the real world.

like image 29
Tsvetomir Dimitrov Avatar answered Oct 01 '22 00:10

Tsvetomir Dimitrov