Appearance
RabbitMQ 集群 TLS 加密
一、概述
TLS(Transport Layer Security)加密是保护 RabbitMQ 集群通信安全的关键措施。通过 TLS 可以加密客户端连接、节点间通信和管理界面访问,防止数据泄露和中间人攻击。
TLS 加密架构
mermaid
graph TB
subgraph "TLS 加密通信"
C[客户端] -->|TLS| LB[负载均衡]
LB -->|TLS| N1[节点1]
LB -->|TLS| N2[节点2]
N1 <-->|TLS| N2
N1 -->|TLS| M[管理界面]
end
subgraph "证书链"
CA[根证书 CA]
CA --> S1[服务器证书]
CA --> S2[客户端证书]
end二、核心知识点
2.1 TLS 加密范围
| 加密类型 | 端口 | 说明 |
|---|---|---|
| AMQPS | 5671 | 客户端 TLS 连接 |
| HTTPS | 15671 | 管理界面 TLS |
| 集群 TLS | 25671 | 节点间 TLS 通信 |
| MQTT TLS | 8883 | MQTT TLS 连接 |
2.2 证书类型
| 证书类型 | 说明 | 用途 |
|---|---|---|
| CA 证书 | 根证书 | 签发其他证书 |
| 服务器证书 | 服务器身份 | 服务端 TLS |
| 客户端证书 | 客户端身份 | 客户端认证 |
2.3 TLS 配置参数
| 参数 | 说明 |
|---|---|
| cacertfile | CA 证书文件 |
| certfile | 服务器证书文件 |
| keyfile | 私钥文件 |
| verify | 验证模式 |
| fail_if_no_peer_cert | 无证书是否拒绝 |
三、配置示例
3.1 生成证书
bash
# 创建 CA
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt
# 创建服务器证书
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out server.crt -days 365 -sha256 \
-extfile <(echo "subjectAltName=DNS:rabbitmq-node1,DNS:rabbitmq-node2,DNS:rabbitmq-node3")
# 创建客户端证书
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
-out client.crt -days 365 -sha2563.2 RabbitMQ TLS 配置
ini
# /etc/rabbitmq/rabbitmq.conf
# AMQP TLS 配置
listeners.ssl.default = 5671
ssl_options.cacertfile = /etc/rabbitmq/ssl/ca.crt
ssl_options.certfile = /etc/rabbitmq/ssl/server.crt
ssl_options.keyfile = /etc/rabbitmq/ssl/server.key
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = false
ssl_options.honor_cipher_order = true
ssl_options.honor_ecc_order = true
ssl_options.versions.1 = tlsv1.3
ssl_options.versions.2 = tlsv1.2
# 管理界面 TLS
management.ssl.port = 15671
management.ssl.cacertfile = /etc/rabbitmq/ssl/ca.crt
management.ssl.certfile = /etc/rabbitmq/ssl/server.crt
management.ssl.keyfile = /etc/rabbitmq/ssl/server.key
# 集群间 TLS
distribution.listener.port_range.min = 25671
distribution.listener.port_range.max = 25671
distribution.ssl.cacertfile = /etc/rabbitmq/ssl/ca.crt
distribution.ssl.certfile = /etc/rabbitmq/ssl/server.crt
distribution.ssl.keyfile = /etc/rabbitmq/ssl/server.key3.3 客户端证书认证
ini
# /etc/rabbitmq/rabbitmq.conf
# 启用客户端证书认证
auth_mechanisms.1 = EXTERNAL
ssl_cert_login_from = common_name
# 证书到用户的映射
ssl_cert_login_from = subject_alternative_name3.4 PHP TLS 连接示例
php
<?php
class TLSConnectionManager
{
private string $host;
private int $port;
private string $cacert;
private string $cert;
private string $key;
public function __construct(
string $host,
int $port = 5671,
string $cacert = '/path/to/ca.crt',
string $cert = '/path/to/client.crt',
string $key = '/path/to/client.key'
) {
$this->host = $host;
$this->port = $port;
$this->cacert = $cacert;
$this->cert = $cert;
$this->key = $key;
}
public function createConnection()
{
$connection = new AMQPStreamConnection(
$this->host,
$this->port,
'guest',
'guest',
'/',
false,
'AMQPLAIN',
null,
'en_US',
3.0,
3.0,
null,
true,
$this->cacert,
$this->cert,
$this->key
);
return $connection;
}
public function testConnection(): array
{
try {
$connection = $this->createConnection();
$channel = $connection->channel();
$result = [
'status' => 'success',
'server_info' => $connection->getServerProperties(),
];
$channel->close();
$connection->close();
return $result;
} catch (Exception $e) {
return [
'status' => 'failed',
'error' => $e->getMessage(),
];
}
}
public function verifyCertificates(): array
{
$results = [];
foreach ([$this->cacert, $this->cert, $this->key] as $file) {
$results[$file] = [
'exists' => file_exists($file),
'readable' => is_readable($file),
'valid' => $this->validateCertificate($file),
];
}
return $results;
}
private function validateCertificate(string $file): bool
{
if (!file_exists($file)) {
return false;
}
$ext = pathinfo($file, PATHINFO_EXTENSION);
if (in_array($ext, ['crt', 'pem'])) {
$result = openssl_x509_read(file_get_contents($file));
return $result !== false;
}
if ($ext === 'key') {
$result = openssl_pkey_get_private(file_get_contents($file));
return $result !== false;
}
return true;
}
}
$manager = new TLSConnectionManager(
'rabbitmq.example.com',
5671,
'/etc/ssl/rabbitmq/ca.crt',
'/etc/ssl/rabbitmq/client.crt',
'/etc/ssl/rabbitmq/client.key'
);
$test = $manager->testConnection();
echo "连接测试: {$test['status']}\n";
$verify = $manager->verifyCertificates();
echo "\n证书验证:\n";
print_r($verify);四、常见问题与解决方案
4.1 证书验证失败
问题: 客户端无法验证服务器证书
解决方案:
bash
# 检查证书链
openssl verify -CAfile ca.crt server.crt
# 检查证书内容
openssl x509 -in server.crt -text -noout
# 检查私钥匹配
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md54.2 TLS 版本不兼容
问题: TLS 版本不匹配
解决方案:
ini
# 支持的 TLS 版本
ssl_options.versions.1 = tlsv1.3
ssl_options.versions.2 = tlsv1.2五、最佳实践建议
5.1 证书管理
- 使用 CA: 使用受信任的 CA 签发证书
- 定期更新: 定期更新证书
- 安全存储: 安全存储私钥
5.2 配置建议
- 禁用弱加密: 禁用弱加密算法
- 证书验证: 启用双向证书验证
- 协议版本: 使用 TLS 1.2 或更高版本
