在连接开始时使用SSL和Netty,然后禁用它

时间:2012-11-27 06:50:15

标签: multithreading ssl netty

我正在编写一个服务器应用程序及其客户端副本,它们都使用Netty作为网络层。我发现自己面临着从客户端向服务器发送密码的典型安全问题,因此我认为SSL是最安全的方式。

我知道securechat示例,并将使用它来相应地修改我的管道。但是,我还希望在密码传输后禁用SSL并确认在服务器端保存一些宝贵的CPU周期,这可能会使许多其他客户端忙。 ChannelPipeline文档指出:

  

“一旦连接,通道和管道之间的耦合是永久性的;通道不能将另一个管道连接到它,也不能将当前管道从它上拆下。”

然后,我们的想法是不动态地更改管道,这是禁止的,但以某种方式告诉管道中的 SslHandler 它应该在某个时刻停止加密消息。我正在考虑创建一个继承自 SslHandler 的类,重写其 handleDownstream 函数,以便在通信中的某些点之后调用 context.sendDownstream(evt)

问题1 :这是一个坏主意,也就是说,在某些时候禁用SSL?

要允许管道中的块(比如 Decoder )告诉另一个块(比如说 SslHandler )它应该从现在开始改变它的行为,我想我可以在我的 ChannelPipelineFactory getPipeline()中创建一个 AtomicBoolean ,并将其传递给 Decoder的构造函数 SslHandler

问题2 :这是一个坏主意,也就是说,在管道块之间共享状态?我担心我可能搞砸了Netty的多线程:是一个管道工作在一条消息上的块,一次一个?即:在拉下一条消息之前,第一个块是否等待完成最后一个块?

修改

哦,我的不好,这是我多次访问过的ChannelPipeline页面并引用了这个问题:

  

“可以随时添加或删除ChannelHandler,因为ChannelPipeline是线程安全的。例如,您可以在敏感信息即将交换时插入SslHandler,并在交换后将其删除。”

因此,这回答了关于在运行中修改管道的内容而不是管道引用本身的问题2。

3 个答案:

答案 0 :(得分:3)

我不确定一旦建立就关闭SSL的功效,但我认为你误解了管道的可变性。一旦给定的通道与管道相关联,该关联就是不可变的。但是,可以安全地修改管道中的处理程序。也就是说,您可以根据协议的要求添加和删除处理程序。因此,您应该能够在SSL处理程序达到其目的后删除它。

答案 1 :(得分:2)

您可以使用SslHandler从管道中删除ChannelPipeline.remove(..),然后将您的连接转为明文。如果它不起作用,请提交一个错误 - 我们实际上没有在生产中尝试过这个场景: - )

答案 2 :(得分:1)

我不确定Netty,但原则上,你确实可以在同一个TCP连接上继续使用普通流量。有一些缺点:

  • 仅保证身份验证。 MITM可以执行除用户预期之外的动作。 (这类似于在某种程度上使用HTTP摘要:凭据受到保护,但请求/响应实体不受保护。)

  • 从实施的角度来看,要做到这一点很棘手。 TLS specification说:

      

    如果使用TLS的应用程序协议提供了任何数据   在TLS连接之后传输底层传输   关闭后,TLS实施必须收到响应   在向应用程序层指示之前发出close_notify警报   TLS连接已经结束。

    这意味着您将继续以某种方式同步您的流以等待close_notify响应,然后继续您的普通流量。 SSLEngine编程模型相当复杂,您可能会发现Netty API不需要处理这种情况。

虽然想要节省几个CPU周期可能有意义,但大多数SSL / TLS开销都在握手中,无论如何你都要做。用于实际数据加密的对称加密操作要便宜得多。 (您应该尝试衡量这种开销,看看它是否确实存在问题。)