【问题标题】:Netty Server connection with SSL drops client connection after invocation使用 SSL 的 Netty 服务器连接在调用后断开客户端连接
【发布时间】:2017-03-07 15:43:43
【问题描述】:

我正在使用 ssl(自签名证书)运行 Netty 4.2 套接字通信代码。

我的问题: 当客户端尝试使用 SSL 连接到服务器时,服务器会立即断开连接。服务器立即触发 channelUnregistered() 方法。

我注意到的一点是,一旦服务器启动,客户端连接第一次保持并正常工作。但是当客户端断开连接并尝试再次连接到服务器时,它会立即断开连接。

但如果没有 SSL,它可以正常工作,没有任何问题。

客户代码:

public Channel initializeNettySocket()
{
    group = new NioEventLoopGroup();
    try
    {
        ClientAdapterInitializer clientAdapterInitializer = null;
        if (ServerSettings.isUseSSL())
        {
            //              SSLEngine engine = SSLContextFactory.getClientContext().createSSLEngine();
            SSLEngine engine = SSLContext.getDefault().createSSLEngine(host,port);
            engine.setUseClientMode(true);
            clientAdapterInitializer = new ClientAdapterInitializer(engine);
        }
        else
        {
            clientAdapterInitializer = new ClientAdapterInitializer();
        }

        Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(clientAdapterInitializer);

        channel = bootstrap.connect(host,port).sync().channel();
        Thread.sleep(3000);

        setChannel(channel);
    }
    catch (Exception e)
    {
        System.out.println(e.getMessage());
        e.printStackTrace();
    }
    return channel;
}

  public class ClientAdapterInitializer extends ChannelInitializer<SocketChannel>

{

private SSLEngine sslCtx = null;

public ClientAdapterInitializer(SSLEngine sslCtx)
{
    this.sslCtx = sslCtx;
}

public ClientAdapterInitializer()
{
}

@Override
protected void initChannel(SocketChannel channel) throws Exception
{
    ChannelPipeline pipeline = channel.pipeline();

    if (ServerSettings.isUseSSL())
    {
        // Add SSL handler first to encrypt and decrypt everything.
        // In this example, we use a bogus certificate in the server side
        // and accept any invalid certificates in the client side.
        // You will need something more complicated to identify both
        // and server in the real world.
        //pipeline.addLast(sslCtx.newHandler(ch.alloc(), SecureChatClient.HOST, SecureChatClient.PORT));
        pipeline.addLast(new SslHandler(sslCtx));
    }
    pipeline.addLast("decoder", new StringDecoder());
    pipeline.addLast("encoder", new StringEncoder());
    pipeline.addLast("handler", new ClientAdapterHandler());

}

服务器端代码

public class ServerAdapterInitializer extends ChannelInitializer<SocketChannel>

{

private SSLEngine sslEngine;

public ServerAdapterInitializer(SSLEngine sslEngine)
{
    this.sslEngine = sslEngine;
}

public ServerAdapterInitializer()
{
}

@Override
protected void initChannel(SocketChannel channel) throws Exception
{
    ChannelPipeline pipeline = channel.pipeline();
    if (sslEngine != null)
    {
        pipeline.addLast(new SslHandler(sslEngine));
    }
    Listeners.getInstance().getAllListeners().size();
    RTReceiverAdapterHandler rtReceiverAdapterHandler = new RTReceiverAdapterHandler();
    pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 0, 10)); // add
                                                                            // with
                                                                            // name
    pipeline.addLast("decoder", new MyStringDecoder(rtReceiverAdapterHandler));
    pipeline.addLast("encoder", new StringEncoder());

    pipeline.addLast("handler", rtReceiverAdapterHandler);
}

}

public class RTReceiverAdapterHandler extends ChannelInboundHandlerAdapter
{
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception
{
    if (ServerSettings.isUseSSL())
    {
        // Once session is secured, send a greeting and register the channel
        // to the global channel
        // list so the channel received the messages from others.
        ctx.pipeline().get(SslHandler.class).handshakeFuture().addListener(new GenericFutureListener<Future<Channel>>()
        {
            @Override
            public void operationComplete(Future<Channel> future) throws Exception
            {
                ctx.writeAndFlush("Welcome!\n");
                ctx.writeAndFlush("Your session is protected by " + ctx.pipeline().get(SslHandler.class).engine().getSession().getCipherSuite()
                        + " cipher suite.\n");
                channels.add(ctx.channel());
            }
        });
    }
    else
    {
        super.channelActive(ctx);
    }
}

}

【问题讨论】:

  • 您可以尝试使用以下选项记录调试: System.setProperty("javax.net.debug", "ssl"); System.setProperty("ssl.debug", "true");
  • 好的,我试试这个
  • 我已启用有效的协议和密码。我遇到的问题已经消失了。但是现在,服务器一旦与客户端连接等待几秒钟并关闭连接,在客户端我得到异常--> nioEventLoopGroup-2-1, fatal error: 80: Inbound closed before received peer's close_notify: possible truncation attack?
  • 再更新一次,我可以使用 SSL 连接到服务器,但是当我尝试写入 (channel.writeAndFlush("something")) 时,它会关闭连接。
  • 如果您可以将您的代码放在 Gist 或 GitHub 上的其他位置,我可以尝试重现并提供帮助。

标签: sockets netty


【解决方案1】:

问题根本不在于代码。在我的应用程序之前,我们已经使用 SSL 配置了 nginx Web 服务器。 nginx 'ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;' 中的这个条目是不允许访问netty服务器的罪魁祸首。

我在ngnix中评论了上面的条目,我的问题得到了解决。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-02
    • 2018-02-20
    • 2018-02-09
    • 1970-01-01
    • 2019-06-06
    • 2012-06-10
    • 1970-01-01
    • 2013-03-28
    相关资源
    最近更新 更多