4、服务端证书签发:生成私钥、创建CSR、使用根CA签发证书
好,咱们接着往下走。上一章我们把根CA搭好了,相当于有了一个“身份证签发机关”。这一章,我们要给MQTT网关服务器办一张正式的“身份证”——也就是服务端证书。
整个过程分三步:生成服务端私钥 → 创建证书签名请求(CSR) → 拿根CA去签发。听起来不复杂,但每一步都有坑。我当年第一次部署生产环境时,就在CSR的Common Name上栽过跟头,后面细说。
核心逻辑:私钥是服务器的“秘密”,CSR是“申请表”,根CA是“审批盖章”。三者缺一不可。
4.1 生成服务端私钥
私钥是服务器的“数字指纹”,绝对不能泄露。我个人习惯用 2048位RSA,兼顾安全与性能。4096位当然更安全,但MQTT网关通常处理大量并发连接,密钥越长握手越慢,没必要。
执行命令:
# 生成2048位RSA私钥
openssl genrsa -out server.key 2048
你会看到类似这样的输出:
Generating RSA private key, 2048 bit long modulus (2 primes)
.............+++++
........................+++++
e is 65537 (0x010001)
嗯,这里要注意:私钥文件默认是明文存储的。如果服务器被入侵,私钥泄露,整个TLS体系就崩了。我在一个物联网项目里见过有人把私钥直接放在Git仓库里……那场面,简直是裸奔。
我的建议:生产环境一定要给私钥加密码保护。虽然每次重启服务需要手动输入密码,但可以用工具(如ssl-cert)配合systemd自动解锁。安全性和便利性要平衡。
加密码的命令也很简单:
# 生成带密码保护的私钥
openssl genrsa -aes256 -out server.key 2048
它会让你输入一个密码,至少12位,大小写+数字+符号。别偷懒。
4.2 创建证书签名请求(CSR)
CSR就是一张“申请表”,里面填了服务器的身份信息。根CA看到这张表,核实无误后才会签发证书。
创建CSR的命令:
openssl req -new -key server.key -out server.csr
执行后,它会交互式问你一堆问题。我直接给你一张表,告诉你每项该怎么填:
| 字段 | 说明 | 推荐值 |
|---|---|---|
| Country Name (2 letter code) | 国家代码 | CN |
| State or Province Name | 省份 | Beijing |
| Locality Name | 城市 | Beijing |
| Organization Name | 公司或组织名称 | YourCompany Inc. |
| Organizational Unit Name | 部门 | IoT Department |
| Common Name | 服务器域名或IP | mqtt.yourcompany.com |
| Email Address | 管理员邮箱 | admin@yourcompany.com |
⚠ 避坑指南:Common Name 是重中之重
我曾经帮一个客户排查TLS握手失败的问题,折腾了两天。最后发现,他的CSR里Common Name写的是“localhost”,但客户端连接的是公网域名。客户端验证证书时发现域名不匹配,直接拒绝连接。
记住:Common Name 必须填写客户端实际访问的域名或IP。如果MQTT网关有多个域名,建议用Subject Alternative Names(SAN),后面会讲。
如果你不想交互式输入,可以用一行命令搞定:
openssl req -new -key server.key -out server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=YourCompany/OU=IoT/CN=mqtt.yourcompany.com"
这样更干净,适合脚本自动化。
4.3 使用根CA签发服务端证书
现在,我们拿着CSR去找根CA盖章。签发命令如下:
openssl x509 -req -in server.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 -sha256
参数解释:
- -in server.csr:输入的CSR文件
- -CA ca.crt -CAkey ca.key:根CA的证书和私钥
- -CAcreateserial:自动创建序列号文件(ca.srl),用于唯一标识每张证书
- -out server.crt:输出的服务端证书
- -days 365:有效期1年。我建议别超过2年,定期轮换更安全
- -sha256:摘要算法。别用SHA1了,早就不安全了
执行成功后,你会得到 server.crt。可以用这个命令查看证书内容:
openssl x509 -in server.crt -text -noout
输出里会包含签发者(Issuer)、有效期、公钥信息等。重点看 Issuer 是不是你的根CA,Subject 是不是你的服务器域名。
最终产物:你手上现在有三个关键文件:
server.key— 私钥,放服务器上,权限设为600server.crt— 服务端证书,放服务器上,公开的ca.crt— 根CA证书,客户端需要导入它来验证服务端
4.4 验证证书链
签发完了别急着部署。先验证一下证书链是否完整:
openssl verify -CAfile ca.crt server.crt
如果输出 server.crt: OK,说明证书链没问题。如果报错,多半是根CA证书没对上,或者证书过期。
我记得有一次,我在一个嵌入式设备上部署MQTT网关,证书链验证一直失败。查了半天,发现设备上的根CA证书是旧版本的,公钥对不上。重新导入一次就好了。这种问题最坑,因为OpenSSL报错信息很模糊。
小技巧:把验证命令写进CI/CD流水线,每次签发新证书自动跑一遍。省得手动检查。
4.5 关于SAN(Subject Alternative Names)
如果你的MQTT网关有多个域名或IP(比如内网用IP,外网用域名),Common Name只能填一个。这时候就需要SAN扩展。
创建一个 server.ext 文件:
subjectAltName = DNS:mqtt.yourcompany.com, DNS:mqtt2.yourcompany.com, IP:192.168.1.100
签发时加上 -extfile 参数:
openssl x509 -req -in server.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 -sha256 \
-extfile server.ext
这样,客户端用任何一个域名或IP连接,证书验证都能通过。我强烈建议生产环境都用SAN,别省这一步。