用 pgBackRest TLS 模式做 PostgreSQL 灾备恢复:少一点 SSH,少一点横向移动风险

2026-07-07 39 预计阅读时间: 1 分钟
来源: postgr.es AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:11 分钟

PostgreSQL 灾备恢复里,pgBackRest 通过 SSH 拉取备份是一条成熟路线:简单、可靠、很多团队已经这么跑。但当 DR 服务器越来越多、隔离区越来越严格、密钥轮换越来越频繁时,SSH key 的分发和审计会变成运维负担。pgBackRest 的原生 TLS transport 提供了另一种模型:DR 服务器不需要拿到能登录备份节点的 SSH key,只用证书向 pgBackRest TLS daemon 认证,然后按 stanza 授权恢复。

SSH 能用,TLS 更适合隔离和规模化

SSH 模式的问题不在加密强度。SSH 本身足够安全,也适合小规模环境。麻烦通常出现在这些地方:

  • 每台 DR 机器都要管理 key pair、authorized_keys、轮换周期和审计记录。
  • DR 服务器一旦被攻破,存放在上面的 SSH key 可能成为横向移动入口。
  • 除非用 forced command 严格约束,否则 SSH key 认证成功后,本质上拿到的是主机级访问能力。

TLS 模式把访问面缩小到 pgBackRest 协议本身。备份节点上运行一个轻量 TLS server,默认监听 8432。DR 服务器拿客户端证书连接,备份节点校验证书是否由受信 CA 签发,再根据配置里的 tls-server-auth=<cert-CN>=<stanza> 判断它能访问哪个 stanza。

这不是“TLS 比 SSH 更安全”的简单结论。更准确地说:TLS 模式改变了权限边界。DR 服务器持有的是面向 pgBackRest daemon 的证书,不是能登录备份节点 shell 的凭据。即使 DR 服务器被完全拿下,攻击者也只能尝试使用该证书访问被授权的 stanza,不能直接从 SSH 跳到备份节点。

pgBackRest TLS 模式的核心机制

TLS 模式依赖 X.509 证书体系:

  • 一个 CA 作为信任根,签发备份节点的服务端证书和 DR 服务器的客户端证书。
  • DR 服务器校验证书,确认自己连接的是正确的备份节点。
  • 备份节点校验 DR 服务器证书,确认它由受信 CA 签发。
  • 备份节点再用客户端证书里的 CN 做应用层授权。

关键配置长这样:

