Play Framework 中的 SSL 导致“常规 SSLEngine 问题”。 (nginx)
Posted
技术标签:
【中文标题】Play Framework 中的 SSL 导致“常规 SSLEngine 问题”。 (nginx)【英文标题】:SSL in Play Framework causes 'General SSLEngine prob.' (nginx) 【发布时间】:2014-10-09 00:25:29 【问题描述】:我的服务器结构由两台服务器组成:一台是主服务器,其中包含内容,另一台是运行 Play 的 Scala 服务器,进行用户管理,包括社交登录(fb、tw、g+)。两台服务器都使用相同的通配符 SSL 证书。
我最近将主服务器从 Apache 切换到 nginx,由于某种原因,Scala 服务器抱怨 SSL 不匹配(这在 Apache 之前从未出现过问题)。
当我尝试登录时,我从 Play 收到以下错误:
[error] s.c.ProviderController - Unable to log user in. An exception was thrown
java.net.ConnectException: General SSLEngine problem to https://www.example.com/login/corsValid
at com.ning.http.client.providers.netty.NettyConnectListener.operationComplete(NettyConnectListener.java:103) ~[async-http-client.jar:na]
at org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:427) ~[netty.jar:na]
at org.jboss.netty.channel.DefaultChannelFuture.notifyListeners(DefaultChannelFuture.java:413) ~[netty.jar:na]
at org.jboss.netty.channel.DefaultChannelFuture.setFailure(DefaultChannelFuture.java:380) ~[netty.jar:na]
at org.jboss.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:1417) ~[netty.jar:na]
at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1293) ~[netty.jar:na]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1290) ~[na:1.7.0_51]
at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:513) ~[na:1.7.0_51]
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:793) ~[na:1.7.0_51]
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:761) ~[na:1.7.0_51]
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624) ~[na:1.7.0_51]
at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1225) ~[netty.jar:na]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[na:1.7.0_51]
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1694) ~[na:1.7.0_51]
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:278) ~[na:1.7.0_51]
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270) ~[na:1.7.0_51]
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1341) ~[na:1.7.0_51]
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153) ~[na:1.7.0_51]
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385) ~[na:1.7.0_51]
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) ~[na:1.7.0_51]
at sun.security.validator.Validator.validate(Validator.java:260) ~[na:1.7.0_51]
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326) ~[na:1.7.0_51]
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:283) ~[na:1.7.0_51]
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:138) ~[na:1.7.0_51]
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196) ~[na:1.7.0_51]
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268) ~[na:1.7.0_51]
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380) ~[na:1.7.0_51]
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) ~[na:1.7.0_51]
at sun.security.validator.Validator.validate(Validator.java:260) ~[na:1.7.0_51]
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326) ~[na:1.7.0_51]
我追查了问题,发现application.conf
需要为正在使用的 SSL 证书提供正确的参数。我创建了一个 JKS 和 P12 证书并将其包含在 conf 文件中,但我仍然收到此错误。 (可能是走错路了?也试过了……)
ws.ssl
trustManager =
stores = [
path: "ssl.jks"
]
但是,当我添加 ws.acceptAnyCertificate=true
时,一切都很好,但这显然是一个安全漏洞,我不想做任何事情。
为什么在 Play 中安装 SSL 证书如此痛苦?
谢谢
【问题讨论】:
【参考方案1】:我认为 Play 主要是一个应用程序框架,而不是 Web 服务器。
我们的播放应用程序始终与 Nginx 网络服务器(在 DMZ 中)进行不安全的通信,SSL/TLS 通信与 Nginx 终止。通过这种设计,如果您的 Play 应用是无状态的,您可以进行负载平衡。
然后,如果您愿意,将自定义 http 标头中的所有内容从 Nginx 转发到后端(例如客户端认证)以进行验证。
proxy_set_header APP-Cert-Verified $ssl_client_verify;
proxy_set_header APP-Client-Cert $ssl_client_cert;
proxy_set_header APP-Client-Cert-DN $ssl_client_s_dn;
您也可以在官方文档中找到它: https://www.playframework.com/documentation/2.5.x/HTTPServer#Set-up-with-nginx.
奖励:如果证书过期,您可以更轻松地在 nginx 中更改证书,而不是重新启动您的 Play 应用。
【讨论】:
以上是关于Play Framework 中的 SSL 导致“常规 SSLEngine 问题”。 (nginx)的主要内容,如果未能解决你的问题,请参考以下文章
测试期间可以在 Play Framework 中启用 HTTPS 侦听吗?
由于构建或路由导致 Play Framework 2.4 编译错误
将 SORM 与 Play Framework 一起使用会导致引发反射异常