
本地证书制作教程的核心结论只有一句话:用OpenSSL生成自签名证书或搭建私有CA,是内网环境最稳妥、成本最低的加密方案。不需要第三方付费服务,一台Linux服务器加上一条命令就能跑通整个流程。本文按操作顺序拆解5个关键环节,每个环节都给出可复制的命令和参数。
第1步:确认OpenSSL版本与密钥算法优先级
先说一个容易被忽略的坑。2024年之后新装的CentOS Stream 9或Ubuntu 24.04,系统自带的OpenSSL已经默认禁用SHA-1签名,RSA密钥低于2048位也会直接报错。所以在动手之前,先执行openssl version确认版本号。如果是3.0以上,后续所有命令里的-sha256可以省略,但RSA位数必须写2048或更高。
坦白讲,Ed25519算法在本地证书场景下比RSA更值得推荐。签名速度快、密钥体积小,一台树莓派跑起来毫无压力。但很多老旧设备——比如某些工控机、老款交换机——只认RSA。所以我的建议是:纯内网且设备较新,优先Ed25519;要兼容杂牌设备,老老实实用RSA 2048。
第2步:生成私钥与证书签名请求(CSR)
这一步是本地证书制作教程里最容易出错的环节。私钥的权限必须是600,否则Nginx或Apache启动时会拒绝读取。具体命令如下:
- 生成Ed25519私钥:openssl genpkey -algorithm Ed25519 -out server.key
- 生成RSA 2048私钥:openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out server.key
- 设置权限:chmod 600 server.key
接着生成CSR。Common Name字段务必填写实际访问的域名或IP,例如192.168.1.50或gitlab.internal。这里有个细节:如果证书要用于多个子域名,必须用SAN扩展,老旧的CN字段在Chrome 58之后已经不再被信任。命令里加-addext "subjectAltName=DNS:gitlab.internal,DNS:*.internal,IP:192.168.1.50"。
说白了,CSR就是一张申请表,里面写清楚“我是谁、我要加密哪个域名”。但真正让证书生效的是下一步的签名动作。
第3步:自签名证书与私有CA的本质区别
很多教程把“自签名证书”和“私有CA签发的证书”混为一谈,这是不对的。自签名证书是证书自己签自己,浏览器永远弹红色警告,除非手动导入信任库。私有CA则是先创建一个根证书,再用根证书的私钥去签服务器证书。两者的信任链完全不同。
生产环境里,我强烈建议用私有CA。原因很简单:你只需要在每台客户端设备上信任一次根证书,之后这个CA签发的所有证书都不会再报警告。而自签名证书每换一张就要重新导入一次,运维成本随设备数量线性增长。在内网证书信任链的设计中有更详细的分析。
创建私有CA的命令其实只有三行:
- openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out ca.key
- openssl req -x509 -new -key ca.key -days 3650 -out ca.crt -subj "/CN=Internal-CA"
- openssl x509 -in ca.crt -noout -fingerprint -sha256
第三行会输出根证书的SHA-256指纹,建议截图存档。后续排查证书问题时,指纹是最可靠的比对依据。
第4步:用CA签发服务器证书并配置SAN
有了根证书之后,签发服务器证书的流程就规范多了。先创建一个扩展文件server.ext,内容如下:
subjectAltName = DNS:gitlab.internal, IP:192.168.1.50
extendedKeyUsage = serverAuth
keyUsage = digitalSignature, keyEncipherment然后执行签发命令:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 825 -sha256 -extfile server.ext -out server.crt
注意-days 825这个数字。Apple从2020年起要求TLS证书有效期不超过398天,但那是针对公共CA的规定。本地私有CA不受此限制,你可以设3年、5年。但我的实际经验是:825天最合适——比两年多一点,减少续期频率,又不至于长到忘记证书什么时候过期。
签发完成后,用openssl verify -CAfile ca.crt server.crt验证。输出OK就说明整个信任链没问题。
第5步:部署到Nginx与客户端信任配置
Nginx配置里只需要两行:
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
然后nginx -t && systemctl reload nginx。证书部署本身不难,真正麻烦的是客户端信任。Windows、macOS、Linux、Android、iOS的导入方式各不相同。Windows最简单,双击ca.crt选择“安装证书”到“受信任的根证书颁发机构”。Linux需要把ca.crt复制到/usr/local/share/ca-certificates/然后执行update-ca-certificates。Android 11以上强制要求系统级信任,普通用户无法导入,这是目前私有CA最大的痛点。
说实话,如果你有超过50台设备需要导入根证书,建议直接上自动化证书分发方案,手动操作太容易漏。
常见故障:证书警告排查清单
证书配好之后浏览器仍然报警告,按以下顺序排查:第一,检查SAN是否包含实际访问的域名或IP——这是90%的故障原因。第二,确认客户端是否已经导入根证书,而不是只导入了服务器证书。第三,检查系统时间,证书有效期的判断完全依赖客户端本地时钟。第四,用openssl s_client -connect 192.168.1.50:443 -showcerts查看实际返回的证书链,确认中间没有缺失。
简单来讲,本地证书制作教程的难点从来不在命令本身,而在于理解信任链的传递逻辑。命令可以复制粘贴,但知道为什么这样配,才能在出问题时快速定位。
本地证书的制作和部署,核心就是五个环节:选算法、生成密钥对、确定签名方式(自签名还是私有CA)、签发配置SAN、部署并导入信任。把这五步跑通一次,后续维护只需要定期检查过期时间和新设备的信任导入。整个流程不依赖任何外部服务,完全离线可用——这正是内网环境最需要的特性。