外观
PostgreSQL SSL/TLS配置
SSL/TLS 证书生成
SSL/TLS 证书是实现加密通信的基础,PostgreSQL 支持自签名证书和第三方权威机构签发的证书。
1. 自签名证书生成
自签名证书适用于内部测试和私有环境,以下是生成步骤:
bash
# 创建证书存储目录
mkdir -p /var/lib/postgresql/15/main/ssl
cd /var/lib/postgresql/15/main/ssl
# 生成根证书私钥(2048位,带密码保护)
openssl genrsa -des3 -out root.key 2048
# 生成根证书签名请求
openssl req -new -key root.key -out root.csr
# 生成自签名根证书(有效期10年)
openssl x509 -req -in root.csr -signkey root.key -out root.crt -days 3650
# 生成服务器私钥(2048位,无密码保护,方便PostgreSQL自动加载)
openssl genrsa -out server.key 2048
# 生成服务器证书请求,指定服务器名称为postgres-server
openssl req -new -key server.key -out server.csr -subj "/CN=postgres-server"
# 使用根证书签署服务器证书(有效期10年)
openssl x509 -req -in server.csr -CA root.crt -CAkey root.key -CAcreateserial -out server.crt -days 3650
# 设置证书文件权限,确保只有postgres用户可访问
chmod 600 server.key
chown postgres:postgres *.key *.crt *.csr2. 使用 Let's Encrypt 证书
Let's Encrypt 提供免费的受信任证书,适用于生产环境:
bash
# 安装 Certbot 工具(用于获取 Let's Encrypt 证书)
sudo apt-get install certbot
# 使用独立模式获取证书,指定域名 postgres.example.com
sudo certbot certonly --standalone -d postgres.example.com
# 将获取的证书复制到 PostgreSQL 证书目录
sudo cp /etc/letsencrypt/live/postgres.example.com/fullchain.pem /var/lib/postgresql/15/main/ssl/server.crt
sudo cp /etc/letsencrypt/live/postgres.example.com/privkey.pem /var/lib/postgresql/15/main/ssl/server.key
# 设置正确的文件权限和所有者
sudo chown postgres:postgres /var/lib/postgresql/15/main/ssl/*
sudo chmod 600 /var/lib/postgresql/15/main/ssl/server.key服务器 SSL/TLS 配置
配置 PostgreSQL 服务器使用 SSL/TLS 加密连接,需要修改主配置文件并调整认证规则。
1. 基础配置
修改 postgresql.conf 文件,启用 SSL 并配置证书路径:
txt
# 启用 SSL 加密连接
ssl = on
# 指定 SSL 证书文件路径
ssl_cert_file = 'ssl/server.crt' # 服务器证书
ssl_key_file = 'ssl/server.key' # 服务器私钥
ssl_ca_file = 'ssl/root.crt' # 根证书(可选,用于客户端证书验证)
# 配置允许的 SSL 协议版本
ssl_min_protocol_version = 'TLSv1.2' # 最低使用 TLS 1.2
ssl_max_protocol_version = 'TLSv1.3' # 最高支持 TLS 1.3
# 配置加密算法套件
ssl_ciphers = 'HIGH:!aNULL:!MD5:!3DES' # 使用高强度加密算法,禁用弱算法
ssl_prefer_server_ciphers = on # 优先使用服务器指定的加密算法2. 客户端认证配置
修改 pg_hba.conf 文件,配置不同来源的 SSL 连接要求:
txt
# 要求所有远程 IPv4 和 IPv6 连接使用 SSL 加密
hostssl all all 0.0.0.0/0 md5
hostssl all all ::/0 md5
# 仅允许本地连接使用非 SSL 方式
local all all peer
host all all 127.0.0.1/32 md5
host all all ::1/128 md5
# 要求特定网段的客户端提供有效的 SSL 证书
# 这是双向 SSL 认证配置
hostssl all all 192.168.1.0/24 cert clientcert=13. 重启数据库使配置生效
bash
# 重启 PostgreSQL 服务,使 SSL 配置生效
sudo systemctl restart postgresql客户端 SSL/TLS 配置
客户端连接 PostgreSQL 服务器时,需要根据服务器的 SSL 配置选择合适的连接方式和验证级别。
1. psql 客户端配置
psql 是 PostgreSQL 自带的命令行客户端,支持多种 SSL 连接模式:
bash
# 基本 SSL 连接:要求使用 SSL,但不验证证书
psql "host=postgres-server port=5432 dbname=mydb user=myuser sslmode=require"
# 验证服务器证书:确保连接到的是受信任的服务器
psql "host=postgres-server port=5432 dbname=mydb user=myuser sslmode=verify-ca sslrootcert=root.crt"
# 验证服务器主机名:确保连接到的是正确的服务器,防止中间人攻击
psql "host=postgres-server port=5432 dbname=mydb user=myuser sslmode=verify-full sslrootcert=root.crt"
# 使用客户端证书:双向 SSL 认证,服务器也验证客户端身份
psql "host=postgres-server port=5432 dbname=mydb user=myuser sslmode=verify-full sslrootcert=root.crt sslcert=client.crt sslkey=client.key"2. 应用程序配置
不同编程语言的 PostgreSQL 客户端库都支持 SSL 连接配置,以下是常见语言的配置示例:
Python (psycopg2)
Python 的 psycopg2 库是 PostgreSQL 最常用的客户端库之一:
python
import psycopg2
# 配置 SSL 连接参数
conn = psycopg2.connect(
host="postgres-server",
port=5432,
dbname="mydb",
user="myuser",
password="mypassword",
sslmode="verify-full", # 使用最高级别的 SSL 验证
sslrootcert="root.crt", # 根证书路径
sslcert="client.crt", # 客户端证书路径
sslkey="client.key" # 客户端私钥路径
)
# 使用连接执行查询
with conn.cursor() as cur:
cur.execute("SELECT 1;")
result = cur.fetchone()
print(result)Java (JDBC)
Java 应用程序使用 PostgreSQL JDBC 驱动连接数据库:
java
// 配置 SSL 连接 URL
String url = "jdbc:postgresql://postgres-server:5432/mydb?" +
"sslmode=verify-full&" +
"sslrootcert=root.crt&" +
"sslcert=client.crt&" +
"sslkey=client.key";
// 建立数据库连接
Connection conn = DriverManager.getConnection(url, "myuser", "mypassword");
// 使用连接执行查询
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1;");
while (rs.next()) {
System.out.println(rs.getInt(1));
}Node.js (pg)
Node.js 应用程序使用 pg 模块连接 PostgreSQL:
javascript
const fs = require('fs');
const { Client } = require('pg');
// 创建客户端实例,配置 SSL 参数
const client = new Client({
host: 'postgres-server',
port: 5432,
database: 'mydb',
user: 'myuser',
password: 'mypassword',
ssl: {
rejectUnauthorized: true, // 拒绝未授权的服务器证书
ca: fs.readFileSync('root.crt').toString(), // 根证书
cert: fs.readFileSync('client.crt').toString(), // 客户端证书
key: fs.readFileSync('client.key').toString() // 客户端私钥
}
});
// 连接数据库
client.connect()
.then(() => {
// 执行查询
return client.query('SELECT 1;');
})
.then(result => {
console.log(result.rows);
})
.catch(err => {
console.error('连接失败:', err);
})
.finally(() => {
// 关闭连接
client.end();
});SSL/TLS 验证方法
| sslmode | 描述 | 安全性 |
|---|---|---|
| disable | 禁用 SSL | 最低 |
| allow | 尝试使用 SSL,失败则降级 | 低 |
| prefer | 优先使用 SSL,失败则降级 | 中 |
| require | 要求使用 SSL,但不验证证书 | 中 |
| verify-ca | 要求使用 SSL,并验证 CA 证书 | 高 |
| verify-full | 要求使用 SSL,验证 CA 证书和主机名 | 最高 |
SSL/TLS 性能优化
1. 证书优化
bash
# 使用 ECDSA 证书(比 RSA 更高效)
openssl ecparam -genkey -name prime256v1 -out server.key
openssl req -new -key server.key -out server.csr -subj "/CN=postgres-server"
openssl x509 -req -in server.csr -CA root.crt -CAkey root.key -CAcreateserial -out server.crt -days 36502. 配置优化
修改 postgresql.conf 文件:
txt
# 使用更高效的密码套件
ssl_ciphers = 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305'
# 启用 SSL 会话缓存
ssl_session_cache = 'shared:SSL:10m' # 共享缓存,大小 10MB
ssl_session_timeout = 300s # 会话超时时间3. 硬件加速
bash
# 检查是否支持硬件加速
grep -i aes /proc/cpuinfo
# 检查 OpenSSL 是否支持硬件加速
openssl engine -t -cSSL/TLS 安全最佳实践
1. 证书管理
bash
# 定期轮换证书
# 提前 30 天生成新证书
openssl req -new -key server.key -out server.csr -subj "/CN=postgres-server"
openssl x509 -req -in server.csr -CA root.crt -CAkey root.key -CAcreateserial -out server.crt -days 3650
# 监控证书过期
openssl x509 -enddate -noout -in server.crt2. 安全配置
txt
# 禁用旧版本协议
ssl_min_protocol_version = 'TLSv1.2'
# 禁用弱密码套件
ssl_ciphers = 'HIGH:!aNULL:!MD5:!3DES:!RC4:!CAMELLIA:!SEED'
# 启用严格的证书验证
ssl_verify_client_cert = on3. 访问控制
txt
# 结合防火墙使用
hostssl all all 192.168.1.0/24 md5
hostssl all all 10.0.0.0/8 md5
hostssl all all 0.0.0.0/0 rejectSSL/TLS 验证
1. 服务器端验证
bash
# 检查 PostgreSQL 是否启用 SSL
psql -h postgres-server -p 5432 -U postgres -c "SHOW ssl;"
# 查看 SSL 配置
psql -h postgres-server -p 5432 -U postgres -c "SHOW ssl_cert_file;"
psql -h postgres-server -p 5432 -U postgres -c "SHOW ssl_key_file;"
# 查看连接的 SSL 状态
psql -h postgres-server -p 5432 -U postgres -c "\conninfo"2. 客户端验证
bash
# 检查证书有效性
openssl verify -CAfile root.crt server.crt
# 查看证书详情
openssl x509 -in server.crt -text -noout
# 测试 SSL 连接
openssl s_client -connect postgres-server:5432 -state -debug常见问题(FAQ)
Q1:如何确认 PostgreSQL 是否启用了 SSL?
A1:
sql
-- 方法1:查看 SSL 设置
SHOW ssl;
-- 方法2:查看连接信息
\conninfo
-- 方法3:从客户端检查
psql -h postgres-server -U postgres -c "SHOW ssl;"Q2:SSL 连接失败,如何排查?
A2:
- 检查 PostgreSQL 日志:
tail -f /var/log/postgresql/postgresql-15-main.log - 验证证书文件权限:
ls -l /var/lib/postgresql/15/main/ssl/ - 测试 SSL 连接:
openssl s_client -connect postgres-server:5432 - 检查 pg_hba.conf 配置:确保使用了 hostssl 而不是 host
- 检查防火墙设置:确保 5432 端口已开放
Q3:如何强制所有连接使用 SSL?
A3:
- 修改 pg_hba.conf,仅允许 hostssl 连接
- 在应用程序中设置 sslmode=require 或更高
- 考虑禁用本地非 SSL 连接(根据安全需求)
Q4:SSL 对性能有影响吗?
A4:SSL 会带来一定的性能开销(通常 5-15%),但可以通过以下方式优化:
- 使用 ECDSA 证书
- 启用 SSL 会话缓存
- 使用高效的密码套件
- 利用硬件加速
Q5:如何配置双向 SSL 认证?
A5:
- 生成客户端证书:bash
openssl genrsa -out client.key 2048 openssl req -new -key client.key -out client.csr -subj "/CN=myuser" openssl x509 -req -in client.csr -CA root.crt -CAkey root.key -CAcreateserial -out client.crt -days 3650 - 修改 pg_hba.conf:txt
hostssl all all 192.168.1.0/24 cert clientcert=1 - 客户端连接时提供证书:bash
psql "host=postgres-server dbname=mydb user=myuser sslmode=verify-full sslrootcert=root.crt sslcert=client.crt sslkey=client.key"
Q6:如何使用 Let's Encrypt 证书配置 PostgreSQL?
A6:
- 安装 Certbot 并获取证书
- 复制证书到 PostgreSQL 目录
- 修改 postgresql.conf 配置 SSL 参数
- 修改 pg_hba.conf 要求 SSL 连接
- 重启 PostgreSQL 服务
Q7:SSL 证书过期了怎么办?
A7:
- 生成新证书(使用相同的 CN 和配置)
- 替换旧证书文件
- 重启 PostgreSQL 服务
- 更新所有客户端的根证书(如果使用自签名证书)
