下面的配置里,ca.crt 是一个 untrusted 的 CA,当用 ca.crt 来验证客户端的证书时,Nginx 的 error log 里提示 unable to verify the first certificate,错误码是 21。但其实我用 openssl 命令行用 ca.crt 校验客户端证书是 OK 的。哪位高人指点下怎么解决?
server {
listen 443 ssl;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
server_name www.example.com;
ssl_certificate server.crt;
ssl_certificate_key server.key;
ssl_verify_client on;
ssl_client_certificate ca.crt;
}
1
virusdefender 2018-08-01 10:05:55 +08:00
client_certificate 不需要是可信 ca,你的可能是其他错误导致的,比如客户端证书导出的不太对?
|
2
xudzhang OP @virusdefender Nginx 的官方文档这样说的:"ssl_client_certificate specifies a file with trusted CA certificates in the PEM format used to verify",这个的意思是不是说我的 ca.crt 必须是 trusted ?
|
3
virusdefender 2018-08-01 10:15:06 +08:00 1
@xudzhang #2 我一直是用的自签名的 ca,然后导出的客户端证书啊,正常用,稍等我看下导出证书的脚本。
|
4
virusdefender 2018-08-01 10:27:25 +08:00
你用的是什么版本的 nginx 啊,我看新版好像行为不太一样了
ssl_verify_client on | off | optional | optional_no_ca; The optional_no_ca parameter (1.3.8, 1.2.5) requests the client certificate but does not require it to be signed by a trusted CA certificate. This is intended for the use in cases when a service that is external to nginx performs the actual certificate verification. The contents of the certificate is accessible through the $ssl_client_cert variable. |
5
owt5008137 2018-08-01 10:29:34 +08:00 via Android 1
@virusdefender 我以前也自己签,写了个写脚本改 openssl.cnf 文件里的配置就成。
https://github.com/owent-utils/bash-shell/tree/master/Others/x509_ssl_cert 但是现在有 let's encrypt |
6
xudzhang OP @virusdefender 这个 optional_no_ca 我昨天试了一下,好像不管用,看官方文档的意思,这个选项启用的时候会请求客户端证书但是不要求客户端证书是 trusted 的,但我这个情况其实是我自己的 ca.crt 是 untrusted,现在我就是没找到路子怎么让 Nginx 或者说让我的 Linux server 信任我的这个 ca.crt ,不知道我这么理解对不对?
|
7
xudzhang OP @owt5008137 大佬,我的 openssl 好像是用 yum install 安装的,能不能指教一下你说的这个 cnf 配置在哪里?我找了一下没找到~
|
8
Zakun 2018-08-01 10:35:39 +08:00
http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_trusted_certificate
ssl_trusted_certificate 字段。 |
9
virusdefender 2018-08-01 10:35:40 +08:00
不过我试了下,我的 nginx version: nginx/1.13.9 还是可以工作的
``` openssl genrsa -out ca.key 4096 openssl req -new -x509 -nodes -sha256 -subj "$subj/CN=Test Root CA" -days 3650 -key ca.key -out ca.crt openssl genrsa -out client.key 4096 openssl req -new -key client.key -out client.csr -subj "/CN=Cert Test" openssl x509 -req -days 3650 -extfile <(printf "keyUsage=digitalSignature") -in client.csr -CA client_ca.crt -CAkey client_ca.key -set_serial 1234 -out client.crt openssl pkcs12 -export -in client.crt -inkey client.key -name "Admin Cert" -out client.p12 -password pass:123456 ``` ``` ssl_client_certificate /ssl/client_ca.crt; ssl_verify_client on; ``` |
10
SirLostWhite 2018-08-01 10:35:50 +08:00
可以用 certbot 自动配置 letsencrypt 证书
全自动的 |
11
xudzhang OP @Zakun 这个字段之前试过,我加了 ssl_trusted_certificate ca.crt 的配置,并没什么用啊……
|
12
xudzhang OP @virusdefender 理解一下,在你这个例子里,你用 ca 签发了 client_ca,那为什么你的 ssl_client_certificate 里配的是 client_ca.crt 而不是 ca.crt ?
|
13
msg7086 2018-08-01 10:50:06 +08:00
ca -> client_ca -> client
如果用 ca.crt 的话,就是 2 层验证,也就是 ssl_verify_depth 2; 。 |
14
Hardrain 2018-08-01 10:53:10 +08:00 1
用于 SSL 双向认证的 CA 证书不需要也不应该是一个商业 CA。
|
15
Hardrain 2018-08-01 11:09:26 +08:00 1
ssl_client_certificate file;
ssl_verify_client on | off | optional | optional_no_ca; ssl_verify_depth number; 你只需要关注以上三行 其中第三行的解释 (用于客户端验证的,下同)根 CA ------第 0 层 | |_____中间 CA(a)-------第 1 层 | | | |________用户 A 的证书----第 2 层 | |________用户 B 的证书----第 2 层 |_____用户 C 的证书----第 1 层 如果你把 depth 设为 1,只有 C 的证书会被信任;如果设成 2,所有三个用户的证书都被信任。 如果设成 0,则需要将根 CA 换成(唯一的)被信任的用户证书,且只有这个用户被信任。 一般地,如果证书的拓扑结构不是很复杂(压根没有中间 CA),设为 1 即可。 |
16
Hardrain 2018-08-01 11:10:23 +08:00
用 OpenSSL 管理 CA,可参考 https://jamielinux.com/docs/openssl-certificate-authority/
|
17
xudzhang OP @Hardrain 感谢!根据你画的图,其实我的情况是这样的,我的 ca.crt 是第 0 层,然后 client 那边的证书都是 ca.crt 签发的,那其实理论上我只要把 ssl_verify_depth 设置成 1 应该就能 work。但实际上,Nginx 的 error log 里提示 client SSL certificate verify error: (7:certificate signature failure),相关的 verify 的 log 如下,大佬能不能帮忙看看什么情况?
2018/08/01 02:52:56 [debug] 6024#0: *9450 verify:1, error:0, depth:1, subject:"/C=CN/ST=Fujian/L=Xiamen/O=Yealink Network Technology Co.,Ltd./OU=yealink.com/CN=Yealink Equipment Issuing CA/[email protected]", issuer:"/C=CN/ST=Fujian/L=Xiamen/O=Yealink Network Technology Co.,Ltd./OU=yealink.com/CN=Yealink Equipment Issuing CA/[email protected]" 2018/08/01 02:52:56 [debug] 6024#0: *9450 verify:0, error:7, depth:0, subject:"/C=CN/ST=Fujian/L=Xiamen/O=Yealink Network Technology Co.,Ltd./OU=Yealink Equipment/CN=$mac/[email protected]", issuer:"/C=CN/ST=Fujian/L=Xiamen/O=Yealink Network Technology Co.,Ltd./OU=yealink.com/CN=Yealink Equipment Issuing CA/[email protected]" 2018/08/01 02:52:56 [debug] 6024#0: *9450 verify:1, error:7, depth:0, subject:"/C=CN/ST=Fujian/L=Xiamen/O=Yealink Network Technology Co.,Ltd./OU=Yealink Equipment/CN=$mac/[email protected]", issuer:"/C=CN/ST=Fujian/L=Xiamen/O=Yealink Network Technology Co.,Ltd./OU=yealink.com/CN=Yealink Equipment Issuing CA/[email protected]" |
18
virusdefender 2018-08-01 11:53:19 +08:00
我开始文件有手动重命名的,重发一下
openssl genrsa -out ca.key 4096 openssl req -new -x509 -nodes -sha256 -subj "$subj/CN=Test Root CA" -days 3650 -key ca.key -out ca.crt openssl genrsa -out client.key 4096 openssl req -new -key client.key -out client.csr -subj "/CN=Cert Test" openssl x509 -req -days 3650 -extfile <(printf "keyUsage=digitalSignature") -in client.csr -CA ca.crt -CAkey ca.key -set_serial 1234 -out client.crt openssl pkcs12 -export -in client.crt -inkey client.key -name "Admin Cert" -out client.p12 -password pass:123456 ssl_client_certificate /ssl/ca.crt; ssl_verify_client on; 其实不存在 client_ca.crt 的 |
19
msg7086 2018-08-01 13:24:50 +08:00
yum 安装的 openssl ?
certificate signature failure ? 我先猜个:sha256 你的 openssl 太老了不支持。 你是啥版本的 openssl ?啥版本的发行版?啥版本的 nginx ? |
22
Hardrain 2018-08-01 21:46:36 +08:00
@xudzhang 很抱歉,我恐怕很难透过这些信息提供帮助
我检索了 nginx+{错误信息中的数字*}(其余的信息似乎都是 x.509 证书的一些字段),但无法找到任何有帮助的结果。 客户端有什么错误出现? 你可以尝试从客户端 /服务器抓一下包吗? *:debug 6024|9450|error:7 等 |
23
Hardrain 2018-08-01 21:53:16 +08:00 1
@xudzhang
检索 openssl 和 error 7 得到一结果,或有帮助: https://serverfault.com/questions/653144/openssl-verify-error-7-at-1-depth-lookupcertificate-signature-failure 从这篇问答来看似乎是用户证书签名问题。 使用`openssl x509 -in {path_to_client_cert} -noout -text`看一下客户端证书所用签名算法。 另外,用`openssl verify -CAfile {path_to_client_verify_ca} {path_to_client_cert}`测试下签发的证书有无问题。 |
24
xudzhang OP @Hardrain 找到 root cause 了,是 openssl 版本的问题,client 使用的签名算法在高版本中的 openssl 已经废弃……
|
25
xierch 2018-08-02 12:09:03 +08:00
> ssl_client_certificate specifies a file with trusted CA certificates in the PEM format used to verify.
他其实是说,你需要指定一个证书作为 trusted CA … 然后这个 trusted CA 用 ssl_client_certificate 来指定… |
26
owt5008137 2018-08-02 13:39:01 +08:00 via Android
@xudzhang 我贴的地址里有两个文件。一个是执行脚本的.sh 另一个就是 openssl.cnf
|