Сервер предоставляет сертификат для недопустимого имени хоста SNI

Я столкнулся с поведением Java SNI SSL, которое не понимаю. При использовании SNI в Java я ожидаю, что 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();

Почему Google вообще предоставляет свой сертификат при запросе недопустимого имени хоста через расширение SNI? Является ли частью SNI предоставление случайного сертификата/сертификата по умолчанию, когда нет подходящего имени хоста?


person Dr Boom    schedule 27.03.2020    source источник


Ответы (1)


Является ли частью SNI предоставление случайного сертификата/сертификата по умолчанию, когда нет подходящего имени хоста?

SNI не диктует конкретное поведение сервера. Все, что он предоставляет, — это способ, с помощью которого сервер может узнать, к какому домену хочет получить доступ клиент.

Поведение серверов очень разное: некоторые вообще игнорируют SNI, так как у них все равно есть только одна конфигурация и сертификат. Другие имеют некоторые значения по умолчанию на случай, если SNI не указан или не совпадает. А остальные обычно выкидывают какую-то ошибку, если имя, данное SNI, не соответствует конкретной конфигурации.

person Steffen Ullrich    schedule 27.03.2020
comment
Я прочитал в ссылку Сервер, который получает клиентское приветствие, содержащее расширение server_name МОЖЕТ использовать информацию, содержащуюся в расширении, для управления выбором соответствующего сертификата для возврата клиенту [...] Это означает, что поведение сервера зависит от реализации, и он может возвращать или не возвращать конкретный сертификат связанные с именем сервера. Например, Java sun.security.ssl.SunX509KeyManagerImpl#chooseServerAlias возвращает первый псевдоним из диспетчера ключей, и поиск имени сервера не выполняется. - person Dr Boom; 28.03.2020