OpenSSL 自签名证书生成教程:从入门到精通
在现代网络世界中,数据传输安全至关重要。无论是访问网站、发送电子邮件还是进行API通信,我们都希望数据能够加密传输,防止被窃听或篡改。传输层安全(TLS)协议(其前身为安全套接层SSL协议)正是实现这一目标的核心技术。而数字证书则是TLS/SSL协议中用于验证通信方身份和建立加密通道的关键组成部分。
通常,在生产环境中,我们会使用由受信任的第三方证书颁发机构(Certificate Authority, CA)签发的证书。这些CA(如Let’s Encrypt, DigiCert, Sectigo等)在全球范围内被操作系统、浏览器和应用程序广泛信任。然而,在开发、测试、内部网络、个人项目或学习阶段,为了快速搭建一个支持HTTPS/TLS的环境,购买或申请CA签发的证书可能不太方便或没有必要。这时,自签名证书(Self-Signed Certificate)就派上了用场。
什么是自签名证书?
顾名思义,自签名证书就是由证书创建者自己签发的证书,而不是由任何受信任的第三方CA签发。这意味着证书的签名者和被签发者是同一个实体。
为什么使用自签名证书?
自签名证书的主要优点在于:
- 成本低廉(免费):无需向CA支付任何费用。
- 获取便捷:可以在任何安装了OpenSSL等工具的机器上随时生成。
- 灵活性高:可以自定义证书的有效期、主题信息(Common Name, CN)、主题备用名称(Subject Alternative Name, SAN)等所有字段。
- 适用于特定场景:非常适合本地开发环境的HTTPS测试、内部网络服务(如Jenkins、GitLab私有部署)、个人实验项目、学习TLS/SSL原理等。
自签名证书的局限性
尽管方便,自签名证书也有其显著的局限性:
- 不受信任:由于不是由被广泛信任的CA签发,操作系统、浏览器和大多数客户端应用程序默认会认为它不受信任。
- 安全警告:使用自签名证书访问网站时,浏览器会显示醒目的安全警告(如“连接不是私密的”、“您的连接不安全”等),用户需要手动选择信任或继续访问。这在生产环境中是不可接受的,会严重影响用户体验。
- 中间人攻击风险:在公共网络上,由于证书的身份无法被第三方验证,攻击者可以更容易地实施中间人攻击(Man-in-the-Middle, MITM),用自己的自签名证书冒充目标服务器,而用户难以察觉。
- 功能受限:某些高级的TLS功能或新的安全标准可能对证书的信任链有要求,自签名证书可能无法满足。
总结: 自签名证书适用于无需外部信任的封闭或受控环境。绝对不应在面向公众的生产环境中使用自签名证书。
什么是 OpenSSL?
OpenSSL 是一个强大的开源加密工具包,实现了SSL和TLS协议,并提供了丰富的命令行工具,用于生成私钥、公钥、证书签名请求(CSR)、管理证书、进行加密解密操作、测试TLS/SSL连接等。它是生成自签名证书最常用和最强大的工具之一。
准备工作:安装 OpenSSL
大多数 Linux 和 macOS 系统预装了 OpenSSL。你可以在终端中输入以下命令来检查是否已安装及版本:
bash
openssl version
如果命令有效并显示版本信息,说明OpenSSL已安装。
在 Windows 系统上,你需要单独下载并安装 OpenSSL。可以从其官方网站或第三方维护者处获取安装包。安装后,可能需要将 OpenSSL 的 bin 目录添加到系统的 PATH 环境变量中,以便在任何位置调用 openssl
命令。
安装完成后,就可以开始使用 OpenSSL 生成自签名证书了。
核心概念回顾
在生成证书之前,快速回顾几个核心概念对理解命令参数很有帮助:
- 私钥 (Private Key):一段保密的加密数据,用于对数据进行签名或解密只有与该私钥配对的公钥加密的数据。私钥必须严格保密。
- 公钥 (Public Key):由私钥派生而来,用于验证私钥签名的数据,或加密只有与该公钥配对的私钥才能解密的数据。公钥是公开的。
- 证书 (Certificate / X.509 Certificate):一个数字文档,包含了持有者的公钥、身份信息(如域名、组织、位置等)、证书的有效期以及由签发机构(CA 或自身)的私钥对该证书内容的签名。证书的作用是将一个公钥绑定到一个特定的身份。
- 证书签名请求 (Certificate Signing Request, CSR):一个包含申请者公钥和身份信息的文件,用于提交给CA以申请签发证书。对于自签名证书,我们有时会先生成CSR再自己签发,有时则一步到位直接生成证书。
生成自签名证书的方法
OpenSSL 提供了多种生成自签名证书的方法。我们将介绍从最简单到更高级的几种,包括如何添加 Subject Alternative Name (SAN),因为 SAN 对于现代浏览器信任证书(即使是自签名的)至关重要。
重要提示: 在执行命令时,你需要在一个你拥有写权限的目录下,以便生成的文件能够保存。
方法一:最简单的一步到位生成 (不推荐用于现代应用,因为它主要依赖于 Common Name)
这个方法使用一个命令生成私钥和证书。它会提示你输入一些信息来填充证书的字段。
bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt
让我们分解这个命令的各个部分:
openssl req
: 这是一个多用途命令,用于处理证书签名请求(CSR)和证书。-x509
: 这个选项告诉req
命令输出一个自签名证书,而不是一个CSR。当你使用-x509
选项时,-new
或-newkey
选项会自动创建一个自签名证书,使用-days
选项指定的有效期。-nodes
: 这个选项表示不使用 DES 加密来保护生成的私钥。这意味着私钥文件(server.key
)在磁盘上将是未加密的纯文本。这样做是为了方便,特别是在自动化脚本或服务器启动时,无需手动输入密码。但是,未加密的私钥风险更高,一旦文件泄露,任何人都可以使用它。在更安全的环境中,你应该省略-nodes
并为私钥设置一个密码,然后在需要时(例如,Web服务器启动)提供该密码。-days 365
: 设置证书的有效期,单位是天。这里设置为 365 天,即一年。你可以根据需要调整这个数字。-newkey rsa:2048
: 这个选项表示生成一个新的私钥。rsa
: 指定密钥类型为 RSA。RSA 是一种常用的非对称加密算法。2048
: 指定 RSA 密钥的长度为 2048 位。2048 位 RSA 密钥目前被认为是安全的,是常用的标准。更长的密钥(如 4096 位)更安全但也更耗费计算资源。
-keyout server.key
: 指定生成的私钥的输出文件名。这里是server.key
。-out server.crt
: 指定生成的自签名证书的输出文件名。这里是server.crt
。.crt
和.cer
都是常见的证书文件扩展名。
执行上述命令后,系统会提示你输入一些信息来填充证书的主体(Subject)字段。这些信息构成了证书所有者的身份:
“`
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, this field will be left blank.
Country Name (2 letter code) [AU]:CN # 国家代码 (例如 CN, US)
State or Province Name (full name) [Some-State]:Beijing # 省/州
Locality Name (eg, city) []:Beijing # 城市
Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Local Dev # 组织/公司名称
Organizational Unit Name (eg, section) []:IT Dept # 组织单位名称 (可选)
Common Name (e.g. server FQDN or YOUR name) []:localhost # 通用名称 (Common Name, CN) – 非常重要! 对于服务器证书,这里通常是服务器的完全限定域名 (FQDN) 或 IP 地址。
Email Address []:[email protected] # 邮箱地址 (可选)
“`
在提示符处逐一输入相应信息(或者直接按回车接受默认值,除了 Common Name 强烈建议输入)。
Common Name (CN) 是历史上用于标识服务器域名的主要字段。然而,现代浏览器已经不推荐甚至逐步废弃依赖 CN 字段进行域名匹配,而是优先或强制使用 Subject Alternative Name (SAN) 字段。
因此,虽然这个方法简单,但生成的证书在现代浏览器中访问时,如果 CN 不是 localhost
或准确匹配你访问的域名/IP,仍然可能会因为缺少 SAN 而产生更严重的警告或直接拒绝连接。
方法二:分开生成私钥和证书 (提供了更灵活的密钥管理)
你可以先独立生成私钥,然后再用该私钥生成自签名证书。
步骤 1:生成私钥
bash
openssl genrsa -out server.key 2048
openssl genrsa
: 生成 RSA 私钥的命令。-out server.key
: 指定输出文件名为server.key
。2048
: 指定 RSA 密钥长度为 2048 位。
默认情况下,genrsa
生成的私钥是未加密的。如果你想为私钥设置密码以增加安全性(省略 -nodes
的效果),可以使用 -des3
, -aes128
, -aes256
等选项。例如:
bash
openssl genrsa -aes256 -out server.key 2048
执行此命令后,系统会提示你输入并验证一个密码。将来使用这个私钥时(例如,启动 Web 服务器),你需要提供这个密码。
步骤 2:使用已生成的私钥生成自签名证书
bash
openssl req -x509 -new -nodes -days 365 -key server.key -out server.crt
-new
: 创建一个新的证书请求。当与-x509
和-key
一起使用时,它会使用指定的私钥创建一个新的自签名证书。-key server.key
: 指定用于签发证书的私钥文件。这里使用了上一步生成的server.key
。- 其他参数 (
-x509
,-nodes
,-days 365
,-out server.crt
) 的含义与方法一相同。注意这里也使用了-nodes
来避免在生成证书时再次为私钥输入密码(如果私钥本身是加密的,这个-nodes
只影响证书生成过程是否需要密码,不会解密私钥文件本身)。如果你在上一步生成了加密的私钥,这里去掉-nodes
将会提示你输入私钥密码。
执行此命令后,同样会提示你输入证书的主体信息(Country, State, Locality, Organization, Common Name 等)。
这种方法的好处是你可以独立管理和备份你的私钥。例如,你可以先生成一个加密的私钥,然后只在需要生成/更新证书时使用它。
方法三:生成带有 Subject Alternative Name (SAN) 的证书 (推荐用于现代应用)
正如前面提到的,SAN 字段是现代浏览器验证服务器身份的首选方式。它允许你在证书中列出多个域名和/或IP地址,这样证书就可以用于所有这些名称。例如,一个证书可以同时对 localhost
, mydev.local
, 192.168.1.100
等多个地址有效。
生成带有 SAN 的自签名证书需要使用 OpenSSL 的配置文件。
步骤 1:创建或修改 OpenSSL 配置文件
你需要一个 OpenSSL 配置文件来指定 SAN 扩展。OpenSSL 的默认配置文件通常位于 /etc/ssl/openssl.cnf
(Linux/macOS) 或 OpenSSL 安装目录下的 openssl.cnf
(Windows)。不建议直接修改系统默认的配置文件。更好的做法是创建一个新的配置文件,或者复制默认文件并修改。
创建一个名为 san.cnf
的文件(或其他你喜欢的名字),内容如下:
“`ini
[ req ]
req_extensions = v3_req # 如果使用 req -new 命令生成 CSR 时需要 SAN,则取消注释此行,并确保 req_extensions 指向包含 SAN 的 section
These are removed when -subj is used.
distinguished_name = req_distinguished_name # 如果使用交互式输入主题信息,则取消注释此行
prompt = no # 如果设置为 no,则不提示输入主题信息,必须使用 -subj 选项或 distinguished_name section
[ req_distinguished_name ]
C = CN # Country Name (2 letter code)
ST = Beijing # State or Province Name
L = Beijing # Locality Name (eg, city)
O = My Local Dev # Organization Name (eg, company)
OU = IT Dept # Organizational Unit Name (optional)
CN = localhost # Common Name (e.g. server FQDN or YOUR name) – 仍然需要,但SAN更重要
[ v3_req ]
Extensions to add to a certificate request
For client certificates: basicConstraints = CA:FALSE
For server certificates: basicConstraints = CA:FALSE
使用 subjectAltName 扩展指定 SANs
subjectAltName = @alt_names
[ v3_ext ]
Extensions to add to a certificate (when signing)
basicConstraints = CA:FALSE # 如果这个自签名证书不会用于签发其他证书,设置为 CA:FALSE 是最佳实践
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names # 引用 SAN 定义的 section
[ alt_names ]
定义 Subject Alternative Name (SAN)
DNS. 用于域名, IP. 用于 IP 地址
DNS.1 = localhost
DNS.2 = mydev.local
DNS.3 = *.mydev.local # 示例:支持通配符子域名 (通配符证书)
IP.1 = 127.0.0.1
IP.2 = 192.168.1.100
IP.3 = 10.0.0.50
更多 DNS 或 IP 地址…
“`
配置文件的解释:
[ req ]
: 配置openssl req
命令的行为。prompt = no
: 设置为no
可以避免交互式输入主题信息,此时必须通过-subj
命令行参数或在[ req_distinguished_name ]
section 中指定。req_extensions = v3_req
: 如果你先生成一个 CSR (openssl req -new
) 并希望 CSR 中包含 SAN 信息以便后续使用它生成证书,则需要启用此项。对于一步到位生成自签名证书 (openssl req -x509
), 重要的扩展部分是[ v3_ext ]
,它通过-extensions
和-extfile
参数引用。
[ req_distinguished_name ]
: 定义证书主体信息(如果prompt = no
并且不使用-subj
)。[ v3_req ]
: 定义用于证书请求 (CSR) 的 X.509v3 扩展。这里的subjectAltName
如果在req_extensions
中引用,会包含在 CSR 里。[ v3_ext ]
: 定义用于证书的 X.509v3 扩展。对于自签名证书 (-x509
),这是最关键的 SAN 定义位置,需要通过-extensions
和-extfile
参数引用。[ alt_names ]
: 定义具体的 SAN 条目。DNS.<number> = <hostname>
: 指定域名。IP.<number> = <ip_address>
: 指定 IP 地址。- 根据需要添加任意数量的 DNS 或 IP 条目。
步骤 2A:一步到位生成带有 SAN 的自签名证书 (推荐)
这是最常用的方法,结合了生成私钥、证书以及 SAN 扩展。
bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout server.key -out server.crt \
-config san.cnf \
-extensions v3_ext \
-subj "/C=CN/ST=Beijing/L=Beijing/O=My Local Dev/OU=IT Dept/CN=localhost"
分解这个命令:
- 前面大部分参数 (
-x509
,-nodes
,-days 365
,-newkey rsa:2048
,-keyout server.key
,-out server.crt
) 与方法一和方法二类似。 -config san.cnf
: 指定使用我们创建的配置文件san.cnf
。-extensions v3_ext
: 告诉 OpenSSL 在生成证书时使用配置文件中[ v3_ext ]
section 定义的扩展。这是将 SAN 添加到最终证书的关键。-subj "/C=.../ST=.../L=.../O=.../OU=.../CN=..."
: 通过命令行直接指定证书的主体信息,避免交互式输入。/C=CN/ST=Beijing/...
是一种标准的 Distinguished Name 格式。确保/CN=
字段与你在[ alt_names ]
中列出的某个 DNS 名称(通常是第一个)一致,尽管 SAN 是主要的匹配项,但某些旧系统或工具可能仍然依赖 CN。
执行此命令后,会在当前目录下生成 server.key
和 server.crt
文件,其中 server.crt
就包含了你在 san.cnf
文件 [ alt_names ]
section 中定义的所有域名和 IP 地址作为 SAN。
步骤 2B:先生成 CSR (包含 SAN),再自签名该 CSR (更贴近标准流程)
这种方法更接近CA签发证书的标准流程:先生成私钥和CSR,然后使用该CSR生成证书。对于自签名,签发机构就是我们自己。
-
2B.1:生成私钥 (同方法二的步骤 1)
bash
openssl genrsa -out server.key 2048
或者带密码:
bash
openssl genrsa -aes256 -out server.key 2048 -
2B.2:生成包含 SAN 的 CSR
你需要修改san.cnf
文件,确保[ req ]
section 中的req_extensions
行被取消注释,并指向[ v3_req ]
或其他包含 SAN 定义的 section。例如:
“`ini
[ req ]
req_extensions = v3_req # 使用 v3_req 定义的扩展 (SAN)
prompt = no
distinguished_name = req_distinguished_name[ req_distinguished_name ]
C = CN
ST = Beijing
L = Beijing
O = My Local Dev
OU = IT Dept
CN = localhost # 这个CN会被包含在CSR中[ v3_req ] # 这个 section 定义了 CSR 的扩展
subjectAltName = @alt_names[ alt_names ] # SAN 定义
DNS.1 = localhost
DNS.2 = mydev.local
IP.1 = 127.0.0.1… 其他 SAN 条目 …
注意:这里不需要 [ v3_ext ] section 来定义证书扩展,因为我们在生成 CSR 阶段已经定义了 SAN,
并在下一步自签名时引用 CSR 中的扩展。
“`
然后执行命令生成 CSR:
bash
openssl req -new -key server.key -out server.csr -config san.cnf
*-new
: 生成一个新的证书请求。
*-key server.key
: 使用这个私钥生成请求。
*-out server.csr
: 输出 CSR 文件。
*-config san.cnf
: 使用配置文件指定主题信息和 SAN 扩展。
* 如果你在san.cnf
中设置了prompt = yes
或没有-subj
部分,这里会提示你输入主题信息。 -
2B.3:自签名 CSR 生成证书
现在,使用私钥和你刚刚生成的 CSR 来签发证书:
bash
openssl x509 -req -in server.csr -signkey server.key -out server.crt -days 365 -extensions v3_req -extfile san.cnf
分解这个命令:openssl x509
: 用于处理 X.509 证书。-req
: 指明输入文件是一个 CSR (server.csr
)。-in server.csr
: 指定输入的 CSR 文件。-signkey server.key
: 指定用于签发证书的私钥(自签名时就是证书持有者的私钥)。-out server.crt
: 输出生成的证书文件。-days 365
: 设置证书有效期。-extensions v3_req
: 指定使用配置文件中[ v3_req ]
section 定义的扩展。注意:这里引用的是 CSR 中的扩展定义 section。 如果你的 SAN 定义在[ v3_ext ]
或其他 section,这里需要相应修改,并确保-extfile
参数指向正确的配置文件。-extfile san.cnf
: 指定包含扩展定义的配置文件。
这种方法分步骤更清晰,有助于理解 CSR 的作用,并且在某些自动化流程中可能更有优势。
总结: 对于大多数现代自签名证书需求,推荐使用方法三,特别是步骤 2A (一步到位),因为它直接生成带有 SAN 的证书,且命令相对简洁。确保你的 san.cnf
文件正确配置了 [ alt_names ]
和 [ v3_ext ]
section (或 [ v3_req ]
如果走 CSR 流程)。
理解生成的证书文件
生成证书后,你会有两个主要文件:
server.key
: 你的私钥文件。内容通常以-----BEGIN RSA PRIVATE KEY-----
或-----BEGIN PRIVATE KEY-----
开头,以-----END RSA PRIVATE KEY-----
或-----END PRIVATE KEY-----
结尾。这个文件非常重要,必须保密!server.crt
: 你的自签名证书文件。内容通常以-----BEGIN CERTIFICATE-----
开头,以-----END CERTIFICATE-----
结尾。这是 PEM 编码的 X.509 证书。你可以公开这个文件。
有时你可能还会看到 .pem
扩展名的文件。.pem
是一种容器格式,它可以包含私钥、证书、CSR,或者它们中的任何组合。通常,一个 .pem
文件可以包含证书(以 -----BEGIN CERTIFICATE-----
开头)和其对应的私钥(以 -----BEGIN PRIVATE KEY-----
或 -----BEGIN RSA PRIVATE KEY-----
开头)串联在一起。许多服务器软件(如 Nginx)可以配置为使用单独的 .key
和 .crt
文件,也有一些(如某些Java应用)可能需要一个包含两者或特定格式的 .pem
文件。你可以简单地将 .key
和 .crt
文件的内容连接起来创建一个 .pem
文件:
bash
cat server.key server.crt > server.pem
查看证书详情
你可以使用 OpenSSL 命令来查看生成的证书或 CSR 的详细信息,验证是否包含了正确的CN、SAN、有效期等。
查看证书详情:
bash
openssl x509 -in server.crt -text -noout
openssl x509
: 处理 X.509 证书。-in server.crt
: 指定输入文件是server.crt
。-text
: 以人类可读的文本格式输出证书内容。-noout
: 不要输出 PEM 编码的证书本身,只输出文本信息。
执行此命令后,你会看到证书的各个字段,包括版本、序列号、签名算法、签发者 (Issuer)、主体 (Subject)、有效期 (Validity)、公钥信息、以及最重要的 Subject Alternative Name (SAN) 扩展。检查 SAN 字段,确认它包含了你期望的所有域名和 IP 地址。
查看 CSR 详情 (如果你生成了 CSR):
bash
openssl req -in server.csr -text -noout
这会显示 CSR 中的主体信息、公钥以及包含的扩展信息(如 SAN)。
在服务器中使用自签名证书
生成 server.key
和 server.crt
文件后,你就可以将它们配置到你的 Web 服务器或其他需要 TLS/SSL 的应用程序中。不同服务器的配置方法不同,但通常都需要指定私钥文件和证书文件的路径。
例如:
-
Nginx:
“`nginx
server {
listen 443 ssl;
server_name localhost mydev.local; # 或你的IP/域名ssl_certificate server.crt; ssl_certificate_key server.key; # ... 其他配置
}
* **Apache:**
apache
ServerName localhost # 或你的域名/IP
# ServerAlias mydev.local … # 如果有多个SAN域名SSLEngine on SSLCertificateFile /path/to/your/server.crt SSLCertificateKeyFile /path/to/your/server.key # ... 其他配置
* **Node.js `https` 模块:**
javascript
const https = require(‘https’);
const fs = require(‘fs’);const options = {
key: fs.readFileSync(‘server.key’),
cert: fs.readFileSync(‘server.crt’)
};https.createServer(options, (req, res) => {
res.writeHead(200);
res.end(‘Hello HTTPS World!\n’);
}).listen(8443, () => {
console.log(‘HTTPS server listening on port 8443’);
});
“`
配置完成后,重启你的服务器或应用程序。
处理浏览器警告
当你使用浏览器访问配置了自签名证书的网站时,由于证书不受信任,浏览器会显示安全警告。要绕过这个警告,你有几种选择:
- 忽略警告并继续访问:大多数浏览器都提供了“继续访问”、“接受风险”或类似的选项。这仅用于临时访问,并且每次都会出现警告。
- 将自签名证书导入到操作系统的信任存储中:这是解决警告的最彻底方法(针对特定机器)。将
.crt
文件作为“受信任的根证书颁发机构”导入到你的操作系统(Windows、macOS、Linux)或浏览器(如 Firefox 有自己的证书存储)的证书信任存储中。导入后,该机器上的浏览器和其他应用程序就会信任这个证书,不再显示警告。导入过程因操作系统和浏览器而异,通常可以在操作系统的“证书管理器”或浏览器的“隐私与安全”设置中找到。请谨慎导入不受信任的证书,只导入你自己生成的并确定安全的证书。 - 使用工具辅助:有一些开发工具或库(如
mkcert
)可以更方便地在本地生成并自动信任自签名证书,简化了手动导入的过程。
特别提示: 确保你访问网站时使用的域名或 IP 地址精确匹配你的证书中的 CN(历史原因)或 SAN 条目。如果不匹配,即使导入了证书,浏览器仍然会因为名称不匹配而显示警告(通常是 NET::ERR_CERT_COMMON_NAME_INVALID
或类似的错误)。这就是 SAN 字段的重要性所在。
故障排除与常见问题
openssl command not found
: OpenSSL 没有安装或其执行路径没有添加到系统的 PATH 环境变量中。Permission denied
: 你可能在没有写权限的目录执行命令,或者输出文件已存在但你没有覆盖的权限。尝试在用户主目录下或创建一个新目录进行操作。- 生成私钥时总是提示输入密码,即使使用了
-nodes
: 检查命令是否正确,-nodes
必须紧跟在openssl req
或openssl genrsa
后面。 - 浏览器警告仍然存在,即使导入了证书:
- 名称不匹配: 这是最常见的问题。检查你访问的 URL (域名或 IP) 是否在证书的 SAN 列表中。使用
openssl x509 -in server.crt -text -noout
检查证书内容。如果你使用的是 IP 地址访问,证书的 SAN 中必须包含该 IP 地址。如果你使用的是域名访问,SAN 中必须包含该域名。 - 证书导入错误: 确认你将证书导入到了正确的位置(通常是“受信任的根证书颁发机构”)并且导入成功。重启浏览器或计算机有时是必要的。
- 证书过期: 检查证书的有效期 (
openssl x509 -in server.crt -text -noout
中的 Validity 字段)。如果过期,重新生成证书。 - 系统时间错误: 确保你的计算机系统时间是正确的。
- 服务器配置错误: 确认你的服务器配置确实指向了新生成的私钥和证书文件,并且服务器已重启。
- 名称不匹配: 这是最常见的问题。检查你访问的 URL (域名或 IP) 是否在证书的 SAN 列表中。使用
- 使用配置文件时提示
Error loading extension section <section_name>
: 配置文件中指定的 section 名称不正确,或者文件路径错误。检查-extensions
参数是否与配置文件中的 section 名称匹配,以及-extfile
参数是否指向正确的配置文件路径。 - 生成的私钥有密码,但服务器启动时没有提示输入密码或报错: 服务器配置可能没有正确处理带密码的私钥,或者没有在启动时提供密码。对于自动化部署,通常会选择无密码的私钥 (
-nodes
),但要注意其安全风险。
安全注意事项
- 私钥安全:无密码的私钥 (
-nodes
) 提供了便利,但也带来了安全隐患。如果你的私钥文件落入恶意方手中,他们可以轻松冒充你的服务器。在非开发/测试环境或更关注安全性的场景下,考虑为私钥设置密码,并采取措施在服务器启动时安全地提供密码。 - 自签名证书的信任范围:记住,自签名证书只在手动将其导入信任存储的机器上被信任。它不具备全球性的信任。
- 不要在公共生产环境使用:再次强调,永远不要在面向公共用户的生产网站或服务上使用自签名证书,除非你希望用户看到安全警告或无法访问。
结论
通过本教程,你应该已经掌握了使用 OpenSSL 生成自签名证书的各种方法,从最简单的一步到位,到更安全地分开生成私钥和证书,以及最重要的——如何生成包含 Subject Alternative Name (SAN) 的证书以适应现代浏览器和应用程序的需求。
自签名证书是开发和测试阶段的强大工具,能够帮助你在无需依赖外部CA的情况下快速搭建安全的TLS/SSL环境。然而,理解其局限性并仅在合适的场景下使用至关重要。
熟练掌握 OpenSSL 的命令行工具,不仅能让你自由生成和管理自签名证书,也是深入理解 TLS/SSL 工作原理和证书体系结构的良好开端。希望这篇详细教程对你有所帮助!