外观
PostgreSQL SSL/TLS配置
SSL/TLS配置概述
SSL/TLS是保护PostgreSQL数据库通信安全的重要机制,通过加密客户端与服务器之间的通信,可以防止数据窃听、篡改和中间人攻击。PostgreSQL从版本8.0开始支持SSL/TLS加密,建议在生产环境中始终启用。
证书准备
自签名证书(测试环境)
自签名证书适用于测试环境或内部网络,不需要第三方CA认证。
1. 创建证书目录
bash
mkdir -p /var/lib/pgsql/14/data/ssl
chown postgres:postgres /var/lib/pgsql/14/data/ssl
chmod 700 /var/lib/pgsql/14/data/ssl2. 生成私钥
bash
# 切换到postgres用户
su - postgres
# 生成私钥(无密码保护)
openssl genrsa -out /var/lib/pgsql/14/data/ssl/server.key 2048
# 设置私钥权限
chmod 600 /var/lib/pgsql/14/data/ssl/server.key3. 生成证书签名请求(CSR)
bash
openssl req -new -key /var/lib/pgsql/14/data/ssl/server.key -out /var/lib/pgsql/14/data/ssl/server.csr在生成CSR时,需要提供一些信息,其中"Common Name"应填写数据库服务器的主机名或IP地址。
4. 生成自签名证书
bash
openssl x509 -req -days 365 -in /var/lib/pgsql/14/data/ssl/server.csr -signkey /var/lib/pgsql/14/data/ssl/server.key -out /var/lib/pgsql/14/data/ssl/server.crt5. 生成根证书(可选)
bash
# 生成根私钥
openssl genrsa -out /var/lib/pgsql/14/data/ssl/root.key 2048
# 生成根证书
openssl req -new -x509 -days 3650 -key /var/lib/pgsql/14/data/ssl/root.key -out /var/lib/pgsql/14/data/ssl/root.crtCA签名证书(生产环境)
生产环境建议使用受信任的CA签名证书,提供更高的安全性和可信度。
1. 生成私钥和CSR
bash
openssl genrsa -out /var/lib/pgsql/14/data/ssl/server.key 2048
openssl req -new -key /var/lib/pgsql/14/data/ssl/server.key -out /var/lib/pgsql/14/data/ssl/server.csr2. 提交CSR给CA机构
将生成的CSR文件提交给受信任的CA机构,如DigiCert、Let's Encrypt等,获取签名证书。
3. 安装CA签名证书
将CA返回的签名证书和中间证书安装到服务器:
bash
# 安装服务器证书
cp server.crt /var/lib/pgsql/14/data/ssl/
# 安装中间证书(如果有)
cp intermediate.crt /var/lib/pgsql/14/data/ssl/
# 安装根证书
cp root.crt /var/lib/pgsql/14/data/ssl/PostgreSQL SSL/TLS配置参数
PostgreSQL的SSL/TLS配置主要通过postgresql.conf文件中的参数进行控制:
| 参数 | 默认值 | 说明 |
|---|---|---|
| ssl | off | 是否启用SSL/TLS |
| ssl_cert_file | server.crt | 服务器证书文件路径 |
| ssl_key_file | server.key | 服务器私钥文件路径 |
| ssl_ca_file | '' | 根证书文件路径,用于验证客户端证书 |
| ssl_crl_file | '' | 证书吊销列表文件路径 |
| ssl_ciphers | 'HIGH:MEDIUM:+3DES:!aNULL' | 允许使用的加密套件 |
| ssl_prefer_server_ciphers | on | 是否优先使用服务器端的加密套件 |
| ssl_min_protocol_version | 'TLSv1.2' | 允许的最低TLS版本(PostgreSQL 12+) |
| ssl_max_protocol_version | '' | 允许的最高TLS版本(PostgreSQL 12+) |
| ssl_ecdh_curve | 'prime256v1' | ECDH曲线名称 |
| ssl_dh_params_file | '' | DH参数文件路径 |
| ssl_passphrase_command | '' | 获取私钥密码的命令 |
| ssl_passphrase_command_supports_reload | off | 是否支持重载时执行密码命令 |
服务器端配置步骤
1. 编辑postgresql.conf文件
ini
# 启用SSL
ssl = on
# 配置证书文件路径
ssl_cert_file = 'ssl/server.crt'
ssl_key_file = 'ssl/server.key'
ssl_ca_file = 'ssl/root.crt' # 可选,用于验证客户端证书
# 配置加密套件和协议版本(PostgreSQL 12+)
ssl_min_protocol_version = 'TLSv1.2'
ssl_max_protocol_version = 'TLSv1.3'
ssl_ciphers = 'HIGH:!aNULL:!MD5:!3DES'2. 配置pg_hba.conf文件
在pg_hba.conf中配置客户端连接使用SSL:
# 强制使用SSL连接
hostssl all all 192.168.1.0/24 scram-sha-256
# 可选使用SSL连接
host all all 192.168.2.0/24 scram-sha-256
# 要求客户端提供证书
hostssl all all 192.168.3.0/24 scram-sha-256 clientcert=13. 重启PostgreSQL服务
bash
# Linux系统
systemctl restart postgresql-14
# Windows系统
net stop postgresql-x64-14
net start postgresql-x64-14客户端配置
psql客户端配置
1. 基本SSL连接
bash
# 基本SSL连接
psql "host=192.168.1.100 dbname=mydb user=myuser sslmode=require"
# 验证服务器证书
psql "host=192.168.1.100 dbname=mydb user=myuser sslmode=verify-ca sslrootcert=/path/to/root.crt"
# 验证服务器主机名
psql "host=192.168.1.100 dbname=mydb user=myuser sslmode=verify-full sslrootcert=/path/to/root.crt"2. SSL模式说明
| SSL模式 | 说明 |
|---|---|
| disable | 禁用SSL |
| allow | 优先使用非SSL连接,如果服务器要求则使用SSL |
| prefer | 优先使用SSL连接,如果不可用则使用非SSL |
| require | 必须使用SSL连接,但不验证证书 |
| verify-ca | 必须使用SSL连接,并验证服务器证书是由受信任的CA签名 |
| verify-full | 必须使用SSL连接,验证证书和服务器主机名 |
应用程序客户端配置
Python(psycopg2)
python
import psycopg2
conn = psycopg2.connect(
host="192.168.1.100",
database="mydb",
user="myuser",
password="mypassword",
sslmode="verify-full",
sslrootcert="/path/to/root.crt"
)Java(JDBC)
java
String url = "jdbc:postgresql://192.168.1.100:5432/mydb?ssl=true&sslmode=verify-full&sslrootcert=/path/to/root.crt";
Connection conn = DriverManager.getConnection(url, "myuser", "mypassword");Node.js(pg)
javascript
const { Client } = require('pg');
const client = new Client({
host: '192.168.1.100',
database: 'mydb',
user: 'myuser',
password: 'mypassword',
ssl: {
rejectUnauthorized: true,
ca: fs.readFileSync('/path/to/root.crt').toString()
}
});验证SSL/TLS连接
1. 使用psql验证
bash
# 连接数据库
psql "host=192.168.1.100 dbname=mydb user=myuser sslmode=require"
# 查看连接是否使用SSL
mydb=> \conninfo
You are connected to database "mydb" as user "myuser" on host "192.168.1.100" at port "5432".
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)2. 查询pg_stat_ssl视图
sql
-- 查看所有SSL连接
SELECT * FROM pg_stat_ssl;
-- 查看SSL连接数量
SELECT count(*) FROM pg_stat_ssl WHERE ssl IS TRUE;3. 使用openssl验证
bash
openssl s_client -connect 192.168.1.100:5432 -starttls postgres常见问题与故障排查
1. 私钥权限问题
错误信息:
fatal: could not load private key file "server.key": Permission denied解决方法:
bash
chmod 600 /var/lib/pgsql/14/data/ssl/server.key
chown postgres:postgres /var/lib/pgsql/14/data/ssl/server.key2. 证书格式问题
错误信息:
fatal: could not load certificate file "server.crt": wrong file format解决方法:确保证书格式正确,使用PEM格式而不是DER格式。
bash
# 转换DER格式为PEM格式
openssl x509 -in server.crt.der -out server.crt -outform PEM3. 证书过期
错误信息:
fatal: connection requires TLS/SSL, but server does not support it解决方法:更新证书。
4. SSL版本不兼容
错误信息:
SSL connection error: sslv3 alert handshake failure解决方法:检查客户端和服务器支持的SSL/TLS版本,确保版本兼容。
版本差异
PostgreSQL 9.x版本
- 默认SSL模式为
off - 不支持
ssl_min_protocol_version和ssl_max_protocol_version参数 - 支持最高TLSv1.2
- 加密套件配置较简单
PostgreSQL 10-11版本
- 引入了
ssl_prefer_server_ciphers参数 - 增强了SSL性能
- 支持更丰富的加密套件
PostgreSQL 12及以上版本
- 引入了
ssl_min_protocol_version和ssl_max_protocol_version参数 - 默认最低TLS版本为TLSv1.2
- 支持TLSv1.3(PostgreSQL 12+)
- 增强了证书验证机制
- 支持更细粒度的SSL配置
PostgreSQL 13及以上版本
- 进一步优化了TLSv1.3支持
- 增强了SSL性能
- 改进了证书错误信息
最佳实践
- 使用CA签名证书:在生产环境中,建议使用受信任的CA签名证书,而不是自签名证书
- 启用强加密套件:使用高强度的加密套件,如AES-256-GCM
- 使用最新的TLS版本:建议使用TLSv1.2或TLSv1.3,禁用旧版本(如TLSv1.0、TLSv1.1)
- 验证服务器证书:客户端连接时使用
verify-ca或verify-full模式 - 定期更新证书:设置证书过期提醒,定期更新证书
- 保护私钥安全:确保私钥文件权限正确,仅允许postgres用户访问
- 配置客户端证书验证:对于敏感数据,建议要求客户端提供证书
- 监控SSL连接:定期检查SSL连接状态,确保所有连接都使用SSL
- 结合防火墙使用:SSL/TLS应与防火墙结合使用,提供多层安全防护
- 定期审计SSL配置:定期审查SSL配置,确保符合安全最佳实践
SSL性能优化
- 使用硬件加速:如果服务器支持,启用SSL硬件加速
- 优化加密套件:选择性能较好的加密套件,如AES-GCM
- 调整SSL缓冲区大小:根据需要调整
ssl_buffer_size参数 - 使用连接池:SSL握手开销较大,使用连接池可以减少握手次数
- 考虑使用TLSv1.3:TLSv1.3比TLSv1.2有更好的性能
通过合理配置SSL/TLS,可以有效保护PostgreSQL数据库的通信安全,防止数据泄露和恶意攻击。在实际生产环境中,应根据业务需求和安全策略,制定适合的SSL/TLS配置方案,并定期进行审查和更新。
