mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-26 12:10:53 +03:00
nftables support
This commit is contained in:
parent
b7aa3a878c
commit
95667733a6
101
blockcheck.sh
101
blockcheck.sh
@ -4,6 +4,12 @@ EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
ZAPRET_BASE="$EXEDIR"
|
||||
|
||||
[ -f "$ZAPRET_BASE/config" ] && . "$ZAPRET_BASE/config"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/dialog.sh"
|
||||
. "$ZAPRET_BASE/common/elevate.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
|
||||
[ -n "$QNUM" ] || QNUM=59780
|
||||
[ -n "$TPPORT" ] || TPPORT=993
|
||||
[ -n "$TPWS_UID" ] || TPWS_UID=1
|
||||
@ -32,14 +38,6 @@ DNSCHECK_DIG2=/tmp/dig2.txt
|
||||
DNSCHECK_DIGS=/tmp/digs.txt
|
||||
|
||||
|
||||
exists()
|
||||
{
|
||||
which $1 >/dev/null 2>/dev/null
|
||||
}
|
||||
whichq()
|
||||
{
|
||||
which $1 2>/dev/null
|
||||
}
|
||||
killwait()
|
||||
{
|
||||
# $1 - signal (-9, -2, ...)
|
||||
@ -59,53 +57,6 @@ exitp()
|
||||
exit $1
|
||||
}
|
||||
|
||||
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
|
||||
$ECHON "$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
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
IPT()
|
||||
{
|
||||
$IPTABLES -C "$@" >/dev/null 2>/dev/null || $IPTABLES -I "$@"
|
||||
@ -165,29 +116,11 @@ check_system()
|
||||
Linux)
|
||||
PKTWS="$NFQWS"
|
||||
PKTWSD=nfqws
|
||||
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" ] && exists opkg && exists uci && [ "$INIT" = "procd" ] ; then
|
||||
SUBSYS=openwrt
|
||||
# new openwrt version abandon iptables and use nftables instead
|
||||
# no iptables/ip6tables/ipt-kmods are installed by default
|
||||
# fw4 firewall is used, fw3 is symbolic link to fw4
|
||||
# no more firewall includes
|
||||
# make sure nft was not just installed by user but all the system is based on fw4
|
||||
if [ -x /sbin/fw4 ] && exists nft && [ "$FWTYPE" != "iptables" ] ; then
|
||||
FWTYPE=nftables
|
||||
else
|
||||
FWTYPE=iptables
|
||||
fi
|
||||
else
|
||||
# generic linux
|
||||
if exists nft && [ "$FWTYPE" != "iptables" ]; then
|
||||
FWTYPE=nftables
|
||||
else
|
||||
FWTYPE=iptables
|
||||
fi
|
||||
fi
|
||||
linux_fwtype
|
||||
[ "$FWTYPE" = iptables -o "$FWTYPE" = nftables ] || {
|
||||
echo firewall type $FWTYPE not supported in $UNAME
|
||||
exitp 5
|
||||
}
|
||||
;;
|
||||
FreeBSD)
|
||||
PKTWS="$DVTWS"
|
||||
@ -403,10 +336,10 @@ pktws_ipt_prepare()
|
||||
nftables)
|
||||
nft add table inet $NFT_TABLE
|
||||
[ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ] && {
|
||||
nft "add chain inet $NFT_TABLE predefrag { type filter hook output priority -401; }"
|
||||
nft "add chain inet $NFT_TABLE predefrag { type filter hook output priority -402; }"
|
||||
nft "add rule inet $NFT_TABLE predefrag meta nfproto ipv${IPV} exthdr frag exists notrack"
|
||||
}
|
||||
nft "add chain inet $NFT_TABLE premangle { type filter hook output priority -151; }"
|
||||
nft "add chain inet $NFT_TABLE premangle { type filter hook output priority -152; }"
|
||||
nft "add rule inet $NFT_TABLE premangle meta nfproto ipv${IPV} tcp dport $1 mark and 0x40000000 != 0x40000000 queue num $QNUM bypass"
|
||||
;;
|
||||
ipfw)
|
||||
@ -447,7 +380,7 @@ tpws_ipt_prepare()
|
||||
nftables)
|
||||
nft add table inet $NFT_TABLE
|
||||
# -101 = pre dstnat
|
||||
nft "add chain inet $NFT_TABLE output { type nat hook output priority -101; }"
|
||||
nft "add chain inet $NFT_TABLE output { type nat hook output priority -102; }"
|
||||
nft "add rule inet $NFT_TABLE output tcp dport $1 skuid != $TPWS_UID dnat ip${IPVV} to $LOCALHOST_IPT:$TPPORT"
|
||||
;;
|
||||
ipfw)
|
||||
@ -801,9 +734,7 @@ configure_curl_opt()
|
||||
|
||||
linux_ipv6_defrag_can_be_disabled()
|
||||
{
|
||||
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 4 -o "$V1" = 4 -a "$V2" -ge 16 ]
|
||||
linux_min_version 4 16
|
||||
}
|
||||
|
||||
configure_defrag()
|
||||
@ -836,7 +767,7 @@ configure_defrag()
|
||||
fi
|
||||
[ -n "$IP6_DEFRAG_DISABLE" ] && {
|
||||
local ipexe="$(readlink -f $(whichq ip6tables))"
|
||||
if [ "${ipexe#*nft}" != "$ipexe" ]; then
|
||||
if contains "$ipexe" nft; then
|
||||
echo "WARNING ! ipv6 ipfrag tests may have no effect if ip6tables-nft is used. current ip6tables point to : $ipexe"
|
||||
else
|
||||
echo "WARNING ! ipv6 ipfrag tests may have no effect if ip6table_raw kernel module is not loaded with parameter : raw_before_defrag=1"
|
||||
|
135
common/base.sh
Normal file
135
common/base.sh
Normal file
@ -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
|
||||
}
|
58
common/dialog.sh
Normal file
58
common/dialog.sh
Normal file
@ -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" ]
|
||||
}
|
13
common/elevate.sh
Normal file
13
common/elevate.sh
Normal file
@ -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
|
||||
}
|
||||
}
|
64
common/fwtype.sh
Normal file
64
common/fwtype.sh
Normal file
@ -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
|
||||
}
|
462
common/installer.sh
Normal file
462
common/installer.sh
Normal file
@ -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
|
||||
}
|
172
common/ipt.sh
Normal file
172
common/ipt.sh
Normal file
@ -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
|
||||
}
|
23
common/linux_fw.sh
Normal file
23
common/linux_fw.sh
Normal file
@ -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 "$@"
|
||||
}
|
51
common/linux_iphelper.sh
Normal file
51
common/linux_iphelper.sh
Normal file
@ -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
|
||||
}
|
348
common/nft.sh
Normal file
348
common/nft.sh
Normal file
@ -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
|
||||
}
|
262
common/pf.sh
Normal file
262
common/pf.sh
Normal file
@ -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"
|
||||
}
|
45
common/queue.sh
Normal file
45
common/queue.sh
Normal file
@ -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
|
||||
}
|
12
config
12
config
@ -4,10 +4,15 @@
|
||||
# can help in case /tmp has not enough space
|
||||
#TMPDIR=/opt/zapret/tmp
|
||||
|
||||
# override firewall type : iptables,nftables,ipfw
|
||||
#FWTYPE=iptables
|
||||
|
||||
# options for ipsets
|
||||
# maximum number of elements in sets. also used for nft sets
|
||||
SET_MAXELEM=262144
|
||||
# too low hashsize can cause memory allocation errors on low RAM systems , even if RAM is enough
|
||||
# too large hashsize will waste lots of RAM
|
||||
IPSET_OPT="hashsize 262144 maxelem 2097152"
|
||||
IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
|
||||
|
||||
# options for ip2net. "-4" or "-6" auto added by ipset create script
|
||||
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
|
||||
@ -65,9 +70,8 @@ FLOWOFFLOAD=donttouch
|
||||
#IFACE_LAN=eth0
|
||||
#IFACE_WAN=eth1
|
||||
|
||||
# should init scripts apply firewall rules ?
|
||||
# set to 0 if firewall control system is present
|
||||
# openwrt uses fw3 firewall , init never touch fw
|
||||
# should start/stop command of init scripts apply firewall rules ?
|
||||
# not applicable to older openwrt with fw3 firewall
|
||||
INIT_APPLY_FW=1
|
||||
|
||||
# do not work with ipv4
|
||||
|
@ -218,3 +218,7 @@ nfqws: ipfrag
|
||||
v45
|
||||
|
||||
nfqws: hop-by-hop ipv6 desync and fooling
|
||||
|
||||
v46
|
||||
|
||||
big startup script refactoring to support nftables and new openwrt snapshot builds with firewall4
|
||||
|
92
docs/nftables_notes.txt
Normal file
92
docs/nftables_notes.txt
Normal file
@ -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.
|
@ -49,7 +49,7 @@ deal with its consequences.
|
||||
3. Modification of TCP connection at the packet level. Implemented through the NFQUEUE handler and raw sockets.
|
||||
|
||||
For options 2 and 3, tpws and nfqws programs are implemented, respectively.
|
||||
You need to run them with the necessary parameters and redirect certain traffic with iptables.
|
||||
You need to run them with the necessary parameters and redirect certain traffic with iptables or nftables.
|
||||
|
||||
To redirect a TCP connection to a transparent proxy, the following commands are used:
|
||||
|
||||
@ -110,6 +110,17 @@ In the PREROUTING DNAT chain, it is possible to any global address or to the lin
|
||||
the packet came from.
|
||||
NFQUEUE works without changes.
|
||||
|
||||
|
||||
## nftables
|
||||
|
||||
nftables are fine except one very big problem.
|
||||
nft requires tons of RAM to load large nf sets (ip lists) with subnets/intervals. Most of the home routers can't afford that.
|
||||
For example, even a 256 Mb system can't load a 100K ip list. nft process will OOM.
|
||||
nf sets do not support overlapping intervals and that's why nft process applies very RAM consuming algorithm to merge intervals so they don't overlap.
|
||||
There're equivalents to iptables for all other functions. Interface and protocol anonymous sets allow not to write multiple similar rules.
|
||||
Flow offloading is built-in into new linux kernels and nft versions.
|
||||
|
||||
|
||||
## When it will not work
|
||||
|
||||
* If DNS server returns false responses. ISP can return false IP addresses or not return anything
|
||||
@ -564,6 +575,9 @@ if remote resolving causes trouble configure clients to use local name resolutio
|
||||
|
||||
## Ways to get a list of blocked IP
|
||||
|
||||
nftables can't work with ipsets. Native nf sets require lots of RAM to load large ip lists with subnets and intervals.
|
||||
In case you're on a low RAM system and need large lists it may be required to fall back to iptables+ipset.
|
||||
|
||||
1. Enter the blocked domains to `ipset/zapret-hosts-user.txt` and run `ipset/get_user.sh`
|
||||
At the output, you get `ipset/zapret-ip-user.txt` with IP addresses.
|
||||
|
||||
@ -643,6 +657,12 @@ When using large regulator lists estimate the amount of RAM on the router !
|
||||
The file `/opt/zapret/config` is used by various components of the system and contains basic settings.
|
||||
It needs to be viewed and edited if necessary.
|
||||
|
||||
Which firewall type use on linux systems : `nftables` or `iptables`.
|
||||
On traditional systems `nftables` is selected by default if nft is installed.
|
||||
On openwrt by default `nftables` is selected on `firewall4` based systems.
|
||||
|
||||
`FWTYPE=iptables`
|
||||
|
||||
Main mode :
|
||||
|
||||
```
|
||||
@ -739,8 +759,9 @@ temp directory. Used by ipset/*.sh scripts for large lists processing.
|
||||
/tmp by default. Can be reassigned if /tmp is tmpfs and RAM is low.
|
||||
TMPDIR=/opt/zapret/tmp
|
||||
|
||||
ipset options :
|
||||
ipset and nfset options :
|
||||
|
||||
`SET_MAXELEM=262144`
|
||||
`IPSET_OPT="hashsize 262144 maxelem 2097152`
|
||||
|
||||
Kernel automatically increases hashsize if ipset is too large for the current hashsize.
|
||||
@ -770,6 +791,11 @@ In openwrt there's default network 'lan'. Only traffic coming from this network
|
||||
To override this behaviour set the following variable :
|
||||
`OPENWRT_LAN="lan lan2 lan3"`
|
||||
|
||||
The `INIT_APPLY_FW=1` parameter enables the init script to independently apply iptables rules.
|
||||
With other values or if the parameter is commented out, the rules will not be applied.
|
||||
This is useful if you have a firewall management system, in the settings of which you should tie the rules.
|
||||
Not applicable to `OpenWRT` if used with `firewall3+iptables`.
|
||||
|
||||
The following settings are not relevant for openwrt :
|
||||
|
||||
If your system works as a router, then you need to enter the names of the internal and external interfaces:
|
||||
@ -781,10 +807,6 @@ IMPORTANT: configuring routing, masquerade, etc. not a zapret task.
|
||||
Only modes that intercept transit traffic are enabled.
|
||||
It's possible to specify multiple interfaces like this : `IFACE_LAN="eth0 eth1 eth2"`
|
||||
|
||||
The `INIT_APPLY_FW=1` parameter enables the init script to independently apply iptables rules.
|
||||
With other values or if the parameter is commented out, the rules will not be applied.
|
||||
This is useful if you have a firewall management system, in the settings of which you should tie the rules.
|
||||
|
||||
|
||||
## Screwing to the firewall control system or your launch system
|
||||
|
||||
@ -795,17 +817,41 @@ In this case, the rules for iptables should be screwed to your firewall separate
|
||||
The following calls allow you to apply or remove iptables rules separately:
|
||||
|
||||
```
|
||||
/opt/zapret/init.d/sysv/zapret start-fw
|
||||
/opt/zapret/init.d/sysv/zapret stop-fw
|
||||
/opt/zapret/init.d/sysv/zapret start_fw
|
||||
/opt/zapret/init.d/sysv/zapret stop_fw
|
||||
/opt/zapret/init.d/sysv/zapret restart_fw
|
||||
```
|
||||
|
||||
And you can start or stop the demons separately from the firewall:
|
||||
|
||||
```
|
||||
/opt/zapret/init.d/sysv/zapret start-daemons
|
||||
/opt/zapret/init.d/sysv/zapret stop-daemons
|
||||
/opt/zapret/init.d/sysv/zapret start_daemons
|
||||
/opt/zapret/init.d/sysv/zapret stop_daemons
|
||||
/opt/zapret/init.d/sysv/zapret restart_daemons
|
||||
```
|
||||
|
||||
nftables nearly eliminate conflicts betweeen firewall control systems because they allow
|
||||
separate tables and netfilter hooks. `zapret` nf table is used for zapret purposes.
|
||||
If your system does not touch it everything will likely be OK.
|
||||
|
||||
Some additional nftables-only calls exist :
|
||||
|
||||
Lookup `lanif`, `wanif`, `wanif6` and `flow table` interface sets.
|
||||
```
|
||||
/opt/zapret/init.d/sysv/zapret list_ifsets
|
||||
```
|
||||
|
||||
Renew `lanif`, `wanif`, `wanif6` and `flow table` interface sets.
|
||||
Taken from `IFACE_LAN`, `IFACE_WAN` config variables on traditional Linux systems.
|
||||
Autoselected on `OpenWRT`. `lanif` can be extended using `OPENWRT_LAN` config variable.
|
||||
/opt/zapret/init.d/sysv/zapret reload_ifsets
|
||||
|
||||
Calls `nft -t list table inet zapret`.
|
||||
```
|
||||
/opt/zapret/init.d/sysv/zapret list_table
|
||||
```
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Checking ISP
|
||||
|
@ -1,4 +1,4 @@
|
||||
zapret v.45
|
||||
zapret v.46
|
||||
|
||||
English
|
||||
-------
|
||||
@ -63,7 +63,7 @@ For english version refer to docs/readme.eng.txt
|
||||
|
||||
Для вариантов 2 и 3 реализованы программы tpws и nfqws соответственно.
|
||||
Чтобы они работали, необходимо их запустить с нужными параметрами и перенаправить на них определенный трафик
|
||||
средствами iptables.
|
||||
средствами iptables или nftables.
|
||||
|
||||
|
||||
Для перенаправления tcp соединения на transparent proxy используются команды следующего вида :
|
||||
@ -149,6 +149,14 @@ DNAT на localhost (::1) возможен только в цепочке OUTPUT
|
||||
NFQUEUE работает без изменений.
|
||||
|
||||
|
||||
Особенности применения nftables
|
||||
-------------------------------
|
||||
|
||||
Более подробно преимущества и недостатки nftables применительно к данной системе описаны в docs/nftables_notes.txt
|
||||
Если коротко, то в nftables невозможно работать с большими ip листами на системах с малым количеством RAM.
|
||||
Остальные рассматриваемые здесь функции могут быть перенесены на nftables.
|
||||
|
||||
|
||||
Когда это работать не будет
|
||||
---------------------------
|
||||
|
||||
@ -490,6 +498,9 @@ options ip6table_raw raw_before_defrag=1
|
||||
|
||||
Это нужно сделать вручную, никакой автоматики в blockcheck.sh нет.
|
||||
|
||||
Либо можно раз и навсегда избавиться от этой проблемы, используя nftables. Там можно создать netfilter hook
|
||||
с любым приоритетом. Используйте приоритет -401 и ниже.
|
||||
|
||||
tpws
|
||||
-----
|
||||
|
||||
@ -642,6 +653,10 @@ tpws полностью работает на асинхронных сокет
|
||||
Способы получения списка заблокированных IP
|
||||
-------------------------------------------
|
||||
|
||||
!!! nftables не могут работать с ipset-ами. Собственный аналогичный механизм требует огромного количество RAM
|
||||
!!! для загрузки больших листов. Например, для загона 100K записей в nfset не хватает даже 256 Mb.
|
||||
!!! Если вам нужны большие листы на домашних роутерах, откатывайтесь на iptables+ipset.
|
||||
|
||||
1) Внесите заблокированные домены в ipset/zapret-hosts-user.txt и запустите ipset/get_user.sh
|
||||
На выходе получите ipset/zapret-ip-user.txt с IP адресами.
|
||||
|
||||
@ -829,6 +844,11 @@ tpws и nfqws решают нужно ли применять дурение в
|
||||
Файл /opt/zapret/config используется различными компонентами системы и содержит основные настройки.
|
||||
Его нужно просмотреть и при необходимости отредактировать.
|
||||
|
||||
На linux системах можно выбрать использовать iptables или nftables.
|
||||
По умолчанию на традиционных linux выбирается nftables, если установлен nft.
|
||||
На openwrt по умолчанию выбирается nftables на новых версиях с firewall4.
|
||||
|
||||
FWTYPE=iptables
|
||||
|
||||
Основной режим :
|
||||
tpws - tpws в режиме transparent
|
||||
@ -910,8 +930,11 @@ MDIG_THREADS=30
|
||||
указать место на флэшке или диске.
|
||||
TMPDIR=/opt/zapret/tmp
|
||||
|
||||
Опции для создания ipset-ов
|
||||
Опции для создания ipset-ов и nfset-ов
|
||||
|
||||
SET_MAXELEM=262144
|
||||
IPSET_OPT="hashsize 262144 maxelem 2097152"
|
||||
|
||||
ПРО РУГАНЬ в dmesg по поводу нехватки памяти.
|
||||
Может так случиться, что памяти в системе достаточно, но при попытке заполнить огромный ipset
|
||||
ядро начинает громко ругаться, ipset заполняется не полностью.
|
||||
@ -939,6 +962,11 @@ GZIP_LISTS=1
|
||||
Но возможно задать другие сети или список сетей :
|
||||
OPENWRT_LAN="lan lan2 lan3"
|
||||
|
||||
Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables.
|
||||
При иных значениях или если параметр закомментирован, правила применены не будут.
|
||||
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.
|
||||
На openwrt неприменимо при использовании firewall3+iptables.
|
||||
|
||||
Следующие настройки не актуальны для openwrt :
|
||||
|
||||
Если ваша система работает как роутер, то нужно вписать названия внутреннего и внешнего интерфейсов :
|
||||
@ -948,10 +976,6 @@ IFACE_WAN=eth1
|
||||
Включаются только режимы, обеспечивающие перехват транзитного трафика.
|
||||
Возможно определить несколько интерфейсов следующим образом : IFACE_LAN="eth0 eth1 eth2"
|
||||
|
||||
Параметр INIT_APPLY_FW=1 разрешает init скрипту самостоятельно применять правила iptables.
|
||||
При иных значениях или если параметр закомментирован, правила применены не будут.
|
||||
Это полезно, если у вас есть система управления фаерволом, в настройки которой и следует прикрутить правила.
|
||||
|
||||
Прикручивание к системе управления фаерволом или своей системе запуска
|
||||
----------------------------------------------------------------------
|
||||
|
||||
@ -961,13 +985,34 @@ IFACE_WAN=eth1
|
||||
|
||||
Следующие вызовы позволяют применить или убрать правила iptables отдельно :
|
||||
|
||||
/opt/zapret/init.d/sysv/zapret start-fw
|
||||
/opt/zapret/init.d/sysv/zapret stop-fw
|
||||
/opt/zapret/init.d/sysv/zapret start_fw
|
||||
/opt/zapret/init.d/sysv/zapret stop_fw
|
||||
/opt/zapret/init.d/sysv/zapret restart_fw
|
||||
|
||||
А так можно запустить или остановить демоны отдельно от фаервола :
|
||||
|
||||
/opt/zapret/init.d/sysv/zapret start-daemons
|
||||
/opt/zapret/init.d/sysv/zapret stop-daemons
|
||||
/opt/zapret/init.d/sysv/zapret start_daemons
|
||||
/opt/zapret/init.d/sysv/zapret stop_daemons
|
||||
/opt/zapret/init.d/sysv/zapret restart_daemons
|
||||
|
||||
nftables сводят практически на нет конфликты между разными системами управления, поскольку позволяют
|
||||
использовать независимые таблицы и хуки. Используется отдельная nf-таблица "zapret".
|
||||
Если ваша система ее не будет трогать, скорее всего все будет нормально.
|
||||
|
||||
Для nftables предусмотрено несколько дополнительных вызовов :
|
||||
|
||||
Посмотреть set-ы интерфейсов, относящихся к lan, wan и wan6. По ним идет завертывание трафика.
|
||||
А так же таблицу flow table с именами интерфейсов ingress hook.
|
||||
/opt/zapret/init.d/sysv/zapret list_ifsets
|
||||
|
||||
Обновить set-ы интерфейсов, относящихся к lan, wan и wan6.
|
||||
Для традиционных linux список интерфейсов берется из переменных конфига IFACE_LAN, IFACE_WAN.
|
||||
Для openwrt определяется автоматически. Множество lanif может быть расширено параметром OPENWRT_LAN.
|
||||
Все интерфейсы lan и wan так же добавляются в ingress hook от flow table.
|
||||
/opt/zapret/init.d/sysv/zapret reload_ifsets
|
||||
|
||||
Просмотр таблицы без содержимого set-ов. Вызывает nft -t list table inet zapret
|
||||
/opt/zapret/init.d/sysv/zapret list_table
|
||||
|
||||
Вариант custom
|
||||
--------------
|
||||
@ -980,20 +1025,22 @@ custom код вынесен в отдельный shell include
|
||||
Нужно свой код вписать в функции :
|
||||
zapret_custom_daemons
|
||||
zapret_custom_firewall
|
||||
zapret_custom_firewall_nft
|
||||
|
||||
В файле custom пишите ваш код, пользуясь хелперами из "functions" или "zapret".
|
||||
Смотрите как там сделано добавление iptables или запуск демонов.
|
||||
Используя хелпер функции, вы избавитесь от необходимости учитывать все возможные случаи
|
||||
типа наличия/отсутствия ipv6, является ли система роутером, имена интерфейсов, ...
|
||||
Хелперы это учитывают , вам нужно сосредоточиться лишь на фильтрах iptables и
|
||||
Хелперы это учитывают , вам нужно сосредоточиться лишь на фильтрах {ip,nf}tables и
|
||||
параметрах демонов.
|
||||
|
||||
Код для openwrt и sysv немного отличается. В sysv нужно обрабатывать и запуск, и остановку.
|
||||
Код для openwrt и sysv немного отличается. В sysv нужно обрабатывать и запуск, и остановку демонов.
|
||||
Запуск это или остановка передается в параметре $1 (0 или 1).
|
||||
В openwrt за остановку демонов отвечает procd, а firewall вычищается при "fw3 restart",
|
||||
потому нет необходимости реализовывать логику останова.
|
||||
В openwrt за остановку отвечает procd.
|
||||
|
||||
При апгрейде нужно сохранить лишь custom, другие файлы править не надо.
|
||||
Для фаервола кастом пишется отдельно для iptables и nftables. Все очень похоже, но отличается
|
||||
написание фильтров и названия процедур хелперов. Если вам не нужны iptables или nftables -
|
||||
можете не писать соответствующую функцию.
|
||||
|
||||
Готовый custom скрипт custom-tpws4http-nfqws4https позволяет применить дурение
|
||||
tpws к http и nfqws к https. При этом поддерживаются установки из config.
|
||||
@ -1011,6 +1058,8 @@ tpws к http и nfqws к https. При этом поддерживаются у
|
||||
apt-get update
|
||||
apt-get install ipset curl dnsutils git
|
||||
|
||||
Если хотите использовать nftables, то нужен пакет nftables, а ipset не обязателен.
|
||||
|
||||
Скопировать директорию zapret в /opt или скачать через git :
|
||||
cd /opt
|
||||
git clone --depth 1 https://github.com/bol-van/zapret
|
||||
@ -1124,7 +1173,7 @@ git и curl по умолчанию могут присутствовать, ips
|
||||
|
||||
Подключить init скрипт :
|
||||
|
||||
ln -fs /opt/zapret/init.d/sysv/zapret /etc/init.d
|
||||
ln -fs /opt/zapret/init.d/openrc/zapret /etc/init.d
|
||||
rc-update add zapret
|
||||
|
||||
Запустить службу :
|
||||
@ -1174,8 +1223,11 @@ install_easy.sh автоматизирует описанные выше руч
|
||||
Деинсталяция выполняется через uninstall_easy.sh
|
||||
|
||||
|
||||
Ручная установка на openwrt/LEDE
|
||||
--------------------------------
|
||||
Ручная установка на openwrt/LEDE 15.xx-21.xx
|
||||
--------------------------------------------
|
||||
|
||||
!!! Данная инструкция написана для систем, основанных на iptables+firewall3
|
||||
!!! В новых версиях openwrt переходит на nftables+firewall4, инструкция неприменима. Пользуйтесь install_easy.sh
|
||||
|
||||
Установить дополнительные пакеты :
|
||||
opkg update
|
||||
@ -1283,10 +1335,10 @@ Cкрипт из /etc/hotplug.d/iface перезапустит демоны по
|
||||
|
||||
Посмотреть через iptables -nL, ip6tables -nL или через luci вкладку "firewall" появились ли нужные правила.
|
||||
|
||||
ЭКОНОМИЯ МЕСТА : если его мало, то можно оставить в директории zapret лишь подкаталог ipset, файл config и init.d/openwrt.
|
||||
ЭКОНОМИЯ МЕСТА : если его мало, то можно оставить в директории zapret лишь подкаталоги
|
||||
ipset, common, файл config, init.d/openwrt.
|
||||
Далее нужно создать подкаталоги с реально используемыми бинариками (ip2net, mdig, tpws, nfq)
|
||||
и скопировать туда из binaries рабочие executables.
|
||||
Рекомендуется оставить ip2net и mdig. Из tpws и nfq оставить лишь тот, что был выбран в config.
|
||||
|
||||
ЕСЛИ ВСЕ ПЛОХО С МЕСТОМ : откажитесь от работы со списком РКН. используйте только get_user.sh
|
||||
|
||||
|
@ -1,4 +1,9 @@
|
||||
# init script functions library for macos
|
||||
|
||||
[ -n "$ZAPRET_BASE" ] || ZAPRET_BASE=/opt/zapret
|
||||
. "$ZAPRET_BASE/config"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/pf.sh"
|
||||
|
||||
IPSET_DIR=$ZAPRET_BASE/ipset
|
||||
. "$IPSET_DIR/def.sh"
|
||||
@ -14,33 +19,9 @@ TPWS_WAIT="--bind-wait-ifup=30 --bind-wait-ip=30"
|
||||
TPWS_WAIT_SOCKS6="$TPWS_WAIT --bind-wait-ip-linklocal=30"
|
||||
[ -n "$TPWS" ] || TPWS="$ZAPRET_BASE/tpws/tpws"
|
||||
|
||||
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"
|
||||
|
||||
CUSTOM_SCRIPT="$ZAPRET_BASE/init.d/macos/custom"
|
||||
[ -f "$CUSTOM_SCRIPT" ] && . "$CUSTOM_SCRIPT"
|
||||
|
||||
existf()
|
||||
{
|
||||
type "$1" >/dev/null 2>/dev/null
|
||||
}
|
||||
|
||||
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" "$@"
|
||||
}
|
||||
|
||||
run_daemon()
|
||||
{
|
||||
# $1 - daemon number : 1,2,3,...
|
||||
@ -134,263 +115,6 @@ get_ipv6_linklocal()
|
||||
}
|
||||
|
||||
|
||||
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"
|
||||
}
|
||||
|
||||
|
||||
|
||||
zapret_do_firewall()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
@ -20,26 +20,26 @@ case "$1" in
|
||||
"$0" start
|
||||
;;
|
||||
|
||||
start-fw)
|
||||
start-fw|start_fw)
|
||||
zapret_apply_firewall
|
||||
;;
|
||||
stop-fw)
|
||||
stop-fw|stop_fw)
|
||||
zapret_unapply_firewall
|
||||
;;
|
||||
restart-fw)
|
||||
restart-fw|stop_fw)
|
||||
zapret_restart_firewall
|
||||
;;
|
||||
reload-fw-tables)
|
||||
reload-fw-tables|reload_fw_tables)
|
||||
pf_table_reload
|
||||
;;
|
||||
|
||||
start-daemons)
|
||||
start-daemons|start_daemons)
|
||||
zapret_run_daemons
|
||||
;;
|
||||
stop-daemons)
|
||||
stop-daemons|stop_daemons)
|
||||
zapret_stop_daemons
|
||||
;;
|
||||
restart-daemons)
|
||||
restart-daemons|restart_daemons)
|
||||
zapret_restart_daemons
|
||||
;;
|
||||
|
||||
|
69
init.d/openrc/zapret
Normal file
69
init.d/openrc/zapret
Normal file
@ -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
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
ZAPRET=/etc/init.d/zapret
|
||||
|
||||
[ "$ACTION" = "ifup" ] && [ -x "$ZAPRET" ] && "$ZAPRET" enabled && {
|
||||
[ -n "$INTERFACE" -a -n "$ACTION" -a -x "$ZAPRET" ] && "$ZAPRET" enabled && {
|
||||
SCRIPT=$(readlink "$ZAPRET")
|
||||
if [ -n "$SCRIPT" ]; then
|
||||
EXEDIR=$(dirname "$SCRIPT")
|
||||
@ -11,11 +11,29 @@ ZAPRET=/etc/init.d/zapret
|
||||
ZAPRET_BASE=/opt/zapret
|
||||
fi
|
||||
. "$ZAPRET_BASE/config"
|
||||
[ -n "$OPENWRT_LAN" ] || OPENWRT_LAN=lan
|
||||
for lan in $OPENWRT_LAN; do
|
||||
[ "$INTERFACE" = "$lan" ] && {
|
||||
"$ZAPRET" restart
|
||||
break
|
||||
}
|
||||
done
|
||||
[ "$ACTION" = "ifup" ] && {
|
||||
[ -n "$OPENWRT_LAN" ] || OPENWRT_LAN=lan
|
||||
for lan in $OPENWRT_LAN; do
|
||||
[ "$INTERFACE" = "$lan" ] && {
|
||||
logger -t zapret restarting daemons due to $ACTION of $INTERFACE
|
||||
"$ZAPRET" restart_daemons
|
||||
break
|
||||
}
|
||||
done
|
||||
}
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
linux_fwtype
|
||||
case "$FWTYPE" in
|
||||
nftables)
|
||||
logger -t zapret reloading nftables ifsets due to $ACTION of $INTERFACE
|
||||
"$ZAPRET" reload_ifsets
|
||||
;;
|
||||
iptables)
|
||||
openwrt_fw3 || {
|
||||
logger -t zapret reloading iptables due to $ACTION of $INTERFACE
|
||||
"$ZAPRET" restart_fw
|
||||
}
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# stop logic is managed by procd
|
||||
|
||||
# PLACEHOLDER
|
||||
echo !!! NEED ATTENTION !!!
|
||||
echo Start daemon\(s\)
|
||||
@ -13,8 +15,19 @@ zapret_custom_daemons()
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# stop logic is managed by procd
|
||||
|
||||
local opt
|
||||
|
||||
[ "$MODE_HTTP" = "1" ] && {
|
||||
@ -19,6 +21,8 @@ zapret_custom_daemons()
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f4 f6
|
||||
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
|
||||
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||
@ -27,13 +31,35 @@ zapret_custom_firewall()
|
||||
f4="--dport 80"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_tpws "$f4" "$f6" $TPPORT
|
||||
fw_tpws $1 "$f4" "$f6" $TPPORT
|
||||
}
|
||||
|
||||
[ "$MODE_HTTPS" = "1" ] && {
|
||||
f4="--dport 443 $first_packet_only"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_nfqws_post "$f4 $desync" "$f6 $desync" $QNUM
|
||||
fw_nfqws_post $1 "$f4 $desync" "$f6 $desync" $QNUM
|
||||
}
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local f4 f6
|
||||
local first_packet_only="ct original packets 1-4"
|
||||
local desync="mark and $DESYNC_MARK == 0"
|
||||
|
||||
[ "$MODE_HTTP" = "1" ] && {
|
||||
f4="tcp dport 80"
|
||||
f6=$f4
|
||||
nft_filter_apply_ipset_target f4 f6
|
||||
nft_fw_tpws "$f4" "$f6" $TPPORT
|
||||
}
|
||||
|
||||
[ "$MODE_HTTPS" = "1" ] && {
|
||||
f4="tcp dport 443 $first_packet_only"
|
||||
f6=$f4
|
||||
nft_filter_apply_ipset_target f4 f6
|
||||
nft_fw_nfqws_post "$f4 $desync" "$f6 $desync" $QNUM
|
||||
}
|
||||
}
|
||||
|
20
init.d/openwrt/custom.default
Normal file
20
init.d/openwrt/custom.default
Normal file
@ -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
|
||||
. "$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 "$TPPORT" ] || TPPORT=988
|
||||
[ -n "$WS_USER" ] || WS_USER=daemon
|
||||
TPWS_LOCALHOST4=127.0.0.127
|
||||
[ -n "$DESYNC_MARK" ] || DESYNC_MARK=0x40000000
|
||||
[ -n "$OPENWRT_LAN" ] || OPENWRT_LAN=lan
|
||||
|
||||
TPWS_LOCALHOST4=127.0.0.127
|
||||
|
||||
# max wait time for the link local ipv6 on the LAN interface
|
||||
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_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
|
||||
@ -46,341 +46,268 @@ existf()
|
||||
|
||||
network_find_wan_all()
|
||||
{
|
||||
__network_ifstatus "$1" "" "[@.route[@.target='0.0.0.0' && !@.table]].interface" "" 10 2>/dev/null && return
|
||||
network_find_wan $1
|
||||
__network_ifstatus "$1" "" "[@.route[@.target='0.0.0.0' && !@.table]].interface" "" 10 2>/dev/null && return
|
||||
network_find_wan $1
|
||||
}
|
||||
network_find_wan6_all()
|
||||
{
|
||||
__network_ifstatus "$1" "" "[@.route[@.target='::' && !@.table]].interface" "" 10 2>/dev/null && return
|
||||
network_find_wan6 $1
|
||||
__network_ifstatus "$1" "" "[@.route[@.target='::' && !@.table]].interface" "" 10 2>/dev/null && return
|
||||
network_find_wan6 $1
|
||||
}
|
||||
|
||||
ipt()
|
||||
route_localnet()
|
||||
{
|
||||
iptables -C "$@" >/dev/null 2>/dev/null || iptables -I "$@"
|
||||
}
|
||||
ipt_del()
|
||||
{
|
||||
iptables -C "$@" >/dev/null 2>/dev/null && iptables -D "$@"
|
||||
}
|
||||
ipt6()
|
||||
{
|
||||
ip6tables -C "$@" >/dev/null 2>/dev/null || ip6tables -I "$@"
|
||||
}
|
||||
ipt6_del()
|
||||
{
|
||||
ip6tables -C "$@" >/dev/null 2>/dev/null && ip6tables -D "$@"
|
||||
}
|
||||
|
||||
# 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
|
||||
for lan in $OPENWRT_LAN; do
|
||||
network_get_device DEVICE $lan
|
||||
[ -n "$DEVICE" ] || continue
|
||||
sysctl -qw net.ipv4.conf.$DEVICE.route_localnet=1
|
||||
done
|
||||
}
|
||||
|
||||
dnat6_target()
|
||||
{
|
||||
# $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)
|
||||
# $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=''
|
||||
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
|
||||
[ -n "$DNAT6_TARGET" ] || {
|
||||
# no reason to query if its down
|
||||
network_is_up $1 || return
|
||||
|
||||
local DEVICE
|
||||
network_get_device DEVICE $1
|
||||
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
|
||||
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"
|
||||
[ -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"
|
||||
}
|
||||
|
||||
|
||||
set_route_localnet()
|
||||
{
|
||||
# $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
|
||||
}
|
||||
}
|
||||
prepare_route_localnet()
|
||||
{
|
||||
set_route_localnet 1
|
||||
}
|
||||
unprepare_route_localnet()
|
||||
{
|
||||
set_route_localnet 0
|
||||
}
|
||||
prepare_tpws_fw4()
|
||||
{
|
||||
# otherwise linux kernel will treat 127.0.0.0/8 as "martian" ip and refuse routing to it
|
||||
# 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
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
iptables -N input_rule_zapret 2>/dev/null
|
||||
ipt input_rule_zapret -d $TPWS_LOCALHOST4 -j RETURN
|
||||
ipta input_rule_zapret -d 127.0.0.0/8 -j DROP
|
||||
ipt INPUT ! -i lo -j input_rule_zapret
|
||||
|
||||
prepare_route_localnet
|
||||
}
|
||||
}
|
||||
unprepare_tpws_fw4()
|
||||
{
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
unprepare_route_localnet
|
||||
|
||||
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()
|
||||
{
|
||||
unprepare_tpws_fw4
|
||||
}
|
||||
|
||||
fw_nfqws_pre4()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - queue number
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter ipv4
|
||||
# $3 - queue number
|
||||
|
||||
local DEVICE wan_iface
|
||||
local DEVICE wan_iface
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
network_find_wan_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
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
|
||||
done
|
||||
}
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
network_find_wan_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
network_get_device DEVICE $ext_iface
|
||||
ipt_add_del $1 PREROUTING -t mangle -i $DEVICE -p tcp $2 $IPSET_EXCLUDE src -j NFQUEUE --queue-num $3 --queue-bypass
|
||||
done
|
||||
}
|
||||
}
|
||||
fw_nfqws_pre6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - queue number
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter ipv6
|
||||
# $3 - queue number
|
||||
|
||||
local DEVICE wan_iface
|
||||
local DEVICE wan_iface
|
||||
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
network_find_wan6_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
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
|
||||
done
|
||||
}
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
network_find_wan6_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
network_get_device DEVICE $ext_iface
|
||||
ipt6_add_del $1 PREROUTING -t mangle -i $DEVICE -p tcp $2 $IPSET_EXCLUDE6 src -j NFQUEUE --queue-num $3 --queue-bypass
|
||||
done
|
||||
}
|
||||
}
|
||||
fw_nfqws_pre()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - filter ipv6
|
||||
# $3 - queue number
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter ipv4
|
||||
# $3 - filter ipv6
|
||||
# $4 - queue number
|
||||
|
||||
fw_nfqws_pre4 "$1" $3
|
||||
fw_nfqws_pre6 "$2" $3
|
||||
fw_nfqws_pre4 $1 "$2" $4
|
||||
fw_nfqws_pre6 $1 "$3" $4
|
||||
}
|
||||
fw_nfqws_post4()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - queue number
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter ipv4
|
||||
# $3 - queue number
|
||||
|
||||
local DEVICE wan_iface
|
||||
local DEVICE wan_iface
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
network_find_wan_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
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
|
||||
done
|
||||
}
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
network_find_wan_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
network_get_device DEVICE $ext_iface
|
||||
ipt_add_del $1 POSTROUTING -t mangle -o $DEVICE -p tcp $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass
|
||||
done
|
||||
}
|
||||
}
|
||||
fw_nfqws_post6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - queue number
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter ipv6
|
||||
# $3 - queue number
|
||||
|
||||
local DEVICE wan_iface
|
||||
local DEVICE wan_iface
|
||||
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
network_find_wan6_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
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
|
||||
done
|
||||
}
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
network_find_wan6_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
network_get_device DEVICE $ext_iface
|
||||
ipt6_add_del $1 POSTROUTING -t mangle -o $DEVICE -p tcp $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass
|
||||
done
|
||||
}
|
||||
}
|
||||
fw_nfqws_post()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - filter ipv6
|
||||
# $3 - queue number
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter ipv4
|
||||
# $3 - filter ipv6
|
||||
# $4 - queue number
|
||||
|
||||
fw_nfqws_post4 "$1" $3
|
||||
fw_nfqws_post6 "$2" $3
|
||||
fw_nfqws_post4 $1 "$2" $4
|
||||
fw_nfqws_post6 $1 "$3" $4
|
||||
}
|
||||
|
||||
|
||||
IPT_OWNER="-m owner ! --uid-owner $WS_USER"
|
||||
fw_tpws4()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - tpws port
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter ipv4
|
||||
# $3 - tpws port
|
||||
|
||||
local DEVICE wan_iface
|
||||
local lan DEVICE ext_iface wan_iface
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
network_find_wan_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
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
|
||||
done
|
||||
|
||||
# allow localnet route only to special tpws IP
|
||||
iptables -N input_rule_zapret 2>/dev/null
|
||||
ipt input_rule_zapret -d 127.0.0.0/8 -j DROP
|
||||
ipt input_rule_zapret -d $TPWS_LOCALHOST4 -j RETURN
|
||||
|
||||
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
|
||||
}
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
network_find_wan_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
network_get_device DEVICE $ext_iface
|
||||
ipt_add_del $1 OUTPUT -t nat -o $DEVICE $IPT_OWNER -p tcp $2 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3
|
||||
done
|
||||
[ "$1" = 1 ] && prepare_tpws_fw4
|
||||
for lan in $OPENWRT_LAN; do
|
||||
network_get_device DEVICE $lan
|
||||
[ -n "$DEVICE" ] || continue
|
||||
ipt_add_del $1 PREROUTING -t nat -i $DEVICE -p tcp $2 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3
|
||||
done
|
||||
}
|
||||
}
|
||||
fw_tpws6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - tpws port
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter ipv6
|
||||
# $3 - tpws port
|
||||
|
||||
local DEVICE wan_iface DNAT6
|
||||
local lan DEVICE ext_iface wan_iface DNAT6
|
||||
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
network_find_wan6_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
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
|
||||
done
|
||||
for lan in $OPENWRT_LAN; do
|
||||
network_get_device DEVICE $lan
|
||||
[ -n "$DEVICE" ] || continue
|
||||
dnat6_target $lan DNAT6
|
||||
[ "$DNAT6" != '-' ] && ipt6 PREROUTING -t nat -i $DEVICE -p tcp $1 $IPSET_EXCLUDE6 dst -j DNAT --to [$DNAT6]:$2
|
||||
done
|
||||
}
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
network_find_wan6_all wan_iface
|
||||
for ext_iface in $wan_iface; do
|
||||
network_get_device DEVICE $ext_iface
|
||||
ipt6_add_del $1 OUTPUT -t nat -o $DEVICE $IPT_OWNER -p tcp $2 $IPSET_EXCLUDE6 dst -j DNAT --to [::1]:$3
|
||||
done
|
||||
for lan in $OPENWRT_LAN; do
|
||||
network_get_device DEVICE $lan
|
||||
[ -n "$DEVICE" ] || continue
|
||||
dnat6_target $lan DNAT6
|
||||
[ "$DNAT6" != '-' ] && ipt6_add_del $1 PREROUTING -t nat -i $DEVICE -p tcp $2 $IPSET_EXCLUDE6 dst -j DNAT --to [$DNAT6]:$3
|
||||
done
|
||||
}
|
||||
}
|
||||
fw_tpws()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - filter ipv6
|
||||
# $3 - tpws port
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter ipv4
|
||||
# $3 - filter ipv6
|
||||
# $4 - tpws port
|
||||
|
||||
fw_tpws4 "$1" $3
|
||||
fw_tpws6 "$2" $3
|
||||
fw_tpws4 $1 "$2" $4
|
||||
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()
|
||||
{
|
||||
echo "Creating ipset"
|
||||
"$IPSET_CR" "$@"
|
||||
echo "Creating ip list table (firewall type $FWTYPE)"
|
||||
"$IPSET_CR" "$@"
|
||||
}
|
||||
|
||||
|
||||
is_flow_offload_avail()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
grep -q FLOWOFFLOAD /proc/net/ip$1_tables_targets
|
||||
}
|
||||
list_nfqws_rules()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
@ -390,7 +317,7 @@ list_nfqws_rules()
|
||||
}
|
||||
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()
|
||||
{
|
||||
@ -411,15 +338,19 @@ apply_flow_offloading_exempt_rule()
|
||||
echo applying ipv${v:-4} flow offloading exemption : $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()
|
||||
{
|
||||
# $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
|
||||
ip$1tables -F forwarding_rule_zapret 2>/dev/null
|
||||
ip$1tables -X forwarding_rule_zapret 2>/dev/null
|
||||
flow_offloading_unexempt_v $1
|
||||
|
||||
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && {
|
||||
ip$1tables -N forwarding_rule_zapret
|
||||
@ -436,7 +367,7 @@ flow_offloading_exempt_v()
|
||||
|
||||
apply_flow_offloading_enable_rule $1
|
||||
|
||||
ipt$1 forwarding_rule -j forwarding_rule_zapret
|
||||
ipt$1 FORWARD -j forwarding_rule_zapret
|
||||
}
|
||||
|
||||
return 0
|
||||
@ -446,75 +377,137 @@ flow_offloading_exempt()
|
||||
[ "$DISABLE_IPV4" = "1" ] || flow_offloading_exempt_v
|
||||
[ "$DISABLE_IPV6" = "1" ] || flow_offloading_exempt_v 6
|
||||
}
|
||||
|
||||
|
||||
zapret_apply_firewall()
|
||||
flow_offloading_unexempt()
|
||||
{
|
||||
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
|
||||
create_ipset no-update
|
||||
|
||||
case "${MODE_OVERRIDE:-$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 "$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" ] || flow_offloading_unexempt_v
|
||||
[ "$DISABLE_IPV6" = "1" ] || flow_offloading_unexempt_v 6
|
||||
}
|
||||
|
||||
|
||||
|
||||
nft_fill_ifsets()
|
||||
{
|
||||
local script elements i wan_iface DEVICE DLAN DWAN DWAN6 ALLDEVS flags
|
||||
|
||||
# if large sets exist nft works very ineffectively
|
||||
# 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
|
||||
|
||||
script="flush set inet $ZAPRET_NFT_TABLE wanif
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif6
|
||||
flush set inet $ZAPRET_NFT_TABLE lanif"
|
||||
|
||||
[ "$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
|
||||
}
|
||||
|
@ -4,6 +4,24 @@ USE_PROCD=1
|
||||
# after network
|
||||
START=21
|
||||
|
||||
my_extra_command() {
|
||||
local cmd="$1"
|
||||
local help="$2"
|
||||
|
||||
local extra="$(printf "%-16s%s" "${cmd}" "${help}")"
|
||||
EXTRA_HELP="${EXTRA_HELP} ${extra}
|
||||
"
|
||||
EXTRA_COMMANDS="${EXTRA_COMMANDS} ${cmd}"
|
||||
}
|
||||
my_extra_command stop_fw "Stop zapret firewall (noop in iptables+fw3 case)"
|
||||
my_extra_command start_fw "Start zapret firewall (noop in iptables+fw3 case)"
|
||||
my_extra_command restart_fw "Restart zapret firewall (noop in iptables+fw3 case)"
|
||||
my_extra_command reload_ifsets "Reload interface lists (nftables only)"
|
||||
my_extra_command list_ifsets "Display interface lists (nftables only)"
|
||||
my_extra_command list_table "Display zapret nftable (nftables only)"
|
||||
my_extra_command stop_daemons "Stop zapret daemons only (=stop in iptables+fw3 case)"
|
||||
my_extra_command start_daemons "Start zapret daemons only (=start in iptables+fw3 case)"
|
||||
my_extra_command restart_daemons "Restart zapret firewall only (=restart in iptables+fw3 case)"
|
||||
|
||||
SCRIPT=$(readlink /etc/init.d/zapret)
|
||||
if [ -n "$SCRIPT" ]; then
|
||||
@ -12,10 +30,12 @@ if [ -n "$SCRIPT" ]; then
|
||||
else
|
||||
ZAPRET_BASE=/opt/zapret
|
||||
fi
|
||||
|
||||
. "$ZAPRET_BASE/init.d/openwrt/functions"
|
||||
|
||||
|
||||
# !!!!! in openwrt firewall rules are configured separately
|
||||
# !!!!! in old openwrt 21.x- with iptables firewall rules are configured separately
|
||||
# !!!!! in new openwrt >21.x with nftables firewall is configured here
|
||||
|
||||
PIDDIR=/var/run
|
||||
|
||||
@ -23,7 +43,6 @@ PIDDIR=/var/run
|
||||
NFQWS_OPT_BASE="--user=$WS_USER --dpi-desync-fwmark=$DESYNC_MARK"
|
||||
|
||||
[ -n "$TPWS" ] || TPWS="$ZAPRET_BASE/tpws/tpws"
|
||||
TPWS_LOCALHOST4=127.0.0.127
|
||||
HOSTLIST="$ZAPRET_BASE/ipset/zapret-hosts.txt.gz"
|
||||
[ -f "$HOSTLIST" ] || HOSTLIST="$ZAPRET_BASE/ipset/zapret-hosts.txt"
|
||||
[ -f "$HOSTLIST" ] || HOSTLIST="$ZAPRET_BASE/ipset/zapret-hosts-user.txt"
|
||||
@ -104,7 +123,8 @@ tpws_apply_socks_binds()
|
||||
}
|
||||
|
||||
|
||||
start_service() {
|
||||
start_daemons_procd()
|
||||
{
|
||||
local opt qn qns qn6 qns6
|
||||
|
||||
case "${MODE_OVERRIDE:-$MODE}" in
|
||||
@ -149,3 +169,61 @@ start_service() {
|
||||
|
||||
return 0
|
||||
}
|
||||
start_daemons()
|
||||
{
|
||||
rc_procd start_daemons_procd "$@"
|
||||
}
|
||||
stop_daemons()
|
||||
{
|
||||
procd_kill "$(basename ${basescript:-$initscript})" "$1"
|
||||
}
|
||||
restart_daemons()
|
||||
{
|
||||
stop_daemons
|
||||
start_daemons
|
||||
}
|
||||
|
||||
start_fw()
|
||||
{
|
||||
zapret_apply_firewall
|
||||
}
|
||||
stop_fw()
|
||||
{
|
||||
zapret_unapply_firewall
|
||||
}
|
||||
restart_fw()
|
||||
{
|
||||
stop_fw
|
||||
start_fw
|
||||
}
|
||||
reload_ifsets()
|
||||
{
|
||||
zapret_reload_ifsets
|
||||
}
|
||||
list_ifsets()
|
||||
{
|
||||
zapret_list_ifsets
|
||||
}
|
||||
list_table()
|
||||
{
|
||||
zapret_list_table
|
||||
}
|
||||
|
||||
start_service()
|
||||
{
|
||||
start_daemons_procd
|
||||
[ "$INIT_APPLY_FW" != "1" ] || {
|
||||
linux_fwtype
|
||||
openwrt_fw3_integration || start_fw
|
||||
}
|
||||
}
|
||||
|
||||
stop_service()
|
||||
{
|
||||
# this procedure is called from stop()
|
||||
# stop() already stop daemons
|
||||
[ "$INIT_APPLY_FW" != "1" ] || {
|
||||
linux_fwtype
|
||||
openwrt_fw3_integration || stop_fw
|
||||
}
|
||||
}
|
||||
|
@ -22,3 +22,13 @@ zapret_custom_firewall()
|
||||
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
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local opt
|
||||
|
||||
[ "$MODE_HTTP" = "1" ] && {
|
||||
@ -19,6 +21,8 @@ zapret_custom_daemons()
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f4 f6
|
||||
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
|
||||
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||
@ -37,3 +41,25 @@ zapret_custom_firewall()
|
||||
fw_nfqws_post $1 "$f4 $desync" "$f6 $desync" $QNUM
|
||||
}
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local f4 f6
|
||||
local first_packet_only="ct original packets 1-4"
|
||||
local desync="mark and $DESYNC_MARK == 0"
|
||||
|
||||
[ "$MODE_HTTP" = "1" ] && {
|
||||
f4="tcp dport 80"
|
||||
f6=$f4
|
||||
nft_filter_apply_ipset_target f4 f6
|
||||
nft_fw_tpws "$f4" "$f6" $TPPORT
|
||||
}
|
||||
|
||||
[ "$MODE_HTTPS" = "1" ] && {
|
||||
f4="tcp dport 443 $first_packet_only"
|
||||
f6=$f4
|
||||
nft_filter_apply_ipset_target f4 f6
|
||||
nft_fw_nfqws_post "$f4 $desync" "$f6 $desync" $QNUM
|
||||
}
|
||||
}
|
||||
|
34
init.d/sysv/custom.default
Normal file
34
init.d/sysv/custom.default
Normal file
@ -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
|
||||
}
|
@ -1,29 +1,16 @@
|
||||
# init script functions library for desktop linux systems
|
||||
|
||||
[ -n "$ZAPRET_BASE" ] || ZAPRET_BASE=/opt/zapret
|
||||
# SHOULD EDIT 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"
|
||||
|
||||
|
||||
exists()
|
||||
{
|
||||
which "$1" >/dev/null 2>/dev/null
|
||||
}
|
||||
existf()
|
||||
{
|
||||
type "$1" >/dev/null 2>/dev/null
|
||||
}
|
||||
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
|
||||
}
|
||||
user_exists()
|
||||
{
|
||||
id -u $1 >/dev/null 2>/dev/null
|
||||
@ -111,89 +98,12 @@ IPSET_EXCLUDE="-m set ! --match-set nozapret"
|
||||
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
|
||||
|
||||
|
||||
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" "$@"
|
||||
}
|
||||
|
||||
|
||||
ipt()
|
||||
{
|
||||
iptables -C "$@" >/dev/null 2>/dev/null || iptables -I "$@"
|
||||
}
|
||||
ipt_del()
|
||||
{
|
||||
iptables -C "$@" >/dev/null 2>/dev/null && iptables -D "$@"
|
||||
}
|
||||
ipt_add_del()
|
||||
{
|
||||
on_off_function ipt ipt_del "$@"
|
||||
}
|
||||
ipt6()
|
||||
{
|
||||
ip6tables -C "$@" >/dev/null 2>/dev/null || ip6tables -I "$@"
|
||||
}
|
||||
ipt6_del()
|
||||
{
|
||||
ip6tables -C "$@" >/dev/null 2>/dev/null && ip6tables -D "$@"
|
||||
}
|
||||
ipt6_add_del()
|
||||
{
|
||||
on_off_function ipt6 ipt6_del "$@"
|
||||
}
|
||||
|
||||
# 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
|
||||
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
|
||||
}
|
||||
get_ipv6_global()
|
||||
{
|
||||
# $1 - interface name. if empty - any interface
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
dnat6_target()
|
||||
{
|
||||
# $1 - lan network name
|
||||
@ -231,30 +141,51 @@ dnat6_target()
|
||||
[ -n "$2" ] && eval $2="$DNAT6_TARGET"
|
||||
}
|
||||
|
||||
set_route_localnet()
|
||||
{
|
||||
# $1 - 1 = enable, 0 = disable
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
local lan
|
||||
for lan in $IFACE_LAN ; do
|
||||
sysctl -q -w net.ipv4.conf.$lan.route_localnet=$1
|
||||
done
|
||||
}
|
||||
}
|
||||
prepare_route_localnet()
|
||||
{
|
||||
set_route_localnet 1
|
||||
}
|
||||
unprepare_route_localnet()
|
||||
{
|
||||
set_route_localnet 0
|
||||
}
|
||||
prepare_tpws_fw4()
|
||||
{
|
||||
# otherwise linux kernel will treat 127.0.0.0/8 as "martian" ip and refuse routing to it
|
||||
# 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
|
||||
[ -n "$IFACE_LAN" ] && {
|
||||
iptables -N input_rule_zapret 2>/dev/null
|
||||
iptables -F input_rule_zapret
|
||||
iptables -A input_rule_zapret -d $TPWS_LOCALHOST4 -j RETURN
|
||||
iptables -A input_rule_zapret -d 127.0.0.0/8 -j DROP
|
||||
for lan in $IFACE_LAN ; do
|
||||
ipt INPUT -i $lan -j input_rule_zapret
|
||||
sysctl -q -w net.ipv4.conf.$lan.route_localnet=1
|
||||
done
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
[ -n "$IFACE_LAN" ] && {
|
||||
local lan
|
||||
iptables -N input_rule_zapret 2>/dev/null
|
||||
iptables -F input_rule_zapret
|
||||
iptables -A input_rule_zapret -d $TPWS_LOCALHOST4 -j RETURN
|
||||
iptables -A input_rule_zapret -d 127.0.0.0/8 -j DROP
|
||||
ipt INPUT ! -i lo -j input_rule_zapret
|
||||
prepare_route_localnet
|
||||
}
|
||||
}
|
||||
}
|
||||
unprepare_tpws_fw4()
|
||||
{
|
||||
[ -n "$IFACE_LAN" ] && {
|
||||
for lan in $IFACE_LAN ; do
|
||||
ipt_del INPUT -i $lan -j input_rule_zapret
|
||||
sysctl -q -w net.ipv4.conf.$lan.route_localnet=0
|
||||
done
|
||||
iptables -F input_rule_zapret 2>/dev/null
|
||||
iptables -X input_rule_zapret 2>/dev/null
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
[ -n "$IFACE_LAN" ] && {
|
||||
local lan
|
||||
unprepare_route_localnet
|
||||
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()
|
||||
@ -263,7 +194,7 @@ unprepare_tpws_fw()
|
||||
}
|
||||
|
||||
|
||||
print_op()
|
||||
ipt_print_op()
|
||||
{
|
||||
if [ "$1" = "1" ]; then
|
||||
echo "Adding ip$4tables rule for $3 : $2"
|
||||
@ -279,7 +210,7 @@ fw_tpws4()
|
||||
# $3 - tpws port
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
[ "$1" = 1 ] && prepare_tpws_fw4
|
||||
print_op $1 "$2" "tpws (port $3)"
|
||||
ipt_print_op $1 "$2" "tpws (port $3)"
|
||||
for lan in $IFACE_LAN ; do
|
||||
ipt_add_del $1 PREROUTING -t nat -i $lan -p tcp $2 $IPSET_EXCLUDE dst -j DNAT --to $TPWS_LOCALHOST4:$3
|
||||
done
|
||||
@ -298,7 +229,7 @@ fw_tpws6()
|
||||
# $2 - iptable filter for ipv6
|
||||
# $3 - tpws port
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
print_op $1 "$2" "tpws (port $3)" 6
|
||||
ipt_print_op $1 "$2" "tpws (port $3)" 6
|
||||
local DNAT6
|
||||
for lan in $IFACE_LAN ; do
|
||||
dnat6_target $lan DNAT6
|
||||
@ -330,7 +261,7 @@ fw_nfqws_pre4()
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - queue number
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
print_op $1 "$2" "nfqws prerouting (qnum $3)"
|
||||
ipt_print_op $1 "$2" "nfqws prerouting (qnum $3)"
|
||||
if [ -n "$IFACE_WAN" ]; then
|
||||
for wan in $IFACE_WAN; do
|
||||
ipt_add_del $1 PREROUTING -t mangle -i $wan -p tcp $2 $IPSET_EXCLUDE src -j NFQUEUE --queue-num $3 --queue-bypass
|
||||
@ -346,7 +277,7 @@ fw_nfqws_pre6()
|
||||
# $2 - iptable filter for ipv6
|
||||
# $3 - queue number
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
print_op $1 "$2" "nfqws prerouting (qnum $3)" 6
|
||||
ipt_print_op $1 "$2" "nfqws prerouting (qnum $3)" 6
|
||||
if [ -n "$IFACE_WAN" ]; then
|
||||
for wan in $IFACE_WAN; do
|
||||
ipt6_add_del $1 PREROUTING -t mangle -i $wan -p tcp $2 $IPSET_EXCLUDE6 src -j NFQUEUE --queue-num $3 --queue-bypass
|
||||
@ -371,7 +302,7 @@ fw_nfqws_post4()
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - queue number
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
print_op $1 "$2" "nfqws postrouting (qnum $3)"
|
||||
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)"
|
||||
if [ -n "$IFACE_WAN" ]; then
|
||||
for wan in $IFACE_WAN; do
|
||||
ipt_add_del $1 POSTROUTING -t mangle -o $wan -p tcp $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass
|
||||
@ -387,7 +318,7 @@ fw_nfqws_post6()
|
||||
# $2 - iptable filter for ipv6
|
||||
# $3 - queue number
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
print_op $1 "$2" "nfqws postrouting (qnum $3)" 6
|
||||
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)" 6
|
||||
if [ -n "$IFACE_WAN" ]; then
|
||||
for wan in $IFACE_WAN; do
|
||||
ipt6_add_del $1 POSTROUTING -t mangle -o $wan -p tcp $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass
|
||||
@ -407,6 +338,11 @@ fw_nfqws_post()
|
||||
fw_nfqws_post6 $1 "$3" $4
|
||||
}
|
||||
|
||||
filter_apply_hostlist_target()
|
||||
{
|
||||
# $1 - var name of tpws or nfqws params
|
||||
[ "$MODE_FILTER" = "hostlist" ] && eval $1="\"\$$1 --hostlist=$HOSTLIST\""
|
||||
}
|
||||
|
||||
run_daemon()
|
||||
{
|
||||
@ -506,96 +442,6 @@ do_nfqws()
|
||||
do_daemon $1 $2 "$NFQWS" "$NFQWS_OPT_BASE $3"
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
filter_apply_hostlist_target()
|
||||
{
|
||||
# $1 - var name of tpws or nfqws params
|
||||
[ "$MODE_FILTER" = "hostlist" ] && eval $1="\"\$$1 --hostlist=$HOSTLIST\""
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
tpws_apply_socks_binds()
|
||||
{
|
||||
local o
|
||||
@ -613,95 +459,11 @@ tpws_apply_socks_binds()
|
||||
|
||||
create_ipset()
|
||||
{
|
||||
echo "Creating ipset"
|
||||
echo "Creating ip list table (firewall type $FWTYPE)"
|
||||
"$IPSET_CR" "$@"
|
||||
}
|
||||
|
||||
|
||||
|
||||
zapret_do_firewall()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
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_OVERRIDE:-$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)
|
||||
if [ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ]; then
|
||||
echo both http and https are disabled. not applying redirection.
|
||||
else
|
||||
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
|
||||
fi
|
||||
;;
|
||||
custom)
|
||||
existf zapret_custom_firewall && zapret_custom_firewall $1
|
||||
;;
|
||||
esac
|
||||
[ "$1" = 0 ] && unprepare_tpws_fw
|
||||
|
||||
return 0
|
||||
}
|
||||
zapret_apply_firewall()
|
||||
{
|
||||
zapret_do_firewall 1 "$@"
|
||||
}
|
||||
zapret_unapply_firewall()
|
||||
{
|
||||
zapret_do_firewall 0 "$@"
|
||||
}
|
||||
|
||||
zapret_do_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
@ -749,7 +511,6 @@ zapret_do_daemons()
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
zapret_run_daemons()
|
||||
{
|
||||
zapret_do_daemons 1 "$@"
|
||||
@ -758,3 +519,120 @@ zapret_stop_daemons()
|
||||
{
|
||||
zapret_do_daemons 0 "$@"
|
||||
}
|
||||
|
||||
|
||||
nft_fill_ifsets()
|
||||
{
|
||||
local script elements i ALLDEVS flags
|
||||
|
||||
# if large sets exist nft works very ineffectively
|
||||
# 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
|
||||
|
||||
script="flush set inet $ZAPRET_NFT_TABLE wanif
|
||||
flush set inet $ZAPRET_NFT_TABLE wanif6
|
||||
flush set inet $ZAPRET_NFT_TABLE lanif"
|
||||
|
||||
[ -n "$IFACE_LAN" ] && {
|
||||
make_comma_list elements $IFACE_LAN
|
||||
script="${script}
|
||||
add element inet $ZAPRET_NFT_TABLE lanif { $elements }"
|
||||
}
|
||||
[ -n "$IFACE_WAN" ] && {
|
||||
make_comma_list elements $IFACE_WAN
|
||||
script="${script}
|
||||
add element inet $ZAPRET_NFT_TABLE wanif { $elements }
|
||||
add element inet $ZAPRET_NFT_TABLE wanif6 { $elements }"
|
||||
}
|
||||
echo "$script" | nft -f -
|
||||
|
||||
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && {
|
||||
ALLDEVS=$(for i in $IFACE_LAN $IFACE_WAN; do echo $i; done | sort -u | xargs)
|
||||
[ -n "$ALLDEVS" ] && {
|
||||
[ "$FLOWOFFLOAD" = 'hardware' ] && nft_hw_offload_supported $ALLDEVS && flags=offload
|
||||
nft_create_or_update_flowtable "$flags" $ALLDEVS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nft_print_op()
|
||||
{
|
||||
echo "Adding nftables ipv$3 rule for $2 : $1"
|
||||
}
|
||||
|
||||
nft_fw_tpws4()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - tpws port
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
nft_print_op "$1" "tpws (port $2)" 4
|
||||
nft_add_rule dnat_output skuid != $WS_USER ${IFACE_WAN:+oifname @wanif }meta l4proto tcp $1 ip daddr != @nozapret dnat ip to $TPWS_LOCALHOST4:$2
|
||||
[ -n "$IFACE_LAN" ] && {
|
||||
prepare_route_localnet
|
||||
nft_add_rule dnat_pre iifname @lanif meta l4proto tcp $1 ip daddr != @nozapret dnat ip to $TPWS_LOCALHOST4:$2
|
||||
}
|
||||
}
|
||||
}
|
||||
nft_fw_tpws6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - tpws port
|
||||
|
||||
local lan DNAT6
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
nft_print_op "$1" "tpws (port $2)" 6
|
||||
nft_add_rule dnat_output skuid != $WS_USER ${IFACE_WAN:+oifname @wanif6 }meta l4proto tcp $1 ip6 daddr != @nozapret6 dnat ip6 to [::1]:$2
|
||||
for lan in $IFACE_LAN ; do
|
||||
dnat6_target $lan DNAT6
|
||||
[ "$DNAT6" != '-' ] && nft_add_rule dnat_pre iifname $lan 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 rule
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
nft_print_op "$1" "nfqws postrouting (qnum $2)" 4
|
||||
rule="${IFACE_WAN:+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 rule
|
||||
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
nft_print_op "$1" "nfqws postrouting (qnum $2)" 6
|
||||
rule="${IFACE_WAN:+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
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ DESC=anti-zapret
|
||||
do_start()
|
||||
{
|
||||
zapret_run_daemons
|
||||
[ "$INIT_APPLY_FW" != "1" ] || zapret_apply_firewall
|
||||
[ "$INIT_APPLY_FW" != "1" ] || { zapret_apply_firewall; }
|
||||
}
|
||||
do_stop()
|
||||
{
|
||||
@ -40,32 +40,42 @@ case "$1" in
|
||||
do_start
|
||||
;;
|
||||
|
||||
start-fw)
|
||||
start-fw|start_fw)
|
||||
zapret_apply_firewall
|
||||
;;
|
||||
stop-fw)
|
||||
stop-fw|stop_fw)
|
||||
zapret_unapply_firewall
|
||||
;;
|
||||
|
||||
restart-fw)
|
||||
restart-fw|restart_fw)
|
||||
zapret_unapply_firewall
|
||||
zapret_apply_firewall
|
||||
;;
|
||||
|
||||
start-daemons)
|
||||
start-daemons|start_daemons)
|
||||
zapret_run_daemons
|
||||
;;
|
||||
stop-daemons)
|
||||
stop-daemons|stop_daemons)
|
||||
zapret_stop_daemons
|
||||
;;
|
||||
restart-daemons)
|
||||
restart-daemons|restart_daemons)
|
||||
zapret_stop_daemons
|
||||
zapret_run_daemons
|
||||
;;
|
||||
|
||||
reload-ifsets|reload_ifsets)
|
||||
zapret_reload_ifsets
|
||||
;;
|
||||
list-ifsets|list_ifsets)
|
||||
zapret_list_ifsets
|
||||
;;
|
||||
list-table|list_table)
|
||||
zapret_list_table
|
||||
;;
|
||||
|
||||
*)
|
||||
N=/etc/init.d/$NAME
|
||||
echo "Usage: $N {start|stop|restart|start-fw|stop-fw|restart-fw|start-daemons|stop-daemons|restart-daemons}" >&2
|
||||
echo "Usage: $N {start|stop|restart|start-fw|stop-fw|restart-fw|start-daemons|stop-daemons|restart-daemons|reload-ifsets|list-ifsets|list-table}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
634
install_easy.sh
634
install_easy.sh
@ -9,64 +9,23 @@ ZAPRET_CONFIG="$EXEDIR/config"
|
||||
ZAPRET_BASE="$EXEDIR"
|
||||
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/elevate.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/common/dialog.sh"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
. "$ZAPRET_BASE/common/installer.sh"
|
||||
|
||||
# install target
|
||||
ZAPRET_TARGET=/opt/zapret
|
||||
|
||||
GET_LIST="$IPSET_DIR/get_config.sh"
|
||||
GET_LIST_PREFIX=/ipset/get_
|
||||
INIT_SCRIPT=/etc/init.d/zapret
|
||||
|
||||
[ -n "$TPPORT" ] || TPPORT=988
|
||||
|
||||
SYSTEMD_DIR=/lib/systemd
|
||||
[ -d "$SYSTEMD_DIR" ] || SYSTEMD_DIR=/usr/lib/systemd
|
||||
[ -d "$SYSTEMD_DIR" ] && SYSTEMD_SYSTEM_DIR="$SYSTEMD_DIR/system"
|
||||
|
||||
ECHON="echo -n"
|
||||
|
||||
exists()
|
||||
{
|
||||
which $1 >/dev/null 2>/dev/null
|
||||
}
|
||||
whichq()
|
||||
{
|
||||
which $1 2>/dev/null
|
||||
}
|
||||
|
||||
MD5=md5sum
|
||||
exists $MD5 || MD5=md5
|
||||
|
||||
contains()
|
||||
{
|
||||
# check if substring $2 contains in $1
|
||||
[ "${1#*$2}" != "$1" ]
|
||||
}
|
||||
|
||||
exitp()
|
||||
{
|
||||
local A
|
||||
|
||||
echo
|
||||
echo press enter to continue
|
||||
read A
|
||||
exit $1
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
sedi()
|
||||
{
|
||||
# MacOS doesnt support -i without parameter. busybox doesnt support -i with parameter.
|
||||
@ -78,58 +37,6 @@ sedi()
|
||||
fi
|
||||
}
|
||||
|
||||
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
|
||||
$ECHON "$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
|
||||
}
|
||||
|
||||
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" "$@"
|
||||
}
|
||||
|
||||
get_dir_inode()
|
||||
{
|
||||
local dir="$1"
|
||||
[ -L "$dir" ] && dir=$(readlink "$dir")
|
||||
ls -id "$dir" | awk '{print $1}'
|
||||
}
|
||||
|
||||
random()
|
||||
{
|
||||
# $1 - min, $2 - max
|
||||
@ -144,96 +51,6 @@ random()
|
||||
echo $(( ($r % ($2-$1+1)) + $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"
|
||||
}
|
||||
|
||||
check_system()
|
||||
{
|
||||
echo \* checking system
|
||||
|
||||
SYSTEM=""
|
||||
SYSTEMCTL=$(whichq systemctl)
|
||||
|
||||
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 exists rc-update && [ "$INIT" = "openrc-init" ]; then
|
||||
SYSTEM=openrc
|
||||
elif [ -f "/etc/openwrt_release" ] && exists opkg && exists uci && [ "$INIT" = "procd" ] ; then
|
||||
SYSTEM=openwrt
|
||||
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
|
||||
# MacOS echo from /bin/sh does not support -n
|
||||
ECHON=printf
|
||||
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
|
||||
}
|
||||
|
||||
check_readonly_system()
|
||||
{
|
||||
local RO
|
||||
@ -304,43 +121,6 @@ install_binaries()
|
||||
}
|
||||
}
|
||||
|
||||
find_str_in_list()
|
||||
{
|
||||
[ -n "$1" ] && {
|
||||
for v in $2; do
|
||||
[ "$v" = "$1" ] && return 0
|
||||
done
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
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
|
||||
$ECHON "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" ]
|
||||
}
|
||||
write_config_var()
|
||||
{
|
||||
# $1 - mode var
|
||||
@ -488,6 +268,17 @@ select_ipv6()
|
||||
fi
|
||||
[ "$old6" != "$DISABLE_IPV6" ] && write_config_var DISABLE_IPV6
|
||||
}
|
||||
select_fwtype()
|
||||
{
|
||||
echo
|
||||
[ $(get_ram_mb) -le 400 ] && {
|
||||
echo WARNING ! you are running a low RAM system
|
||||
echo WARNING ! nft requires lots of RAM to load huge ip sets, much more than ipsets require
|
||||
echo WARNING ! if you need large lists it may be necessary to fall back to iptables+ipset firewall
|
||||
}
|
||||
echo select firewall type :
|
||||
ask_list FWTYPE "iptables nftables" "$FWTYPE" && write_config_var FWTYPE
|
||||
}
|
||||
|
||||
ask_config()
|
||||
{
|
||||
@ -497,7 +288,7 @@ ask_config()
|
||||
|
||||
ask_config_offload()
|
||||
{
|
||||
is_flow_offload_avail && {
|
||||
[ "$FWTYPE" = nftables ] || is_ipt_flow_offload_avail && {
|
||||
echo
|
||||
echo flow offloading can greatly increase speed on slow devices and high speed links \(usually 150+ mbits\)
|
||||
echo unfortuantely its not compatible with most nfqws options. nfqws traffic must be exempted from flow offloading.
|
||||
@ -510,20 +301,6 @@ ask_config_offload()
|
||||
}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
ask_config_tmpdir()
|
||||
{
|
||||
# ask tmpdir change for low ram systems with enough free disk space
|
||||
@ -643,7 +420,7 @@ copy_openwrt()
|
||||
[ -d "$2" ] || mkdir -p "$2"
|
||||
|
||||
mkdir "$2/tpws" "$2/nfq" "$2/ip2net" "$2/mdig" "$2/binaries" "$2/binaries/$ARCH" "$2/init.d" "$2/tmp"
|
||||
cp -R "$1/ipset" "$2"
|
||||
cp -R "$1/common" "$1/ipset" "$2"
|
||||
cp -R "$1/init.d/openwrt" "$2/init.d"
|
||||
cp "$1/config" "$1/install_easy.sh" "$1/uninstall_easy.sh" "$1/install_bin.sh" "$1/blockcheck.sh" "$2"
|
||||
cp "$BINDIR/tpws" "$BINDIR/nfqws" "$BINDIR/ip2net" "$BINDIR/mdig" "$2/binaries/$ARCH"
|
||||
@ -718,19 +495,34 @@ check_prerequisites_linux()
|
||||
{
|
||||
echo \* checking prerequisites
|
||||
|
||||
if exists iptables && exists ip6tables ; then
|
||||
echo iptables present
|
||||
else
|
||||
# looks like it's a limited system. will not guess how to install base tools
|
||||
echo '! iptables/ip6tables NOT present. you must install them manually.'
|
||||
exitp 5
|
||||
fi
|
||||
local s cmd PKGS UTILS req="curl curl"
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
req="$req iptables iptables ip6tables iptables ipset ipset"
|
||||
;;
|
||||
nftables)
|
||||
req="$req nft nftables"
|
||||
;;
|
||||
esac
|
||||
|
||||
if exists ipset && exists curl ; then
|
||||
echo ipset and curl are present
|
||||
PKGS=$(for s in $req; do echo $s; done |
|
||||
while read cmd; do
|
||||
read pkg
|
||||
exists $cmd || echo $pkg
|
||||
done | sort -u | xargs)
|
||||
UTILS=$(for s in $req; do echo $s; done |
|
||||
while read cmd; do
|
||||
read pkg
|
||||
echo $cmd
|
||||
done | sort -u | xargs)
|
||||
|
||||
if [ -z "$PKGS" ] ; then
|
||||
echo required utilities exist : $UTILS
|
||||
else
|
||||
echo \* installing prerequisites
|
||||
|
||||
echo packages required : $PKGS
|
||||
|
||||
APTGET=$(whichq apt-get)
|
||||
YUM=$(whichq yum)
|
||||
PACMAN=$(whichq pacman)
|
||||
@ -739,39 +531,42 @@ check_prerequisites_linux()
|
||||
APK=$(whichq apk)
|
||||
if [ -x "$APTGET" ] ; then
|
||||
"$APTGET" update
|
||||
"$APTGET" install -y --no-install-recommends ipset curl dnsutils || {
|
||||
"$APTGET" install -y --no-install-recommends $PKGS dnsutils || {
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
elif [ -x "$YUM" ] ; then
|
||||
"$YUM" -y install curl ipset || {
|
||||
"$YUM" -y install $PKGS || {
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
elif [ -x "$PACMAN" ] ; then
|
||||
"$PACMAN" -Syy
|
||||
"$PACMAN" --noconfirm -S ipset curl || {
|
||||
"$PACMAN" --noconfirm -S $PKGS || {
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
elif [ -x "$ZYPPER" ] ; then
|
||||
"$ZYPPER" --non-interactive install ipset curl || {
|
||||
"$ZYPPER" --non-interactive install $PKGS || {
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
elif [ -x "$EOPKG" ] ; then
|
||||
"$EOPKG" -y install ipset curl || {
|
||||
"$EOPKG" -y install $PKGS || {
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
elif [ -x "$APK" ] ; then
|
||||
"$APK" add ipset curl || {
|
||||
"$APK" update
|
||||
# for alpine
|
||||
[ "$FWTYPE" = iptables ] && [ -n "$($APK list ip6tables)" ] && PKGS="$PKGS ip6tables"
|
||||
"$APK" add $PKGS || {
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
else
|
||||
echo supported package manager not found
|
||||
echo you must manually install : ipset curl
|
||||
echo you must manually install : $UTILS
|
||||
exitp 5
|
||||
fi
|
||||
fi
|
||||
@ -795,25 +590,6 @@ service_install_systemd()
|
||||
fi
|
||||
}
|
||||
|
||||
service_stop_systemd()
|
||||
{
|
||||
echo \* stopping zapret service
|
||||
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
"$SYSTEMCTL" disable zapret
|
||||
"$SYSTEMCTL" stop zapret
|
||||
}
|
||||
|
||||
service_start_systemd()
|
||||
{
|
||||
echo \* starting zapret service
|
||||
|
||||
"$SYSTEMCTL" start zapret || {
|
||||
echo could not start zapret service
|
||||
exitp 30
|
||||
}
|
||||
}
|
||||
|
||||
timer_install_systemd()
|
||||
{
|
||||
echo \* installing zapret-list-update timer
|
||||
@ -851,59 +627,6 @@ download_list()
|
||||
}
|
||||
}
|
||||
|
||||
end_with_newline()
|
||||
{
|
||||
local c=$(tail -c 1)
|
||||
[ "$c" = "" ]
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dnstest()
|
||||
{
|
||||
@ -930,10 +653,11 @@ install_systemd()
|
||||
require_root
|
||||
check_readonly_system
|
||||
check_location copy_all
|
||||
check_prerequisites_linux
|
||||
service_stop_systemd
|
||||
install_binaries
|
||||
check_dns
|
||||
service_stop_systemd
|
||||
select_fwtype
|
||||
check_prerequisites_linux
|
||||
install_binaries
|
||||
select_ipv6
|
||||
ask_config
|
||||
service_install_systemd
|
||||
@ -945,66 +669,19 @@ install_systemd()
|
||||
service_start_systemd
|
||||
}
|
||||
|
||||
|
||||
|
||||
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_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
|
||||
}
|
||||
}
|
||||
|
||||
_install_sysv()
|
||||
{
|
||||
# $1 - install init script
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
|
||||
|
||||
check_bins
|
||||
require_root
|
||||
check_readonly_system
|
||||
check_location copy_all
|
||||
check_prerequisites_linux
|
||||
service_stop_sysv
|
||||
install_binaries
|
||||
check_dns
|
||||
service_stop_sysv
|
||||
select_fwtype
|
||||
check_prerequisites_linux
|
||||
install_binaries
|
||||
select_ipv6
|
||||
ask_config
|
||||
$1
|
||||
@ -1017,11 +694,13 @@ _install_sysv()
|
||||
|
||||
install_sysv()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
|
||||
_install_sysv install_sysv_init
|
||||
}
|
||||
|
||||
install_openrc()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/openrc/zapret"
|
||||
_install_sysv install_openrc_init
|
||||
}
|
||||
|
||||
@ -1033,9 +712,10 @@ install_linux()
|
||||
check_bins
|
||||
require_root
|
||||
check_location copy_all
|
||||
check_dns
|
||||
select_fwtype
|
||||
check_prerequisites_linux
|
||||
install_binaries
|
||||
check_dns
|
||||
select_ipv6
|
||||
ask_config
|
||||
download_list
|
||||
@ -1051,45 +731,22 @@ install_linux()
|
||||
}
|
||||
|
||||
|
||||
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)" ]
|
||||
}
|
||||
check_packages_openwrt()
|
||||
{
|
||||
for pkg in $@; do
|
||||
check_package_openwrt $pkg || return
|
||||
done
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
check_prerequisites_openwrt()
|
||||
{
|
||||
echo \* checking prerequisites
|
||||
|
||||
local PKGS="iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ipset curl"
|
||||
[ "$DISABLE_IPV6" != "1" ] && PKGS="$PKGS ip6tables-mod-nat ip6tables-extra"
|
||||
local UPD=0
|
||||
local PKGS="curl" PKGS UPD=0
|
||||
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra"
|
||||
[ "$DISABLE_IPV6" != "1" ] && PKGS="$PKGS ip6tables-mod-nat ip6tables-extra"
|
||||
;;
|
||||
nftables)
|
||||
PKGS="nftables kmod-nft-nat kmod-nft-offload kmod-nft-queue"
|
||||
[ "$DISABLE_IPV6" != "1" ] && PKGS="$PKGS kmod-nft-nat6"
|
||||
;;
|
||||
esac
|
||||
|
||||
if check_packages_openwrt $PKGS ; then
|
||||
echo everything is present
|
||||
@ -1149,111 +806,11 @@ check_prerequisites_openwrt()
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
# free some RAM
|
||||
"$IPSET_DIR/create_ipset.sh" clear
|
||||
}
|
||||
|
||||
install_openwrt_iface_hook()
|
||||
{
|
||||
echo \* installing ifup hook
|
||||
|
||||
ln -fs "$OPENWRT_IFACE_HOOK" /etc/hotplug.d/iface
|
||||
}
|
||||
|
||||
is_flow_offload_avail()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
grep -q FLOWOFFLOAD /proc/net/ip$1_tables_targets
|
||||
}
|
||||
|
||||
deoffload_openwrt_firewall()
|
||||
{
|
||||
echo \* checking flow offloading
|
||||
|
||||
is_flow_offload_avail || {
|
||||
[ "$FWTYPE" = "nftables" ] || is_ipt_flow_offload_avail || {
|
||||
echo unavailable
|
||||
return
|
||||
}
|
||||
@ -1262,7 +819,7 @@ deoffload_openwrt_firewall()
|
||||
|
||||
if [ "$fo" = "1" ] ; then
|
||||
local mod=0
|
||||
$ECHON "system wide flow offloading detected. "
|
||||
printf "system wide flow offloading detected. "
|
||||
case $FLOWOFFLOAD in
|
||||
donttouch)
|
||||
if [ "$MODE" = "nfqws" ]; then
|
||||
@ -1303,23 +860,31 @@ install_openwrt()
|
||||
check_location copy_openwrt
|
||||
install_binaries
|
||||
check_dns
|
||||
|
||||
echo \* stopping current firewall rules/daemons
|
||||
"$INIT_SCRIPT_SRC" stop_fw
|
||||
"$INIT_SCRIPT_SRC" stop_daemons
|
||||
|
||||
select_fwtype
|
||||
select_ipv6
|
||||
check_prerequisites_openwrt
|
||||
ask_config
|
||||
ask_config_tmpdir
|
||||
ask_config_offload
|
||||
# stop and reinstall sysv init
|
||||
install_sysv_init
|
||||
# can be previous firewall preventing access
|
||||
remove_openwrt_firewall
|
||||
restart_openwrt_firewall
|
||||
# free some RAM
|
||||
clear_ipset
|
||||
download_list
|
||||
crontab_del_quiet
|
||||
# router system : works 24/7. night is the best time
|
||||
crontab_add 0 6
|
||||
cron_ensure_running
|
||||
service_start_sysv
|
||||
install_openwrt_iface_hook
|
||||
install_openwrt_firewall
|
||||
# in case of nftables or iptables without fw3 sysv init script also controls firewall
|
||||
[ -n "$OPENWRT_FW3" -a "$FWTYPE" = iptables ] && install_openwrt_firewall
|
||||
service_start_sysv
|
||||
deoffload_openwrt_firewall
|
||||
restart_openwrt_firewall
|
||||
}
|
||||
@ -1332,24 +897,7 @@ remove_pf_zapret_hooks()
|
||||
|
||||
pf_anchors_clear
|
||||
}
|
||||
service_install_macos()
|
||||
{
|
||||
echo \* installing zapret service
|
||||
|
||||
ln -fs /opt/zapret/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
|
||||
}
|
||||
macos_fw_reload_trigger_clear()
|
||||
{
|
||||
case "$MODE" in
|
||||
|
@ -2,16 +2,23 @@
|
||||
|
||||
# create ipset or ipfw table from resolved ip's
|
||||
# $1=no-update - do not update ipset, only create if its absent
|
||||
# $1=clear - clear ipset
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
. "$IPSET_DIR/../common/fwtype.sh"
|
||||
. "$IPSET_DIR/../common/nft.sh"
|
||||
|
||||
IPSET_CMD="$TMPDIR/ipset_cmd.txt"
|
||||
IPSET_SAVERAM_CHUNK_SIZE=20000
|
||||
IPSET_SAVERAM_MIN_FILESIZE=131072
|
||||
|
||||
NFSET_TEMP="$TMPDIR/nfset_temp.txt"
|
||||
NFSET_SAVERAM_MIN_FILESIZE=16384
|
||||
NFSET_SAVERAM_CHUNK_SIZE=1000
|
||||
|
||||
|
||||
while [ -n "$1" ]; do
|
||||
[ "$1" = "no-update" ] && NO_UPDATE=1
|
||||
@ -22,180 +29,266 @@ done
|
||||
|
||||
file_extract_lines()
|
||||
{
|
||||
# $1 - filename
|
||||
# $2 - from line (starting with 0)
|
||||
# $3 - line count
|
||||
# awk "{ err=1 } NR < $(($2+1)) { next } { print; err=0 } NR == $(($2+$3)) { exit err } END {exit err}" "$1"
|
||||
$AWK "NR < $(($2+1)) { next } { print } NR == $(($2+$3)) { exit }" "$1"
|
||||
# $1 - filename
|
||||
# $2 - from line (starting with 0)
|
||||
# $3 - line count
|
||||
# awk "{ err=1 } NR < $(($2+1)) { next } { print; err=0 } NR == $(($2+$3)) { exit err } END {exit err}" "$1"
|
||||
$AWK "NR < $(($2+1)) { next } { print } NR == $(($2+$3)) { exit }" "$1"
|
||||
}
|
||||
ipset_restore_chunked()
|
||||
{
|
||||
# $1 - filename
|
||||
# $2 - chunk size
|
||||
local pos lines
|
||||
[ -f "$1" ] || return
|
||||
lines=$(wc -l <"$1")
|
||||
pos=$lines
|
||||
while [ "$pos" -gt "0" ]; do
|
||||
pos=$((pos-$2))
|
||||
[ "$pos" -lt "0" ] && pos=0
|
||||
file_extract_lines "$1" $pos $2 | ipset -! restore
|
||||
sed -i "$(($pos+1)),$ d" "$1"
|
||||
done
|
||||
# $1 - filename
|
||||
# $2 - chunk size
|
||||
local pos lines
|
||||
[ -f "$1" ] || return
|
||||
lines=$(wc -l <"$1")
|
||||
pos=$lines
|
||||
while [ "$pos" -gt "0" ]; do
|
||||
pos=$((pos-$2))
|
||||
[ "$pos" -lt "0" ] && pos=0
|
||||
file_extract_lines "$1" $pos $2 | ipset -! restore
|
||||
sed -i "$(($pos+1)),$ d" "$1"
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
ipset_get_script()
|
||||
{
|
||||
# $1 - filename
|
||||
# $2 - ipset name
|
||||
zzcat "$1" | sort -u | sed -nEe "s/^.+$/add $2 &/p"
|
||||
# $1 - filename
|
||||
# $2 - ipset name
|
||||
zzcat "$1" | sort -u | sed -nEe "s/^.+$/add $2 &/p"
|
||||
}
|
||||
|
||||
ipset_restore()
|
||||
{
|
||||
# $1 - filename
|
||||
# $2 - ipset name
|
||||
# $3 - "6" = ipv6
|
||||
zzexist "$1" || return
|
||||
local fsize=$(zzsize "$1")
|
||||
local svram=0
|
||||
# do not saveram small files. file can also be gzipped
|
||||
[ "$SAVERAM" = "1" ] && [ "$fsize" -ge "$IPSET_SAVERAM_MIN_FILESIZE" ] && svram=1
|
||||
# $1 - ipset name
|
||||
# $2 - filename
|
||||
|
||||
local T="Adding to ipset $2 "
|
||||
[ "$svram" = "1" ] && T="$T (saveram)"
|
||||
T="$T : $f"
|
||||
echo $T
|
||||
zzexist "$2" || return
|
||||
local fsize=$(zzsize "$2")
|
||||
local svram=0
|
||||
# do not saveram small files. file can also be gzipped
|
||||
[ "$SAVERAM" = "1" ] && [ "$fsize" -ge "$IPSET_SAVERAM_MIN_FILESIZE" ] && svram=1
|
||||
|
||||
if [ "$svram" = "1" ]; then
|
||||
ipset_get_script "$1" "$2" >"$IPSET_CMD"
|
||||
ipset_restore_chunked "$IPSET_CMD" $IPSET_SAVERAM_CHUNK_SIZE
|
||||
rm -f "$IPSET_CMD"
|
||||
else
|
||||
ipset_get_script "$1" "$2" | ipset -! restore
|
||||
fi
|
||||
local T="Adding to ipset $1 "
|
||||
[ "$svram" = "1" ] && T="$T (saveram)"
|
||||
T="$T : $f"
|
||||
echo $T
|
||||
|
||||
if [ "$svram" = "1" ]; then
|
||||
ipset_get_script "$2" "$1" >"$IPSET_CMD"
|
||||
ipset_restore_chunked "$IPSET_CMD" $IPSET_SAVERAM_CHUNK_SIZE
|
||||
rm -f "$IPSET_CMD"
|
||||
else
|
||||
ipset_get_script "$2" "$1" | ipset -! restore
|
||||
fi
|
||||
}
|
||||
|
||||
create_ipset()
|
||||
{
|
||||
if [ "$1" -eq "6" ]; then
|
||||
FAMILY=inet6
|
||||
else
|
||||
FAMILY=inet
|
||||
fi
|
||||
ipset create $2 $3 $4 family $FAMILY 2>/dev/null || {
|
||||
[ "$NO_UPDATE" = "1" ] && return
|
||||
}
|
||||
ipset flush $2
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
for f in "$5" "$6" ; do
|
||||
ipset_restore "$f" "$2" $1
|
||||
done
|
||||
}
|
||||
return 0
|
||||
if [ "$1" -eq "6" ]; then
|
||||
FAMILY=inet6
|
||||
else
|
||||
FAMILY=inet
|
||||
fi
|
||||
ipset create $2 $3 $4 family $FAMILY 2>/dev/null || {
|
||||
[ "$NO_UPDATE" = "1" ] && return
|
||||
}
|
||||
ipset flush $2
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
for f in "$5" "$6" ; do
|
||||
ipset_restore "$2" "$f"
|
||||
done
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
nfset_get_script_multi()
|
||||
{
|
||||
# $1 - set name
|
||||
# $2,$3,... - filenames
|
||||
|
||||
# all in one shot. this allows to merge overlapping ranges
|
||||
# good but eats lots of RAM
|
||||
|
||||
local set=$1 nonempty N=1 f
|
||||
|
||||
shift
|
||||
|
||||
# first we need to make sure at least one element exists or nft will fail
|
||||
while :
|
||||
do
|
||||
eval f=\$$N
|
||||
[ -n "$f" ] || break
|
||||
nonempty=$(zzexist "$f" && zzcat "$f" | head -n 1)
|
||||
[ -n "$nonempty" ] && break
|
||||
N=$(($N+1))
|
||||
done
|
||||
|
||||
[ -n "$nonempty" ] && {
|
||||
echo "add element inet $ZAPRET_NFT_TABLE $set {"
|
||||
while [ -n "$1" ]; do
|
||||
zzexist "$1" && zzcat "$1" | sed -nEe "s/^.+$/&,/p"
|
||||
shift
|
||||
done
|
||||
echo "}"
|
||||
}
|
||||
}
|
||||
nfset_restore()
|
||||
{
|
||||
# $1 - set name
|
||||
# $2,$3,... - filenames
|
||||
|
||||
echo "Adding to nfset $1 : $2 $3 $4 $5"
|
||||
nfset_get_script_multi "$@" | nft -f -
|
||||
}
|
||||
create_nfset()
|
||||
{
|
||||
# $1 - family
|
||||
# $2 - set name
|
||||
# $3 - maxelem
|
||||
# $4,$5 - list files
|
||||
|
||||
local policy
|
||||
[ $SAVERAM = "1" ] && policy="policy memory;"
|
||||
nft_create_set $2 "type ipv${1}_addr; size $3; flags interval; auto-merge; $policy" || {
|
||||
[ "$NO_UPDATE" = "1" ] && return
|
||||
nft flush set inet $ZAPRET_NFT_TABLE $2
|
||||
}
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
nfset_restore $2 $4 $5
|
||||
return
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
add_ipfw_table()
|
||||
{
|
||||
# $1 - table name
|
||||
sed -nEe "s/^.+$/table $1 add &/p" | ipfw -q /dev/stdin
|
||||
# $1 - table name
|
||||
sed -nEe "s/^.+$/table $1 add &/p" | ipfw -q /dev/stdin
|
||||
}
|
||||
populate_ipfw_table()
|
||||
{
|
||||
# $1 - table name
|
||||
# $2 - ip list file
|
||||
zzexist "$2" || return
|
||||
zzcat "$2" | sort -u | add_ipfw_table $1
|
||||
# $1 - table name
|
||||
# $2 - ip list file
|
||||
zzexist "$2" || return
|
||||
zzcat "$2" | sort -u | add_ipfw_table $1
|
||||
}
|
||||
create_ipfw_table()
|
||||
{
|
||||
# $1 - table name
|
||||
# $2 - table options
|
||||
# $3,$4, ... - ip list files. can be v4,v6 or mixed
|
||||
# $1 - table name
|
||||
# $2 - table options
|
||||
# $3,$4, ... - ip list files. can be v4,v6 or mixed
|
||||
|
||||
local name=$1
|
||||
ipfw table "$name" create $2 2>/dev/null || {
|
||||
[ "$NO_UPDATE" = "1" ] && return
|
||||
}
|
||||
ipfw -q table $1 flush
|
||||
shift
|
||||
shift
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
while [ -n "$1" ]; do
|
||||
populate_ipfw_table $name "$1"
|
||||
shift
|
||||
done
|
||||
}
|
||||
local name=$1
|
||||
ipfw table "$name" create $2 2>/dev/null || {
|
||||
[ "$NO_UPDATE" = "1" ] && return
|
||||
}
|
||||
ipfw -q table $1 flush
|
||||
shift
|
||||
shift
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
while [ -n "$1" ]; do
|
||||
echo "Adding to ipfw table $name : $1"
|
||||
populate_ipfw_table $name "$1"
|
||||
shift
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
print_reloading_backend()
|
||||
{
|
||||
# $1 - backend name
|
||||
local s="reloading $1 backend"
|
||||
if [ "$NO_UPDATE" = 1 ]; then
|
||||
s="$s (no-update)"
|
||||
else
|
||||
s="$s (forced-update)"
|
||||
fi
|
||||
echo $s
|
||||
# $1 - backend name
|
||||
local s="reloading $1 backend"
|
||||
if [ "$NO_UPDATE" = 1 ]; then
|
||||
s="$s (no-update)"
|
||||
elif [ "$DO_CLEAR" = 1 ]; then
|
||||
s="$s (clear)"
|
||||
else
|
||||
s="$s (forced-update)"
|
||||
fi
|
||||
echo $s
|
||||
}
|
||||
|
||||
|
||||
oom_adjust_high
|
||||
get_fwtype
|
||||
|
||||
if [ -n "$LISTS_RELOAD" ] ; then
|
||||
if [ "$LISTS_RELOAD" = "-" ] ; then
|
||||
echo not reloading ip list backend
|
||||
true
|
||||
else
|
||||
echo executing custom ip list reload command : $LISTS_RELOAD
|
||||
$LISTS_RELOAD
|
||||
fi
|
||||
elif exists ipset; then
|
||||
# ipset seem to buffer the whole script to memory
|
||||
# on low RAM system this can cause oom errors
|
||||
# in SAVERAM mode we feed script lines in portions starting from the end, while truncating source file to free /tmp space
|
||||
# only /tmp is considered tmpfs. other locations mean tmpdir was redirected to a disk
|
||||
SAVERAM=0
|
||||
[ "$TMPDIR" = "/tmp" ] && {
|
||||
RAMSIZE=$($GREP MemTotal /proc/meminfo | $AWK '{print $2}')
|
||||
[ "$RAMSIZE" -lt "110000" ] && SAVERAM=1
|
||||
}
|
||||
print_reloading_backend ipset
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
create_ipset 4 $ZIPSET hash:net "$IPSET_OPT" "$ZIPLIST" "$ZIPLIST_USER"
|
||||
create_ipset 4 $ZIPSET_IPBAN hash:net "$IPSET_OPT" "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN"
|
||||
create_ipset 4 $ZIPSET_EXCLUDE hash:net "$IPSET_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
create_ipset 6 $ZIPSET6 hash:net "$IPSET_OPT" "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_ipset 6 $ZIPSET_IPBAN6 hash:net "$IPSET_OPT" "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_ipset 6 $ZIPSET_EXCLUDE6 hash:net "$IPSET_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE6"
|
||||
}
|
||||
true
|
||||
elif exists ipfw; then
|
||||
print_reloading_backend "ipfw table"
|
||||
if [ "$DISABLE_IPV4" != "1" ] && [ "$DISABLE_IPV6" != "1" ]; then
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT" "$ZIPLIST" "$ZIPLIST_USER" "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT" "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN" "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE" "$ZIPLIST_EXCLUDE6"
|
||||
elif [ "$DISABLE_IPV4" != "1" ]; then
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT" "$ZIPLIST" "$ZIPLIST_USER"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT" "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE"
|
||||
elif [ "$DISABLE_IPV6" != "1" ]; then
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT" "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT" "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE6"
|
||||
else
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE"
|
||||
fi
|
||||
true
|
||||
if [ "$LISTS_RELOAD" = "-" ] ; then
|
||||
echo not reloading ip list backend
|
||||
true
|
||||
else
|
||||
echo executing custom ip list reload command : $LISTS_RELOAD
|
||||
$LISTS_RELOAD
|
||||
fi
|
||||
else
|
||||
echo no supported ip list backend found
|
||||
true
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
# ipset seem to buffer the whole script to memory
|
||||
# on low RAM system this can cause oom errors
|
||||
# in SAVERAM mode we feed script lines in portions starting from the end, while truncating source file to free /tmp space
|
||||
# only /tmp is considered tmpfs. other locations mean tmpdir was redirected to a disk
|
||||
SAVERAM=0
|
||||
[ "$TMPDIR" = "/tmp" ] && {
|
||||
RAMSIZE=$($GREP MemTotal /proc/meminfo | $AWK '{print $2}')
|
||||
[ "$RAMSIZE" -lt "110000" ] && SAVERAM=1
|
||||
}
|
||||
print_reloading_backend ipset
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
create_ipset 4 $ZIPSET hash:net "$IPSET_OPT" "$ZIPLIST" "$ZIPLIST_USER"
|
||||
create_ipset 4 $ZIPSET_IPBAN hash:net "$IPSET_OPT" "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN"
|
||||
create_ipset 4 $ZIPSET_EXCLUDE hash:net "$IPSET_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
create_ipset 6 $ZIPSET6 hash:net "$IPSET_OPT" "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_ipset 6 $ZIPSET_IPBAN6 hash:net "$IPSET_OPT" "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_ipset 6 $ZIPSET_EXCLUDE6 hash:net "$IPSET_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE6"
|
||||
}
|
||||
true
|
||||
;;
|
||||
nftables)
|
||||
nft_create_table && {
|
||||
SAVERAM=0
|
||||
RAMSIZE=$($GREP MemTotal /proc/meminfo | $AWK '{print $2}')
|
||||
[ "$RAMSIZE" -lt "420000" ] && SAVERAM=1
|
||||
print_reloading_backend "nftables set"
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
create_nfset 4 $ZIPSET $SET_MAXELEM "$ZIPLIST" "$ZIPLIST_USER"
|
||||
create_nfset 4 $ZIPSET_IPBAN $SET_MAXELEM "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN"
|
||||
create_nfset 4 $ZIPSET_EXCLUDE $SET_MAXELEM_EXCLUDE "$ZIPLIST_EXCLUDE"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
create_nfset 6 $ZIPSET6 $SET_MAXELEM "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_nfset 6 $ZIPSET_IPBAN6 $SET_MAXELEM "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_nfset 6 $ZIPSET_EXCLUDE6 $SET_MAXELEM_EXCLUDE "$ZIPLIST_EXCLUDE6"
|
||||
}
|
||||
true
|
||||
}
|
||||
;;
|
||||
ipfw)
|
||||
print_reloading_backend "ipfw table"
|
||||
if [ "$DISABLE_IPV4" != "1" ] && [ "$DISABLE_IPV6" != "1" ]; then
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT" "$ZIPLIST" "$ZIPLIST_USER" "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT" "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN" "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE" "$ZIPLIST_EXCLUDE6"
|
||||
elif [ "$DISABLE_IPV4" != "1" ]; then
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT" "$ZIPLIST" "$ZIPLIST_USER"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT" "$ZIPLIST_IPBAN" "$ZIPLIST_USER_IPBAN"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE"
|
||||
elif [ "$DISABLE_IPV6" != "1" ]; then
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT" "$ZIPLIST6" "$ZIPLIST_USER6"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT" "$ZIPLIST_IPBAN6" "$ZIPLIST_USER_IPBAN6"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE" "$ZIPLIST_EXCLUDE6"
|
||||
else
|
||||
create_ipfw_table $ZIPSET "$IPFW_TABLE_OPT"
|
||||
create_ipfw_table $ZIPSET_IPBAN "$IPFW_TABLE_OPT"
|
||||
create_ipfw_table $ZIPSET_EXCLUDE "$IPFW_TABLE_OPT_EXCLUDE"
|
||||
fi
|
||||
true
|
||||
;;
|
||||
*)
|
||||
echo no supported ip list backend found
|
||||
true
|
||||
;;
|
||||
esac
|
||||
|
||||
fi
|
||||
|
24
ipset/def.sh
24
ipset/def.sh
@ -4,17 +4,19 @@
|
||||
}
|
||||
|
||||
. "$IPSET_DIR/../config"
|
||||
. "$IPSET_DIR/../common/base.sh"
|
||||
|
||||
[ -z "$TMPDIR" ] && TMPDIR=/tmp
|
||||
[ -z "$GZIP_LISTS" ] && GZIP_LISTS=1
|
||||
|
||||
[ -z "$IPSET_OPT" ] && IPSET_OPT="hashsize 262144 maxelem 2097152"
|
||||
[ -z "$IPSET_OPT_EXCLUDE" ] && IPSET_OPT_EXCLUDE="hashsize 1024 maxelem 65536"
|
||||
[ -z "$SET_MAXELEM" ] && SET_MAXELEM=262144
|
||||
[ -z "$IPSET_OPT" ] && IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
|
||||
[ -z "$SET_MAXELEM_EXCLUDE" ] && SET_MAXELEM_EXCLUDE=65536
|
||||
[ -z "$IPSET_OPT_EXCLUDE" ] && IPSET_OPT_EXCLUDE="hashsize 1024 maxelem $SET_MAXELEM_EXCLUDE"
|
||||
|
||||
[ -z "$IPFW_TABLE_OPT" ] && IPFW_TABLE_OPT="algo addr:radix"
|
||||
[ -z "$IPFW_TABLE_OPT_EXCLUDE" ] && IPFW_TABLE_OPT_EXCLUDE="algo addr:radix"
|
||||
|
||||
|
||||
ZIPSET=zapret
|
||||
ZIPSET6=zapret6
|
||||
ZIPSET_EXCLUDE=nozapret
|
||||
@ -43,10 +45,6 @@ ZUSERLIST_EXCLUDE="$IPSET_DIR/zapret-hosts-user-exclude.txt"
|
||||
[ -z "$MDIG_THREADS" ] && MDIG_THREADS=30
|
||||
|
||||
|
||||
exists()
|
||||
{
|
||||
which "$1" >/dev/null 2>/dev/null
|
||||
}
|
||||
|
||||
# BSD grep is damn slow with -f option. prefer GNU grep (ggrep) if present
|
||||
# MacoS in cron does not include /usr/local/bin to PATH
|
||||
@ -55,9 +53,9 @@ if [ -x /usr/local/bin/ggrep ] ; then
|
||||
elif [ -x /usr/local/bin/grep ] ; then
|
||||
GREP=/usr/local/bin/grep
|
||||
elif exists ggrep; then
|
||||
GREP=$(which ggrep)
|
||||
GREP=$(whichq ggrep)
|
||||
else
|
||||
GREP=$(which grep)
|
||||
GREP=$(whichq grep)
|
||||
fi
|
||||
|
||||
# GNU awk is faster
|
||||
@ -109,7 +107,7 @@ zzcat()
|
||||
{
|
||||
if [ -f "$1.gz" ]; then
|
||||
gunzip -c "$1.gz"
|
||||
else
|
||||
elif [ -f "$1" ]; then
|
||||
cat "$1"
|
||||
fi
|
||||
}
|
||||
@ -127,7 +125,11 @@ zzsize()
|
||||
{
|
||||
local f="$1"
|
||||
[ -f "$1.gz" ] && f="$1.gz"
|
||||
wc -c <"$f" | xargs
|
||||
if [ -f "$f" ]; then
|
||||
wc -c <"$f" | xargs
|
||||
else
|
||||
$ECHON -n 0
|
||||
fi
|
||||
}
|
||||
|
||||
digger()
|
||||
|
@ -5,271 +5,66 @@
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
IPSET_DIR="$EXEDIR/ipset"
|
||||
ZAPRET_CONFIG="$EXEDIR/config"
|
||||
ZAPRET_BASE="$EXEDIR"
|
||||
|
||||
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
|
||||
|
||||
exists()
|
||||
{
|
||||
which $1 >/dev/null 2>/dev/null
|
||||
}
|
||||
whichq()
|
||||
{
|
||||
which $1 2>/dev/null
|
||||
}
|
||||
|
||||
exitp()
|
||||
{
|
||||
echo
|
||||
echo press enter to continue
|
||||
read A
|
||||
exit $1
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
check_system()
|
||||
{
|
||||
echo \* checking system
|
||||
|
||||
SYSTEM=""
|
||||
SYSTEMCTL=$(whichq systemctl)
|
||||
|
||||
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 exists rc-update && [ "$INIT" = "openrc-init" ]; then
|
||||
SYSTEM=openrc
|
||||
elif [ -f "/etc/openwrt_release" ] && exists opkg && exists uci && [ "$INIT" = "procd" ] ; then
|
||||
SYSTEM=openwrt
|
||||
else
|
||||
echo system is not either systemd, openrc or openwrt based
|
||||
echo check readme.txt for manual setup info.
|
||||
SYSTEM=linux
|
||||
fi
|
||||
elif [ "$UNAME" = "Darwin" ]; then
|
||||
SYSTEM=macos
|
||||
# MacOS echo from /bin/sh does not support -n
|
||||
ECHON=printf
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/elevate.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
. "$ZAPRET_BASE/common/nft.sh"
|
||||
. "$ZAPRET_BASE/common/pf.sh"
|
||||
. "$ZAPRET_BASE/common/installer.sh"
|
||||
|
||||
remove_systemd()
|
||||
{
|
||||
clear_ipset
|
||||
service_stop_systemd
|
||||
service_remove_systemd
|
||||
timer_remove_systemd
|
||||
nft_del_table
|
||||
crontab_del
|
||||
}
|
||||
|
||||
|
||||
service_remove_sysv()
|
||||
{
|
||||
echo \* removing zapret service
|
||||
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
"$INIT_SCRIPT" disable
|
||||
"$INIT_SCRIPT" stop
|
||||
}
|
||||
rm -f "$INIT_SCRIPT"
|
||||
}
|
||||
|
||||
service_remove_openrc()
|
||||
{
|
||||
echo \* removing zapret service
|
||||
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
rc-update del zapret
|
||||
"$INIT_SCRIPT" stop
|
||||
}
|
||||
rm -f "$INIT_SCRIPT"
|
||||
}
|
||||
|
||||
|
||||
remove_openrc()
|
||||
{
|
||||
clear_ipset
|
||||
service_remove_openrc
|
||||
nft_del_table
|
||||
crontab_del
|
||||
}
|
||||
|
||||
remove_linux()
|
||||
{
|
||||
crontab_del
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
|
||||
|
||||
clear_ipset
|
||||
|
||||
echo \* executing sysv init stop
|
||||
"$INIT_SCRIPT_SRC" stop
|
||||
|
||||
nft_del_table
|
||||
crontab_del
|
||||
|
||||
echo
|
||||
echo '!!! WARNING. YOUR UNINSTALL IS INCOMPLETE !!!'
|
||||
echo 'you must manually remove zapret auto start from your system'
|
||||
}
|
||||
|
||||
|
||||
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"
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
# free some RAM
|
||||
"$IPSET_DIR/create_ipset.sh" clear
|
||||
}
|
||||
|
||||
restart_openwrt_firewall()
|
||||
{
|
||||
echo \* restarting firewall
|
||||
|
||||
fw3 -q restart || {
|
||||
echo could not restart firewall
|
||||
exitp 30
|
||||
}
|
||||
}
|
||||
|
||||
remove_openwrt_iface_hook()
|
||||
{
|
||||
echo \* removing ifup hook
|
||||
|
||||
rm -f /etc/hotplug.d/iface/??-zapret
|
||||
}
|
||||
|
||||
|
||||
|
||||
remove_openwrt()
|
||||
{
|
||||
OPENWRT_FW_INCLUDE=/etc/firewall.zapret
|
||||
|
||||
remove_openwrt_firewall
|
||||
restart_openwrt_firewall
|
||||
clear_ipset
|
||||
service_remove_sysv
|
||||
remove_openwrt_firewall
|
||||
remove_openwrt_iface_hook
|
||||
nft_del_table
|
||||
restart_openwrt_firewall
|
||||
crontab_del
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
remove_macos()
|
||||
{
|
||||
remove_macos_firewall
|
||||
|
Loading…
Reference in New Issue
Block a user