TLS/SSL 加密通信
RabbitMQ支持TLS/SSL加密通信,确保客户端与Broker之间的消息传输安全,防止中间人攻击与数据泄露。
TLS/SSL 原理
加密流程
- 证书交换:服务端向客户端发送SSL证书
- 证书验证:客户端使用CA证书验证服务端证书合法性
- 密钥协商:双方协商加密算法与会话密钥
- 加密通信:后续所有通信使用会话密钥加密传输
加密协议对比
| 协议版本 | 安全性 | 推荐程度 |
|---|---|---|
| TLS 1.0 | 存在已知漏洞 | 禁用 |
| TLS 1.1 | 安全性一般 | 不推荐 |
| TLS 1.2 | 安全性高 | 推荐 |
| TLS 1.3 | 安全性最高,性能更好 | 强烈推荐 |
服务端证书配置
生成自签名证书(测试环境)
Bash
# 1. 生成 CA 私钥
openssl genrsa -out ca.key 4096
# 2. 生成 CA 证书
openssl req -new -x509 -days 365 -key ca.key -out ca.crt \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/CN=MyCA"
# 3. 生成服务端私钥
openssl genrsa -out server.key 4096
# 4. 生成服务端 CSR
openssl req -new -key server.key -out server.csr \
-subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/CN=rabbitmq.example.com"
# 5. 使用 CA 签发服务端证书
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt
# 6. 合并证书为 PEM 格式(RabbitMQ 需要)
cat server.crt server.key > server.pem
RabbitMQ 配置 TLS
ini
# rabbitmq.conf TLS 配置
listeners.ssl.default = 5671
ssl_options.cacertfile = /path/to/ca.crt
ssl_options.certfile = /path/to/server.crt
ssl_options.keyfile = /path/to/server.key
ssl_options.verify = verify_peer
ssl_options.fail_if_no_peer_cert = true
# TLS 版本与加密套件
ssl_options.versions.1 = tlsv1.2
ssl_options.versions.2 = tlsv1.3
ssl_options.ciphers.1 = ECDHE-ECDSA-AES256-GCM-SHA384
ssl_options.ciphers.2 = ECDHE-RSA-AES256-GCM-SHA384
生产环境必须使用受信任的CA签发的证书,禁止使用自签名证书。
Java 客户端加密连接
基础 TLS 连接
Java
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.util.concurrent.TimeoutException;
/**
* RabbitMQ TLS/SSL 加密连接示例
*/
public class TLSConnectionExample {
private static final String HOST = "rabbitmq.example.com";
private static final int TLS_PORT = 5671;
private static final String USERNAME = "app_user";
private static final String PASSWORD = "app_pass";
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost(HOST);
factory.setPort(TLS_PORT);
factory.setUsername(USERNAME);
factory.setPassword(PASSWORD);
factory.setVirtualHost("/");
// 配置 TLS
factory.useSslProtocol(createSSLContext());
factory.enableHostnameVerification();
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
channel.queueDeclare("secure_queue", true, false, false, null);
String message = "Encrypted message over TLS";
channel.basicPublish("", "secure_queue", null, message.getBytes());
System.out.println("TLS 加密消息发送成功");
}
}
private static SSLContext createSSLContext() throws Exception {
// 加载信任库(包含 CA 证书)
KeyStore trustStore = KeyStore.getInstance("JKS");
try (FileInputStream fis = new FileInputStream("/path/to/truststore.jks")) {
trustStore.load(fis, "changeit".toCharArray());
}
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
// 加载密钥库(包含客户端证书,可选双向认证时使用)
KeyStore keyStore = KeyStore.getInstance("JKS");
try (FileInputStream fis = new FileInputStream("/path/to/keystore.jks")) {
keyStore.load(fis, "changeit".toCharArray());
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, "changeit".toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return sslContext;
}
}
单向认证 vs 双向认证
| 类型 | 服务端证书 | 客户端证书 | 适用场景 |
|---|---|---|---|
| 单向认证 | 必须 | 不需要 | 一般加密通信场景 |
| 双向认证 | 必须 | 必须 | 高安全要求场景 |
双向认证需在服务端配置
ssl_options.fail_if_no_peer_cert = true。
证书管理
生成 Java Keystore
Bash
# 将 CA 证书导入信任库
keytool -import -alias myca -file ca.crt -keystore truststore.jks \
-storepass changeit -noprompt
# 将服务端证书导入密钥库
keytool -import -alias server -file server.pem -keystore keystore.jks \
-storepass changeit -keypass changeit
证书轮换
Bash
# 1. 生成新证书(使用相同 CN)
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server-new.crt
# 2. 更新 RabbitMQ 配置并重启
# 3. 客户端更新信任库
证书轮换期间新旧证书可同时有效,确保平滑过渡。
注意事项
- 端口区分:TLS使用5671端口,非加密使用5672端口
- 性能影响:TLS加密会增加约10-15%的CPU开销,需评估吞吐量
- 证书有效期:定期监控证书过期时间,设置自动续期告警
- 协议版本:强制使用TLS 1.2及以上版本,禁用不安全的旧版本
- 加密套件:优先选择ECDHE等前向安全的加密套件
要点总结
- 全链路加密:TLS/SSL确保客户端与Broker间通信不被窃听或篡改
- 证书管理:生产环境使用受信任CA签发证书,定期轮换
- 单向/双向认证:根据安全要求选择认证模式
- 协议与加密套件:强制TLS 1.2+,使用前向安全加密套件
- 性能评估:TLS会增加CPU开销,需合理规划集群容量
📝 发现内容有误?点击此处直接编辑