mongo no subject alternative dns name matching

1 mongo相关的参数

--tlsAllowConnectionsWithoutCertificates               允许客户端连接而不提供证书
  --tlsAllowInvalidHostnames            允许服务器证书提供不匹配的主机名
  --tlsAllowInvalidCertificates         允许连接到证书无效的服务器
 
 
2 一个java对外请求究竟有多少truststore

首先,我们需要理解 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:公钥的详细信息。
通过这些方法,可以方便地查看服务器的证书信息,并检查证书是否有效,或进一步用于信任链验证等操作。

posted on 2024-11-22 19:29  silyvin  阅读(33)  评论(0编辑  收藏  举报