跳到主要内容

安全配置

在多租户或网络环境不安全的场景下,需要对 RocketMQ 进行安全配置,防止未授权访问。本章将介绍 ACL 访问控制和 TLS/SSL 加密传输的配置方法。

安全机制概述

RocketMQ 提供了多层安全机制:

适用场景

场景安全需求推荐方案
私有网络无特殊需求可不开启
多部门共享隔离访问ACL 权限控制
公网暴露防止未授权ACL + TLS
金融/政务高安全要求ACL + TLS + 双向认证

ACL 访问控制

ACL(Access Control List)提供 Topic 级别的访问控制,可以限制用户对 Topic 的读写权限。

权限定义

权限含义说明
DENY拒绝禁止任何操作
PUB发送允许发送消息
SUB订阅允许订阅消费
PUB|SUB发送+订阅允许发送和消费

开启 ACL

步骤 1:修改 Broker 配置

conf/broker.conf 中添加:

# 开启 ACL 功能
aclEnable = true

# 指定 ACL 配置文件路径(可选,默认为 conf/plain_acl.yml)
aclFilePath = /data/rocketmq/conf/plain_acl.yml

步骤 2:创建 ACL 配置文件

创建 conf/plain_acl.yml 文件:

# 全局白名单(不进行权限校验)
globalWhiteRemoteAddresses:
- 10.10.103.* # 内网 IP 段
- 192.168.0.* # 内网 IP 段
- 127.0.0.1 # 本地

# 账户配置
accounts:
# 管理员账户
- accessKey: admin
secretKey: 12345678
admin: true # 管理员权限,拥有所有权限

# 生产者账户
- accessKey: producer_user
secretKey: producer_pass
whiteRemoteAddress: "" # IP 白名单,空表示不限制
admin: false
defaultTopicPerm: DENY # 默认 Topic 权限
defaultGroupPerm: SUB # 默认消费组权限
topicPerms:
- topicA=PUB # 对 topicA 有发送权限
- topicB=PUB # 对 topicB 有发送权限
groupPerms:
- groupA=SUB # 对 groupA 有订阅权限

# 消费者账户
- accessKey: consumer_user
secretKey: consumer_pass
admin: false
defaultTopicPerm: DENY
defaultGroupPerm: DENY
topicPerms:
- topicA=SUB # 对 topicA 有订阅权限
- topicB=SUB # 对 topicB 有订阅权限
groupPerms:
- groupA=SUB # 对 groupA 有订阅权限
- groupB=SUB # 对 groupB 有订阅权限

步骤 3:重启 Broker

sh bin/mqshutdown broker
nohup sh bin/mqbroker -c conf/broker.conf &

客户端配置 ACL

Java 客户端配置

import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.UtilAll;

public class AclProducer {
public static void main(String[] args) throws Exception {
// 创建生产者时注入 ACL 凭证
DefaultMQProducer producer = new DefaultMQProducer(
"ProducerGroup",
new AclClientRPCHook(new SessionCredentials("producer_user", "producer_pass"))
);

producer.setNamesrvAddr("localhost:9876");
producer.start();

// 发送消息...

producer.shutdown();
}
}

Spring Boot 集成

# application.yml
rocketmq:
name-server: localhost:9876
producer:
group: ProducerGroup
access-key: producer_user
secret-key: producer_pass
consumer:
group: ConsumerGroup
access-key: consumer_user
secret-key: consumer_pass
@Configuration
public class RocketMQConfig {

@Bean
public DefaultMQProducer producer() {
DefaultMQProducer producer = new DefaultMQProducer(
"ProducerGroup",
new AclClientRPCHook(new SessionCredentials(
"producer_user",
"producer_pass"
))
);
producer.setNamesrvAddr("localhost:9876");
return producer;
}
}

ACL 配置详解

globalWhiteRemoteAddresses:全局 IP 白名单

globalWhiteRemoteAddresses:
- 127.0.0.1 # 单个 IP
- 192.168.1.* # IP 段(通配符)
- 10.10.103.1-10 # IP 范围
- 10.10.103.* # IP 段

accounts:账户配置

accounts:
- accessKey: user1 # 用户名
secretKey: password1 # 密码
admin: false # 是否管理员
whiteRemoteAddress: "" # 该账户的 IP 白名单
defaultTopicPerm: DENY # 默认 Topic 权限
defaultGroupPerm: SUB # 默认消费组权限
topicPerms: # Topic 权限列表
- topicA=PUB|SUB
- topicB=PUB
groupPerms: # 消费组权限列表
- groupA=SUB
- groupB=SUB

权限校验流程

主从架构 ACL 配置

在 Master-Slave 架构下,Slave 需要访问 Master 进行同步,需要在 Master 的白名单中添加 Slave 的 IP:

# Master 的 plain_acl.yml
globalWhiteRemoteAddresses:
- 192.168.1.11 # Slave1 IP
- 192.168.1.12 # Slave2 IP

TLS/SSL 加密传输

TLS/SSL 可以加密客户端与服务端之间的通信,防止数据被窃听。

生成证书

步骤 1:创建证书脚本

#!/bin/bash
# 生成 CA 证书
keytool -genkeypair -alias ca -keyalg RSA -keysize 4096 \
-keystore ca.keystore -storepass 123456 \
-dname "CN=CA, OU=CA, O=CA, L=CA, ST=CA, C=CN" \
-ext bc:ca:true

# 导出 CA 证书
keytool -exportcert -alias ca -keystore ca.keystore \
-storepass 123456 -file ca.cer

