Java 升级 8 到 11 导致 LDAPS 连接出现问题(连接或出站已关闭)
java 升级后出现此问题:
This issue seen after java upgrade:
- 具有 DNS 别名的 LDAP 无法与 java 11.0.2 连接,因为它可以正常工作使用 java 8
DNS 别名如下,保持不变,这里没有变化,唯一的变化是 java 升级 8 到 11:
DNS alias as below this remain same no change here only change is java upgrade 8 to 11:
$ nslookup ad1.XXXXX.zz
$ nslookup ad1.XXXXX.zz
Server: 10.222.249.209
Address: 10.222.249.209#53
Name: ad1.XXXXX.zz
Address: 10.222.249.205
Name: ad1.XXXXX.zz
Address: 10.222.249.204
Name: ad1.XXXXX.zz
Address: 10.222.249.210
- LDAP 直接 IP 与 java 11.0.2 没有问题:
$ nslookup qdegsf.XXXXX.zz
$ nslookup qdegsf.XXXXX.zz
Server: 10.222.249.209
Address: 10.222.249.209#53
Name: qdegsf.XXXXX.zz
Address: 10.222.249.210
工艺参数:
/opt/3rdparty/jdk_installed/jdk-11.0.2/bin/java -Dsserver -Djdk.serialFilter=* -Dfile.encoding=UTF8 -Djavax.net.ssl.trustStore=/opt/3rdparty/tomcat/conf/svrtrust -Djavax.net.ssl.trustStorePassword=XXXX -Djavax.net.ssl.keyStore=/opt/3rdparty/tomcat/conf/svrkeystore.jks
/opt/3rdparty/jdk_installed/jdk-11.0.2/bin/java -Dsserver -Djdk.serialFilter=* -Dfile.encoding=UTF8 -Djavax.net.ssl.trustStore=/opt/3rdparty/tomcat/conf/svrtrust -Djavax.net.ssl.trustStorePassword=XXXX -Djavax.net.ssl.keyStore=/opt/3rdparty/tomcat/conf/svrkeystore.jks
以下是建立 ldap 连接时的问题跟踪
Below is the issue traces when ldap connection is made
java.lang.RuntimeException: connection to ldap server failed;url;ldaps://ad1.XXXXX.zz:636;authDN;sa_XXX@XXXXX.zz
javax.naming.CommunicationException: simple bind failed: ad1.XXXXX.zz:636 [Root exception is java.net.SocketException: Connection or outbound has closed]
java.net.SocketException: Connection or outbound has closed
Trace for the thrown exceptions:
java.lang.RuntimeException: connection to ldap server failed;url;ldaps://ad1.XXXXX.zz:636;authDN;sa_XXX@XXXXX.zz
at auth.ldap.LdapConnection.testConnection(LdapConnection.java:46)
Caused by: javax.naming.CommunicationException: simple bind failed: ad1.XXXXX.zz:636 [Root exception is java.net.SocketException: Connection or outbound has closed]
at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:219)
at java.naming/com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2795)
at java.naming/com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:320)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:730)
at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
at java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
at java.naming/javax.naming.InitialContext.<init>(InitialContext.java:208)
at java.naming/javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:101)
at auth.ldap.LdapConnection.testConnection(LdapConnection.java:41)
... 3 more
Caused by: java.net.SocketException: Connection or outbound has closed
at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:976)
at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:398)
at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:371)
at java.naming/com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:359)
at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:214)
... 15 more
javax.naming.CommunicationException: simple bind failed: ad1.XXXXX.zz:636 [Root exception is java.net.SocketException: Connection or outbound has closed]
at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:219)
at java.naming/com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2795)
at java.naming/com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:320)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:730)
at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
at java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
at java.naming/javax.naming.InitialContext.<init>(InitialContext.java:208)
at java.naming/javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:101)
at auth.ldap.LdapConnection.testConnection(LdapConnection.java:41)
Caused by: java.net.SocketException: Connection or outbound has closed
at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:976)
at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:398)
at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:371)
at java.naming/com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:359)
at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:214)
... 15 more
java.net.SocketException: Connection or outbound has closed
at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:976)
at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:142)
at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:398)
at java.naming/com.sun.jndi.ldap.Connection.writeRequest(Connection.java:371)
at java.naming/com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:359)
at java.naming/com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:214)
at java.naming/com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2795)
at java.naming/com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:320)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:192)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:210)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:153)
at java.naming/com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:83)
at java.naming/javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:730)
at java.naming/javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:305)
at java.naming/javax.naming.InitialContext.init(InitialContext.java:236)
at java.naming/javax.naming.InitialContext.<init>(InitialContext.java:208)
at java.naming/javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:101)
at nims.auth.ldap.LdapConnection.testConnection(LdapConnection.java:41)
at auth.LdapAuthenticationService.doTestConnection(LdapAuthenticationService.java:50)
> 更新时出现以下错误:
$ openssl s_client -connect ad1.XXXXX-ru.zz:636
$ openssl s_client -connect ad1.XXXXX-ru.zz:636
已连接(00000003)深度=0验证错误:num=20:无法获取本地颁发者证书验证返回:1深度=0验证错误:num=27:证书不受信任验证返回:1深度=0验证错误:num=21:无法验证第一个证书验证返回:1
CONNECTED(00000003) depth=0 verify error:num=20:unable to get local issuer certificate verify return:1 depth=0 verify error:num=27:certificate not trusted verify return:1 depth=0 verify error:num=21:unable to verify the first certificate verify return:1
证书链0 秒:i:/DC=zz/DC=XXXXX-ru/CN=XXXXX-ru-ROOT-CA
Certificate chain 0 s: i:/DC=zz/DC=XXXXX-ru/CN=XXXXX-ru-ROOT-CA
服务器证书-----开始证书-----MIIFfjCCBGagAwIBAgITLwAAAKgllUHEZUjzRwAAAAAAqDANBgkqhkiG9w0BA.......
Server certificate -----BEGIN CERTIFICATE----- MIIFfjCCBGagAwIBAgITLwAAAKgllUHEZUjzRwAAAAAAqDANBgkqhkiG9w0BA.................
APPpwNrloBJjZo2bJ7pqe4gXN-----结束证书-----
APpwNrloBJjZo2bJ7pqe4gXN -----END CERTIFICATE-----
主题=发行人=/DC=zz/DC=XXXXX-ru/CN=XXXXX-ru-ROOT-CA
subject= issuer=/DC=zz/DC=XXXXX-ru/CN=XXXXX-ru-ROOT-CA
未发送客户端证书 CA 名称服务器临时密钥:ECDH,prime256v1,256 位
No client certificate CA names sent Server Temp Key: ECDH, prime256v1, 256 bits
SSL 握手已读取 1980 字节并写入 441 字节
SSL handshake has read 1980 bytes and written 441 bytes
新,TLSv1/SSLv3,密码为 ECDHE-RSA-AES256-SHA384服务器公钥为 2048 位支持安全重新协商压缩:无扩展:无SSL-会话:协议:TLSv1.2密码:ECDHE-RSA-AES256-SHA384会话 ID:C51900006745E495E1C8CA132C0EDF901C3638DE9E5EEA506551E298E2374372会话 ID-ctx:万能钥匙:A8B4C4E2B01FE11822CE047D3B7D692EE1C001DA551DFE63FBC314737177BE7A285F79D6FF36B67D3E1AFF72C1402D2D键-Arg:无Krb5 主体:无PSK 身份:无PSK 身份提示:无开始时间:1574232095超时:300(秒)验证返回码:21(无法验证第一个证书)
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA384 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES256-SHA384 Session-ID: C51900006745E495E1C8CA132C0EDF901C3638DE9E5EEA506551E298E2374372 Session-ID-ctx: Master-Key: A8B4C4E2B01FE11822CE047D3B7D692EE1C001DA551DFE63FBC314737177BE7A285F79D6FF36B67D3E1AFF72C1402D2D Key-Arg : None Krb5 Principal: None PSK identity: None PSK identity hint: None Start Time: 1574232095 Timeout : 300 (sec) Verify return code: 21 (unable to verify the first certificate)
请提供建议.谢谢
推荐答案
写了一个测试脚本连接ldap(启用ssl日志)@jdk 11
wrote a test script to connect with ldap ( with ssl logs enable) @ jdk 11
/opt/soft/jdk_installed/jdk-11.0.2/bin/java -XX:+UseSerialGC -DLdapsConnect -Djavax.net.debug=all -Djavax.net.ssl.trustStore=/opt/soft/tomcat/conf/svrtrust -Djavax.net.ssl.trustStorePassword=hsqlIiza -Djavax.net.ssl.keyStore=/opt/soft/tomcat/conf/svrkeystore.jks -Djavax.net.ssl.keyStorePassword=hsqlIiza -classpath/tmp/LdapsConnect$*
/opt/soft/jdk_installed/jdk-11.0.2/bin/java -XX:+UseSerialGC -DLdapsConnect -Djavax.net.debug=all -Djavax.net.ssl.trustStore=/opt/soft/tomcat/conf/svrtrust -Djavax.net.ssl.trustStorePassword=hsqlIiza -Djavax.net.ssl.keyStore=/opt/soft/tomcat/conf/svrkeystore.jks -Djavax.net.ssl.keyStorePassword=hsqlIiza -classpath /tmp/ LdapsConnect $*
在 ssl 日志中发现以下错误javax.net.ssl|ERROR|1D|Thread-0|2020-01-22 10:55:21.632 CET|TransportContext.java:313|致命(CERTIFICATE_UNKNOWN):找不到与 ad1.xxxx.zz 匹配的主题备用 DNS 名称.
found that below error in ssl logs javax.net.ssl|ERROR|1D|Thread-0|2020-01-22 10:55:21.632 CET|TransportContext.java:313|Fatal (CERTIFICATE_UNKNOWN): No subject alternative DNS name matching ad1.xxxx.zz found.
结论/解决方案:Ldap 证书应修改为缺少 ad1.ngssm-ru.zz.由于 Java 8u181 在 ldap 支持方面进行了如下更改,在 Java 8u181 及更高版本之后不允许使用旧方式.
Conclusion/Solution : Ldap certificate should be modified to have ad1.ngssm-ru.zz which is missing. As Java 8u181 has changes as below in ldap support which does not allow old way after java version 8u181 and above.
Java 正在尝试确保连接配置中的主机名与远程 LDAPS TLS 服务器证书中的主机名匹配,并且证书中的这些主机名是有效的.安全连接的正确解决方案是让您的 LDAP 服务器管理员更正 ldap 服务器正在使用的 LDAP 证书,以便改进的端点识别算法起作用.这是为了保护我们.
Java is trying to make sure the host name in your connection configuration matches the host names in the remote LDAPS TLS server certificate and that those host names in the certificate are valid. The correct solution for a secure connection is to have your LDAP server administrators correct the LDAPs certificate the ldap server is using so that the improved endpoint identification algorithms work. This is for our protection.
https://www.oracle.com/technetwork/java/javase/8u181-relnotes-4479407.html变化核心库/javax.naming?改进 LDAP 支持已在 LDAPS 连接上启用端点识别.
https://www.oracle.com/technetwork/java/javase/8u181-relnotes-4479407.html Changes core-libs/javax.naming ? Improve LDAP support Endpoint identification has been enabled on LDAPS connections.
为了提高 LDAPS(基于 TLS 的安全 LDAP)连接的稳健性,已默认启用端点识别算法.
To improve the robustness of LDAPS (secure LDAP over TLS) connections, endpoint identification algorithms have been enabled by default.
请注意,在某些情况下,以前能够成功连接到 LDAPS 服务器的某些应用程序可能不再能够这样做.如果它们认为合适,此类应用程序可以使用新的系统属性禁用端点识别:com.sun.jndi.ldap.object.disableEndpointIdentification.
Note that there may be situations where some applications that were previously able to successfully connect to an LDAPS server may no longer be able to do so. Such applications may, if they deem appropriate, disable endpoint identification using a new system property: com.sun.jndi.ldap.object.disableEndpointIdentification.
定义此系统属性(或将其设置为 true)以禁用端点识别算法.
Define this system property (or set it to true) to disable endpoint identification algorithms.
相关文章