I have an MITM proxy server built with java/netty. Recently I ran into an https url, for which my proxy gets an SSL handshake failure but the curl
command is able to access in TLS protocol. In my proxy code, the client SSL context uses a trust-all trust manager. Below is how I create the client-side SSL context and SSL handler.
public static SSLContext createClientSslContext() throws NoSuchAlgorithmException, KeyManagementException {
SSLContext context = SSLContext.getInstance("TLS");
// create a trust-all manager
TrustManager trustAllManager = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
log.debug("do nothing - getAcceptedIssuers");
return new X509Certificate[0];
}
};
context.init(null, new TrustManager[]{trustAllManager}, null);
return context;
}
private SslHandler createClientSslHandler() {
try {
SSLContext context = SslContextFactory.createClientSslContext();
SSLEngine engine = context.createSSLEngine();
engine.setUseClientMode(true);
engine.setEnabledProtocols(new String[]{"TLSv1.2", "TLSv1.1", "TLSv1", "SSLv3"});
return new SslHandler(engine);
} catch (Exception e) {
log.error("Failed to create SslHandler with exception:", e);
return null;
}
}
I set javax.net.debug=all. Below is error output.
*** ClientHello, TLSv1.2
RandomCookie: GMT: 1429274460 bytes = { 38, 155, 211, 75, 172, 225, 176, 73, 59, 96, 150, 25, 105, 108, 225, 216, 178, 171, 40, 154, 59, 187, 206, 50, 87, 63, 46, 137 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension signature_algorithms, signature_algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA224withECDSA, SHA224withRSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA, MD5withRSA
***
[write] MD5 and SHA1 hashes: len = 193
0000: 01 00 00 BD 03 03 55 31 FF 5C 26 9B D3 4B AC E1 ......U1.\&..K..
0010: B0 49 3B 60 96 19 69 6C E1 D8 B2 AB 28 9A 3B BB .I;`..il....(.;.
0020: CE 32 57 3F 2E 89 00 00 38 C0 23 C0 27 00 3C C0 .2W?....8.#.'.<.
0030: 25 C0 29 00 67 00 40 C0 09 C0 13 00 2F C0 04 C0 %.).g.@...../...
0040: 0E 00 33 00 32 C0 08 C0 12 00 0A C0 03 C0 0D 00 ..3.2...........
0050: 16 00 13 C0 07 C0 11 00 05 C0 02 C0 0C 00 04 00 ................
0060: FF 01 00 00 5C 00 0A 00 34 00 32 00 17 00 01 00 ....\...4.2.....
0070: 03 00 13 00 15 00 06 00 07 00 09 00 0A 00 18 00 ................
0080: 0B 00 0C 00 19 00 0D 00 0E 00 0F 00 10 00 11 00 ................
0090: 02 00 12 00 04 00 05 00 14 00 08 00 16 00 0B 00 ................
00A0: 02 01 00 00 0D 00 1A 00 18 06 03 06 01 05 03 05 ................
00B0: 01 04 03 04 01 03 03 03 01 02 03 02 01 02 02 01 ................
00C0: 01 .
nioEventLoopGroup-15-0, WRITE: TLSv1.2 Handshake, length = 193
[Raw write]: length = 198
0000: 16 03 03 00 C1 01 00 00 BD 03 03 55 31 FF 5C 26 ...........U1.\&
0010: 9B D3 4B AC E1 B0 49 3B 60 96 19 69 6C E1 D8 B2 ..K...I;`..il...
0020: AB 28 9A 3B BB CE 32 57 3F 2E 89 00 00 38 C0 23 .(.;..2W?....8.#
0030: C0 27 00 3C C0 25 C0 29 00 67 00 40 C0 09 C0 13 .'.<.%.).g.@....
0040: 00 2F C0 04 C0 0E 00 33 00 32 C0 08 C0 12 00 0A ./.....3.2......
0050: C0 03 C0 0D 00 16 00 13 C0 07 C0 11 00 05 C0 02 ................
0060: C0 0C 00 04 00 FF 01 00 00 5C 00 0A 00 34 00 32 .........\...4.2
0070: 00 17 00 01 00 03 00 13 00 15 00 06 00 07 00 09 ................
0080: 00 0A 00 18 00 0B 00 0C 00 19 00 0D 00 0E 00 0F ................
0090: 00 10 00 11 00 02 00 12 00 04 00 05 00 14 00 08 ................
00A0: 00 16 00 0B 00 02 01 00 00 0D 00 1A 00 18 06 03 ................
00B0: 06 01 05 03 05 01 04 03 04 01 03 03 03 01 02 03 ................
00C0: 02 01 02 02 01 01 ......
[Raw read]: length = 5
0000: 15 03 03 00 02 .....
[Raw read]: length = 2
0000: 02 28 .(
nioEventLoopGroup-15-0, READ: TLSv1.2 Alert, length = 2
nioEventLoopGroup-15-0, RECV TLSv1 ALERT: fatal, handshake_failure
nioEventLoopGroup-15-0, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
nioEventLoopGroup-15-0, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
nioEventLoopGroup-15-0, called closeOutbound()
nioEventLoopGroup-15-0, closeOutboundInternal()
nioEventLoopGroup-15-0, SEND TLSv1 ALERT: warning, description = close_notify
nioEventLoopGroup-15-0, WRITE: TLSv1 Alert, length = 2
nioEventLoopGroup-15-0, called closeInbound()
nioEventLoopGroup-15-0, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
2015-04-17 23:53:16.246 [nioEventLoopGroup-15-0] ERROR ClientHandler#exceptionCaught(): Caught exception
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLException: Received fatal alert: handshake_failure
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:347) ~[netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:230) ~[netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:84) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:153) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.PausableChannelEventExecutor.invokeChannelRead(PausableChannelEventExecutor.java:86) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:389) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at com.company.proxy.handler.TrafficCounterHandler.channelRead(TrafficCounterHandler.java:29) [classes/:na]
at io.netty.channel.ChannelHandlerInvokerUtil.invokeChannelReadNow(ChannelHandlerInvokerUtil.java:84) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.DefaultChannelHandlerInvoker.invokeChannelRead(DefaultChannelHandlerInvoker.java:153) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.PausableChannelEventExecutor.invokeChannelRead(PausableChannelEventExecutor.java:86) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:389) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:956) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:127) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:514) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:471) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:385) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:351) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.util.internal.chmv8.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1412) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.util.internal.chmv8.ForkJoinTask.doExec(ForkJoinTask.java:280) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.util.internal.chmv8.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:877) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.util.internal.chmv8.ForkJoinPool.scan(ForkJoinPool.java:1706) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.util.internal.chmv8.ForkJoinPool.runWorker(ForkJoinPool.java:1661) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.util.internal.chmv8.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:126) [netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
Caused by: javax.net.ssl.SSLException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208) ~[na:1.7.0_80]
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1639) ~[na:1.7.0_80]
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1607) ~[na:1.7.0_80]
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1776) ~[na:1.7.0_80]
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1068) ~[na:1.7.0_80]
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:890) ~[na:1.7.0_80]
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:764) ~[na:1.7.0_80]
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624) ~[na:1.7.0_80]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1071) ~[netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:938) ~[netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:891) ~[netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:316) ~[netty-all-5.0.0.Alpha2.jar:5.0.0.Alpha2]
... 23 common frames omitted
nioEventLoopGroup-15-0, called closeOutbound()
nioEventLoopGroup-15-0, closeOutboundInternal()
nioEventLoopGroup-15-0, called closeInbound()
nioEventLoopGroup-15-0, closeInboundInternal()
nioEventLoopGroup-15-0, closeOutboundInternal()
I have tried both JDK 7 and JDK 8, and neither gave me any luck. I also installed the unlimited-strength JCE policies, but no luck either. Given that curl
command is able to access the https url successfully, I think the url itself should be fine. So, how can I make it work in Java/netty?
BTW, I am not sure if it is ok to disclose the https url in question, so I choose not to in order to avoid unnecessary trouble.
update
From the curl -v
output, I can see this line:
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
The cipher TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
is present in the ClientHello message, so missing-cipher is unlikely the root cause here.
update
I made two tests for the same https url, one using jersey-client, and the other using my own custom netty client. Below is the code.
@Test
public void testHandshakeFailedUrlWithJersey() throws Exception {
String url = "https://cdn.prod.paperg.com/ajax/libs/require.js/2.1.10/require.js";
Client client = ClientBuilder.newClient();
Response response = null;
try {
response = client.target(url).request().get();
} catch (Exception e) {
e.printStackTrace();
}
log.info("Response - {}", response);
}
@Test
public void testHandshakeFailedUrlWithNetty() throws Exception {
String url = "https://cdn.prod.paperg.com/ajax/libs/require.js/2.1.10/require.js";
Bootstrap clientBootstrap = new Bootstrap();
EventLoopGroup clientGroup = new NioEventLoopGroup();
SSLContext context = SslContextFactory.createClientSslContext();
SSLEngine engine = context.createSSLEngine();
engine.setUseClientMode(true);
engine.setEnabledProtocols(new String[]{"TLSv1"});
final SslHandler sslHandler = new SslHandler(engine);
clientBootstrap.group(clientGroup)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(CLIENT_SSL_HANDLER, sslHandler)
.addLast(HTTP_CLIENT_CODEC, new HttpClientCodec())
.addLast(HTTP_CONTENT_AGGREGATOR, new HttpObjectAggregator(MAX_HTTP_CONTENT_LENGTH))
.addLast(CLIENT_HANDLER, new ChannelHandlerAdapter(){
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.info("Received message");
}
});
}
});
String host = "cdn.prod.paperg.com";
InetSocketAddress inetSocketAddress = new InetSocketAddress(host, 443);
FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_0,
HttpMethod.GET, url);
Channel channel = clientBootstrap.connect(inetSocketAddress).sync().channel();
channel.writeAndFlush(request);
}
It turns out that the jersey-client test is able to get a valid response, but the netty-client test fails with the same handshake_failure error. BTW, I verified the netty-client test code with https://www.google.com
, and it was able to complete the SSL handshake successfully and get a valid certificate.
Below are relevant logs.
From jersey-client test:
trigger seeding of SecureRandom
done seeding SecureRandom
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
main, setSoTimeout(0) called
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: GMT: 1429371593 bytes = { 30, 195, 29, 134, 181, 7, 17, 54, 187, 208, 156, 70, 39, 155, 224, 131, 105, 241, 174, 168, 211, 230, 57, 162, 17, 27, 183, 151 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
Extension server_name, server_name: [host_name: cdn.prod.paperg.com]
***
main, WRITE: TLSv1 Handshake, length = 191
main, READ: TLSv1 Handshake, length = 61
*** ServerHello, TLSv1
RandomCookie: GMT: -1685243653 bytes = { 168, 78, 151, 192, 211, 185, 197, 74, 192, 90, 94, 113, 176, 188, 210, 43, 19, 253, 221, 73, 35, 104, 243, 6, 28, 79, 40, 190 }
Session ID: {}
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
Compression Method: 0
Extension server_name, server_name:
Extension renegotiation_info, renegotiated_connection: <empty>
Extension ec_point_formats, formats: [uncompressed, ansiX962_compressed_prime, ansiX962_compressed_char2]
***
%% Initialized: [Session-1, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA]
** TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
main, READ: TLSv1 Handshake, length = 2560
*** Certificate chain
From netty-client test:
trigger seeding of SecureRandom
done seeding SecureRandom
Using SSLEngineImpl.
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: GMT: 1429371694 bytes = { 31, 45, 240, 255, 71, 215, 187, 150, 66, 220, 94, 118, 163, 1, 24, 38, 155, 158, 254, 201, 249, 203, 125, 96, 56, 225, 162, 247 }
Session ID: {}
Cipher Suites: [TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_DSS_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_SHA, TLS_ECDH_ECDSA_WITH_RC4_128_SHA, TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_RC4_128_MD5, TLS_EMPTY_RENEGOTIATION_INFO_SCSV]
Compression Methods: { 0 }
Extension elliptic_curves, curve names: {secp256r1, sect163k1, sect163r2, secp192r1, secp224r1, sect233k1, sect233r1, sect283k1, sect283r1, secp384r1, sect409k1, sect409r1, secp521r1, sect571k1, sect571r1, secp160k1, secp160r1, secp160r2, sect163r1, secp192k1, sect193r1, sect193r2, secp224k1, sect239k1, secp256k1}
Extension ec_point_formats, formats: [uncompressed]
***
nioEventLoopGroup-0-1, WRITE: TLSv1 Handshake, length = 163
nioEventLoopGroup-0-1, READ: TLSv1 Alert, length = 2
nioEventLoopGroup-0-1, RECV TLSv1 ALERT: fatal, handshake_failure
nioEventLoopGroup-0-1, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
nioEventLoopGroup-0-1, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: handshake_failure
nioEventLoopGroup-0-1, called closeOutbound()
nioEventLoopGroup-0-1, closeOutboundInternal()
nioEventLoopGroup-0-1, SEND TLSv1 ALERT: warning, description = close_notify
nioEventLoopGroup-0-1, WRITE: TLSv1 Alert, length = 2
nioEventLoopGroup-0-1, called closeInbound()
nioEventLoopGroup-0-1, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
The only difference that I can see from the two tests is that the jersey-client puts this message in the ClientHello:
Extension server_name, server_name
which is not present in the netty-client test.
It turns out that the peer host and port matter in my case. This line fixed the issue:
SSLEngine engine = context.createSSLEngine(host, 443);
OK, here is what solved a similar issue for me (in case anyone else is hitting this problem).
Using the Webupd8 packages on Ubuntu, I had to install oracle-java8-unlimited-jce-policy
separately. This enables strong encryption which falls under some US export limitation.
Go figure.
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