Improve client SNI in testSniWithApnHandler
Motivations The test SniHandlerTest#testSniWithApnHandler() does not actually involve SNI: given the client setup, the ClientHello in the form of hex strings is not actually written to the wire, so the server never receives that. We may need to write in somewhere else (e.g., channelActive()) instead of in initChannel() in order for the hex strings to reach the server. So here what's actually going on is an ordinary TLS C/S communication without SNI. Modifications The client part is modified to enable SNI by using an SslHandler with an SSLEngine created by io.netty.handler.ssl.SslContext#newEngine(), where the server hostname is specified. Also, more clauses are added to verify that the SNI is indeed successful. Results Now the test verifies that both SNI and APN actually happen and succeed.
This commit is contained in:
parent
6d7bed3431
commit
ad27387646
@ -18,11 +18,11 @@ package io.netty.handler.ssl;
|
|||||||
|
|
||||||
import io.netty.bootstrap.Bootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
@ -41,7 +41,6 @@ import java.net.InetSocketAddress;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.net.ssl.HandshakeCompletedEvent;
|
|
||||||
import javax.xml.bind.DatatypeConverter;
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
@ -164,25 +163,15 @@ public class SniHandlerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSniWithApnHandler() throws Exception {
|
public void testSniWithApnHandler() throws Exception {
|
||||||
SslContext nettyContext = makeSslContext();
|
SslContext nettyContext = makeSslContext();
|
||||||
SslContext leanContext = makeSslContext();
|
SslContext sniContext = makeSslContext();
|
||||||
final SslContext clientContext = makeSslClientContext();
|
final SslContext clientContext = makeSslClientContext();
|
||||||
SslContext wrappedLeanContext = null;
|
|
||||||
final CountDownLatch serverApnDoneLatch = new CountDownLatch(1);
|
final CountDownLatch serverApnDoneLatch = new CountDownLatch(1);
|
||||||
final CountDownLatch clientApnDoneLatch = new CountDownLatch(1);
|
final CountDownLatch clientApnDoneLatch = new CountDownLatch(1);
|
||||||
|
|
||||||
final DomainNameMapping<SslContext> mapping = new DomainMappingBuilder(nettyContext)
|
final DomainNameMapping<SslContext> mapping = new DomainMappingBuilder(nettyContext)
|
||||||
.add("*.netty.io", nettyContext)
|
.add("*.netty.io", nettyContext)
|
||||||
.add("*.LEANCLOUD.CN", leanContext).build();
|
.add("sni.fake.site", sniContext).build();
|
||||||
// hex dump of a client hello packet, which contains hostname "CHAT4。LEANCLOUD。CN"
|
final SniHandler handler = new SniHandler(mapping);
|
||||||
final String tlsHandshakeMessageHex1 = "16030100";
|
|
||||||
// part 2
|
|
||||||
final String tlsHandshakeMessageHex = "bd010000b90303a74225676d1814ba57faff3b366" +
|
|
||||||
"3656ed05ee9dbb2a4dbb1bb1c32d2ea5fc39e0000000100008c0000001700150000164348" +
|
|
||||||
"415434E380824C45414E434C4F5544E38082434E000b000403000102000a00340032000e0" +
|
|
||||||
"00d0019000b000c00180009000a0016001700080006000700140015000400050012001300" +
|
|
||||||
"0100020003000f0010001100230000000d0020001e0601060206030501050205030401040" +
|
|
||||||
"20403030103020303020102020203000f00010133740000";
|
|
||||||
|
|
||||||
EventLoopGroup group = new NioEventLoopGroup(2);
|
EventLoopGroup group = new NioEventLoopGroup(2);
|
||||||
Channel serverChannel = null;
|
Channel serverChannel = null;
|
||||||
Channel clientChannel = null;
|
Channel clientChannel = null;
|
||||||
@ -195,7 +184,7 @@ public class SniHandlerTest {
|
|||||||
protected void initChannel(Channel ch) throws Exception {
|
protected void initChannel(Channel ch) throws Exception {
|
||||||
ChannelPipeline p = ch.pipeline();
|
ChannelPipeline p = ch.pipeline();
|
||||||
// Server side SNI.
|
// Server side SNI.
|
||||||
p.addLast(new SniHandler(mapping));
|
p.addLast(handler);
|
||||||
// Catch the notification event that APN has completed successfully.
|
// Catch the notification event that APN has completed successfully.
|
||||||
p.addLast(new ApplicationProtocolNegotiationHandler("foo") {
|
p.addLast(new ApplicationProtocolNegotiationHandler("foo") {
|
||||||
@Override
|
@Override
|
||||||
@ -212,11 +201,8 @@ public class SniHandlerTest {
|
|||||||
cb.handler(new ChannelInitializer<Channel>() {
|
cb.handler(new ChannelInitializer<Channel>() {
|
||||||
@Override
|
@Override
|
||||||
protected void initChannel(Channel ch) throws Exception {
|
protected void initChannel(Channel ch) throws Exception {
|
||||||
// Simulate client side SNI (which is currently not supported).
|
ch.pipeline().addLast(new SslHandler(clientContext.newEngine(
|
||||||
ch.write(Unpooled.wrappedBuffer(DatatypeConverter.parseHexBinary(tlsHandshakeMessageHex1)));
|
ch.alloc(), "sni.fake.site", -1)));
|
||||||
ch.writeAndFlush(Unpooled.wrappedBuffer(DatatypeConverter.parseHexBinary(tlsHandshakeMessageHex)));
|
|
||||||
// Add a SslHandler so we can do the client side of the handshake.
|
|
||||||
ch.pipeline().addLast(clientContext.newHandler(ch.alloc()));
|
|
||||||
// Catch the notification event that APN has completed successfully.
|
// Catch the notification event that APN has completed successfully.
|
||||||
ch.pipeline().addLast(new ApplicationProtocolNegotiationHandler("foo") {
|
ch.pipeline().addLast(new ApplicationProtocolNegotiationHandler("foo") {
|
||||||
@Override
|
@Override
|
||||||
@ -235,6 +221,8 @@ public class SniHandlerTest {
|
|||||||
|
|
||||||
assertTrue(serverApnDoneLatch.await(5, TimeUnit.SECONDS));
|
assertTrue(serverApnDoneLatch.await(5, TimeUnit.SECONDS));
|
||||||
assertTrue(clientApnDoneLatch.await(5, TimeUnit.SECONDS));
|
assertTrue(clientApnDoneLatch.await(5, TimeUnit.SECONDS));
|
||||||
|
assertThat(handler.hostname(), is("sni.fake.site"));
|
||||||
|
assertThat(handler.sslContext(), is(sniContext));
|
||||||
} finally {
|
} finally {
|
||||||
if (serverChannel != null) {
|
if (serverChannel != null) {
|
||||||
serverChannel.close().sync();
|
serverChannel.close().sync();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user