与远程服务器进行 SSL 握手期间出错
Posted
技术标签:
【中文标题】与远程服务器进行 SSL 握手期间出错【英文标题】:Error during SSL Handshake with remote server 【发布时间】:2013-09-23 05:27:46 【问题描述】:我有Apache2
(在 443 上收听)和一个在 Ubuntu
上运行的网络应用程序 Tomcat7
(在 8443 上收听)。
我将 apache2 设置为反向代理,以便通过端口 443 而不是 8443 访问 Web 应用程序。此外,我不仅需要在浏览器和 apache2 之间进行 SSL 通信,还需要在 apache2 和 tomcat7 之间进行 SSL 通信,因此我在两者上都设置了 SSL apache2和tomcat7。 如果我尝试通过直接联系 tomcat7 来访问 Web 应用程序,一切都很好。 问题是当我尝试通过apache2(反向代理)访问tomcat的web应用时,在浏览器上出现错误:
Proxy Error
The proxy server could not handle the request GET /web_app.
Reason: Error during SSL Handshake with remote server
【问题讨论】:
Apache 不验证您在 tomcat 上安装的证书。它是自签名证书吗?还是由内部 CA 制作? 使用以下命令自签名:openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt serverfault.com/questions/356678/… 我想这就是你想要的: SSLProxyVerify none SSLProxyCheckPeerCN off 最好将SSLProxyCACertificateFile
设置为您的私有 CA 证书,而不是仅仅关闭验证。
如this blog 中所述,您可以关闭 SSL 检查。
【参考方案1】:
MK 的评论为我指明了正确的方向。
对于 Apache 2.4 及更高版本,有不同的默认值和新指令。
我正在运行 Apache 2.4.6,我必须添加以下指令才能使其正常工作:
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
【讨论】:
所以这会关闭保护,但只要流量是本地的(即127.0.0.1:8443),问题应该不大,对吧? 嗯,它不会关闭保护,因为涉及到加密。流量仍然是加密的。这只是禁用了对证书的检查,以确保它是由受信任的权威机构提供的。因此,如果您信任服务器,则应该没有问题。但是,是的,对于本地交通,我认为你也很好。 感谢 mydoghasworms。您的指令适用于服务器版本:Apache/2.4.6。如果有人需要知道 httpd 的版本,请使用:httpd -V 我刚刚在 Apache 2.4.29 上遇到了 AH01097 错误,所以有些类似于原始问题。我将以上所有内容添加到我的/etc/apache2/apache2.conf
文件中,并通过它们来查看哪些内容有所不同。就我而言,SSLProxyCheckPeerExpire off
是握手最终成功的原因。
这帮助我设置了我的 HTTP 到 HTTPS 映射反向代理。请在下面的答案中参考我的详细说明,因为 cmets 有字符限制。【参考方案2】:
我在 docker、反向代理和 Web 服务器上设置了 2 台服务器。 一年后,我的所有网站突然开始发生此错误。 之前设置时,我在网络服务器上生成了一个自签名证书。
所以,我不得不再次生成 SSL 证书,它才开始工作......
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ssl.key -out ssl.crt
【讨论】:
【参考方案3】:遇到了和 OP 一样的问题:
通过 SOAP UI 直接访问时,Tomcat 返回响应 没有加载 html 文件 使用上一个答案提到的 Apache 属性时,出现网页但 AngularJS 无法获得 HTTP 响应Tomcat SSL 证书已过期,而浏览器显示它是安全的 - Apache 证书还远未过期。更新 Tomcat KeyStore 文件解决了这个问题。
【讨论】:
【参考方案4】:在远程 OEL (Oracle Enterprise Linux) 7.8 服务器上,我有一个使用 HTTPS/8009 运行的后端 Web 应用程序。作为第三方应用,我没有选择禁用 SSL 或更改端口。
由于我需要从本地计算机的浏览器访问 Web 应用程序,我想到了使用 Apache httpd 设置反向代理(HTTP 到 HTTPS 映射)。现在我可以通过以下 URL 从本地浏览器访问网络应用程序:
http://10.157.146.97:1234/
仅供参考,在 Linux 机器中运行的 CURL 命令如下:
curl http://10.157.146.97:1234/
curl -k https://localhost:8009/
这是我的反向代理设置:
/etc/httpd/conf/httpd.conf
Listen 1234
<VirtualHost *:1234>
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPreserveHost On
ProxyPass / https://localhost:8009/
ProxyPassReverse / https://localhost:8009/
</VirtualHost>
在一个方面我很挣扎,早些时候我尝试在 ProxyPass/ProxyPassReverse 中使用 url 模式(/sample),但这导致 css/js 文件出现 HTTP 404(未找到),因为 web 应用程序的欢迎页面包含间接 css/ js 路径(下面的示例代码)。所以用 (/) 替换 url 模式 (/sample) 也解决了这个问题。
previous Not working config:
ProxyPass /sample https://localhost:8009/
ProxyPassReverse /sample https://localhost:8009/
<script defer src="abc.js"></script><link href="xyz.css" rel="stylesheet"></head>
【讨论】:
【参考方案5】:请注意,当您的系统禁用 TLSv1 时,也可能会发生该错误。例如,Ubuntu 20.x 默认禁用 TLSv1.0。例如,如果你有这样的事情:
Apache 2.4.41 on Ubutntu20 (proxy) --[https]--> old Apache serving TLS v1.0
SSLProxyVerify
等不会帮助你。
您需要做的是在openssl.conf
中启用 TLS 1.0。至少在您可以更新旧服务器之前 ?...
在 Ubuntu 上启用旧 TLS
所以在 Ubuntu 20.04.3 TLS 中有效启用 TLSv1 更改 /etc/ssl/openssl.cnf
。在文件顶部(任何部分之前)添加:
# Added to enable TLS1.0
openssl_conf = default_conf
在文件的最后
##
# Added to enable TLS1.0
[default_conf]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
CipherString = DEFAULT@SECLEVEL=1
##
注释显然不是必需的 ?,但在您想再次禁用 TLS1 时会有所帮助。
重启/重启后一切正常。
请注意,这是一个全局(系统范围)更改。所以它并不理想,但它确实有效。另见:more notes about Ubuntu and default TLS versions。
【讨论】:
您的解决方案存在几个问题:1. 您没有更改协议设置,但密码套件列表(MinProtocol
和 MaxProtocol
更改了协议),2. 您是使用 OpenSSL 更改所有软件的默认配置,而不仅仅是代理连接的设置, 3. 大多数软件(包括 Apache2)总是覆盖这些默认设置。对于 Apache2,请参阅 SSLProxyProtocol
指令。
好吧,当我从 Ubuntu 18 升级到 20 时,它开箱即用。而且我不必在我的 Apache conf 中更改 anything。而且curl
也开始工作(在此更改之前,它报告了“不支持的协议”)。所以它确实改变了支持的协议versions。但是,是的,您说得对,这种变化是全球性的。
我检查了,我有代理协议的默认设置,所以 SSLProxyProtocol all -SSLv3
包括 TLS1.0。并且仍然无法从 Ubuntu 20 连接到 tls1 服务器。
我错误地认为 Ubuntu 和 Debian 的 openssl
软件包是同步的。 Debian 选择 add a MinProtocol
default 到 openssl.cnf
,而 Ubuntu 选择了更激进的解决方案,并将最低版本 1.2 硬编码到 security level 2。【参考方案6】:
这是我对这个主题的变体,灵感来自this Git gist。服务器是一个带有内部自签名 SSL 证书的 Docker 容器,可通过https://localhost:8443
访问。代理到server.example.org:443
。相关配置详情:
<VirtualHost AAA.BBB.CCC.DDD:443>
ServerName server.example.org
ErrorLog $APACHE_LOG_DIR/error.log
CustomLog $APACHE_LOG_DIR/access.log combined
# These settings are definitely needed
SSLEngine On
SSLProxyEngine On
ProxyRequests Off
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
# These may not be needed, depending on proxied application
ProxyPreserveHost on
RequestHeader set X-Forwarded-Proto https
ProxyPass "/" "https://localhost:8443/"
RewriteEngine on
RewriteCond %HTTP:Upgrade websocket [NC]
RewriteCond %HTTP:Connection upgrade [NC]
RewriteRule ^/?(.*) "wss://localhost:8443/$1" [P,L]
ProxyPassReverse "/" "https://localhost:8443/"
</VirtualHost>
SSLEngine On
和 RequestHeader...
之间的部分是我通过谷歌搜索和反复试验拼凑而成的。也许其中一些设置是不需要的,YMMV。
注意:需要 RewriteRule
和 "wss"
,因为服务器使用安全 websocket。
平台:Ubuntu 20.04.3 LTS、Apache 2.4.41。
【讨论】:
以上是关于与远程服务器进行 SSL 握手期间出错的主要内容,如果未能解决你的问题,请参考以下文章
与服务器成功建立连接,但在登录前握手期间发生错误。 (提供者:SSL 提供者,错误:0
已成功与服务器建立连接,但是在登录前的握手期间发生错误。 (provider: SSL Provider, error: 0 - 等待的
javax.net.ssl.SSLHandshakeException:在 jdk 6 中握手期间远程主机关闭连接