mongo no subject alternative dns name matching
1 mongo相关的参数
--tlsAllowConnectionsWithoutCertificates 允许客户端连接而不提供证书
--tlsAllowInvalidHostnames 允许服务器证书提供不匹配的主机名
--tlsAllowInvalidCertificates 允许连接到证书无效的服务器
首先,我们需要理解 CA 证书的存储和管理机制。在 JDK 中,存在多个默 认的 CA 证书库,它们分别位于不同的位置。这些位置包括:
1. 应用程序级别的证书库:位于 Java 安装目录的 `jre/lib/security/cacerts`文件中。这是 JDK 默认使用的系统级别证书库, 其中存储了大量的受信任的 CA 证书。
2. 用户级别的证书库:位于用户的个人目录下的`.keystore`文件中。这个文件是一个二进制文件,存储了个人用户导入的或自签名的证书。
另外,我们可以通过配置`javax.net.ssl.trustStore`系统属性来指定其他的 证书库路径。例如,我们可以使用以下命令行选项来指定自定义的证书库 路径:
java -Djavax.net.ssl.trustStore=/path/to/custom/truststore
默认情况下,JDK 会在运行时加载上述证书库,并使用其中的 CA 证书进 行身份验证。如果需要,我们可以在程序中动态加载和管理这些证书库。
接下来,让我们看一下如何在 Java 中通过代码来获取和使用 CA 证书的路 径。
java import java.security.KeyStore; import java.security.cert.Certificate;
public class Main {
public static void main(String[] args) throws Exception {
获取默认的系统级别证书库
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
加载证书库 遍历证书库中的 CA 证书
for (String alias : keyStore.aliases()) {
Certificate cert = keyStore.getCertificate(alias);
打印证书的主题
System.out.println(cert.getSubjectDN());
}
获取用户级别的证书库
KeyStore userKeyStore = KeyStore.getInstance("JKS");
char[] password = "password".toCharArray(); 证书库密码
userKeyStore.load(new FileInputStream("/path/to/user/keystore.jks"), password);
加载证 书库 遍历证书库中的 CA 证书
for (String alias : userKeyStore.aliases()) {
Certificate cert = userKeyStore.getCertificate(alias);
打印证书的主题 System.out.println(cert.getSubjectDN());
} } }
上述代码中,我们首先使用`KeyStore.getDefaultType()`获取默认的系统 级别证书库类型。然后,使用`keyStore.load(null, null)`加载证书库。接着,我们遍历证书库中的所有 CA 证书,并使用`cert.getSubjectDN()`获 取证书的主题,并将其打印出来。
类似地,我们也可以通过`KeyStore.getInstance("JKS")`获取用户级别的证书库,并加载、遍历证书,以及获取主题。
--------------------------------------------------------
作者:n叶子1
链接:https://wenku.baidu.com/view/882334a8b7daa58da0116c175f0e7cd1842518d6.html
3 https://blog.51cto.com/u_16213689/8935443
java中的KeyStore这种文件可以分为两类:KeyStore和TrustStore。KeyStore保存私钥,在加解密、签名时使用。TrustStore保存可信任的证书,用于对被访问者进行认证。所以准确的来说cacerts文件其实应该属于TrustStore。
初始化SSLContext时会将TrustStore中的所有证书加载进来。TrustManagerFactoryImpl.getCacertsKeyStore()方法负责加载证书,首先查找JRE/lib/security/cacerts文件。如果都不存在,则使用空的TrustStore,这样的话不会有服务器的CA证书被校验通过。
初始化后,客户端会与服务器端建立连接,然后进入Handshake过程,当拿到服务器端的CA证书时,会调用X509TrustManager. checkServerTrusted(…)方法,
a).校验域名/IP
校验访问地址中的域名/IP(要么域名,要么IP)是否与服务器证书包含的一致,使用到HostnameChecker. match方法进行。
如果访问使用的是域名,但服务器CA证书中没有包含域名,则抛出错误:
No subject alternative DNS name matching localhost found //其中localhost表示域名。
如果访问使用的是IP,但服务器CA证书中没有IP,则抛出错误:
No subject alternative names present
如果域名不匹配抛出错误:
No name matching localhost found //其中localhost表示域名。
如果IP不匹配,则抛出错误:
No subject alternative names matching IP address 127.0.0.1 found //其中127.0.0.1表示ip。
b). 服务器证书是否可信
通过加载的TrustStore证书来校验服务器的证书是否由信任的证书机构颁发,使用到方法PKIXValidator.engineValidate()。该校验过程如果失败,则抛出类似如下错误:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
HostnameVerifier和SSLSocketFactory。这两个类是实现HTTPS请求的核心,通过配置这两个类可以影响SSL层校验域名/IP和服务器证书校验的过程。可以通过HttpsURLConnection.SetDefaultSSLSocketFactory和HttpsURLConnection.SetDefaultHostnameVerifier来设置
而在HTTPS层我们同样有HostnameVerifier来校验hostname,为什么呢?其实二者之间是合作关系,HTTPS层的会影响SSL/TLS层的逻辑,他们的关系可以通过如下表格来表示:
HTTPS与SSL层Hostname校验器关系
EIA algorithm表示SSL/TLS层面的校验,SSL层面可以通过如下方法进行设置:
SSLParameters.setEndpointIdentificationAlgorithm(String)
可设置三个值null,HTTPS和LDAP/其他。
HNV表示HTTPS层面的HostnameVerifier,HNV可以通过方法HttpsURLConnection.setDefaultHostnameVerifier(obj)进行设置,如果不设置则表中的值为defualt,如果设置了,则值为non-default。defualt的实现类为DefaultHostnameVerifier,该类为HttpsURLConnectionImpl的静态内部类。
4
关于Netty和io.netty.handler.ssl.SslContext
的一个小问题
在Tomcat和org.apache.http.ssl.SSLContexts
中,我们可以执行以下操作:
.loadKeyMaterial(someKeystorePropertlyInitialized)
.loadTrustMaterial(someTruststorePropertlyInitialized)
HttpClient = HttpClients.custom() .setSSLContext(SSLContexts.custom() SSLContexts.custom .build()) .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .build();
(欣赏我们是否可以保留字体,而不是在代码块中包装)
例如,这可以修复由: java.security.cert.CertificateException: No subject可供选择的DNS名称匹配xxx找到的问题(这个问题不是关于NoopHostnameVerifier.INSTANCE
是否是修复这个问题的正确方法)。
我的问题是,在Netty of .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
,没有 .trustManager(InsecureTrustManagerFactory.INSTANCE)
的中,什么是等价的,因为我有一个真正的信任商店,我只想跳过主机名,而不是所有的东西。
实际上,默认情况下,Netty关闭了主机名验证--参见本期。看起来你正在使用的库(反应堆网络)可能会打开它。在反应堆网络的github上似乎有一个指向解决方案的类似问题,但是提供的代码片段似乎做得比必要的更多。本质上,您只需要从SSLEngine
访问SslHandler
,并确保端点识别算法为空/空:
HttpClient.create().secure(
ssl -> ssl.sslContext(sslContext)
.handlerConfigurator(handler-> {
SSLEngine engine = handler.engine();
SSLParameters params = new SSLParameters();
// ... set other SSL
params params.setEndpointIdentificationAlgorithm(null);
}) );
5 java代码忽略https证书 no subject alternative names present
https://blog.csdn.net/hanlinhe111/article/details/139113095
自己生成的证书,由于没有设置域名,会到这这个问题
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present
解决办法,强制信任即可
HttpsURLConnection.setDefaultHostnameVerifier(new NullHostNameVerifier());
public static class NullHostNameVerifier implements HostnameVerifier {
/*
* (non-Javadoc)
*
* @see javax.net.ssl.HostnameVerifier#verify(java.lang.String,
* javax.net.ssl.SSLSession)
*/
@Override
public boolean verify(String arg0, SSLSession arg1) {
// TODO Auto-generated method stub
return true;
}
}
https://blog.51cto.com/oktokeep/12279512
HttpsURLConnection.setDefaultHostnameVerifier(new HttpsUtils().new NullHostNameVerifier());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
-----------------------------------
static TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
// TODO Auto-generated method stub
}
@Override
public X509Certificate[] getAcceptedIssuers() {
// TODO Auto-generated method stub
return null;
}
} };
public class NullHostNameVerifier implements HostnameVerifier {
/*
* (non-Javadoc)
*
* @see javax.net.ssl.HostnameVerifier#verify(java.lang.String,
* javax.net.ssl.SSLSession)
*/
@Override
public boolean verify(String arg0, SSLSession arg1) {
// TODO Auto-generated method stub
return true;
}
}
6 结论:
expection:
提出问题,证书里是哪个host
good for both with DNS:
SAN in server's cert
(btw: #1 是CA证书)
参考:https://blog.csdn.net/promise524/article/details/142471388
查看服务器端的证书时,可以通过导入服务器的公钥证书文件,或者直接从服务器上抓取并查看证书。常见以下几种方法:
方法 1:直接从服务器上抓取并查看证书
可以通过 keytool 来连接远程服务器的端口,并查看其 SSL/TLS 证书:
keytool -printcert -rfc -sslserver <hostname>:<port>
1
<hostname>:服务器的主机名或 IP 地址。
<port>:服务器使用 SSL/TLS 的端口号,通常是 443(HTTPS)或其他端口。
假设需要查看 www.test.com 网站的证书:
keytool -printcert -rfc -sslserver www.test.com:443
1
运行此命令后,将看到服务器的证书详细信息,包括证书链中的所有证书、颁发者信息、公钥、有效期等。
方法 2:通过 openssl 抓取并查看证书
如果不想使用 keytool,可以使用 openssl 工具来抓取服务器端的证书,然后通过 keytool 查看:
使用 openssl 抓取服务器证书:
openssl s_client -connect <hostname>:<port> -showcerts
1
这将输出服务器的证书链,包含服务器证书及其链中其他证书。
保存证书:
将证书保存到一个文件(例如 server.crt)中。
使用 keytool 查看证书:
keytool -printcert -file server.crt
1
方法 3:下载并查看证书文件
有时,可能已经从服务器上下载了证书文件(如 .cer 或 .crt 文件),可以直接使用 keytool 查看:
keytool -printcert -file <cert-file-path>
1
keytool -printcert -file server.cer
1
证书信息解析
在输出结果中,你可以看到以下信息:
Owner:证书的拥有者信息(通常包括 CN、OU、O、L、ST、C 等)。
Issuer:证书的颁发者信息。
Serial number:证书的序列号。
Valid from / to:证书的有效期。
Signature algorithm:签名算法(如 SHA256withRSA)。
Public key:公钥的详细信息。
通过这些方法,可以方便地查看服务器的证书信息,并检查证书是否有效,或进一步用于信任链验证等操作。