强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

BIND DNS 服务器搭建完全教程 / 第 07 章:动态更新与 DDNS

本章概述

动态更新(Dynamic Update)允许运行时修改 DNS 区域数据,无需手动编辑区域文件。本章讲解 TSIG 认证、安全动态更新、DHCP 联动(DDNS)以及动态区域与 DNSSEC 的配合。


7.1 动态更新基础

7.1.1 什么是动态更新

动态更新(RFC 2136)允许通过 DNS 协议向权威服务器发送更新请求,添加、修改或删除资源记录。

# 传统方式:编辑区域文件 → 递增 Serial → 重载
vim /var/cache/bind/primary/example.com.zone
rndc reload example.com

# 动态更新:直接通过 nsupdate 命令发送更新
nsupdate -k Kexample.com.+013+12345.key
> update add test.example.com 3600 A 192.168.1.50
> send

7.1.2 支持的操作

操作说明示例
添加记录update add添加 A、AAAA、TXT 等
删除记录update delete删除指定记录
删除所有update delete name删除该名称的所有记录
条件添加update add + prerequisite仅在记录不存在时添加
条件删除update delete + prerequisite仅在记录存在时删除

7.2 TSIG(Transaction Signature)

TSIG 使用共享密钥对 DNS 消息进行签名认证。

7.2.1 生成 TSIG 密钥

# 使用 tsig-keygen 生成密钥(推荐)
tsig-keygen -a hmac-sha256 update-key > /etc/bind/update.key

# 查看生成的密钥
cat /etc/bind/update.key

输出

key "update-key" {
    algorithm hmac-sha256;
    secret "aBcDeFgHiJkLmNoPqRsTuVwXyZ0123456789=";
};
# 或者使用旧工具(不推荐)
dnssec-keygen -a HMAC-SHA256 -b 256 -n HOST update-key

7.2.2 在 named.conf 中引用 TSIG 密钥

// 引入 TSIG 密钥
include "/etc/bind/update.key";

zone "example.com" {
    type primary;
    file "primary/example.com.zone";
    
    // 仅允许使用 TSIG 密钥的客户端进行动态更新
    allow-update { key update-key; };
};

7.2.3 TSIG 算法选择

算法安全性性能推荐
hmac-sha256✅ 推荐
hmac-sha384更高稍慢高安全需求
hmac-sha512最高一般极高安全需求
hmac-sha1中(已不推荐)❌ 不推荐新部署
hmac-md5低(已不安全)最快❌ 禁止使用

7.3 使用 nsupdate 发送动态更新

7.3.1 nsupdate 基本用法

# 交互模式
nsupdate -k /etc/bind/update.key

> server 127.0.0.1
> zone example.com.
> update add test.example.com 3600 A 192.168.1.50
> send
> quit

7.3.2 添加记录

# 添加 A 记录
nsupdate -k /etc/bind/update.key <<EOF
server 127.0.0.1
zone example.com.
update add newhost.example.com 3600 A 192.168.1.60
send
EOF

# 添加 AAAA 记录
nsupdate -k /etc/bind/update.key <<EOF
server 127.0.0.1
zone example.com.
update add newhost.example.com 3600 AAAA fd00::60
send
EOF

# 添加 MX 记录
nsupdate -k /etc/bind/update.key <<EOF
server 127.0.0.1
zone example.com.
update add example.com 3600 MX 10 mail.example.com.
send
EOF

# 添加 TXT 记录
nsupdate -k /etc/bind/update.key <<EOF
server 127.0.0.1
zone example.com.
update add _dmarc.example.com 3600 TXT "v=DMARC1; p=reject"
send
EOF

7.3.3 删除记录

# 删除特定记录
nsupdate -k /etc/bind/update.key <<EOF
server 127.0.0.1
zone example.com.
update delete test.example.com A
send
EOF

# 删除该名称的所有记录
nsupdate -k /etc/bind/update.key <<EOF
server 127.0.0.1
zone example.com.
update delete test.example.com
send
EOF

7.3.4 前置条件(Prerequisites)

# 条件添加:仅当记录不存在时添加
nsupdate -k /etc/bind/update.key <<EOF
server 127.0.0.1
zone example.com.
prereq nxdomain newhost.example.com
update add newhost.example.com 3600 A 192.168.1.60
send
EOF

