如何用 OpenSSL 生成自签名 SSL 证书
使用 OpenSSL 3.x 生成带 SAN 的自签名证书,理解私钥保护、CSR 扩展复制和客户端信任前提。包含一条命令与三步流程,SAN 本身不建立信任。
一句话回答:最快的一条命令:openssl req -x509 -newkey rsa:2048 -nodes -keyout server.key -out server.crt -days 365 -subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"——同时生成私钥和自签名证书,SAN 应匹配实际访问的域名/IP,但仅有 SAN 并不能建立信任;客户端仍需信任该证书或其签发 CA。命令中的未加密私钥需要严格权限保护。
一条命令版(推荐)
umask 077
openssl req -x509 -newkey rsa:2048 -noenc -days 365 -keyout server.key -out server.crt -subj "/CN=example.local" -addext "subjectAltName=DNS:example.local,DNS:*.example.local,IP:192.168.1.10"
参数说明:示例面向 OpenSSL 3.x,-noenc(旧选项 -nodes)使私钥不加密(服务器自动重启不用输密码);-days 有效期;SAN 里按需列出所有域名和 IP。
传统三步版(理解流程)
1. 生成私钥
umask 077
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.key -aes256
-aes256 给私钥加口令保护;服务器无人值守场景去掉它(改用 -nodes 思路)。
2. 生成证书签名请求(CSR)
openssl req -new -key private.key -out certificate.csr \
-subj "/CN=localhost" -addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
这里显式提供 CN 和 SAN。第三步以 OpenSSL 3.x 为例复制本地可信 CSR 的扩展;不要无审查地复制外部 CSR 的任意扩展。生成后再次检查 SAN。
3. 自签生成证书
openssl x509 -req -days 365 -in certificate.csr -signkey private.key \
-copy_extensions copy -out certificate.crt
验证结果
openssl x509 -in server.crt -text -noout | grep -A1 'Subject Alternative Name'
openssl x509 -in server.crt -noout -dates # 有效期
使用注意
- 仅限测试/内网:自签证书不被公网客户端信任,浏览器会告警。公网服务用 Let's Encrypt 免费证书
- 想被本地浏览器信任:把 server.crt 导入系统信任库,或直接用 mkcert 工具(建立并安装开发 CA,再签发域名匹配的证书;是否信任取决于实际客户端)
- 私钥保管:
chmod 600 server.key,别提交进 Git 仓库
常见问题(FAQ)
Q:生成的证书 Chrome 报 NET::ERR_CERT_COMMON_NAME_INVALID?
A:可能缺少 SAN,也可能 SAN 与访问的域名/IP 不匹配。检查服务实际返回的证书;需要重新签发时将访问名称正确加入 SAN。信任链错误是另一个独立问题。
Q:能生成泛域名(通配符)自签证书吗?
A:能,SAN 里写 DNS:*.example.local 即可。注意它只覆盖一级子域名。
Q:自签证书和 mkcert 有什么区别?
A:自签描述的是“谁签名”,不代表证书一定有 CA:TRUE 或签发其他证书的用途权限。mkcert 创建开发 CA 并签发叶证书,受信任客户端可据此验证;这也使开发 CA 私钥非常敏感,不可共享或用于生产。
核查依据
本文依据官方文档核对,示例未在实际业务环境运行;上线前请按部署版本、权限与数据范围验证。