Creating procd init script with firewall rule inside

You could detect fw3/fw4 and create appropriate rules this way:

mk_fw_rule() {
	checkutil() { hash "$1" 2>/dev/null; }
	fw_util_missing() { die "Detected OpenWrt firewall $1 but the $2 utility is misisng."; }

	# detect OpenWrt firewall version
	owrt_fw_ver=
	checkutil uci && checkutil procd && for i in 3 4; do
		[ -x "/sbin/fw$i" ] && owrt_fw_ver="$i"
	done

	case "$owrt_fw_ver" in
		3)
			checkutil iptables || fw_util_missing 3 iptables
			mk_ipt_rule ;;
		4)
			checkutil nftables || fw_util_missing 4 nftables
			mk_nft_rule ;;
		*) die "Failed to detect OpenWrt firewall version."
	esac
}

mk_ipt_rule()
{
	: # create your iptables rule here
}

mk_nft_rule()
{
	: # create your nftables rule here
}

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"
1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.