ALB_Mosquitto_mTLS集成方案

AWS ALB + Mosquitto mTLS 安全集成方案(Header 透传模式)

1. 方案概述

本方案旨在解决"设备端 mTLS 认证"与"内网 Mosquitto 匿名访问"之间的安全断层问题。通过 AWS ALB 终结设备侧双向 TLS,并将客户端证书身份信息以自定义 Header 形式注入后端 TCP 流量,配合 Mosquitto 认证插件实现基于身份的动态访问控制,彻底消除内网匿名访问风险,同时保留 ALB 统一证书管理的便利性。

核心架构流程

复制代码
[IoT 设备] --(mTLS:8883)--> [AWS ALB] --(TCP:1883 + X-Client-Cert-CN)--> [Mosquitto Broker]
                                      |
                              [Auth Plugin] <--(读取Header)--> [ACL/DB]

2. 前置条件

  • AWS ALB 已配置 TLS Listener(端口 8883),并启用 Mutual Authentication (mTLS)
  • ALB 关联的 ACM Private CA 或自签 CA 信任库已正确配置
  • Mosquitto 版本 ≥ 2.0(支持动态安全模块与插件 API)
  • 内网安全组/NACL 仅允许 ALB 所在子网的 ENI 访问 Mosquitto 1883 端口
  • 已准备用于测试的有效/无效客户端证书

3. 详细实施步骤

3.1 ALB 配置:启用证书信息透传

在 ALB 的 TLS Listener 上配置自定义 Header,将客户端证书的 Common Name (CN) 传递给后端:

  1. 进入 EC2 Console → Load Balancers → 选择目标 ALB
  2. Listeners → 编辑 8883 端口监听器
  3. 在 "Mutual authentication" 部分确认已启用且模式为 "Verify client certificate"
  4. 添加自定义 Header:
    • Header Name: X-Client-Cert-CN
    • Header Value: ${client.cert.subject.cn}
  5. (推荐)添加指纹 Header 用于防伪造与审计:
    • Header Name: X-Client-Cert-Fingerprint
    • Header Value: ${client.cert.fingerprint.sha256}

⚠️ 关键注意:ALB 仅在 mTLS 握手成功时才会注入这些 Header。若设备未提供有效证书,连接将在 ALB 层被终止,不会到达 Mosquitto。此特性是方案安全性的基石。

3.2 Mosquitto 部署认证插件

推荐使用 mosquitto-go-auth 插件,它原生支持从 TCP 连接中提取 ALB 注入的 Header,无需修改 Mosquitto 源码。

安装插件(Docker 方式推荐)
复制代码
docker pull iegomez/mosquitto-go-auth:latest
配置 mosquitto.conf
复制代码
# 禁用匿名访问(必须!)
allow_anonymous false

# 加载认证插件
plugin /usr/lib/mosquitto/auth-plugin.so

# 插件配置:使用 HTTP 后端验证
auth_opt_backends http
auth_opt_http_host 127.0.0.1        # 认证服务地址
auth_opt_http_port 8080             # 认证服务端口
auth_opt_http_get_params clientid=%c,username=%u,cn=%h:X-Client-Cert-CN,fingerprint=%h:X-Client-Cert-Fingerprint
auth_opt_http_superuser_uri /api/mqtt/superuser
auth_opt_http_aclcheck_uri /api/mqtt/acl
auth_opt_http_timeout_ms 3000       # 超时设置,避免阻塞连接

3.3 开发轻量级认证服务

需部署一个 HTTP 微服务(Python/Go/Node.js 均可),接收插件请求并返回认证结果。以下为 Python Flask 示例:

复制代码
from flask import Flask, request, jsonify
import re

app = Flask(__name__)

# CN 白名单正则,防止 Header 注入攻击
CN_PATTERN = re.compile(r'^[a-zA-Z0-9\-\.]+$')

@app.route('/api/mqtt/acl', methods=['GET'])
def check_acl():
    cn = request.args.get('cn', '')
    topic = request.args.get('topic', '')
    acc = int(request.args.get('acc', 0))  # 1=SUB, 2=PUB
    
    # 1. 校验 CN 格式合法性
    if not CN_PATTERN.match(cn):
        return jsonify({"status": "deny"}), 403
        
    # 2. 业务逻辑:根据 CN 判断是否有权访问该主题
    # 示例:device-{id} 只能操作 devices/{id}/telemetry
    device_id = cn.replace('device-', '')
    allowed_pub_topic = f"devices/{device_id}/telemetry"
    allowed_sub_topic = f"devices/{device_id}/command"
    
    if acc == 2 and topic == allowed_pub_topic:
        return jsonify({"status": "allow"}), 200
    elif acc == 1 and topic == allowed_sub_topic:
        return jsonify({"status": "allow"}), 200
    else:
        return jsonify({"status": "deny"}), 403

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=8080)

3.4 ACL 策略设计建议

证书 CN 模式 允许发布 允许订阅 说明
device-{id} devices/{id}/telemetry devices/{id}/command 设备只能操作自己的主题
gateway-{region} gateways/{region}/+/uplink gateways/{region}/+/downlink 网关可代理子设备
admin-* # # 管理账号(仅限运维跳板机)

4. 安全加固要点

  1. Header 防伪 :Mosquitto 必须绑定到 127.0.0.1 或通过 VPC Security Group 严格限制来源 IP 仅为 ALB ENI,防止绕过 ALB 直接伪造 Header
  2. CN 白名单校验:认证服务中对 CN 做正则校验,避免特殊字符导致注入或路径遍历
  3. 日志审计 :Mosquitto 开启 log_type security,记录每次认证的 CN、IP、时间戳;认证服务同步写入结构化日志
  4. 证书吊销检查:ALB 的 mTLS 已内置 CRL/OCSP 检查,无需后端重复验证,但需确保 CRL 更新及时
  5. 超时与限流:在 ALB 上设置 Idle Timeout ≤ 60s;认证服务加 Redis 缓存(TTL 30s)减少查询压力,避免高频连接拖垮认证服务

5. 测试验证清单

  • 无证书设备连接 → ALB 拒绝,Mosquitto 无日志
  • 无效/过期证书设备连接 → ALB 拒绝,Mosquitto 无日志
  • 有效证书但 CN 不在 ACL 范围 → Mosquitto 返回 CONNACK 0x05 (Not Authorized)
  • 有效证书且 CN 匹配 → 正常收发指定主题消息
  • 尝试越权订阅其他设备主题 → 被 ACL 拦截,日志记录 deny
  • 直接从内网 IP 连接 1883(无 Header)→ 被插件拒绝
  • 认证服务宕机 → Mosquitto 拒绝所有新连接(fail-closed)

6. 后续演进建议

  • 短期(1-2天):按本方案落地,完成基础身份化改造
  • 中期:将认证服务接入公司统一 IAM/OAuth2 体系,实现证书与用户/设备账号绑定,支持动态权限下发
  • 长期:评估迁移至 EMQX Enterprise,其原生支持 ALB Header 认证 + 可视化 ACL 管理 + 规则引擎数据转发,免维护自定义插件,更适合大规模生产环境