Authentication 中间CA签署的NGinx SSL证书身份验证(链)

Authentication 中间CA签署的NGinx SSL证书身份验证(链),authentication,ssl,nginx,ssl-certificate,Authentication,Ssl,Nginx,Ssl Certificate,我正在尝试在nginx中启用客户端证书身份验证,其中证书已由中间CA签名。当使用由自签名根CA签名的证书时,我能够很好地实现这一点;但是,当签名CA是中间CA时,这不起作用 我的简单服务器部分如下所示: server { listen 443; server_name _; ssl on; ssl_certificate cert.pem; ssl_certificate_key cert.ke

我正在尝试在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\u verify\u depth显式设置为1(如上所述),然后甚至设置为0(不确定该数字的确切含义),但仍然会得到相同的错误

我在intermed CA的所有变体中得到的错误是“400错误请求”,更具体地说是“SSL证书错误”(不确定这到底意味着什么)

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

更新: 我相信您希望在服务器端启用客户端验证。如果是这样,请正确创建证书链。按完全相同的顺序尝试以下操作。使用certchain.pem

  cat intermediate.crt >> certchain.pem
  cat root.crt >> certchain.pem

您是否尝试过增加
ssl\u verify\u depth
指令?说:

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

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

所以,试试2或3

附言:
无论我在哪里发现这个问题,都会告诉我将中间CA证书与您的服务器证书合并到一个文件中(正如您所做的那样),以便进行验证(但我不确定顺序是否重要),粗略地说,将
ssl\u verify\u depth
设置为捆绑包中的证书数。

编辑:我也有这个“问题”,解决方案和解释位于文本底部

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

我想在nginx中使用“IntermediateCA1”,只允许“Client1”证书的所有者访问站点

当我将IntermediateC1和RootCA放入“ssl\u客户端\u证书”文件,并设置“ssl\u验证\u深度2”(或更多)时,客户端可以使用证书客户端1和客户端2登录到站点(应仅使用客户端1)。 同样的结果是,当我将放入“ssl\u客户端\u证书”文件时,只有RootCA——两个客户端都可以登录

当我将“ssl\U客户端\U证书”文件设置为仅包含中间版本1,并设置“ssl\U验证\U深度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上测试。 我看到nginx1.3在使用客户端证书方面没有更多的选择,但我看不到这个问题的解决方案

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

编辑1: 我在这里报告了这个问题:

编辑2“ *好的,这不是bug,而是特性;)*

我在这里得到回应: 它正在工作,您只需检查您的ssl_客户端_i_dn是什么。您还可以使用证书的主题,或者您想要从中获取什么,而不是使用颁发者

这就是证书验证的工作原理:证书必须是 已验证到受信任的根目录。如果无法将链构建到受信任的根目录 根(非中间)-验证失败。如果信任根-所有 由其直接或间接签署的证书将 已成功验证

如果需要,可以使用限制验证深度 要将客户端证书限制为直接颁发的证书吗 只是,但更多的是关于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;
    }
}

另一种简单的方法是将证书(包括域证书)连接到一个文件中,并在服务器和nginx conf文件上使用该文件

cat www.example.com.crt bundle.crt>www.example.com.chained.crt

始终记住首先使用服务器证书,然后仅使用CA服务器证书


当我在使用nginx和cloudflare时,您可以阅读更多关于at的信息,
这些台词对我起了作用:

ssl_client_certificate    /etc/nginx/ssl/ca-bundle-client.crt;  
ssl_verify_client optional_no_ca;  
ssl_verify_depth 2;

带有可选\u no\u ca的第二行是重要的部分

我不得不说,它在
nginx/1.13.2
中工作得很好,即

  • 我有一个根CA,它签署了两个中间CA
  • 两个中间人各自签署了一份客户协议
  • 我喜欢这样的证书
    cat client-intermediate1.crt ca-client.crt>ca.chained1.crt
    cat client-intermediate2.crt ca-client.crt>ca.chained2.crt
    cat ca.chained1.crt ca.chained2.crt>ca.multiple.intermediate.crt

  • 如果我只将ca.chained1.crt设置为
    ssl\u client\u certificate
    ,则只有client1.crt可以连接,同样地,对于ca.chained2.crt/client2.crt也是如此

  • 当我使用
    ca.multiple.intermediate.crt
    时,两个客户端都可以连接
要撤销中间版本,只需从ca.multiple.intermediate.crt中删除证书链

这是rele
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;
    }
}
ssl_client_certificate    /etc/nginx/ssl/ca-bundle-client.crt;  
ssl_verify_client optional_no_ca;  
ssl_verify_depth 2;
# minimum settings for ssl client auth 
ssl_client_certificate /etc/ssl/ca.multiple.intermediate.crt;
ssl_verify_client on;
ssl_verify_depth 2;

# ssl high security settings (as of writing this post)
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
# parse out CN
map $ssl_client_s_dn $ssl_client_s_dn_cn {
    default "should_not_happen";
    ~CN=(?<CN>[^,]+) $CN;
}
# add headers for backend containing SSL DN/CN
add_header X-SSL-client-s-dn $ssl_client_s_dn;
add_header X-SSL-client-s-dn_cn $ssl_client_s_dn_cn;
'$ openssl s_client -connect www.godaddy.com:443
Certificate chain
 0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US
     /1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc
     /OU=MIS Department/CN=www.GoDaddy.com
     /serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b)
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
     /OU=http://certificates.godaddy.com/repository
     /CN=Go Daddy Secure Certification Authority
     /serialNumber=07969287
   i:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
 2 s:/C=US/O=The Go Daddy Group, Inc.
     /OU=Go Daddy Class 2 Certification Authority
   i:/L=ValiCert Validation Network/O=ValiCert, Inc.
     /OU=ValiCert Class 2 Policy Validation Authority
     /CN=http://www.valicert.com//emailAddress=info@valicert.com'
ssl_client_certificate     /etc/nginx/ssl/ca-bundle-for-client-selection-filtering.crt;
ssl_trusted_certificate    /etc/nginx/ssl/ca-bundle-for-client-cert-valdiation.crt;