nsupdate.info 0.13.0 常用命令与运维实战

nsupdate.info 0.13.0 运维手册:Django 管理与自定义巡检命令、/nic/update API 与 ddclient 客户端、BIND nsupdate/rndc/dig 直更与验证,全部命令真实服务器实测,含密钥名 NOTAUTH/BADKEY 排障实录。

nsupdate.infoDNSBIND网络2026/10/27

nsupdate.info 0.13.0 常用命令与运维实战

目标:本文是 nsupdate.info 0.13.0 的日常运维手册,覆盖三类命令入口——Django 管理命令(含 0.13.0 自定义运维命令)、动态更新 API(curl/ddclient 客户端路径)、BIND 名字服务器侧命令(nsupdate/rndc/dig)。所有命令输入与输出均在真实服务器环境逐条实测,含一次密钥名错误的排障实录。

一、环境信息

本文所有命令在以下环境实测(2026-10-27):

组件版本/形态
操作系统Ubuntu 22.04(x86_64)
nsupdate.info0.13.0(PyPI 发行版,部署于 /srv/nsupdate.info,虚拟环境 env/)
Python / Django3.10.12 / 5.2.18
数据库PostgreSQL 14.24(本机 127.0.0.1:5432)
权威 DNSBIND 9.18.39(本机 53 端口)
Web 层gunicorn 26.2.0(systemd 单元 nsupdate.service)+ nginx 1.18.0
实验域名nsupdate.test(Domain 记录,zone 级 TSIG 密钥)
实验主机home.nsupdate.test(Host 记录,update secret:q1w2e3r4)

部署形态背景见 《nsupdate.info 介绍与选型指南》,容器化部署实操见 《nsupdate.info Docker Compose 部署实战》,参数含义见 《nsupdate.info 0.13.0 配置参数详解》。

二、工具概览

nsupdate.info 的运维命令分五组,各自作用于系统的不同平面:

组命令作用平面典型场景
Django 核心django-admin migrate/createsuperuser/collectstatic/check应用框架部署、升级、体检
nsupdate 自定义domains/hosts/faults/users/testuser/illegal应用业务巡检、清理、防滥用
Django/三方清理cleanupregistration/clearsessions/clearsocial应用框架cron 定期维护
更新 API 客户端curl、ddclient、路由器内置客户端对外服务DDNS 日常上报
BIND 侧nsupdate/rndc/digDNS 数据面直更、重载、验证

💡 说明:本文用 django-admin 作为命令入口(官方文档与 cron 模板的写法),它等价于 manage.py——前提是 DJANGO_SETTINGS_MODULE 与 PYTHONPATH 环境变量已设置。为省篇幅,下文示例用函数别名代替公共前缀:

cd /srv/nsupdate.info
E() { DJANGO_SETTINGS_MODULE=local_settings PYTHONPATH=/srv/nsupdate.info \
  /srv/nsupdate.info/env/bin/python /srv/nsupdate.info/env/bin/django-admin "$@"; }

三、前置条件

  1. 服务处于运行状态(systemctl is-active nsupdate nginx bind9 均为 active);
  2. shell 能访问部署目录 /srv/nsupdate.info(虚拟环境 env/bin/ 可执行);
  3. 已有一个 Domain(本文 nsupdate.test)与至少一个 Host(本文 home),且 BIND 侧 zone/update-policy 已完成对齐(官方示例模板与对齐要点见本专栏配置参数详解篇第 5.8 节);
  4. BIND 侧直更实验需要知道 zone 级 TSIG 密钥(Web 管理界面的 Domain 详情页可查看,本环境为 HMAC-SHA512、secret 以 U8zj... 开头的 base64 串)。

四、Django 管理命令详解

4.1 命令入口与帮助

django-admin help 列出全部可用命令(节选,实测回显):

[auth]
    changepassword
    createsuperuser

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    ...

[cleanup]
    clearsessions

[main]
    domains
    faults
    hosts
    illegal
    testuser
    users

[registration]
    cleanupregistration

[social_django]
    clearsocial

要点:[main] 小节的 6 个命令是 nsupdate.info 自定义的运维命令;[cleanup]/[registration]/[social_django] 三小节是配套的清理命令(官方 cron 模板要求每天执行)。

4.2 核心初始化命令

