SSL (Secure Sockets Layer) 是一种用于保护 TCP/IP 连接安全的标准技术。通过在 PostgreSQL 中配置 SSL,可以对网络传输的数据进行加密,有效防止数据在传输过程中被窃听或篡改,确保数据通信的安全性。

1. SSL 基础概念

1.1 SSL 简介

PostgreSQL 原生支持使用 SSL 加密客户端与服务器之间的通信。要启用此功能,需满足以下条件:

  • 客户端和服务器端都必须安装 OpenSSL
  • 编译 PostgreSQL 时必须启用 SSL 支持

编译时添加 --with-openssl 参数:

./configure ... --with-openssl

1.2 OpenSSL req 命令参数详解

openssl req 命令常用参数:

参数 说明
-new 创建证书请求文件,交互式输入信息
-x509 生成自签名证书而非证书请求
-days n 指定证书有效期(天)
-nodes 禁止对私钥文件加密
-text 以文本格式打印证书请求
-out filename 指定输出文件
-keyout filename 指定私钥存放位置
-subj args 自定义证书请求信息

X.509 说明:X.509 是公钥证书的格式标准,规定了数字证书的格式。X.509 证书包含公钥和标识信息(主机名、组织等),并由证书颁发机构(CA)签名或自签名。

1.3 PostgreSQL 支持的 SSL 模式

PostgreSQL 提供多种 SSL 连接模式:

模式 描述
disable 仅尝试非 SSL 连接
allow 先尝试非 SSL,失败后尝试 SSL
prefer (默认) 先尝试 SSL,失败后尝试非 SSL
require 仅尝试 SSL 连接
verify-ca 仅 SSL,并验证服务器证书是否由可信 CA 签发
verify-full 仅 SSL,验证 CA 签发且主题匹配连接域名/IP

使用建议

  • 公共 CA:推荐使用 verify-full
  • 本地/自签名 CA:verify-ca 通常已足够

1.4 密码套件配置

PostgreSQL 通过 ssl_ciphers 参数控制允许的密码套件(仅影响 TLS 1.2 及以下版本):

ssl_ciphers = 'HIGH:MEDIUM:+3DES:!aNULL'

默认值说明

  • HIGH:高强度密码套件(如 AES、Camellia、3DES)
  • MEDIUM:中等强度密码套件(如 RC4、SEED)
  • +3DES:修正 3DES 的排序问题
  • !aNULL:禁用匿名密码套件(易受中间人攻击)

查看当前支持的密码套件:

openssl ciphers -v 'HIGH:MEDIUM:+3DES:!aNULL'

2. SSL 证书类型

2.1 自签名证书

自签名证书由自己签发,无需 CA 认证,适用于测试或内部环境。

生成自签名证书命令:

openssl req -new -x509 -days 365 -nodes -text -out server.crt -keyout server.key -subj "/CN=dbhost.yourdomain.com"
chmod og-rwx server.key

2.2 自签名 CA 证书

建立本地 CA 体系,更安全的解决方案:

生成根 CA 密钥和证书:

# 生成根 CA 私钥和证书请求
openssl req -new -nodes -text -out root.csr -keyout root.key -subj "/CN=root.yourdomain.com"
chmod og-rwx root.key

# 自签名生成根证书
openssl x509 -req -in root.csr -text -days 3650 -extfile /etc/pki/tls/openssl.cnf -extensions v3_ca -signkey root.key -out root.crt

生成服务器证书:

# 生成服务器证书请求
openssl req -new -nodes -text -out server.csr -keyout server.key -subj "/CN=dbhost.yourdomain.com"
chmod og-rwx server.key

# 使用根 CA 签发服务器证书
openssl x509 -req -in server.csr -text -days 365 -CA root.crt -CAkey root.key -CAcreateserial -out server.crt

2.3 权威机构 CA 证书

由知名 CA 机构签发的证书,适用于生产环境:

  1. 申请证书(通常需要付费)
  2. 获取三个文件:
    • 服务器私钥 server.key
    • 服务器证书 server.crt
    • CA 证书

部署说明

  • 服务器:部署 server.keyserver.crt
  • 客户端:部署 CA 证书(可从 libcurl 网站获取最新 CA 证书集合)

3. PostgreSQL SSL 配置实践

3.1 单向认证配置

步骤 1:生成自签名证书

openssl req -new -x509 -days 365 -nodes -text -out server.crt -keyout server.key -subj "/CN=host"
chmod 600 server.*
cp server.* $PGDATA

步骤 2:修改配置文件

postgresql.conf

ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'

pg_hba.conf

hostnossl all all 0.0.0.0/0 reject
hostssl all all 0.0.0.0/0 md5

步骤 3:重启服务并验证

