VerneMQ无法自动断开持已吊销证书的在线客户端方案
问题根因
VerneMQ 依赖的 Erlang TLS 栈默认只在客户端建立连接、完成TLS握手阶段校验CRL,连接建立后既不会自动重载更新后的CRL文件,也不会周期性重校验已连接客户端的证书有效性。你现在的sidecar虽然定时把最新的CRL写到了共享目录,但已经握完手的长连接根本不会触发二次校验,自然踢不掉用吊销证书连上来的客户端。
方案1:CRL更新后触发全量重连(改几行脚本就行,不用改镜像)
这是成本最低的实现方式,你现有部署架构不用动,只需要改pull_crl.sh的逻辑:每次拉完新CRL先对比和旧版本有没有差异,有差异就替换正式CRL文件,同时调用VerneMQ本地管理接口踢掉所有在线连接,客户端自动重连时会被新的CRL规则拦截,吊销证书的客户端直接连不上。
改完的脚本参考:
#!/usr/bin/env sh if ! apk info | grep ^curl ; then apk update && apk add curl; fi OLD_CRL_HASH="" while true do echo $(date) # 先把新CRL下到临时文件,避免写一半被VerneMQ读到损坏的文件 curl -w "\n" --header "X-Vault-Token: $VAULT_TOKEN" http://vault.backend.svc.cluster.local:8200/v1/my-ca/crl/pem > /tmp/shared/ca.crl.tmp NEW_CRL_HASH=$(md5sum /tmp/shared/ca.crl.tmp | awk '{print $1}') if [ "$NEW_CRL_HASH" != "$OLD_CRL_HASH" ]; then # CRL有更新才替换+断连,平时不做无意义操作 mv /tmp/shared/ca.crl.tmp /tmp/shared/ca.crl # 调用VerneMQ本地接口断开所有会话,cleanup参数会清理掉会话残留状态 curl -X POST http://localhost:8888/api/v1/session/disconnect -d '{"cleanup": true}' OLD_CRL_HASH=$NEW_CRL_HASH else rm -f /tmp/shared/ca.crl.tmp fi sleep $SLEEP_INTERVAL done
这个方案唯一的影响是CRL更新时所有客户端会断一次线重连,一般MQTT客户端都有自动重连机制,业务侧基本感知不到,适合对可用性要求不是极端严苛的场景。
方案2:定向断开吊销证书客户端(无全量断连影响)
如果不能接受全量断连,就在脚本里加一层匹配逻辑:
- CRL更新后,用
openssl crl命令解析出文件里所有吊销的证书序列号 - 调用VerneMQ的
/api/v1/sessions接口拉取所有在线客户端的信息,里面会带每个连接使用的客户端证书序列号 - 只给序列号匹配吊销列表的客户端发断开请求,其余正常连接完全不受影响
这个逻辑写个简单的awk/python脚本就能实现,不需要修改VerneMQ本身的代码或配置。
必加配置补全
你当前的Deployment里漏了CRL强制校验的开关,需要在VerneMQ的环境变量里加下面这行,不然就算重连也可能出现CRL校验不生效的问题:
- name: DOCKER_VERNEMQ_LISTENER__SSL__CRL_CHECK value: "peer"
加上这个参数后,VerneMQ会在每次TLS握手时强制校验对端证书是否在CRL列表中,不会放行吊销证书的连接请求。
内容的提问来源于stack exchange,提问作者rp346
相关产品推荐
相关产品推荐

