5.19 - SSL/TLS Filter
This is a critical part of any serious network application: securing the communication between the client and the server.
In MINA, we do that with the SslFilter. The idea is to add this Filter in the chain and it will deal with the Handshake negociation, and the following encrypting and uncrypting of the data.
How it works
The thing to remember is that the TLS protocol works in two steps:
- First there is a negociation part (the Handshake)
- Then once the Handshake is completed, all the data will be encrypted before being sent, and decryptd when received.
We just have to add the filter in the chain like this:
...
SslFilter sslFilter = new SslFilter(sslContext);
DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
chain.addFirst("sslFilter", sslFilter);
...
The chain is the instance of IoFilterChainBuilder class that is associated with either the Connector or the Acceptor instances (wether we are using a client or a server). It will be used when a connection is set to define the filter chain this connected session will use.
The missing part here is the sslContext which has to be defined. It’s an instance of the SSLContext class, where you define a TrustManager, a KeyManager and a Securerandom.
The filter can be added either before the connection has been established, or after the connection has been established. In the first case, it’s easy, the filter initialisation will be done when the connection is created. The second is a bit more complex, as we will have to deal with ongoing messages.
Initialization
When a connection is created, the filter chain is created, and the SslFilter is added to this chain, which intializes it. The filter’s onPreAdd method is called, which will only check if the filter has already been added (we can’t have the SslFilter twice in the chain).
The filter’s onPostAdd method is then called, and if the autostart flag is set to true and the session is connected (which should be the case…), then the onConnected method is called.
The SslHandler will then be created, which will contain a newly created SslEngine. This is the place where the TLS parameters will be set:
- The authentication WANT or NEED flags
- The cipher suite
- The enabled protocols
- The endpoint identification algorithms
- and finally the flag indicating if it’s for a server or a client
All those flags are optionnal but the last one.
The newly created SslHandler instance will be added into the session’s attributes, under the org.apache.mina.filter.ssl.SslHandler.handler@
Last, not least, the SslHandler instance is opened. If we are on the client side, the TLS Handshake will be started, otherwise a flag will be set to indicate we are expecting a Handshake on the server side.
We are all set and ready for the Handshake to be processed!
Handshake
The Handshake must be done as soon as the TLS layer is activated. It’s initiated by the client, which must send a CLIENT_HELLO message (see the Client Hello description), but the server must be ready to accept this message.
We will consider two use cases: the Client side and the Server side (as Mina can handle both sides, but could work with a peer written using a different implementation)
Initial Handshake message
The first Handshake message to be processed is the CLIENT HELLO TLS message.
Server side
The Handshake is initiated by a CLIENT_HELLO TLS request which is sent by the client, the server is waiting for it. There starts a serie of TLS messages exchanged between the cleint and the server, at the end of which the session is secured, and data can be exchanged encrypted.
What is important to note here is that during the Handshake exchanges, no application data can be sent, and the SslFilter is handling the whole process, before returning the hand to the application. That means messages emitted by the application will be stacked until the session is secured.
Client side
The client is the initiator of the Handshake exchange. The difference with the server is that the client SSLhandler will generate the inital Handshake message (CLIENT HELLO) and send it to the server
Follow up Handshake messages
Once the Handshake has been initiated, the dance keeps going until the Handshake is either done or fails:
- The client sends Handshake requests
- The server sends Handshake responses
This dance can use many steps.
It ends with both side send a finished message, and has verified that it’s valid.
Session secured
The application is informed that the session is secured:
- In MINA 2.0.X, the SslFilterMessage message is sent and can be processed in the IoHandler.messageReived handler.
- In MINA 2.1.X and 2.2.X, the IoHandler interface exposes an event handler that is used by the SslFilter to inform the application that the session is secured, by emmiting a SslEvent.SECURED event.
It’s clear that the way MINA 2.1.X and 2.2.X signal that the session is secured is way simpler.
StartTLS use case
Some protocols, like LDAP, FTP, XMPP, NNTP, SMTP, can be used without encryption, but allow some encryption to be set by using a specific command. When this command is issued, the TLS layer is added to an already connected session, without reestablishing a new session.
That is what the startTLS command is used for that purpose. Here are a list of existing protocols that use this mechanism:
The way it works is that at some point of a clear text established connection, the client sends a STARTLS command, which forces the TLS Handshake to start to establish a secured connection. When the secured connection is established, the client and the server exchanges will be encrypted.
Now, that is a bit tricky to implement, because both the client and the server must block the exchange of messages during the establishement of the TLS session. As the client is the initiator of the command, it’s easy, but on the server side, we must pass a response to the original command in clear text informing the client that the command has been received and processed.
(C) The client sends a **StartTLS** command
(S) The server receives the command, initialize the **TLS** layer, and send back a response to the client, bypassing the **TLS** layer.
(C) The client received the server response to the command, and setup the **TLS** layer, and initiates the **TLS** _Handshake_
(S/C) The _Handshake_ is processed
(S/C) The session is secured on both side
(S/C) at this point, every message exchanged are encrypted.