# 条件删除:仅当记录值匹配时删除
nsupdate -k /etc/bind/update.key <<EOF
server 127.0.0.1
zone example.com.
prereq yxrrset test.example.com A 192.168.1.50
update delete test.example.com A 192.168.1.50
send
EOF
前置条件含义
prereq nxdomain name名称必须不存在
prereq yxdomain name名称必须存在
prereq nxrrset name class type记录必须不存在
prereq yxrrset name class type data记录必须存在且值匹配

7.4 动态更新后的区域文件

7.4.1 文件变化

# 动态更新后,BIND 会自动修改区域文件
# 原始文件:example.com.zone → 变为 example.com.zone.jnl(日志)
# 最终写入:example.com.zone(定期或冻结时合并)

# 查看日志文件
ls -la /var/cache/bind/primary/
# example.com.zone
# example.com.zone.jnl   ← 动态更新日志

7.4.2 冻结和解冻区域

# 冻结区域(合并日志到区域文件,禁止动态更新)
sudo rndc freeze example.com

# 现在可以手动编辑区域文件
sudo vim /var/cache/bind/primary/example.com.zone
# 注意:需要手动更新 Serial!

# 解冻区域(重新启用动态更新)
sudo rndc thaw example.com

⚠️ 冻结期间动态更新将被拒绝,操作应尽快完成。


7.5 DHCP 联动(DDNS)

DDNS(Dynamic DNS)是指 DHCP 服务器在分配 IP 后自动向 DNS 服务器注册记录。

7.5.1 ISC DHCP 配置

# /etc/dhcp/dhcpd.conf

# TSIG 密钥
key dhcp-update-key {
    algorithm hmac-sha256;
    secret "dhcp-secret-key-here=";
}

# 区域定义
zone example.com. {
    primary 127.0.0.1;
    key dhcp-update-key;
}

zone 1.168.192.in-addr.arpa. {
    primary 127.0.0.1;
    key dhcp-update-key;
}

# 子网配置
subnet 192.168.1.0 netmask 255.255.255.0 {
    range 192.168.1.100 192.168.1.200;
    option routers 192.168.1.1;
    option domain-name-servers 192.168.1.10;
    option domain-name "example.com";
    
    # DDNS 设置
    ddns-domainname "example.com.";
    ddns-rev-domainname "in-addr.arpa.";
    ddns-updates on;
    update-static-leases on;
    
    # 租约时间
    default-lease-time 3600;
    max-lease-time 86400;
}

7.5.2 BIND 侧配置

// named.conf

// DHCP 更新密钥
key dhcp-update-key {
    algorithm hmac-sha256;
    secret "dhcp-secret-key-here=";
};

// 正向区域
zone "example.com" {
    type primary;
    file "primary/example.com.zone";
    allow-update { key dhcp-update-key; };
    // 也可以限制来源 IP
    // allow-update { key dhcp-update-key; 192.168.1.1; };
};

// 反向区域
zone "1.168.192.in-addr.arpa" {
    type primary;
    file "primary/192.168.1.rev";
    allow-update { key dhcp-update-key; };
};

7.5.3 Kea DHCP(ISC 新一代 DHCP)

// /etc/kea/kea-dhcp4.conf
{
    "Dhcp4": {
        "interfaces-config": {
            "interfaces": ["eth0"]
        },
        "lease-database": {
            "type": "memfile"
        },
        "ddns-qualifying-suffix": "example.com",
        "dhcp-ddns": {
            "enable-updates": true,
            "server-ip": "127.0.0.1",
            "server-port": 53,
            "sender-ip": "192.168.1.1",
            "sender-port": 53,
            "ncr-protocol": "UDP",
            "ncr-format": "JSON"
        },
        "subnet4": [{
            "subnet": "192.168.1.0/24",
            "pools": [{"pool": "192.168.1.100 - 192.168.1.200"}],
            "option-data": [
                {"name": "routers", "data": "192.168.1.1"},
                {"name": "domain-name-servers", "data": "192.168.1.10"}
            ]
        }]
    }
}

7.6 安全动态更新配置

7.6.1 基于 IP 的更新控制(不推荐)

zone "example.com" {
    type primary;
    file "primary/example.com.zone";
    
    // 仅允许特定 IP 更新
    allow-update { 192.168.1.1; };  // 仅 DHCP 服务器 IP
};

⚠️ 不推荐:IP 地址可以被伪造,安全性较低。

7.6.2 基于 TSIG 的更新控制(推荐)

