Назад | Перейти на главную страницу

stunnel не проверяет сертификат клиента должным образом

Я пытаюсь настроить stunnel чтобы предоставить оболочку TLS для службы HTTP, которая изначально не поддерживает TLS. У меня это хорошо работает без использования клиентских сертификатов TLS.

При добавлении конфигурации сертификата клиента:

CAfile = /path/to/trusted.crt
verify = 4

Кажется, я не могу подключиться, используя openssl s_client. (Обратите внимание, что я немного обманываю - использую сертификат моего TLS-сервера в качестве сертификата клиента, но в сертификате указано, что у него есть расширение для X509v3 Extended Key Usage: TLS Web Client Authentication, TLS Web Server Authentication, поэтому я считаю, что это должно сработать.)

$ openssl s_client -state -connect [my-host-name]:[port] -cert [my-host-name].crt -key [my-host-name].key-nopass
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
depth=2 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN = StartCom Certification Authority
verify return:1
depth=1 C = IL, O = StartCom Ltd., OU = StartCom Certification Authority, CN = StartCom Class 1 DV Server CA
verify return:1
depth=0 CN = [my-hostname]
verify return:1
SSL_connect:SSLv3 read server certificate A
SSL_connect:SSLv3 read server key exchange A
SSL_connect:SSLv3 read server certificate request A
SSL_connect:SSLv3 read server done A
SSL_connect:SSLv3 write client certificate A
SSL_connect:SSLv3 write client key exchange A
SSL_connect:SSLv3 write certificate verify A
SSL_connect:SSLv3 write change cipher spec A
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL3 alert read:fatal:unknown CA
SSL_connect:failed in SSLv3 read server session ticket A
140391435724640:error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca:s3_pkt.c:1293:SSL alert number 48
140391435724640:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:184:
---
Certificate chain
 0 s:/CN=[my-host-name]
   i:/C=IL/O=StartCom Ltd./OU=StartCom Certification Authority/CN=StartCom Class 1 DV Server CA
 1 s:/C=IL/O=StartCom Ltd./OU=StartCom Certification Authority/CN=StartCom Class 1 DV Server CA
   i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
 2 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
   i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=/CN=[my-host-name]
issuer=/C=IL/O=StartCom Ltd./OU=StartCom Certification Authority/CN=StartCom Class 1 DV Server CA
---
Acceptable client certificate CA names
/C=[the actual client cert I'd like to use]
/CN=[my-host-name] (for testing)
Server Temp Key: ECDH, prime256v1, 256 bits
---
SSL handshake has read 5620 bytes and written 1937 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 3072 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : ECDHE-RSA-AES256-SHA
    Session-ID:
    Session-ID-ctx:
    Master-Key: [...]
    Key-Arg   : None
    Krb5 Principal: None
    PSK identity: None
    PSK identity hint: None
    Start Time: 1465393332
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

(На этом этапе соединение закрыто.)

Если я установлю verify = 0 в конфигурации stunnel соединение успешно, и я могу сделать запрос. Если я установлю verify = 1 в stunnel конфигурации соединение разрывается, если я предоставляю сертификат клиента, но принимается, если я его не предоставляю.

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

Я хочу проверять только те сертификаты, которые действительно присутствуют в моем trusted.crts файл. Эти строки отладки наводят меня на мысль, что я правильно указал сертификаты (это вывод от клиента):

Acceptable client certificate CA names
/C=[the actual client cert I'd like to use]
/CN=[my-host-name] (for testing)

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

Я не уверен, что мне не хватает.

В /var/log/secure, stunnel регистрирует это:

Jun  8 13:58:59 ip-10-0-0-176 stunnel: LOG5[17497:139964729063168]: Service [mysvc] accepted connection from 52.203.5.20:57224
Jun  8 13:58:59 ip-10-0-0-176 stunnel: LOG4[17497:139964729063168]: CERT: Verification error: unable to get local issuer certificate
Jun  8 13:58:59 ip-10-0-0-176 stunnel: LOG4[17497:139964729063168]: Certificate check failed: depth=0, /CN=[my-host-name]
Jun  8 13:58:59 ip-10-0-0-176 stunnel: LOG3[17497:139964729063168]: SSL_accept: 140890B2: error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned
Jun  8 13:58:59 ip-10-0-0-176 stunnel: LOG5[17497:139964729063168]: Connection reset: 0 byte(s) sent to SSL, 0 byte(s) sent to socket

Это выглядит как stunnel пытается проверить сертификат по ЦС, вместо того, чтобы напрямую доверять сертификату, который находится в моем trusted.crts файл.

Какие-либо предложения?

ОБНОВИТЬ

Если я уйду verify = 4 в stunnel файл конфигурации, но поместите родительский сертификат клиентского сертификата (тот, что от StartCom) в trusted.crts файл, я могу подключиться, используя свой тестовый сертификат. Если я перейду на использование verify = 3 с тестовым сертификатом и его подписывающей стороной в trusted.crts файл, я снова не могу подключиться.

Есть ли способ дать stunnel точные сертификаты, которые я готов принять от клиентов? В документации предлагается использовать verify = 3 или verify = 4 это способ сделать это, но я не могу заставить его работать так, как я думаю, я должен быть в состоянии.

Этот ответ не проверен, поскольку я только начинаю использовать stunnel, но из документации я думаю:

а) вам следует отказаться от verify вариант, так как он либо неполный, либо не такой ясный, как verifyChain и verifyPeer варианты и он устарел:

verify = LEVEL
       verify the peer certificate

       This option is obsolete and should be replaced with the verifyChain
       and verifyPeer options.

б) verifyChain следует проверить цепочку сертификатов, используя указанное в CAfile или в файле внутри CApath. Для цепочки с промежуточными сертификатами все промежуточные сертификаты должны быть действительны для корня CA, который должен содержаться в коллекциях CA (файл или путь).

