由中间CA(链)签名的NGinx SSL证书认证 [英] NGinx SSL certificate authentication signed by intermediate CA (chain)

查看:31
本文介绍了由中间CA(链)签名的NGinx SSL证书认证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to enable client certificate authentication in nginx where the certificates have been signed by an intermediate CA. I am able to get this working fine when using a certificate signed by a self-signed root CA; however, this does not work when the signing CA is an intermediate CA.

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

My simple server section looks like this:

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 证书连接起来,例如:

For the contents of ca.pem, I have tried using only the intermediate CA and also concatenating the intermediate CA cert and the root CA cert, i.e. something like:

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

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

I have also validated that the certificate is valid from openssl's perspective when using that same CA chain:

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

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

I have experimented with setting ssl_verify_depth explicitly to 1 (as above) and then even 0 (not sure what that number means exactly), but still get same error.

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

The error I get in all variants of the intermed CA is "400 Bad Request" and more specifically "The SSL certificate error" (not sure what that means exactly).

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

Maybe nginx just doesn't support cert chains for intermediate certs? Any help greatly appreciated!

推荐答案

我也遇到过这个问题",解决方案和解释在文末.

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

It seemed like nginx doesn't support intermediate certificates. My certs self created: (RootCA is selfsigned, IntrermediateCA1 is signed by RootCA, etc.)

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

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

I want to use in nginx "IntermediateCA1", to allow access to site only to owner of the "Client1" certificate.

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

When I put to "ssl_client_certificate" file with IntermediateCA1 and RootCA, and set "ssl_verify_depth 2" (or more) , clients can login to site both using certificate Client1 and Client2 (should only Client1). The same result is when I put to "ssl_client_certificate" file with only RootCA - both clients can login.

当我将 IntermediateCA1 放入ssl_client_certificate"文件并设置ssl_verify_depth 1"(或2"或更多 - 无论如何)时,无法登录,我收到错误400. 在调试模式下,我看到了日志:

When I put to "ssl_client_certificate" file with only IntermediateCA1, and set "ssl_verify_depth 1" (or "2" or more - no matter) , it is imposible to log in, I get error 400. And in debug mode i see logs:

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 关于使用客户端证书的选项很少,但我没有看到解决此问题的方法.

I thing this is a bug. Tested on Ubuntu, nginx 1.1.19 and 1.2.7-1~dotdeb.1, openssl 1.0.1. I see that nginx 1.3 has few more options about using client certificates, but I'dont see solution to this problem.

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

Currently, the only one way to separate clients 1 and 2 is to create two, selfsigned RootCAs, but this is only workaround..

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

Edit 1: I've reported this issue here: 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

I get response here: http://trac.nginx.org/nginx/ticket/301 It is working, you must only check what your ssl_client_i_dn is (. Instead of issuer you can use also subject of certificate, or what you want from http://wiki.nginx.org/HttpSslModule#Built-in_variables

这是证书验证的工作原理:证书必须是验证到受信任的根.如果无法将链构建到受信任的根(非中间) - 验证失败.如果您信任 root - all由它直接或间接签署的证书将被成功验证.

This is how certificate verification works: certificate must be verified up to a trusted root. If chain can't be built to a trusted root (not intermediate) - verification fails. If you trust root - all certificates signed by it, directly or indirectly, will be successfully verified.

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

Limiting verification depth may be used if you want to limit client certificates to a directly issued certificates only, but it's more about DoS prevention, and obviously it can't be used to limit verificate to intermediate1 only (but not intermediate2).

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

What you want here is some authorization layer based on the verification result - i.e. you may want to check that client's certificate issuer is intermediate1. Simplest solution would be to reject requests if issuer's DN doesn't match one allowed, e.g. something like this (completely untested):

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

[ Edit by me, it is working correctly in my configuration ]

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

这篇关于由中间CA(链)签名的NGinx SSL证书认证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