mirror of https://github.com/bol-van/zapret/
35 changed files with 3093 additions and 1994 deletions
@ -0,0 +1,135 @@ |
|||||
|
exists() |
||||
|
{ |
||||
|
which "$1" >/dev/null 2>/dev/null |
||||
|
} |
||||
|
existf() |
||||
|
{ |
||||
|
type "$1" >/dev/null 2>/dev/null |
||||
|
} |
||||
|
whichq() |
||||
|
{ |
||||
|
which $1 2>/dev/null |
||||
|
} |
||||
|
exist_all() |
||||
|
{ |
||||
|
while [ -n "$1" ]; do |
||||
|
exists "$1" || return 1 |
||||
|
shift |
||||
|
done |
||||
|
return 0 |
||||
|
} |
||||
|
on_off_function() |
||||
|
{ |
||||
|
# $1 : function name on |
||||
|
# $2 : function name off |
||||
|
# $3 : 0 - off, 1 - on |
||||
|
local F="$1" |
||||
|
[ "$3" = "1" ] || F="$2" |
||||
|
shift |
||||
|
shift |
||||
|
shift |
||||
|
"$F" "$@" |
||||
|
} |
||||
|
contains() |
||||
|
{ |
||||
|
# check if substring $2 contains in $1 |
||||
|
[ "${1#*$2}" != "$1" ] |
||||
|
} |
||||
|
find_str_in_list() |
||||
|
{ |
||||
|
[ -n "$1" ] && { |
||||
|
for v in $2; do |
||||
|
[ "$v" = "$1" ] && return 0 |
||||
|
done |
||||
|
} |
||||
|
return 1 |
||||
|
} |
||||
|
end_with_newline() |
||||
|
{ |
||||
|
local c=$(tail -c 1) |
||||
|
[ "$c" = "" ] |
||||
|
} |
||||
|
make_separator_list() |
||||
|
{ |
||||
|
# $1 - var name to receive result |
||||
|
# $2 - separator |
||||
|
# $3,$4,... - elements |
||||
|
local var="$1" sep="$2" i |
||||
|
|
||||
|
shift; shift |
||||
|
while [ -n "$1" ]; do |
||||
|
if [ -n "$i" ] ; then |
||||
|
i=$i$sep$1 |
||||
|
else |
||||
|
i=$1 |
||||
|
fi |
||||
|
shift |
||||
|
done |
||||
|
eval $var=$i |
||||
|
} |
||||
|
make_comma_list() |
||||
|
{ |
||||
|
# $1 - var name to receive result |
||||
|
# $2,$3,... - elements |
||||
|
local var="$1" |
||||
|
shift |
||||
|
make_separator_list $var , "$@" |
||||
|
} |
||||
|
|
||||
|
is_linked_to_busybox() |
||||
|
{ |
||||
|
local IFS F P |
||||
|
|
||||
|
IFS=: |
||||
|
for path in $PATH; do |
||||
|
F=$path/$1 |
||||
|
P="$(readlink $F)" |
||||
|
if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi |
||||
|
[ "${P%busybox*}" != "$P" ] && return |
||||
|
done |
||||
|
} |
||||
|
get_dir_inode() |
||||
|
{ |
||||
|
local dir="$1" |
||||
|
[ -L "$dir" ] && dir=$(readlink "$dir") |
||||
|
ls -id "$dir" | awk '{print $1}' |
||||
|
} |
||||
|
|
||||
|
linux_min_version() |
||||
|
{ |
||||
|
# $1 - major ver |
||||
|
# $2 - minor ver |
||||
|
local V1=$(sed -nre 's/^Linux version ([0-9]+)\.[0-9]+.*$/\1/p' /proc/version) |
||||
|
local V2=$(sed -nre 's/^Linux version [0-9]+\.([0-9]+).*$/\1/p' /proc/version) |
||||
|
[ -n "$V1" -a -n "$V2" ] && [ "$V1" -gt "$1" -o "$V1" -eq "$1" -a "$V2" -ge "$2" ] |
||||
|
} |
||||
|
linux_get_subsys() |
||||
|
{ |
||||
|
local INIT=$(sed 's/\x0/\n/g' /proc/1/cmdline | head -n 1) |
||||
|
|
||||
|
[ -L "$INIT" ] && INIT=$(readlink "$INIT") |
||||
|
INIT=$(basename "$INIT") |
||||
|
if [ -f "/etc/openwrt_release" ] && [ "$INIT" = "procd" ] ; then |
||||
|
SUBSYS=openwrt |
||||
|
else |
||||
|
# generic linux |
||||
|
SUBSYS= |
||||
|
fi |
||||
|
} |
||||
|
openwrt_fw3() |
||||
|
{ |
||||
|
[ ! -x /sbin/fw4 -a -x /sbin/fw3 ] |
||||
|
} |
||||
|
openwrt_fw4() |
||||
|
{ |
||||
|
[ -x /sbin/fw4 ] |
||||
|
} |
||||
|
openwrt_fw3_integration() |
||||
|
{ |
||||
|
[ "$FWTYPE" = iptables ] && openwrt_fw3 |
||||
|
} |
||||
|
|
||||
|
create_dev_stdin() |
||||
|
{ |
||||
|
[ -e /dev/stdin ] || ln -s /proc/self/fd/0 /dev/stdin |
||||
|
} |
@ -0,0 +1,58 @@ |
|||||
|
read_yes_no() |
||||
|
{ |
||||
|
# $1 - default (Y/N) |
||||
|
local A |
||||
|
read A |
||||
|
[ -z "$A" ] || ([ "$A" != "Y" ] && [ "$A" != "y" ] && [ "$A" != "N" ] && [ "$A" != "n" ]) && A=$1 |
||||
|
[ "$A" = "Y" ] || [ "$A" = "y" ] || [ "$A" = "1" ] |
||||
|
} |
||||
|
ask_yes_no() |
||||
|
{ |
||||
|
# $1 - default (Y/N or 0/1) |
||||
|
# $2 - text |
||||
|
local DEFAULT=$1 |
||||
|
[ "$1" = "1" ] && DEFAULT=Y |
||||
|
[ "$1" = "0" ] && DEFAULT=N |
||||
|
[ -z "$DEFAULT" ] && DEFAULT=N |
||||
|
printf "$2 (default : $DEFAULT) (Y/N) ? " |
||||
|
read_yes_no $DEFAULT |
||||
|
} |
||||
|
ask_yes_no_var() |
||||
|
{ |
||||
|
# $1 - variable name for answer : 0/1 |
||||
|
# $2 - text |
||||
|
local DEFAULT |
||||
|
eval DEFAULT="\$$1" |
||||
|
if ask_yes_no "$DEFAULT" "$2"; then |
||||
|
eval $1=1 |
||||
|
else |
||||
|
eval $1=0 |
||||
|
fi |
||||
|
} |
||||
|
ask_list() |
||||
|
{ |
||||
|
# $1 - mode var |
||||
|
# $2 - space separated value list |
||||
|
# $3 - (optional) default value |
||||
|
local M_DEFAULT |
||||
|
eval M_DEFAULT="\$$1" |
||||
|
local M_ALL=$M_DEFAULT |
||||
|
local M="" |
||||
|
local m |
||||
|
|
||||
|
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;} |
||||
|
|
||||
|
n=1 |
||||
|
for m in $2; do |
||||
|
echo $n : $m |
||||
|
n=$(($n+1)) |
||||
|
done |
||||
|
printf "your choice (default : $M_DEFAULT) : " |
||||
|
read m |
||||
|
[ -n "$m" ] && M=$(echo $2 | cut -d ' ' -f$m 2>/dev/null) |
||||
|
[ -z "$M" ] && M="$M_DEFAULT" |
||||
|
echo selected : $M |
||||
|
eval $1="\"$M\"" |
||||
|
|
||||
|
[ "$M" != "$M_OLD" ] |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
require_root() |
||||
|
{ |
||||
|
local exe |
||||
|
echo \* checking privileges |
||||
|
[ $(id -u) -ne "0" ] && { |
||||
|
echo root is required |
||||
|
exe="$EXEDIR/$(basename "$0")" |
||||
|
exists sudo && exec sudo "$exe" |
||||
|
exists su && exec su root -c "$exe" |
||||
|
echo su or sudo not found |
||||
|
exitp 2 |
||||
|
} |
||||
|
} |
@ -0,0 +1,64 @@ |
|||||
|
linux_ipt_avail() |
||||
|
{ |
||||
|
exists iptables && exists ip6tables |
||||
|
} |
||||
|
linux_maybe_iptables_fwtype() |
||||
|
{ |
||||
|
linux_ipt_avail && FWTYPE=iptables |
||||
|
} |
||||
|
linux_nft_avail() |
||||
|
{ |
||||
|
exists nft |
||||
|
} |
||||
|
linux_fwtype() |
||||
|
{ |
||||
|
[ -n "$FWTYPE" ] && return |
||||
|
|
||||
|
FWTYPE=unsupported |
||||
|
|
||||
|
linux_get_subsys |
||||
|
if [ "$SUBSYS" = openwrt ] ; then |
||||
|
# linux kernel is new enough if fw4 is there |
||||
|
if [ -x /sbin/fw4 ] && linux_nft_avail ; then |
||||
|
FWTYPE=nftables |
||||
|
else |
||||
|
linux_maybe_iptables_fwtype |
||||
|
fi |
||||
|
else |
||||
|
SUBSYS= |
||||
|
# generic linux |
||||
|
# flowtable is implemented since kernel 4.16 |
||||
|
if linux_nft_avail && linux_min_version 4 16; then |
||||
|
FWTYPE=nftables |
||||
|
else |
||||
|
linux_maybe_iptables_fwtype |
||||
|
fi |
||||
|
fi |
||||
|
|
||||
|
export FWTYPE |
||||
|
} |
||||
|
|
||||
|
get_fwtype() |
||||
|
{ |
||||
|
[ -n "$FWTYPE" ] && return |
||||
|
|
||||
|
local UNAME="$(uname)" |
||||
|
|
||||
|
case "$UNAME" in |
||||
|
Linux) |
||||
|
linux_fwtype |
||||
|
;; |
||||
|
FreeBSD) |
||||
|
if exists ipfw ; then |
||||
|
FWTYPE=ipfw |
||||
|
else |
||||
|
FWTYPE=unsupported |
||||
|
fi |
||||
|
;; |
||||
|
*) |
||||
|
FWTYPE=unsupported |
||||
|
;; |
||||
|
esac |
||||
|
|
||||
|
export FWTYPE |
||||
|
} |
@ -0,0 +1,462 @@ |
|||||
|
GET_LIST_PREFIX=/ipset/get_ |
||||
|
|
||||
|
SYSTEMD_DIR=/lib/systemd |
||||
|
[ -d "$SYSTEMD_DIR" ] || SYSTEMD_DIR=/usr/lib/systemd |
||||
|
[ -d "$SYSTEMD_DIR" ] && SYSTEMD_SYSTEM_DIR="$SYSTEMD_DIR/system" |
||||
|
|
||||
|
INIT_SCRIPT=/etc/init.d/zapret |
||||
|
|
||||
|
|
||||
|
exitp() |
||||
|
{ |
||||
|
echo |
||||
|
echo press enter to continue |
||||
|
read A |
||||
|
exit $1 |
||||
|
} |
||||
|
|
||||
|
parse_var_checked() |
||||
|
{ |
||||
|
# $1 - file name |
||||
|
# $2 - var name |
||||
|
local sed="sed -nre s/^[[:space:]]*$2=[\\\"|\']?([^\\\"|\']*)[\\\"|\']?/\1/p" |
||||
|
local v="$($sed <"$1" | tail -n 1)" |
||||
|
eval $2=\"$v\" |
||||
|
} |
||||
|
parse_vars_checked() |
||||
|
{ |
||||
|
# $1 - file name |
||||
|
# $2,$3,... - var names |
||||
|
local f="$1" |
||||
|
shift |
||||
|
while [ -n "$1" ]; do |
||||
|
parse_var_checked "$f" $1 |
||||
|
shift |
||||
|
done |
||||
|
} |
||||
|
edit_file() |
||||
|
{ |
||||
|
# $1 - file name |
||||
|
local ed="$EDITOR" |
||||
|
[ -n "$ed" ] || { |
||||
|
for e in mcedit nano vi; do |
||||
|
exists "$e" && { |
||||
|
ed="$e" |
||||
|
break |
||||
|
} |
||||
|
done |
||||
|
} |
||||
|
[ -n "$ed" ] && "$ed" "$1" |
||||
|
} |
||||
|
edit_vars() |
||||
|
{ |
||||
|
# $1,$2,... - var names |
||||
|
local n=1 var v tmp="/tmp/zvars" |
||||
|
rm -f "$tmp" |
||||
|
while [ 1=1 ]; do |
||||
|
eval var="\$$n" |
||||
|
[ -n "$var" ] || break |
||||
|
eval v="\$$var" |
||||
|
echo $var=\"$v\" >>"$tmp" |
||||
|
n=$(($n+1)) |
||||
|
done |
||||
|
edit_file "$tmp" && parse_vars_checked "$tmp" "$@" |
||||
|
rm -f "$tmp" |
||||
|
} |
||||
|
|
||||
|
openrc_test() |
||||
|
{ |
||||
|
exists rc-update || return 1 |
||||
|
# some systems do not usse openrc-init but launch openrc from inittab |
||||
|
[ "$INIT" = "openrc-init" ] || grep -qE "sysinit.*openrc" /etc/inittab 2>/dev/null |
||||
|
} |
||||
|
check_system() |
||||
|
{ |
||||
|
echo \* checking system |
||||
|
|
||||
|
SYSTEM="" |
||||
|
SYSTEMCTL=$(whichq systemctl) |
||||
|
|
||||
|
get_fwtype |
||||
|
OPENWRT_FW3= |
||||
|
|
||||
|
local info |
||||
|
local UNAME=$(uname) |
||||
|
if [ "$UNAME" = "Linux" ]; then |
||||
|
# do not use 'exe' because it requires root |
||||
|
local INIT=$(sed 's/\x0/\n/g' /proc/1/cmdline | head -n 1) |
||||
|
[ -L "$INIT" ] && INIT=$(readlink "$INIT") |
||||
|
INIT=$(basename "$INIT") |
||||
|
# some distros include systemctl without systemd |
||||
|
if [ -d "$SYSTEMD_DIR" ] && [ -x "$SYSTEMCTL" ] && [ "$INIT" = "systemd" ]; then |
||||
|
SYSTEM=systemd |
||||
|
elif [ -f "/etc/openwrt_release" ] && exists opkg && exists uci && [ "$INIT" = "procd" ] ; then |
||||
|
{ |
||||
|
SYSTEM=openwrt |
||||
|
if openwrt_fw3 ; then |
||||
|
OPENWRT_FW3=1 |
||||
|
info="openwrt firewall uses fw3" |
||||
|
if is_ipt_flow_offload_avail; then |
||||
|
info="$info. hardware flow offloading requires iptables." |
||||
|
else |
||||
|
info="$info. flow offloading unavailable." |
||||
|
fi |
||||
|
elif openwrt_fw4; then |
||||
|
info="openwrt firewall uses fw4. flow offloading requires nftables." |
||||
|
fi |
||||
|
} |
||||
|
elif openrc_test; then |
||||
|
SYSTEM=openrc |
||||
|
else |
||||
|
echo system is not either systemd, openrc or openwrt based |
||||
|
echo easy installer can set up config settings but can\'t configure auto start |
||||
|
echo you have to do it manually. check readme.txt for manual setup info. |
||||
|
if ask_yes_no N "do you want to continue"; then |
||||
|
SYSTEM=linux |
||||
|
else |
||||
|
exitp 5 |
||||
|
fi |
||||
|
fi |
||||
|
elif [ "$UNAME" = "Darwin" ]; then |
||||
|
SYSTEM=macos |
||||
|
else |
||||
|
echo easy installer only supports Linux and MacOS. check readme.txt for supported systems and manual setup info. |
||||
|
exitp 5 |
||||
|
fi |
||||
|
echo system is based on $SYSTEM |
||||
|
[ -n "$info" ] && echo $info |
||||
|
} |
||||
|
|
||||
|
get_free_space_mb() |
||||
|
{ |
||||
|
df -m $PWD | awk '/[0-9]%/{print $(NF-2)}' |
||||
|
} |
||||
|
get_ram_kb() |
||||
|
{ |
||||
|
grep MemTotal /proc/meminfo | awk '{print $2}' |
||||
|
} |
||||
|
get_ram_mb() |
||||
|
{ |
||||
|
local R=$(get_ram_kb) |
||||
|
echo $(($R/1024)) |
||||
|
} |
||||
|
|
||||
|
crontab_del() |
||||
|
{ |
||||
|
exists crontab || return |
||||
|
|
||||
|
echo \* removing crontab entry |
||||
|
|
||||
|
CRONTMP=/tmp/cron.tmp |
||||
|
crontab -l >$CRONTMP 2>/dev/null |
||||
|
if grep -q "$GET_LIST_PREFIX" $CRONTMP; then |
||||
|
echo removing following entries from crontab : |
||||
|
grep "$GET_LIST_PREFIX" $CRONTMP |
||||
|
grep -v "$GET_LIST_PREFIX" $CRONTMP >$CRONTMP.2 |
||||
|
crontab $CRONTMP.2 |
||||
|
rm -f $CRONTMP.2 |
||||
|
fi |
||||
|
rm -f $CRONTMP |
||||
|
} |
||||
|
crontab_del_quiet() |
||||
|
{ |
||||
|
exists crontab || return |
||||
|
|
||||
|
CRONTMP=/tmp/cron.tmp |
||||
|
crontab -l >$CRONTMP 2>/dev/null |
||||
|
if grep -q "$GET_LIST_PREFIX" $CRONTMP; then |
||||
|
grep -v "$GET_LIST_PREFIX" $CRONTMP >$CRONTMP.2 |
||||
|
crontab $CRONTMP.2 |
||||
|
rm -f $CRONTMP.2 |
||||
|
fi |
||||
|
rm -f $CRONTMP |
||||
|
} |
||||
|
crontab_add() |
||||
|
{ |
||||
|
# $1 - hour min |
||||
|
# $2 - hour max |
||||
|
[ -x "$GET_LIST" ] && { |
||||
|
echo \* adding crontab entry |
||||
|
|
||||
|
if exists crontab; then |
||||
|
CRONTMP=/tmp/cron.tmp |
||||
|
crontab -l >$CRONTMP 2>/dev/null |
||||
|
if grep -q "$GET_LIST_PREFIX" $CRONTMP; then |
||||
|
echo some entries already exist in crontab. check if this is corrent : |
||||
|
grep "$GET_LIST_PREFIX" $CRONTMP |
||||
|
else |
||||
|
end_with_newline <"$CRONTMP" || echo >>"$CRONTMP" |
||||
|
echo "$(random 0 59) $(random $1 $2) */2 * * $GET_LIST" >>$CRONTMP |
||||
|
crontab $CRONTMP |
||||
|
fi |
||||
|
rm -f $CRONTMP |
||||
|
else |
||||
|
echo '!!! CRON IS ABSENT !!! LISTS AUTO UPDATE WILL NOT WORK !!!' |
||||
|
fi |
||||
|
} |
||||
|
} |
||||
|
cron_ensure_running() |
||||
|
{ |
||||
|
# if no crontabs present in /etc/cron openwrt init script does not launch crond. this is default |
||||
|
[ "$SYSTEM" = "openwrt" ] && { |
||||
|
/etc/init.d/cron enable |
||||
|
/etc/init.d/cron start |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
service_start_systemd() |
||||
|
{ |
||||
|
echo \* starting zapret service |
||||
|
|
||||
|
"$SYSTEMCTL" start zapret || { |
||||
|
echo could not start zapret service |
||||
|
exitp 30 |
||||
|
} |
||||
|
} |
||||
|
service_stop_systemd() |
||||
|
{ |
||||
|
echo \* stopping zapret service |
||||
|
|
||||
|
"$SYSTEMCTL" daemon-reload |
||||
|
"$SYSTEMCTL" disable zapret |
||||
|
"$SYSTEMCTL" stop zapret |
||||
|
} |
||||
|
service_remove_systemd() |
||||
|
{ |
||||
|
echo \* removing zapret service |
||||
|
|
||||
|
rm -f "$SYSTEMD_SYSTEM_DIR/zapret.service" |
||||
|
"$SYSTEMCTL" daemon-reload |
||||
|
} |
||||
|
timer_remove_systemd() |
||||
|
{ |
||||
|
echo \* removing zapret-list-update timer |
||||
|
|
||||
|
"$SYSTEMCTL" daemon-reload |
||||
|
"$SYSTEMCTL" disable zapret-list-update.timer |
||||
|
"$SYSTEMCTL" stop zapret-list-update.timer |
||||
|
rm -f "$SYSTEMD_SYSTEM_DIR/zapret-list-update.service" "$SYSTEMD_SYSTEM_DIR/zapret-list-update.timer" |
||||
|
"$SYSTEMCTL" daemon-reload |
||||
|
} |
||||
|
|
||||
|
install_sysv_init() |
||||
|
{ |
||||
|
# $1 - "0"=disable |
||||
|
echo \* installing init script |
||||
|
|
||||
|
[ -x "$INIT_SCRIPT" ] && { |
||||
|
"$INIT_SCRIPT" stop |
||||
|
"$INIT_SCRIPT" disable |
||||
|
} |
||||
|
ln -fs "$INIT_SCRIPT_SRC" "$INIT_SCRIPT" |
||||
|
[ "$1" != "0" ] && "$INIT_SCRIPT" enable |
||||
|
} |
||||
|
install_openrc_init() |
||||
|
{ |
||||
|
# $1 - "0"=disable |
||||
|
echo \* installing init script |
||||
|
|
||||
|
[ -x "$INIT_SCRIPT" ] && { |
||||
|
"$INIT_SCRIPT" stop |
||||
|
rc-update del zapret |
||||
|
} |
||||
|
ln -fs "$INIT_SCRIPT_SRC" "$INIT_SCRIPT" |
||||
|
[ "$1" != "0" ] && rc-update add zapret |
||||
|
} |
||||
|
service_remove_openrc() |
||||
|
{ |
||||
|
echo \* removing zapret service |
||||
|
|
||||
|
[ -x "$INIT_SCRIPT" ] && { |
||||
|
rc-update del zapret |
||||
|
"$INIT_SCRIPT" stop |
||||
|
} |
||||
|
rm -f "$INIT_SCRIPT" |
||||
|
} |
||||
|
service_start_sysv() |
||||
|
{ |
||||
|
[ -x "$INIT_SCRIPT" ] && { |
||||
|
echo \* starting zapret service |
||||
|
"$INIT_SCRIPT" start || { |
||||
|
echo could not start zapret service |
||||
|
exitp 30 |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
service_stop_sysv() |
||||
|
{ |
||||
|
[ -x "$INIT_SCRIPT" ] && { |
||||
|
echo \* stopping zapret service |
||||
|
"$INIT_SCRIPT" stop |
||||
|
} |
||||
|
} |
||||
|
service_remove_sysv() |
||||
|
{ |
||||
|
echo \* removing zapret service |
||||
|
|
||||
|
[ -x "$INIT_SCRIPT" ] && { |
||||
|
"$INIT_SCRIPT" disable |
||||
|
"$INIT_SCRIPT" stop |
||||
|
} |
||||
|
rm -f "$INIT_SCRIPT" |
||||
|
} |
||||
|
|
||||
|
check_kmod() |
||||
|
{ |
||||
|
[ -f "/lib/modules/$(uname -r)/$1.ko" ] |
||||
|
} |
||||
|
check_package_exists_openwrt() |
||||
|
{ |
||||
|
[ -n "$(opkg list $1)" ] |
||||
|
} |
||||
|
check_package_openwrt() |
||||
|
{ |
||||
|
[ -n "$(opkg list-installed $1)" ] && return 0 |
||||
|
local what=$(opkg whatprovides $1 | tail -n +2 | head -n 1) |
||||
|
[ -n "$what" ] || return 1 |
||||
|
[ -n "$(opkg list-installed $what)" ] |
||||
|
} |
||||
|
check_packages_openwrt() |
||||
|
{ |
||||
|
for pkg in $@; do |
||||
|
check_package_openwrt $pkg || return |
||||
|
done |
||||
|
} |
||||
|
|
||||
|
install_openwrt_iface_hook() |
||||
|
{ |
||||
|
echo \* installing ifup hook |
||||
|
|
||||
|
ln -fs "$OPENWRT_IFACE_HOOK" /etc/hotplug.d/iface |
||||
|
} |
||||
|
remove_openwrt_iface_hook() |
||||
|
{ |
||||
|
echo \* removing ifup hook |
||||
|
|
||||
|
rm -f /etc/hotplug.d/iface/??-zapret |
||||
|
} |
||||
|
openwrt_fw_section_find() |
||||
|
{ |
||||
|
# $1 - fw include postfix |
||||
|
# echoes section number |
||||
|
|
||||
|
i=0 |
||||
|
while true |
||||
|
do |
||||
|
path=$(uci -q get firewall.@include[$i].path) |
||||
|
[ -n "$path" ] || break |
||||
|
[ "$path" = "$OPENWRT_FW_INCLUDE$1" ] && { |
||||
|
echo $i |
||||
|
return 0 |
||||
|
} |
||||
|
i=$(($i+1)) |
||||
|
done |
||||
|
return 1 |
||||
|
} |
||||
|
openwrt_fw_section_del() |
||||
|
{ |
||||
|
# $1 - fw include postfix |
||||
|
|
||||
|
local id=$(openwrt_fw_section_find $1) |
||||
|
[ -n "$id" ] && { |
||||
|
uci delete firewall.@include[$id] && uci commit firewall |
||||
|
rm -f "$OPENWRT_FW_INCLUDE$1" |
||||
|
} |
||||
|
} |
||||
|
openwrt_fw_section_add() |
||||
|
{ |
||||
|
openwrt_fw_section_find || |
||||
|
{ |
||||
|
uci add firewall include >/dev/null || return |
||||
|
echo -1 |
||||
|
} |
||||
|
} |
||||
|
openwrt_fw_section_configure() |
||||
|
{ |
||||
|
local id=$(openwrt_fw_section_add $1) |
||||
|
[ -z "$id" ] || |
||||
|
! uci set firewall.@include[$id].path="$OPENWRT_FW_INCLUDE" || |
||||
|
! uci set firewall.@include[$id].reload="1" || |
||||
|
! uci commit firewall && |
||||
|
{ |
||||
|
echo could not add firewall include |
||||
|
exitp 50 |
||||
|
} |
||||
|
} |
||||
|
install_openwrt_firewall() |
||||
|
{ |
||||
|
echo \* installing firewall script $1 |
||||
|
|
||||
|
[ -n "MODE" ] || { |
||||
|
echo should specify MODE in $ZAPRET_CONFIG |
||||
|
exitp 7 |
||||
|
} |
||||
|
|
||||
|
echo "linking : $FW_SCRIPT_SRC => $OPENWRT_FW_INCLUDE" |
||||
|
ln -fs "$FW_SCRIPT_SRC" "$OPENWRT_FW_INCLUDE" |
||||
|
|
||||
|
openwrt_fw_section_configure $1 |
||||
|
} |
||||
|
restart_openwrt_firewall() |
||||
|
{ |
||||
|
echo \* restarting firewall |
||||
|
|
||||
|
fw3 -q restart || { |
||||
|
echo could not restart firewall |
||||
|
exitp 30 |
||||
|
} |
||||
|
} |
||||
|
remove_openwrt_firewall() |
||||
|
{ |
||||
|
echo \* removing firewall script |
||||
|
|
||||
|
openwrt_fw_section_del |
||||
|
# from old zapret versions. now we use single include |
||||
|
openwrt_fw_section_del 6 |
||||
|
} |
||||
|
|
||||
|
clear_ipset() |
||||
|
{ |
||||
|
echo "* clearing ipset(s)" |
||||
|
|
||||
|
# free some RAM |
||||
|
"$IPSET_DIR/create_ipset.sh" clear |
||||
|
} |
||||
|
|
||||
|
|
||||
|
service_install_macos() |
||||
|
{ |
||||
|
echo \* installing zapret service |
||||
|
|
||||
|
ln -fs "$ZAPRET_BASE/init.d/macos/zapret.plist" /Library/LaunchDaemons |
||||
|
} |
||||
|
service_start_macos() |
||||
|
{ |
||||
|
echo \* starting zapret service |
||||
|
|
||||
|
"$INIT_SCRIPT_SRC" start |
||||
|
} |
||||
|
service_stop_macos() |
||||
|
{ |
||||
|
echo \* stopping zapret service |
||||
|
|
||||
|
"$INIT_SCRIPT_SRC" stop |
||||
|
} |
||||
|
service_remove_macos() |
||||
|
{ |
||||
|
echo \* removing zapret service |
||||
|
|
||||
|
rm -f /Library/LaunchDaemons/zapret.plist |
||||
|
zapret_stop_daemons |
||||
|
} |
||||
|
|
||||
|
remove_macos_firewall() |
||||
|
{ |
||||
|
echo \* removing zapret PF hooks |
||||
|
|
||||
|
pf_anchors_clear |
||||
|
pf_anchors_del |
||||
|
pf_anchor_root_del |
||||
|
pf_anchor_root_reload |
||||
|
} |
@ -0,0 +1,172 @@ |
|||||
|
ipt() |
||||
|
{ |
||||
|
iptables -C "$@" >/dev/null 2>/dev/null || iptables -I "$@" |
||||
|
} |
||||
|
ipta() |
||||
|
{ |
||||
|
iptables -C "$@" >/dev/null 2>/dev/null || iptables -A "$@" |
||||
|
} |
||||
|
ipt_del() |
||||
|
{ |
||||
|
iptables -C "$@" >/dev/null 2>/dev/null && iptables -D "$@" |
||||
|
} |
||||
|
ipt_add_del() |
||||
|
{ |
||||
|
on_off_function ipt ipt_del "$@" |
||||
|
} |
||||
|
ipta_add_del() |
||||
|
{ |
||||
|
on_off_function ipta ipt_del "$@" |
||||
|
} |
||||
|
ipt6() |
||||
|
{ |
||||
|
ip6tables -C "$@" >/dev/null 2>/dev/null || ip6tables -I "$@" |
||||
|
} |
||||
|
ipt6a() |
||||
|
{ |
||||
|
ip6tables -C "$@" >/dev/null 2>/dev/null || ip6tables -A "$@" |
||||
|
} |
||||
|
ipt6_del() |
||||
|
{ |
||||
|
ip6tables -C "$@" >/dev/null 2>/dev/null && ip6tables -D "$@" |
||||
|
} |
||||
|
ipt6_add_del() |
||||
|
{ |
||||
|
on_off_function ipt6 ipt6_del "$@" |
||||
|
} |
||||
|
ipt6a_add_del() |
||||
|
{ |
||||
|
on_off_function ipt6 ipt6a_del "$@" |
||||
|
} |
||||
|
|
||||
|
is_ipt_flow_offload_avail() |
||||
|
{ |
||||
|
# $1 = '' for ipv4, '6' for ipv6 |
||||
|
grep -q FLOWOFFLOAD 2>/dev/null /proc/net/ip$1_tables_targets |
||||
|
} |
||||
|
|
||||
|
filter_apply_port_target() |
||||
|
{ |
||||
|
# $1 - var name of iptables filter |
||||
|
local f |
||||
|
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then |
||||
|
f="-m multiport --dports 80,443" |
||||
|
elif [ "$MODE_HTTPS" = "1" ]; then |
||||
|
f="--dport 443" |
||||
|
elif [ "$MODE_HTTP" = "1" ]; then |
||||
|
f="--dport 80" |
||||
|
else |
||||
|
echo WARNING !!! HTTP and HTTPS are both disabled |
||||
|
fi |
||||
|
eval $1="\"\$$1 $f\"" |
||||
|
} |
||||
|
filter_apply_ipset_target4() |
||||
|
{ |
||||
|
# $1 - var name of ipv4 iptables filter |
||||
|
if [ "$MODE_FILTER" = "ipset" ]; then |
||||
|
eval $1="\"\$$1 -m set --match-set zapret dst\"" |
||||
|
fi |
||||
|
} |
||||
|
filter_apply_ipset_target6() |
||||
|
{ |
||||
|
# $1 - var name of ipv6 iptables filter |
||||
|
if [ "$MODE_FILTER" = "ipset" ]; then |
||||
|
eval $1="\"\$$1 -m set --match-set zapret6 dst\"" |
||||
|
fi |
||||
|
} |
||||
|
filter_apply_ipset_target() |
||||
|
{ |
||||
|
# $1 - var name of ipv4 iptables filter |
||||
|
# $2 - var name of ipv6 iptables filter |
||||
|
filter_apply_ipset_target4 $1 |
||||
|
filter_apply_ipset_target6 $2 |
||||
|
} |
||||
|
|
||||
|
|
||||
|
zapret_do_firewall_ipt() |
||||
|
{ |
||||
|
# $1 - 1 - add, 0 - del |
||||
|
|
||||
|
if [ "$1" = 1 ]; then |
||||
|
echo Applying iptables |
||||
|
else |
||||
|
echo Clearing iptables |
||||
|
fi |
||||
|
|
||||
|
local mode="${MODE_OVERRIDE:-$MODE}" |
||||
|
|
||||
|
[ "$mode" = "tpws-socks" ] && return 0 |
||||
|
|
||||
|
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4" |
||||
|
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK" |
||||
|
local f4 f6 qn qns qn6 qns6 |
||||
|
|
||||
|
# always create ipsets. ip_exclude ipset is required |
||||
|
[ "$1" = 1 ] && create_ipset no-update |
||||
|
|
||||
|
case "$mode" in |
||||
|
tpws) |
||||
|
if [ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ]; then |
||||
|
echo both http and https are disabled. not applying redirection. |
||||
|
else |
||||
|
filter_apply_port_target f4 |
||||
|
f6=$f4 |
||||
|
filter_apply_ipset_target f4 f6 |
||||
|
fw_tpws $1 "$f4" "$f6" $TPPORT |
||||
|
fi |
||||
|
;; |
||||
|
|
||||
|
nfqws) |
||||
|
# quite complex but we need to minimize nfqws processes to save RAM |
||||
|
get_nfqws_qnums qn qns qn6 qns6 |
||||
|
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn" ] && [ "$qn" = "$qns" ]; then |
||||
|
filter_apply_port_target f4 |
||||
|
f4="$f4 $first_packet_only" |
||||
|
filter_apply_ipset_target4 f4 |
||||
|
fw_nfqws_post4 $1 "$f4 $desync" $qn |
||||
|
else |
||||
|
if [ -n "$qn" ]; then |
||||
|
f4="--dport 80" |
||||
|
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f4="$f4 $first_packet_only" |
||||
|
filter_apply_ipset_target4 f4 |
||||
|
fw_nfqws_post4 $1 "$f4 $desync" $qn |
||||
|
fi |
||||
|
if [ -n "$qns" ]; then |
||||
|
f4="--dport 443 $first_packet_only" |
||||
|
filter_apply_ipset_target4 f4 |
||||
|
fw_nfqws_post4 $1 "$f4 $desync" $qns |
||||
|
fi |
||||
|
fi |
||||
|
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn6" ] && [ "$qn6" = "$qns6" ]; then |
||||
|
filter_apply_port_target f6 |
||||
|
f6="$f6 $first_packet_only" |
||||
|
filter_apply_ipset_target6 f6 |
||||
|
fw_nfqws_post6 $1 "$f6 $desync" $qn6 |
||||
|
else |
||||
|
if [ -n "$qn6" ]; then |
||||
|
f6="--dport 80" |
||||
|
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f6="$f6 $first_packet_only" |
||||
|
filter_apply_ipset_target6 f6 |
||||
|
fw_nfqws_post6 $1 "$f6 $desync" $qn6 |
||||
|
fi |
||||
|
if [ -n "$qns6" ]; then |
||||
|
f6="--dport 443 $first_packet_only" |
||||
|
filter_apply_ipset_target6 f6 |
||||
|
fw_nfqws_post6 $1 "$f6 $desync" $qns6 |
||||
|
fi |
||||
|
fi |
||||
|
;; |
||||
|
custom) |
||||
|
existf zapret_custom_firewall && zapret_custom_firewall $1 |
||||
|
;; |
||||
|
esac |
||||
|
|
||||
|
if [ "$1" = 1 ] ; then |
||||
|
existf flow_offloading_exempt && flow_offloading_exempt |
||||
|
else |
||||
|
existf flow_offloading_unexempt && flow_offloading_unexempt |
||||
|
unprepare_tpws_fw |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
zapret_do_firewall() |
||||
|
{ |
||||
|
linux_fwtype |
||||
|
|
||||
|
case "$FWTYPE" in |
||||
|
iptables) |
||||
|
zapret_do_firewall_ipt "$@" |
||||
|
;; |
||||
|
nftables) |
||||
|
zapret_do_firewall_nft "$@" |
||||
|
;; |
||||
|
esac |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
zapret_apply_firewall() |
||||
|
{ |
||||
|
zapret_do_firewall 1 "$@" |
||||
|
} |
||||
|
zapret_unapply_firewall() |
||||
|
{ |
||||
|
zapret_do_firewall 0 "$@" |
||||
|
} |
@ -0,0 +1,51 @@ |
|||||
|
# there's no route_localnet for ipv6 |
||||
|
# the best we can is to route to link local of the incoming interface |
||||
|
# OUTPUT - can DNAT to ::1 |
||||
|
# PREROUTING - can't DNAT to ::1. can DNAT to link local of -i interface or to any global addr |
||||
|
# not a good idea to expose tpws to the world (bind to ::) |
||||
|
|
||||
|
|
||||
|
get_ipv6_linklocal() |
||||
|
{ |
||||
|
# $1 - interface name. if empty - any interface |
||||
|
if exists ip ; then |
||||
|
local dev |
||||
|
[ -n "$1" ] && dev="dev $1" |
||||
|
ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope link.*$/\1/;t;d' | head -n 1 |
||||
|
else |
||||
|
ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Link.*$/\1/;t;d' | head -n 1 |
||||
|
fi |
||||
|
} |
||||
|
get_ipv6_global() |
||||
|
{ |
||||
|
# $1 - interface name. if empty - any interface |
||||
|
if exists ip ; then |
||||
|
local dev |
||||
|
[ -n "$1" ] && dev="dev $1" |
||||
|
ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope global.*$/\1/;t;d' | head -n 1 |
||||
|
else |
||||
|
ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Global.*$/\1/;t;d' | head -n 1 |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
iface_is_up() |
||||
|
{ |
||||
|
# $1 - interface name |
||||
|
[ -f /sys/class/net/$1/operstate ] || return |
||||
|
local state |
||||
|
read state </sys/class/net/$1/operstate |
||||
|
[ "$state" != "down" ] |
||||
|
} |
||||
|
wait_ifup() |
||||
|
{ |
||||
|
# $1 - interface name |
||||
|
local ct=0 |
||||
|
while |
||||
|
iface_is_up $1 && return |
||||
|
[ "$ct" -ge "$IFUP_WAIT_SEC" ] && break |
||||
|
echo waiting for ifup of $1 for another $(($IFUP_WAIT_SEC - $ct)) seconds ... |
||||
|
ct=$(($ct+1)) |
||||
|
sleep 1 |
||||
|
do :; done |
||||
|
false |
||||
|
} |
@ -0,0 +1,348 @@ |
|||||
|
[ -n "$ZAPRET_NFT_TABLE" ] || ZAPRET_NFT_TABLE=zapret |
||||
|
|
||||
|
# required for : nft -f - |
||||
|
create_dev_stdin |
||||
|
|
||||
|
nft_create_table() |
||||
|
{ |
||||
|
nft add table inet $ZAPRET_NFT_TABLE |
||||
|
} |
||||
|
nft_del_table() |
||||
|
{ |
||||
|
nft delete table inet $ZAPRET_NFT_TABLE 2>/dev/null |
||||
|
} |
||||
|
nft_list_table() |
||||
|
{ |
||||
|
nft -t list table inet $ZAPRET_NFT_TABLE |
||||
|
} |
||||
|
|
||||
|
nft_create_set() |
||||
|
{ |
||||
|
# $1 - set name |
||||
|
# $2 - params |
||||
|
nft create set inet $ZAPRET_NFT_TABLE $1 "{ $2 }" 2>/dev/null |
||||
|
} |
||||
|
nft_del_set() |
||||
|
{ |
||||
|
# $1 - set name |
||||
|
nft delete set inet $ZAPRET_NFT_TABLE $1 |
||||
|
} |
||||
|
nft_flush_set() |
||||
|
{ |
||||
|
# $1 - set name |
||||
|
nft flush set inet $ZAPRET_NFT_TABLE $1 |
||||
|
} |
||||
|
nft_set_exists() |
||||
|
{ |
||||
|
# $1 - set name |
||||
|
nft -t list set inet $ZAPRET_NFT_TABLE $1 2>/dev/null >/dev/null |
||||
|
} |
||||
|
|
||||
|
nft_del_all_chains_from_table() |
||||
|
{ |
||||
|
# $1 - table_name with or without family |
||||
|
|
||||
|
# delete all chains with possible references to each other |
||||
|
# cannot just delete all in the list because of references |
||||
|
# avoid infinite loops |
||||
|
local chains deleted=1 error=1 |
||||
|
while [ -n "$deleted" -a -n "$error" ]; do |
||||
|
chains=$(nft -t list table $1 2>/dev/null | sed -nre "s/^[ ]*chain ([^ ]+) \{/\1/p" | xargs) |
||||
|
[ -n "$chains" ] || break |
||||
|
deleted= |
||||
|
error= |
||||
|
for chain in $chains; do |
||||
|
if nft delete chain $1 $chain 2>/dev/null; then |
||||
|
deleted=1 |
||||
|
else |
||||
|
error=1 |
||||
|
fi |
||||
|
done |
||||
|
done |
||||
|
} |
||||
|
|
||||
|
nft_del_chains() |
||||
|
{ |
||||
|
nft_del_all_chains_from_table "inet $ZAPRET_NFT_TABLE" |
||||
|
} |
||||
|
nft_create_chains() |
||||
|
{ |
||||
|
cat << EOF | nft -f - |
||||
|
add chain inet $ZAPRET_NFT_TABLE dnat_output { type nat hook output priority -101; } |
||||
|
flush chain inet $ZAPRET_NFT_TABLE dnat_output |
||||
|
add chain inet $ZAPRET_NFT_TABLE dnat_pre { type nat hook prerouting priority -101; } |
||||
|
flush chain inet $ZAPRET_NFT_TABLE dnat_pre |
||||
|
add chain inet $ZAPRET_NFT_TABLE forward { type filter hook forward priority -1; } |
||||
|
flush chain inet $ZAPRET_NFT_TABLE forward |
||||
|
add chain inet $ZAPRET_NFT_TABLE input { type filter hook input priority -1; } |
||||
|
flush chain inet $ZAPRET_NFT_TABLE input |
||||
|
add chain inet $ZAPRET_NFT_TABLE flow_offload |
||||
|
flush chain inet $ZAPRET_NFT_TABLE flow_offload |
||||
|
add chain inet $ZAPRET_NFT_TABLE localnet_protect |
||||
|
flush chain inet $ZAPRET_NFT_TABLE localnet_protect |
||||
|
add rule inet $ZAPRET_NFT_TABLE localnet_protect ip daddr $TPWS_LOCALHOST4 return comment "route_localnet allow access to tpws" |
||||
|
add rule inet $ZAPRET_NFT_TABLE localnet_protect ip daddr 127.0.0.0/8 drop comment "route_localnet remote access protection" |
||||
|
add rule inet $ZAPRET_NFT_TABLE input iifname != lo jump localnet_protect |
||||
|
add chain inet $ZAPRET_NFT_TABLE postrouting { type filter hook postrouting priority -151; } |
||||
|
flush chain inet $ZAPRET_NFT_TABLE postrouting |
||||
|
add set inet $ZAPRET_NFT_TABLE lanif { type ifname; } |
||||
|
add set inet $ZAPRET_NFT_TABLE wanif { type ifname; } |
||||
|
add set inet $ZAPRET_NFT_TABLE wanif6 { type ifname; } |
||||
|
EOF |
||||
|
} |
||||
|
nft_del_flowtable() |
||||
|
{ |
||||
|
nft delete flowtable inet $ZAPRET_NFT_TABLE ft 2>/dev/null |
||||
|
} |
||||
|
nft_create_or_update_flowtable() |
||||
|
{ |
||||
|
# $1 = flags ('offload' for hw offload) |
||||
|
# $2,$3,$4,... - interfaces |
||||
|
# can be called multiple times to add interfaces. interfaces can only be added , not removed |
||||
|
local flags=$1 devices |
||||
|
shift |
||||
|
make_comma_list devices "$@" |
||||
|
[ -n "$devices" ] && devices="devices={$devices};" |
||||
|
[ -n "$flags" ] && flags="flags $flags;" |
||||
|
nft add flowtable inet $ZAPRET_NFT_TABLE ft "{ hook ingress priority -1; $flags $devices }" |
||||
|
} |
||||
|
nft_flush_ifsets() |
||||
|
{ |
||||
|
cat << EOF | nft -f - 2>/dev/null |
||||
|
flush set inet $ZAPRET_NFT_TABLE lanif |
||||
|
flush set inet $ZAPRET_NFT_TABLE wanif |
||||
|
flush set inet $ZAPRET_NFT_TABLE wanif6 |
||||
|
EOF |
||||
|
} |
||||
|
nft_list_ifsets() |
||||
|
{ |
||||
|
nft list set inet $ZAPRET_NFT_TABLE lanif |
||||
|
nft list set inet $ZAPRET_NFT_TABLE wanif |
||||
|
nft list set inet $ZAPRET_NFT_TABLE wanif6 |
||||
|
nft list flowtable inet $ZAPRET_NFT_TABLE ft |
||||
|
} |
||||
|
|
||||
|
nft_create_firewall() |
||||
|
{ |
||||
|
nft_create_table |
||||
|
nft_del_flowtable |
||||
|
nft_create_chains |
||||
|
} |
||||
|
nft_del_firewall() |
||||
|
{ |
||||
|
nft_del_chains |
||||
|
nft_del_flowtable |
||||
|
nft_flush_ifsets |
||||
|
} |
||||
|
|
||||
|
nft_add_rule() |
||||
|
{ |
||||
|
# $1 - chain |
||||
|
# $2,$3,... - rule(s) |
||||
|
local chain="$1" |
||||
|
shift |
||||
|
nft add rule inet $ZAPRET_NFT_TABLE $chain "$@" |
||||
|
} |
||||
|
nft_add_set_elements() |
||||
|
{ |
||||
|
# $1 - set name |
||||
|
# $2,$3,... - element(s) |
||||
|
local set="$1" elements |
||||
|
shift |
||||
|
make_comma_list elements "$@" |
||||
|
[ -z "$elements" ] || nft add element inet $ZAPRET_NFT_TABLE $set "{ $elements }" |
||||
|
} |
||||
|
nft_reverse_nfqws_rule() |
||||
|
{ |
||||
|
echo "$@" | sed -e 's/oifname /iifname /g' -e 's/dport /sport /g' -e 's/daddr /saddr /g' -e 's/ct original /ct reply /g' -e "s/mark and $DESYNC_MARK == 0//g" |
||||
|
} |
||||
|
nft_clean_nfqws_rule() |
||||
|
{ |
||||
|
echo "$@" | sed -e "s/mark and $DESYNC_MARK == 0//g" |
||||
|
} |
||||
|
nft_add_nfqws_flow_exempt_rule() |
||||
|
{ |
||||
|
# $1 - rule (must be all filters in one var) |
||||
|
nft_add_rule flow_offload $(nft_clean_nfqws_rule $1) return comment \"direct flow offloading exemption\" |
||||
|
nft_add_rule flow_offload $(nft_reverse_nfqws_rule $1) return comment \"reverse flow offloading exemption\" |
||||
|
} |
||||
|
|
||||
|
nft_hw_offload_supported() |
||||
|
{ |
||||
|
# $1,$2,... - interface names |
||||
|
local devices res=1 |
||||
|
make_comma_list devices "$@" |
||||
|
[ -n "$devices" ] && devices="devices={$devices};" |
||||
|
nft add table ${ZAPRET_NFT_TABLE}_test && nft add flowtable ${ZAPRET_NFT_TABLE}_test ft "{ flags offload; $devices }" 2>/dev/null && res=0 |
||||
|
nft delete table ${ZAPRET_NFT_TABLE}_test 2>/dev/null |
||||
|
return $res |
||||
|
} |
||||
|
|
||||
|
nft_apply_flow_offloading() |
||||
|
{ |
||||
|
# ft can be absent |
||||
|
nft_add_rule flow_offload meta l4proto "{ tcp, udp }" flow add @ft 2>/dev/null && nft_add_rule forward jump flow_offload |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
nft_filter_apply_port_target() |
||||
|
{ |
||||
|
# $1 - var name of nftables filter |
||||
|
local f |
||||
|
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then |
||||
|
f="tcp dport {80,443}" |
||||
|
elif [ "$MODE_HTTPS" = "1" ]; then |
||||
|
f="tcp dport 443" |
||||
|
elif [ "$MODE_HTTP" = "1" ]; then |
||||
|
f="tcp dport 80" |
||||
|
else |
||||
|
echo WARNING !!! HTTP and HTTPS are both disabled |
||||
|
fi |
||||
|
eval $1="\"\$$1 $f\"" |
||||
|
} |
||||
|
nft_filter_apply_ipset_target4() |
||||
|
{ |
||||
|
# $1 - var name of ipv4 nftables filter |
||||
|
if [ "$MODE_FILTER" = "ipset" ]; then |
||||
|
eval $1="\"\$$1 ip daddr @zapret\"" |
||||
|
fi |
||||
|
} |
||||
|
nft_filter_apply_ipset_target6() |
||||
|
{ |
||||
|
# $1 - var name of ipv6 nftables filter |
||||
|
if [ "$MODE_FILTER" = "ipset" ]; then |
||||
|
eval $1="\"\$$1 ip6 daddr @zapret6\"" |
||||
|
fi |
||||
|
} |
||||
|
nft_filter_apply_ipset_target() |
||||
|
{ |
||||
|
# $1 - var name of ipv4 nftables filter |
||||
|
# $2 - var name of ipv6 nftables filter |
||||
|
nft_filter_apply_ipset_target4 $1 |
||||
|
nft_filter_apply_ipset_target6 $2 |
||||
|
} |
||||
|
|
||||
|
nft_only() |
||||
|
{ |
||||
|
linux_fwtype |
||||
|
|
||||
|
case "$FWTYPE" in |
||||
|
nftables) |
||||
|
"$@" |
||||
|
;; |
||||
|
esac |
||||
|
} |
||||
|
|
||||
|
zapret_reload_ifsets() |
||||
|
{ |
||||
|
nft_only nft_create_table ; nft_fill_ifsets |
||||
|
return 0 |
||||
|
} |
||||
|
zapret_list_ifsets() |
||||
|
{ |
||||
|
nft_only nft_list_ifsets |
||||
|
return 0 |
||||
|
} |
||||
|
zapret_list_table() |
||||
|
{ |
||||
|
nft_only nft_list_table |
||||
|
return 0 |
||||
|
} |
||||
|
|
||||
|
zapret_apply_firewall_nft() |
||||
|
{ |
||||
|
echo Applying nftables |
||||
|
|
||||
|
local mode="${MODE_OVERRIDE:-$MODE}" |
||||
|
|
||||
|
[ "$mode" = "tpws-socks" ] && return 0 |
||||
|
|
||||
|
local first_packet_only="ct original packets 1-4" |
||||
|
local desync="mark and $DESYNC_MARK == 0" |
||||
|
local f4 f6 qn qns qn6 qns6 |
||||
|
|
||||
|
create_ipset no-update |
||||
|
nft_create_firewall |
||||
|
nft_fill_ifsets |
||||
|
|
||||
|
case "$mode" in |
||||
|
tpws) |
||||
|
if [ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ]; then |
||||
|
echo both http and https are disabled. not applying redirection. |
||||
|
else |
||||
|
nft_filter_apply_port_target f4 |
||||
|
f6=$f4 |
||||
|
nft_filter_apply_ipset_target f4 f6 |
||||
|
nft_fw_tpws "$f4" "$f6" $TPPORT |
||||
|
fi |
||||
|
;; |
||||
|
nfqws) |
||||
|
# quite complex but we need to minimize nfqws processes to save RAM |
||||
|
get_nfqws_qnums qn qns qn6 qns6 |
||||
|
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn" ] && [ "$qn" = "$qns" ]; then |
||||
|
nft_filter_apply_port_target f4 |
||||
|
f4="$f4 $first_packet_only" |
||||
|
nft_filter_apply_ipset_target4 f4 |
||||
|
nft_fw_nfqws_post4 "$f4 $desync" $qn |
||||
|
else |
||||
|
if [ -n "$qn" ]; then |
||||
|
f4="tcp dport 80" |
||||
|
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f4="$f4 $first_packet_only" |
||||
|
nft_filter_apply_ipset_target4 f4 |
||||
|
nft_fw_nfqws_post4 "$f4 $desync" $qn |
||||
|
fi |
||||
|
if [ -n "$qns" ]; then |
||||
|
f4="tcp dport 443 $first_packet_only" |
||||
|
nft_filter_apply_ipset_target4 f4 |
||||
|
nft_fw_nfqws_post4 "$f4 $desync" $qns |
||||
|
fi |
||||
|
fi |
||||
|
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn6" ] && [ "$qn6" = "$qns6" ]; then |
||||
|
nft_filter_apply_port_target f6 |
||||
|
f6="$f6 $first_packet_only" |
||||
|
nft_filter_apply_ipset_target6 f6 |
||||
|
nft_fw_nfqws_post6 "$f6 $desync" $qn6 |
||||
|
else |
||||
|
if [ -n "$qn6" ]; then |
||||
|
f6="tcp dport 80" |
||||
|
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f6="$f6 $first_packet_only" |
||||
|
nft_filter_apply_ipset_target6 f6 |
||||
|
nft_fw_nfqws_post6 "$f6 $desync" $qn6 |
||||
|
fi |
||||
|
if [ -n "$qns6" ]; then |
||||
|
f6="tcp dport 443 $first_packet_only" |
||||
|
nft_filter_apply_ipset_target6 f6 |
||||
|
nft_fw_nfqws_post6 "$f6 $desync" $qns6 |
||||
|
fi |
||||
|
fi |
||||
|
;; |
||||
|
custom) |
||||
|
existf zapret_custom_firewall_nft && zapret_custom_firewall_nft |
||||
|
;; |
||||
|
esac |
||||
|
|
||||
|
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && nft_apply_flow_offloading |
||||
|
|
||||
|
return 0 |
||||
|
} |
||||
|
zapret_unapply_firewall_nft() |
||||
|
{ |
||||
|
echo Clearing nftables |
||||
|
|
||||
|
unprepare_route_localnet |
||||
|
nft_del_firewall |
||||
|
return 0 |
||||
|
} |
||||
|
zapret_do_firewall_nft() |
||||
|
{ |
||||
|
# $1 - 1 - add, 0 - del |
||||
|
|
||||
|
if [ "$1" = 0 ] ; then |
||||
|
zapret_unapply_firewall_nft |
||||
|
else |
||||
|
zapret_apply_firewall_nft |
||||
|
fi |
||||
|
|
||||
|
return 0 |
||||
|
} |
@ -0,0 +1,262 @@ |
|||||
|
PF_MAIN="/etc/pf.conf" |
||||
|
PF_ANCHOR_DIR=/etc/pf.anchors |
||||
|
PF_ANCHOR_ZAPRET="$PF_ANCHOR_DIR/zapret" |
||||
|
PF_ANCHOR_ZAPRET_V4="$PF_ANCHOR_DIR/zapret-v4" |
||||
|
PF_ANCHOR_ZAPRET_V6="$PF_ANCHOR_DIR/zapret-v6" |
||||
|
|
||||
|
pf_anchor_root_reload() |
||||
|
{ |
||||
|
echo reloading PF root anchor |
||||
|
pfctl -qf "$PF_MAIN" |
||||
|
} |
||||
|
|
||||
|
pf_anchor_root() |
||||
|
{ |
||||
|
local patch |
||||
|
[ -f "$PF_MAIN" ] && { |
||||
|
grep -q '^rdr-anchor "zapret"$' "$PF_MAIN" || { |
||||
|
echo patching rdr-anchor in $PF_MAIN |
||||
|
patch=1 |
||||
|
sed -i '' -e '/^rdr-anchor "com\.apple\/\*"$/i \ |
||||
|
rdr-anchor "zapret" |
||||
|
' $PF_MAIN |
||||
|
} |
||||
|
grep -q '^anchor "zapret"$' "$PF_MAIN" || { |
||||
|
echo patching anchor in $PF_MAIN |
||||
|
patch=1 |
||||
|
sed -i '' -e '/^anchor "com\.apple\/\*"$/i \ |
||||
|
anchor "zapret" |
||||
|
' $PF_MAIN |
||||
|
} |
||||
|
grep -q "^set limit table-entries" "$PF_MAIN" || { |
||||
|
echo patching table-entries limit |
||||
|
patch=1 |
||||
|
sed -i '' -e '/^scrub-anchor "com\.apple\/\*"$/i \ |
||||
|
set limit table-entries 5000000 |
||||
|
' $PF_MAIN |
||||
|
} |
||||
|
|
||||
|
grep -q '^anchor "zapret"$' "$PF_MAIN" && |
||||
|
grep -q '^rdr-anchor "zapret"$' "$PF_MAIN" && |
||||
|
grep -q '^set limit table-entries' "$PF_MAIN" && { |
||||
|
if [ -n "$patch" ]; then |
||||
|
echo successfully patched $PF_MAIN |
||||
|
pf_anchor_root_reload |
||||
|
else |
||||
|
echo successfully checked zapret anchors in $PF_MAIN |
||||
|
fi |
||||
|
return 0 |
||||
|
} |
||||
|
} |
||||
|
echo ---------------------------------- |
||||
|
echo Automatic $PF_MAIN patching failed. You must apply root anchors manually in your PF config. |
||||
|
echo rdr-anchor \"zapret\" |
||||
|
echo anchor \"zapret\" |
||||
|
echo ---------------------------------- |
||||
|
return 1 |
||||
|
} |
||||
|
pf_anchor_root_del() |
||||
|
{ |
||||
|
sed -i '' -e '/^anchor "zapret"$/d' -e '/^rdr-anchor "zapret"$/d' -e '/^set limit table-entries/d' "$PF_MAIN" |
||||
|
} |
||||
|
|
||||
|
pf_anchor_zapret() |
||||
|
{ |
||||
|
[ "$DISABLE_IPV4" = "1" ] || { |
||||
|
if [ -f "$ZIPLIST_EXCLUDE" ]; then |
||||
|
echo "table <nozapret> persist file \"$ZIPLIST_EXCLUDE\"" |
||||
|
else |
||||
|
echo "table <nozapret> persist" |
||||
|
fi |
||||
|
} |
||||
|
[ "$DISABLE_IPV6" = "1" ] || { |
||||
|
if [ -f "$ZIPLIST_EXCLUDE6" ]; then |
||||
|
echo "table <nozapret6> persist file \"$ZIPLIST_EXCLUDE6\"" |
||||
|
else |
||||
|
echo "table <nozapret6> persist" |
||||
|
fi |
||||
|
} |
||||
|
[ "$DISABLE_IPV4" = "1" ] || echo "rdr-anchor \"/zapret-v4\" inet to !<nozapret>" |
||||
|
[ "$DISABLE_IPV6" = "1" ] || echo "rdr-anchor \"/zapret-v6\" inet6 to !<nozapret6>" |
||||
|
[ "$DISABLE_IPV4" = "1" ] || echo "anchor \"/zapret-v4\" inet to !<nozapret>" |
||||
|
[ "$DISABLE_IPV6" = "1" ] || echo "anchor \"/zapret-v6\" inet6 to !<nozapret6>" |
||||
|
} |
||||
|
pf_anchor_zapret_tables() |
||||
|
{ |
||||
|
# $1 - variable to receive applied table names |
||||
|
# $2/$3 $4/$5 ... table_name/table_file |
||||
|
local tblv=$1 |
||||
|
local _tbl |
||||
|
|
||||
|
shift |
||||
|
[ "$MODE_FILTER" = "ipset" ] && |
||||
|
{ |
||||
|
while [ -n "$1" ] && [ -n "$2" ] ; do |
||||
|
[ -f "$2" ] && { |
||||
|
echo "table <$1> file \"$2\"" |
||||
|
_tbl="$_tbl<$1> " |
||||
|
} |
||||
|
shift |
||||
|
shift |
||||
|
done |
||||
|
} |
||||
|
[ -n "$_tbl" ] || _tbl="any" |
||||
|
|
||||
|
eval $tblv="\"\$_tbl\"" |
||||
|
} |
||||
|
pf_anchor_port_target() |
||||
|
{ |
||||
|
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then |
||||
|
echo "{80,443}" |
||||
|
elif [ "$MODE_HTTPS" = "1" ]; then |
||||
|
echo "443" |
||||
|
elif [ "$MODE_HTTP" = "1" ]; then |
||||
|
echo "80" |
||||
|
fi |
||||
|
} |
||||
|
|
||||
|
pf_anchor_zapret_v4_tpws() |
||||
|
{ |
||||
|
# $1 - port |
||||
|
|
||||
|
local rule port=$(pf_anchor_port_target) |
||||
|
for lan in $IFACE_LAN; do |
||||
|
for t in $tbl; do |
||||
|
echo "rdr on $lan inet proto tcp from any to $t port $port -> 127.0.0.1 port $1" |
||||
|
done |
||||
|
done |
||||
|
echo "rdr on lo0 inet proto tcp from !127.0.0.0/8 to any port $port -> 127.0.0.1 port $1" |
||||
|
for t in $tbl; do |
||||
|
rule="route-to (lo0 127.0.0.1) inet proto tcp from !127.0.0.0/8 to $t port $port user { >root }" |
||||
|
if [ -n "$IFACE_WAN" ] ; then |
||||
|
for wan in $IFACE_WAN; do |
||||
|
echo "pass out on $wan $rule" |
||||
|
done |
||||
|
else |
||||
|
echo "pass out $rule" |
||||
|
fi |
||||
|
done |
||||
|
} |
||||
|
|
||||
|
pf_anchor_zapret_v4() |
||||
|
{ |
||||
|
local tbl port |
||||
|
[ "$DISABLE_IPV4" = "1" ] || { |
||||
|
case $MODE in |
||||
|
tpws) |
||||
|
[ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ] && return |
||||
|
pf_anchor_zapret_tables tbl zapret-user "$ZIPLIST_USER" zapret "$ZIPLIST" |
||||
|
pf_anchor_zapret_v4_tpws $TPPORT |
||||
|
;; |
||||
|
custom) |
||||
|
pf_anchor_zapret_tables tbl zapret-user "$ZIPLIST_USER" zapret "$ZIPLIST" |
||||
|
existf zapret_custom_firewall_v4 && zapret_custom_firewall_v4 |
||||
|
;; |
||||
|
esac |
||||
|
} |
||||
|
} |
||||
|
pf_anchor_zapret_v6_tpws() |
||||
|
{ |
||||
|
# $1 - port |
||||
|
|
||||
|
local LL_LAN rule port=$(pf_anchor_port_target) |
||||
|
# LAN link local is only for router |
||||
|
for lan in $IFACE_LAN; do |
||||
|
LL_LAN=$(get_ipv6_linklocal $lan) |
||||
|
[ -n "$LL_LAN" ] && { |
||||
|
for t in $tbl; do |
||||
|
echo "rdr on $lan inet6 proto tcp from any to $t port $port -> $LL_LAN port $1" |
||||
|
done |
||||
|
} |
||||
|
done |
||||
|
echo "rdr on lo0 inet6 proto tcp from !::1 to any port $port -> fe80::1 port $1" |
||||
|
for t in $tbl; do |
||||
|
rule="route-to (lo0 fe80::1) inet6 proto tcp from !::1 to $t port $port user { >root }" |
||||
|
if [ -n "$IFACE_WAN" ] ; then |
||||
|
for wan in $IFACE_WAN; do |
||||
|
echo "pass out on $wan $rule" |
||||
|
done |
||||
|
else |
||||
|
echo "pass out $rule" |
||||
|
fi |
||||
|
done |
||||
|
} |
||||
|
pf_anchor_zapret_v6() |
||||
|
{ |
||||
|
local tbl port |
||||
|
|
||||
|
[ "$DISABLE_IPV6" = "1" ] || { |
||||
|
case $MODE in |
||||
|
tpws) |
||||
|
[ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ] && return |
||||
|
pf_anchor_zapret_tables tbl zapret6-user "$ZIPLIST_USER6" zapret6 "$ZIPLIST6" |
||||
|
pf_anchor_zapret_v6_tpws $TPPORT |
||||
|
;; |
||||
|
custom) |
||||
|
pf_anchor_zapret_tables tbl zapret6-user "$ZIPLIST_USER6" zapret6 "$ZIPLIST6" |
||||
|
existf zapret_custom_firewall_v6 && zapret_custom_firewall_v6 |
||||
|
;; |
||||
|
esac |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
pf_anchors_create() |
||||
|
{ |
||||
|
wait_lan_ll |
||||
|
pf_anchor_zapret >"$PF_ANCHOR_ZAPRET" |
||||
|
pf_anchor_zapret_v4 >"$PF_ANCHOR_ZAPRET_V4" |
||||
|
pf_anchor_zapret_v6 >"$PF_ANCHOR_ZAPRET_V6" |
||||
|
} |
||||
|
pf_anchors_del() |
||||
|
{ |
||||
|
rm -f "$PF_ANCHOR_ZAPRET" "$PF_ANCHOR_ZAPRET_V4" "$PF_ANCHOR_ZAPRET_V6" |
||||
|
} |
||||
|
pf_anchors_load() |
||||
|
{ |
||||
|
echo loading zapret anchor from "$PF_ANCHOR_ZAPRET" |
||||
|
pfctl -qa zapret -f "$PF_ANCHOR_ZAPRET" || { |
||||
|
echo error loading zapret anchor |
||||
|
return 1 |
||||
|
} |
||||
|
if [ "$DISABLE_IPV4" = "1" ]; then |
||||
|
echo clearing zapret-v4 anchor |
||||
|
pfctl -qa zapret-v4 -F all 2>/dev/null |
||||
|
else |
||||
|
echo loading zapret-v4 anchor from "$PF_ANCHOR_ZAPRET_V4" |
||||
|
pfctl -qa zapret-v4 -f "$PF_ANCHOR_ZAPRET_V4" || { |
||||
|
echo error loading zapret-v4 anchor |
||||
|
return 1 |
||||
|
} |
||||
|
fi |
||||
|
if [ "$DISABLE_IPV6" = "1" ]; then |
||||
|
echo clearing zapret-v6 anchor |
||||
|
pfctl -qa zapret-v6 -F all 2>/dev/null |
||||
|
else |
||||
|
echo loading zapret-v6 anchor from "$PF_ANCHOR_ZAPRET_V6" |
||||
|
pfctl -qa zapret-v6 -f "$PF_ANCHOR_ZAPRET_V6" || { |
||||
|
echo error loading zapret-v6 anchor |
||||
|
return 1 |
||||
|
} |
||||
|
fi |
||||
|
echo successfully loaded PF anchors |
||||
|
return 0 |
||||
|
} |
||||
|
pf_anchors_clear() |
||||
|
{ |
||||
|
echo clearing zapret anchors |
||||
|
pfctl -qa zapret-v4 -F all 2>/dev/null |
||||
|
pfctl -qa zapret-v6 -F all 2>/dev/null |
||||
|
pfctl -qa zapret -F all 2>/dev/null |
||||
|
} |
||||
|
pf_enable() |
||||
|
{ |
||||
|
echo enabling PF |
||||
|
pfctl -qe |
||||
|
} |
||||
|
pf_table_reload() |
||||
|
{ |
||||
|
echo reloading zapret tables |
||||
|
[ "$DISABLE_IPV4" = "1" ] || pfctl -qTl -a zapret-v4 -f "$PF_ANCHOR_ZAPRET_V4" |
||||
|
[ "$DISABLE_IPV6" = "1" ] || pfctl -qTl -a zapret-v6 -f "$PF_ANCHOR_ZAPRET_V6" |
||||
|
pfctl -qTl -a zapret -f "$PF_ANCHOR_ZAPRET" |
||||
|
} |
@ -0,0 +1,45 @@ |
|||||
|
get_nfqws_qnums() |
||||
|
{ |
||||
|
# $1 - var name for ipv4 http |
||||
|
# $2 - var name for ipv4 https |
||||
|
# $3 - var name for ipv6 http |
||||
|
# $4 - var name for ipv6 https |
||||
|
local _qn _qns _qn6 _qns6 |
||||
|
|
||||
|
[ "$DISABLE_IPV4" = "1" ] || { |
||||
|
_qn=$QNUM |
||||
|
_qns=$_qn |
||||
|
[ "$NFQWS_OPT_DESYNC_HTTP" = "$NFQWS_OPT_DESYNC_HTTPS" ] || _qns=$(($QNUM+1)) |
||||
|
} |
||||
|
[ "$DISABLE_IPV6" = "1" ] || { |
||||
|
_qn6=$(($QNUM+2)) |
||||
|
_qns6=$(($QNUM+3)) |
||||
|
[ "$DISABLE_IPV4" = "1" ] || { |
||||
|
if [ "$NFQWS_OPT_DESYNC_HTTP6" = "$NFQWS_OPT_DESYNC_HTTP" ]; then |
||||
|
_qn6=$_qn; |
||||
|
elif [ "$NFQWS_OPT_DESYNC_HTTP6" = "$NFQWS_OPT_DESYNC_HTTPS" ]; then |
||||
|
_qn6=$_qns; |
||||
|
fi |
||||
|
if [ "$NFQWS_OPT_DESYNC_HTTPS6" = "$NFQWS_OPT_DESYNC_HTTP" ]; then |
||||
|
_qns6=$_qn; |
||||
|
elif [ "$NFQWS_OPT_DESYNC_HTTPS6" = "$NFQWS_OPT_DESYNC_HTTPS" ]; then |
||||
|
_qns6=$_qns; |
||||
|
fi |
||||
|
} |
||||
|
[ "$NFQWS_OPT_DESYNC_HTTPS6" = "$NFQWS_OPT_DESYNC_HTTP6" ] && _qns6=$_qn6; |
||||
|
} |
||||
|
if [ "$MODE_HTTP" = 1 ]; then |
||||
|
eval $1=$_qn |
||||
|
eval $3=$_qn6 |
||||
|
else |
||||
|
eval $1= |
||||
|
eval $3= |
||||
|
fi |
||||
|
if [ "$MODE_HTTPS" = 1 ]; then |
||||
|
eval $2=$_qns |
||||
|
eval $4=$_qns6 |
||||
|
else |
||||
|
eval $2= |
||||
|
eval $4= |
||||
|
fi |
||||
|
} |
@ -0,0 +1,92 @@ |
|||||
|
nftables - это технология, пришедшая на замену iptables. |
||||
|
В ней собрали все, что относилось к различным iptables. А их немало. iptables, ip6tables, ebtables, arptables, ipset. |
||||
|
Весь код из разрозненных, но похожих компонент, собрали в одно целое с единым синтаксисом. |
||||
|
Добавили различные конструкции языка, позволяющие писать правила более лаконично, не повторяя одни и те же команды с небольшими различиями. |
||||
|
На nftables можно сделать почти все, что можно было сделать на iptables. Есть то, что можно сделать на nftables, но нельзя на iptables. |
||||
|
Удобно, красиво. |
||||
|
|
||||
|
К сожалению, не обошлось и без боли. 10 лет развития nftables казалось бы должны были вылизать все. Но не тут то было. |
||||
|
|
||||
|
Главная боль N1. Очень серьезная, актуальная для openwrt, и решения не видно. |
||||
|
|
||||
|
ipset-ы позволяли загонять пересекающиеся интервалы ip адресов или подсетей. |
||||
|
nftables sets это не позволяют. Любое пересечение вызывает ошибку. |
||||
|
Есть auto-merge, но это работает только в user mode в процессе nft, при условии, что весь блок адресов загоняется одной командой |
||||
|
и нет пересечений с уже имеющимся контентом в set. |
||||
|
Это не было бы критической проблемой, поскольку скрипты zapret и так загоняют ipset целиком. |
||||
|
Проблема в катастрофическом расходе памяти при операции загона больших интервальных листов, то есть с подсетями и диапазонами. |
||||
|
Чтобы загнать 100000 ipv4 записей, едва хватает 300 Mb памяти устройства. |
||||
|
При успехе операции в ядре список столько не занимает, но суть дела это не меняет. |
||||
|
Для традиционных linux систем это не проблема, но почти все роутеры загнутся. |
||||
|
Приемлемого решения не просматривается. |
||||
|
Сделать записи непересекающимися в листах - задача непростая. Потребуется переписать алгоритм auto-merge из nft, |
||||
|
но с пониженным расходом памяти. |
||||
|
Загонять записи по одному отдельными вызовами nft, игнорируя ошибки, займет вечность. |
||||
|
Загонять блоком отдельных команд, игнорируя ошибки, - nft такого не умеет. Похоже, при любой ошибке происходит откат всего скрипта. |
||||
|
К тому же при таком подходе будут неточности в итоговом результате. |
||||
|
Swap позволяет немного сгладить проблему, но лишь незначительно. |
||||
|
Скажем, если вдруг list загоняется без ошибок с 300 Mb памяти и с падением на 256 Mb, то swap спасает. |
||||
|
Если памяти становится 200 Mb, то swap уже не спасет. Все равно вызывается OOM killer, заодно убивая и другие процессы, кроме nft, |
||||
|
а это уже совсем плохо. Может быть убито что-то важное. |
||||
|
|
||||
|
Боль N2, но не такая смертельная. |
||||
|
|
||||
|
10 лет вылизывания кода, но при загоне больших листов в set-ы то и дело при вызовах nft list происходят seg faults. |
||||
|
Например, падать может nft -t list ruleset, но nft -t list table inet zapret может не падать. |
||||
|
Вроде это не влияет на функционал, но все равно создается неудобство. |
||||
|
|
||||
|
Боль N3, не смертельная, но тоже не айс. |
||||
|
|
||||
|
Какие-то нерациональные алгоритмы разбора таблиц в nft. |
||||
|
Например, есть 1 большой set на 100000 элементов и 1 маленький на 2 элемента. |
||||
|
Чтобы просто пролистать мелкий set или добавить туда еще что-то nft будет мусолить несколько секунд. |
||||
|
Что он делает за это время ? Тащит из ядра огромный блоб, в котором все в куче, и разбирает его, чтобы выделить искомую мелочь ? |
||||
|
В какой-то мере удается это сгладить, обьединяя несколько команд в единый скрипт. |
||||
|
|
||||
|
|
||||
|
Плюс N1, главный |
||||
|
|
||||
|
iptables хороши, когда ими пользуется кто-то один. Иначе это проходной двор. |
||||
|
Когда есть система управления фаерволом, то приходится как-то к ней прикручиваться, чтобы не нарушить ее работу |
||||
|
и управлять правилами синхронно. Нужно уметь внести и удалить отдельные правила когда это нужно, не трогая все остальное. |
||||
|
Некоторые системы управления фаерволом вообще не предполагают, чтобы кто-то еще лез в iptables, и это очень сильно портит жизнь. |
||||
|
У iptables есть предопределенный набор хуков netfilter с фиксированным приоритетом. |
||||
|
В nftables хуков можно создать неограниченное количество с выбранным приоритетом, управляя ими независимо в отдельных таблицах. |
||||
|
Система управления фаерволом может работать в одной таблице (fw4 в случае openwrt) и не трогать все остальное. |
||||
|
zapret может работать в другой таблице и не трогать систему управления фаерволом. Они друг другу не мешают. |
||||
|
Это снимает множество боли. |
||||
|
|
||||
|
Плюс N2 |
||||
|
|
||||
|
Возможность выбора приоритета хука позволяет легко решить проблему хаотической и принудительной дефрагментацией L3 ipv6, |
||||
|
без танцев с загрузкой модулей ядра со специальными параметрами или перекомпиляцией nftables-nft. |
||||
|
|
||||
|
Плюс N3 |
||||
|
|
||||
|
Наличие множеств (anonymous/named sets) позволяет не писать кучу однообразных правил там, где в iptables их пришлось бы написать. |
||||
|
|
||||
|
Плюс N4 |
||||
|
|
||||
|
Если у вас есть nftables, то там наверняка есть уже все или почти все. |
||||
|
Нет кучи разных модулей ядра и .so плагинов для iptables user-mode процесса. |
||||
|
Отдельные модули ядра есть, но их меньше, чем в iptables, и openwrt их делит на меньшее число пакетов, большинство из которых |
||||
|
и так ставятся по умолчанию. user-mode процесс nft и вовсе неделим. EXE-шник + lib. |
||||
|
|
||||
|
Плюс N5 |
||||
|
|
||||
|
Пишут, что nftables работают быстрее. |
||||
|
|
||||
|
|
||||
|
Выводы |
||||
|
|
||||
|
Честно говоря, лучше бы openwrt оставался на iptables. |
||||
|
Пусть они и старые, c недостатками, но как говорится ложка дегтя портит цистерну меда. |
||||
|
nftables - именно тот случай. Все хорошо, но все плохо из-за досадной особенности. |
||||
|
Без больших листов все почти прекрасно. Но большие ip листы убивают все. Не для домашних это роутеров. |
||||
|
А ipset-ы к nftables не прикрутить. |
||||
|
Делать нечего. Openwrt отошел от iptables. С этим придется как-то жить. |
||||
|
Поэтому пришлось сделать для openwrt поддержку и iptables, и nftables (только с версии openwrt 21.xx, в более старых будут проблемы). |
||||
|
iptables можно задействовать на любой openwrt версии. |
||||
|
Если используется fw3, применяется старый механизм интеграции в fw3. |
||||
|
Если он не используется, то правилами iptables управляем как в традиционных linux системах - то есть с возможностью |
||||
|
запуска и остановки, а скрипт запуска вносит в том числе и правила iptables. |
@ -0,0 +1,69 @@ |
|||||
|
#!/sbin/openrc-run |
||||
|
|
||||
|
# zapret openrc to sysv adapter |
||||
|
# on some systems (alpine) for unknown reason non-openrc-run scripts are not started from /etc/init.d |
||||
|
|
||||
|
EXEDIR=$(dirname "$RC_SERVICE") |
||||
|
EXEDIR="$(cd "$EXEDIR"; pwd)" |
||||
|
ZAPRET_BASE="$EXEDIR/../.." |
||||
|
ZAPRET_INIT="$ZAPRET_BASE/init.d/sysv/zapret" |
||||
|
|
||||
|
extra_commands="start_fw stop_fw restart_fw start_daemons stop_daemons restart_daemons reload_ifsets list_ifsets list_table" |
||||
|
description="extra commands :" |
||||
|
description_stop_fw="Stop zapret firewall" |
||||
|
description_start_fw="Start zapret firewall" |
||||
|
description_restart_fw="Restart zapret firewall" |
||||
|
description_reload_ifsets="Reload interface lists (nftables only)" |
||||
|
description_list_ifsets="Display interface lists (nftables only)" |
||||
|
description_list_table="Display zapret nftable (nftables only)" |
||||
|
description_stop_daemons="Stop zapret daemons only" |
||||
|
description_start_daemons="Start zapret daemons only" |
||||
|
description_restart_daemons="Restart zapret firewall only" |
||||
|
|
||||
|
depend() { |
||||
|
rc-service -e networking && need networking |
||||
|
} |
||||
|
start() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" start |
||||
|
} |
||||
|
stop() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" stop |
||||
|
} |
||||
|
start_fw() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" start_fw |
||||
|
} |
||||
|
stop_fw() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" stop_fw |
||||
|
} |
||||
|
restart_fw() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" restart_fw |
||||
|
} |
||||
|
start_daemons() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" start_daemons |
||||
|
} |
||||
|
stop_daemons() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" stop_daemons |
||||
|
} |
||||
|
restart_daemons() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" restart_daemons |
||||
|
} |
||||
|
reload_ifsets() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" reload_ifsets |
||||
|
} |
||||
|
list_ifsets() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" list_ifsets |
||||
|
} |
||||
|
list_table() |
||||
|
{ |
||||
|
"$ZAPRET_INIT" list_table |
||||
|
} |
@ -0,0 +1,20 @@ |
|||||
|
# this script contain your special code to launch daemons and configure firewall |
||||
|
# use helpers from "functions" file and "zapret" init script |
||||
|
# in case of upgrade keep this file only, do not modify others |
||||
|
|
||||
|
zapret_custom_daemons() |
||||
|
{ |
||||
|
# PLACEHOLDER |
||||
|
echo !!! NEED ATTENTION !!! |
||||
|
echo Start daemon\(s\) |
||||
|
echo Study how other sections work |
||||
|
|
||||
|
run_daemon 1 /bin/sleep 20 |
||||
|
} |
||||
|
zapret_custom_firewall() |
||||
|
{ |
||||
|
# PLACEHOLDER |
||||
|
echo !!! NEED ATTENTION !!! |
||||
|
echo Configure iptables for required actions |
||||
|
echo Study how other sections work |
||||
|
} |
@ -2,14 +2,22 @@ |
|||||
|
|
||||
[ -n "$ZAPRET_BASE" ] || ZAPRET_BASE=/opt/zapret |
[ -n "$ZAPRET_BASE" ] || ZAPRET_BASE=/opt/zapret |
||||
. "$ZAPRET_BASE/config" |
. "$ZAPRET_BASE/config" |
||||
|
. "$ZAPRET_BASE/common/base.sh" |
||||
|
. "$ZAPRET_BASE/common/fwtype.sh" |
||||
|
. "$ZAPRET_BASE/common/queue.sh" |
||||
|
. "$ZAPRET_BASE/common/linux_iphelper.sh" |
||||
|
. "$ZAPRET_BASE/common/ipt.sh" |
||||
|
. "$ZAPRET_BASE/common/nft.sh" |
||||
|
. "$ZAPRET_BASE/common/linux_fw.sh" |
||||
|
|
||||
[ -n "$QNUM" ] || QNUM=200 |
[ -n "$QNUM" ] || QNUM=200 |
||||
[ -n "$TPPORT" ] || TPPORT=988 |
[ -n "$TPPORT" ] || TPPORT=988 |
||||
[ -n "$WS_USER" ] || WS_USER=daemon |
[ -n "$WS_USER" ] || WS_USER=daemon |
||||
TPWS_LOCALHOST4=127.0.0.127 |
|
||||
[ -n "$DESYNC_MARK" ] || DESYNC_MARK=0x40000000 |
[ -n "$DESYNC_MARK" ] || DESYNC_MARK=0x40000000 |
||||
[ -n "$OPENWRT_LAN" ] || OPENWRT_LAN=lan |
[ -n "$OPENWRT_LAN" ] || OPENWRT_LAN=lan |
||||
|
|
||||
|
TPWS_LOCALHOST4=127.0.0.127 |
||||
|
|
||||
# max wait time for the link local ipv6 on the LAN interface |
# max wait time for the link local ipv6 on the LAN interface |
||||
LINKLOCAL_WAIT_SEC=5 |
LINKLOCAL_WAIT_SEC=5 |
||||
|
|
||||
@ -26,14 +34,6 @@ NFQWS_OPT_DESYNC_HTTPS="${NFQWS_OPT_DESYNC_HTTPS:-$NFQWS_OPT_DESYNC}" |
|||||
NFQWS_OPT_DESYNC_HTTP6="${NFQWS_OPT_DESYNC_HTTP6:-$NFQWS_OPT_DESYNC_HTTP}" |
NFQWS_OPT_DESYNC_HTTP6="${NFQWS_OPT_DESYNC_HTTP6:-$NFQWS_OPT_DESYNC_HTTP}" |
||||
NFQWS_OPT_DESYNC_HTTPS6="${NFQWS_OPT_DESYNC_HTTPS6:-$NFQWS_OPT_DESYNC_HTTPS}" |
NFQWS_OPT_DESYNC_HTTPS6="${NFQWS_OPT_DESYNC_HTTPS6:-$NFQWS_OPT_DESYNC_HTTPS}" |
||||
|
|
||||
exists() |
|
||||
{ |
|
||||
which "$1" >/dev/null 2>/dev/null |
|
||||
} |
|
||||
existf() |
|
||||
{ |
|
||||
type "$1" >/dev/null 2>/dev/null |
|
||||
} |
|
||||
|
|
||||
|
|
||||
# can be multiple ipv6 outgoing interfaces |
# can be multiple ipv6 outgoing interfaces |
||||
@ -46,341 +46,268 @@ existf() |
|||||
|
|
||||
network_find_wan_all() |
network_find_wan_all() |
||||
{ |
{ |
||||
__network_ifstatus "$1" "" "[@.route[@.target='0.0.0.0' && [email protected]]].interface" "" 10 2>/dev/null && return |
__network_ifstatus "$1" "" "[@.route[@.target='0.0.0.0' && [email protected]]].interface" "" 10 2>/dev/null && return |
||||
network_find_wan $1 |
network_find_wan $1 |
||||
} |
} |
||||
network_find_wan6_all() |
network_find_wan6_all() |
||||
{ |
{ |
||||
__network_ifstatus "$1" "" "[@.route[@.target='::' && [email protected]]].interface" "" 10 2>/dev/null && return |
__network_ifstatus "$1" "" "[@.route[@.target='::' && [email protected]]].interface" "" 10 2>/dev/null && return |
||||
network_find_wan6 $1 |
network_find_wan6 $1 |
||||
} |
} |
||||
|
|
||||
ipt() |
route_localnet() |
||||
{ |
{ |
||||
iptables -C "$@" >/dev/null 2>/dev/null || iptables -I "$@" |
for lan in $OPENWRT_LAN; do |
||||
|
network_get_device DEVICE $lan |
||||
|
[ -n "$DEVICE" ] || continue |
||||
|
sysctl -qw net.ipv4.conf.$DEVICE.route_localnet=1 |
||||
|
done |
||||
} |
} |
||||
ipt_del() |
|
||||
|
dnat6_target() |
||||
{ |
{ |
||||
iptables -C "$@" >/dev/null 2>/dev/null && iptables -D "$@" |
# $1 - lan network name |
||||
|
# $2 - var to store target ip6 |
||||
|
# get target ip address for DNAT. prefer link locals |
||||
|
# tpws should be as inaccessible from outside as possible |
||||
|
# link local address can appear not immediately after ifup |
||||
|
# DNAT6_TARGET=- means attempt was made but address was not found (to avoid multiple re-attempts) |
||||
|
|
||||
|
local DNAT6_TARGET DVAR=DNAT6_TARGET_$1 |
||||
|
DVAR=$(echo $DVAR | sed 's/[^a-zA-Z0-9_]/_/g') |
||||
|
eval DNAT6_TARGET="\$$DVAR" |
||||
|
[ -n "$2" ] && eval $2='' |
||||
|
|
||||
|
[ -n "$DNAT6_TARGET" ] || { |
||||
|
# no reason to query if its down |
||||
|
network_is_up $1 || return |
||||
|
|
||||
|
local DEVICE |
||||
|
network_get_device DEVICE $1 |
||||
|
|
||||
|
local ct=0 |
||||
|
while |
||||
|
DNAT6_TARGET=$(get_ipv6_linklocal $DEVICE) |
||||
|
[ -n "$DNAT6_TARGET" ] && break |
||||
|
[ "$ct" -ge "$LINKLOCAL_WAIT_SEC" ] && break |
||||
|
echo $DEVICE: waiting for the link local for another $(($LINKLOCAL_WAIT_SEC - $ct)) seconds ... |
||||
|
ct=$(($ct+1)) |
||||
|
sleep 1 |
||||
|
do :; done |
||||
|
|
||||
|
[ -n "$DNAT6_TARGET" ] || { |
||||
|
echo $DEVICE: no link local. getting global |
||||
|
DNAT6_TARGET=$(get_ipv6_global $DEVICE) |
||||
|
[ -n "$DNAT6_TARGET" ] || { |
||||
|
echo $DEVICE: could not get any address |
||||
|
DNAT6_TARGET=- |
||||
|
} |
||||
|
} |
||||
|
eval $DVAR="$DNAT6_TARGET" |
||||
|
} |
||||
|
[ -n "$2" ] && eval $2="$DNAT6_TARGET" |
||||
} |
} |
||||
ipt6() |
|
||||
|
|
||||
|
set_route_localnet() |
||||
{ |
{ |
||||
ip6tables -C "$@" >/dev/null 2>/dev/null || ip6tables -I "$@" |
# $1 - 1 = enable, 0 = disable |
||||
|
|
||||
|
[ "$DISABLE_IPV4" = "1" ] || { |
||||
|
local lan DEVICE |
||||
|
for lan in $OPENWRT_LAN; do |
||||
|
network_get_device DEVICE $lan |
||||
|
[ -n "$DEVICE" ] || continue |
||||
|
sysctl -q -w net.ipv4.conf.$DEVICE.route_localnet=$1 |
||||
|
done |
||||
|
} |
||||
} |
} |
||||
ipt6_del() |
prepare_route_localnet() |
||||
{ |
{ |
||||
ip6tables -C "$@" >/dev/null 2>/dev/null && ip6tables -D "$@" |
set_route_localnet 1 |
||||
} |
} |
||||
|
unprepare_route_localnet() |
||||
# there's no route_localnet for ipv6 |
|
||||
# the best we can is to route to link local of the incoming interface |
|
||||
# OUTPUT - can DNAT to ::1 |
|
||||
# PREROUTING - can't DNAT to ::1. can DNAT to link local of -i interface or to any global addr |
|
||||
# not a good idea to expose tpws to the world (bind to ::) |
|
||||
|
|
||||
get_ipv6_linklocal() |
|
||||
{ |
{ |
||||
# $1 - interface name. if empty - any interface |
set_route_localnet 0 |
||||
if exists ip ; then |
|
||||
local dev |
|
||||
[ -n "$1" ] && dev="dev $1" |
|
||||
ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope link.*$/\1/;t;d' | head -n 1 |
|
||||
else |
|
||||
ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Link.*$/\1/;t;d' | head -n 1 |
|
||||
fi |
|
||||
} |
} |
||||
get_ipv6_global() |
prepare_tpws_fw4() |
||||
{ |
{ |
||||
# $1 - interface name. if empty - any interface |
# otherwise linux kernel will treat 127.0.0.0/8 as "martian" ip and refuse routing to it |
||||
if exists ip ; then |
# NOTE : kernels <3.6 do not have this feature. consider upgrading or change DNAT to REDIRECT and do not bind to 127.0.0.0/8 |
||||
local dev |
|
||||
[ -n "$1" ] && dev="dev $1" |
[ "$DISABLE_IPV4" = "1" ] || { |
||||
ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope global.*$/\1/;t;d' | head -n 1 |
iptables -N input_rule_zapret 2>/dev/null |
||||
else |
ipt input_rule_zapret -d $TPWS_LOCALHOST4 -j RETURN |
||||
ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Global.*$/\1/;t;d' | head -n 1 |
ipta input_rule_zapret -d 127.0.0.0/8 -j DROP |
||||
fi |
ipt INPUT ! -i lo -j input_rule_zapret |
||||
|
|
||||
|
prepare_route_localnet |
||||
|
} |
||||
} |
} |
||||
|
unprepare_tpws_fw4() |
||||
|
{ |
||||
|
[ "$DISABLE_IPV4" = "1" ] || { |
||||
|
unprepare_route_localnet |
||||
|
|
||||
dnat6_target() |
ipt_del INPUT ! -i lo -j input_rule_zapret |
||||
|
iptables -F input_rule_zapret 2>/dev/null |
||||
|
iptables -X input_rule_zapret 2>/dev/null |
||||
|
} |
||||
|
} |
||||
|
unprepare_tpws_fw() |
||||
{ |
{ |
||||
# $1 - lan network name |
unprepare_tpws_fw4 |
||||
# $2 - var to store target ip6 |
|
||||
# get target ip address for DNAT. prefer link locals |
|
||||
# tpws should be as inaccessible from outside as possible |
|
||||
# link local address can appear not immediately after ifup |
|
||||
# DNAT6_TARGET=- means attempt was made but address was not found (to avoid multiple re-attempts) |
|
||||
|
|
||||
local DNAT6_TARGET DVAR=DNAT6_TARGET_$1 |
|
||||
DVAR=$(echo $DVAR | sed 's/[^a-zA-Z0-9_]/_/g') |
|
||||
eval DNAT6_TARGET="\$$DVAR" |
|
||||
[ -n "$2" ] && eval $2='' |
|
||||
|
|
||||
[ -n "$DNAT6_TARGET" ] || { |
|
||||
# no reason to query if its down |
|
||||
network_is_up $1 || return |
|
||||
|
|
||||
local DEVICE |
|
||||
network_get_device DEVICE $1 |
|
||||
|
|
||||
local ct=0 |
|
||||
while |
|
||||
DNAT6_TARGET=$(get_ipv6_linklocal $DEVICE) |
|
||||
[ -n "$DNAT6_TARGET" ] && break |
|
||||
[ "$ct" -ge "$LINKLOCAL_WAIT_SEC" ] && break |
|
||||
echo $DEVICE: waiting for the link local for another $(($LINKLOCAL_WAIT_SEC - $ct)) seconds ... |
|
||||
ct=$(($ct+1)) |
|
||||
sleep 1 |
|
||||
do :; done |
|
||||
|
|
||||
[ -n "$DNAT6_TARGET" ] || { |
|
||||
echo $DEVICE: no link local. getting global |
|
||||
DNAT6_TARGET=$(get_ipv6_global $DEVICE) |
|
||||
[ -n "$DNAT6_TARGET" ] || { |
|
||||
echo $DEVICE: could not get any address |
|
||||
DNAT6_TARGET=- |
|
||||
} |
|
||||
} |
|
||||
eval $DVAR="$DNAT6_TARGET" |
|
||||
} |
|
||||
[ -n "$2" ] && eval $2="$DNAT6_TARGET" |
|
||||
} |
} |
||||
|
|
||||
|
|
||||
fw_nfqws_pre4() |
fw_nfqws_pre4() |
||||
{ |
{ |
||||
# $1 - filter ipv4 |
# $1 - 1 - add, 0 - del |
||||
# $2 - queue number |
# $2 - filter ipv4 |
||||
|
# $3 - queue number |
||||
|
|
||||
local DEVICE wan_iface |
local DEVICE wan_iface |
||||
|
|
||||
[ "$DISABLE_IPV4" = "1" ] || { |
[ "$DISABLE_IPV4" = "1" ] || { |
||||
network_find_wan_all wan_iface |
network_find_wan_all wan_iface |
||||
for ext_iface in $wan_iface; do |
for ext_iface in $wan_iface; do |
||||
network_get_device DEVICE $ext_iface |
network_get_device DEVICE $ext_iface |
||||
ipt PREROUTING -t mangle -i $DEVICE -p tcp $1 $IPSET_EXCLUDE src -j NFQUEUE --queue-num $2 --queue-bypass |
ipt_add_del $1 PREROUTING -t mangle -i $DEVICE -p tcp $2 $IPSET_EXCLUDE src -j NFQUEUE --queue-num $3 --queue-bypass |
||||
done |
done |
||||
} |
} |
||||
} |
} |
||||
fw_nfqws_pre6() |
fw_nfqws_pre6() |
||||
{ |
{ |
||||
# $1 - filter ipv6 |
# $1 - 1 - add, 0 - del |
||||
# $2 - queue number |
# $2 - filter ipv6 |
||||
|
# $3 - queue number |
||||
|
|
||||
local DEVICE wan_iface |
local DEVICE wan_iface |
||||
|
|
||||
[ "$DISABLE_IPV6" = "1" ] || { |
[ "$DISABLE_IPV6" = "1" ] || { |
||||
network_find_wan6_all wan_iface |
network_find_wan6_all wan_iface |
||||
for ext_iface in $wan_iface; do |
for ext_iface in $wan_iface; do |
||||
network_get_device DEVICE $ext_iface |
network_get_device DEVICE $ext_iface |
||||
ipt6 PREROUTING -t mangle -i $DEVICE -p tcp $1 $IPSET_EXCLUDE6 src -j NFQUEUE --queue-num $2 --queue-bypass |
ipt6_add_del $1 PREROUTING -t mangle -i $DEVICE -p tcp $2 $IPSET_EXCLUDE6 src -j NFQUEUE --queue-num $3 --queue-bypass |
||||
done |
done |
||||
} |
} |
||||
} |
} |
||||
fw_nfqws_pre() |
fw_nfqws_pre() |
||||
{ |
{ |
||||
# $1 - filter ipv4 |
# $1 - 1 - add, 0 - del |
||||
# $2 - filter ipv6 |
# $2 - filter ipv4 |
||||
# $3 - queue number |
# $3 - filter ipv6 |
||||
|
# $4 - queue number |
||||
|
|
||||
fw_nfqws_pre4 "$1" $3 |
fw_nfqws_pre4 $1 "$2" $4 |
||||
fw_nfqws_pre6 "$2" $3 |
fw_nfqws_pre6 $1 "$3" $4 |
||||
} |
} |
||||
fw_nfqws_post4() |
fw_nfqws_post4() |
||||
{ |
{ |
||||
# $1 - filter ipv4 |
# $1 - 1 - add, 0 - del |
||||
# $2 - queue number |
# $2 - filter ipv4 |
||||
|
# $3 - queue number |
||||
|
|
||||
local DEVICE wan_iface |
local DEVICE wan_iface |
||||
|
|
||||
[ "$DISABLE_IPV4" = "1" ] || { |
[ "$DISABLE_IPV4" = "1" ] || { |
||||
network_find_wan_all wan_iface |
network_find_wan_all wan_iface |
||||
for ext_iface in $wan_iface; do |
for ext_iface in $wan_iface; do |
||||
network_get_device DEVICE $ext_iface |
network_get_device DEVICE $ext_iface |
||||
ipt POSTROUTING -t mangle -o $DEVICE -p tcp $1 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $2 --queue-bypass |
ipt_add_del $1 POSTROUTING -t mangle -o $DEVICE -p tcp $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass |
||||
done |
done |
||||
} |
} |
||||
} |
} |
||||
fw_nfqws_post6() |
fw_nfqws_post6() |
||||
{ |
{ |
||||
# $1 - filter ipv6 |
# $1 - 1 - add, 0 - del |
||||
# $2 - queue number |
# $2 - filter ipv6 |
||||
|
# $3 - queue number |
||||
|
|
||||
local DEVICE wan_iface |
local DEVICE wan_iface |
||||
|
|
||||
[ "$DISABLE_IPV6" = "1" ] || { |
[ "$DISABLE_IPV6" = "1" ] || { |
||||
network_find_wan6_all wan_iface |
network_find_wan6_all wan_iface |
||||
for ext_iface in $wan_iface; do |
for ext_iface in $wan_iface; do |
||||
network_get_device DEVICE $ext_iface |
network_get_device DEVICE $ext_iface |
||||
ipt6 POSTROUTING -t mangle -o $DEVICE -p tcp $1 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $2 --queue-bypass |
ipt6_add_del $1 POSTROUTING -t mangle -o $DEVICE -p tcp $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass |
||||
done |
done |
||||
} |
} |
||||
} |
} |
||||
fw_nfqws_post() |
fw_nfqws_post() |
||||
{ |
{ |
||||
# $1 - filter ipv4 |
# $1 - 1 - add, 0 - del |
||||
# $2 - filter ipv6 |
# $2 - filter ipv4 |
||||
# $3 - queue number |
# $3 - filter ipv6 |
||||
|
# $4 - queue number |
||||
|
|
||||
fw_nfqws_post4 "$1" $3 |
fw_nfqws_post4 $1 "$2" $4 |
||||
fw_nfqws_post6 "$2" $3 |
fw_nfqws_post6 $1 "$3" $4 |
||||
} |
} |
||||
|
|
||||
|
|
||||
IPT_OWNER="-m owner ! --uid-owner $WS_USER" |
IPT_OWNER="-m owner ! --uid-owner $WS_USER" |
||||
fw_tpws4() |
fw_tpws4() |
||||
{ |
{ |
||||
# $1 - filter ipv6 |
# $1 - 1 - add, 0 - del |
||||
# $2 - tpws port |
# $2 - filter ipv4 |
||||
|
# $3 - tpws port |
||||
|
|
||||
local DEVICE wan_iface |
local lan DEVICE ext_iface wan_iface |
||||
|
|
||||
[ "$DISABLE_IPV4" = "1" ] || { |
[ "$DISABLE_IPV4" = "1" ] || { |
||||
network_find_wan_all wan_iface |
network_find_wan_all wan_iface |
||||
for ext_iface in $wan_iface; do |
for ext_iface in $wan_iface; do |
||||
network_get_device DEVICE $ext_iface |
network_get_device DEVICE $ext_iface |
||||
ipt OUTPUT -t nat -o $DEVICE $IPT_OWNER -p tcp $1 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$2 |
ipt_add_del $1 OUTPUT -t nat -o $DEVICE $IPT_OWNER -p tcp $2 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3 |
||||
done |
done |
||||
|
[ "$1" = 1 ] && prepare_tpws_fw4 |
||||
# allow localnet route only to special tpws IP |
for lan in $OPENWRT_LAN; do |
||||
iptables -N input_rule_zapret 2>/dev/null |
network_get_device DEVICE $lan |
||||
ipt input_rule_zapret -d 127.0.0.0/8 -j DROP |
[ -n "$DEVICE" ] || continue |
||||
ipt input_rule_zapret -d $TPWS_LOCALHOST4 -j RETURN |
ipt_add_del $1 PREROUTING -t nat -i $DEVICE -p tcp $2 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3 |
||||
|
done |
||||
for lan in $OPENWRT_LAN; do |
} |
||||
network_get_device DEVICE $lan |
|
||||
[ -n "$DEVICE" ] || continue |
|
||||
ipt prerouting_rule -t nat -i $DEVICE -p tcp $1 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$2 |
|
||||
ipt input_rule -i $DEVICE -j input_rule_zapret |
|
||||
sysctl -qw net.ipv4.conf.$DEVICE.route_localnet=1 |
|
||||
done |
|
||||
} |
|
||||
} |
} |
||||
fw_tpws6() |
fw_tpws6() |
||||
{ |
{ |
||||
# $1 - filter ipv6 |
# $1 - 1 - add, 0 - del |
||||
# $2 - tpws port |
# $2 - filter ipv6 |
||||
|
# $3 - tpws port |
||||
|
|
||||
local DEVICE wan_iface DNAT6 |
local lan DEVICE ext_iface wan_iface DNAT6 |
||||
|
|
||||
[ "$DISABLE_IPV6" = "1" ] || { |
[ "$DISABLE_IPV6" = "1" ] || { |
||||
network_find_wan6_all wan_iface |
network_find_wan6_all wan_iface |
||||
for ext_iface in $wan_iface; do |
for ext_iface in $wan_iface; do |
||||
network_get_device DEVICE $ext_iface |
network_get_device DEVICE $ext_iface |
||||
ipt6 OUTPUT -t nat -o $DEVICE $IPT_OWNER -p tcp $1 $IPSET_EXCLUDE6 dst -j DNAT --to [::1]:$2 |
ipt6_add_del $1 OUTPUT -t nat -o $DEVICE $IPT_OWNER -p tcp $2 $IPSET_EXCLUDE6 dst -j DNAT --to [::1]:$3 |
||||
done |
done |
||||
for lan in $OPENWRT_LAN; do |
for lan in $OPENWRT_LAN; do |
||||
network_get_device DEVICE $lan |
network_get_device DEVICE $lan |
||||
[ -n "$DEVICE" ] || continue |
[ -n "$DEVICE" ] || continue |
||||
dnat6_target $lan DNAT6 |
dnat6_target $lan DNAT6 |
||||
[ "$DNAT6" != '-' ] && ipt6 PREROUTING -t nat -i $DEVICE -p tcp $1 $IPSET_EXCLUDE6 dst -j DNAT --to [$DNAT6]:$2 |
[ "$DNAT6" != '-' ] && ipt6_add_del $1 PREROUTING -t nat -i $DEVICE -p tcp $2 $IPSET_EXCLUDE6 dst -j DNAT --to [$DNAT6]:$3 |
||||
done |
done |
||||
} |
} |
||||
} |
} |
||||
fw_tpws() |
fw_tpws() |
||||
{ |
{ |
||||
# $1 - filter ipv4 |
# $1 - 1 - add, 0 - del |
||||
# $2 - filter ipv6 |
# $2 - filter ipv4 |
||||
# $3 - tpws port |
# $3 - filter ipv6 |
||||
|
# $4 - tpws port |
||||
|
|
||||
fw_tpws4 "$1" $3 |
fw_tpws4 $1 "$2" $4 |
||||
fw_tpws6 "$2" $3 |
fw_tpws6 $1 "$3" $4 |
||||
} |
} |
||||
|
|
||||
filter_apply_port_target() |
|
||||
{ |
|
||||
# $1 - var name of iptables filter |
|
||||
local f |
|
||||
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then |
|
||||
f="-m multiport --dports 80,443" |
|
||||
elif [ "$MODE_HTTPS" = "1" ]; then |
|
||||
f="--dport 443" |
|
||||
elif [ "$MODE_HTTP" = "1" ]; then |
|
||||
f="--dport 80" |
|
||||
else |
|
||||
echo WARNING !!! HTTP and HTTPS are both disabled |
|
||||
fi |
|
||||
eval $1="\"\$$1 $f\"" |
|
||||
} |
|
||||
filter_apply_ipset_target4() |
|
||||
{ |
|
||||
# $1 - var name of ipv4 iptables filter |
|
||||
if [ "$MODE_FILTER" = "ipset" ]; then |
|
||||
eval $1="\"\$$1 -m set --match-set zapret dst\"" |
|
||||
fi |
|
||||
} |
|
||||
filter_apply_ipset_target6() |
|
||||
{ |
|
||||
# $1 - var name of ipv4 iptables filter |
|
||||
if [ "$MODE_FILTER" = "ipset" ]; then |
|
||||
eval $1="\"\$$1 -m set --match-set zapret6 dst\"" |
|
||||
fi |
|
||||
} |
|
||||
filter_apply_ipset_target() |
|
||||
{ |
|
||||
# $1 - var name of ipv4 iptables filter |
|
||||
# $2 - var name of ipv6 iptables filter |
|
||||
filter_apply_ipset_target4 $1 |
|
||||
filter_apply_ipset_target6 $2 |
|
||||
} |
|
||||
|
|
||||
get_nfqws_qnums() |
|
||||
{ |
|
||||
# $1 - var name for ipv4 http |
|
||||
# $2 - var name for ipv4 https |
|
||||
# $3 - var name for ipv6 http |
|
||||
# $4 - var name for ipv6 https |
|
||||
local _qn _qns _qn6 _qns6 |
|
||||
|
|
||||
[ "$DISABLE_IPV4" = "1" ] || { |
|
||||
_qn=$QNUM |
|
||||
_qns=$_qn |
|
||||
[ "$NFQWS_OPT_DESYNC_HTTP" = "$NFQWS_OPT_DESYNC_HTTPS" ] || _qns=$(($QNUM+1)) |
|
||||
} |
|
||||
[ "$DISABLE_IPV6" = "1" ] || { |
|
||||
_qn6=$(($QNUM+2)) |
|
||||
_qns6=$(($QNUM+3)) |
|
||||
[ "$DISABLE_IPV4" = "1" ] || { |
|
||||
if [ "$NFQWS_OPT_DESYNC_HTTP6" = "$NFQWS_OPT_DESYNC_HTTP" ]; then |
|
||||
_qn6=$_qn; |
|
||||
elif [ "$NFQWS_OPT_DESYNC_HTTP6" = "$NFQWS_OPT_DESYNC_HTTPS" ]; then |
|
||||
_qn6=$_qns; |
|
||||
fi |
|
||||
if [ "$NFQWS_OPT_DESYNC_HTTPS6" = "$NFQWS_OPT_DESYNC_HTTP" ]; then |
|
||||
_qns6=$_qn; |
|
||||
elif [ "$NFQWS_OPT_DESYNC_HTTPS6" = "$NFQWS_OPT_DESYNC_HTTPS" ]; then |
|
||||
_qns6=$_qns; |
|
||||
fi |
|
||||
} |
|
||||
[ "$NFQWS_OPT_DESYNC_HTTPS6" = "$NFQWS_OPT_DESYNC_HTTP6" ] && _qns6=$_qn6; |
|
||||
} |
|
||||
if [ "$MODE_HTTP" = 1 ]; then |
|
||||
eval $1=$_qn |
|
||||
eval $3=$_qn6 |
|
||||
else |
|
||||
eval $1= |
|
||||
eval $3= |
|
||||
fi |
|
||||
if [ "$MODE_HTTPS" = 1 ]; then |
|
||||
eval $2=$_qns |
|
||||
eval $4=$_qns6 |
|
||||
else |
|
||||
eval $2= |
|
||||
eval $4= |
|
||||
fi |
|
||||
} |
|
||||
|
|
||||
create_ipset() |
create_ipset() |
||||
{ |
{ |
||||
echo "Creating ipset" |
echo "Creating ip list table (firewall type $FWTYPE)" |
||||
"$IPSET_CR" "$@" |
"$IPSET_CR" "$@" |
||||
} |
} |
||||
|
|
||||
|
|
||||
is_flow_offload_avail() |
|
||||
{ |
|
||||
# $1 = '' for ipv4, '6' for ipv6 |
|
||||
grep -q FLOWOFFLOAD /proc/net/ip$1_tables_targets |
|
||||
} |
|
||||
list_nfqws_rules() |
list_nfqws_rules() |
||||
{ |
{ |
||||
# $1 = '' for ipv4, '6' for ipv6 |
# $1 = '' for ipv4, '6' for ipv6 |
||||
@ -390,7 +317,7 @@ list_nfqws_rules() |
|||||
} |
} |
||||
reverse_nfqws_rule() |
reverse_nfqws_rule() |
||||
{ |
{ |
||||
sed -e 's/-o /-i /' -e 's/--dport /--sport /' -e 's/--dports /--sports /' -e 's/ dst$/ src/' -e 's/ dst / src /' |
sed -e 's/-o /-i /g' -e 's/--dport /--sport /g' -e 's/--dports /--sports /g' -e 's/ dst$/ src/' -e 's/ dst / src /g' |
||||
} |
} |
||||
apply_flow_offloading_enable_rule() |
apply_flow_offloading_enable_rule() |
||||
{ |
{ |
||||
@ -411,15 +338,19 @@ apply_flow_offloading_exempt_rule() |
|||||
echo applying ipv${v:-4} flow offloading exemption : $i |
echo applying ipv${v:-4} flow offloading exemption : $i |
||||
ip${v}tables -A $i |
ip${v}tables -A $i |
||||
} |
} |
||||
|
flow_offloading_unexempt_v() |
||||
|
{ |
||||
|
ipt$1_del FORWARD -j forwarding_rule_zapret |
||||
|
ip$1tables -F forwarding_rule_zapret 2>/dev/null |
||||
|
ip$1tables -X forwarding_rule_zapret 2>/dev/null |
||||
|
} |
||||
flow_offloading_exempt_v() |
flow_offloading_exempt_v() |
||||
{ |
{ |
||||
# $1 = '' for ipv4, '6' for ipv6 |
# $1 = '' for ipv4, '6' for ipv6 |
||||
|
|
||||
is_flow_offload_avail $1 || return 0 |
is_ipt_flow_offload_avail $1 || return 0 |
||||
|
|
||||
ipt$1_del forwarding_rule -j forwarding_rule_zapret |
flow_offloading_unexempt_v $1 |
||||
ip$1tables -F forwarding_rule_zapret 2>/dev/null |
|
||||
ip$1tables -X forwarding_rule_zapret 2>/dev/null |
|
||||
|
|
||||
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && { |
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && { |
||||
ip$1tables -N forwarding_rule_zapret |
ip$1tables -N forwarding_rule_zapret |
||||
@ -436,7 +367,7 @@ flow_offloading_exempt_v() |
|||||
|
|
||||
apply_flow_offloading_enable_rule $1 |
apply_flow_offloading_enable_rule $1 |
||||
|
|
||||
ipt$1 forwarding_rule -j forwarding_rule_zapret |
ipt$1 FORWARD -j forwarding_rule_zapret |
||||
} |
} |
||||
|
|
||||
return 0 |
return 0 |
||||
@ -446,75 +377,137 @@ flow_offloading_exempt() |
|||||
[ "$DISABLE_IPV4" = "1" ] || flow_offloading_exempt_v |
[ "$DISABLE_IPV4" = "1" ] || flow_offloading_exempt_v |
||||
[ "$DISABLE_IPV6" = "1" ] || flow_offloading_exempt_v 6 |
[ "$DISABLE_IPV6" = "1" ] || flow_offloading_exempt_v 6 |
||||
} |
} |
||||
|
flow_offloading_unexempt() |
||||
|
{ |
||||
|
[ "$DISABLE_IPV4" = "1" ] || flow_offloading_unexempt_v |
||||
|
[ "$DISABLE_IPV6" = "1" ] || flow_offloading_unexempt_v 6 |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
zapret_apply_firewall() |
nft_fill_ifsets() |
||||
{ |
{ |
||||
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4" |
local script elements i wan_iface DEVICE DLAN DWAN DWAN6 ALLDEVS flags |
||||
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK" |
|
||||
local f4 f6 qn qns qn6 qns6 |
|
||||
|
|
||||
# always create ipsets. ip_exclude ipset is required |
# if large sets exist nft works very ineffectively |
||||
create_ipset no-update |
# looks like it analyzes the whole table blob to find required data pieces |
||||
|
# calling all in one shot helps not to waste cpu time many times |
||||
|
|
||||
case "${MODE_OVERRIDE:-$MODE}" in |
script="flush set inet $ZAPRET_NFT_TABLE wanif |
||||
tpws) |
flush set inet $ZAPRET_NFT_TABLE wanif6 |
||||
if [ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ]; then |
flush set inet $ZAPRET_NFT_TABLE lanif" |
||||
echo both http and https are disabled. not applying redirection. |
|
||||
else |
|
||||
filter_apply_port_target f4 |
|
||||
f6=$f4 |
|
||||
filter_apply_ipset_target f4 f6 |
|
||||
fw_tpws "$f4" "$f6" $TPPORT |
|
||||
fi |
|
||||
;; |
|
||||
|
|
||||
nfqws) |
|
||||
# quite complex but we need to minimize nfqws processes to save RAM |
|
||||
get_nfqws_qnums qn qns qn6 qns6 |
|
||||
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn" ] && [ "$qn" = "$qns" ]; then |
|
||||
filter_apply_port_target f4 |
|
||||
f4="$f4 $first_packet_only" |
|
||||
filter_apply_ipset_target4 f4 |
|
||||
fw_nfqws_post4 "$f4 $desync" $qn |
|
||||
else |
|
||||
if [ -n "$qn" ]; then |
|
||||
f4="--dport 80" |
|
||||
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f4="$f4 $first_packet_only" |
|
||||
filter_apply_ipset_target4 f4 |
|
||||
fw_nfqws_post4 "$f4 $desync" $qn |
|
||||
fi |
|
||||
if [ -n "$qns" ]; then |
|
||||
f4="--dport 443 $first_packet_only" |
|
||||
filter_apply_ipset_target4 f4 |
|
||||
fw_nfqws_post4 "$f4 $desync" $qns |
|
||||
fi |
|
||||
fi |
|
||||
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn6" ] && [ "$qn6" = "$qns6" ]; then |
|
||||
filter_apply_port_target f6 |
|
||||
f6="$f6 $first_packet_only" |
|
||||
filter_apply_ipset_target6 f6 |
|
||||
fw_nfqws_post6 "$f6 $desync" $qn6 |
|
||||
else |
|
||||
if [ -n "$qn6" ]; then |
|
||||
f6="--dport 80" |
|
||||
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f6="$f6 $first_packet_only" |
|
||||
filter_apply_ipset_target6 f6 |
|
||||
fw_nfqws_post6 "$f6 $desync" $qn6 |
|
||||
fi |
|
||||
if [ -n "$qns6" ]; then |
|
||||
f6="--dport 443 $first_packet_only" |
|
||||
filter_apply_ipset_target6 f6 |
|
||||
fw_nfqws_post6 "$f6 $desync" $qns6 |
|
||||
fi |
|
||||
fi |
|
||||
;; |
|
||||
custom) |
|
||||
existf zapret_custom_firewall && zapret_custom_firewall |
|
||||
;; |
|
||||
esac |
|
||||
|
|
||||
flow_offloading_exempt |
|
||||
|
|
||||
return 0 |
[ "$DISABLE_IPV4" = "1" ] || { |
||||
|
network_find_wan_all wan_iface |
||||
|
for i in $wan_iface; do |
||||
|
network_get_device DEVICE $i |
||||
|
DWAN="$DWAN $DEVICE" |
||||
|
done |
||||
|
[ -n "$DWAN" ] && { |
||||
|
make_comma_list elements $DWAN |
||||
|
script="${script} |
||||
|
add element inet $ZAPRET_NFT_TABLE wanif { $elements }" |
||||
|
} |
||||
|
} |
||||
|
[ "$DISABLE_IPV6" = "1" ] || { |
||||
|
network_find_wan6_all wan_iface |
||||
|
for i in $wan_iface; do |
||||
|
network_get_device DEVICE $i |
||||
|
DWAN6="$DWAN6 $DEVICE" |
||||
|
done |
||||
|
[ -n "$DWAN6" ] && { |
||||
|
make_comma_list elements $DWAN6 |
||||
|
script="${script} |
||||
|
add element inet $ZAPRET_NFT_TABLE wanif6 { $elements }" |
||||
|
} |
||||
|
} |
||||
|
for i in $OPENWRT_LAN; do |
||||
|
network_get_device DEVICE $i |
||||
|
DLAN="$DLAN $DEVICE" |
||||
|
done |
||||
|
[ -n "$DLAN" ] && { |
||||
|
make_comma_list elements $DLAN |
||||
|
script="${script} |
||||
|
add element inet $ZAPRET_NFT_TABLE lanif { $elements }" |
||||
|
} |
||||
|
echo "$script" | nft -f - |
||||
|
|
||||
|
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && { |
||||
|
ALLDEVS=$(for i in $DLAN $DWAN $DWAN6; do echo $i; done | sort -u | xargs) |
||||
|
[ "$FLOWOFFLOAD" = 'hardware' ] && nft_hw_offload_supported $ALLDEVS && flags=offload |
||||
|
nft_create_or_update_flowtable "$flags" $ALLDEVS |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
nft_fw_tpws4() |
||||
|
{ |
||||
|
# $1 - filter ipv4 |
||||
|
# $2 - tpws port |
||||
|
|
||||
|
[ "$DISABLE_IPV4" = "1" ] || { |
||||
|
nft_add_rule dnat_output skuid != $WS_USER oifname @wanif meta l4proto tcp $1 ip daddr != @nozapret dnat ip to $TPWS_LOCALHOST4:$2 |
||||
|
nft_add_rule dnat_pre iifname @lanif meta l4proto tcp $1 ip daddr != @nozapret dnat ip to $TPWS_LOCALHOST4:$2 |
||||
|
prepare_route_localnet |
||||
|
} |
||||
|
} |
||||
|
nft_fw_tpws6() |
||||
|
{ |
||||
|
# $1 - filter ipv6 |
||||
|
# $2 - tpws port |
||||
|
|
||||
|
local lan DEVICE DNAT6 |
||||
|
[ "$DISABLE_IPV6" = "1" ] || { |
||||
|
nft_add_rule dnat_output skuid != $WS_USER oifname @wanif6 meta l4proto tcp $1 ip6 daddr != @nozapret6 dnat ip6 to [::1]:$2 |
||||
|
for lan in $OPENWRT_LAN; do |
||||
|
network_get_device DEVICE $lan |
||||
|
[ -n "$DEVICE" ] || continue |
||||
|
dnat6_target $lan DNAT6 |
||||
|
[ "$DNAT6" != '-' ] && nft_add_rule dnat_pre iifname $DEVICE meta l4proto tcp $1 ip6 daddr != @nozapret6 dnat ip6 to [$DNAT6]:$2 |
||||
|
done |
||||
|
} |
||||
|
} |
||||
|
nft_fw_tpws() |
||||
|
{ |
||||
|
# $1 - filter ipv4 |
||||
|
# $2 - filter ipv6 |
||||
|
# $3 - tpws port |
||||
|
|
||||
|
nft_fw_tpws4 "$1" $3 |
||||
|
nft_fw_tpws6 "$2" $3 |
||||
|
} |
||||
|
|
||||
|
nft_fw_nfqws_post4() |
||||
|
{ |
||||
|
# $1 - filter ipv4 |
||||
|
# $2 - queue number |
||||
|
|
||||
|
local DEVICE wan_iface rule |
||||
|
|
||||
|
[ "$DISABLE_IPV4" = "1" ] || { |
||||
|
rule="oifname @wanif meta l4proto tcp $1 ip daddr != @nozapret" |
||||
|
nft_add_rule postrouting $rule queue num $2 bypass |
||||
|
nft_add_nfqws_flow_exempt_rule "$rule" |
||||
|
} |
||||
|
} |
||||
|
nft_fw_nfqws_post6() |
||||
|
{ |
||||
|
# $1 - filter ipv6 |
||||
|
# $2 - queue number |
||||
|
|
||||
|
local DEVICE wan_iface rule |
||||
|
|
||||
|
[ "$DISABLE_IPV6" = "1" ] || { |
||||
|
rule="oifname @wanif6 meta l4proto tcp $1 ip6 daddr != @nozapret6" |
||||
|
nft_add_rule postrouting $rule queue num $2 bypass |
||||
|
nft_add_nfqws_flow_exempt_rule "$rule" |
||||
|
} |
||||
|
} |
||||
|
nft_fw_nfqws_post() |
||||
|
{ |
||||
|
# $1 - filter ipv4 |
||||
|
# $2 - filter ipv6 |
||||
|
# $3 - queue number |
||||
|
|
||||
|
nft_fw_nfqws_post4 "$1" $3 |
||||
|
nft_fw_nfqws_post6 "$2" $3 |
||||
} |
} |
||||
|
@ -0,0 +1,34 @@ |
|||||
|
# this script contain your special code to launch daemons and configure firewall |
||||
|
# use helpers from "functions" file |
||||
|
# in case of upgrade keep this file only, do not modify others |
||||
|
|
||||
|
zapret_custom_daemons() |
||||
|
{ |
||||
|
# $1 - 1 - run, 0 - stop |
||||
|
|
||||
|
# PLACEHOLDER |
||||
|
echo !!! NEED ATTENTION !!! |
||||
|
echo Start daemon\(s\) |
||||
|
echo Study how other sections work |
||||
|
|
||||
|
do_daemon $1 1 /bin/sleep 20 |
||||
|
} |
||||
|
zapret_custom_firewall() |
||||
|
{ |
||||
|
# $1 - 1 - run, 0 - stop |
||||
|
|
||||
|
# PLACEHOLDER |
||||
|
echo !!! NEED ATTENTION !!! |
||||
|
echo Configure iptables for required actions |
||||
|
echo Study how other sections work |
||||
|
} |
||||
|
|
||||
|
zapret_custom_firewall_nft() |
||||
|
{ |
||||
|
# stop logic is not required |
||||
|
|
||||
|
# PLACEHOLDER |
||||
|
echo !!! NEED ATTENTION !!! |
||||
|
echo Configure nftables for required actions |
||||
|
echo Study how other sections work |
||||
|
} |
Loading…
Reference in new issue