Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Java中实现SSL代理服务器以克服浏览器中的证书错误?_Java_Ssl_Https_Proxy - Fatal编程技术网

如何在Java中实现SSL代理服务器以克服浏览器中的证书错误?

如何在Java中实现SSL代理服务器以克服浏览器中的证书错误?,java,ssl,https,proxy,Java,Ssl,Https,Proxy,我正在尝试用Java实现一个SSL代理服务器,它不会在浏览器中引发证书错误。我知道我需要处理“连接”请求,进行SSL握手,因此需要创建服务器证书并将其存储在密钥库中,我将为SSL套接字初始化密钥库 但浏览器将始终必须验证返回的服务器证书,并在以下情况下抛出警告错误:; 1.CA证书不受信任,但这可以通过在浏览器中安装一次用于签署服务器证书的CA证书来解决。 2.证书的CN与所请求网站的主机名不匹配。 对于第二个问题,我使用BouncyCastle实现了一个证书生成线程,该线程使用被请求的主机名生

我正在尝试用Java实现一个SSL代理服务器,它不会在浏览器中引发证书错误。我知道我需要处理“连接”请求,进行SSL握手,因此需要创建服务器证书并将其存储在密钥库中,我将为SSL套接字初始化密钥库

但浏览器将始终必须验证返回的服务器证书,并在以下情况下抛出警告错误:; 1.CA证书不受信任,但这可以通过在浏览器中安装一次用于签署服务器证书的CA证书来解决。 2.证书的CN与所请求网站的主机名不匹配。 对于第二个问题,我使用BouncyCastle实现了一个证书生成线程,该线程使用被请求的主机名生成一个证书,该证书由上面的可信CA私钥签名。然后,我使用主机名作为密钥项的别名,将生成的服务器证书及其私钥添加到密钥库中。 现在是我似乎无法掌握的部分,如何根据请求的主机名使用不同的证书进行握手。 我已经看到很多关于keymanagers和sslcontext的建议,但这些建议似乎都无法根据请求的不同主机名动态更改用于sslhandshake的证书

很抱歉,这个问题非常冗长,我对这一切都不熟悉,所以请对我耐心一点


编辑:考虑实现一个keymanager并用它初始化sslcontext,然后创建serversocket,在创建serversocket时,没有请求主机名,那么,如何创建一个动态的keymanager,它不同于我所看到的fixedserveralias示例。

基本上,您必须记住目标主机名,并从
X509KeyManager返回一个适当的密钥库别名。选择ServerAlias()


对我来说,整件事听起来像是a级安全漏洞,不止一个方面。您无权在所谓的私人对话中进行调解,最终用户有权知道他认为正在与之交谈的服务器是否有错误或不受信任的证书。

您的代理服务器可能在一个IP地址上提供多个主机名。您最好的选择是生成一个具有多个主题备选名称(SAN)的证书,从您的IP地址提供服务的每个主机名对应一个证书


您不能对每个主机名使用单独的证书,因为您的代理服务器无法知道请求的主机名。这是因为浏览器首先转到DNS将主机名转换为IP地址,然后将请求直接发送到IP地址。事实上,从技术角度来看,使用单独的动态生成的证书执行此操作相当于“中间人”攻击,这正是主机名检查应该防止的攻击。

因为您可能通过普通套接字获得
连接
请求,之后,您试图将该套接字升级为
SSLSocket
(您确实可以使用它来升级)

由于您是通过将通过
CONNECT
获得的主机名放入其CN来动态生成新证书(顺便说一句,在SAN中会更好),您可以非常轻松地在内存中创建一个
密钥库
实例,并将该证书及其私钥放入其中。然后,从该实例初始化KeyManagerFactory,使用该KMF初始化一个新的
SSLContext
,从该
SSLContext
创建一个新的
SSLSocketFactory
,然后使用
SSLSocketFactory.createeSocket(Socket,…)
升级特定接受的套接字。您可以对每个接受的套接字执行所有这些操作,它们都是独立的


为所有套接字提供一个
KeyManager
SSLContext
意味着您需要在自己的
X509KeyManager
子类中实现一些自定义逻辑(实现自己的
chooseServerAlias()
),这似乎是不必要的复杂。

我理解您对整个过程中的安全漏洞的看法,稍后我会担心这个问题。因此,在使用我的KeyManager初始化SSLContext并使用SSLContext的SSLServerSocketFactory后,创建我的侦听器。我是否需要为不同的主机名重新初始化SSLContext一次又一次。我现在会担心。如果这不是你应该做的事情,你就不应该开始做。这是一个代理服务器,用于嗅探https请求的内容。你能解释一下这与这个答案有什么关系吗?实际上,代理服务器有一种方法知道请求的主机名,因为它是参数关于
CONNECT
方法。那么,也许我不理解这个问题。如果CONNECT方法是在未加密的HTTP中传递的,那么代理服务器为什么要担心SSL证书呢?似乎他希望此代理执行MITM“攻击”(但不是真正的攻击,因为客户端将拥有代理CA的CA证书)。因此,我创建了一个现有的SSLServerSocket,并将其与另一个使用动态SSLContext创建的SSL套接字覆盖,但在套接字关闭时,“布尔自动关闭”不会同时关闭基础套接字。当然,您通常确实希望自动关闭。为什么不呢?别忘了在服务器模式下设置新的
SSLSocket
setUseClientMode(false)
),但是,由于您正在使用
SSLSocketFactory
创建一个
SSLSocket
,而不是一个
SSLServerSocket
。我似乎无法这样做,我可能不得不涉足chooseServerAlias()选项。您有任何示例代码来说明您正在尝试的内容吗