Appearance
RabbitMQ Erlang Cookie
一、概述
Erlang Cookie 是 RabbitMQ 集群节点间认证的核心机制。所有集群节点必须使用相同的 Cookie 才能相互通信。正确管理 Erlang Cookie 对于集群安全至关重要。
Cookie 认证流程
mermaid
sequenceDiagram
participant N1 as 节点1
participant N2 as 节点2
N1->>N2: 连接请求 + Cookie
N2->>N2: 验证 Cookie
alt Cookie 匹配
N2->>N1: 认证成功
Note over N1,N2: 建立集群连接
else Cookie 不匹配
N2->>N1: 认证失败
Note over N1,N2: 拒绝连接
end二、核心知识点
2.1 Cookie 文件位置
| 位置 | 说明 |
|---|---|
| /var/lib/rabbitmq/.erlang.cookie | 默认位置 |
| $HOME/.erlang.cookie | 用户主目录 |
| ERLANG_COOKIE 环境变量 | 环境变量指定 |
2.2 Cookie 文件权限
bash
# 正确的权限设置
chmod 600 /var/lib/rabbitmq/.erlang.cookie
chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie
# 验证权限
ls -la /var/lib/rabbitmq/.erlang.cookie
# 输出: -rw------- 1 rabbitmq rabbitmq 20 Jan 1 00:00 .erlang.cookie2.3 Cookie 生成
bash
# 方法1: 使用 openssl
openssl rand -base64 32 > /var/lib/rabbitmq/.erlang.cookie
# 方法2: 使用随机字符串
echo "MY_SECRET_COOKIE_$(date +%s)" > /var/lib/rabbitmq/.erlang.cookie
# 方法3: 使用 RabbitMQ 命令
rabbitmqctl eval 'rabbit_misc:cookie().'2.4 Cookie 安全要求
| 要求 | 说明 |
|---|---|
| 长度 | 至少 20 字符 |
| 复杂度 | 包含字母、数字、特殊字符 |
| 保密性 | 仅集群节点知晓 |
| 权限 | 文件权限 600 |
三、配置示例
3.1 同步 Cookie 脚本
bash
#!/bin/bash
# sync_cookie.sh
# 同步 Erlang Cookie 到所有节点
COOKIE_FILE="/var/lib/rabbitmq/.erlang.cookie"
NODES=("node1" "node2" "node3")
# 从第一个节点获取 Cookie
COOKIE=$(ssh root@${NODES[0]} "cat $COOKIE_FILE")
# 同步到所有节点
for node in "${NODES[@]}"; do
echo "同步 Cookie 到 $node..."
ssh root@$node "echo '$COOKIE' > $COOKIE_FILE"
ssh root@$node "chmod 600 $COOKIE_FILE"
ssh root@$node "chown rabbitmq:rabbitmq $COOKIE_FILE"
done
echo "Cookie 同步完成"3.2 Docker Cookie 配置
yaml
version: '3.8'
services:
rabbitmq:
image: rabbitmq:3.12-management
environment:
RABBITMQ_ERLANG_COOKIE: 'your_secret_cookie_here'
volumes:
- rabbitmq_data:/var/lib/rabbitmq3.3 Kubernetes Cookie 配置
yaml
apiVersion: v1
kind: Secret
metadata:
name: rabbitmq-cookie
type: Opaque
stringData:
erlang-cookie: "your_secret_cookie_here"
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: rabbitmq
spec:
template:
spec:
containers:
- name: rabbitmq
env:
- name: RABBITMQ_ERLANG_COOKIE
valueFrom:
secretKeyRef:
name: rabbitmq-cookie
key: erlang-cookie3.4 PHP Cookie 管理
php
<?php
class ErlangCookieManager
{
private array $nodes;
private string $sshUser;
public function __construct(array $nodes, string $sshUser = 'root')
{
$this->nodes = $nodes;
$this->sshUser = $sshUser;
}
public function generateCookie(): string
{
return base64_encode(random_bytes(32));
}
public function getCookieFromNode(string $node): ?string
{
$command = "ssh {$this->sshUser}@{$node} 'cat /var/lib/rabbitmq/.erlang.cookie' 2>/dev/null";
return trim(shell_exec($command) ?? '');
}
public function setCookieOnNode(string $node, string $cookie): bool
{
$commands = [
"echo '{$cookie}' > /var/lib/rabbitmq/.erlang.cookie",
"chmod 600 /var/lib/rabbitmq/.erlang.cookie",
"chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie",
];
foreach ($commands as $cmd) {
$fullCmd = "ssh {$this->sshUser}@{$node} '{$cmd}' 2>/dev/null";
shell_exec($fullCmd);
}
return true;
}
public function syncCookie(): array
{
$sourceNode = $this->nodes[0];
$cookie = $this->getCookieFromNode($sourceNode);
if (empty($cookie)) {
$cookie = $this->generateCookie();
$this->setCookieOnNode($sourceNode, $cookie);
}
$results = [];
foreach ($this->nodes as $node) {
$results[$node] = $this->setCookieOnNode($node, $cookie);
}
return [
'cookie' => $cookie,
'nodes' => $results,
];
}
public function verifyCookie(): array
{
$cookies = [];
foreach ($this->nodes as $node) {
$cookies[$node] = $this->getCookieFromNode($node);
}
$uniqueCookies = array_unique(array_filter($cookies));
return [
'consistent' => count($uniqueCookies) === 1,
'cookies' => $cookies,
];
}
public function generateSecurityReport(): string
{
$verification = $this->verifyCookie();
$report = "=== Erlang Cookie 安全报告 ===\n";
$report .= "时间: " . date('Y-m-d H:i:s') . "\n\n";
$report .= "Cookie 一致性: " . ($verification['consistent'] ? '一致' : '不一致') . "\n\n";
foreach ($verification['cookies'] as $node => $cookie) {
$masked = substr($cookie, 0, 4) . '****' . substr($cookie, -4);
$report .= "节点 {$node}: {$masked}\n";
}
return $report;
}
}
$manager = new ErlangCookieManager(['node1', 'node2', 'node3']);
echo $manager->generateSecurityReport();
// 同步 Cookie
$result = $manager->syncCookie();
echo "\nCookie 已同步到所有节点\n";四、常见问题与解决方案
4.1 Cookie 不一致
问题: 节点间 Cookie 不一致导致无法通信
解决方案:
bash
# 同步 Cookie
COOKIE=$(cat /var/lib/rabbitmq/.erlang.cookie)
for node in node2 node3; do
ssh $node "echo '$COOKIE' > /var/lib/rabbitmq/.erlang.cookie"
ssh $node "chmod 600 /var/lib/rabbitmq/.erlang.cookie"
ssh $node "chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie"
ssh $node "systemctl restart rabbitmq-server"
done4.2 Cookie 权限错误
问题: Cookie 文件权限不正确
解决方案:
bash
chmod 600 /var/lib/rabbitmq/.erlang.cookie
chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie五、最佳实践建议
5.1 安全建议
- 强 Cookie: 使用足够长度的随机 Cookie
- 保密存储: 不要在代码库中存储 Cookie
- 定期更换: 定期更换 Cookie
- 权限控制: 确保文件权限正确
5.2 运维建议
- 备份 Cookie: 安全备份 Cookie
- 文档记录: 记录 Cookie 管理流程
- 自动化: 使用脚本自动化管理
