Node/TypeScript使用pg 8.7.3开启SSL连接PostgreSQL报自签名证书链错误
pg 8.x连接PostgreSQL报自签名证书错误的长期解决方案
问题根因
pg 8.0及以上版本调整了SSL连接的默认校验逻辑:当传入ssl: true时,会默认启用Node.js TLS层的严格证书校验,拒绝所有不在系统可信链里的自签名证书;而7.x版本默认不会做严格的证书链校验,所以不会抛出这个错误。降级版本只是利用了旧版本的宽松默认配置,存在安全隐患,且旧版本已停止维护,不适合长期使用。
触发的报错信息如下:
Error: self signed certificate in certificate chain at TLSSocket.onConnectSecure at TLSSocket.emit (events.js:315:20) at TLSSocket._finishInit (_tls_wrap.js:935:8) at TLSWrap.ssl.onhandshakedone code: 'SELF_SIGNED_CERT_IN_CHAIN'
分场景解决方案
场景1:本地开发/内网测试环境(无公网暴露风险)
修改Pool的SSL配置,不要直接传布尔值true,而是传入配置对象显式关闭未授权证书拒绝逻辑,修改后的连接配置代码如下:
import { Pool } from 'pg'; console.log('[WORKER]: DB CONNECTION SSL =', process.env.DB_SSL) const pool = new Pool({ user: process.env.DB_USER, host: process.env.DB_HOST, database: process.env.DB_NAME, password: process.env.DB_PASSWORD, port: process.env.DB_PORT ? parseInt(process.env.DB_PORT) : 5432, ssl: process.env.DB_SSL === 'true' ? { rejectUnauthorized: false } : false }); export default pool;
注意:该配置会跳过证书合法性校验,存在中间人攻击风险,禁止在公网生产环境使用。
场景2:生产公网环境
不要关闭证书校验,正确配置CA证书信任链即可:
- 首先从PostgreSQL服务端运维方/云服务商控制台获取数据库实例对应的根CA证书文件
- 连接时读取证书内容,传入SSL配置的
ca字段,示例配置如下:
import { Pool } from 'pg'; import fs from 'fs'; import path from 'path'; // 读取CA证书文件内容 const caCert = fs.readFileSync(path.resolve(__dirname, './certs/postgres-root.crt')); const pool = new Pool({ user: process.env.DB_USER, host: process.env.DB_HOST, database: process.env.DB_NAME, password: process.env.DB_PASSWORD, port: process.env.DB_PORT ? parseInt(process.env.DB_PORT) : 5432, ssl: process.env.DB_SSL === 'true' ? { ca: caCert, // 生产环境保持rejectUnauthorized为true,默认值即为true可省略 rejectUnauthorized: true } : false }); export default pool;
如果使用的是云厂商托管PostgreSQL服务,直接在对应云平台的RDS控制台下载实例对应的根CA证书,按上述方式配置即可正常连接,不需要降级pg版本。
不推荐降级到7.x版本的原因
- pg 7.x分支已停止官方维护,后续不会再有安全补丁、Bug修复,对Node.js新大版本的兼容性也不会做适配
- 7.x版本默认跳过SSL证书校验的逻辑本身就是安全缺陷,公网环境下传输数据存在被窃听、篡改的风险
内容的提问来源于stack exchange,提问作者xyz83242
相关产品推荐
相关产品推荐

