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

Сертификаты Nginx и клиентов от иерархических центров сертификации на основе OpenSSL

Я пытаюсь создать корневой центр сертификации, подчиненный центр сертификации и сгенерировать клиентские сертификаты, подписанные любым из этого центра сертификации, который nginx 0.7.67 в Debian Squeeze будет принимать. Моя проблема в том, что сертификат клиента, подписанный корневым ЦС, работает нормально, в то время как подписанный подчиненным ЦС один приводит к «400 Bad Request. Ошибка сертификата SSL».

Шаг 1: конфигурация виртуального хоста nginx:

server {

    server_name  test.local;

    access_log  /var/log/nginx/test.access.log;

    listen                  443 default ssl;
    keepalive_timeout       70;

    ssl_protocols           SSLv3 TLSv1;
    ssl_ciphers             AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
    ssl_certificate         /etc/nginx/ssl/server.crt;
    ssl_certificate_key     /etc/nginx/ssl/server.key;
    ssl_client_certificate  /etc/nginx/ssl/client.pem;
    ssl_verify_client       on;
    ssl_session_cache       shared:SSL:10m;
    ssl_session_timeout     5m;

    location / {
            proxy_pass http://testsite.local/;
    }
}

Шаг 2: Организация инфраструктуры PKI как для корневого, так и для подчиненного ЦС (на основе этот статья):

# mkdir ~/pki && cd ~/pki
# mkdir rootCA subCA
# cp -v /etc/ssl/openssl.cnf rootCA/
# cd rootCA/
# mkdir certs private crl newcerts; touch serial; echo 01 > serial; touch index.txt; touch crlnumber; echo 01 > crlnumber
# cp -Rvp * ../subCA/

В rootCA / openssl.cnf изменений почти не было:

[ CA_default ]

dir             = .                     # Where everything is kept
...
certificate     = $dir/certs/rootca.crt # The CA certificate
...
private_key     = $dir/private/rootca.key # The private key

и в subCA / openssl.cnf:

[ CA_default ]

dir             = .                     # Where everything is kept
...
certificate     = $dir/certs/subca.crt  # The CA certificate
...
private_key     = $dir/private/subca.key # The private key

Шаг 3: Создание сертификата корневого центра сертификации с собственной подписью:

# openssl genrsa -out ./private/rootca.key -des3 2048
# openssl req -x509 -new -key ./private/rootca.key -out certs/rootca.crt -config openssl.cnf
Enter pass phrase for ./private/rootca.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:rootca
Email Address []:

Шаг 4: Создание сертификата подчиненного ЦС:

# cd ../subCA
# openssl genrsa -out ./private/subca.key -des3 2048
# openssl req -new -key ./private/subca.key -out subca.csr -config openssl.cnf
Enter pass phrase for ./private/subca.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:subca
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Шаг 5: Подпись сертификата подчиненного ЦС сертификатом корневого ЦС:

# cd ../rootCA/
# openssl ca -in ../subCA/subca.csr -extensions v3_ca -config openssl.cnf
Using configuration from openssl.cnf
Enter pass phrase for ./private/rootca.key:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Feb  4 10:49:43 2013 GMT
            Not After : Feb  4 10:49:43 2014 GMT
        Subject:
            countryName               = AU
            stateOrProvinceName       = Some-State
            organizationName          = Internet Widgits Pty Ltd
            commonName                = subca
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                C9:E2:AC:31:53:81:86:3F:CD:F8:3D:47:10:FC:E5:8E:C2:DA:A9:20
            X509v3 Authority Key Identifier:
                keyid:E9:50:E6:BF:57:03:EA:6E:8F:21:23:86:BB:44:3D:9F:8F:4A:8B:F2
                DirName:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca
                serial:9F:FB:56:66:8D:D3:8F:11

            X509v3 Basic Constraints:
                CA:TRUE
Certificate is to be certified until Feb  4 10:49:43 2014 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
...
# cd ../subCA/
# cp -v ../rootCA/newcerts/01.pem certs/subca.crt

Шаг 6: Генерация сертификата сервера и подпись корневым центром сертификации (для виртуального хоста nginx):

# cd ../rootCA
# openssl genrsa -out ./private/server.key -des3 2048
# openssl req -new -key ./private/server.key -out server.csr -config openssl.cnf
Enter pass phrase for ./private/server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:test.local
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
# openssl ca -in server.csr -out certs/server.crt -config openssl.cnf

Шаг 7: Создание сертификата клиента №1 и подпись корневым центром сертификации:

# openssl genrsa -out ./private/client1.key -des3 2048
# openssl req -new -key ./private/client1.key -out client1.csr -config openssl.cnf
Enter pass phrase for ./private/client1.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Client #1
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
# openssl ca -in client1.csr -out certs/client1.crt -config openssl.cnf