в) verifyPeer проверяет, должен ли сам сертификат содержаться в CAfile или CApath.

Обратите внимание, что на самом деле, без ссылки на расширения, корневой сертификат CA - это просто самозаверяющий сертификат с установленным флагом CA значением yes. Конечно, такие сертификаты CA не входят в набор доверенных CA, обычно распространяемых с браузерами или в операционной системе. В Linux путь CApath, в котором openssl хранит доверенные центры сертификации (/etc/ssl/certs) следует проверить на соответствие стандартному набору доверенных сертификатов. Конечно, вы также можете добавить туда свой собственный CA.

Условия /C и /CN являются частью субъекта сертификатов, где /C это страна и /CN это общее имя. См. Вывод

openssl x509 -noout -subject </etc/ssl/certs/Deutsche_Telekom_Root_CA_2.pem
subject=C = DE, O = Deutsche Telekom AG, OU = T-TeleSec Trust Center, CN = Deutsche Telekom Root CA 2

Например. Опять же: эти корневые сертификаты полезны только в том случае, если вы используете verifyChain=yes. Если вариант verifyPeer=yes проверяется сам сертификат, если вы установите для обоих значение «Да», будут проверены как корневой, так и одноранговый сертификаты, возможно, со всеми промежуточными (не отмеченными).

Из stunnel (8):

   cert = CERT_FILE
       certificate chain file name

       The parameter specifies the file containing certificates used by
       stunnel to authenticate itself against the remote client or server.
       The file should contain the whole certificate chain starting from
       the actual server/client certificate, and ending with the self-
       signed root CA certificate.  The file must be either in PEM or P12
       format.

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

Теперь мы можем проверить, действителен ли сертификат, но мы все еще не знаем, как проверить, действительно ли сертификат принадлежит одноранговому узлу. Одноранговый узел мог украсть действующий сертификат и пытается использовать его сейчас.

В stunnel теперь есть:

checkEmail, чтобы проверить DN (отличительное имя или имя каталога) в теме или в расширении альтернативного имени субъекта (rfc822Name (см. RFC280)) (X509v3).

checkHostпроверьте DNS-имя сертификата. Это может быть сложно или непригодно для проверки сертификатов клиента.

checkIP, IP-адрес сертификата проверяется.

В руководстве говорится "Certificates are accepted if no subject checks where specified". На самом деле я этого не понимаю, потому что считаю checkIP, checkHost и checkEmail поля являются "subject checks" и трудно указать checkEmail предмет проверки, а "no subject checks are specified".

Я полагаю, они имеют в виду «никакой другой предметной проверки». Конечно, если предметная проверка не указана, сертификат должен быть действительным.

Обратите внимание, что хост и IP-адрес из сертификата проверяются, и нет ни слова о том, сравнивается ли он с именем хоста или IP-адресом однорангового узла при подключении, как это делается при связи с серверами HTTPS, где CN должен соответствовать Имя хоста или DNS-имя в альтернативных вариантах или IP-адрес в альтернативных вариантах.

Все эти побочные случаи не тестировались, и они могли пропустить часть документации.

Также предметные проверки излишни, если вы используете verifyPeer так как verifyPeer содержит полный одноранговый сертификат с темой и альтернативами и так далее.

Я не вижу, чтобы поля использования сертификата где-то проверялись. Если да, то этот пункт отсутствует в документации!

Я выложу обновление, когда проверю все боковые корпуса.