4、TLS单向认证实战:Mosquitto配置TLS、客户端连接测试、证书生成流程
好,咱们进入实战环节。
前面讲了TLS的理论,说白了就是加密通信、防窃听、防篡改。但光说不练假把式,今天咱们亲手把Mosquitto的TLS单向认证搭起来。
我个人习惯,先讲证书怎么生成,再讲服务端怎么配,最后用客户端连上去验证。这样流程最顺,你跟着做一遍,基本就不会出问题。
4.1 证书生成流程:从CA到服务端证书
单向认证,只需要服务端有证书,客户端验证服务端身份就行。
证书生成分三步:
- 生成CA根证书(自签名)
- 生成服务端私钥和证书签名请求(CSR)
- 用CA给服务端证书签名
嗯,这里要注意:千万别直接用自签名证书当服务端证书。我在项目中遇到过有人图省事,直接把自签名证书扔给Mosquitto用,结果客户端连接时证书链验证失败,折腾了半天才发现问题。
核心原则:服务端证书必须由CA签发,客户端信任CA根证书即可。
4.1.1 生成CA根证书
先创建一个目录,专门放证书文件。我习惯用 /etc/mosquitto/certs,你也可以放别的地方。
# 创建目录
sudo mkdir -p /etc/mosquitto/certs
cd /etc/mosquitto/certs
# 生成CA私钥(2048位,够用了)
openssl genrsa -out ca.key 2048
# 生成CA自签名证书,有效期10年
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyIoT/CN=MyCA"
这里 -subj 参数里的CN(Common Name)填什么?其实无所谓,CA证书的CN不参与验证,但建议填个有意义的名称,方便管理。
4.1.2 生成服务端证书
服务端证书的CN必须填服务器的域名或IP地址。为什么?因为客户端连接时会检查证书CN是否匹配服务器地址。我曾经踩过这个坑——CN填了个"test",结果客户端报错"Hostname mismatch",尴尬得很。
# 生成服务端私钥
openssl genrsa -out server.key 2048
# 生成证书签名请求(CSR)
openssl req -new -key server.key -out server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyIoT/CN=192.168.1.100"
# 用CA给服务端证书签名,有效期1年
openssl x509 -req -days 365 -in server.csr \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt
小技巧:如果服务器有多个域名或IP,可以用SAN(Subject Alternative Name)扩展。但单向认证场景下,CN匹配就够用了。
最终你会得到这些文件:
| 文件 | 用途 | 保密性 |
|---|---|---|
| ca.crt | CA根证书,分发给客户端 | 公开 |
| ca.key | CA私钥,必须保护好 | 绝密 |
| server.crt | 服务端证书,给Mosquitto用 | 公开 |
| server.key | 服务端私钥,必须保护好 | 绝密 |
4.2 Mosquitto配置TLS单向认证
证书准备好了,接下来配置Mosquitto。打开配置文件,我一般用 /etc/mosquitto/mosquitto.conf。
配置内容如下:
# 监听8883端口(MQTT over TLS标准端口)
listener 8883
# 证书文件路径
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
# 要求客户端提供证书?不,单向认证不需要
require_certificate false
# 允许匿名登录(生产环境建议用密码认证)
allow_anonymous true
注意:require_certificate false 是单向认证的关键。如果设成true,就变成双向认证了,客户端也必须提供证书。
配置完重启Mosquitto:
sudo systemctl restart mosquitto
检查一下端口是否监听成功:
sudo netstat -tlnp | grep 8883
如果看到 mosquitto 在监听8883,说明配置生效了。
4.3 客户端连接测试
服务端配好了,咱们用 mosquitto_pub 和 mosquitto_sub 来测试。
客户端需要做两件事:
- 指定TLS版本(推荐tlsv1.2)
- 提供CA根证书用于验证服务端
4.3.1 订阅端测试
mosquitto_sub -h 192.168.1.100 -p 8883 \
--cafile /etc/mosquitto/certs/ca.crt \
--tls-version tlsv1.2 \
-t "test/topic" -v
4.3.2 发布端测试
mosquitto_pub -h 192.168.1.100 -p 8883 \
--cafile /etc/mosquitto/certs/ca.crt \
--tls-version tlsv1.2 \
-t "test/topic" -m "Hello TLS!"
如果连接成功,订阅端会收到消息。如果失败,常见错误有:
- 证书验证失败:检查CA证书路径是否正确,或者服务端证书是否由该CA签发
- 主机名不匹配:检查服务端证书的CN是否与
-h参数一致 - 连接超时:检查防火墙是否放行了8883端口
调试技巧:加 -d 参数可以打印详细日志,比如 mosquitto_sub -d ...,能看到TLS握手过程。
4.4 避坑指南
做TLS配置时,有几个坑我反复踩过,分享给你:
- 证书权限问题:Mosquitto以mosquitto用户运行,证书文件必须可读。我曾经把证书权限设成600,结果Mosquitto读不了,启动失败。建议
chmod 644 *.crt,私钥chmod 600 *.key。 - CA证书链不完整:如果用了中间CA,需要把CA证书链合并到一个文件里。单向认证一般用自签名CA,不存在这个问题。
- TLS版本不兼容:老客户端可能不支持TLSv1.2,但为了安全,我建议强制使用TLSv1.2以上。
嗯,单向认证配置其实就这么简单。说白了就是三步:生成证书、配Mosquitto、客户端连接。你跟着做一遍,半小时就能搞定。
下一章咱们讲双向认证,那个稍微复杂一点,但原理是一样的。