Skip to content

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/ssl

2. 生成私钥

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.key

3. 生成证书签名请求(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.crt

5. 生成根证书(可选)

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.crt

CA签名证书(生产环境)

生产环境建议使用受信任的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.csr

2. 提交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文件中的参数进行控制:

参数默认值说明
ssloff是否启用SSL/TLS
ssl_cert_fileserver.crt服务器证书文件路径
ssl_key_fileserver.key服务器私钥文件路径
ssl_ca_file''根证书文件路径,用于验证客户端证书
ssl_crl_file''证书吊销列表文件路径
ssl_ciphers'HIGH:MEDIUM:+3DES:!aNULL'允许使用的加密套件
ssl_prefer_server_cipherson是否优先使用服务器端的加密套件
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_reloadoff是否支持重载时执行密码命令

服务器端配置步骤

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=1

3. 重启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.key

2. 证书格式问题

错误信息

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 PEM

3. 证书过期

错误信息

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_versionssl_max_protocol_version参数
  • 支持最高TLSv1.2
  • 加密套件配置较简单

PostgreSQL 10-11版本

  • 引入了ssl_prefer_server_ciphers参数
  • 增强了SSL性能
  • 支持更丰富的加密套件

PostgreSQL 12及以上版本

  • 引入了ssl_min_protocol_versionssl_max_protocol_version参数
  • 默认最低TLS版本为TLSv1.2
  • 支持TLSv1.3(PostgreSQL 12+)
  • 增强了证书验证机制
  • 支持更细粒度的SSL配置

PostgreSQL 13及以上版本

  • 进一步优化了TLSv1.3支持
  • 增强了SSL性能
  • 改进了证书错误信息

最佳实践

  1. 使用CA签名证书:在生产环境中,建议使用受信任的CA签名证书,而不是自签名证书
  2. 启用强加密套件:使用高强度的加密套件,如AES-256-GCM
  3. 使用最新的TLS版本:建议使用TLSv1.2或TLSv1.3,禁用旧版本(如TLSv1.0、TLSv1.1)
  4. 验证服务器证书:客户端连接时使用verify-caverify-full模式
  5. 定期更新证书:设置证书过期提醒,定期更新证书
  6. 保护私钥安全:确保私钥文件权限正确,仅允许postgres用户访问
  7. 配置客户端证书验证:对于敏感数据,建议要求客户端提供证书
  8. 监控SSL连接:定期检查SSL连接状态,确保所有连接都使用SSL
  9. 结合防火墙使用:SSL/TLS应与防火墙结合使用,提供多层安全防护
  10. 定期审计SSL配置:定期审查SSL配置,确保符合安全最佳实践

SSL性能优化

  1. 使用硬件加速:如果服务器支持,启用SSL硬件加速
  2. 优化加密套件:选择性能较好的加密套件,如AES-GCM
  3. 调整SSL缓冲区大小:根据需要调整ssl_buffer_size参数
  4. 使用连接池:SSL握手开销较大,使用连接池可以减少握手次数
  5. 考虑使用TLSv1.3:TLSv1.3比TLSv1.2有更好的性能

通过合理配置SSL/TLS,可以有效保护PostgreSQL数据库的通信安全,防止数据泄露和恶意攻击。在实际生产环境中,应根据业务需求和安全策略,制定适合的SSL/TLS配置方案,并定期进行审查和更新。