• HAProxy终结TLS双向认证代理EMQX集群


    1. 背景介绍

      MQTT协议已经成为当前物联网领域的关键技术之一,当前市面上主流的实现MQTT协议的产品主要有 EMQX、Mosquito、NanoMQ等。本文以EMQX开源版为基础,构建 MQTT Broker 集群,并使用 HAProxy代理 MQTT Broker 集群,由 HAProxy 开启双向认证,并终结TLS,HAProxy 到 MQTT Broker 集群的流量采用非加密模式。

    2. 系统架构

    在这里插入图片描述
      设备端携带设备证书向NLB所在的域名发起业务请求,NLB将流量转发到 HAProxy 负载均衡服务,HAProxy校验设备证书的有效性,当校验通过后终结TLS,将流量分发到某个MQTT Broker节点。HAProxy的负载策略可采用循环负载。

    3. 证书签发

      使用 cfssl 工具签发设备证书。证书信任模型为:
    在这里插入图片描述

    3.1 创建根证书

    • 首先创建配置文件config.json
    {
       "signing": {
         "default": {
           "expiry": "262800h"
         },
         "profiles": {
           "intermediate": {
             "usages": ["cert sign", "crl sign"],
             "expiry": "700800h",
             "ca_constraint": {
               "is_ca": true,
               "max_path_len": 1
             }
          },
          "device": {
            "usages": [
                "client auth",
                "signing",
                "digital signing",
                "key encipherment",
                "server auth"
            ],
            "expiry": "262800h"
          }
         }
       }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 创建根证书配置文件 root.json
    {
        "CN": "emqx.com",
        "key": {
            "algo": "rsa",
            "size": 2048
        },
        "names": [
            {
                "C": "CN",
                "L": "WuHan",
                "O": "emqx",
                "OU": "EMQX Root CA",
                "ST": "China"
            }
        ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 创建根CA证书
    cfssl gencert -initca root.json  | cfssljson -bare CaRoot
    
    • 1
    • 执行上边命令后将会得到根证书私钥、根证书请求文件、根证书。
      在这里插入图片描述

    3.2 创建中间证书

    • 创建中间证书配置文件 intermediate.json
    {
      "CN": "intermediate.emqx.com",
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "WuHan",
          "L": "XS",
          "O": "EMQX intermediate CA",
          "OU": "EMQX intermediate CA"
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 使用根CA签发中间证书
    cfssl gencert -ca=./CaRoot.pem -ca-key=./CaRoot-key.pem -config=./config.json -profile=intermediate ./intermediate.json | cfssljson -bare CaIntermediate
    
    • 1
    • 执行上边命令后将会生成中间证书私钥、中间证书申请文件、中间证书
      在这里插入图片描述

    3.3 创建设备证书

    • 创建设备证书配置文件device-a-csr.json
    {
      "CN": "DEVICEAXXXXXXXX",
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "WuHan",
          "L": "XS",
          "O": "EMQX DEVICE",
          "OU": "EMQX DEVICE"
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 创建设备证书
    cfssl gencert -ca=./CaIntermediate.pem -ca-key=./CaIntermediate-key.pem -config=./config.json -profile=device ./device-a-csr.json | cfssljson -bare device-a
    
    • 1
    • 执行上边命令将会得到设备证书私钥、设备证书申请文件、设备证书
      在这里插入图片描述

    3.4 创建服务端证书

    • 创建服务端证书配置文件 emqx-server-csr.json
    {
      "CN": "emqx.xxx.com",
      "key": {
        "algo": "rsa",
        "size": 2048
      },
      "names": [
        {
          "C": "CN",
          "ST": "Hubei",
          "L": "Wuhan",
          "O": "emqx",
          "OU": "EMQX Server"
        }
      ]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 使用根CA签发服务端证书
    cfssl gencert -ca=./CaRoot.pem -ca-key=./CaRoot-key.pem -config=./config.json -profile=device ./emqx-server-csr.json | cfssljson -bare emqx-server
    
    • 1
    • 执行上边命令将会得到EMQX服务端证书私钥 emqx-server-key.pem、证书申请文件 emqx-server.csr、服务端证书emqx-server.pem
    • 将服务端证书私钥与服务端证书合并到一个PEM文件,得到 server-allinone.pem 证书文件。
    cat emqx-server-key.pem emqx-server.pem |tee server-allinone.pem
    
    • 1

    4. HAProxy开启双向认证

      修改/etc/haproxy/haproxy.cfg文件,开启MQTT Broker访问端口,并开启双向认证。

    frontend emqx-tls
            bind *:8091 ssl crt /etc/emqx/certs/server-allinone.pem ca-file /etc/haproxy/certs/CaIntermediate.pem ca-verify-file /etc/haproxy/certs/CaRoot.pem verify required
            # 一层证书信任模型,设备证书直接由根证书签发时,ca-file 配置根证书
            # bind *:8091 ssl crt /etc/emqx/certs/server-allinone.pem ca-file /etc/haproxy/certs/CaRoot.pem verify required
            mode tcp
            log global
            option tcplog
            default_backend emqx-backend
    
    backend emqx-backend
            mode tcp
            option tcplog
            balance roundrobin
            default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 500000 maxqueue 10000 weight 100
            server emqx-165 10.0.1.165:1883 check-send-proxy send-proxy-v2 check inter 10s fall 2 rise 5
            server emqx-171 10.0.1.171:1883 check-send-proxy send-proxy-v2 check inter 10s fall 2 rise 5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • ca-file 指定中间证书,用于校验设备端证书的有效性
    • ca-verify-file 指定根CA证书,用于校验中间证书的有效性,如果只有一层信任模型,这个参数通常不会使用
    • crt 指定服务端证书,此处的服务端证书包含了证书及私钥
    • verify required 表示开启双向认证,
    • check-send-proxy send-proxy-v2 用于开启 Proxy Protocol 协议,MQTT Broker 可获取到设备端的IP地址
    • maxconn 指定最大连接数,默认值2000,一定要修改这个值,否则设备连接最大数量将会被限制在2000个连接内

    当 HAProxy 设置了 check-send-proxy 与 send-proxy-v2 参数后,需要 EMQX 开启 proxy-protocol 协议。开启方式时修改 /etc/emqx/emqx.conf 配置文件,在 1883 监听端口配置 proxy-protocol = true

    listeners.tcp.default {
      bind = "0.0.0.0:1883"
      max_connections = 500000
      proxy_protocol = true
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5. 验证

       使用 MQTT客户端工具向NLB所在的IP地址发起连接请求,请求参数携带根CA证书,设备证书,设备私钥,详细信息如下图所示:
    在这里插入图片描述
      点击CONNECT按钮发起连接请求。
    在这里插入图片描述
      如上图所示,客户端成功连接到MQTT Broker。

    6. 总结

       HAProxy 作为一款非常优秀的四层均衡程序,在大量的生产项目中得到广泛的应用,相较于NGINX在七层负载场景中广泛应用,四层负载均衡服务在TCP服务负载业务场景上有着更好的性能优势。云商的NLB服务作为高可靠的负载均衡服务,为何不直接将NLB的流量负载分发到MQTT Broker节点,还额外的安装HAProxy负载均衡程序,主要原因是云商NLB的功能通常比较基础,无法满足企业额外的定制化需求,所以,大量的业务场景中使用云商的NLB作为第一层负载入口,定制化的业务处理交给后边的HAProxy负载均衡服务实现。

  • 相关阅读:
    【Flutter】2023 Google 开发者大会给 Fluter 带来了什么
    MySQL----常见的存储引擎
    栈的应用场景(三)
    【Ubuntu18.04 重启后卡在[OK]界面的解决方案】
    jvs-智能bi(自助式数据分析)9.1更新内容
    基于文本相似度的康复量表ICF映射研究
    07.适配器模式设计思想
    three.js
    虹科分享 | 软件供应链攻击如何工作?如何评估软件供应链安全?
    智慧排水监测系统,科技助力城市排水治理
  • 原文地址:https://blog.csdn.net/hzwy23/article/details/132747758