安全配置
在多租户或网络环境不安全的场景下,需要对 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 的安全配置:
- ACL 访问控制:身份认证和权限控制
- TLS/SSL 加密:通信加密和双向认证
- 安全最佳实践:密钥管理、网络隔离、审计日志、最小权限
- 常见问题:ACL 验证失败、TLS 连接失败、主从同步问题
安全配置需要在安全性和便利性之间权衡,根据实际业务场景选择合适的安全级别。