外观
MongoDB SSL/TLS 配置
证书准备
证书类型
自签名证书:
- 自行生成,无需第三方 CA 认证
- 适合开发和测试环境
- 生产环境不推荐,因为无法验证服务器身份
CA 签名证书:
- 由受信任的证书颁发机构(CA)签发
- 适合生产环境
- 提供完整的身份验证
链式证书:
- 包含服务器证书、中间 CA 证书和根 CA 证书
- 确保客户端可以验证服务器证书的完整信任链
生成自签名证书
1. 生成 CA 私钥和证书
bash
# 生成 CA 私钥
openssl genrsa -out ca.key 4096
# 生成 CA 证书签名请求(CSR)
openssl req -new -x509 -days 365 -key ca.key -out ca.crt -subj "/CN=MyMongoDBCA"2. 生成服务器私钥和 CSR
bash
# 生成服务器私钥
openssl genrsa -out mongodb.key 4096
# 生成服务器 CSR
openssl req -new -key mongodb.key -out mongodb.csr -subj "/CN=mongodb.example.com" -addext "subjectAltName = DNS:mongodb.example.com,DNS:localhost,IP:127.0.0.1,IP:192.168.1.100"3. 使用 CA 签名服务器证书
bash
# 使用 CA 签名服务器证书
openssl x509 -req -days 365 -in mongodb.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out mongodb.crt4. 合并证书和私钥
bash
# 合并证书和私钥为 PEM 文件
cat mongodb.crt mongodb.key > mongodb.pem
# 设置权限
chmod 600 mongodb.pem ca.key证书格式转换
PKCS#12 转 PEM:
bash
openssl pkcs12 -in mongodb.p12 -out mongodb.pem -nodesPFX 转 PEM:
bash
openssl pkcs12 -in mongodb.pfx -out mongodb.pem -nodes单节点 TLS 配置
配置文件设置
mongod.conf:
yaml
net:
port: 27017
bindIp: 0.0.0.0
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/mongodb.pem
CAFile: /etc/mongodb/ca.crt
allowInvalidHostnames: false
allowInvalidCertificates: false
disabledProtocols: TLS1_0,TLS1_1
security:
authorization: enabled命令行参数
bash
mongod --tlsMode requireTLS \
--tlsCertificateKeyFile /etc/mongodb/mongodb.pem \
--tlsCAFile /etc/mongodb/ca.crt \
--tlsAllowInvalidHostnames false \
--tlsAllowInvalidCertificates false \
--tlsDisabledProtocols TLS1_0,TLS1_1副本集 TLS 配置
配置文件示例
所有副本集成员的 mongod.conf:
yaml
net:
port: 27017
bindIp: 0.0.0.0
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/mongodb.pem
CAFile: /etc/mongodb/ca.crt
clusterFile: /etc/mongodb/mongodb.pem
security:
keyFile: /etc/mongodb/keyfile
authorization: enabled
replication:
replSetName: rs0副本集初始化
javascript
// 使用 TLS 连接到主节点
mongo --tls --tlsCertificateKeyFile /etc/mongodb/mongodb.pem --tlsCAFile /etc/mongodb/ca.crt --host mongodb.example.com:27017
// 初始化副本集
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "mongodb1.example.com:27017" },
{ _id: 1, host: "mongodb2.example.com:27017" },
{ _id: 2, host: "mongodb3.example.com:27017" }
]
})分片集群 TLS 配置
配置文件示例
mongos 配置:
yaml
net:
port: 27017
bindIp: 0.0.0.0
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/mongodb.pem
CAFile: /etc/mongodb/ca.crt
security:
keyFile: /etc/mongodb/keyfile
sharding:
configDB: configReplSet/config1.example.com:27019,config2.example.com:27019,config3.example.com:27019分片配置(mongod 作为分片):
yaml
net:
port: 27018
bindIp: 0.0.0.0
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/mongodb.pem
CAFile: /etc/mongodb/ca.crt
clusterFile: /etc/mongodb/mongodb.pem
security:
keyFile: /etc/mongodb/keyfile
authorization: enabled
sharding:
clusterRole: shardsvr
replication:
replSetName: shard1配置服务器配置:
yaml
net:
port: 27019
bindIp: 0.0.0.0
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/mongodb.pem
CAFile: /etc/mongodb/ca.crt
clusterFile: /etc/mongodb/mongodb.pem
security:
keyFile: /etc/mongodb/keyfile
authorization: enabled
sharding:
clusterRole: configsvr
replication:
replSetName: configReplSet客户端 TLS 连接
MongoDB Shell 连接
使用用户名密码认证:
bash
mongo --tls \
--tlsCAFile /etc/mongodb/ca.crt \
--host mongodb.example.com:27017 \
-u admin -p password \
--authenticationDatabase admin使用 X.509 证书认证:
bash
mongo --tls \
--tlsCertificateKeyFile /etc/mongodb/client.pem \
--tlsCAFile /etc/mongodb/ca.crt \
--host mongodb.example.com:27017 \
--authenticationMechanism MONGODB-X509 \
--authenticationDatabase '$external'MongoDB Compass 连接
- 打开 MongoDB Compass
- 选择 "Connect"
- 填写连接信息:
- Hostname: mongodb.example.com
- Port: 27017
- 选择 "SSL/TLS" 选项卡
- 选择 "Require TLS"
- 上传 CA 证书和客户端证书(如果需要)
- 点击 "Connect"
驱动连接示例
Python (pymongo):
python
from pymongo import MongoClient
client = MongoClient(
"mongodb://admin:password@mongodb.example.com:27017/admin",
tls=True,
tlsCAFile="/etc/mongodb/ca.crt",
tlsCertificateKeyFile="/etc/mongodb/client.pem"
)Node.js (mongodb):
javascript
const { MongoClient } = require('mongodb');
const uri = "mongodb://admin:password@mongodb.example.com:27017/admin";
const client = new MongoClient(uri, {
tls: true,
tlsCAFile: "/etc/mongodb/ca.crt",
tlsCertificateKeyFile: "/etc/mongodb/client.pem"
});Java (MongoDB Java Driver):
java
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.MongoClientSettings;
import com.mongodb.connection.netty.NettyStreamFactoryFactory;
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString("mongodb://admin:password@mongodb.example.com:27017/admin"))
.applyToSslSettings(builder -> {
builder.enabled(true);
builder.invalidHostNameAllowed(false);
})
.build();
MongoClient client = MongoClients.create(settings);X.509 认证
配置步骤
- 创建 X.509 用户:
javascript
use admin
db.getSiblingDB("$external").createUser({
user: "CN=client.example.com",
roles: [ { role: "root", db: "admin" } ]
})- 生成客户端证书:
bash
# 生成客户端私钥
openssl genrsa -out client.key 4096
# 生成客户端 CSR
openssl req -new -key client.key -out client.csr -subj "/CN=client.example.com"
# 使用 CA 签名客户端证书
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt
# 合并为 PEM 文件
cat client.crt client.key > client.pem- 使用 X.509 证书连接:
bash
mongo --tls \
--tlsCertificateKeyFile /etc/mongodb/client.pem \
--tlsCAFile /etc/mongodb/ca.crt \
--host mongodb.example.com:27017 \
--authenticationMechanism MONGODB-X509 \
--authenticationDatabase '$external'TLS 配置最佳实践
1. 证书管理
- 使用受信任的 CA:生产环境使用受信任的第三方 CA 签发的证书
- 定期轮换证书:证书有效期建议设置为 1 年,到期前及时轮换
- 安全存储证书:证书和私钥文件权限设置为 600,仅允许所有者访问
- 建立证书吊销机制:当证书泄露或过期时,及时吊销
2. TLS 协议和加密套件
- 禁用旧版协议:禁用 TLS 1.0 和 TLS 1.1,只启用 TLS 1.2 和 TLS 1.3
- 使用强加密套件:配置 MongoDB 使用强加密套件,如 AES-256-GCM
- 定期更新加密套件:根据安全建议更新加密套件配置
3. 配置验证
- 验证主机名:设置
allowInvalidHostnames: false,验证证书中的主机名 - 验证证书有效性:设置
allowInvalidCertificates: false,验证证书的有效性 - 使用完整的证书链:确保配置了完整的 CA 证书链
4. 监控和审计
- 监控 TLS 连接:监控 TLS 连接的建立和断开
- 审计 TLS 配置更改:记录 TLS 配置的更改
- 定期检查 TLS 配置:使用工具如
ssllabs.com检查 TLS 配置的安全性
5. 集群配置
- 所有组件启用 TLS:副本集成员之间、分片集群组件之间都启用 TLS
- 使用相同的 CA:所有节点使用相同的 CA 证书
- 配置集群文件:使用
clusterFile参数配置集群内部通信的证书
TLS 故障排查
常见错误
1. 证书验证失败
错误信息:
SSL handshake failed: SSL peer certificate validation failed: self signed certificate解决方案:
- 确保客户端信任服务器的 CA 证书
- 检查证书是否过期
- 检查证书中的主机名是否与实际主机名匹配
2. 协议版本不匹配
错误信息:
SSL handshake failed: SSL protocol error: unsupported protocol解决方案:
- 检查 MongoDB 版本支持的 TLS 协议版本
- 确保客户端和服务器使用兼容的 TLS 版本
- 更新 MongoDB 版本或客户端驱动
3. 加密套件不匹配
错误信息:
SSL handshake failed: no shared cipher解决方案:
- 检查客户端和服务器支持的加密套件
- 配置兼容的加密套件
- 更新 MongoDB 版本或客户端驱动
4. 私钥权限问题
错误信息:
SSL error: Unable to load private key file解决方案:
- 检查私钥文件的权限(应为 600)
- 确保 MongoDB 进程可以读取私钥文件
- 检查私钥文件的路径是否正确
故障排查步骤
- 检查 MongoDB 日志:查看 mongod 或 mongos 日志,获取详细的错误信息
- 验证证书:使用 openssl 验证证书的有效性bash
openssl x509 -in mongodb.crt -text -noout - 测试 TLS 连接:使用 openssl s_client 测试 TLS 连接bash
openssl s_client -connect mongodb.example.com:27017 -CAfile ca.crt - 检查配置文件:验证 TLS 配置参数是否正确
- 检查防火墙设置:确保 MongoDB 端口已开放
TLS 性能影响
性能开销
- CPU 开销:TLS 加密和解密会增加 CPU 使用率(约 5-10%)
- 网络开销:TLS 握手会增加连接建立时间
- 内存开销:维护 TLS 会话会增加内存使用
性能优化
- 使用硬件加速:使用支持 AES-NI 的 CPU 加速 TLS 加密
- 启用会话恢复:减少 TLS 握手开销
- 使用连接池:减少连接建立次数
- 优化加密套件:选择性能较好的加密套件
常见问题(FAQ)
Q1: MongoDB 支持 TLS 1.3 吗?
A1: 是的,MongoDB 4.2+ 支持 TLS 1.3。建议在生产环境中使用 TLS 1.3,因为它提供了更好的性能和安全性。
Q2: 如何在副本集环境中轮换 TLS 证书?
A2: 轮换副本集 TLS 证书的步骤:
- 生成新的证书
- 将新证书部署到所有副本集成员
- 逐个重启副本集成员(先从副本节点开始,最后重启主节点)
- 验证 TLS 连接正常
Q3: 自签名证书和 CA 签名证书有什么区别?
A3:
- 自签名证书:由自己生成,没有第三方 CA 认证,适合开发和测试环境
- CA 签名证书:由受信任的证书颁发机构签发,提供完整的身份验证,适合生产环境
Q4: 如何测试 MongoDB 的 TLS 配置是否正确?
A4: 可以使用以下方法测试:
- 使用 openssl s_client 测试 TLS 连接
- 使用 MongoDB Shell 连接并执行命令
- 检查 MongoDB 日志中是否有 TLS 相关错误
- 使用 SSL 扫描工具(如 ssllabs.com)检查 TLS 配置
Q5: 客户端连接 MongoDB 需要证书吗?
A5: 这取决于 MongoDB 的配置:
- 如果 MongoDB 配置了
mode: requireTLS,客户端必须使用 TLS 连接 - 如果 MongoDB 配置了客户端证书验证,客户端需要提供有效的证书
- 否则,客户端可以选择是否使用 TLS 连接
Q6: 如何在分片集群中配置 TLS?
A6: 在分片集群中,需要为所有组件配置 TLS:
- mongos 路由
- 分片(mongod)
- 配置服务器(mongod) 所有组件之间的通信都应该使用 TLS 加密,确保整个集群的安全性。
