UniFi 搭配 HE DNS 配置延迟最小的 DDNS

因为并没有用到 Unifi 中提供的 ddns 服务商:

而且 he 又提供一个非常方便的更新 ddns 记录的方法,所以这里尝试一个能及时更新 ddns 但又不至于请求接口太频繁的方法。

脚本

首先编辑一个更新 dns 的脚本,脚本的具体逻辑是读取拨号接口的 IP 并缓存,当 IP 发生变化时上报新的记录,这样不至于触发 he 的滥用限制,但是有可以通过定时任务将 ddns 延迟控制到1分钟以内:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/bash
# 确保自己的公网 IP 在这个接口上
INTERFACE="pppoe0"
PRE_IP=`cat /tmp/ddns.ip`
# 将 {hostname} {key} 改成自己的,参考 https://dns.he.net/docs.html
URLS=(
"https://{hostname}:{key}@dyn.dns.he.net/nic/update?hostname={hostname}"
)
IP_RAW=`ip addr show dev $INTERFACE 2>&1`

if [ $? -ne 0 ]; then
logger -t ddns "get pppoe0 ip failed: $IP_RAW"
exit
fi

IP=`echo -e "${IP_RAW}" | grep "inet\b" | awk '{print $2}' | cut -d/ -f1`
if [ "$IP" != "$PRE_IP" ]; then
logger -t ddns "ip change to $IP"
for url in "${URLS[@]}";
do
CURL_RES=`curl -sSf4 "${url}" 2>&1`
# good ip address
# nochg ip address
if [ "${CURL_RES:0:4}" = "good" ] || [ "${CURL_RES:0:5}" = "nochg" ]; then
logger -t ddns "update ddns success: $CURL_RES"
else
logger -t ddns "update ddns failed: $CURL_RES"
exit
fi
done
echo $IP > /tmp/ddns.ip
fi

添加可执行权限后将其上传到 usg 的 /config/scripts/ddns.sh 备用。

配置文件

接下来自定义 USG 的配置文件 config.geteway.json 添加如下配置段,实现每分钟执行 ddns 脚本以及定时重新拨号:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"system": {
"task-scheduler": {
"task": {
"ddns": {
"executable": {
"path": "/config/scripts/ddns.sh"
},
"interval": "1m"
},
"redial": {
"crontab-spec": "0 5 * * *",
"executable": {
"path": "/usr/bin/killall -HUP pppd"
}
}
}
},
}
}

因为电信的宽带一般两天左右会自动重拨并获取新的 IP,所以这里设置每天临晨 5 点自动重拨不影响白天使用。

将配置文件上传到 Unifi 的相应站点目录后强制同步 USG 即可,参考 Unifi 安装设置分享,测试下来表现很稳定:

并且重启路由器后脚本没有丢失,不过官方论坛上有人提到 USG 的固件更新后脚本可能会丢失,届时需要再次上传 ddns.sh 脚本。