stunnel - как заменить сертификат сервера без перерыва - PullRequest
0 голосов
/ 24 сентября 2019

Я пытаюсь понять процедуру, используемую для замены сертификата по истечении срока действия на stunnel.Итак, у меня есть установка stunnel в Windows с простой конфигурацией:

[test1]
accept = 127.0.0.1:21234
connect = 127.0.0.1:21235
cert = p1.pem

Файл p1.pem имеет структуру:

-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD1f+2n88ThTvLn ....
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEFjCCAv6gAwIBAgIUHD/p+ctiyaWxZCd1LiFqC5vzKGQwDQYJKoZIhvcNAQEL ....
-----END CERTIFICATE-----

Используя клиентское приложение Java, я мог быуспешно открыть SSL-соединение с портом 21234.

Сертификат p1.pem является самозаверяющим сертификатом, созданным с использованием openssl.До истечения срока действия сертификата p1.pem у нас должен быть период, в течение которого сервер будет принимать два сертификата (например, p1.pem и p2.pem).

Я попытался объединить два файла в p1p2.pem с помощьюструктура:

-----BEGIN PRIVATE KEY-----
p1 key
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
p1 cert
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
p2 key
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
p2 cert
-----END CERTIFICATE-----

Когда я пробовал то же самое клиентское приложение java, оно работает с общедоступным сертификатом p1, но с общедоступным сертификатом p2 возвращает:

Exception in thread "main"
javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find v alid certification path to requested target at
sun.security.ssl.Alerts.getSSLException(Unknown Source) at
sun.security.ssl.SSLSocketImpl.fatal(Unknown Source) at
sun.security.ssl.Handshaker.fatalSE(Unknown Source) at
sun.security.ssl.Handshaker.fatalSE(Unknown Source) at
sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source) at
sun.security.ssl.ClientHandshaker.processMessage(Unknown Source) at
sun.security.ssl.Handshaker.processLoop(Unknown Source) at
sun.security.ssl.Handshaker.process_record(Unknown Source) at
sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source) at
sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source) at
sun.security.ssl.SSLSocketImpl.writeRecord(Unknown Source) at
sun.security.ssl.AppOutputStream.write(Unknown Source) at
java.io.OutputStream.write(Unknown Source) at clt.main(clt.java:16) Caused by:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at
sun.security.validator.PKIXValidator.doBuild(Unknown Source) at
sun.security.validator.PKIXValidator.engineValidate(Unknown Source) at
sun.security.validator.Validator.validate(Unknown Source) at
sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source) at
sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source) at
sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source) ... 10 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target at
sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source) at
sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source) at
java.security.cert.CertPathBuilder.build(Unknown Source) ... 16 more

1 Ответ

0 голосов
/ 24 сентября 2019

TLDR: вы не можете перевести сервер

Сервер TLS, включая stunnel, использует только один сертификат и ключ за раз или, по выбору, один на SNI (т. Е.имя домена хоста) если клиент отправляет SNI, что всегда делают браузеры (начиная с 2010 года) и последние версии Java (IIRC где-то в середине восьмого) обычно делать, но это может зависеть от того, как код настроил и открыл SSLSocket, который вы не показываете или не описываете.(Чтобы увидеть получение сетевой трассировки, если это возможно (может быть не для loopback / localhost, если в Windows) или запустить Java с sysprop javax.net.debug=ssl,handshake и посмотрите.) Это потому, что клиент не предоставляет серверу никакой информации о том, какой CA (s) или другой сертификат, который он «хочет»;в 1.2 и 1.3 он может указать алгоритмы подписи , которые он будет принимать, но обычно он не различает более старый и более новый сертификат.

stunnel, в частности, использует только first privatekey в файле cert= (или key=, если указан), и хотя он может использовать несколько цепочек сертификатов в файле cert=, он использует только первое в качестве сущности сертификат, как для данной «услуги», так и для SNI.И ваш p2.cert, по-видимому, не является действительным цепочечным сертификатом для p1.cert, поэтому выложенная вами конфигурация stunnel всегда использует p1.key и p1.cert.Если «... клиентское приложение Java ... с общедоступным сертификатом p2» означает, что вы помещаете p2, но не p1, в хранилище доверенных сертификатов клиента, то, конечно, этот клиент не проверяет соединение с сервером, использующим p1.

обычный метод обновления или иного перехода (серверных) сертификатов, предназначенный для работы, заключается в использовании сертификатов, выданных ЦС, в рамках долгоживущих ЦС, чтобы сервер могвыдал новый сертификат, и клиент будет доверять ему, потому что центр сертификации продолжает действовать и срок его действия не истек.

Если необходимо заменить подписанный сертификат , единственный способ, который работает с минимальным прерываниемэто:

  1. настройка клиента или всех клиентов для принятия как старых, так и новых сертификатов (что может включать или не включать мгновенное отключение каждого клиента, но несколько клиентовможет быть выполнено в разное время, особенно если они являются пулом или кластером или иным образом совместно обеспечивают возможность высокой доступности некоторого вида),

  2. затем смените сервер со старого на новый (stunnel может перезагрузиться без выключения),

  3. , а затем при необходимости удалите старый из клиента (ов) (при необходимости это может подождать, пока ихследующее время простоя по другим причинам или даже до следующей замены сертификата).

Но вам может и не понадобиться. Предполагается, что вы используете «самоподписанный» с правильным значением - сертификат, подписанный тем же ключом он содержит, а не просто подписан вами, и, следовательно, обязательно настроен в хранилище доверенных сертификатов клиента, поскольку над ним нет сертификата, который можно было бы использовать для его проверки - тогда при тестировании Java-клиента по умолчанию (то есть тот, который использует валидатор по умолчанию, как явно делает ваш код, и не не добавляет никакой другой валидации за пределами, что мы не можем сказать отсюда), тогда он примет самоподписанный сертификат в складах доверенных сертификатов даже после истечения срока действия .(Как ни странно, потому что официальный API CertPathValidator отклоняет его . Я попытаюсь разобраться с этим позже.) Настройте тестовый компьютер (возможно, виртуальную машину, чтобы не рисковатьлюбые важные файлы) и просмотрите его дату вперед, и посмотрите, работает ли он, и вы можете избежать всей проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...