Java 使用SSL时Netty ChannelHandler关闭
我在客户机/服务器环境中使用netty时遇到问题。使用设置服务器后Java 使用SSL时Netty ChannelHandler关闭,java,ssl,client,netty,keep-alive,Java,Ssl,Client,Netty,Keep Alive,我在客户机/服务器环境中使用netty时遇到问题。使用设置服务器后 bossGroup = new NioEventLoopGroup(); workerGroup = new NioEventLoopGroup(); try { serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup); serverBootstrap.channel(NioSer
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
try {
serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup);
serverBootstrap.channel(NioServerSocketChannel.class);
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
channel.pipeline().addLast(new ObjectEncoder(), new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)), new UserPacketDecoder(serverRev));
channel.pipeline().addLast(new LoggingHandler());
}
});
logger.info(language.getProperty("Server.Info.Netty.PortOpened"));
serverBootstrap.bind(serverPort).sync().channel().closeFuture().sync().channel().closeFuture().sync();
} catch (Exception e) {
logger.error(language.getProperty("Server.Error.Netty.Initialize"), e);
}
客户端连接、发送请求数据包、等待来自服务器的应答数据包,并应通过以下方式关闭连接:
workerGroup = new NioEventLoopGroup();
bootstrap = new Bootstrap();
bootstrap.group(workerGroup);
bootstrap.channel(NioSocketChannel.class);
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel channel) {
channel.pipeline().addLast(new ObjectEncoder(), new ObjectDecoder(50000000, ClassResolvers.cacheDisabled(null)), new PacketRelay());
channel.pipeline().addLast(new LoggingHandler());
}
});
try {
bootstrap.connect(hostIP, hostPort).sync().channel().closeFuture().sync();
} catch (Exception e) {
logger.error("Error connecting", e);
} finally {
workerGroup.shutdownGracefully();
}
没有加密,一切正常!
现在,我在服务器端使用启用SSL(自签名证书)
System.setProperty("javax.net.ssl.keyStore", ksPath);
System.setProperty("javax.net.ssl.keyStorePassword", ksPW);
System.setProperty("javax.net.ssl.trustStore", tsPath);
System.setProperty("javax.net.ssl.trustStorePassword", tsPW);
SSLContext ctx = null;
try {
ctx = SSLContext.getDefault();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
final SSLEngine engine = ctx.createSSLEngine();
engine.setUseClientMode(false);
engine.setNeedClientAuth(false); //tried both -> true and false
及
作为管道中的第一个元素。在客户端,情况非常相似
SSLContext ctx = null;
try {
ctx = SSLContext.getDefault();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
final SSLEngine engine = ctx.createSSLEngine();
engine.setUseClientMode(true);
及
作为管道中的第一个元素。如您所见,我通过向管道添加新的LoggingHandler()启用了netty的调试模式。我也设置了
InternalLoggerFactory.setDefaultFactory(new Log4JLoggerFactory());
System.setProperty("javax.net.debug", "ssl");
System.setProperty("ssl.debug", "true");
用于其他日志记录
来自客户端的第一个请求按预期处理,但我在客户端看到一个异常:
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data: { 30, 112, 54, 24, 223, 62, 135, 143, 88, 178, 186, 12 }
***
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Handshake, length = 96
nioEventLoopGroup-2-1, READ: TLSv1.2 Change Cipher Spec, length = 1
nioEventLoopGroup-2-1, READ: TLSv1.2 Handshake, length = 96
*** Finished
verify_data: { 5, 115, 178, 143, 196, 203, 86, 123, 42, 40, 44, 34 }
***
%% Cached client session: [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384]
2018-02-19 16:45:36 DEBUG SslHandler:1435 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 - R:localhost/127.0.0.1:23600] HANDSHAKEN: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 - R:localhost/127.0.0.1:23600] USER_EVENT: SslHandshakeCompletionEvent(SUCCESS)
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Application Data, length = 129
nioEventLoopGroup-2-1, called closeOutbound()
nioEventLoopGroup-2-1, closeOutboundInternal()
nioEventLoopGroup-2-1, SEND TLSv1.2 ALERT: warning, description = close_notify
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Alert, length = 80
nioEventLoopGroup-2-1, called closeOutbound()
nioEventLoopGroup-2-1, closeOutboundInternal()
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 ! R:localhost/127.0.0.1:23600] USER_EVENT: SslCloseCompletionEvent(java.nio.channels.ClosedChannelException)
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 ! R:localhost/127.0.0.1:23600] INACTIVE
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 ! R:localhost/127.0.0.1:23600] UNREGISTERED
GetNews OK //<-------------------- Answer from server
2018-02-19 16:45:39 DEBUG PoolThreadCache:262 - Freed 13 thread-local buffer(s) from thread: nioEventLoopGroup-2-1
我找不到答案。。。感谢您的建议问题在于客户何时应该正确关闭并打开一个新的。有两个证据可以证明这一点:它只对第一个请求起作用,以及客户端发送的消息(之后是服务器发送的消息)。在第一次成功的事务之后,日志显示SSL握手超时,这是SSL连接上的正常现象,该连接应该已经关闭
我现在还没有足够的关于netty的知识来给出确切的解决方案,但是了解原因应该会对你有很大帮助。在这种情况下,他们提供了一种禁用HTTP保持活动的方法,这正是我们想要实现的,通过将头设置为Close值。他们正在解决相反的问题,但可能会给我们提供解决方案。感谢Eugene对SSL过程的更多解释。如果客户端已经关闭了连接,为什么要在这种情况下禁用Keep Alive帮助?在引用的线程中,使用了一个HttpResponse,该头被设置为Close值。如何将其转录到不使用HttpResponse的示例中?网络连接仍处于打开状态,但您无法再使用它,因为客户端发送了TLS close_notify警报。您需要关闭网络连接,我认为禁用Keep-Alive头值可能是解决方案。如果你不使用HttpResponse,一定有办法做到这一点,但我不是网络专家,我可以阅读文档。你写道:“客户端连接,发送请求数据包,等待服务器的应答数据包,并通过以下方式关闭连接:”。我怀疑这会结束任何事情。网络捕获将显示是否关闭。或者您可以使用netstat-an监视连接,并在服务器端口上进行筛选感谢Eugene。。。我试图通过在服务器端设置serverBootstrap.option(ChannelOption.SO_KEEPALIVE,false)来取消激活行为。它会导致通道“[id:0xf4ed9bbf]”的警告->服务器引导:460-未知通道选项“SO_KEEPALIVE”。此外,我还更改了ctx.writeAndFlush(outgoingPacket.addListener(ChannelFutureListener.CLOSE);在UserPacketDecoder中。它没有任何效果。@knoop:SO_KEEPALIVE是一个TCP设置,而不是用来保持连接打开的HTTP keep-alive。这些名字看起来很相似,让一些人误会了。无论如何,我相信这是在一周后,在理解这个问题上迈出的一大步。
SSLContext ctx = null;
try {
ctx = SSLContext.getDefault();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
final SSLEngine engine = ctx.createSSLEngine();
engine.setUseClientMode(true);
channel.pipeline().addLast("sslHandler", new SslHandler(engine));
InternalLoggerFactory.setDefaultFactory(new Log4JLoggerFactory());
System.setProperty("javax.net.debug", "ssl");
System.setProperty("ssl.debug", "true");
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data: { 30, 112, 54, 24, 223, 62, 135, 143, 88, 178, 186, 12 }
***
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Handshake, length = 96
nioEventLoopGroup-2-1, READ: TLSv1.2 Change Cipher Spec, length = 1
nioEventLoopGroup-2-1, READ: TLSv1.2 Handshake, length = 96
*** Finished
verify_data: { 5, 115, 178, 143, 196, 203, 86, 123, 42, 40, 44, 34 }
***
%% Cached client session: [Session-1, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384]
2018-02-19 16:45:36 DEBUG SslHandler:1435 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 - R:localhost/127.0.0.1:23600] HANDSHAKEN: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 - R:localhost/127.0.0.1:23600] USER_EVENT: SslHandshakeCompletionEvent(SUCCESS)
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Application Data, length = 129
nioEventLoopGroup-2-1, called closeOutbound()
nioEventLoopGroup-2-1, closeOutboundInternal()
nioEventLoopGroup-2-1, SEND TLSv1.2 ALERT: warning, description = close_notify
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Alert, length = 80
nioEventLoopGroup-2-1, called closeOutbound()
nioEventLoopGroup-2-1, closeOutboundInternal()
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 ! R:localhost/127.0.0.1:23600] USER_EVENT: SslCloseCompletionEvent(java.nio.channels.ClosedChannelException)
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 ! R:localhost/127.0.0.1:23600] INACTIVE
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x0c2c19e6, L:/127.0.0.1:54629 ! R:localhost/127.0.0.1:23600] UNREGISTERED
GetNews OK //<-------------------- Answer from server
2018-02-19 16:45:39 DEBUG PoolThreadCache:262 - Freed 13 thread-local buffer(s) from thread: nioEventLoopGroup-2-1
nioEventLoopGroup-3-1, READ: TLSv1.2 Change Cipher Spec, length = 1
nioEventLoopGroup-3-1, READ: TLSv1.2 Handshake, length = 96
*** Finished
verify_data: { 30, 112, 54, 24, 223, 62, 135, 143, 88, 178, 186, 12 }
***
nioEventLoopGroup-3-1, WRITE: TLSv1.2 Change Cipher Spec, length = 1
*** Finished
verify_data: { 5, 115, 178, 143, 196, 203, 86, 123, 42, 40, 44, 34 }
***
nioEventLoopGroup-3-1, WRITE: TLSv1.2 Handshake, length = 96
%% Cached server session: [Session-2, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384]
2018-02-19 16:45:36 DEBUG SslHandler:1435 - [id: 0x6245c2c5, L:/127.0.0.1:23600 - R:/127.0.0.1:54629] HANDSHAKEN: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x6245c2c5, L:/127.0.0.1:23600 - R:/127.0.0.1:54629] USER_EVENT: SslHandshakeCompletionEvent(SUCCESS)
2018-02-19 16:45:36 INFO UserPacketDecoder:865 - IncomingPacket -> GetNews //<-------------------- Request from client
nioEventLoopGroup-3-1, WRITE: TLSv1.1 Application Data, length = 144
nioEventLoopGroup-3-1, READ: TLSv1.1 Application Data, length = 112
nioEventLoopGroup-3-1, WRITE: TLSv1.1 Application Data, length = 144
nioEventLoopGroup-3-1, READ: TLSv1.1 Application Data, length = 112
nioEventLoopGroup-3-1, WRITE: TLSv1.1 Application Data, length = 176
nioEventLoopGroup-3-1, READ: TLSv1.1 Application Data, length = 160
nioEventLoopGroup-3-1, WRITE: TLSv1.1 Application Data, length = 96
nioEventLoopGroup-3-1, READ: TLSv1.1 Application Data, length = 992
nioEventLoopGroup-3-1, WRITE: TLSv1.1 Application Data, length = 96
nioEventLoopGroup-3-1, READ: TLSv1.1 Application Data, length = 1136
nioEventLoopGroup-3-1, WRITE: TLSv1.1 Application Data, length = 112
nioEventLoopGroup-3-1, READ: TLSv1.1 Application Data, length = 432
nioEventLoopGroup-3-1, WRITE: TLSv1.1 Application Data, length = 80
nioEventLoopGroup-3-1, READ: TLSv1.1 Application Data, length = 64
nioEventLoopGroup-3-1, WRITE: TLSv1.1 Application Data, length = 96
nioEventLoopGroup-3-1, READ: TLSv1.1 Application Data, length = 64
nioEventLoopGroup-3-1, WRITE: TLSv1.1 Application Data, length = 80
nioEventLoopGroup-3-1, READ: TLSv1.1 Application Data, length = 128
nioEventLoopGroup-3-1, WRITE: TLSv1.2 Application Data, length = 122
nioEventLoopGroup-3-1, READ: TLSv1.2 Alert, length = 80
nioEventLoopGroup-3-1, RECV TLSv1.2 ALERT: warning, close_notify
nioEventLoopGroup-3-1, closeInboundInternal()
nioEventLoopGroup-3-1, closeOutboundInternal()
nioEventLoopGroup-3-1, SEND TLSv1.2 ALERT: warning, description = close_notify
nioEventLoopGroup-3-1, WRITE: TLSv1.2 Alert, length = 80
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x6245c2c5, L:/127.0.0.1:23600 - R:/127.0.0.1:54629] USER_EVENT: SslCloseCompletionEvent(SUCCESS)
nioEventLoopGroup-3-1, called closeOutbound()
nioEventLoopGroup-3-1, closeOutboundInternal()
nioEventLoopGroup-3-1, called closeInbound()
nioEventLoopGroup-3-1, closeInboundInternal()
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x6245c2c5, L:/127.0.0.1:23600 ! R:/127.0.0.1:54629] INACTIVE
2018-02-19 16:45:36 DEBUG LoggingHandler:147 - [id: 0x6245c2c5, L:/127.0.0.1:23600 ! R:/127.0.0.1:54629] UNREGISTERED
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Handshake, length = 203
2018-02-19 16:55:39 DEBUG Recycler:96 - -Dio.netty.recycler.maxCapacityPerThread: 32768
2018-02-19 16:55:39 DEBUG Recycler:97 - -Dio.netty.recycler.maxSharedCapacityFactor: 2
2018-02-19 16:55:39 DEBUG Recycler:98 - -Dio.netty.recycler.linkCapacity: 16
2018-02-19 16:55:39 DEBUG Recycler:99 - -Dio.netty.recycler.ratio: 8
2018-02-19 16:55:39 DEBUG AbstractByteBuf:52 - -Dio.netty.buffer.bytebuf.checkAccessible: true
2018-02-19 16:55:39 DEBUG ResourceLeakDetectorFactory:202 - Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@13e73780
2018-02-19 16:55:49 DEBUG LoggingHandler:147 - [id: 0x25b3173b, L:/127.0.0.1:55853 - R:localhost/127.0.0.1:23600] USER_EVENT: SslHandshakeCompletionEvent(javax.net.ssl.SSLException: handshake timed out)
nioEventLoopGroup-2-1, called closeOutbound()
nioEventLoopGroup-2-1, closeOutboundInternal()
nioEventLoopGroup-2-1, SEND TLSv1.2 ALERT: warning, description = close_notify
nioEventLoopGroup-2-1, WRITE: TLSv1.2 Alert, length = 2
nioEventLoopGroup-2-1, called closeInbound()
nioEventLoopGroup-2-1, fatal error: 80: Inbound closed before receiving peer's close_notify: possible truncation attack?
javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
nioEventLoopGroup-2-1, SEND TLSv1.2 ALERT: fatal, description = internal_error
nioEventLoopGroup-2-1, Exception sending alert: java.io.IOException: writer side was already closed.
2018-02-19 16:55:49 DEBUG LoggingHandler:147 - [id: 0x25b3173b, L:/127.0.0.1:55853 ! R:localhost/127.0.0.1:23600] USER_EVENT: SslCloseCompletionEvent(java.nio.channels.ClosedChannelException)
2018-02-19 16:55:49 DEBUG LoggingHandler:147 - [id: 0x25b3173b, L:/127.0.0.1:55853 ! R:localhost/127.0.0.1:23600] INACTIVE
2018-02-19 16:55:49 DEBUG LoggingHandler:147 - [id: 0x25b3173b, L:/127.0.0.1:55853 ! R:localhost/127.0.0.1:23600] UNREGISTERED
2018-02-19 16:55:51 DEBUG PoolThreadCache:262 - Freed 4 thread-local buffer(s) from thread: nioEventLoopGroup-2-1