Skip to content

集群安全

当涉及到 EMQX 集群的安全时,主要有两个方面需要考虑。

  • 确保每个节点在集群中监听的端口安全。
  • 对 Erlang 的 cookie 进行保密,见 node.cookie 配置。

TIP

建议通过配置防火墙规则来保持集群端口的内部防火墙规则,如 AWS 安全组,或 iptables。

集群内通信端口

为了形成一个集群,EMQX 节点需要通过一些常规端口进行互联

如果集群节点之间有防火墙,常规监听端口应该允许集群中的其他节点连通。

EMQX 节点之间有两种不同的通道进行通信。

Erlang 分布式传输端口

TIP

EMQX 采用了传统的端口映射机制,而非 Erlang Port Mapper Daemon, EPMD

Erlang 分布端口。ListeningPort = BasePort + Offset。 其中 BasePort 是 4370(默认不可以配置),Offset 是节点名称的后缀。 如果节点名称没有数字后缀,Offsset 就是 0。

例如,在 emqx.conf 中的 node.name = emqx@192.168.0.12 应该使 节点的监听端口为 4370,而 emqx1(或 emqx-1)的端口为 4371,以此类推。

集群 RPC 端口

默认情况下,每个 EMQX 节点有一个 RPC 监听端口。 防火墙应该配置成允许访问。

端口映射规则类似于 Erlang 分布式端口映射规则。 只有 "BasePort" 是 "5370"。

也就是说,在 emqx.conf 中的 node.name = emqx@192.168.0.12 应该使节点的 监听端口 5370,端口 5371 用于 emqx1(或 emqx-1),以此类推。

TIP

Docker 容器中的 EMQX 使用静态端口 5369 进行集群 RPC。

使用 TLS 为集群 RPC 传输层

TIP

TLS 是以增加 CPU 负载和 RAM 使用为代价的。

要为集群 RPC 配置 TLS,应在 emqx.conf 中进行以下配置:

rpc {
  driver = ssl
  # PEM format file containing the trusted CA (certificate authority) certificates that the listener uses to verify the authenticity of the cluster peers.
  cacertfile = "/path/to/cert/ca.pem"
  # PEM format file containing the SSL/TLS certificate chain for the listener. If the certificate is not directly issued by a root CA, the intermediate CA certificates should be appended after the listener certificate to form a chain.
  certfile = "/path/to/cert/domain.pem"
  # PEM format file containing the private key corresponding to the SSL/TLS certificate
  keyfile = "/path/to/cert/domain.key"
  # Set to 'verify_peer' to verify the authenticity of the clients' certificates, otherwise 'verify_none'.
  verify = verify_peer
  # If set to true, the handshake fails if the peer does not have a certificate to send, that is, sends an empty certificate. If set to false, it fails only if the peer sends an invalid certificate (an empty certificate is considered valid).
  fail_if_no_peer_cert = true

}

以下是创建证书和自签名 CA 的步骤。

  1. 使用 openssl 工具创建一个根 CA。

    # Create self-signed root CA:
    openssl req -nodes -x509 -sha256 -days 1825 -newkey rsa:2048 -keyout rootCA.key -out rootCA.pem -subj "/O=LocalOrg/CN=LocalOrg-Root-CA"
  2. 使用在步骤 1 创建的 rootCA.pem 为节点生成 CA 签名的证书。

    # Create a private key:
    openssl genrsa -out domain.key 2048
    # Create openssl extfile:
    cat <<EOF > domain.ext
    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    subjectAltName = @alt_names
    [alt_names]
    DNS.1 = backplane
    EOF
    # Create a CSR:
    openssl req -key domain.key -new -out domain.csr -subj "/O=LocalOrg"
    # Sign the CSR with the Root CA:
    openssl x509 -req -CA rootCA.pem -CAkey rootCA.key -in domain.csr -out domain.pem -days 365 -CAcreateserial -extfile domain.ext

    集群中的所有节点必须使用由同一 CA 签署的证书。

  3. 把生成的 domain.pemdomain.keyrootCA.pem 文件放到集群的每个节点上的 /var/lib/emqx/ssl。 确保 EMQX 用户可以读取这些文件,并且权限设置为 600

为 Erlang 分布式协议使用 TLS

TIP

TLS 是以增加 CPU 负载和 RAM 使用为代价的。

EMQX 核心节点用 Erlang 分布机制来同步数据库更新并管理集群中的节点,例如启停某个组件,收集运行指标等。

  • 确保 ssl_dist.conf 文件有正确的密钥和证书的路径。
  • 确保配置 cluster.proto_dist 被设置为 inet_tls

结合规则引擎策略与防火墙规则防御 SSRF

EMQX 连接器、数据桥接和动作会向外部服务建立出站网络连接。如果缺乏访问控制,错误配置或恶意的目标地址可能导致 EMQX 向内部或敏感网络发起非预期请求,即服务端请求伪造(SSRF)漏洞。EMQX 提供两种互补的防御手段:在配置更新时校验目标地址的内置规则引擎 SSRF 策略,以及在运行时强制执行网络边界的主机级出站访问控制。

优先启用 rule_engine.ssrf

从 EMQX 6.0.36.1.26.2.1 开始,EMQX 为连接器、数据桥接和动作等规则引擎相关的出站目标提供了集群级 SSRF 策略:

