必须用自签名证书时,服务端能跑通不代表客户端能连上——关键在ca信任链是否完整传递;需先生成自签名ca(ca.crt)并用其签发服务器证书,服务端用mongodb.pem,客户端必须显式配置tlscafile指向ca.crt才能验证身份。

必须用自签名证书时,服务端能跑通不代表客户端能连上——关键在 CA 信任链是否完整传递。
生成自签名证书链(不是单个 PEM 文件)
很多失败源于只生成了 mongodb.pem(私钥+服务器证书),但没提供客户端验证所需的 CA 根证书。自签名场景下,你既是 CA 也是服务器,必须显式导出并分发 CA 证书。
- 先生成自签名 CA:
openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout ca.key -out ca.crt - 再用该 CA 签发服务器证书:
openssl req -new -key mongodb.key -out mongodb.csr,然后openssl x509 -req -in mongodb.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out mongodb.crt -days 365 - 最终服务端只需
mongodb.pem(cat mongodb.key mongodb.crt > mongodb.pem),但客户端必须拿到ca.crt才能验证服务器身份
mongod.conf 中的 tls 配置要点
新版 MongoDB(≥4.4)已弃用 ssl 配置块,统一使用 tls。且 mode: requireTLS 是硬性要求,否则客户端可降级到非加密连接。
-
certificateKeyFile必须指向合并后的mongodb.pem,路径需 MongoDB 进程有读权限(常见坑:SELinux 或文件属主不对) -
CAFile可选,但若启用tlsMode: requireTLS且客户端需双向认证(mTLS),就必须提供;仅服务端单向认证时,此项可省略 - 务必确认
bindIp包含监听地址(如0.0.0.0),否则本地生成的证书 CN/SAN 若为localhost,远程客户端连192.168.x.x会因主机名不匹配被拒绝
Node.js 驱动连接时的信任配置
即使服务端启用了 TLS,Node.js 驱动默认仍会校验服务器证书有效性。若用自签名 CA,不显式传入 ca 选项,会报 UNABLE_TO_VERIFY_LEAF_SIGNATURE。
- 连接字符串中不能只写
?tls=true,必须附加 CA:mongodb://localhost:27017/?tls=true&tlsCAFile=ca.crt - 代码中更可靠的方式是用
MongoClientOptions显式指定:{ tls: true, tlsCAFile: 'ca.crt' } - 开发时临时跳过验证(仅限调试):
{ tls: true, tlsAllowInvalidCertificates: true },但该选项会禁用全部证书校验,等同于裸奔
验证是否真走 TLS 以及证书是否被信任
别只看连接成功就认为 OK。实际加密和身份验证可能早已失效。
- 服务端日志里搜
connection accepted后是否带tls字样;连上后执行db.runCommand({ connectionStatus: 1 }),检查返回里的tls字段是否为true - 客户端用
openssl s_client -connect localhost:27017 -servername localhost -CAfile ca.crt直接测 TLS 握手,成功才说明证书链和主机名都对得上 - 最容易被忽略的是证书 SAN(Subject Alternative Name):自签名时若没加
-addext "subjectAltName = DNS:localhost,IP:127.0.0.1",现代驱动(尤其 6.x+)会直接拒连,哪怕 CN 是 localhost