# Backup Node: /etc/pgbackrest.conf
[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=2
log-level-console=info
log-level-file=debug

tls-server-address=*
tls-server-port=8432
tls-server-cert-file=/etc/pgbackrest/certs/server.crt
tls-server-key-file=/etc/pgbackrest/certs/server.key
tls-server-ca-file=/etc/pgbackrest/certs/ca.crt

# 客户端证书 CN 为 dr-server 时,只允许访问 db stanza
tls-server-auth=dr-server=db

[db]
pg1-path=/var/lib/pgsql/15/data

tls-server-auth=dr-server=db 是访问控制点。这里的 dr-server 必须和 DR 服务器客户端证书里的 CN 完全一致。

需要特别注意:pgBackRest 不支持 CRL,也就是不能通过证书吊销列表让 pgBackRest 自动拒绝未过期但已失效的证书。撤销访问要在授权层完成:删除或修改备份节点上的 tls-server-auth 行,然后重启 TLS server。如果证书泄露,还应签发一个使用新 CN 的证书,避免旧 CN 被重新授权时带来风险。

可以这样实践:搭建一个 TLS 恢复通道

下面示例基于 RHEL 9、PostgreSQL 15,并假设备份节点已经有可用的 pgBackRest repository。运行前把 <BACKUP_NODE_DNS> 替换成 DR 服务器访问备份节点时使用的 DNS 名称或 IP。

1. 在 DR 服务器安装依赖

sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo dnf -qy module disable postgresql
sudo dnf install -y postgresql15-server
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf install -y libssh2 pgbackrest openssl

2. 在备份节点创建演示 CA 和服务端证书

生产环境通常应该接入已有企业 CA 或专门的证书管理系统。下面命令适合实验和理解流程,不等于生产 PKI 方案。

sudo mkdir -p /etc/pgbackrest/certs
cd /etc/pgbackrest/certs

sudo openssl genrsa -out ca.key 4096
sudo openssl req -new -x509 -days 3650 -key ca.key \
  -subj "/CN=pgBackRest-CA" \
  -out ca.crt

sudo openssl genrsa -out server.key 4096
sudo openssl req -new -key server.key \
  -subj "/CN=<BACKUP_NODE_DNS>" \
  -out server.csr

sudo openssl x509 -req -days 3650 -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out server.crt

sudo chmod 600 ca.key server.key
sudo chmod 644 ca.crt server.crt
sudo chown -R postgres:postgres /etc/pgbackrest/certs

企业环境里更推荐完整 DN,例如:

-subj "/C=US/ST=California/O=YourOrg/OU=Database/CN=backup-node.example.com"

3. 在 DR 服务器创建客户端证书请求

sudo mkdir -p /etc/pgbackrest/certs
cd /etc/pgbackrest/certs

sudo openssl genrsa -out client.key 4096
sudo openssl req -new -key client.key \
  -subj "/CN=dr-server" \
  -out client.csr

sudo chmod 600 client.key

/etc/pgbackrest/certs/client.csr 的内容复制到备份节点,然后在备份节点签发:

cd /etc/pgbackrest/certs
sudo openssl x509 -req -days 3650 -in client.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out client.crt

再把 client.crtca.crt 放回 DR 服务器的 /etc/pgbackrest/certs/,并设置权限:

sudo chmod 600 /etc/pgbackrest/certs/client.key
sudo chmod 644 /etc/pgbackrest/certs/client.crt /etc/pgbackrest/certs/ca.crt
sudo chown -R postgres:postgres /etc/pgbackrest/certs

4. 在备份节点启动 pgBackRest TLS server

sudo tee /etc/systemd/system/pgbackrest.service > /dev/null <<'EOF'
[Unit]
Description=pgBackRest TLS Server
After=network.target

[Service]
User=postgres
ExecStart=/usr/bin/pgbackrest server
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now pgbackrest
sudo systemctl status pgbackrest

还要确认备份节点防火墙允许 8432 端口。可以这样检查监听状态:

sudo ss -lntp | grep ':8432'

5. 在 DR 服务器配置 TLS repository

# DR Server: /etc/pgbackrest.conf
[global]
repo1-host=<BACKUP_NODE_DNS>
repo1-host-type=tls
repo1-host-port=8432
repo1-host-cert-file=/etc/pgbackrest/certs/client.crt
repo1-host-key-file=/etc/pgbackrest/certs/client.key
repo1-host-ca-file=/etc/pgbackrest/certs/ca.crt
log-level-console=info

[db]
pg1-path=/var/lib/pgsql/15/restored-data

创建恢复目录:

sudo mkdir -p /var/lib/pgsql/15/restored-data
sudo chown postgres:postgres /var/lib/pgsql/15/restored-data

连接验证:

sudo -u postgres pgbackrest --stanza=db info

如果出现 TLS handshake 错误,优先查三件事:客户端证书 CN 是否和 tls-server-auth 完全一致;DR 服务器上的 ca.crt 是否真的是签发备份节点服务端证书的 CA;备份节点的 8432 是否被防火墙挡住。

恢复数据,以及一个容易踩坏生产备份链的细节

恢复最新备份:

sudo -i -u postgres pgbackrest --stanza=db \
  --pg1-path=/var/lib/pgsql/15/restored-data \
  --process-max=4 \
  --log-level-console=info \
  restore

做时间点恢复可以这样改:

sudo -i -u postgres pgbackrest --stanza=db \
  --pg1-path=/var/lib/pgsql/15/restored-data \
  --type=time \
  --target="2026-05-12 11:30:00" \
  --target-action=promote \
  --process-max=4 \
  --log-level-console=info \
  restore

pgBackRest 会通过 TLS 传输文件,并写入恢复所需配置。启动 PostgreSQL 后,实例会自动 replay WAL。

但启动前有一个必须手动确认的点:恢复出来的 postgresql.conf 可能还保留着生产环境的 archive_command。如果 DR 实例启动后继续向生产 archive 写 WAL,就可能把 DR WAL 混进生产备份链,后果很难收拾。

启动前修改恢复目录里的配置:

vi /var/lib/pgsql/15/restored-data/postgresql.conf

确认设置为:

archive_mode = off

然后启动并做基础检查:

sudo -i -u postgres /usr/pgsql-15/bin/pg_ctl \
  -D /var/lib/pgsql/15/restored-data \
  -l /var/lib/pgsql/15/dr-logfile \
  start

psql -U postgres -c "SELECT now();"
psql -U postgres -c "\l+"

采用 TLS 模式前的检查清单

TLS transport 很适合这些场景:DR 服务器是临时拉起的;DR 环境和生产处在不同安全区;团队已有企业 CA、Active Directory Certificate Services 或类似证书基础设施;恢复演练需要频繁执行,但不希望建立 SSH 信任关系。

它的代价也要算清楚:

  • 证书过期需要监控,否则恢复演练当天可能先撞上证书问题。
  • CA 根证书生命周期要管理,续期和分发不能靠临时手工流程。
  • pgBackRest 不支持 CRL,撤权依赖 tls-server-auth 授权配置和服务重启。
  • 小环境里 SSH 可能更简单,尤其是机器少、key 管理清楚、forced command 已经配置到位时。

一句话判断:如果你的问题主要是“怎么最快恢复一次”,SSH 通常足够;如果你的问题是“怎么让很多隔离 DR 节点长期、可审计、低横向移动风险地恢复”,pgBackRest TLS transport 更值得投入。


相关推荐