Files
my-vault/01_Projects/Infrastructure/Services/PowerDNS Auth/Rebuild-Master-Node.md
T

306 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🌀 从 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
```
---