If using custom iptables/nftables rules, keep in mind that they will get removed after service firewall restart (with fw4+nftables) or service firewall reload (with fw3+iptables). For this reason I implemented the firewall include solution, which runs on every such event and restores the rules. You would also need some basic lock file implementation to avoid race conditions (because sometimes the firewall service will get reloaded multiple times quickly, before your script exits). Here is a basic lock file implementation which is used in geoip-shell and adblock-lean (another project I'm contributing to):
mk_lock()
{
[ -z "$lock_file" ] && die "The \$lock_file variable is unset."
check_lock
case $? in
1) return 1 ;;
2) printf '%s\n' "Lock file '$lock_file' exists. Refusing to open another instance."; return 1
esac
printf '%s\n' "$$" > "$lock_file" || printf '%s\n' "Failed to write to lock file '$lock_file'."
:
}
rm_lock()
{
[ -f "$lock_file" ] && rm -f "$lock_file"
:
}
check_lock()
{
local _pid=
[ -z "$lock_file" ] && { printf '%s\n' "\$lock_file variable is unset."; return 1; }
[ ! -f "$lock_file" ] && return 0
if read -r _pid _ < "$lock_file"
then
case "$_pid" in
"$$") return 0 ;;
*[!0-9]*) printf '%s\n' "lock file '$lock_file' contains unexpected string."; return 1; ;;
*) kill -0 "$_pid" 2>/dev/null && return 2
esac
else
printf '%s\n' "Failed to read the pid file '$lock_file'."; return 1
fi
printf '%s\n' "Detected stale lock file '$lock_file'. Removing."
rm_lock
:
}
lock_file="your-path-here"