psql "host=192.168.138.81 dbname=postgres port=5432 user=pg96"
# 应显示 SSL 连接信息

3.2 双向认证配置

步骤 1:搭建 CA 环境

# 创建文件夹demoCA
mkdir -p test/demoCA/{private,newcerts}
cd test/
# 将配置文件拷贝到test
cp `openssl version -d | awk -F '"' '{print $2}'`/openssl.cnf .
# 创建serial文件,写入01
echo '01' > demoCA/serial
# 创建文件index.txt
touch demoCA/index.txt
# 修改dir参数
sed -i 's|^dir\s*=.*|dir = ./demoCA|' openssl.cnf
# 修改default_md参数
sed -i 's|^default_md\s*=.*|default_md = sha256|' openssl.cnf

步骤 2:生成根 CA 证书

# 生成根私钥
openssl genrsa -aes256 -passout pass:postgresql@123 -out demoCA/private/cakey.pem 2048
# 生成根证书请求文件
openssl req -config openssl.cnf -passin pass:postgresql@123 -new -key demoCA/private/cakey.pem -out demoCA/careq.pem -subj "/C=CN/ST=guangzhou/L=Shenzhen/O=test/OU=test/CN=localhost"
# --生成根证书时,需要修改openssl.cnf文件,设置basicConstraints=CA:TRUE
sed -i 's/^basicConstraints.*$/basicConstraints=CA:TRUE/' openssl.cnf
# 生成自签发根证书,有y直接确认
openssl ca -config openssl.cnf -out demoCA/cacert.pem -passin pass:postgresql@123 -keyfile demoCA/private/cakey.pem -selfsign -infiles demoCA/careq.pem

步骤 3:生成服务器证书

#生成服务端私钥
openssl genrsa -aes256 -passout pass:postgresql@123 -out server.key 2048
# 生成服务端证书请求文件
openssl req -config openssl.cnf -passin pass:postgresql@123 -new -key server.key -out server.req -subj "/C=CN/ST=guangzhou/L=Shenzhen/O=test/OU=test/CN=server"
# 生成服务端/客户端证书时,修改openssl.cnf文件,设置basicConstraints=CA:FALSE
sed -i 's/^basicConstraints.*$/basicConstraints=CA:FALSE/' openssl.cnf
# 生成服务端证书,有y直接确认
openssl ca -config openssl.cnf -passin pass:postgresql@123 -in server.req -out server.crt -days 3650 -md sha256
#去掉服务端私钥的密码保护
openssl rsa -in server.key -out server.key

步骤 4:生成客户端证书

#生成客户端私钥
openssl genrsa -aes256 -passout pass:postgresql@123 -out client.key 2048 
# 生成客户端证书请求文件
openssl req -config openssl.cnf -passin pass:postgresql@123 -new -key client.key -out client.req -subj "/C=CN/ST=guangzhou/L=Shenzhen/O=test/OU=test/CN=test"
# 生成服务端证书,有y直接确认
openssl ca -config openssl.cnf -passin pass:postgresql@123 -in client.req -out client.crt -days 3650 -md sha256
#去掉客户端私钥的密码保护
openssl rsa -in client.key -out client.key

步骤 5:部署证书

chmod 600 server.* client.* demoCA/cacert.pem
cp server.* demoCA/cacert.pem $PGDATA
cp client.* demoCA/cacert.pem /home/postgres/certs

步骤 6:修改配置

postgresql.conf

ssl = on
ssl_cert_file = 'server.crt'
ssl_key_file = 'server.key'
ssl_ca_file = 'cacert.pem'

pg_hba.conf

hostnossl all all 0.0.0.0/0 reject
hostssl all all 0.0.0.0/0 cert

步骤 7:配置客户端环境变量

export PGSSLCERT="/home/postgres/certs/client.crt"
export PGSSLKEY="/home/postgres/certs/client.key"
export PGSSLMODE="verify-ca"
export PGSSLROOTCERT="/home/postgres/certs/cacert.pem"

步骤 8:验证连接

psql "host=127.0.0.1 dbname=postgres port=5432 user=postgres sslmode=verify-ca"

4. 注意事项

  1. 权限管理:证书和私钥文件应设置严格权限(如 600)
  2. 证书有效期:注意监控证书过期时间
  3. 性能影响:SSL 加密会带来一定的性能开销
  4. 混合模式:允许 SSL 和非 SSL 连接并存时需谨慎配置 pg_hba.conf

参考资源

  1. PostgreSQL SSL 官方文档
  2. OpenSSL 命令详解
  3. SSL 双向认证配置
  4. SSL证书生成

关注以下公众号,获取最新PG帖子。

posted on 2025-04-24 07:56  jl1771  阅读(503)  评论(0)    收藏  举报