当前位置:  开发笔记 > 后端 > 正文

由中间CA(链)签名的NGinx SSL证书认证

如何解决《由中间CA(链)签名的NGinxSSL证书认证》经验,为你挑选了2个好方法。

我试图在nginx中启用客户端证书身份验证,其中证书已由中间CA签名.使用由自签名根CA签名的证书时,我能够正常工作; 但是,当签名CA是中间CA时,这不起作用.

我的简单服务器部分如下所示:

server {
    listen       443;
    server_name  _;

    ssl                  on;
    ssl_certificate      cert.pem;
    ssl_certificate_key  cert.key;

    ssl_session_timeout  5m;

    ssl_protocols  SSLv2 SSLv3 TLSv1;
    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    ssl_prefer_server_ciphers   on;

    ssl_client_certificate ca.pem;
    ssl_verify_client on;
    ssl_verify_depth 1;

    location / {
        root   html;
        index  index.html index.htm;
    }
}

对于ca.pem的内容,我尝试过使用中间CA并连接中间CA证书和根CA证书,例如:

cp intermediate.crt ca.pem
cat root.crt >> ca.pem

我还验证了在使用相同的CA链时,从openssl的角度来看证书是有效的:

openssl verify -CAfile /etc/nginx/ca.pem certs/client.crt 
certs/client.crt: OK

我已经尝试将ssl_verify_depth显式设置为1(如上所述)然后甚至为0(不确定该数字的确切含义),但仍然会得到相同的错误.

我在中间CA的所有变体中得到的错误是"400 Bad Request",更具体地说是"SSL证书错误"(不确定这意味着什么).

也许nginx只是不支持中间证书的证书链?任何帮助非常感谢!



1> Jack..:

编辑:我也有这个"问题",解决方案和解释是在文本的底部.

似乎nginx不支持中间证书.我的证书是自己创建的:(RootCA是自签名的,IntrermediateCA1是由RootCA签名的,等等)

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

我想在nginx"IntermediateCA1"中使用,只允许访问"Client1"证书的所有者.

当我使用IntermediateCA1和RootCA设置"ssl_client_certificate"文件并设置"ssl_verify_depth 2"(或更多)时,客户端可以使用证书Client1和Client2(仅应该是Client1)登录到站点.同样的结果是当我只使用RootCA放入"ssl_client_certificate"文件时- 两个客户端都可以登录.

当我只使用IntermediateCA1放入"ssl_client_certificate"文件,并设置"ssl_verify_depth 1"(或"2"或更多 - 无论如何)时,登录是不可能的,我得到错误400.在调试模式下,我看到日志:

verify:0, error:20, depth:1, subject:"/C=PL/CN=IntermediateCA1/emailAddress=cert@asdf.com",issuer: "/C=PL/CN=RootCA/emailAddress=cert@asdf.com"
verify:0, error:27, depth:1, subject:"/C=PL/CN=IntermediateCA1/emailAddress=cert@asdf.com",issuer: "/C=PL/CN=RootCA/emailAddress=cert@asdf.com"
verify:1, error:27, depth:0, subject:"/C=PL/CN=Client1/emailAddress=cert@asdf.com",issuer: "/C=PL/CN=IntermediateCA1/emailAddress=cert@asdf.com"
(..)
client SSL certificate verify error: (27:certificate not trusted) while reading client request headers, (..)

我觉得这是一个错误.在Ubuntu上测试,nginx 1.1.19和1.2.7-1~dotdeb.1,openssl 1.0.1.我看到nginx 1.3有更多关于使用客户端证书的选项,但我们没有看到解决这个问题的方法.

目前,分离客户端1和2的唯一方法是创建两个自签名的RootCAs,但这只是解决方法.

编辑1: 我在这里报告了这个问题:http://trac.nginx.org/nginx/ticket/301

编辑2" *好的,这不是错误,它是功能;)*

我在这里得到回复:http ://trac.nginx.org/nginx/ticket/301 它正在运行,你必须只检查你的ssl_client_i_dn是什么(.你可以使用证书主题,或者你想要的东西,而不是发行者http://wiki.nginx.org/HttpSslModule#Built-in_variables

这是证书验证的工作原理:证书必须经过验证,最多可以验证到受信任的根.如果无法将链构建到受信任的根(非中间),则验证失败.如果您信任root,则将成功验证由其直接或间接签署的所有证书.

如果要将客户端证书限制为仅直接颁发的证书,则可以使用限制验证深度,但它更多的是关于DoS预防,显然它不能用于将verificate限制为仅限于中间1(而不是中间2).

你想要的是一些基于验证结果的授权层 - 即你可能想检查客户的证书发行者是否为中间1.如果发行人的DN与允许的DN不匹配,最简单的解决方案是拒绝请求,例如像这样(完全未经测试):

[由我编辑,它在我的配置中正常工作]

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;
    }
}


要确定客户端证书的颁发者DN,请使用以下命令:`openssl x509 -noout -in -issuer`
我认为中间证书的存在理由是它们可以被撤销(而根目录,仅用于签署中间证书)可以得到更好的保护,有时仅用于气隙系统或通过硬件安全模块).那么如何使用这个Nginx设置来执行中间证书撤销?ssl_crl参数仅用于客户端证书本身.

2> Andrew D...:

你试过增加ssl_verify_depth指令吗?文件说:

(it) sets a verification depth in the client certificates chain.

但你的验证深度是1.你说:

我已经尝试将ssl_verify_depth显式设置为1(如上所述)然后甚至为0(不确定该数字的确切含义),但仍然会得到相同的错误.

所以,试试2或3 ..

PS: 在我发现提到这个问题的任何地方,它被告知将中间CA证书与您的服务器证书结合起来.到了一个文件(正如@ vikas-nalwar所建议你做的那样)按照验证顺序(但我不确定订单是否重要)并粗略地说是设置ssl_verify_depth为捆绑中的证书数量.

推荐阅读
sx-March23
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有