6.8 KiB
6.8 KiB
🌀 从 Slave 节点恢复 PowerDNS Authoritative 主节点(5.0.0 + PostgreSQL)
本文记录如何从 PowerDNS 从节点完整恢复主节点,包括数据库重建、Zone 导入、TSIG 同步与 DNSSEC 校验。
适用于 PowerDNS Authoritative 5.0.0 + PostgreSQL gpgsql backend 环境。
一、系统角色
| 节点 | 地址 | 角色 | 说明 |
|---|---|---|---|
| 主节点 | 154.36.174.161 | primary | 新建 |
| 从节点 | 202.91.35.141 | secondary | 当前持有所有 zone |
| 数据库 | PostgreSQL 15 | backend | gpgsql |
| TSIG | mykey (hmac-sha512) | 用于 AXFR 验证 |
二、从 Slave 导出数据
1️⃣ 列出所有 zone
sudo pdnsutil zone list-all
2️⃣ 导出 zone 文件(PowerDNS 5.0 无 dump-zone)
sudo pdnsutil zone list windy.me > /var/tmp/windy.me.zone
sudo pdnsutil zone list wsvc.info > /var/tmp/wsvc.info.zone
sudo pdnsutil zone list chans.xyz > /var/tmp/chans.xyz.zone
3️⃣ 导出 TSIG 密钥
sudo pdnsutil tsigkey list
示例:
mykey. hmac-sha512. 4es15ROFVNZh76mqbn7sVu1kodAdULYKp8I/jGAWvmH/uyxeyDwqoBiYYBKPro5M+TRkKYn7ulxZKskfKIBKNg==
三、部署主节点环境
1️⃣ 目录结构
/opt/pdns-primary/
├── docker-compose.yml
├── pdns.conf
└── db-init/
└── 01-init.sql
2️⃣ docker-compose.yml
version: "3.8"
services:
pdns-db:
image: postgres:15
environment:
POSTGRES_USER: pdns
POSTGRES_PASSWORD: windyboy2006
POSTGRES_DB: pdns
volumes:
- ./db-init:/docker-entrypoint-initdb.d
- pdns-db-data:/var/lib/postgresql/data
restart: unless-stopped
auth:
image: powerdns/pdns-auth-50:latest
depends_on:
- pdns-db
volumes:
- ./pdns.conf:/etc/powerdns/pdns.conf:ro
- ./import:/import:ro
ports:
- "53:53/tcp"
- "53:53/udp"
- "8081:8081"
restart: unless-stopped
volumes:
pdns-db-data:
3️⃣ 初始化数据库
db-init/01-init.sql:
CREATE USER pdns WITH PASSWORD 'windyboy2006';
CREATE DATABASE pdns OWNER pdns ENCODING 'UTF8';
启动数据库:
docker compose up -d pdns-db
sleep 10
四、主节点配置(pdns.conf)
primary=yes
secondary=no
launch=gpgsql
gpgsql-host=pdns-db
gpgsql-port=5432
gpgsql-dbname=pdns
gpgsql-user=pdns
gpgsql-password=windyboy2006
gpgsql-dnssec=yes
local-address=0.0.0.0
local-port=53
setuid=pdns
setgid=pdns
loglevel=4
version-string=anonymous
api=yes
api-key=SuperSecretKey
webserver=yes
webserver-address=0.0.0.0
webserver-port=8081
default-soa-edit=INCEPTION-INCREMENT
default-soa-edit-signed=INCEPTION-INCREMENT
disable-axfr=no
✅ 所有字段均为 5.0.0 有效选项,无 default-soa-edit-api。
五、导入 Zone 数据
1️⃣ 创建空 zone 并设为 master
docker compose exec auth pdnsutil zone create windy.me
docker compose exec auth pdnsutil zone set-kind windy.me master
docker compose exec auth pdnsutil zone create wsvc.info
docker compose exec auth pdnsutil zone set-kind wsvc.info master
docker compose exec auth pdnsutil zone create chans.xyz
docker compose exec auth pdnsutil zone set-kind chans.xyz master
2️⃣ 导入 zone 文件
docker compose exec auth pdnsutil zone load windy.me /import/windy.me.zone
docker compose exec auth pdnsutil zone load wsvc.info /import/wsvc.info.zone
docker compose exec auth pdnsutil zone load chans.xyz /import/chans.xyz.zone
3️⃣ 如 zone 含有 RRSIG/DNSKEY,设为 presigned
docker compose exec auth pdnsutil zone set-presigned windy.me
docker compose exec auth pdnsutil zone set-presigned wsvc.info
docker compose exec auth pdnsutil zone set-presigned chans.xyz
六、导入 TSIG 密钥并授权从节点
1️⃣ 导入 TSIG key
docker compose exec auth pdnsutil tsigkey import "mykey." hmac-sha512 "4es15ROFVNZh76mqbn7sVu1kodAdULYKp8I/jGAWvmH/uyxeyDwqoBiYYBKPro5M+TRkKYn7ulxZKskfKIBKNg=="
2️⃣ 授权从节点(202.91.35.141)
docker compose exec auth pdnsutil metadata set windy.me TSIG-ALLOW-AXFR "mykey."
docker compose exec auth pdnsutil metadata set windy.me ALLOW-AXFR-FROM "202.91.35.141"
docker compose exec auth pdnsutil metadata set windy.me ALSO-NOTIFY "202.91.35.141"
docker compose exec auth pdnsutil metadata set wsvc.info TSIG-ALLOW-AXFR "mykey."
docker compose exec auth pdnsutil metadata set wsvc.info ALLOW-AXFR-FROM "202.91.35.141"
docker compose exec auth pdnsutil metadata set wsvc.info ALSO-NOTIFY "202.91.35.141"
docker compose exec auth pdnsutil metadata set chans.xyz TSIG-ALLOW-AXFR "mykey."
docker compose exec auth pdnsutil metadata set chans.xyz ALLOW-AXFR-FROM "202.91.35.141"
docker compose exec auth pdnsutil metadata set chans.xyz ALSO-NOTIFY "202.91.35.141"
⚠️ 不带
@mykey.,因为已全局指定 TSIG key。
七、在从节点配置新的主节点
sudo pdnsutil zone create-secondary windy.me 154.36.174.161
sudo pdnsutil metadata set windy.me AXFR-MASTER-TSIG "mykey."
sudo pdnsutil zone create-secondary wsvc.info 154.36.174.161
sudo pdnsutil metadata set wsvc.info AXFR-MASTER-TSIG "mykey."
sudo pdnsutil zone create-secondary chans.xyz 154.36.174.161
sudo pdnsutil metadata set chans.xyz AXFR-MASTER-TSIG "mykey."
八、触发 AXFR 同步
主节点发送 NOTIFY
docker compose exec auth pdns_control notify windy.me
docker compose exec auth pdns_control notify wsvc.info
docker compose exec auth pdns_control notify chans.xyz
从节点主动获取
sudo pdns_control retrieve windy.me
sudo pdns_control retrieve wsvc.info
sudo pdns_control retrieve chans.xyz
九、验证结果
检查 zone 状态
docker compose exec auth pdnsutil zone list-all
对比 SOA 序列号
dig @154.36.174.161 soa windy.me +short
dig @202.91.35.141 soa windy.me +short
应相同。
查看日志
主节点:
AXFR-out zone 'windy.me', client '202.91.35.141' transfer started/done
从节点:
AXFR done for 'windy.me'
十、常见错误与修复
| 日志 | 原因 | 修复 |
|---|---|---|
| Signature with TSIG key failed | 双方 TSIG secret 不一致 | 重新导入一致的 key |
| Server Not Authoritative / Not Authorized | 主节点未授权从节点 | 执行 metadata set ALLOW-AXFR-FROM |
| AXFR-out denied: client has no permission | 同上 | 增加 ALLOW-AXFR-FROM |
| Trying to set unknown setting 'default-soa-edit-api' | 配置无效 | 删除该字段 |
十一、备份与维护
1️⃣ 数据库备份
docker compose exec pdns-db pg_dump -U pdns pdns > /backup/pdns-$(date +%F).dump
2️⃣ 导出所有 zone 文件
mkdir -p /backup/zones
for z in $(docker compose exec auth pdnsutil zone list-all | tr -d '\r'); do
docker compose exec auth pdnsutil zone list "$z" > "/backup/zones/$z-$(date +%F).zone"
done