部署与升级时的三条必备命令(官方文档顺序):

E migrate            # 应用数据库迁移
E createsuperuser    # 创建超级管理员(交互式)
E collectstatic      # 收集静态文件到 STATIC_ROOT

实测回显(库表已就绪时重复执行 migrate):

Operations to perform:
  Apply all migrations: accounts, admin, auth, contenttypes, main, registration, sessions, sites, social_django
Running migrations:
  No migrations to apply.

查看迁移计划用 E migrate --plan(回显为"Planned operations:"加逐条计划,无待执行项时为空列表)。

4.3 部署体检(check --deploy)

升级后强烈建议跑一次 Django 的部署检查清单:

E check            # 基础检查
E check --deploy   # 生产安全检查

实测回显:

$ E check
System check identified no issues (0 silenced).

$ E check --deploy
System check identified some issues:

WARNINGS:
?: (security.W004) You have not set a value for the SECURE_HSTS_SECONDS setting. ...
?: (security.W008) Your SECURE_SSL_REDIRECT setting is not set to True. ...
?: (security.W012) SESSION_COOKIE_SECURE is not set to True. ...
?: (security.W016) You have 'django.middleware.csrf.CsrfViewMiddleware' in your MIDDLEWARE, but you have not set CSRF_COOKIE_SECURE to True. ...

System check identified 4 issues (0 silenced).

⚠️ 注意:本实验环境是纯 HTTP 内网服务,所以 W012/W016(Cookie Secure)触发告警属预期;生产 HTTPS 环境应只看到 HSTS/SSL_REDIRECT 两条(按配置参数详解篇 5.1 节配齐即可消除)。

4.4 自定义运维命令(0.13.0 实测参数)

域名可达性巡检——对每个 Domain 记录做一次 SOA 查询,验证 BIND 可达:

E domains --check

实测回显:

[2026-10-27 23:41:49,699] DEBUG query: nsupdate.test answer: ns1.nsupdate.test. root.nsupdate.test. 2026102613 3600 600 604800 60

(SOA 应答正常即代表 zone 配置与网络连通;名字服务器不可达时该 Domain 会被标记不可用并邮件通知所有者。)

陈旧主机检查——列出长期未使用的主机(0.13.0 只有两个开关:--stale-check 与 --notify-user):

E hosts --stale-check --notify-user

实测回显(无陈旧主机时静默,退出码 0):

(无输出)

故障计数处置——按阈值封禁滥用主机、重置计数并通知:

E faults --flag-abuse=150 --reset-client --notify-user

实测回显:静默执行(退出码 0)。注意 --flag-abuse 取值是"次数阈值",命中即把对应主机置 abuse_blocked,在 Web 管理界面解除。

用户巡检与重建测试用户:

E users --stale-check
E testuser

实测回显:

$ E users --stale-check
before: users: 3, hosts: 1, domains: 1
'opsadmin <opsadmin@nsupdate.test>' kept, was used recently.
'admin <admin@nsupdate.test>' kept, was used recently.
'test <nsupdate@nsupdate.test>' kept, was used recently.
after: users: 3, hosts: 1, domains: 1

$ E testuser
Successfully reinitialized the test user

滥用检测(交互式,慎用)——按 IP 反查多主机共用异常并交互确认删除:

E illegal

实测回显(检测到单 IP 多主机关联时进入交互):

[2026-10-27 23:42:07,969] DEBUG query: home.nsupdate.test answer: 192.0.2.10
IP 192.0.2.10 is referred to by 1 hosts.
User admin (admin@nsupdate.test) has created 1 hosts all pointing to same IP as 0 other hostnames.
Hostname samples: home
Delete user? no [default], y = yes, Y = YES to all, a = abort >

⚠️ 注意:illegal 是交互式命令,在 cron/无终端环境会因读不到输入抛 EOFError: EOF when reading a line 后退出——排障实录见第八章 Q4。另外该命令输出的"1 hosts"在单用户环境也可能命中,按提示选择 a = abort 退出即可,确认删除前务必人工复核。

每日清理三件套(官方 cron 模板的固定动作):

E cleanupregistration
E clearsessions
E clearsocial

实测回显:

$ E cleanupregistration
Running cleanupregistration.
cleanupregistration completed. There is no user that has to be deleted.
$ E clearsessions
(静默成功)
$ E clearsocial
(静默成功)

