配置 SSL 相互(双向)身份验证

信息安全 tls 验证 linux 证书颁发机构
2021-09-08 08:27:18

很多教程,很多页面,很多问题,它们在这个问题“配置 SSL 相互(双向)身份验证”的实现方面有所不同。我必须用 Linux 来做,我不知道从哪里开始或遵循什么指令。

我要做的是:

  • 我有一个服务器和许多客户端,只有当他们有来自服务器的签名证书时,他们才能访问服务器上的代码。
  • 服务器可以生成这些证书并禁用它们主服务器将是 CA .. 这意味着它必须为其他人生成证书然后对其进行签名。

我已经想好该怎么做

  1. 生成 CA 证书
  2. 为其他用户生成证书。
  3. 给用户颁发证书。
  4. 签署证书。
  5. 验证证书。
  6. 为用户或禁用重新生成证书。
  7. 用户只能从一台设备上签名。(证书不得复制)

我错过了什么吗?我必须是 root 用户吗?有没有为此准备好的bash?我在哪里可以找到它。为什么在 linux 上有多个 openssl.cnf 文件?我应该把 CA 证书放在哪里,任何信息都将不胜感激。

1个回答

与 openssl 一起分发了一个方便的脚本,CA.sh可以完成大部分工作。它的位置是特定于分布的。在 Debian 及其衍生版本中,您可以使用以下命令找到它:

# apt-file search CA.sh
openssl: /usr/lib/ssl/misc/CA.sh

RedHat 及其衍生产品的(近似)等价物是:

# yum provides */CA
1:openssl-1.0.1e-4.fc18.x86_64 : Utilities from the general purpose cryptography library with TLS implementation
Repo        : @updates
Matched from:
Filename    : /etc/pki/tls/misc/CA

这是一个非常简单的 bash 脚本,它简化了管理 CA 所需的目录结构的创建(这在[ CA_default ]openssl.cnf 部分中进行了描述)。我建议您使用它并查看代码以了解它实际在做什么。

# ./CA.sh -help
usage: ./CA.sh -newcert|-newreq|-newreq-nodes|-newca|-sign|-verify

此脚本将使用 openssl.cnf 中提供的默认值,和/或您可以提供一个配置文件作为参数,如果不openssl $command使用. 文件的位置也是特定于发行版的,您可以使用上述相同的命令来查找它。您想要的是包装提供的那个。-configCA.shopenssl.cnfopenssl

您可能想要修改以下部分:

[ CA_default ]
default_days    = 365                   # how long to certify for
default_crl_days= 30                    # how long before next CRL

[ req ]
default_bits            = 2048

[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = AU
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Some-State
localityName                    = Locality Name (eg, city)
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = Internet Widgits Pty Ltd
#1.organizationName             = Second Organization Name (eg, company)
#1.organizationName_default     = World Wide Web Pty Ltd
organizationalUnitName          = Organizational Unit Name (eg, section)
#organizationalUnitName_default =
commonName                      = Common Name (e.g. server FQDN or YOUR name)
commonName_max                  = 64
emailAddress                    = Email Address
emailAddress_max                = 64
  • 生成 CA

一旦您openssl.cnf根据需要进行了编辑,您就可以生成 CA 证书。根据您是否需要此 CA 由公认的第三方 CA 签名,您可以生成自签名 CA 或 CSR 提交以供签名。

./CA.sh -newca

系统会以交互方式提示您提出一些问题,默认值将出现在方括号之间。您将在openssl.cnf此处识别您修改的选项。

  • 为服务器生成证书

您可以使用相同的脚本为服务器创建证书请求:

./CA.sh -newreq

再次,会提示你问几个问题,最重要的是证书的通用名称,它必须与服务器 IP 的 DNS 可解析名称匹配(或者你可以使用其他方式,例如/etc/hosts,不推荐,很难维护和扩展)

您将获得的是证书签名请求(简称 CSR)。这将由您之前创建的证书颁发机构 (CA) 签名。

./CA.sh -sign

  • 为客户端生成证书

重复创建 CSR 并让 CA 签署的步骤。执行此操作时,请密切注意如何填写 Common Name、Organization 和 Organizational Unit 字段,因为之后需要这些字段才能配置服务器。

将客户端证书与各自的私钥和 CA 证书一起分发的一种巧妙方法是使用 p12 捆绑包:

openssl pkcs12 -export -in Certificates/client.pem -inkey client.key -certfile CA.pem -out clientcert.p12

  • 配置服务器

假设您所指的服务器是 Apache Web 服务器。获得服务器证书后,您可以配置适当VHOST的服务以提供将受相互 SSL 身份验证保护的任何内容。一个例子可能是这个phpmyadmin虚拟主机。这是在 Apache 2.4 服务器中运行的,因此请不要按原样使用它,并仔细检查和测试它以使其适应您的需求。

Listen                   443 https

<VirtualHost 120.120.120.120:443>
  DocumentRoot           "/srv/www/html"
  ServerAdmin            admin@company.com
  SSLCACertificateFile   /etc/pki/CA/cacert.pem
  SSLCertificateFile     /etc/pki/tls/private/phpmyadmin.company.com/newcert.pem
  SSLCertificateKeyFile  /etc/pki/tls/private/phpmyadmin.company.com/newkey.pem
  SSLCARevocationCheck   chain
  SSLCARevocationFile    /etc/pki/CA/crl/crl.pem
  SSLEngine              on
  SSLStrictSNIVHostCheck on
  SSLVerifyClient        require
  SSLVerifyDepth         5
  ServerName             phpmyadmin.company.com
  RewriteEngine          on
  RewriteCond            %{REMOTE_ADDR} !^127\.0\.0\.1$
  RewriteCond            %{HTTPS} !=on
  RewriteRule            . - [F]
  Alias                  /console /usr/share/phpMyAdmin
  ErrorLog               "|/usr/sbin/rotatelogs -L /var/log/httpd/phpmyadmin/error.log -f /var/log/httpd/phpmyadmin/error.log.%Y%m%d 86400"
  CustomLog              "|/usr/sbin/rotatelogs -L /var/log/httpd/phpmyadmin/access.log -f /var/log/httpd/phpmyadmin/access.log.%Y%m%d 86400" logstash_json
  <Directory /usr/share/phpMyAdmin/>
    Require              ssl
    Require              ssl-verify-client
    SSLRequireSSL
    SSLOptions           +FakeBasicAuth +StrictRequire
    SSLRequire           %{SSL_CIPHER_USEKEYSIZE} >= 256
    SSLRequire           %{SSL_CLIENT_S_DN_O} eq "Awesome Company" \
                     and %{SSL_CLIENT_S_DN_OU} eq "Development" \
                     and %{SSL_CLIENT_S_DN_CN} in {"John Doe", "Jane Doe"}
    SSLRenegBufferSize   131072
  </Directory>
</VirtualHost>

您可以根据需要使用尽可能多的每个目录访问控制,重要的是显示的客户端证书必须符合SSLRequire指令施加的限制,即它们必须匹配组织、组织单元和通用名称条件(或其他您认为合适的证书字段)。这些字段取自客户端证书。

  • 生成证书吊销列表

为了能够撤销对客户端证书的访问,您需要生成一个 CRL。执行此操作的命令(在 CA 目录结构的顶部提供):

openssl ca -config /path/to/openssl.cnf -gencrl -out crl/crl.pem

之后,您可以根据需要使用以下方法撤销客户端证书:

openssl ca -config /path/to/openssl.cnf -revoke clientcert.pem

参考:

OpenSSL在线文档和Apache在线文档。