这与
此问题相似,我已回答过它是不可能的:
你不能仅仅将SSL/TLS流量从Apache中转到Tomcat。要么你的SSL连接在Apache处结束,然后你应该反向代理流量到Tomcat(在这种情况下,在Httpd和Tomcat之间的SSL很少有用),要么让客户端直接连接Tomcat并让其处理SSL连接。
我承认这篇文章缺乏支持此说法的链接。我想我可能是错的(我从未见过这样的操作,但这并不严格意义上意味着它不存在...)。
正如您所知,您需要一个直接连接或完全中继的连接,用户代理和SSL终点之间(在这种情况下,您希望它是Tomcat)。这意味着Apache Httpd将无法查看URL:最多只会知道主机名(使用服务器名称指示时)。
在mod_proxy
文档中,唯一似乎不依赖URL的选项是AllowCONNECT
,这是用于HTTPS的正向代理服务器的选项。
即使在mod_proxy_balancer
的选项中,也希望在配置的某个点上提供路径。它的文档没有提到SSL/HTTPS("它为HTTP、FTP和AJP13协议提供负载平衡支持"),而mod_proxy
在提到CONNECT
时至少提到了SSL。
我建议有几个选项:
这个第二种选项需要更多的配置来处理客户端证书和Tomcat的安全限制。
如果您已经使用
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
配置了您的Web应用程序,则需要使Tomcat标记连接为安全连接,尽管它从其普通HTTP端口接收到这些连接。对于Tomcat 5,
这里有一篇文章(原文是法语,但自动翻译并不太糟糕),描述了如何实现一个阀门来设置
isSecure()
。(如果您不熟悉
阀门,它们类似于过滤器,但在Tomcat本身内部操作,在请求传播到Web应用程序之前进行操作。它们可以在Catalina中配置)我认为从Tomcat 5.5开始,
HTTP连接器secure
选项正是这样做的,而不需要您自己的阀门。如果使用
mod_proxy_ajp
或
mod_jk
,AJP连接器也有类似的选项。
如果使用AJP连接器,
mod_proxy_ajp
将转发证书链中的第一个证书,并在Tomcat中使其可用(通过正常请求属性)。您可能需要
SSLOptions +ExportCertData +StdEnvVars
。据我所知,
mod_jk
(虽然已被弃用)也可以转发客户端发送的整个证书链(使用
JkOptions +ForwardSSLCertChain
)。这在使用
代理证书时可能是必要的(如果没有直到终端实体证书的链,则代理证书毫无意义)。
如果您想使用
mod_proxy_http
,一个技巧是通过
HTTP头(mod_header
)传递证书,类似于
RequestHeader set X-ClientCert %{SSL_CLIENT_CERT}s
。我记不清确切的细节,但重要的是要确保清除此标头,以便它永远不会来自客户端浏览器(否则可能被伪造)。如果需要完整的链式证书,可以尝试
这个Httpd补丁尝试。这种方法可能需要额外的阀门/过滤器将标头转换为
javax.servlet.request.X509Certificate
(通过解析PEM块)。
还有几点可能会感兴趣:
- 如果我没记错的话,您需要明确下载 Httpd 和 配置它以使用这些文件。根据您使用的 Httpd 版本,您可能需要 重新启动它以重新加载 CRLs。
- 如果您正在使用重新协商来获取客户端证书,则据我所知,
CLIENT-CERT
指令不会使 Httpd 请求客户端证书(当直接使用 JSSE 连接器时,可以通过访问 SSLSession
的阀门来完成此操作)。您可能需要在 Httpd 中配置匹配的路径以请求客户端证书。
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
,这并不困扰我,并在代码中搜索和销毁isSecure()
,以及(d)使用mod_proxy_ajp
,这样证书就可以通过了,事实上我已经在做了。我可以处理配置HTTPD的HTTPS和证书等问题。 - user207421SSLVerifyClient none
,并在<Location /path/...>
元素中放置SSLVerifyClient optional/require
(但路径可能需要特定于 Web 应用程序的预期)。 - Brunomod_jk
+Jetty/AJP 会出现一些稳定性问题:AJP连接会突然断开,日志中没有任何信息(无论是Httpd还是Jetty)。让Jetty(即使是BIO)通过JSSE直接处理请求的结果更加稳定(当时我没有完全调查原因,您可能会得到更好的结果)。 - Bruno