适用场景
使用 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。配合定期升级版本与插件最小化,可系统性降低消息队列被未授权访问与数据篡改的风险。