目录
一、系统环境
树莓派4B-4GB/raspberrypi OS(32位,内核版本5.10.63)/dhcpcd客户端(8.1.2)
二、实现功能
1.当系统获取到新的IPV6地址时,自动更新地址到DNSpod解析记录。
2.无需添加常驻后台的系统服务或监控IP地址变化的后台程序;不需要使用系统cron定时执行定期执行更新脚本,保证系统轻量化运行。
3.IPV4同样适用。
三、前提条件
1. DHCP服务器必须配置为有状态获取IPV6地址。
路由或光猫的ipv6RA消息配置应打开M位(即真正的dhcpv6),关闭O位(O位用于无状态配置时获取DNS等其他信息),且不能为无状态自动配置(SLAAC)(M位和O位均关闭)。
至于为什么?因为无状态自动配置是客户端自己生成地址,不会触发特定事件,也就不能利用dhcpcd的hook机制。
2. 只能由dhcpcd接管分配系统网络地址
在/etc/network/interfaces网络接口配置文件中不能出现指定静态IP地址的static或dhcp字样。否则dhcpcd就会退出。详见/usr/lib/dhcpcd5/dhcpcd这个文件。其代码实现如下:
#!/bin/sh -e
DHCPCD=/sbin/dhcpcd
INTERFACES=/etc/network/interfaces
if grep -q -E "^[[:space:]]*iface[[:space:]]*.*[[:space:]]*inet[[:space:]]*(dhcp|static)" \
$INTERFACES; then
echo "Not running dhcpcd because $INTERFACES"
echo "defines some interfaces that will use a"
echo "DHCP client or static address"
exit 6
fi
exec $DHCPCD $@
四、实现原理分析
在raspberrypi OS系统中,没有使用systemd-networkd,Network-manager,netctl,dhclient (已弃用)等常见客户端来管理网络地址,默认安装并使用了dhcpcd客户端来管理网络地址。
原dhclient 和现在的dhcp客户端dhcpcd 都提供了在发生特定事件时执行任意代码和脚本的选项(hook机制),以帮助用户实现特定需求。
我们就可以通过捕获reason这个变量的值来做一些自己想做的事情 。本文就是利用上述机制,实现触发更新IP地址事件时执行更新DDNS的脚本。当然,你也可以利用这个机制做点其他事情。
(一)dhcpcd-run-hooks执行过程
1. dhcpcd 客户端会自动与dhcp服务器协商网络地址,并进行相应网络地址配置。在这个过程中,dhcpcd客户端会因为某些特定事件调用执行/usr/lib/dhcpcd/dhcpcd-run-hooks这个脚本,这些事件名称会以reason作为环境变量传入/usr/lib/dhcpcd/dhcpcd-run-hooks中。
2. /usr/lib/dhcpcd/dhcpcd-run-hooks这个脚本又会调用执行 /etc/dhcpcd.enter-hook 和在 /usr/lib/dhcpcd/dhcpcd-hooks 中的一系列脚本,最后执行 /etc/dhcpcd.exit-hook这个脚本。 并向 /etc/resolv.conf 写入DNS信息。
3. 每一次 dhcpcd-run-hooks被调用, $interface会被设置为当前接口名称,如:eth0。 dhcpcd会设置$reason 的值说明为什么 dhcpcd-run-hooks会被调用。 要被配置的 DHCP 信息保存在以new_开头的变量中,旧的 DHCP 信息保存在以old_ 开头的变量中。命令dhcpcd -V 可查看支持的完整变量列表 。
/usr/lib/dhcpcd/dhcpcd-run-hooks脚本最后的内容如下(前面定义了一些函数):
# 导入下列脚本
for hook in \
/etc/dhcpcd.enter-hook \
/lib/dhcpcd/dhcpcd-hooks/* \
/etc/dhcpcd.exit-hook
do
# 过滤掉一些脚本
for skip in $skip_hooks; do
case "$hook" in
*/*~) continue 2;;
*/"$skip") continue 2;;
*/[0-9][0-9]"-$skip") continue 2;;
*/[0-9][0-9]"-$skip.sh") continue 2;;
esac
done
# 通过. 脚本路径 来执行脚本
if [ -f "$hook" ]; then
. "$hook"
fi
done
(二)DHCPCD的事件reason的值有哪些?
上小节中要执行的一系列 shell脚本并不是单独调用执行的,而是/usr/lib/dhcpcd/dhcpcd-run-hooks脚本中导入到自己的进程中执行。因此,使用shell 内置函数 exit, exec或类似的会导致 dhcpcd-run-hooks退出。
据dhcpcd文档描述,可触发dhcpcd客户端调用 dhcpcd-run-hooks的原因有这些:
序号 | reason值 | 说明 |
1 |
PREINIT | dhcpcd 启动,初始化完成。 |
2 | CARRIER | dhcpcd 已检测到网卡已启用。 这通常只是一个通知,无需采取任何行动, |
3 | NOCARRIER | dhcpcd 丢失了载体。 电缆可能已拔下或无线已断开。 |
4 | NOCARRIER_ROAMING | dhcpcd 丢失了载体,但接口配置仍然存在。. |
5 | INFORM | INFORM6 | dhcpcd 地址声明消息,将其地址告知 DHCP 服务器并获取其他 配置细节。. |