我按照 这篇博文,但当我用 测试它时curl
,nginx 的$ssl_client_verify
变量始终是NONE
。事实上,当我根本没有指定和选项curl
时,甚至不会给出不同的输出。就好像它忽略了我的证书。我该如何调试它?--cert
--key
我甚至尝试让所有这些地方都具有相同的值:
- CA 和服务器证书上的通用名称
- 服务器的主机名
- NginX 的虚拟主机名
- 服务器的反向 DNS 名称
答案1
如果您所说的 CA 和服务器证书中的“通用名称”是指整个主题名称(除了通用名称外,它还可以包含其他项目,尽管大多数人做这样的临时 SSL 证书时并不关心它们),那么就不要这样做。nginx 和 curl 都使用的 OpenSSL 不能将子证书链接到具有相同名称的父证书;这在 X.509 中不是正常情况,在其他软件中也可能无法处理,至少一般来说也是如此。
- CA 证书应该有一个作为主题(由于这是根,因此它自动也是颁发者,见下文)的名称,该名称是 CA 的名称——这不需要是域名,但如果您愿意也可以是域名。
- (SSL) 服务器请求和证书应将服务器的域名作为 Subject.CommonName,如果服务器有多个但密切相关的域名,则可以是通配符,或者如果全部客户端将通过地址进行访问(实际上,这只在客户端都是您非常亲密的同事或朋友时才有效)。服务器证书中的颁发者名称会自动设置为CA 名称。
- 类似地,每个客户端请求和证书都应具有与 CA 名称不同的主题名称,而颁发者则成为 CA 名称。如果您希望客户端证书能够安全地识别客户端(这大概是本练习的目的),则每个客户端证书都应具有与其他所有客户端证书不同的名称,最好与服务器证书不同,以避免混淆。
我相信这样应该可以。一个更基本、可能更好的测试工具是 openssl 命令行:
openssl s_client -connect $addr:$port -cert $clicert -key $clikey -CAfile $cacert
这将输出有关(尝试的)SSL/TLS 连接的详细信息。如果在接近末尾时显示 ,Acceptable client certificate CA names
后面跟着您的 CA 的正确名称,则服务器已正确设置客户端身份验证(以及基本 SSL)。如果它有其他名称,或显示No client certificate CA names sent
,则出现问题。s_client
等待输入时只需输入 EOF(Unix 通常为 ^D,Windows 为 ^Z)。
另外:该网站错误地称使用您自己创建的临时 CA 密钥和证书对服务器请求进行签名是“自签名”。自签名具体是指使用相同的密钥对对证书进行签名,其公共部分是在该证书中;实际上,这只用于顶级 CA,称为“根”。您正在使用自己的 CA 签署服务器证书,但您不是自签名。如果您想处理来自以下来源的连接,使用自己的 CA 签署服务器证书是不好的陌生人因为它无法像 Verisign 或 GoDaddy 等知名 CA 颁发的“商业”服务器证书那样向他们提供任何信任您服务器的证据。这通常是生产环境而非测试环境的情况,因为测试环境通常仅由开发人员和/或少数 beta 测试人员使用,但某些生产系统也可能仅限于少数密切相关的客户端。
编辑:获取由知名 CA 签名的临时 CA(用于客户端证书):这会很困难、成本昂贵,而且没有必要。
如果一个知名的 CA 给你一个“子 CA”或“中级 CA”证书,允许你颁发证书,那么他们就押注了他们的业务你的安全——因此你必须提供与他们同等级别的安全保障(定制硬件、专门的建筑、全天候武装警卫,多种的专门培训和认证的人员、定期的外部审计(所有这些都很昂贵)或者你必须买断他们的业务(这样他们就不再面临风险)。除了你的https://security.stackexchange.com/questions/25551/help-understanding-client-certificate-verification 看:
- 获取中级 SSL 证书
- https://security.stackexchange.com/questions/47267/can-i-buy-a-signing-valid-certificate-for-internal-use
- https://security.stackexchange.com/questions/61842/how-to-become-intermediate-certificate-authority
但是,唯一需要信任您向客户端颁发的证书的系统是您自己的服务器;只要您控制自己的服务器,只需将它们配置为信任您自己的 CA 证书。