diff --git a/docs/changes.txt b/docs/changes.txt index eee2bbd..ac9e913 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -167,4 +167,4 @@ v0.8.1 * nfqws2, zapret-lib: gzip compression and decompression * nfqws2: ignore trailing spaces and tabs in hostlists and ipsets. "host.com " or "1.2.3.4 " are ok now - +* init.d: 99-lan-filter custom script diff --git a/init.d/custom.d.examples.linux/99-lan-filter b/init.d/custom.d.examples.linux/99-lan-filter new file mode 100644 index 0000000..7b60d6a --- /dev/null +++ b/init.d/custom.d.examples.linux/99-lan-filter @@ -0,0 +1,145 @@ +# this custom script sets FILTER_MARK to specified source ips + +# NOTE !!! SCRIPT REQUIRES FILTER_MARK VAR IN CONFIG FILE !!! +# NOTE !!! WITHOUT FILTER_MARK IT DOES NOTHING !!! + +# NOTE !!! ON NON-OPENWRT SYSTEMS SCRIPT REQUIRES IFACE_LAN VAR IN CONFIG FILE !!! + +# can override in config : +# LAN ip/cidr list to be fooled. elements are space separated +FILTER_LAN_IP="${FILTER_LAN_IP:-192.168.0.0/16}" +FILTER_LAN_IP6="${FILTER_LAN_IP6:-fc00::/7}" +# allow fooling from local system (0|1) ? +FILTER_LAN_ALLOW_OUTPUT="${FILTER_LAN_ALLOW_OUTPUT:-1}" + +FILTER_LAN_SET="lanfilter" +FILTER_LAN_SET6="${FILTER_LAN_SET}6" +FILTER_LAN_IPSET_SIZE=${FILTER_LAN_IPSET_SIZE:-256} +FILTER_LAN_IPSET_OPT="${FILTER_LAN_IPSET_OPT:-hash:net hashsize 8192 maxelem $FILTER_LAN_IPSET_SIZE}" + +filter_mark_check() +{ + [ -n "$FILTER_MARK" ] || { + echo "WARNING ! lan filter cannot work without FILTER_MARK set in config" + return 1 + } + [ "$DISABLE_IPV4" = 1 -a "$DISABLE_IPV6" = 1 ] && return 1 + return 0 +} + +zapret_custom_firewall() +{ + # $1 - 1 - run, 0 - stop + + filter_mark_check || return + + local subnet lanifs rule + local setmark="-j MARK --set-mark $FILTER_MARK/$FILTER_MARK" + local filt4="-m set --match-set $FILTER_LAN_SET src" + local filt6="-m set --match-set $FILTER_LAN_SET6 src" + + get_lanif lanifs + + [ "$DISABLE_IPV4" != 1 ] && { + [ "$FILTER_LAN_ALLOW_OUTPUT" = 1 ] && { + ipt_print_op $1 "$setmark" "filter output" + ipt_add_del $1 OUTPUT -t mangle $setmark + } + [ -n "$lanifs" ] && { + [ "$1" = 1 ] && { + ipset create $FILTER_LAN_SET $FILTER_LAN_IPSET_OPT family inet 2>/dev/null + ipset flush $FILTER_LAN_SET + for subnet in $FILTER_LAN_IP; do + echo add $FILTER_LAN_SET $subnet + done | ipset -! restore + } + for lan in $lanifs; do + rule="-i $lan $filt4 $setmark" + ipt_print_op $1 "$rule" "filter forward" + ipt_add_del $1 FORWARD -t mangle $rule + done + } + } + [ "$DISABLE_IPV6" != 1 ] && { + [ "$FILTER_LAN_ALLOW_OUTPUT" = 1 ] && { + ipt_print_op $1 "$setmark" "filter output" 6 + ipt6_add_del $1 OUTPUT -t mangle $setmark + } + [ -n "$lanifs" ] && { + [ "$1" = 1 ] && { + ipset create $FILTER_LAN_SET6 $FILTER_LAN_IPSET_OPT family inet6 2>/dev/null + ipset flush $FILTER_LAN_SET6 + for subnet in $FILTER_LAN_IP6; do + echo add $FILTER_LAN_SET6 $subnet + done | ipset -! restore + } + for lan in $lanifs; do + rule="-i $lan $filt6 $setmark" + ipt_print_op $1 "$rule" "filter forward" 6 + ipt6_add_del $1 FORWARD -t mangle $rule + done + } + } + + [ "$1" = 1 ] || { + ipset destroy $FILTER_LAN_SET 2>/dev/null + ipset destroy $FILTER_LAN_SET6 2>/dev/null + } +} + +zapret_custom_firewall_nft() +{ + filter_mark_check || return + + local subnets rule + local setmark="meta mark set meta mark or $FILTER_MARK" + local filt4="ip saddr == @$FILTER_LAN_SET" + local filt6="ip6 saddr == @$FILTER_LAN_SET6" + local lanif="iifname @lanif" + + nft_add_chain forward_lan_filter "type filter hook forward priority mangle;" + nft_flush_chain forward_lan_filter + + if [ "$FILTER_LAN_ALLOW_OUTPUT" = 1 ]; then + nft_add_chain output_lan_filter "type filter hook output priority mangle;" + nft_flush_chain output_lan_filter + nft_print_op "$setmark" "filter output" "4+6" + nft_add_rule output_lan_filter $setmark + else + nft_del_chain output_lan_filter 2>/dev/null + fi + + [ "$DISABLE_IPV4" != 1 ] && { + make_comma_list subnets $FILTER_LAN_IP + nft_create_set $FILTER_LAN_SET "type ipv4_addr; size $FILTER_LAN_IPSET_SIZE; auto-merge; flags interval;" + nft_flush_set $FILTER_LAN_SET + nft_add_set_element $FILTER_LAN_SET "$subnets" + + rule="$lanif $filt4 $setmark" + nft_print_op "$rule" "filter forward" "4" + nft_add_rule forward_lan_filter $rule + } + [ "$DISABLE_IPV6" != 1 ] && { + make_comma_list subnets $FILTER_LAN_IP6 + nft_create_set $FILTER_LAN_SET6 "type ipv6_addr; size $FILTER_LAN_IPSET_SIZE; auto-merge; flags interval;" + nft_flush_set $FILTER_LAN_SET6 + nft_add_set_element $FILTER_LAN_SET6 "$subnets" + + rule="$lanif $filt6 $setmark" + nft_print_op "$rule" "filter forward" "6" + nft_add_rule forward_lan_filter $rule + } +} + + +zapret_custom_firewall_nft_flush() +{ + # this function is called after all nft fw rules are deleted + # however sets are not deleted. it's desired to clear sets here. + + nft_del_chain forward_lan_filter 2>/dev/null + nft_del_chain output_lan_filter 2>/dev/null + + nft_del_set $FILTER_LAN_SET 2>/dev/null + nft_del_set $FILTER_LAN_SET6 2>/dev/null +}