使用netty-all-5.0.0.Alpha2进行SSL处理失败,但正在使用netty-all-5.0.0.Alpha1

时间:2015-03-29 01:08:40

标签: java ssl netty

我有一个用netty构建的man-in-the-middle代理的宠物项目。最初我使用netty-all-5.0.0.Alpha1并设法构建SSL处理管道。但是,在升级到netty-all-5.0.0.Alpha2之后,相同的SSL处理失败。基本上,当它工作时,我可以配置浏览器使用代理并成功加载https页面。现在使用netty-all-5.0.0.Alpha2,浏览器似乎没有得到任何东西。

以下是我所拥有的SSL处理的详细信息。

// server bootstrap
serverBootstrap.group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline p = ch.pipeline();
                p
                        .addLast(SERVER_LOGGING_HANDLER, new LoggingHandler(SERVER_LOGGING_HANDLER))
                        .addLast(SERVER_HTTP_REQUEST_DECODER, new HttpRequestDecoder())
                        .addLast(SERVER_HTTP_RESPONSE_ENCODER, new HttpResponseEncoder())
                        .addLast(HTTP_CONTENT_AGGREGATOR, new HttpObjectAggregator(MAX_HTTP_CONTENT_LENGTH))
                        .addLast(SERVER_HANDLER, new ServerHandler(ch, portContextManager) );
            }
        });


// inside ServerHandler
private static final HttpResponse CONNECT_RESPONSE = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
        new HttpResponseStatus(200, "Connection established"));

public void channelRead(ChannelHandlerContext context, Object message) throws Exception {
    log.debug("server pipeline handlers: " + context.pipeline().names());

    if (message instanceof FullHttpRequest) {
        FullHttpRequest request = (FullHttpRequest) message;
        if (request.method() == HttpMethod.CONNECT) {
            context.write(CONNECT_RESPONSE);
            log.debug("responded CONNECT method with {}", CONNECT_RESPONSE);
            context.pipeline().remove(SERVER_HTTP_REQUEST_DECODER);
            context.pipeline().remove(SERVER_HTTP_RESPONSE_ENCODER);
            context.pipeline().addBefore(HTTP_CONTENT_AGGREGATOR, SERVER_SSL_HANDLER, createServerSslHandler());
            context.pipeline().addBefore(HTTP_CONTENT_AGGREGATOR, HTTP_SERVER_CODEC, new HttpServerCodec());
            return;
        }
        log.debug("Received HTTP request:\n{}", request);
        chain.processRequest(request);
    } else {
        throw new Exception("Only FullHttpRequest is supported");
    }
}

private SslHandler createServerSslHandler() {
    try {
        SSLContext context = SslContextFactory.createServerSslContext();
        SSLEngine engine = context.createSSLEngine();
        engine.setUseClientMode(false);
        return new SslHandler(engine);
    } catch (Exception e) {
        log.error("Failed to create SslHandler with exception:", e);
        return null;
    }
}

使用netty-all-5.0.0.Alpha2后,LoggingHandler中没有任何内容:

2015-03-28 17:46:39.206 [nioEventLoopGroup-1-0] DEBUG SERVER_LOGGING_HANDLER#debug(): [id: 0x1b8d61d1, /0:0:0:0:0:0:0:1:63483 => /0:0:0:0:0:0:0:1:7000] WRITE: 39B
         +-------------------------------------------------+
         |  0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 54 54 50 2f 31 2e 31 20 32 30 30 20 43 6f 6e |HTTP/1.1 200 Con|
|00000010| 6e 65 63 74 69 6f 6e 20 65 73 74 61 62 6c 69 73 |nection establis|
|00000020| 68 65 64 0d 0a 0d 0a                            |hed....         |
+--------+-------------------------------------------------+----------------+

那么,在SSL处理方面,从5.0.0.Alpha1到5.0.0.Alpha2的变化是什么?如何让SSL处理再次运行?

更新
我现在设法让它再次运作。我唯一的更改是在回复初始writeAndFlush()请求时使用write()而不是CONNECT。也就是说,现在我有:

context.writeAndFlush(CONNECT_RESPONSE);

但是,我仍然想了解原因。让我感到困惑的另一件事是我必须删除最初的http编解码器,如

        context.pipeline().remove(SERVER_HTTP_REQUEST_DECODER);
        context.pipeline().remove(SERVER_HTTP_RESPONSE_ENCODER);

并添加一组新的编解码器以使SSL处理正常工作。有人可以解释原因吗?

1 个答案:

答案 0 :(得分:1)

在Netty 4中,write()操作仅将写请求放入每个通道队列。实际上是flush()操作告诉Netty将每个通道队列中的写请求写入套接字。

在旧版本的Netty 4中,SslHandler有一个错误,它会自动刷新每个写入请求,并且最近已修复。可能你的旧代码不再起作用了。 (我们的错误修复已经揭示了代码中隐藏的错误。)