SSL概述
SSL(Secure Sockets Layer)是网景公司(Netscape)设计的主要用于Web的安全传输协议,SSL是一种安全协议,用于加密客户端与服务器之间的网络通信,保护数据传输时的私密性和完整性。
PostgreSQL 默认的客户端与服务端之间通信是明文传输的,数据(包括用户名、密码、SQL 语句、查询结果)在网络中可能被窃听或篡改。
启用 SSL(TLS)后,客户端与服务端之间的所有通信都会经过加密,有效保障:
Ø 数据机密性:防止明文数据被中间人窃听;
Ø 数据完整性:防止数据在传输中被篡改;
Ø 身份验证:可通过校验服务端证书(`verify-ca` / `verify-full`)确认连接的是可信的数据库服务器。
适用场景:跨机房/跨公网访问数据库、等保合规要求、生产环境安全加固等。
SSL工作原理

SSL前提条件

服务端 SSL 配置
生成 服务端SSL 证书(方式一:自签名证书)
PostgreSQL 需要服务端证书(server.crt)和私钥(server.key)。生产环境建议使用企业内部 CA 签发;测试环境可直接使用自签名证书。
1、以 postgres 用户进入数据目录
2、成私钥(2048 位 RSA):
openssl genrsa -out server.key 2048
3、生成自签名证书(有效期 1 年)
openssl req -new -x509 -key server.key -out server.crt -days 365 -subj "/CN=db.example.com“
4、修改权限
chmod 600 server.*
生成 服务端SSL 证书(方式二:使用自有 CA 签发)
PostgreSQL 需要服务端证书(server.crt)和私钥(server.key)。生产环境建议使用企业内部 CA 签发;测试环境可直接使用自签名证书。
1、以 postgres 用户进入数据目录
2、创建 CA 根证书(仅需一次)
openssl req -new -x509 -days 3650 -nodes -keyout ca.key -out ca.crt -subj "/CN=MyCompanyCA"
3、生成服务端私钥
openssl genrsa -out server.key 2048
4、生成证书签名请求(CSR),SAN 需包含服务器域名和 IP
openssl req -new -key server.key -out server.csr -subj "/CN=db.example.com" \
-addext "subjectAltName=DNS:db.example.com,IP:10.0.0.10“
5、使用 CA 签发服务端证书(有效期 1 年)
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \ -CAcreateserial -out \
server.crt -days 365 \
-extfile <(printf "subjectAltName=DNS:db.example.com,IP:10.0.0.10")
6、修改权限
chmod 600 server.*
生成客户端证书(可选,用于 cert 双向认证)
若要启用「客户端证书认证」(`pg_hba.conf` 使用 `cert` 认证方式,客户端须持 CA 签发的证书才能登录),需额外生成客户端证书,将 `client.crt`、`client.key` 分发给对应数据库用户妥善保管(私钥权限 `600`)
1、生成客户端私钥
openssl genrsa -out client.key 2048
2、生成客户端 CSR(CN 填写数据库用户名,如 dbuser)
openssl req -new -key client.key -out client.csr -subj "/CN=postgres“
3、使用与签发 server.crt 相同的 CA 签发客户端证书
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out client.crt -days 365
把上面产生文件权限改为600。
启用 cert 认证的配套要求
1. `postgresql.conf` 中启用 `ssl_ca_file`(须指向签发客户端证书的 CA);
2. `pg_hba.conf` 中配置 `hostssl ... cert`;
3. 重启 PostgreSQL;
4. 客户端连接时指定 `sslcert` / `sslkey`。
配置postgresql.conf文件
# 证书文件路径(如与数据目录相对,直接写文件名)
ssl_cert_file = 'server.crt‘
ssl_key_file = 'server.key‘
# CA 根证书(可选):cert 客户端证书认证时必须启用;verify-full 模式客户端也用它校验链
# 启用 cert 认证时确保 ca.crt 路径正确
ssl_ca_file = 'ca.crt'
修改 pg_hba.conf`pg_hba.conf`
控制客户端认证规则,**SSL 类型规则使用 `hostssl` 关键字**。
`host` : 允许 TCP 明文或 SSL 连接
`hostssl` : 仅允许 SSL 加密连接(推荐生产环境)
`hostnossl`: 仅允许明文连接(一般用于排障)
`cert` 认证无需密码,凭客户端证书 + 私钥登录,证书 `CN` 必须等于数据库用户名;
hostssl all all 0.0.0.0/0 cert
启动数据库
1、重启数据库
pg_ctl restart
2、确认 SSL 已启用(psql 登录后查看)
psql -U postgres -c "SHOW ssl";
输出 `on` 即表示服务端 SSL 已开启。
客户端 SSL 连接
SSLMODE行为控制
连接字符串中的 `sslmode` 控制 SSL 行为,各取值含义如下:
| sslmode | 加密 | 校验服务端证书 | 说明
|--------- |------ |--------------- |------
| `disable` | 否 | 否 | 不使用 SSL
| `allow` | 视情况 | 否 | 优先明文,失败时尝试 SSL(PG 14 已移除该值)
| `prefer` | 是 | 否 | **默认值**,优先 SSL,失败回退明文
| `require` | 是 | 否 | 强制 SSL,但不校验证书有效性(防窃听,不防伪装)
| `verify-ca` | 是 | 是(校验 CA 链) | 强制 SSL,并校验服务端证书由可信 CA 签发
| `verify-full` | 是 | 是(校验 CA 链 + 主机名) | 最强安全级别,校验证书与主机名/域名匹配
psql 命令行连接
方式一:URI 格式
psql "postgresql://dbuser:mypassword@db.example.com:5432/mydb?sslmode=require "
方式二:键值对格式
psql "host=node1 dbname=postgres user=postgres sslmode=require "
方式三:verify-full(校验证书与主机名,需提供 CA 证书)
psql "host=node1 dbname=postgres user=postgres sslmode=verify-full sslrootcert=/home/postgres/.postgres/ca.crt "
方式四:基于客户端证书认证(配合 pg_hba 的 cert 认证)
psql "host=node1 dbname=postgres user=postgres sslmode=verify-full \ sslcert=/home/postgres/.postgres/client.crt sslkey=/home/postgres/.postgres/client.key \ sslrootcert=/home/postgres/.postgres/ca.crt"
连接成功后可通过 `\conninfo` 查看是否处于 SSL 状态:
```textYou are connected to database "mydb" as user "dbuser" on host "db.example.com" at port "5432".SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)```

PostgreSQL中文社区认证
与工信部人才交流中心合作,推出PostgreSQL初/中/高级证书,证书中明确指定适用于信息技术应用创新人才岗位能力评定要求。

