如何在 Ubuntu 22.04 上搭建和配置证书颁发机构 (CA)

·

7 min read


介绍

证书颁发机构(CA)是一个负责为网上的主体颁发数字证书的实体。公共 CA 常用于确认公众服务如网站的身份,而私有 CA 则多用于私人服务和特定的用户群组。

构建自己的私有证书颁发机构可以让您配置、测试并运行需要客户端与服务器之间进行加密连接的应用程序。有了私有 CA,您可以为您的用户、服务器,或者您基础设施中的特定程序和服务颁发证书。

在 Linux 中使用私有 CA 的程序包括 OpenVPNPuppet 等。您还可以配置您的 Web 服务器,使用私有 CA 颁发的证书,使得开发和临时环境与使用 TLS 加密连接的生产环境保持一致。

在本指南里,您将会在一台 Ubuntu 22.04 服务器上搭建自己的私有证书颁发机构,并生成及签发一张测试用证书。您还会学习如何把 CA 服务器的公共证书导入操作系统的证书仓库中,以确认 CA 和远端服务器或用户间的信任链条。最后,您将了解如何撤销证书和分发证书撤销列表(CRL),确保只有经授权的用户和系统能够使用依靠您的 CA 的服务。

准备

为了完成本教程,您需要能够访问一个运行 Ubuntu 22.04 的服务器,用于托管您的 CA 服务器。在开始本指南之前,您必须配置一个非 root 用户,并赋予其 sudo 特权。您可以按照我们的 Ubuntu 22.04 初始服务器设置指南来创建一个具有适当权限的用户。链接的教程还将帮助您设置防火墙,在本指南的整个过程中我们将假定防火墙已经设置好。

在本教程中,我们将称此服务器为 CA 服务器

确保 CA 服务器是一个独立的系统。它仅用于导入、签发和撤销证书请求。它不应该运行任何其他服务,并且最好在您不与 CA 服务器进行互动时处于离线状态或完全关闭。

💡
注意:如果您想了解有关签发和撤销证书的信息,本教程的最后部分是可选的。如果您选择完成这些实践步骤,您将需要第二台 Ubuntu 22.04 服务器,或者您也可以使用您自己运行 Ubuntu、Debian 或者这两者派生的其他 Linux 计算机。

Step 1 — Installing Easy-RSA

本教程的第一个任务是在您的 CA 服务器上安装 easy-rsa 脚本集。easy-rsa 是一个证书颁发机构管理工具,您将使用它生成一个私钥和公共根证书,然后使用它来签署客户端和服务器的请求,这些请求将依赖于您的 CA。 请使用您在初始设置步骤中创建的非 root sudo 用户登录到您的 CA 服务器,并运行以下命令:

sudo apt update
sudo apt install easy-rsa

系统会提示您下载并安装该软件包。按下 y 确认您要安装该软件包。

此时,您已经设置好并准备好使用 Easy-RSA。在下一步中,您将创建一个公钥基础设施,并开始建立您的证书颁发机构。

Step 2 — Preparing a Public Key Infrastructure Directory

现在您已经安装了 easy-rsa,是时候在 CA 服务器上创建一个骨架式的公钥基础设施(PKI)了。确保您仍然以非 root 用户身份登录,并创建一个 easy-rsa 目录。请注意不要使用 sudo 运行以下任何命令,因为您的普通用户应该在没有提升权限的情况下管理和与 CA 进行交互。

mkdir ~/easy-rsa

这将在您的家目录中创建一个名为 easy-rsa 的新目录。我们将使用这个目录来创建符号链接,指向我们在前一步中安装的 easy-rsa 软件包文件。这些文件位于 CA 服务器上的 /usr/share/easy-rsa 文件夹中。

使用 ln 命令创建符号链接:

