server {
...
ssl_client_certificate /certs/t1_t2_coagent_ca.crt;
ssl_verify_client on;
ssl_verify_depth 3;
...
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
response:
ps:
1)all alpine based images can return index.html;
2)nginx:1.11 is OK
Which images are that? Can you provide a simple test scenario e.g. using self-signed certificates? ssl_verify_client are definitely not broken in numerous setups we have with 1.12.0+.
cert.zip
use:
./nginx_restart.sh
./docker_curl.sh
cd cert
./curl_test.sh (you should use your ip instead of 192.168.0.107 )
Thanks, that clarifies things a lot!
First of all, this is not a bug in nginx :-)
Enabling debug in error log in nginx, I could see the following error when trying to auth using generated certificates:
2017/06/06 15:59:58 [info] 6#6: *2 client SSL certificate verify error: (26:unsupported certificate purpose) while reading client request headers, client: 172.17.0.1, server: localhost, request: "GET / HTTP/1.1", host: "server:3001"
And this did not happen when I compiled the same nginx with an old openssl version - which led me thinking that some bug might have been fixed or introduced in openssl. I've also checked old nginx version against openssl 1.1.0 - which exhibited the same exact problem of not validating the certificates.
I've took a closer look on the certificates. The ca.crt generated has the following (via openssl x509 -in ./certs/ca.crt -noout -purpose):
Certificate purposes:
SSL client : Yes
SSL client CA : Yes
SSL server : Yes
SSL server CA : Yes
Although coagent.crt and all the following ones:
Certificate purposes:
SSL client : Yes
SSL client CA : No
SSL server : Yes
SSL server CA : No
So it looks like that prior to 1.1.0 openssl did not actually check the purposes of the certificates when checking if they are valid:
/cert/certs # openssl version
OpenSSL 1.0.2k 26 Jan 2017
/cert/certs # openssl x509 -in ./ca.crt -noout -purpose |grep ^SSL
SSL client : Yes
SSL client CA : Yes (WARNING code=3)
SSL server : Yes
SSL server CA : Yes (WARNING code=3)
/cert/certs # openssl x509 -in ./coagent.crt -noout -purpose |grep ^SSL
SSL client : Yes
SSL client CA : No
SSL server : Yes
SSL server CA : No
/cert/certs # openssl verify -verbose -CAfile ./ca.crt coagent.crt
coagent.crt: OK
/cert/certs # cat ./ca.crt ./coagent.crt > ca_coagent.crt
/cert/certs # openssl verify -verbose -CAfile ./ca_coagent.crt ./t1.crt
./t1.crt: OK
/cert/certs # cat ./ca.crt ./coagent.crt ./t1.crt > ca_coagent_t1.crt
/cert/certs # openssl x509 -in ./t1.crt -noout -purpose |grep ^SSL
SSL client : Yes
SSL client CA : No
SSL server : Yes
SSL server CA : No
/cert/certs # openssl verify -verbose -CAfile ./ca_coagent_t1.crt ./v1.crt
./v1.crt: OK
However things are different in 1.1.0:
root@deb9-test1:/etc/nginx/cert/certs# openssl version
OpenSSL 1.1.0e 16 Feb 2017
root@deb9-test1:/etc/nginx/cert/certs# openssl x509 -in ./ca.crt -noout -purpose |grep ^SSL
SSL client : Yes
SSL client CA : Yes (WARNING code=3)
SSL server : Yes
SSL server CA : Yes (WARNING code=3)
root@deb9-test1:/etc/nginx/cert/certs# openssl x509 -in ./coagent.crt -noout -purpose |grep ^SSL
SSL client : Yes
SSL client CA : No
SSL server : Yes
SSL server CA : No
root@deb9-test1:/etc/nginx/cert/certs# openssl verify -verbose -CAfile ./ca.crt coagent.crt
coagent.crt: OK
root@deb9-test1:/etc/nginx/cert/certs# cat ./ca.crt ./coagent.crt > ca_coagent.crt
root@deb9-test1:/etc/nginx/cert/certs# openssl verify -verbose -CAfile ./ca_coagent.crt ./t1.crt
C = US, ST = Denial, L = Springfield, O = Dis, CN = coagent
error 24 at 1 depth lookup: invalid CA certificate
error ./t1.crt: verification failed
root@deb9-test1:/etc/nginx/cert/certs# cat ./ca.crt ./coagent.crt ./t1.crt > ca_coagent_t1.crt
root@deb9-test1:/etc/nginx/cert/certs# openssl x509 -in ./t1.crt -noout -purpose |grep ^SSL
SSL client : Yes
SSL client CA : No
SSL server : Yes
SSL server CA : No
root@deb9-test1:/etc/nginx/cert/certs# openssl verify -verbose -CAfile ./ca_coagent_t1.crt ./v1.crt
C = US, ST = Denial, L = Springfield, O = Dis, CN = t1
error 24 at 1 depth lookup: invalid CA certificate
C = US, ST = Denial, L = Springfield, O = Dis, CN = coagent
error 24 at 2 depth lookup: invalid CA certificate
error ./v1.crt: verification failed
So the problem here is that openssl has fixed the bug, and now actually checks for the purposes of the certificates. I guess prior to that clients could generate new leaf certificates and if you did not set the ssl_verify_depth in nginx properly, you could have been abused...
Anyway, I've re-generated the certificates with:
openssl x509 -req -days 365 -in coagent.csr -CA ca.crt -CAkey ca.key -set_serial 1002 -out coagent.crt -extfile ./openssl.cnf -extensions v3_ca
where openssl.cnf is:
[ v3_ca ]
basicConstraints = CA:true
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid
Now the certificates have SSL client CA: Yes and SSL server CA: Yes and validation goes just fine. But I guess you would want to set it only for the intermediaries, not the actual clients.
Thanks!
Most helpful comment
Thanks, that clarifies things a lot!
First of all, this is not a bug in nginx :-)
Enabling debug in error log in nginx, I could see the following error when trying to auth using generated certificates:
And this did not happen when I compiled the same nginx with an old openssl version - which led me thinking that some bug might have been fixed or introduced in openssl. I've also checked old nginx version against openssl 1.1.0 - which exhibited the same exact problem of not validating the certificates.
I've took a closer look on the certificates. The ca.crt generated has the following (via
openssl x509 -in ./certs/ca.crt -noout -purpose):Although coagent.crt and all the following ones:
So it looks like that prior to 1.1.0 openssl did not actually check the purposes of the certificates when checking if they are valid:
However things are different in 1.1.0:
So the problem here is that openssl has fixed the bug, and now actually checks for the purposes of the certificates. I guess prior to that clients could generate new leaf certificates and if you did not set the ssl_verify_depth in nginx properly, you could have been abused...
Anyway, I've re-generated the certificates with:
openssl x509 -req -days 365 -in coagent.csr -CA ca.crt -CAkey ca.key -set_serial 1002 -out coagent.crt -extfile ./openssl.cnf -extensions v3_cawhere openssl.cnf is:
Now the certificates have
SSL client CA: YesandSSL server CA: Yesand validation goes just fine. But I guess you would want to set it only for the intermediaries, not the actual clients.