Шаг 8: Преобразование сертификата клиента №1 в формат PKCS12:

# openssl pkcs12 -export -out certs/client1.p12 -inkey private/client1.key -in certs/client1.crt -certfile certs/rootca.crt

Шаг 9: Создание сертификата клиента №2 и подпись подчиненным центром сертификации:

# cd ../subCA/
# openssl genrsa -out ./private/client2.key -des3 2048
# openssl req -new -key ./private/client2.key -out client2.csr -config openssl.cnf
Enter pass phrase for ./private/client2.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:Client #2
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
# openssl ca -in client2.csr -out certs/client2.crt -config openssl.cnf

Шаг 10: Преобразование сертификата клиента №2 в формат PKCS12:

# openssl pkcs12 -export -out certs/client2.p12 -inkey private/client2.key -in certs/client2.crt -certfile certs/subca.crt

Шаг 11: Передача сертификата сервера и закрытого ключа в nginx (выполняется с привилегиями суперпользователя ОС):

# cd ../rootCA/
# cp -v certs/server.crt /etc/nginx/ssl/
# cp -v private/server.key /etc/nginx/ssl/

Шаг 12: Передача корневого и подчиненного сертификатов ЦС в nginx (выполняется с привилегиями суперпользователя ОС):

# cat certs/rootca.crt > /etc/nginx/ssl/client.pem
# cat ../subCA/certs/subca.crt >> /etc/nginx/ssl/client.pem

Файл client.pem выглядит так:

# cat /etc/nginx/ssl/client.pem
-----BEGIN CERTIFICATE-----
MIID6TCCAtGgAwIBAgIJAJ/7VmaN048RMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnJvb3RjYTAeFw0xMzAyMDQxMDM1NTda
...
-----END CERTIFICATE-----
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
...
-----BEGIN CERTIFICATE-----
MIID4DCCAsigAwIBAgIBATANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQ8wDQYDVQQDEwZyb290Y2EwHhcNMTMwMjA0MTA0OTQzWhcNMTQwMjA0
...
-----END CERTIFICATE-----

Вроде все нормально работает:

# service nginx reload
# Reloading nginx configuration: Enter PEM pass phrase:
# nginx.
#

Шаг 13: Установка сертификатов * .p12 в браузере (в моем случае Firefox) вызывает проблему, о которой я упоминал выше. Клиент № 1 = 200 OK, Клиент № 2 = 400 Неверный запрос / Ошибка сертификата SSL. Есть идеи, что мне делать?

Обновление 1: Результаты попыток проверки SSL-соединения:

# openssl s_client -connect test.local:443 -CAfile ~/pki/rootCA/certs/rootca.crt -cert ~/pki/rootCA/certs/client1.crt -key ~/pki/rootCA/private/client1.key -showcerts
Enter pass phrase for tmp/testcert/client1.key:
CONNECTED(00000003)
depth=1 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = rootca
verify return:1
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = test.local
verify return:1
---
Certificate chain
 0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=test.local
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca
-----BEGIN CERTIFICATE-----
MIIDpjCCAo6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBWMQswCQYDVQQGEwJBVTET
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQ8wDQYDVQQDEwZyb290Y2EwHhcNMTMwMjA0MTEwNjAzWhcNMTQwMjA0
...
-----END CERTIFICATE-----
 1 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca
-----BEGIN CERTIFICATE-----
MIID6TCCAtGgAwIBAgIJAJ/7VmaN048RMA0GCSqGSIb3DQEBBQUAMFYxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnJvb3RjYTAeFw0xMzAyMDQxMDM1NTda
...
-----END CERTIFICATE-----
---
Server certificate
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=test.local
issuer=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca
---
Acceptable client certificate CA names
/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca
/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=subca
---
SSL handshake has read 3395 bytes and written 2779 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: zlib compression
Expansion: zlib compression
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES256-SHA
    Session-ID: 15BFC2029691262542FAE95A48078305E76EEE7D586400F8C4F7C516B0F9D967
    Session-ID-ctx: 
    Master-Key: 23246CF166E8F3900793F0A2561879E5DB07291F32E99591BA1CF53E6229491FEAE6858BFC9AACAF271D9C3706F139C7
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket:
    0000 - c2 5e 1d d2 b5 6d 40 23-b2 40 89 e4 35 75 70 07   .^...m@#.@..5up.
    0010 - 1b bb 2b e6 e0 b5 ab 10-10 bf 46 6e aa 67 7f 58   ..+.......Fn.g.X
    0020 - cf 0e 65 a4 67 5a 15 ba-aa 93 4e dd 3d 6e 73 4c   ..e.gZ....N.=nsL
    0030 - c5 56 f6 06 24 0f 48 e6-38 36 de f1 b5 31 c5 86   .V..$.H.86...1..
    ...
    0440 - 4c 53 39 e3 92 84 d2 d0-e5 e2 f5 8a 6a a8 86 b1   LS9.........j...

    Compression: 1 (zlib compression)
    Start Time: 1359989684
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

