Я в следующей ситуации. Мне нужно настроить двустороннюю интеграцию с внешней системой. Администратор внешней системы потребовал, чтобы я отправил два CSR, один для генерации сертификата клиента, другой для генерации сертификата сервера. Прислали мне соответствующие справки. Я успешно настроил канал me-> they (то есть: я могу вызвать их службу, предоставив мой клиентский сертификат), но я не могу правильно настроить обратный канал (то есть: я не могу заставить свой Apache принимать их сертификат клиента без жалоб).
Вместе с моим сертификатом сервера (назовем его my-server.pem) они также прислали мне свой собственный сертификат клиента (назовем его их-client.pem). Этот сертификат (их-client.pem) выдается «самоподписанным» ЦС, то есть ЦС, не входящим в число известных ЦС, уже доступных в моей системе Linux. У меня нет этого сертификата, и я еще не смог получить его от внешних системных администраторов (они не хотят ... давайте отложим любые комментарии по этому поводу, пожалуйста ...> - |)
Вот как я настроил свой VirtualHost в Apache:
SSLEngine on
SSLCertificateFile /path/to/my-server.pem
SSLCertificateKeyFile /path/to/my-server-secret-key.key
SSLVerifyClient require
SSLCACertificateFile /path/to/their-client.pem
SSLVerifyDepth 0
Поскольку у меня нет сертификата ЦС, и поскольку я могу сказать «просто доверяйте этому сертификату клиента, никому другому!», Я поставил сам сертификат клиента как SSLCACertificateFile
, как предложено в ответе на: https://security.stackexchange.com/questions/36069/use-client-certificate-using-self-signed-ca- while-using-web-certificate-of-a-pub
Однако, похоже, это не работает. Ошибка, которую они видят на своей стороне:
javax.net.ssl.SSLException: Received fatal alert: unknown_ca
После включения журнала SSL и настройки его на отладку я вижу на своей стороне:
[ssl:debug] [pid 3396] ssl_engine_kernel.c(1381): [client <their-ip>:41474] AH02275: Certificate Verification, depth 1, CRL checking mode: none [subject: CN=Test CA,OU=Foo,O=Bar,C=it / issuer: CN=Test CA,OU=Foo,O=Bar,C=it / serial: 1BFE / notbefore: Dec 6 15:22:45 2010 GMT / notafter: Dec 6 15:21:52 2020 GMT]
[ssl:info] [pid 3396] [client <their-IP>:41474] AH02276: Certificate Verification: Error (19): self signed certificate in certificate chain [subject: CN=Test CA,OU=Foo,O=Bar,C=it / issuer: CN=Test CA,OU=Foo,O=Bar,C=it / serial: 1BFE / notbefore: Dec 6 15:22:45 2010 GMT / notafter: Dec 6 15:21:52 2020 GMT]
[ssl:info] [pid 3396] [client <their-IP>:41474] AH02008: SSL library error 1 in handshake (server my-server.com:443)
[ssl:info] [pid 3396] SSL Library Error: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned
[ssl:info] [pid 3396] [client <their-IP>:41474] AH01998: Connection closed to child 54 with abortive shutdown (server my-server.com:443)
Другими словами, он все еще пытается проверить фиктивный ЦС сертификата клиента. Я тоже пытался изменить SSLVerifyDepth
до 1, безуспешно (та же ошибка). Если я отключу запрос сертификата клиента (изменив SSLVerifyClient
value) вызов проходит нормально, но я не думаю, что это правильный путь.
Очень похожий вопрос: Как я могу сделать так, чтобы apache запросил клиентский SSL-сертификат, не проверяя его с помощью известного центра сертификации?
Однако я не уверен, что понимаю принятое решение. Прежде всего, сертификат клиента, который я должен проверить, не является самоподписанным (он выпущен неизвестным центром сертификации).
Во-вторых, насколько я понимаю из документации Apache / mod_ssl, SSLVerifyCLient optional_no_ca
фактически отключает надежную проверку подлинности сертификата клиента, поскольку делает ее необязательной.
В-третьих, возможность создать поддельный сертификат с тем же DN отсутствующего сертификата корневого ЦС звучит как обходной путь для принуждения клиента к отправке своего сертификата клиента, но в моем случае я не думаю, что моя проблема в том, что клиент не отправляет мне сертификат, а скорее неспособность Apache полностью правильно его проверить.
Любые предложения по этой теме были бы очень полезны.
В вашем сообщении об ошибке четко указана причина прямо здесь: «глубина 1». Вы установили SSLVerifyDepth 0
что в руководстве означает, что:
принимаются только самоподписанные клиентские сертификаты
Чтобы проверить, соответствует ли сертификат клиента ожидаемому, и без проверки цепочки, попробуйте что-то вроде этого:
SSLVerify none
SSLRequire ( %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." and %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/ )
Это для Apache 2.4.
# Unchanged:
SSLEngine on
SSLCertificateFile /path/to/my-server.pem
SSLCertificateKeyFile /path/to/my-server-secret-key.key
SSLCACertificateFile /path/to/their-client.pem
SSLVerifyDepth 0
# Changed:
SSLVerifyClient optional_no_ca
Require expr "%{SSL_CLIENT_I_DN_CN} -eq 'www.example.com'"
Также ответил в Как я могу сделать так, чтобы apache запросил клиентский SSL-сертификат, не проверяя его в известном ЦС?
Я действительно ненавижу ответы, которые предлагают альтернативы, которые на самом деле не отвечают на вопрос, но ... если вы не хотите (или не можете, потому что они этого не предоставляют) принимать их CA для своего сертификата, вам следует выпустить им сертификат из вашего собственного центра сертификации. Это решило бы проблему не только того, что они не предоставляют сертификат подписавшего, но также избавило бы вас от необходимости доверять странному ЦС.
Я не эксперт по Apache, но с точки зрения сертификатов, если они не хотят предоставлять вам открытый ключ своего корневого ЦС, просто попросите их получить сертификат клиента из хорошо известного ЦС, а не из собственного ЦС. . Например, StartSSL предлагает бесплатный сертификат на 1 год. Вы создаете кошмар, потому что партнер не понимает, как это работает. Другой способ - установить собственный CA (Linux) https://jamielinux.com/docs/openssl-certificate-authority/ (Windows) http://datacenteroverlords.com/2012/03/01/creating-your-own-ssl-certificate-authority/ и попросите предоставить вам CSR для замены (their-client.pem)