RabbitMQ 消息队列安全加固实战:未授权访问防护配置

适用场景

使用 RabbitMQ 作为消息中间件的后端服务,尤其是部署在云服务器、容器集群中的场景。消息队列承载订单、支付、日志等业务数据,一旦被未授权访问,攻击者可读取、篡改甚至清空队列,造成数据泄露与业务中断。本文适用于 RabbitMQ 3.8.x/3.12.x/4.x 版本,覆盖 AMQP 协议端口与管理插件 Web 端口的双重加固。

前置条件

  • 已部署 RabbitMQ 并可通过 rabbitmqctl status 查看运行状态
  • 具备服务器 sudo 权限,可修改 /etc/rabbitmq/rabbitmq.conf
  • 了解本机防火墙配置方式(firewalld 或 ufw)
  • 如需 TLS 需准备证书(可自签或使用 CA 签发)

原理说明

RabbitMQ 未授权访问的常见成因有三个:其一,默认账号 guest/guest 仅限 localhost 登录,但很多部署为方便调试将其放开或未创建专用账号;其二,管理插件 Web 端口 15672 与 AMQP 端口 5672 直接暴露公网,配合弱口令即可被登录;其三,vhost 与权限未做隔离,单一账号可访问全部队列。历史上 RabbitMQ 亦曝出管理插件路径遍历(CVE-2019-18674)等漏洞,关闭公网暴露面是成本最低的缓解手段。

操作步骤

1. 加固默认账号并创建专用账号

# 删除 guest 账号(生产环境建议直接删除)
rabbitmqctl delete_user guest

# 创建专用业务账号并设置强密码
rabbitmqctl add_user order_service '<强密码>'

# 标记管理员(仅管理需要)
rabbitmqctl set_user_tags order_service management

# 设置权限:仅允许访问指定 vhost
rabbitmqctl set_permissions -p / order_service '^order\.' '^order\.' '^order\.'

2. vhost 隔离与权限最小化

# 为不同业务创建独立 vhost
rabbitmqctl add_vhost order_vhost
rabbitmqctl add_vhost payment_vhost

# 授权最小权限:conf(配置) / write(写) / read(读) 按需放开
rabbitmqctl set_permissions -p order_vhost order_service '^order\.' '^order\.' '^order\.'

权限参数按 configure / write / read 顺序书写,正则用于限定资源名,全部使用 ^前缀\. 模式可防止跨业务访问。

3. 关闭公网管理端口并限制监听

编辑 /etc/rabbitmq/rabbitmq.conf

# 关键参数:管理界面仅监听内网
management.tcp.port = 15672
management.tcp.ip = 127.0.0.1

# AMQP 端口同样收敛
listeners.tcp.default = 5672
listeners.tcp.local = 10.0.0.10:5672

若管理界面只给本机运维使用,可直接用 Nginx 反代并叠加认证,参考上一节做法。同时在防火墙层限制:

firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.1.0/24 port port=5672 protocol=tcp accept'
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.1.0/24 port port=15672 protocol=tcp accept'
firewall-cmd --reload

4. 启用 TLS 加密传输

# 生成自签证书(生产建议使用受信任 CA)
openssl req -x509 -nodes -newkey rsa:2048 -keyout /etc/rabbitmq/certs/server.key   -out /etc/rabbitmq/certs/server.crt -days 365 -subj "/CN=rabbitmq.example.com"
openssl dhparam -out /etc/rabbitmq/certs/dhparam.pem 2048
# rabbitmq.conf 追加
listeners.ssl.default = 5671
ssl_options.cacertfile = /etc/rabbitmq/certs/server.crt
ssl_options.certfile   = /etc/rabbitmq/certs/server.crt
ssl_options.keyfile    = /etc/rabbitmq/certs/server.key
ssl_options.verify     = verify_none
ssl_options.fail_if_no_peer_cert = false

重启后客户端改用 amqps:// 协议连接 5671 端口。生产环境应设置 verify = verify_peer 并配置 CA,实现双向校验。

5. 关闭不必要的插件

# 查看已启用插件
rabbitmq-plugins list

# 仅保留必要插件,卸载 MQTT/STOMP 等不用的协议插件
rabbitmq-plugins disable rabbitmq_mqtt
rabbitmq-plugins disable rabbitmq_stomp

# 重启生效
systemctl restart rabbitmq-server

配置验证

# 1. 检查监听端口(15672 应只在本机/内网)
ss -tlnp | grep -E '5672|15672'

# 2. 未授权连接 AMQP 应被拒绝
rabbitmqctl list_users
rabbitmqctl list_permissions -p order_vhost

# 3. 外部机器验证:应无法连接 15672(防火墙拦截)
nc -zv 10.0.0.10 15672

# 4. TLS 端口连通性
openssl s_client -connect 10.0.0.10:5671 -servername rabbitmq.example.com </dev/null | head -5

常见问题

Q1:删除 guest 后客户端连接报认证失败?

说明客户端仍使用 guest/guest 连接。正确做法:用 rabbitmqctl add_user 创建的专用账号连接,并确保 set_permissions 已对目标 vhost 授权。若为遗留服务,可临时用新账号在测试环境验证后再切换。

Q2:启用 TLS 后老客户端连不上怎么办?

TLS 与明文端口可以并存:保留 listeners.tcp.default = 5672 供内网明文使用(配合防火墙白名单),新增 5671 供跨网段加密传输,逐步迁移客户端后再关闭明文。切勿在未验证证书链的情况下对生产客户端强制 verify_peer

总结

RabbitMQ 安全加固的核心是「账号收敛 + 权限最小化 + 网络收敛 + 传输加密」:删除默认 guest、创建按 vhost 隔离的专用账号,管理端口仅监听内网并叠加防火墙白名单,生产链路启用 TLS。配合定期升级版本与插件最小化,可系统性降低消息队列被未授权访问与数据篡改的风险。