服务器为无效的 SNI 主机名提供证书
Server provides certificate for invalid SNI host name
我遇到了一个我不理解的 Java SNI SSL 行为。在 Java 中使用 SNI 时,我希望 Google 不会为无效主机名提供任何证书,但它会提供。
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("src/main/resources/empty.keystore"), "password".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keystore, "password".toCharArray());
KeyStore trustStore = KeyStore.getInstance("JKS");
// truststore contains single trusted certificate with serial number: 0x72a9296669b20ad60800000000320a0a
trustStore.load(new FileInputStream("src/main/resources/client-test-cn.truststore"), "password".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket();
SSLParameters sslParameters = socket.getSSLParameters();
sslParameters.setServerNames(Arrays.asList(new SNIHostName("microsoft.com")));
// Google provides certificate with serial number: 0x72a9296669b20ad60800000000320a0a
// CN=*.google.com,O=Google LLC,L=Mountain View,ST=California,C=US
// CN=GTS CA 1O1,O=Google Trust Services,C=US
// this works as this certificate is in the trust store
// handshake log: Extension server_name, server_name: [type=host_name (0), value=microsoft.com]
// ????? why does Google provide Google certificate for invalid hostname ?????
// sslParameters.setServerNames(Arrays.asList(new SNIHostName("google.com")));
// Google provides certificate with serial number: 0xcbfd0b2561656ea202000000005c675c
// this does NOT work as intentionally this certificate is missing from truststore
// handshake log: Extension server_name, server_name: [type=host_name (0), value=google.com]
sslParameters.setProtocols(new String[] {"TLSv1.2"});
socket.setSSLParameters(sslParameters);
socket.connect(new InetSocketAddress(InetAddress.getByName("google.com"), 443));
socket.addHandshakeCompletedListener(event -> System.out.println("----- HANDSHAKE DONE -----"));
socket.startHandshake();
为什么在通过 SNI 扩展请求无效主机名时 Google 根本不提供其证书?当没有匹配的主机名时,提供 random/default 证书是 SNI 的一部分吗?
Is it part of the SNI to provide random/default certificate when no matching host name?
SNI 不规定服务器的特定行为。它所提供的只是一种方式,服务器可以找出客户端想要访问的域。
服务器的行为非常不同:有些服务器完全忽略 SNI,因为它们只有一个配置和证书。如果没有给出 SNI 或不匹配,其他人有一些默认值。如果 SNI 给出的名称与特定配置不匹配,其余的通常会抛出某种错误。
我遇到了一个我不理解的 Java SNI SSL 行为。在 Java 中使用 SNI 时,我希望 Google 不会为无效主机名提供任何证书,但它会提供。
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(new FileInputStream("src/main/resources/empty.keystore"), "password".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keystore, "password".toCharArray());
KeyStore trustStore = KeyStore.getInstance("JKS");
// truststore contains single trusted certificate with serial number: 0x72a9296669b20ad60800000000320a0a
trustStore.load(new FileInputStream("src/main/resources/client-test-cn.truststore"), "password".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), null);
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket();
SSLParameters sslParameters = socket.getSSLParameters();
sslParameters.setServerNames(Arrays.asList(new SNIHostName("microsoft.com")));
// Google provides certificate with serial number: 0x72a9296669b20ad60800000000320a0a
// CN=*.google.com,O=Google LLC,L=Mountain View,ST=California,C=US
// CN=GTS CA 1O1,O=Google Trust Services,C=US
// this works as this certificate is in the trust store
// handshake log: Extension server_name, server_name: [type=host_name (0), value=microsoft.com]
// ????? why does Google provide Google certificate for invalid hostname ?????
// sslParameters.setServerNames(Arrays.asList(new SNIHostName("google.com")));
// Google provides certificate with serial number: 0xcbfd0b2561656ea202000000005c675c
// this does NOT work as intentionally this certificate is missing from truststore
// handshake log: Extension server_name, server_name: [type=host_name (0), value=google.com]
sslParameters.setProtocols(new String[] {"TLSv1.2"});
socket.setSSLParameters(sslParameters);
socket.connect(new InetSocketAddress(InetAddress.getByName("google.com"), 443));
socket.addHandshakeCompletedListener(event -> System.out.println("----- HANDSHAKE DONE -----"));
socket.startHandshake();
为什么在通过 SNI 扩展请求无效主机名时 Google 根本不提供其证书?当没有匹配的主机名时,提供 random/default 证书是 SNI 的一部分吗?
Is it part of the SNI to provide random/default certificate when no matching host name?
SNI 不规定服务器的特定行为。它所提供的只是一种方式,服务器可以找出客户端想要访问的域。
服务器的行为非常不同:有些服务器完全忽略 SNI,因为它们只有一个配置和证书。如果没有给出 SNI 或不匹配,其他人有一些默认值。如果 SNI 给出的名称与特定配置不匹配,其余的通常会抛出某种错误。