我想运行一个systemd一次性服务每当我的系统从网络路由器获得分配给它的新 IPv6 地址时(这将在启动时,并在整个正常运行时间内定期进行)。
理想情况下,此事件仅适用于 IPv6 地址更新,而不包括潜在的 IPv4 地址更改。
是否可以使用 systemd 监控此类事件的网络 dbus 活动?
我的最终目标是在发生这种情况时命中动态 DNS 端点,以便该系统的 IPv6 DNS 记录避免过时。
答案1
我很多年前写过这样的东西,叫做(缺乏想象力)自动域名。
它不调用 systemd 服务(我认为当时不存在 systemd!),但它确实调用外部进程来执行 DNS 更新(更新)。然而,它确实直接在网络链路级别监视 IP 地址的添加和删除,这意味着无论它们如何发生(手动管理配置、SLAAC、DHCP、网络管理器),它都会拾取它们。当发生变化时它会立即做出反应。它确实支持过滤器(设计用于自动排除链接本地地址等内容),因此您可以让它尊重 IPv6 地址更改并忽略 IPv4 地址更改,如您所愿。
也许您可以使用它或修改它来满足您的需求。检测 IP 地址变化并做出反应的大部分魔力在于watchip.c, 我认为。
答案2
使用持久的 systemd 服务,而不是一次性的:
[Unit]
Description=Dynamic DNS updater
DefaultDependencies=no
Wants=local-fs.target
After=local-fs.target
Wants=network-pre.target
Before=network-pre.target
[Service]
Type=exec
ExecStart=/usr/local/sbin/ddns-updater
[Install]
WantedBy=sysinit.target
相应的/usr/local/sbin/ddns-updater
守护进程脚本,使用包ip
中的工具iproute2
:
#!/bin/sh -e
ip -o -6 monitor address |
while read index iface proto addr dummy scope temporary dummy; do
case "$iface:$proto:$scope:$temporary" in
enp2s0:inet6:global:dynamic)
addr="${addr%/*}"
if [ "$addr" != "$current" ]; then
nsupdate -k /etc/network/nsupdate/Kyour.dyn.domain.name.+157+58882.private <<EOF
update delete your.dyn.domain.name AAAA
update add your.dyn.domain.name 300 AAAA $addr
send
EOF
echo "AAAA record set to $addr"
current="$addr"
fi;;
esac
done
这可以避免将经常变化的随机(隐私增强型、临时)地址写入 DNS 服务器,但如果您有多个全局非临时地址(例如静态配置的地址和 SLAAC 的地址),则会出现问题。根据需要进行调整(接口名称、域名、密钥文件路径、附加逻辑、TTL...)