五、动态更新 API 客户端命令

5.1 端点一览

0.13.0 对外提供三个 dyndns2 风格端点(均要求 HTTP Basic 认证,用户名=主机 FQDN,密码=该主机的 update secret):

端点方法作用
/nic/update?myip=<IP>GET更新主机 A/AAAA 记录
/nic/delete?myip=0.0.0.0GET删除主机记录
/myipGET返回请求来源 IP(nginx 直应答,不进 Python)

5.2 curl 实测

更新 A 记录到新地址(回显第一行是服务应答体,第二行是 dig 验证结果):

curl -s -u "home.nsupdate.test:q1w2e3r4" "http://127.0.0.1/nic/update?myip=192.0.2.10"
dig @127.0.0.1 home.nsupdate.test A +short

实测回显:

good 192.0.2.10
192.0.2.10

重复上报同一地址时返回 nochg(实测连续两次):

nochg 192.0.2.10
nochg 192.0.2.10

💡 说明:nochg 判定依据是"目标记录当前值与上报值一致"——若此前执行过 /nic/delete 记录已不存在,同样的更新会先返回 good 再回到 nochg,两态交替属正常行为。

密码错误时返回 401(实测,curl -si 摘选响应行):

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="nsupdate.info"

删除记录(实测):

$ curl -s -u "home.nsupdate.test:q1w2e3r4" "http://127.0.0.1/nic/delete?myip=0.0.0.0"
deleted A
$ dig @127.0.0.1 home.nsupdate.test A +short
(空)

查看自身出口 IP(nginx 直应答,实测):

$ curl -s http://127.0.0.1/myip
127.0.0.1

(生产场景该值就是客户端的公网 IP;本实验从本机回环访问,故为 127.0.0.1。)

5.3 ddclient 客户端配置(官方模板)

Web 界面的主机详情页内置主流客户端的"复制即用"配置样例(ddclient/dyndnsc/EdgeOS/inadyn/IPFire/m0n0wall/OpenWRT/pfSense/Speedport Hybrid/浏览器),其中 ddclient 模板(≥ 3.11 版本语法)经实测环境参数替换后如下——login 是主机 FQDN、password 是该主机的 update secret、server 指向服务的 ipv4. 检测域名:

# /etc/ddclient.conf

# For ddclient >= 3.11
# --------------------

# Global / shared settings
protocol=dyndns2
ssl=yes
login=home.nsupdate.test
password='q1w2e3r4'
server=ipv4.nsupdate.test

# IPv4
usev4=webv4, webv4=http://ipv4.nsupdate.test/myip
home.nsupdate.test

(IPv6 场景按界面提示改为 usev6=ifv6, ifv6=<你的网卡名>,其余不变。)

六、BIND 侧命令

6.1 nsupdate 直更(RFC 2136)

BIND 自带的 nsupdate 工具可绕过 Web 应用直接发动态更新——适用于验证 zone/update-policy 配置、或批量脚本场景。密钥文件需包含 zone 级 TSIG 密钥:

cat > /tmp/zone.key <<EOF
key "nsupdate.test." {
    algorithm hmac-sha512;
    secret "U8zjtY5HQ6M2+V8yZFS8cjSzPGNd2w8Tp+VFdh1z7EIKSMuPtTygnjO5O5BEqdtG";
};
EOF
printf "server 127.0.0.1\nzone nsupdate.test\nupdate delete direct.nsupdate.test A\nupdate add direct.nsupdate.test 60 A 198.51.100.27\nsend\n" \
  | nsupdate -k /tmp/zone.key -v && echo NSUPDATE-OK
dig @127.0.0.1 direct.nsupdate.test A +short

实测回显:

NSUPDATE-OK
198.51.100.27

⚠️ 排障实录(密钥名写错的 NOTAUTH/BADKEY):第一次实验把密钥名写成了主机名 home.nsupdate.test.(secret 值相同),服务器拒绝并报错,DNS 记录保持不变:

; TSIG error with server: tsig indicates error
update failed: NOTAUTH(BADKEY)