# 生成 Broker 证书
keytool -genkeypair -alias broker -keyalg RSA -keysize 4096 \
-keystore broker.keystore -storepass 123456 \
-dname "CN=broker, OU=broker, O=broker, L=broker, ST=broker, C=CN"

# 使用 CA 签名 Broker 证书
keytool -importcert -alias ca -file ca.cer \
-keystore broker.keystore -storepass 123456 -noprompt

# 生成客户端证书
keytool -genkeypair -alias client -keyalg RSA -keysize 4096 \
-keystore client.keystore -storepass 123456 \
-dname "CN=client, OU=client, O=client, L=client, ST=client, C=CN"

# 使用 CA 签名客户端证书
keytool -importcert -alias ca -file ca.cer \
-keystore client.keystore -storepass 123456 -noprompt

步骤 2:执行脚本生成证书

chmod +x gen_certs.sh
./gen_certs.sh

Broker TLS 配置

修改 conf/broker.conf

# 开启 TLS
tlsEnable = true

# TLS 配置
tlsKeyStorePath = /data/rocketmq/certs/broker.keystore
tlsKeyStorePassword = 123456
tlsTrustStorePath = /data/rocketmq/certs/ca.keystore
tlsTrustStorePassword = 123456

# 是否需要客户端认证
tlsNeedClientAuth = true # 双向认证
# tlsNeedClientAuth = false # 单向认证

NameServer TLS 配置

修改 conf/namesrv.conf

# 开启 TLS
tlsEnable = true

tlsKeyStorePath = /data/rocketmq/certs/broker.keystore
tlsKeyStorePassword = 123456
tlsTrustStorePath = /data/rocketmq/certs/ca.keystore
tlsTrustStorePassword = 123456
tlsNeedClientAuth = true

客户端 TLS 配置

Java 客户端

import org.apache.rocketmq.client.producer.DefaultMQProducer;

public class TlsProducer {
public static void main(String[] args) throws Exception {
// 设置 TLS 配置
System.setProperty("rocketmq.client.tls.enable", "true");
System.setProperty("rocketmq.client.tls.truststore.path", "/path/to/client.keystore");
System.setProperty("rocketmq.client.tls.truststore.password", "123456");

// 双向认证时需要
System.setProperty("rocketmq.client.tls.keystore.path", "/path/to/client.keystore");
System.setProperty("rocketmq.client.tls.keystore.password", "123456");

DefaultMQProducer producer = new DefaultMQProducer("ProducerGroup");
producer.setNamesrvAddr("localhost:9876");
producer.start();

// 发送消息...
}
}

使用配置文件

创建 tls.properties

tls.client.auth.enable=true
tls.client.truststore.path=/path/to/client.keystore
tls.client.truststore.password=123456
tls.client.keystore.path=/path/to/client.keystore
tls.client.keystore.password=123456

安全最佳实践

1. 密钥管理

密钥生成建议

# 生成强随机密钥
openssl rand -base64 32

2. 网络隔离

网络隔离建议

  • NameServer 和 Broker 部署在内网
  • 使用防火墙限制访问来源
  • 生产者和消费者通过 VPN 或专线访问
  • 管理端口不对外开放

3. 审计日志

开启审计日志记录所有操作:

# broker.conf
# 开启消息轨迹
traceTopicEnable = true

# 配置审计日志
aclEnable = true

审计日志格式

2024-01-01 10:00:00 INFO  [ACL] User: admin, IP: 192.168.1.100, Operation: PUB, Topic: TopicA, Result: SUCCESS
2024-01-01 10:00:01 WARN [ACL] User: unknown, IP: 10.0.0.1, Operation: SUB, Topic: TopicA, Result: DENIED

4. 最小权限原则

# 错误示例:权限过大
accounts:
- accessKey: app1
secretKey: pass1
defaultTopicPerm: PUB|SUB # 给所有 Topic 权限
defaultGroupPerm: SUB

# 正确示例:最小权限
accounts:
- accessKey: app1
secretKey: pass1
defaultTopicPerm: DENY # 默认拒绝
defaultGroupPerm: DENY
topicPerms:
- topicA=PUB # 只给需要的权限
groupPerms:
- groupA=SUB

常见问题

1. ACL 验证失败

错误信息No permission to access resource

排查步骤

# 1. 检查配置文件是否正确
cat conf/plain_acl.yml

# 2. 检查 Broker 是否开启了 ACL
sh bin/mqadmin brokerStatus -n localhost:9876 -b broker-a | grep acl

# 3. 检查客户端是否传递了正确的凭证
# 4. 检查用户权限配置

2. TLS 连接失败

错误信息SSL handshake failed

排查步骤

# 1. 检查证书是否正确
keytool -list -keystore broker.keystore -storepass 123456

# 2. 检查证书有效期
keytool -list -v -keystore broker.keystore -storepass 123456

# 3. 检查客户端和服务端证书是否匹配
# 4. 检查 TLS 配置是否正确

3. 主从同步失败

问题:开启 ACL 后主从同步失败

解决方案

# 在 Master 的配置中添加 Slave IP 到白名单
globalWhiteRemoteAddresses:
- 192.168.1.11 # Slave IP

小结

本章介绍了 RocketMQ 的安全配置:

  1. ACL 访问控制:身份认证和权限控制
  2. TLS/SSL 加密:通信加密和双向认证
  3. 安全最佳实践:密钥管理、网络隔离、审计日志、最小权限
  4. 常见问题:ACL 验证失败、TLS 连接失败、主从同步问题

安全配置需要在安全性和便利性之间权衡,根据实际业务场景选择合适的安全级别。

延伸阅读