Class SslHandler
- All Implemented Interfaces:
ChannelDownstreamHandler,ChannelHandler,ChannelUpstreamHandler,LifeCycleAwareChannelHandler
Channel. Please refer
to the "SecureChat" example in the distribution or the web
site for the detailed usage.
Beginning the handshake
You must make sure not to write a message while the
handshake is in progress unless you are
renegotiating. You will be notified by the ChannelFuture which is
returned by the handshake() method when the handshake
process succeeds or fails.
Handshake
If isIssueHandshake() is false
(default) you will need to take care of calling handshake() by your own. In most
situations were SslHandler is used in 'client mode' you want to issue a handshake once
the connection was established. if setIssueHandshake(boolean) is set to true
you don't need to worry about this as the SslHandler will take care of it.
Renegotiation
If enableRenegotiation is true
(default) and the initial handshake has been done successfully, you can call
handshake() to trigger the renegotiation.
If enableRenegotiation is false,
an attempt to trigger renegotiation will result in the connection closure.
Please note that TLS renegotiation had a security issue before. If your
runtime environment did not fix it, please make sure to disable TLS
renegotiation by calling setEnableRenegotiation(boolean) with
false. For more information, please refer to the following documents:
Closing the session
To close the SSL session, the close() method should be
called to send the close_notify message to the remote peer. One
exception is when you close the Channel - SslHandler
intercepts the close request and send the close_notify message
before the channel closure automatically. Once the SSL session is closed,
it is not reusable, and consequently you should create a new
SslHandler with a new SSLEngine as explained in the
following section.
Restarting the session
To restart the SSL session, you must remove the existing closed
SslHandler from the ChannelPipeline, insert a new
SslHandler with a new SSLEngine into the pipeline,
and start the handshake process as described in the first section.
Implementing StartTLS
StartTLS is the communication pattern that secures the wire in the middle of the plaintext connection. Please note that it is different from SSL · TLS, that secures the wire from the beginning of the connection. Typically, StartTLS is composed of three steps:
- Client sends a StartTLS request to server.
- Server sends a StartTLS response to client.
- Client begins SSL handshake.
- create a new
SslHandlerinstance withstartTlsflag set totrue, - insert the
SslHandlerto theChannelPipeline, and - write a StartTLS response.
SslHandler before sending
the StartTLS response. Otherwise the client can send begin SSL handshake
before SslHandler is inserted to the ChannelPipeline, causing
data corruption.
The client-side implementation is much simpler.
- Write a StartTLS request,
- wait for the StartTLS response,
- create a new
SslHandlerinstance withstartTlsflag set tofalse, - insert the
SslHandlerto theChannelPipeline, and - Initiate SSL handshake by calling
handshake().
Known issues
Because of a known issue with the current implementation of the SslEngine that comes with Java it may be possible that you see blocked IO-Threads while a full GC is done.
So if you are affected you can workaround this problem by adjust the cache settings like shown below:
SslContext context = ...;
context.getServerSessionContext().setSessionCacheSize(someSaneSize);
context.getServerSessionContext().setSessionTime(someSameTimeout);
What values to use here depends on the nature of your application and should be set based on monitoring and debugging of it. For more details see #832 in our issue tracker.
-
Nested Class Summary
Nested classes/interfaces inherited from interface org.jboss.netty.channel.ChannelHandler
ChannelHandler.Sharable -
Field Summary
Fields inherited from class org.jboss.netty.handler.codec.frame.FrameDecoder
cumulation, DEFAULT_MAX_COMPOSITEBUFFER_COMPONENTS -
Constructor Summary
ConstructorsConstructorDescriptionSslHandler(SSLEngine engine) Creates a new instance.SslHandler(SSLEngine engine, boolean startTls) Creates a new instance.SslHandler(SSLEngine engine, SslBufferPool bufferPool) Creates a new instance.SslHandler(SSLEngine engine, SslBufferPool bufferPool, boolean startTls) Creates a new instance.SslHandler(SSLEngine engine, SslBufferPool bufferPool, boolean startTls, Timer timer, long handshakeTimeoutInMillis) Creates a new instance. -
Method Summary
Modifier and TypeMethodDescriptionvoidFail all pending writes which we were not able to flush outvoidvoidLoop over all the pending writes and fail them.voidCallshandshake()once theChannelis connectedvoidInvoked when aChannelwas disconnected from its remote peer.close()Sends an SSLclose_notifymessage to the specified channel and destroys the underlyingSSLEngine.protected Objectdecode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer in) Decodes the received packets so far into a frame.voidInvoked when an exception was raised by an I/O thread or aChannelHandler.booleanstatic SslBufferPoolReturns the defaultSslBufferPoolused when no pool is specified in the constructor.Returns theSSLEnginewhich is used by this handler.longReturn the timeout (in ms) after which theChannelFutureofhandshake()will be failed, while a handshake is in progressReturn theChannelFuturethat will get notified if the inbound of theSSLEnginewill get closed.voidhandleDownstream(ChannelHandlerContext context, ChannelEvent evt) Handles the specified downstream event.Starts an SSL / TLS handshake for the specified channel.booleanReturnstrueif and only if TLS renegotiation is enabled.static booleanisEncrypted(ChannelBuffer buffer) Returnstrueif the givenChannelBufferis encrypted.booleanReturnstrueif the automatic handshake is enabledvoidsetCloseOnSSLException(boolean closeOnSslException) voidsetEnableRenegotiation(boolean enableRenegotiation) Enables or disables TLS renegotiation.voidsetIssueHandshake(boolean issueHandshake) Enables or disables the automatic handshake once theChannelis connected.Methods inherited from class org.jboss.netty.handler.codec.frame.FrameDecoder
actualReadableBytes, afterAdd, appendToCumulation, beforeRemove, cleanup, decodeLast, extractFrame, getMaxCumulationBufferCapacity, getMaxCumulationBufferComponents, internalBuffer, isUnfold, messageReceived, newCumulationBuffer, replace, setMaxCumulationBufferCapacity, setMaxCumulationBufferComponents, setUnfold, unfoldAndFireMessageReceived, updateCumulationMethods inherited from class org.jboss.netty.channel.SimpleChannelUpstreamHandler
channelBound, channelInterestChanged, channelOpen, channelUnbound, childChannelClosed, childChannelOpen, handleUpstream, writeComplete
-
Constructor Details
-
SslHandler
Creates a new instance.- Parameters:
engine- theSSLEnginethis handler will use
-
SslHandler
Creates a new instance.- Parameters:
engine- theSSLEnginethis handler will usebufferPool- theSslBufferPoolwhere this handler will acquire the buffers required by theSSLEngine
-
SslHandler
Creates a new instance. -
SslHandler
Creates a new instance.- Parameters:
engine- theSSLEnginethis handler will usebufferPool- theSslBufferPoolwhere this handler will acquire the buffers required by theSSLEnginestartTls-trueif the first write request shouldn't be encrypted by theSSLEngine
-
SslHandler
public SslHandler(SSLEngine engine, SslBufferPool bufferPool, boolean startTls, Timer timer, long handshakeTimeoutInMillis) Creates a new instance.- Parameters:
engine- theSSLEnginethis handler will usebufferPool- theSslBufferPoolwhere this handler will acquire the buffers required by theSSLEnginestartTls-trueif the first write request shouldn't be encrypted by theSSLEnginetimer- theTimerwhich will be used to process the timeout of thehandshake(). Be aware that the givenTimerwill not get stopped automaticly, so it is up to you to cleanup once you not need it anymorehandshakeTimeoutInMillis- the time in milliseconds after whic thehandshake()will be failed, and so the future notified
-
-
Method Details
-
getDefaultBufferPool
Returns the defaultSslBufferPoolused when no pool is specified in the constructor. -
getEngine
Returns theSSLEnginewhich is used by this handler. -
handshake
Starts an SSL / TLS handshake for the specified channel.- Returns:
- a
ChannelFuturewhich is notified when the handshake succeeds or fails.
-
close
Sends an SSLclose_notifymessage to the specified channel and destroys the underlyingSSLEngine. -
isEnableRenegotiation
public boolean isEnableRenegotiation()Returnstrueif and only if TLS renegotiation is enabled. -
setEnableRenegotiation
public void setEnableRenegotiation(boolean enableRenegotiation) Enables or disables TLS renegotiation. -
setIssueHandshake
public void setIssueHandshake(boolean issueHandshake) -
isIssueHandshake
public boolean isIssueHandshake()Returnstrueif the automatic handshake is enabled -
getSSLEngineInboundCloseFuture
Return theChannelFuturethat will get notified if the inbound of theSSLEnginewill get closed. This method will return the sameChannelFutureall the time. For more informations see the apidocs ofSSLEngine -
getHandshakeTimeout
public long getHandshakeTimeout()Return the timeout (in ms) after which theChannelFutureofhandshake()will be failed, while a handshake is in progress -
setCloseOnSSLException
public void setCloseOnSSLException(boolean closeOnSslException) If set totrue, theChannelwill automatically get closed one aSSLExceptionwas caught. This is most times what you want, as after this its almost impossible to recover. Anyway the default isfalseto not break compatibility with older releases. This will be changed totruein the next major release. -
getCloseOnSSLException
public boolean getCloseOnSSLException() -
handleDownstream
Description copied from interface:ChannelDownstreamHandlerHandles the specified downstream event.- Specified by:
handleDownstreamin interfaceChannelDownstreamHandler- Parameters:
context- the context object for this handlerevt- the downstream event to process or intercept- Throws:
Exception
-
channelDisconnected
Description copied from class:SimpleChannelUpstreamHandlerInvoked when aChannelwas disconnected from its remote peer.- Overrides:
channelDisconnectedin classFrameDecoder- Throws:
Exception
-
exceptionCaught
Description copied from class:SimpleChannelUpstreamHandlerInvoked when an exception was raised by an I/O thread or aChannelHandler.- Overrides:
exceptionCaughtin classFrameDecoder- Throws:
Exception
-
isEncrypted
Returnstrueif the givenChannelBufferis encrypted. Be aware that this method will not increase the readerIndex of the givenChannelBuffer.- Parameters:
buffer- TheChannelBufferto read from. Be aware that it must have at least 5 bytes to read, otherwise it will throw anIllegalArgumentException.- Returns:
- encrypted
trueif theChannelBufferis encrypted,falseotherwise. - Throws:
IllegalArgumentException- Is thrown if the givenChannelBufferhas not at least 5 bytes to read.
-
decode
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer in) throws Exception Description copied from class:FrameDecoderDecodes the received packets so far into a frame. If an sub-class wants to extract a frame out of the buffer it should use theFrameDecoder.extractFrame(ChannelBuffer, int, int)method, to make optimizations easier later.- Specified by:
decodein classFrameDecoder- Parameters:
ctx- the context of this handlerchannel- the current channelin- the cumulative buffer of received packets so far. Note that the buffer might be empty, which means you should not make an assumption that the buffer contains at least one byte in your decoder implementation.- Returns:
- the decoded frame if a full frame was received and decoded.
nullif there's not enough data in the buffer to decode a frame. - Throws:
Exception
-
beforeAdd
- Specified by:
beforeAddin interfaceLifeCycleAwareChannelHandler- Overrides:
beforeAddin classFrameDecoder- Throws:
Exception
-
afterRemove
Fail all pending writes which we were not able to flush out- Specified by:
afterRemovein interfaceLifeCycleAwareChannelHandler- Overrides:
afterRemovein classFrameDecoder- Throws:
Exception
-
channelConnected
Callshandshake()once theChannelis connected- Overrides:
channelConnectedin classSimpleChannelUpstreamHandler- Throws:
Exception
-
channelClosed
Loop over all the pending writes and fail them. See #305 for more details.- Overrides:
channelClosedin classFrameDecoder- Throws:
Exception
-