Кажется, все в порядке с клиентом №2 и корневым сертификатом CA, но запрос возвращает ошибку 400 Bad Request:

# openssl s_client -connect test.local:443 -CAfile ~/pki/rootCA/certs/rootca.crt -cert ~/pki/subCA/certs/client2.crt -key ~/pki/subCA/private/client2.key -showcerts
Enter pass phrase for tmp/testcert/client2.key:
CONNECTED(00000003)
depth=1 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = rootca
verify return:1
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = test.local
verify return:1
...
    Compression: 1 (zlib compression)
    Start Time: 1359989989
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
GET / HTTP/1.0

HTTP/1.1 400 Bad Request
Server: nginx/0.7.67
Date: Mon, 04 Feb 2013 15:00:43 GMT
Content-Type: text/html
Content-Length: 231
Connection: close

<html>
<head><title>400 The SSL certificate error</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>The SSL certificate error</center>
<hr><center>nginx/0.7.67</center>
</body>
</html>
closed

Проверка не выполняется с сертификатом клиента №2 и сертификатом подчиненного ЦС:

# openssl s_client -connect test.local:443 -CAfile ~/pki/subCA/certs/subca.crt -cert ~/pki/subCA/certs/client2.crt -key ~/pki/subCA/private/client2.key -showcerts
Enter pass phrase for tmp/testcert/client2.key:
CONNECTED(00000003)
depth=1 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = rootca
verify error:num=19:self signed certificate in certificate chain
verify return:0
...
    Compression: 1 (zlib compression)
    Start Time: 1359990354
    Timeout   : 300 (sec)
    Verify return code: 19 (self signed certificate in certificate chain)
---
GET / HTTP/1.0

HTTP/1.1 400 Bad Request
...

По-прежнему появляется ошибка 400 Bad Request с объединенными сертификатами CA и клиентом №2 (но с клиентом №1 все в порядке):

# cat certs/rootca.crt ../subCA/certs/subca.crt > certs/concatenatedca.crt
# openssl s_client -connect test.local:443 -CAfile ~/pki/rootCA/certs/concatenatedca.crt -cert ~/pki/subCA/certs/client2.crt -key ~/pki/subCA/private/client2.key -showcerts
Enter pass phrase for tmp/testcert/client2.key:
CONNECTED(00000003)
depth=1 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = rootca
verify return:1
depth=0 C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = test.local
verify return:1
---
...
    Compression: 1 (zlib compression)
    Start Time: 1359990772
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
GET / HTTP/1.0

HTTP/1.1 400 Bad Request
...

Обновление 2: Мне удалось перекомпилировать nginx с включенной отладкой. Вот часть успешного соединения по треку Клиента №1:

2013/02/05 14:08:23 [debug] 38701#0: *119 accept: <MY IP ADDRESS> fd:3
2013/02/05 14:08:23 [debug] 38701#0: *119 event timer add: 3: 60000:2856497512
2013/02/05 14:08:23 [debug] 38701#0: *119 kevent set event: 3: ft:-1 fl:0025
2013/02/05 14:08:23 [debug] 38701#0: *119 malloc: 28805200:660
2013/02/05 14:08:23 [debug] 38701#0: *119 malloc: 28834400:1024
2013/02/05 14:08:23 [debug] 38701#0: *119 posix_memalign: 28860000:4096 @16
2013/02/05 14:08:23 [debug] 38701#0: *119 http check ssl handshake
2013/02/05 14:08:23 [debug] 38701#0: *119 https ssl handshake: 0x16
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL server name: "test.local"
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL_do_handshake: -1
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL_get_error: 2
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL handshake handler: 0
2013/02/05 14:08:23 [debug] 38701#0: *119 verify:1, error:0, depth:1, subject:"/C=AU    /ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca",issuer: "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca"
2013/02/05 14:08:23 [debug] 38701#0: *119 verify:1, error:0, depth:0, subject:"/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=Client #1",issuer: "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca"
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL_do_handshake: 1
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL: TLSv1, cipher: "AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1"
2013/02/05 14:08:23 [debug] 38701#0: *119 http process request line
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL_read: -1
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL_get_error: 2
2013/02/05 14:08:23 [debug] 38701#0: *119 http process request line
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL_read: 1
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL_read: 524
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL_read: -1
2013/02/05 14:08:23 [debug] 38701#0: *119 SSL_get_error: 2
2013/02/05 14:08:23 [debug] 38701#0: *119 http request line: "GET / HTTP/1.1"

А вот часть неудачного подключения по треку Клиента №2:

