# 🌀 从 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 ```bash sudo pdnsutil zone list-all ``` ### 2️⃣ 导出 zone 文件(PowerDNS 5.0 无 dump-zone) ```bash 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 密钥 ```bash 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 ```yaml 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`: ```sql CREATE USER pdns WITH PASSWORD 'windyboy2006'; CREATE DATABASE pdns OWNER pdns ENCODING 'UTF8'; ``` 启动数据库: ```bash docker compose up -d pdns-db sleep 10 ``` --- ## 四、主节点配置(pdns.conf) ```ini 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 ```bash 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 文件 ```bash 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 ```bash 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 ```bash docker compose exec auth pdnsutil tsigkey import "mykey." hmac-sha512 "4es15ROFVNZh76mqbn7sVu1kodAdULYKp8I/jGAWvmH/uyxeyDwqoBiYYBKPro5M+TRkKYn7ulxZKskfKIBKNg==" ``` ### 2️⃣ 授权从节点(202.91.35.141) ```bash 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。 --- ## 七、在从节点配置新的主节点 ```bash 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 ```bash 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 ``` ### 从节点主动获取 ```bash sudo pdns_control retrieve windy.me sudo pdns_control retrieve wsvc.info sudo pdns_control retrieve chans.xyz ``` --- ## 九、验证结果 ### 检查 zone 状态 ```bash docker compose exec auth pdnsutil zone list-all ``` ### 对比 SOA 序列号 ```bash 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️⃣ 数据库备份 ```bash docker compose exec pdns-db pg_dump -U pdns pdns > /backup/pdns-$(date +%F).dump ``` ### 2️⃣ 导出所有 zone 文件 ```bash 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 ``` ---