hocon
rule_engine {
  ssrf {
    enable = true
    allow_cidrs = []
    deny_cidrs = [
      "127.0.0.0/8",
      "::1/128",
      "169.254.0.0/16",
      "fe80::/10",
      "10.0.0.0/8",
      "172.16.0.0/12",
      "192.168.0.0/16",
      "fc00::/7",
      "0.0.0.0/32",
      "224.0.0.0/4",
      "ff00::/8",
      "100.100.100.200/32",
      "169.254.169.253/32"
    ]
    deny_hosts = [
      "metadata.tencentyun.com",
      "metadata.google.internal",
      "metadata.azure.internal"
    ]
  }
}

启用后,EMQX 会在配置创建或更新时校验出站目标。deny_hosts 中的主机会被直接拒绝;解析得到的 IP 会先匹配 allow_cidrs,如果没有命中,再继续匹配 deny_cidrs

为兼容现有部署,该策略默认关闭。建议在所有部署中启用,除非您的连接器或动作必须访问内部服务,在这种情况下,请先审查并调整 allow_cidrsdeny_cidrs 配置,再启用该策略。

何时仅启用 rule_engine.ssrf 通常就足够

如果同时满足以下条件,通常仅启用 rule_engine.ssrf 就已经足够:

  • 只有受信任的管理员可以创建或修改连接器、数据桥接或动作。
  • 出站目标是稳定且可预期的,例如固定的 SaaS 端点或已批准的公共服务。
  • 您的主要目标是在配置更新时阻止明显的 SSRF 目标或误配置。
  • 您不依赖后续可能被重新绑定到其他地址的 DNS 名称。

何时还应同时实施防火墙规则

如果满足以下任一条件,建议再增加 iptablesnftables、云安全组或 Kubernetes NetworkPolicy 等主机级出站访问控制:

  • 委派管理员可以配置命名空间范围内的资源。
  • 即使目标通过了配置时校验,EMQX 运行主机在运行时仍绝不能访问内部服务、元数据端点或管理网络。
  • 您需要防御 DNS rebinding 或其他“校验通过后目标地址发生变化”的场景。
  • 您的部署属于多租户、高风险场景,或需要在运行时强制执行严格的出站网络边界。

在规划出站访问限制时,建议:

  • 仅放行部署实际需要访问的目标地址,例如身份提供商、Webhook 接收端和连接器后端服务。
  • 默认拒绝 SSRF 攻击中常见的敏感地址,例如回环地址、链路本地地址以及实例元数据地址,除非您的部署明确需要访问它们。尤其建议显式阻止以下元数据端点:
    • 100.100.100.200,阿里云元数据服务
    • 169.254.169.253,AWS 外部元数据服务
    • 169.254.169.254,AWS 和 Azure 元数据服务
    • fd00:ec2::254,AWS IPv6 元数据服务
  • 如果您在 EC2 上使用 AWS 相关连接器或动作,并且通过省略 Access Key ID 与 Secret Access Key 的方式让 EMQX 从实例元数据服务获取凭据,请不要阻止 169.254.169.254。这不仅适用于 Amazon MSK IAM,也适用于 S3、S3 Tables、DynamoDB、Kinesis 等集成。该例外也应体现在您的 iptablesnftables 规则中。
  • 在生产环境启用前,先在预发或测试环境中仔细验证规则。
  • 如果 EMQX 运行在容器或 Kubernetes 中,应通过宿主机防火墙、云安全组或 Kubernetes NetworkPolicy 实现等效的出站访问控制。

rule_engine.ssrf 不能替代这些网络层控制。该策略只在配置创建或更新时校验目标;如果您需要防御 DNS rebinding,或担心目标在校验通过后被解析到不同地址,仍应使用运行时网络访问控制。

下面的 iptables 示例展示了基本思路。请根据您的环境调整网卡名称、端口和目标地址。如果宿主机未提供 iptables,请使用 nftables 配置等效规则:

bash
# 允许已建立的出站连接
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# 如宿主机需要,可放行 DNS 和 NTP
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p udp --dport 123 -j ACCEPT

# 仅允许访问经批准的外部服务
iptables -A OUTPUT -p tcp -d 198.51.100.10 --dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp -d 203.0.113.20 --dport 443 -j ACCEPT

# 阻止常见的元数据地址和本地地址
iptables -A OUTPUT -d 127.0.0.0/8 -j REJECT
# 如果 EC2 上的 AWS 相关连接器或动作需要通过实例元数据服务获取凭据,
# 请不要直接套用这条对 169.254.169.254 生效的整段拒绝规则,而应改为更具体的放行规则。
iptables -A OUTPUT -d 169.254.0.0/16 -j REJECT
iptables -A OUTPUT -d 100.100.100.200 -j REJECT
ip6tables -A OUTPUT -d fd00:ec2::254 -j REJECT

# 默认拒绝所有新的其他出站连接
iptables -A OUTPUT -m conntrack --ctstate NEW -j REJECT

如果您的宿主机使用 nftables 而非 iptables,也应实现同样的策略,并显式阻止这些已知元数据端点:100.100.100.200169.254.169.253169.254.169.254fd00:ec2::254。如果 EC2 上的 AWS 相关连接器或动作需要通过实例元数据服务获取凭据,请确保规则保留对 169.254.169.254 的访问。