国庆快乐国庆节第 7 / 7 天
100%10-01 → 10-07

给 ddns-go 加条通知:IPv6 一变,手机就响

2242 字约 6 分钟0 次阅读#ddns#ipv6#运维#服务器

🤖 AI 辅助说明:本文由 AI 协助整理,配置与验证都在实际服务器上跑过;仍可能有疏漏,关键步骤建议自行复核。

家里是动态 IPv6,前缀换了是常事。域名解析一直交给 ddns-go 自动更新,问题是它太安静了——直到有次排查问题,才发现 IPv6 其实换了两天,我还在拿旧地址试。

于是给它挂了个通知。

效果

Server酱 App 的消息列表:同一条「微光录 · IPv6 变动」通知,正文是新地址、结果、域名、时间戳(地址已打码)

调试时一口气推了 7 条测试消息,平时只在 IPv6 变化时才来一条。

怎么接的

链路不复杂:ddns-go 每几分钟读一次网卡上的 IPv6,和 DNS 里的记录比一比,变了才去更新——顺手回调一个 URL。要做的就是把那个 URL 指向 Server酱³。

链路图:家里的 Debian 上 ddns-go 读网卡 IPv6,变了才更新雨云 AAAA 记录并 POST 到 Server酱³,再由 App 推送到手机

我用的是 Server酱³(https://sc3.ft07.com/),它走自家 App 推送,所以得先把 App 装上、用同一账号登录,再去 https://sc3.ft07.com/sendkey 拿一串 SendKey(sctp… 开头)。

想推到微信 / 企业微信 / 钉钉 / 飞书的,那是另一条产品线 Server酱 Turbo(两边 SendKey 不通用);或者干脆用企业微信机器人,免费且不限条数。

面板里就三个框,对应配置文件 /root/.ddns_go_config.yaml 的三行:

ddns-go 面板的 Webhook 页:URL、RequestBody、Headers 三个输入框,以及「模拟测试Webhook」按钮(URL 里的 SendKey 已打码)

配置示意图:三个字段的取值,以及 7 个可用变量

webhook:
    webhookurl: "https://<uid>.push.ft07.com/send/<SendKey>.send"
    webhookheaders: "Content-Type: application/json"
    webhookrequestbody: '{"title":"IPv6 变动","desp":"新地址:#{ipv6Addr}\n结果:#{ipv6Result}"}'

两个记下来的点:uid 就藏在 SendKey 里(sctp12345t… 的数字段);请求体留空是 GET、非空才是 POST,这是它判断方法的唯一开关。请求体得用单引号包,不然 YAML 会把 \n 变成真换行,JSON 就断了。

改完 systemctl restart ddns-go(改之前先备一份配置)。

为什么它不会吵

我最担心的就是每 5 分钟来一条「没变」。翻了下源码,回调的条件是:

if conf.WebhookURL != "" && (v4Status != UpdatedNothing || v6Status != UpdatedNothing) {

也就是只有真的更新了(成功或失败)才回调,「未改变」直接跳过。

判定流程图:读到 IPv6 后与 DNS 记录比对,一样就什么都不做、记一笔「未改变」,不一样才更新 AAAA 并回调 webhook

不放心的话在服务器上起个本地探针盯着就行,跑几轮就服了。

怎么验

不用等 IPv6 真的变:把请求体里的变量换成真值,用 ddns-go 同款 UA 打一次。

curl -s -X POST -A "Go-http-client/1.1" -H "Content-Type: application/json" \
     --data-binary @/tmp/body.json "https://<uid>.push.ft07.com/send/<SendKey>.send"
# 期望:{"code":0,"errno":0,"data":{"pushid":...},"message":"SUCCESS"}

拿到 SUCCESS 就说明地址、头部、请求体三样都对。

备忘

  • 三个字段:webhookurl / webhookheaders / webhookrequestbody;可用变量只有 7 个:#{ipv6Addr} #{ipv6Result} #{ipv6Domains} #{ipv4Addr} #{ipv4Result} #{ipv4Domains} #{timestamp},结果值是中文(成功 / 失败 / 未改变),发送时才替换。
  • 坑一:别用脚本的字符串替换往配置里写 \n——re.sub 会把替换串里的 \n 还原成真换行,YAML 的多行单引号标量再把它折叠成空格,消息全挤成一行;改完回读确认是字面量。
  • 坑二:调试别用 Python 的 urllib,Server酱 的 WAF 会 403;curl 和 Go 的 Go-http-client/1.1 都正常。

相关文章


评论

评论区由 giscus 提供(基于 GitHub Discussions),内容会保存在 GitHub 上;详见《隐私政策》。