ln -s /usr/share/easy-rsa/* ~/easy-rsa/
💡
注意:尽管其他指南可能会指导您将 easy-rsa 软件包文件复制到您的 PKI 目录中,但本教程采用符号链接的方法。因此,任何对 easy-rsa 软件包的更新都将自动反映在您的 PKI 脚本中。

为了保护您的新 PKI 目录,确保只有所有者可以访问它,可以使用 chmod 命令进行设置:

chmod 700 /home/sammy/easy-rsa

最后,在 easy-rsa 目录中初始化 PKI:

cd ~/easy-rsa
./easyrsa init-pki
Output
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /home/sammy/easy-rsa/pki

完成本节后,您将拥有一个包含创建证书颁发机构所需的所有文件的目录。在下一节中,您将为您的 CA 创建私钥和公共证书。

Step 3 — Creating a Certificate Authority

在您可以创建 CA 的私钥和证书之前,您需要创建并填充一个名为 vars 的文件,其中包含一些默认值。首先,您将切换到 easy-rsa 目录,然后使用 nano 或您喜欢的文本编辑器创建和编辑 vars 文件:

cd ~/easy-rsa
nano vars

一旦文件打开,请粘贴以下行,并编辑每个突出显示的值,以反映您自己的组织信息。这里的重要部分是确保您没有留下任何值为空:

~/easy-rsa/vars
set_var EASYRSA_REQ_COUNTRY    "US"
set_var EASYRSA_REQ_PROVINCE   "NewYork"
set_var EASYRSA_REQ_CITY       "New York City"
set_var EASYRSA_REQ_ORG        "DigitalOcean"
set_var EASYRSA_REQ_EMAIL      "admin@example.com"
set_var EASYRSA_REQ_OU         "Community"
set_var EASYRSA_ALGO           "ec"
set_var EASYRSA_DIGEST         "sha512"

完成后,请保存并关闭文件。如果您使用的是 nano,您可以按下 CTRL+X,然后按 YENTER 以确认。现在,您已经准备好构建您的 CA。

要为您的证书颁发机构创建根公钥和私钥对,请再次运行 ./easy-rsa 命令,并选择 build-ca 选项:

./easyrsa build-ca

在输出中,您将看到有关 OpenSSL 版本的一些信息,并且将提示您为密钥对输入密码。请务必选择一个强密码,并将其记录在安全的地方。您需要在任何需要与您的 CA 交互的时候输入这个密码,例如签署或撤销证书。

此外,您还将被要求确认您的 CA 的通用名称(Common Name,CN)。CN 是在证书颁发机构的上下文中用来指代此计算机的名称。您可以输入任何字符串作为 CA 的通用名称,但为了简单起见,按 ENTER 接受默认名称即可。

Output
. . .
Enter New CA Key Passphrase:
Re-Enter New CA Key Passphrase:
. . .
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/home/sammy/easy-rsa/pki/ca.crt
💡
注意:如果您不希望每次与您的 CA 进行交互时都被提示输入密码,您可以使用 nopass 选项运行 build-ca 命令,就像这样:
./easyrsa build-ca nopass

现在您有两个重要的文件 — ~/easy-rsa/pki/ca.crt~/easy-rsa/pki/private/ca.key — 它们构成了证书颁发机构的公共和私有组件。

  • ca.crt 是 CA 的公共证书文件。用户、服务器和客户端将使用此证书来验证它们是否属于同一信任网络。每个使用您的 CA 的用户和服务器都需要拥有此文件的副本。所有参与方都将依赖于公共证书来确保没有人在冒充系统并执行中间人攻击
  • ca.key 是 CA 用于为服务器和客户端签署证书的私钥。如果攻击者获得对您的 CA 的访问权限,并进而获得您的 ca.key 文件,您将需要销毁您的 CA。这就是为什么您的 ca.key 文件应该只存在于您的 CA 机器上,并且理想情况下,当不签署证书请求时,您的 CA 机器应该处于离线状态作为额外的安全措施。

有了这些,您的 CA 就位了,可以用于签署证书请求和撤销证书了。

Step 4 — Distributing your Certificate Authority’s Public Certificate

现在您的 CA 已配置并准备好作为信任的根来为您想要配置使用它的任何系统提供服务。您可以将 CA 的证书添加到您的 OpenVPN 服务器、Web 服务器、邮件服务器等。任何需要验证您网络中另一个用户或服务器的身份的用户或服务器都应该将 ca.crt 文件的副本导入到其操作系统的证书存储中。

要将 CA 的公共证书导入到第二个 Linux 系统(如另一个服务器或本地计算机)中,首先从您的 CA 服务器获取 ca.crt 文件的副本。您可以使用 cat 命令在终端中输出它,然后将其复制粘贴到导入证书的第二台计算机上的文件中。您还可以使用 scprsync 等工具在系统之间传输文件。但是,在此步骤中,我们将使用 nano 进行复制和粘贴,因为它在所有系统上都可以使用。

作为您的非 root 用户在 CA 服务器上,运行以下命令:

cat ~/easy-rsa/pki/ca.crt

您的终端将输出类似以下的内容:

# Output
-----BEGIN CERTIFICATE-----
MIIDSzCCAjOgAwIBAgIUcR9Crsv3FBEujrPZnZnU4nSb5TMwDQYJKoZIhvcNAQEL
BQAwFjEUMBIGA1UEAwwLRWFzeS1SU0EgQ0EwHhcNMjAwMzE4MDMxNjI2WhcNMzAw
. . .
. . .
-----END CERTIFICATE-----

复制所有内容,包括 -----BEGIN CERTIFICATE----------END CERTIFICATE----- 行以及破折号。

在您的第二个 Linux 系统上使用 nano 或您喜欢的文本编辑器打开一个名为 /tmp/ca.crt 的文件:

nano /tmp/ca.crt

将您刚从 CA 服务器复制的内容粘贴到编辑器中。完成后,保存并关闭文件。如果您使用的是 nano,您可以按下 CTRL+X,然后按 YENTER 以确认。

现在,您在第二个 Linux 系统上有了 ca.crt 文件的副本,是时候将证书导入其操作系统的证书存储中了。

在 Ubuntu 和 Debian 等基于的系统上,以非 root 用户身份运行以下命令来导入证书:

sudo cp /tmp/ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

要在基于 CentOS、Fedora 或 RedHat 的系统上导入 CA 服务器的证书,只需像之前的示例中一样,将文件内容复制粘贴到系统中一个名为 /tmp/ca.crt 的文件中。接下来,您将把证书复制到 /etc/pki/ca-trust/source/anchors/ 中,然后运行 update-ca-trust 命令。

sudo cp /tmp/ca.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust

现在,您的第二个 Linux 系统将信任任何由 CA 服务器签名的证书。

💡
注意:如果您将您的 CA 用于 Web 服务器,并且使用 Firefox 浏览器,则需要直接将公共 ca.crt 证书导入 Firefox。Firefox 不使用本地操作系统的证书存储。有关如何将您的 CA 证书添加到 Firefox 的详细信息,请参阅 Mozilla 的支持文章《在 Firefox 中设置证书颁发机构(CAs)》。如果您将您的 CA 用于与 Windows 环境或桌面计算机集成,请参阅有关如何使用 certutil.exe 安装 CA 证书的文档

如果您将此教程作为另一个教程的先决条件,或者已经熟悉如何签署和撤销证书,您可以在这里停下来。如果您想进一步了解如何签署和撤销证书,那么接下来的可选部分将详细解释每个过程。

(Optional) — Creating Certificate Signing Requests and Revoking Certificates

教程的以下部分是可选的。如果您已完成了所有先前的步骤,那么您已经拥有一个完全配置和正常运行的证书颁发机构,您可以将您的 CA 的 ca.crt 文件导入,并验证您的网络中已由您的 CA 签名的证书。

如果您想练习并了解更多关于如何签署证书请求以及如何撤销证书的内容,那么这些可选部分将解释这两个过程的工作原理。

(Optional) — Creating and Signing a Practice Certificate Request

现在您已经准备好使用 CA,您可以练习生成私钥和证书请求,以熟悉签署和分发过程。

证书签名请求(CSR)由三部分组成:公钥、关于请求系统的识别信息以及请求本身的签名,该签名是使用请求方的私钥创建的。私钥将保密,将用于加密信息,而任何拥有签名公共证书的人都可以解密。

以下步骤将在您的第二个 Ubuntu 或 Debian 系统上运行,或者派生自它们之一的分发版。它可以是另一个远程服务器,也可以是像笔记本电脑或台式计算机这样的本地 Linux 机器。由于并非所有系统都默认安装了 easy-rsa,我们将使用 openssl 工具来创建一个练习私钥和证书。

openssl 通常默认安装在大多数 Linux 发行版上,但为了确保,请在您的系统上运行以下命令:

sudo apt update
sudo apt install openssl

当您被提示安装 openssl 时,请输入 y 以继续安装步骤。现在您已经准备好使用 openssl 创建一个练习 CSR。

创建 CSR 需要完成的第一步是生成一个私钥。要使用 openssl 创建私钥,请创建一个 practice-csr 目录,然后在其中生成一个密钥。我们将为一个名为 sammy-server 的虚构服务器创建此请求,而不是创建一个用于识别用户或另一个 CA 的证书。

mkdir ~/practice-csr
cd ~/practice-csr
openssl genrsa -out sammy-server.key

现在您已经有了一个私钥,可以使用 openssl 工具再次创建相应的 CSR。您将被提示填写一些字段,如国家、州和城市。您可以输入 . 来留空一个字段,但请注意,如果这是一个真实的 CSR,最好使用您所在地区和组织的正确值:

openssl req -new -key sammy-server.key -out sammy-server.req
# Output
. . .
-----
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:New York
Locality Name (eg, city) [Default City]:New York City
Organization Name (eg, company) [Default Company Ltd]:DigitalOcean
Organizational Unit Name (eg, section) []:Community
Common Name (eg, your name or your server's hostname) []:sammy-server
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

如果您希望自动将这些值作为 openssl 调用的一部分添加,而不是通过交互式提示添加,您可以将 -subj 参数传递给 OpenSSL。确保编辑高亮显示的值以匹配您的练习位置、组织和服务器名称:

openssl req -new -key sammy-server.key -out server.req -subj \
/C=US/ST=New\ York/L=New\ York\ City/O=DigitalOcean/OU=Community/CN=sammy-server

要验证 CSR 的内容,您可以使用 openssl 读取一个请求文件,并检查其中的字段。

openssl req -in sammy-server.req -noout -subject
# Output
subject=C = US, ST = New York, L = New York City, O = DigitalOcean, OU = Community, CN = sammy-server

一旦您对练习证书请求的主题满意,请使用 scpsammy-server.req 文件复制到您的 CA 服务器:

scp sammy-server.req sammy@your_ca_server_ip:/tmp/sammy-server.req

在这一步中,您为一个名为 sammy-server 的虚构服务器生成了证书签名请求。在真实世界的场景中,请求可能来自像是需要用于测试的暂存或开发 Web 服务器;或者来自请求证书以便用户可以连接到 VPN 的 OpenVPN 服务器。在下一步中,我们将继续使用 CA 服务器的私钥签署证书签名请求。

(Optional) — Signing a CSR

在上一步中,您为一个虚构服务器创建了一个练习证书请求和密钥。您将其复制到了 CA 服务器上的 /tmp 目录中,模拟了如果真实客户端或服务器向您发送需要签名的 CSR 请求时您将要使用的过程。

继续虚构的情景,现在 CA 服务器需要导入练习证书并对其进行签名。一旦 CA 验证了证书请求并将其传递回服务器,信任证书颁发机构的客户端也将能够信任新颁发的证书。

由于我们将在 CA 的 PKI 中运行,其中 easy-rsa 实用程序可用,签名步骤将使用 easy-rsa 实用程序使事情变得更容易,而不是像我们在前面的示例中直接使用 openssl 一样。

签署虚构 CSR 的第一步是使用 easy-rsa 脚本导入证书请求:

cd ~/easy-rsa
./easyrsa import-req /tmp/sammy-server.req sammy-server

在输出中,您将被要求验证请求是否来自受信任的来源。输入 yes 然后按 ENTER 键确认:

# Output
You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 825 days:

subject=
    countryName               = US
    stateOrProvinceName       = New York
    localityName              = New York City
    organizationName          = DigitalOcean
    organizationalUnitName    = Community
    commonName                = sammy-server


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
. . .

如果您对 CA 密钥进行了加密,那么此时会提示您输入密码。

您将收到以下类似的输出:

# Output
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :ASN.1 12:'New York'
localityName          :ASN.1 12:'New York City'
organizationName      :ASN.1 12:'DigitalOcean'
organizationalUnitName:ASN.1 12:'Community'
commonName            :ASN.1 12:'sammy-server'
Certificate is to be certified until Jul 21 13:59:08 2024 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /home/sammy/easy-rsa/pki/issued/sammy-server.crt

完成这些步骤后,您已经使用 CA 服务器的私钥在 /home/sammy/easy-rsa/pki/private/ca.key 中签署了 sammy-server.req CSR。生成的 sammy-server.crt 文件包含练习服务器的公共加密密钥,以及来自 CA 服务器的新签名。签名的目的是告诉任何信任 CA 的人,他们也可以信任 sammy-server 证书。

如果此请求是为了一个真实的服务器,如 Web 服务器或 VPN 服务器,那么 CA 服务器上的最后一步将是将新的 sammy-server.crt 和 ca.crt 文件从 CA 服务器分发到进行 CSR 请求的远程服务器:

scp pki/issued/sammy-server.crt sammy@your_server_ip:/tmp
scp pki/ca.crt sammy@your_server_ip:/tmp

在这一点上,您可以将已签发的证书用于诸如 Web 服务器、VPN、配置管理工具、数据库系统或客户端认证等用途。

(Optional) — Revoking a Certificate

偶尔,您可能需要吊销证书以防止用户或服务器使用它。也许有人的笔记本电脑被盗,一个 Web 服务器被入侵,或者一名员工或承包商离开了您的组织。

要吊销证书,通常的过程如下所示:

  1. 使用 ./easyrsa revoke client_name 命令吊销证书。

  2. 使用 ./easyrsa gen-crl 命令生成新的 CRL。

  3. 将更新后的 crl.pem 文件传输到依赖于您的 CA 的服务器,然后在这些系统上将其复制到程序所需的目录或目录。

  4. 重新启动使用您的 CA 和 CRL 文件的任何服务。

您可以使用此过程随时吊销先前颁发的任何证书。我们将在以下各节中详细介绍每个步骤,从吊销命令开始。

Revoking a Certificate(吊销证书)

要吊销证书,请前往您的 CA 服务器上的 easy-rsa 目录:

cd ~/easy-rsa

接下来,运行带有吊销选项的 easyrsa 脚本,然后是您希望吊销的客户端名称。按照上面的示例,证书的通用名称为 sammy-server

./easyrsa revoke sammy-server

这将要求您确认吊销,输入 yes 即可:

# Output
Please confirm you wish to revoke the certificate with the following subject:

subject=
    commonName                = sammy-server


Type the word 'yes' to continue, or any other input to abort.
  Continue with revocation: yes
. . .
Revoking Certificate 8348B3F146A765581946040D5C4D590A
. . .

请注意“Revoking Certificate”行上突出显示的值。这个值是要吊销的证书的唯一序列号。如果您想在本节的最后一步中检查吊销列表以验证证书是否在其中,您将需要此值。

确认操作后,CA 将吊销证书。然而,依赖于 CA 的远程系统无法检查是否已吊销任何证书。用户和服务器仍然可以使用证书,直到 CA 的证书吊销列表 (CRL) 分发到所有依赖于该 CA 的系统为止。

在下一步中,您将生成一个 CRL 或更新现有的 crl.pem 文件。

Generating a Certificate Revocation List(生成证书吊销列表)

现在您已经吊销了一个证书,更新您的 CA 服务器上的吊销证书列表非常重要。一旦您有了更新后的吊销列表,您将能够知道哪些用户和系统在您的 CA 中拥有有效的证书。

要生成 CRL,请在 ~/easy-rsa 目录中运行 easy-rsa 命令,并使用 gen-crl 选项:

./easyrsa gen-crl

如果您在创建 ca.key 文件时使用了密码,您将被提示输入密码。gen-crl 命令将生成一个名为 crl.pem 的文件,其中包含该 CA 的更新的吊销证书列表。

接下来,每次运行 gen-crl 命令时,您都需要将更新后的 crl.pem 文件传输到依赖于此 CA 的所有服务器和客户端。否则,客户端和系统仍然可以访问使用您的 CA 的服务和系统,因为这些服务需要了解证书的吊销状态。

传输证书吊销列表 现在您已经在 CA 服务器上生成了一个 CRL,您需要将其传输到依赖于您的 CA 的远程系统。要将此文件传输到您的服务器上,您可以使用 scp 命令。

💡
注意:本教程解释了如何手动生成和分发 CRL。虽然有更强大和自动化的方法来分发和检查吊销列表,如 OCSP-Stapling,但配置这些方法超出了本文的范围。

请确保以您的非 root 用户身份登录到您的 CA 服务器,并执行以下命令,将您自己的服务器 IP 或 DNS 名称替换为 your_server_ip:

scp ~/easy-rsa/pki/crl.pem sammy@your_server_ip:/tmp

现在文件已经传输到远程系统,最后一步是使用新的吊销列表副本更新任何服务。

Updating Services that Support a CRL(更新支持 CRL 的服务)

详细说明如何更新使用 crl.pem 文件的服务超出了本教程的范围。一般来说,您需要将 crl.pem 文件复制到服务期望的位置,然后使用 systemctl 重新启动它。

一旦您使用新的 crl.pem 文件更新了您的服务,您的服务将能够拒绝来自使用吊销证书的客户端或服务器的连接。

Examining and Verifying the Contents of a CRL(查看和验证 CRL 的内容)

如果您想要查看 CRL 文件,例如确认吊销证书的列表,请在您的 CA 服务器上的 easy-rsa 目录中使用以下 openssl 命令:

cd ~/easy-rsa
openssl crl -in pki/crl.pem -noout -text

您还可以在任何安装了 openssl 工具并且具有 crl.pem 文件副本的服务器或系统上运行此命令。例如,如果您将 crl.pem 文件传输到了第二个系统,并希望验证 sammy-server 证书是否被吊销,您可以使用类似以下的 openssl 命令,将您在撤销证书时记录的序列号替换为此处突出显示的序列号:

openssl crl -in /tmp/crl.pem -noout -text |grep -A 1 8348B3F146A765581946040D5C4D590A
# Output
    Serial Number: 8348B3F146A765581946040D5C4D590A
        Revocation Date: Apr 18 14:00:37 2022 GMT

请注意,grep 命令是如何用于检查您在吊销步骤中记录的唯一序列号。现在,您可以在任何依赖它来限制用户和服务访问的系统上验证您的证书吊销列表的内容。

总结

在本教程中,您在独立的 Ubuntu 22.04 服务器上使用 Easy-RSA 软件包创建了一个私有证书颁发机构。您了解了依赖于 CA 的各方之间的信任模型是如何工作的。您还创建并签署了一个用于练习服务器的证书签名请求 (CSR),然后学习了如何吊销证书。最后,您学习了如何生成和分发证书吊销列表 (CRL),以确保依赖于您的 CA 的任何系统都可以防止不应访问服务的用户或服务器。

现在,您可以为用户签发证书,并将其用于诸如 OpenVPN 等服务。您还可以使用您的 CA 为开发和预备环境的网页服务器配置证书,以保护非生产环境。在开发过程中使用带有 TLS 证书的 CA 可以帮助确保您的代码和环境尽可能地与生产环境匹配。