2013/02/05 13:51:34 [debug] 38701#0: *112 accept: <MY_IP_ADDRESS> fd:3
2013/02/05 13:51:34 [debug] 38701#0: *112 event timer add: 3: 60000:2855488975
2013/02/05 13:51:34 [debug] 38701#0: *112 kevent set event: 3: ft:-1 fl:0025
2013/02/05 13:51:34 [debug] 38701#0: *112 malloc: 28805200:660
2013/02/05 13:51:34 [debug] 38701#0: *112 malloc: 28834400:1024
2013/02/05 13:51:34 [debug] 38701#0: *112 posix_memalign: 28860000:4096 @16
2013/02/05 13:51:34 [debug] 38701#0: *112 http check ssl handshake
2013/02/05 13:51:34 [debug] 38701#0: *112 https ssl handshake: 0x16
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL server name: "test.local"
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL_do_handshake: -1
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL_get_error: 2
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL handshake handler: 0
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL_do_handshake: -1
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL_get_error: 2
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL handshake handler: 0
2013/02/05 13:51:34 [debug] 38701#0: *112 verify:0, error:20, depth:1, subject:"/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=subca",issuer: "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca"
2013/02/05 13:51:34 [debug] 38701#0: *112 verify:0, error:27, depth:1, subject:"/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=subca",issuer: "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=rootca"
2013/02/05 13:51:34 [debug] 38701#0: *112 verify:1, error:27, depth:0, subject:"/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=Client #2",issuer: "/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=subca"
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL_do_handshake: 1
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL: TLSv1, cipher: "AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1"
2013/02/05 13:51:34 [debug] 38701#0: *112 http process request line
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL_read: 1
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL_read: 524
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL_read: -1
2013/02/05 13:51:34 [debug] 38701#0: *112 SSL_get_error: 2
2013/02/05 13:51:34 [debug] 38701#0: *112 http request line: "GET / HTTP/1.1"

Итак, я получаю ошибку OpenSSL №20, а затем №27. По данным проверки документация:

20 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: unable to get local issuer certificate

    the issuer certificate could not be found: this occurs if the issuer certificate of an untrusted certificate cannot be found.

27 X509_V_ERR_CERT_UNTRUSTED: certificate not trusted

    the root CA is not marked as trusted for the specified purpose.

Насколько я понимаю,

ssl_verify_depth 2;

должен сделать свое дело. Видеть http://nginx.org/r/ssl_verify_depth для подробностей.

Хорошо, это не ошибка, это особенность;)

У меня тоже была эта «проблема», решение и объяснение здесь: https://stackoverflow.com/questions/8431528/nginx-ssl-certificate-authentication-signed-by-intermediate-ca-chain/14895039#14895039 (источник: http://trac.nginx.org/nginx/ticket/301)

В этой конфигурации:

RootCA -> IntermediateCA1 -> Client1 
RootCA -> IntermediateCA2 -> Client2

если я хочу предоставить доступ только к Client1 (и другим сертификатам, подписанным IntermediateCA1), я использую эту конфигурацию:

server {
  listen 443 ssl;

  ssl_certificate ...
  ssl_certificate_key ...

  ssl_client_certificate /path/to/ca.crt;
  ssl_verify_client on;
  ssl_verify_depth 2;

  if ($ssl_client_i_dn != "/C=PL/CN=IntermediateCA1/emailAddress=cert@asdf.com") {
    return 403;
  }
}

Как отметил @Maxim Dounin, ssl_verify_depth 2; должен сделать свое дело. Причина этого в том, что по умолчанию ssl_verify_depth == 1, а nginx просто не может проверить ваши сертификаты с глубиной == 2 (Root + Intermediate)

По документыпопробуйте добавить промежуточный сертификат CA к файлу, указанному ssl_certificate? Похоже, он добавляется в конец файла, который вы указали для ssl_client_certificate вместо.

Итак, вместо этого:

# cat certs/rootca.crt > /etc/nginx/ssl/client.pem
# cat ../subCA/certs/subca.crt >> /etc/nginx/ssl/client.pem

Попробуй это:

# cat certs/rootca.crt > /etc/nginx/ssl/client.pem
# cat ../subCA/certs/subca.crt >> /etc/nginx/ssl/server.crt

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

Из того, что я обнаружил, nginx не принимает цепочку сертификатов, как и следовало ожидать, когда она у вас есть в качестве клиента. Похоже, что он примет любой сертификат от любого CA в цепочке. У меня есть RootCA> Внутренний CA> Клиентский CA> Клиентский сертификат ... Можно было бы ожидать, что если бы сертификат для клиентского CA был предоставлен как клиентский CA, тогда сертификаты, подписанные клиентским CA, действительны. Я не добился успеха ни с одним промежуточным центром сертификации, поскольку клиент ca. Он отлично работает с самоподписанным корневым центром сертификации для клиентских сертификатов. - Стив Бузонас 02 июня 2012, 21:21