mongodb副本集tls必须用openssl自建ca并签发含完整san的证书,配置需严格匹配net.tls三字段、clusterfile及主机名,否则连接失败。

证书必须用 OpenSSL 生成,不能用 mkcert 或 Let’s Encrypt 直接套用
MongoDB 副本集的 TLS 要求证书的 subjectAltName(SAN)必须显式包含所有节点的 DNS 名称和 IP 地址,且 keyUsage 和 extendedKeyUsage 必须匹配服务端用途。用 mkcert 生成的证书默认不带 SAN,Let’s Encrypt 证书通常只覆盖域名、不包含内网 IP,直接配置会报错 SSL peer certificate validation failed 或启动失败。
实操建议:
- 用 OpenSSL 自建 CA,再签发服务端证书;
openssl req -x509 -newkey rsa:4096 -days 3650 -keyout ca.key -out ca.crt -nodes - 为每个副本集成员单独生成 CSR,
subjectAltName列全该节点所有可被客户端访问的地址,例如:DNS.1 = node1.example.com, IP.1 = 192.168.1.10, IP.2 = 127.0.0.1 - 签发时加
-extfile指定扩展配置,确保keyUsage = digitalSignature,keyEncipherment,extendedKeyUsage = serverAuth - 最终每个节点需持有:自己的
server.pem(私钥 + 证书链)、CA 的ca.crt
net.tls 配置项不能只写 tlsMode,必须配齐三个关键字段
net.tls.mode 设为 requireTLS 只是开关,真正起效靠另外两个字段:缺少任一,mongod 启动会静默失败或拒绝 TLS 连接。
实操建议:
-
net.tls.certificateKeyFile:必须是 PEM 格式,且私钥不能加密(即不能有DEK-Info行),否则报错Failed to load certificate file: bad password -
net.tls.CAFile:必须指定 CA 根证书(ca.crt),用于验证客户端证书(如果启用双向认证)和校验自身证书链 -
net.tls.allowConnectionsWithoutCertificates:设为true才允许非证书客户端连入(单向 TLS);设为false则强制双向认证,但副本集内部通信也会被拦住——除非所有节点都配了net.tls.clusterFile
副本集节点间通信也要走 TLS,clusterFile 是独立配置项
即使 net.tls.mode = requireTLS,副本集成员之间的心跳、oplog 同步默认仍走明文,除非显式启用集群内部 TLS。不配 net.tls.clusterFile,会出现日志里反复刷 connection refused 或 no SSL certificate provided,但主节点状态仍是 PRIMARY,从节点却始终卡在 STARTUP2。
实操建议:
-
net.tls.clusterFile必须指向一个单独的 PEM 文件,内容是该节点的私钥 + 证书(可复用certificateKeyFile,但不推荐) -
net.tls.clusterCAFile必须和net.tls.CAFile一致,否则节点间互相不认 - 所有节点的
replSetName和host(在rs.initiate()里声明的)必须与各自证书里的 SAN 完全匹配,一个字母都不能差
mongo shell 连接时报 “unable to verify the first certificate” 怎么快速定位
这不是 MongoDB 错误,是 Node.js 驱动(或 shell 内部 TLS 层)校验失败的通用提示,根源几乎都在证书链或主机名不匹配上。
实操建议:
- 先用
openssl s_client -connect node1.example.com:27017 -CAfile ca.crt测试底层握手是否成功;失败就说明证书或网络问题 - 连接时显式传参:
mongo --host node1.example.com --port 27017 --tls --tlsCAFile ca.crt --tlsCertificateKeyFile client.pem;漏掉--tlsCAFile就会报这个错 - 检查 shell 版本:4.2+ 才支持完整 TLS 选项,旧版
--ssl参数已被弃用,混用会导致静默降级 - 副本集连接字符串里每个
host:port都必须出现在某个节点证书的 SAN 中;不能只写域名而证书里只有 IP










