6
votes

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.

5

5 Answers

2
votes

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

1
votes

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.

1
votes

A recent kernel patch may make it possible by giving a normal fd for a TLS connection. See the page "TLS in the kernel By Jake Edge December 2, 2015". I also cross posted to another SO question.

0
votes

I don't think it's possible, since part of the initial handshake is key exchange, and the keys are required for the ongoing communication. Process B would need to know the key being used by the remote end and by process A.

0
votes

sounds like way more trouble that it's worth... consider other designs, e.g. proxy the connection through A on behalf of B using the loopback interface for example.