Nginx 怎么使用不被信任的 CA 验证客户端证书?

2018-08-01 09:59:01 +08:00
 xudzhang

下面的配置里,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;
}
6212 次点击
所在节点    NGINX
26 条回复
virusdefender
2018-08-01 10:05:55 +08:00
client_certificate 不需要是可信 ca,你的可能是其他错误导致的,比如客户端证书导出的不太对?
xudzhang
2018-08-01 10:08:44 +08:00
@virusdefender Nginx 的官方文档这样说的:"ssl_client_certificate specifies a file with trusted CA certificates in the PEM format used to verify",这个的意思是不是说我的 ca.crt 必须是 trusted ?
virusdefender
2018-08-01 10:15:06 +08:00
@xudzhang #2 我一直是用的自签名的 ca,然后导出的客户端证书啊,正常用,稍等我看下导出证书的脚本。
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.
owt5008137
2018-08-01 10:29:34 +08:00
@virusdefender 我以前也自己签,写了个写脚本改 openssl.cnf 文件里的配置就成。
https://github.com/owent-utils/bash-shell/tree/master/Others/x509_ssl_cert

但是现在有 let's encrypt
xudzhang
2018-08-01 10:32:01 +08:00
@virusdefender 这个 optional_no_ca 我昨天试了一下,好像不管用,看官方文档的意思,这个选项启用的时候会请求客户端证书但是不要求客户端证书是 trusted 的,但我这个情况其实是我自己的 ca.crt 是 untrusted,现在我就是没找到路子怎么让 Nginx 或者说让我的 Linux server 信任我的这个 ca.crt ,不知道我这么理解对不对?
xudzhang
2018-08-01 10:32:45 +08:00
@owt5008137 大佬,我的 openssl 好像是用 yum install 安装的,能不能指教一下你说的这个 cnf 配置在哪里?我找了一下没找到~
Zakun
2018-08-01 10:35:39 +08:00
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;
```
SirLostWhite
2018-08-01 10:35:50 +08:00
可以用 certbot 自动配置 letsencrypt 证书
全自动的
xudzhang
2018-08-01 10:39:07 +08:00
@Zakun 这个字段之前试过,我加了 ssl_trusted_certificate ca.crt 的配置,并没什么用啊……
xudzhang
2018-08-01 10:41:39 +08:00
@virusdefender 理解一下,在你这个例子里,你用 ca 签发了 client_ca,那为什么你的 ssl_client_certificate 里配的是 client_ca.crt 而不是 ca.crt ?
msg7086
2018-08-01 10:50:06 +08:00
ca -> client_ca -> client
如果用 ca.crt 的话,就是 2 层验证,也就是 ssl_verify_depth 2; 。
Hardrain
2018-08-01 10:53:10 +08:00
用于 SSL 双向认证的 CA 证书不需要也不应该是一个商业 CA。
Hardrain
2018-08-01 11:09:26 +08:00
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 即可。
Hardrain
2018-08-01 11:10:23 +08:00
xudzhang
2018-08-01 11:17:52 +08:00
@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/emailAddress=support@yealink.com", issuer:"/C=CN/ST=Fujian/L=Xiamen/O=Yealink Network Technology Co.,Ltd./OU=yealink.com/CN=Yealink Equipment Issuing CA/emailAddress=support@yealink.com"

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/emailAddress=support@yealink.com", issuer:"/C=CN/ST=Fujian/L=Xiamen/O=Yealink Network Technology Co.,Ltd./OU=yealink.com/CN=Yealink Equipment Issuing CA/emailAddress=support@yealink.com"

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/emailAddress=support@yealink.com", issuer:"/C=CN/ST=Fujian/L=Xiamen/O=Yealink Network Technology Co.,Ltd./OU=yealink.com/CN=Yealink Equipment Issuing CA/emailAddress=support@yealink.com"
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 的
msg7086
2018-08-01 13:24:50 +08:00
yum 安装的 openssl ?
certificate signature failure ?

我先猜个:sha256 你的 openssl 太老了不支持。
你是啥版本的 openssl ?啥版本的发行版?啥版本的 nginx ?
xudzhang
2018-08-01 13:58:31 +08:00
@msg7086 Openssl 版本是 1.0.2k-fips,Nginx 版本是 1.13.8 ……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/475834

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX