![我如何告诉 Apache 强制客户端身份验证,但根据受信任的证书列表而不是 CA 进行授权?](https://linux22.com/image/520013/%E6%88%91%E5%A6%82%E4%BD%95%E5%91%8A%E8%AF%89%20Apache%20%E5%BC%BA%E5%88%B6%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81%EF%BC%8C%E4%BD%86%E6%A0%B9%E6%8D%AE%E5%8F%97%E4%BF%A1%E4%BB%BB%E7%9A%84%E8%AF%81%E4%B9%A6%E5%88%97%E8%A1%A8%E8%80%8C%E4%B8%8D%E6%98%AF%20CA%20%E8%BF%9B%E8%A1%8C%E6%8E%88%E6%9D%83%EF%BC%9F.png)
我正在尝试创建一个 Apache SSL 服务器,用于预生产测试,即使在生产中也只有不到 5 个左右的用户访问。由于用户群较小,我认为管理证书的最简单方法就是自行签名,然后明确告诉 Apache 只信任我们创建的少数证书。据我所知,Apache 似乎需要一个 CA,但我希望有办法解决这个问题。
此外,就开发而言,我倾向于了解我的东西,但作为系统管理员,我还是个新手,所以解决方案越简单越好。
顺便说一句,我还看到了这篇文章:这里我认为这与我所问的问题类似,但不是我想要的解决方案。理想情况下,我可以使用 openSSL 动态生成自签名证书,并将它们副本添加到目录中,这样当它们用于访问服务器时,Apache 就会创建连接。
答案1
你需要做两件事。
首先,您需要为要连接的浏览器生成证书。
然后,您需要设置 Apache 以要求某些文件夹使用这些证书。
apache 部分很简单 - 只需将其添加到您的 /etc/apache2/sites-enabled/your_apache_file.conf:
<Location /path/to/folder>
SSLVerifyClient require
SSLVerifyDepth 1
</Location>
现在假设您已经像这样设置了 apache SSL:
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/server.crt
SSLCertificateKeyFile /etc/apache2/ssl/server.key
SSLCACertificateFile /etc/apache2/ssl/ca.crt
SSLVerifyClient optional
SSLOptions +StdEnvVars +ExportCertData
您还需要将自己设置为 CA。
这是我们用于生成客户端证书的一段 Python 代码 - 这应该可以让您很好地了解从这里需要做什么:
commonname = "name_of_client_machine"
serial_file = open('/usr/local/my/web/certs/ca.srl','r')
serial = serial_file.read().strip()
cert_folder = '/usr/local/my/web/certs/clients/%s_%s' % (serial,commonname)
try:
os.makedirs(cert_folder, 0755)
except OSError:
pass
commands.getstatusoutput("sed s/hostname/%s/ /usr/local/my/web/certs/client.tpl > %s/client.tpl" % (commonname,cert_folder))
commands.getstatusoutput("openssl genrsa -des3 -passout pass:mypassword -out %s/web_client.key 4096" % cert_folder)
commands.getstatusoutput("openssl req -new -key %(cert_folder)s/web_client.key -out %(cert_folder)s/web_client.csr -config %(cert_folder)s/client.tpl -passin pass:mypassword" % ({'cert_folder':cert_folder}))
commands.getstatusoutput("openssl x509 -req -days 3650 -in %(cert_folder)s/web_client.csr -CA /usr/local/my/web/certs/ca.crt -CAkey /usr/local/my/web/certs/ca.key -out %(cert_folder)s/web_client.crt -passin pass:mypassword" % ({'cert_folder':cert_folder}))
commands.getstatusoutput("openssl pkcs12 -export -clcerts -in %(cert_folder)s/web_client.crt -inkey %(cert_folder)s/web_client.key -out %(cert_folder)s/web_client.P12 -passin pass:mypassword -passout pass:mypassword" % ({'cert_folder':cert_folder}))
现在,您将获取 .p12 文件并将其导入到客户端浏览器。系统将要求您输入密码(上面的密码为“mypassword”),然后系统将安装并准备就绪。
答案2
经过一番努力,我们终于找到了解决方案。虽然不是非常理想,但现在看来效果不错。
在 Apache 中,我们首先必须启用 mod_ssl,要求客户端身份验证,然后将验证深度设置为 1。然后我们必须将服务器证书和密钥设置为由我们的 CA 生成和签名的内容(我稍后会讲到这一点),并将 SSLCACertificateFile 设置为我们的 CA 证书。在创建 CA 时,这指南非常详尽,我发现它非常准确。除了稍微修改一些目录路径以使其与 Ubuntu 兼容(即使用 /etc/ssl)之外,它运行良好。我们创建了一个 CA,然后生成了一个 CA 证书。然后,我们生成了一个服务器密钥和服务器证书请求,并使用 CA 对该请求进行了签名。然后,我们将 Apache 设置为使用新的服务器证书和密钥。此时,您可以执行服务器身份验证,但不能执行客户端身份验证。为了完成后面的部分,我们只是基于上面链接中的一些示例。创建/签署证书密钥组合的过程是通用的,即您可以在服务器或客户端上使用该组合。因此,我们只需重复该过程即可创建客户端证书(并且可以反复执行以创建更多证书)。一旦我们有了证书,我们就将这两个文件转换为 .pk12
# openssl pkcs12 -export -in certs/client.crt -inkey private/client.key -out ~/clientcred.p12
最后,我们将证书导入 Firefox 以供使用。我们还将新 CA 添加到 Firefox 的内部受信任 CA 列表中。希望这对尝试类似操作的其他人有所帮助。