key "update-key" {
    algorithm hmac-sha256;
    secret "...";
};

zone "example.com" {
    type primary;
    file "primary/example.com.zone";
    
    // 仅允许持有 TSIG 密钥的客户端更新
    allow-update { key update-key; };
};

7.6.3 多密钥场景

// 不同服务使用不同的 TSIG 密钥
key "dhcp-key" {
    algorithm hmac-sha256;
    secret "dhcp-secret...";
};

key "monitoring-key" {
    algorithm hmac-sha256;
    secret "monitoring-secret...";
};

key "devops-key" {
    algorithm hmac-sha256;
    secret "devops-secret...";
};

zone "example.com" {
    type primary;
    file "primary/example.com.zone";
    
    // DHCP 可更新正向和反向
    allow-update {
        key dhcp-key;
    };
};

zone "dev.example.com" {
    type primary;
    file "primary/dev.example.com.zone";
    
    // 开发团队可更新 dev 子域
    allow-update {
        key dhcp-key;
        key devops-key;
    };
};

7.7 动态更新与 DNSSEC

7.7.1 自动签名模式

zone "example.com" {
    type primary;
    file "primary/example.com.zone";
    
    // 动态更新 + DNSSEC 自动签名
    inline-signing yes;
    auto-dnssec maintain;
    key-directory "primary/keys";
    allow-update { key update-key; };
};

在这种模式下,BIND 会:

  1. 接收动态更新
  2. 修改区域数据
  3. 自动更新 RRSIG 签名
  4. 自动维护密钥轮转

💡 这是生产环境推荐配置inline-signing + auto-dnssec + allow-update 完美配合。

7.7.2 手动签名模式

如果使用手动签名,动态更新后需要重新签名:

# 冻结 → 编辑 → 签名 → 解冻
rndc freeze example.com
# 手动编辑区域文件
dnssec-signzone -o example.com example.com.zone
rndc thaw example.com

7.8 动态更新日志与监控

7.8.1 启用动态更新日志

logging {
    channel update_log {
        file "/var/log/named/update.log" versions 10 size 50m;
        severity info;
        print-time yes;
        print-severity yes;
        print-category yes;
    };
    
    category update { update_log; };
    category update-security { update_log; };
};

7.8.2 日志分析

# 查看更新日志
tail -f /var/log/named/update.log

# 典型日志条目:
# 10-Jan-2026 14:30:15.123 client @0x7f8b8c0d 192.168.1.1#12345/key dhcp-key: updating zone 'example.com/IN': adding an RR at 'newhost.example.com' A 192.168.1.60

# 查看更新统计
rndc stats
cat /var/cache/bind/named.stats

7.9 常见问题排查

7.9.1 更新被拒绝

# 症状:update failed: REFUSED

# 检查 allow-update 配置
named-checkconf

# 检查 TSIG 密钥是否匹配
# 客户端和服务器的密钥必须完全一致

# 查看安全日志
tail -f /var/log/named/security.log

# 测试更新
nsupdate -k update.key
> server 127.0.0.1
> zone example.com.
> update add test.example.com 3600 A 192.168.1.50
> send
# 检查返回的响应码

7.9.2 更新成功但解析不到

# 可能原因:日志未合并到区域文件
# 解决:rndc freeze → rndc thaw

# 检查日志文件
ls -la /var/cache/bind/primary/*.jnl

# 验证更新
dig @127.0.0.1 test.example.com A

7.9.3 区域文件被清空

# 罕见情况:动态更新可能导致区域文件损坏
# 解决:从备份恢复
sudo rndc freeze example.com
sudo cp /backup/example.com.zone /var/cache/bind/primary/
sudo rndc thaw example.com

7.10 本章小结

配置项说明推荐值
allow-update允许动态更新的客户端key tsig-key;(基于 TSIG)
inline-signing自动签名yes(配合 DNSSEC)
auto-dnssec自动密钥轮转maintain
TSIG 算法事务签名算法hmac-sha256
前置条件条件更新用于防止冲突

💡 小技巧

  1. 始终使用 TSIG 认证:不要用 allow-update { any; };
  2. 定期备份区域文件:动态更新可能导致数据丢失。
  3. 使用 inline-signing:让 BIND 自动处理 DNSSEC 签名。
  4. rndc freeze 操作要快:冻结期间所有更新都会被拒绝。
  5. 每个 DHCP 服务器使用独立密钥:便于审计和撤销。

📖 执展阅读