是否关闭SSL而不关闭底层套接字?

5lwkijsr  于 2022-12-04  发布在  其他
关注(0)|答案(2)|浏览(156)

如何在不关闭底层套接字的情况下正常关闭Java SSL会话?
场景是Java客户端连接到(非java)服务器,设置SSL并安全地发送凭据(用户名和密码)。服务器建立一个在这些凭据下运行的环境,在该环境中产生一个新进程,并将套接字句柄传递给它,但问题是这个新进程不能重用现有的SSL连接(并且不能使用SSL会话恢复)......因此,我们的想法是在产生此新进程之前关闭SSL,然后与新进程从头开始重新协商SSL会话。
问题是Java的SSLSocket'sclose()方法除了关闭SSL会话(通过发送close_notify警报)之外还关闭了套接字。似乎没有与OpenSSL的SSL_shutdown()函数等效的函数,该函数允许底层套接字保持打开。
我已经尝试了一些方法来解决这个问题:
1.第二次使用SSLSocket.startHandshake(),但会自动尝试恢复现有的缓存SSL会话(失败,因为派生的服务器进程不知道此会话),并且虽然有一种方法强制恢复SSL会话或停止尝试,但没有方法使所有缓存会话无效或禁用缓存会话。
1.使用SSLSocketFactory.createSocket()在现有套接字之上创建一个SSLSocket,并将autoClose设置为false。这并不能阻止close()方法关闭底层套接字,我怀疑autoClose参数只是在初始握手失败时阻止套接字关闭。
1.在现有套接字上创建一个SSLSocket(如上所述),然后创建第二个SSLSocket,用于与派生的进程(从新的SSLContext)进行SSL握手。这会失败,因为当服务器发送close_notify警报(在派生子进程之前)时,Java会关闭套接字。
我听说过SSLEngine,但我也读到过(尽管我目前还不清楚源代码),使用它编写一个正确的SSL over TCP/IP实现是一项非常痛苦的工作,而且当我所需要的只是一个SSLSocket版本(其close()不调用super.Close())时,这似乎有点大材小用。
然而,SSLSocket似乎什至没有覆盖close()(根据javadoc),因此我不确定它如何挂钩close()方法,因为似乎不支持在Socket上注册关闭侦听器。
公司政策规定不能使用第三方加密库,因此我不能求助于替代的SSL实现(如Bouncy Castle)来解决这个问题。
如果我们不能让当前的单套接字设计工作,另一种选择是重写客户端和服务器以使用2个单独的套接字(这在必须对抗拒绝服务和中间人攻击方面变得相当混乱,而这不正是SSL最初应该做的吗?)
我们非常欢迎就如何解决这一问题提出任何意见或想法。

qv7cva1a

qv7cva1a1#

这不会阻止close()方法关闭基础套接字
是的,根据文件.
并且我怀疑autoClose参数只会在初始握手失败时阻止套接字关闭。
不可以。它可以防止关闭底层套接字。如文档所示。
给我们看看代码。

von4xj4u

von4xj4u2#

您应该能够使用一个普通的底层套接字(您的#3),因为这是带有Clear Control Channel的FTP实现所做的。
请记住,您尝试执行的操作会使您在两个SSL会话之间遭受中间人攻击,除非您在这两个会话之间携带一些秘密来表明身份验证仍然有效。
1.使用网络恶意(阿普中毒?)成为客户端和服务器之间的代理。
1.双向转发数据包,直到身份验证完成和SSL会话结束。(任何SSL ALERT都会发出结束信号,我们不需要解密内容)。
1.关闭客户端的套接字,这样它将出错。
1.与服务器进行自己的SSL协商。
1.继续使用客户端的凭据进行操作。

相关问题