mirror of
https://github.com/juewuy/ShellCrash.git
synced 2026-10-24 11:49:20 +00:00
feat: 动态同步 IPv6 前缀到 nftables
This commit is contained in:
Executable
+123
@@ -0,0 +1,123 @@
|
||||
#!/bin/sh
|
||||
# Keep the nftables LAN IPv6 prefix set in sync with dynamic prefixes.
|
||||
|
||||
[ -z "$CRASHDIR" ] && CRASHDIR=$(
|
||||
cd "$(dirname "$0")"
|
||||
cd ..
|
||||
pwd
|
||||
)
|
||||
. "$CRASHDIR"/libs/get_config.sh
|
||||
. "$CRASHDIR"/starts/fw_getlanip.sh
|
||||
|
||||
[ -z "$TMPDIR" ] && TMPDIR=/tmp/ShellCrash
|
||||
ipv6_watch_pid="$TMPDIR/ipv6_watch.pid"
|
||||
ipv6_watch_fifo="$TMPDIR/ipv6_route_monitor.$$"
|
||||
ipv6_nft_family=${SHELLCRASH_NFT_FAMILY:-inet}
|
||||
ipv6_nft_table=${SHELLCRASH_NFT_TABLE:-shellcrash}
|
||||
ipv6_nft_set=${SHELLCRASH_IPV6_SET:-lan_ip6}
|
||||
|
||||
stop_ipv6_watch() {
|
||||
[ -s "$ipv6_watch_pid" ] || return 0
|
||||
ipv6_watch_old_pid=$(cat "$ipv6_watch_pid" 2>/dev/null)
|
||||
case "$ipv6_watch_old_pid" in
|
||||
'' | *[!0-9]*) ;;
|
||||
*)
|
||||
if [ ! -r "/proc/$ipv6_watch_old_pid/cmdline" ] ||
|
||||
tr '\0' ' ' <"/proc/$ipv6_watch_old_pid/cmdline" 2>/dev/null | grep -q 'fw_ipv6_watch.sh'; then
|
||||
kill "$ipv6_watch_old_pid" 2>/dev/null
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
rm -f "$ipv6_watch_pid"
|
||||
}
|
||||
|
||||
cleanup_ipv6_watch() {
|
||||
trap - EXIT INT TERM
|
||||
[ -n "$ipv6_monitor_pid" ] && kill "$ipv6_monitor_pid" 2>/dev/null
|
||||
[ -p "$ipv6_watch_fifo" ] && rm -f "$ipv6_watch_fifo"
|
||||
if [ "$(cat "$ipv6_watch_pid" 2>/dev/null)" = "$$" ]; then
|
||||
rm -f "$ipv6_watch_pid"
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
update_ipv6_set() {
|
||||
lan_ifaces=$(get_lan_ifaces)
|
||||
detected_host_ipv6=$(get_ipv6_prefixes)
|
||||
build_host_ipv6 "$detected_host_ipv6"
|
||||
ipv6_watch_state="$host_ipv6"
|
||||
|
||||
if [ "$ipv6_watch_state" = "$ipv6_watch_last_state" ] &&
|
||||
nft list set "$ipv6_nft_family" "$ipv6_nft_table" "$ipv6_nft_set" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
ipv6_watch_elements=$(echo "$host_ipv6" | sed 's/[[:space:]]\+/, /g')
|
||||
[ -n "$ipv6_watch_elements" ] || return 1
|
||||
nft list set "$ipv6_nft_family" "$ipv6_nft_table" "$ipv6_nft_set" >/dev/null 2>&1 || return 1
|
||||
|
||||
# nft processes a batch atomically, so packets never observe a partially
|
||||
# updated set while an ISP prefix is being replaced.
|
||||
printf 'flush set %s %s %s\nadd element %s %s %s { %s }\n' \
|
||||
"$ipv6_nft_family" "$ipv6_nft_table" "$ipv6_nft_set" \
|
||||
"$ipv6_nft_family" "$ipv6_nft_table" "$ipv6_nft_set" "$ipv6_watch_elements" |
|
||||
nft -f - >/dev/null 2>&1 || return 1
|
||||
ipv6_watch_last_state="$ipv6_watch_state"
|
||||
}
|
||||
|
||||
run_iproute2_monitor() {
|
||||
rm -f "$ipv6_watch_fifo"
|
||||
mkfifo "$ipv6_watch_fifo" 2>/dev/null || return 1
|
||||
ip -6 monitor route >"$ipv6_watch_fifo" 2>/dev/null &
|
||||
ipv6_monitor_pid=$!
|
||||
while IFS= read -r _ipv6_route_event; do
|
||||
# Coalesce delete/add notifications emitted during renumbering.
|
||||
sleep 1
|
||||
update_ipv6_set
|
||||
done <"$ipv6_watch_fifo"
|
||||
wait "$ipv6_monitor_pid" 2>/dev/null
|
||||
ipv6_monitor_pid=
|
||||
rm -f "$ipv6_watch_fifo"
|
||||
return 1
|
||||
}
|
||||
|
||||
run_ipv6_watch() {
|
||||
mkdir -p "$TMPDIR"
|
||||
echo $$ >"$ipv6_watch_pid"
|
||||
trap cleanup_ipv6_watch EXIT INT TERM
|
||||
ipv6_watch_last_state=
|
||||
update_ipv6_set
|
||||
|
||||
# Full iproute2 has event monitoring. BusyBox/router variants that do not
|
||||
# support it use a small polling fallback instead.
|
||||
if ip -Version 2>&1 | grep -qi 'iproute2'; then
|
||||
run_iproute2_monitor
|
||||
fi
|
||||
while :; do
|
||||
sleep 30
|
||||
update_ipv6_set
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
mkdir -p "$TMPDIR"
|
||||
stop_ipv6_watch
|
||||
/bin/sh "$0" run >/dev/null 2>&1 &
|
||||
echo $! >"$ipv6_watch_pid"
|
||||
;;
|
||||
stop)
|
||||
stop_ipv6_watch
|
||||
;;
|
||||
run)
|
||||
run_ipv6_watch
|
||||
;;
|
||||
once)
|
||||
ipv6_watch_last_state=
|
||||
update_ipv6_set
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|run|once}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user