原因:BIND update-policy 中 grant <密钥名> subdomain <zone> 的第一段引用的是密钥的名字(本环境为 nsupdate.test.),TSIG 签名里的 key name 必须与之完全一致,而不是主机名。改成 key "nsupdate.test." 后立即成功。据此沉淀规则:nsupdate 命令行、named.conf key 块、grant/deny 行三处的密钥名要逐字一致。

6.2 rndc 状态与重载

改完 /etc/bind/named.conf.local 或 zone 文件后执行:

rndc reload          # 重载配置与 zone
rndc status          # 查看运行状态

实测回显(status 节选):

version: BIND 9.18.39-0ubuntu0.22.04.7-Ubuntu (Extended Support Version) <id:>
running on localhost: Linux x86_64 ...
boot time: Tue, 27 Oct 2026 15:19:06 GMT
last configured: Tue, 27 Oct 2026 15:19:06 GMT
configuration file: /etc/bind/named.conf
CPUs found: 6

6.3 dig 验证

任何更新操作后都用 dig 向权威服务器求证(绕过本地缓存直接问 127.0.0.1):

dig @127.0.0.1 home.nsupdate.test A +short
dig @127.0.0.1 nsupdate.test SOA +short

实测回显:

192.0.2.10
ns1.nsupdate.test. root.nsupdate.test. 2026102613 3600 600 604800 60

七、注意事项

  1. 入口环境变量不能省:所有 django-admin 命令都要求 DJANGO_SETTINGS_MODULE=local_settings 与 PYTHONPATH 指向部署目录,否则会加载默认 settings 报数据库/密钥错误;
  2. 每主机独立密钥:/nic/update 的凭据是主机级(FQDN + update secret),不是账号密码;secret 只在生成时明文展示一次,忘记只能重建;
  3. 基础设施主机不可更新:zone 本身、www、ipv4、ipv6 等主机被 update-policy 显式 deny,客户端报 REFUSED 属预期防护,不要试图给它们做动态更新;
  4. 交互式命令别进 cron:illegal 需要人工确认,cron 只放非交互命令(domains/hosts/faults/users 与三个清理命令);
  5. 应用更新与直更共用一套 deny/grant:nsupdate 直更同样受 update-policy 约束,修改后记得 rndc reload;
  6. 自定义命令的参数以 help 输出为准:不同版本参数名有差异(如 0.13.0 的 hosts 只有 --stale-check/--notify-user),拿不准先看 django-admin help <命令>。

八、常见问题(排障实录)

Q1:/nic/update 返回 401 Unauthorized? 凭据错误。用户名必须是完整主机 FQDN(如 home.nsupdate.test)而不是用户名;密码是该主机的 update secret(非登录密码)。实测用错误密码即复现 401。

Q2:更新返回 5xx,应用日志见 REFUSED? BIND update-policy 拒绝。两类原因:目标是基础设施主机(预期拒绝);或普通主机的 grant 行 zone 名/密钥名拼写错误。用 6.1 节的 nsupdate 直更复现,能更快定位是密钥问题还是策略问题。

Q3:nsupdate 报 NOTAUTH(BADKEY)? TSIG 密钥名与服务器配置不一致(本文 6.1 节排障实录)。逐字核对三处密钥名:named.conf 的 key 块名、update-policy 的 grant/deny 首段、nsupdate 密钥文件里的 key 名。

Q4:cron 里跑 illegal 报 EOFError: EOF when reading a line? 该命令会交互式确认删除用户,cron 无标准输入必然报此错。把确认逻辑换成人工在终端执行,cron 中只跑非交互命令;若需无人值守审查,可基于应用日志自建脚本。

Q5:domains --check 无异常但客户端更新失败? domains --check 只验证 SOA 可达,不代表动态更新被放行。按顺序排查:① BIND update-policy 是否含 grant ... subdomain <zone>;② zone 级密钥两侧是否一致(对齐要点见本专栏配置参数详解篇 5.8 节);③ Domain 记录是否因历史失败被标记不可用(Web 界面查看,或等 120 秒重试窗口)。

Q6:hosts/faults 命令"静默"了,怎么确认执行成功? 0.13.0 多数自定义命令"无事发生即无输出",以退出码为准(echo $? 为 0 即成功);需要更多细节时可临时加 -v 2 提升日志级别(Django 通用参数,实测输出如 4.4 节 domains --check 的 DEBUG 行)。

九、参考链接