mirror of
https://github.com/bol-van/zapret2.git
synced 2026-03-14 14:21:41 +00:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f4bdd5eb4 | ||
|
|
0588240d8d | ||
|
|
b9e03ef71b | ||
|
|
9c0c7cfa8c | ||
|
|
807ad5953b | ||
|
|
ee031db3a1 | ||
|
|
93e4df72e5 | ||
|
|
e62d3919f4 | ||
|
|
63414f8608 | ||
|
|
18974e6c1f | ||
|
|
e61967ac2b | ||
|
|
6010307667 | ||
|
|
04ceb589e0 | ||
|
|
69b08f0a36 | ||
|
|
ec6021898b | ||
|
|
711eefed3e | ||
|
|
032b24f5b4 | ||
|
|
ef4b427836 | ||
|
|
a795b0f10c | ||
|
|
b56be286c9 | ||
|
|
63668fc84e | ||
|
|
837833feaf | ||
|
|
90afc96283 | ||
|
|
b0455bfee2 | ||
|
|
d279fab308 | ||
|
|
27695a892f | ||
|
|
151226dfc2 | ||
|
|
ef78f8d30c | ||
|
|
a01408a5c9 | ||
|
|
50ae834005 | ||
|
|
b21e85bfe9 |
@@ -275,44 +275,45 @@ mdig_cache()
|
||||
mdig_resolve()
|
||||
{
|
||||
# $1 - ip version 4/6
|
||||
# $2 - hostname, possibly with uri : rutracker.org/xxx/xxxx
|
||||
local hostvar cachevar countvar count ip n sdom
|
||||
# $2 - var to receive result
|
||||
# $3 - hostname, possibly with uri : rutracker.org/xxx/xxxx
|
||||
local hostvar cachevar countvar count n sdom
|
||||
|
||||
split_by_separator "$2" / sdom
|
||||
split_by_separator "$3" / sdom
|
||||
mdig_vars "$1" "$sdom"
|
||||
if [ -n "$count" ]; then
|
||||
n=$(random 0 $(($count-1)))
|
||||
eval ip=\$${cachevar}_$n
|
||||
echo $ip
|
||||
eval $2=\$${cachevar}_$n
|
||||
return 0
|
||||
else
|
||||
mdig_cache "$1" "$sdom" && mdig_resolve "$1" "$sdom"
|
||||
mdig_cache "$1" "$sdom" && mdig_resolve "$1" "$2" "$sdom"
|
||||
fi
|
||||
}
|
||||
mdig_resolve_all()
|
||||
{
|
||||
# $1 - ip version 4/6
|
||||
# $2 - hostname
|
||||
# $2 - var to receive result
|
||||
# $3 - hostname
|
||||
|
||||
local hostvar cachevar countvar count ip ips n sdom
|
||||
local hostvar cachevar countvar count ip__ ips__ n sdom
|
||||
|
||||
split_by_separator "$2" / sdom
|
||||
split_by_separator "$3" / sdom
|
||||
mdig_vars "$1" "$sdom"
|
||||
if [ -n "$count" ]; then
|
||||
n=0
|
||||
while [ "$n" -le $count ]; do
|
||||
eval ip=\$${cachevar}_$n
|
||||
if [ -n "$ips" ]; then
|
||||
ips="$ips $ip"
|
||||
eval ip__=\$${cachevar}_$n
|
||||
if [ -n "$ips__" ]; then
|
||||
ips__="$ips__ $ip__"
|
||||
else
|
||||
ips="$ip"
|
||||
ips__="$ip__"
|
||||
fi
|
||||
n=$(($n + 1))
|
||||
done
|
||||
echo "$ips"
|
||||
eval $2="\$ips__"
|
||||
return 0
|
||||
else
|
||||
mdig_cache "$1" "$sdom" && mdig_resolve_all "$1" "$sdom"
|
||||
mdig_cache "$1" "$sdom" && mdig_resolve_all "$1" "$2" "$sdom"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -640,7 +641,7 @@ curl_with_dig()
|
||||
local sdom suri ip
|
||||
|
||||
split_by_separator "$dom" / sdom suri
|
||||
ip=$(mdig_resolve $1 $sdom)
|
||||
mdig_resolve $1 ip $sdom
|
||||
shift ; shift ; shift
|
||||
if [ -n "$ip" ]; then
|
||||
curl_with_subst_ip "$sdom" "$port" "$ip" "$@"
|
||||
@@ -965,7 +966,7 @@ check_domain_port_block()
|
||||
echo
|
||||
echo \* port block tests ipv$IPV $1:$2
|
||||
if netcat_setup; then
|
||||
ips=$(mdig_resolve_all $IPV $1)
|
||||
mdig_resolve_all $IPV ips $1
|
||||
if [ -n "$ips" ]; then
|
||||
for ip in $ips; do
|
||||
if netcat_test $ip $2; then
|
||||
@@ -1254,7 +1255,7 @@ check_dpi_ip_block()
|
||||
|
||||
echo "> testing $UNBLOCKED_DOM on it's original ip"
|
||||
if curl_test $1 $UNBLOCKED_DOM; then
|
||||
unblocked_ip=$(mdig_resolve $IPV $UNBLOCKED_DOM)
|
||||
mdig_resolve $IPV unblocked_ip $UNBLOCKED_DOM
|
||||
[ -n "$unblocked_ip" ] || {
|
||||
echo $UNBLOCKED_DOM does not resolve. tests not possible.
|
||||
return 1
|
||||
@@ -1263,7 +1264,7 @@ check_dpi_ip_block()
|
||||
echo "> testing $blocked_dom on $unblocked_ip ($UNBLOCKED_DOM)"
|
||||
curl_test $1 $blocked_dom $unblocked_ip detail
|
||||
|
||||
blocked_ips=$(mdig_resolve_all $IPV $blocked_dom)
|
||||
mdig_resolve_all $IPV blocked_ips $blocked_dom
|
||||
for blocked_ip in $blocked_ips; do
|
||||
echo "> testing $UNBLOCKED_DOM on $blocked_ip ($blocked_dom)"
|
||||
curl_test $1 $UNBLOCKED_DOM $blocked_ip detail
|
||||
@@ -1314,6 +1315,8 @@ check_domain_http_tcp()
|
||||
# $3 - encrypted test : 0 = plain, 1 - encrypted with server reply risk, 2 - encrypted without server reply risk
|
||||
# $4 - domain
|
||||
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_tcp $2
|
||||
ws_kill
|
||||
@@ -1325,7 +1328,8 @@ check_domain_http_tcp()
|
||||
[ "$SKIP_PKTWS" = 1 ] || {
|
||||
echo
|
||||
echo preparing $PKTWSD redirection
|
||||
pktws_ipt_prepare_tcp $2 "$(mdig_resolve_all $IPV $4)"
|
||||
mdig_resolve_all $IPV ips $4
|
||||
pktws_ipt_prepare_tcp $2 "$ips"
|
||||
|
||||
pktws_check_domain_http_bypass $1 $3 $4
|
||||
|
||||
@@ -1339,6 +1343,8 @@ check_domain_http_udp()
|
||||
# $2 - port
|
||||
# $3 - domain
|
||||
|
||||
local ips
|
||||
|
||||
# in case was interrupted before
|
||||
pktws_ipt_unprepare_udp $2
|
||||
ws_kill
|
||||
@@ -1348,7 +1354,8 @@ check_domain_http_udp()
|
||||
[ "$SKIP_PKTWS" = 1 ] || {
|
||||
echo
|
||||
echo preparing $PKTWSD redirection
|
||||
pktws_ipt_prepare_udp $2 "$(mdig_resolve_all $IPV $3)"
|
||||
mdig_resolve_all $IPV ips $4
|
||||
pktws_ipt_prepare_udp $2 "$ips"
|
||||
|
||||
pktws_check_domain_http3_bypass $1 $3
|
||||
|
||||
|
||||
@@ -4,6 +4,10 @@ which()
|
||||
# 'command -v' replacement does not work exactly the same way. it outputs shell aliases if present
|
||||
# $1 - executable name
|
||||
local IFS=:
|
||||
[ "$1" != "${1#/}" ] && [ -x "$1" ] && {
|
||||
echo "$1"
|
||||
return 0
|
||||
}
|
||||
for p in $PATH; do
|
||||
[ -x "$p/$1" ] && {
|
||||
echo "$p/$1"
|
||||
@@ -416,10 +420,10 @@ alloc_num()
|
||||
|
||||
std_ports()
|
||||
{
|
||||
NFQWS2_PORTS_TCP_IPT=$(replace_char - : $NFQWS_PORTS_TCP)
|
||||
NFQWS2_PORTS_TCP_KEEPALIVE_IPT=$(replace_char - : $NFQWS_PORTS_TCP_KEEPALIVE)
|
||||
NFQWS2_PORTS_UDP_IPT=$(replace_char - : $NFQWS_PORTS_UDP)
|
||||
NFQWS2_PORTS_UDP_KEEPALIVE_IPT=$(replace_char - : $NFQWS_PORTS_UDP_KEEPALIVE)
|
||||
NFQWS2_PORTS_TCP_IPT=$(replace_char - : $NFQWS2_PORTS_TCP)
|
||||
NFQWS2_PORTS_TCP_KEEPALIVE_IPT=$(replace_char - : $NFQWS2_PORTS_TCP_KEEPALIVE)
|
||||
NFQWS2_PORTS_UDP_IPT=$(replace_char - : $NFQWS2_PORTS_UDP)
|
||||
NFQWS2_PORTS_UDP_KEEPALIVE_IPT=$(replace_char - : $NFQWS2_PORTS_UDP_KEEPALIVE)
|
||||
}
|
||||
|
||||
has_bad_ws_options()
|
||||
|
||||
34
common/custom.sh
Normal file
34
common/custom.sh
Normal file
@@ -0,0 +1,34 @@
|
||||
custom_runner()
|
||||
{
|
||||
# $1 - function name
|
||||
# $2+ - params
|
||||
|
||||
[ "$DISABLE_CUSTOM" = 1 ] && return 0
|
||||
|
||||
local n script FUNC=$1
|
||||
|
||||
shift
|
||||
|
||||
[ -d "$CUSTOM_DIR/custom.d" ] && {
|
||||
dir_is_not_empty "$CUSTOM_DIR/custom.d" && {
|
||||
for script in "$CUSTOM_DIR/custom.d/"*; do
|
||||
[ -f "$script" ] || continue
|
||||
unset -f $FUNC
|
||||
. "$script"
|
||||
existf $FUNC && $FUNC "$@"
|
||||
done
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
alloc_qnum()
|
||||
{
|
||||
# $1 - target var name
|
||||
alloc_num NUMPOOL_QNUM $1 65300 65399
|
||||
}
|
||||
alloc_dnum()
|
||||
{
|
||||
# alloc daemon number
|
||||
# $1 - target var name
|
||||
alloc_num NUMPOOL_DNUM $1 2000 2999
|
||||
}
|
||||
803
common/installer.sh
Normal file
803
common/installer.sh
Normal file
@@ -0,0 +1,803 @@
|
||||
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/zapret2
|
||||
|
||||
|
||||
exitp()
|
||||
{
|
||||
echo
|
||||
echo press enter to continue
|
||||
read A
|
||||
exit $1
|
||||
}
|
||||
|
||||
extract_var_def()
|
||||
{
|
||||
# $1 - var name
|
||||
# this sed script parses single or multi line shell var assignments with optional ' or " enclosure
|
||||
sed -n \
|
||||
"/^$1=\"/ {
|
||||
:s1
|
||||
/\".*\"/ {
|
||||
p
|
||||
b
|
||||
}
|
||||
N
|
||||
t c1
|
||||
b s1
|
||||
:c1
|
||||
}
|
||||
/^$1='/ {
|
||||
:s2
|
||||
/'.*'/ {
|
||||
p
|
||||
b
|
||||
}
|
||||
N
|
||||
t c2
|
||||
b s2
|
||||
:c2
|
||||
}
|
||||
/^$1=/p
|
||||
"
|
||||
}
|
||||
replace_var_def()
|
||||
{
|
||||
# $1 - var name
|
||||
# $2 - new val
|
||||
# $3 - conf file
|
||||
# this sed script replaces single or multi line shell var assignments with optional ' or " enclosure
|
||||
local repl
|
||||
if [ -z "$2" ]; then
|
||||
repl="#$1="
|
||||
elif contains "$2" " "; then
|
||||
repl="$1=\"$2\""
|
||||
else
|
||||
repl="$1=$2"
|
||||
fi
|
||||
local script=\
|
||||
"/^#*[[:space:]]*$1=\"/ {
|
||||
:s1
|
||||
/\".*\"/ {
|
||||
c\\
|
||||
$repl
|
||||
b
|
||||
}
|
||||
N
|
||||
t c1
|
||||
b s1
|
||||
:c1
|
||||
}
|
||||
/^#*[[:space:]]*$1='/ {
|
||||
:s2
|
||||
/'.*'/ {
|
||||
c\\
|
||||
$repl
|
||||
b
|
||||
}
|
||||
N
|
||||
t c2
|
||||
b s2
|
||||
:c2
|
||||
}
|
||||
/^#*[[:space:]]*$1=/c\\
|
||||
$repl"
|
||||
# there's incompatibility with -i option on BSD and busybox/GNU
|
||||
if [ "$UNAME" = "Linux" ]; then
|
||||
sed -i -e "$script" "$3"
|
||||
else
|
||||
sed -i '' -e "$script" "$3"
|
||||
fi
|
||||
}
|
||||
|
||||
parse_var_checked()
|
||||
{
|
||||
# $1 - file name
|
||||
# $2 - var name
|
||||
|
||||
local tmp="/tmp/zvar-pid-$$.sh"
|
||||
local v
|
||||
cat "$1" | extract_var_def "$2" >"$tmp"
|
||||
. "$tmp"
|
||||
rm -f "$tmp"
|
||||
eval v="\$$2"
|
||||
# trim
|
||||
v="$(echo "$v" | trim)"
|
||||
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 vim vi; do
|
||||
exists "$e" && {
|
||||
ed="$e"
|
||||
break
|
||||
}
|
||||
done
|
||||
}
|
||||
[ -n "$ed" ] && "$ed" "$1"
|
||||
}
|
||||
echo_var()
|
||||
{
|
||||
local v delimeter delims=
|
||||
eval v="\$$1"
|
||||
if find_str_in_list $1 "$EDITVAR_NEWLINE_VARS"; then
|
||||
echo "$1=\""
|
||||
for delimeter in $EDITVAR_NEWLINE_DELIMETERS; do
|
||||
delims="${delims:+$delims }-e "'"'"s/$delimeter/"'\\n'"$delimeter/g"'"'
|
||||
done
|
||||
echo "$v\"" | tr '\n' ' ' | tr -d '\r' | eval sed -e 's/^\ *//' -e 's/\ *$//' $delims
|
||||
else
|
||||
if contains "$v" " "; then
|
||||
echo $1=\"$v\"
|
||||
else
|
||||
echo $1=$v
|
||||
fi
|
||||
fi
|
||||
}
|
||||
edit_vars()
|
||||
{
|
||||
# $1,$2,... - var names
|
||||
local n=1 var tmp="/tmp/zvars-pid-$$.txt"
|
||||
rm -f "$tmp"
|
||||
while : ; do
|
||||
eval var="\${$n}"
|
||||
[ -n "$var" ] || break
|
||||
echo_var $var >> "$tmp"
|
||||
n=$(($n+1))
|
||||
done
|
||||
edit_file "$tmp" && parse_vars_checked "$tmp" "$@"
|
||||
rm -f "$tmp"
|
||||
}
|
||||
|
||||
list_vars()
|
||||
{
|
||||
while [ -n "$1" ] ; do
|
||||
echo_var $1
|
||||
shift
|
||||
done
|
||||
echo
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
# $1 - nonempty = do not fail on unknown rc system
|
||||
|
||||
echo \* checking system
|
||||
|
||||
SYSTEM=
|
||||
SUBSYS=
|
||||
SYSTEMCTL="$(whichq systemctl)"
|
||||
|
||||
get_fwtype
|
||||
OPENWRT_FW3=
|
||||
OPENWRT_FW4=
|
||||
|
||||
local info
|
||||
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
|
||||
[ -f "$EXEDIR/init.d/sysv/functions" ] && . "$EXEDIR/init.d/sysv/functions"
|
||||
elif [ -f "/etc/openwrt_release" ] && exists opkg || exists apk && exists uci && [ "$INIT" = "procd" ] ; then
|
||||
SYSTEM=openwrt
|
||||
OPENWRT_PACKAGER=opkg
|
||||
OPENWRT_PACKAGER_INSTALL="opkg install"
|
||||
OPENWRT_PACKAGER_UPDATE="opkg update"
|
||||
exists apk && {
|
||||
OPENWRT_PACKAGER=apk
|
||||
OPENWRT_PACKAGER_INSTALL="apk add"
|
||||
OPENWRT_PACKAGER_UPDATE=
|
||||
}
|
||||
info="package manager $OPENWRT_PACKAGER\n"
|
||||
if openwrt_fw3 ; then
|
||||
OPENWRT_FW3=1
|
||||
info="${info}firewall 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
|
||||
OPENWRT_FW4=1
|
||||
info="${info}firewall fw4. flow offloading requires nftables."
|
||||
fi
|
||||
[ -f "$EXEDIR/init.d/openwrt/functions" ] && . "$EXEDIR/init.d/openwrt/functions"
|
||||
elif openrc_test; then
|
||||
SYSTEM=openrc
|
||||
[ -f "$EXEDIR/init.d/sysv/functions" ] && . "$EXEDIR/init.d/sysv/functions"
|
||||
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.md for manual setup info.
|
||||
if [ -n "$1" ] || ask_yes_no N "do you want to continue"; then
|
||||
SYSTEM=linux
|
||||
else
|
||||
exitp 5
|
||||
fi
|
||||
[ -f "$EXEDIR/init.d/sysv/functions" ] && . "$EXEDIR/init.d/sysv/functions"
|
||||
fi
|
||||
linux_get_subsys
|
||||
else
|
||||
echo easy installer only supports Linux. check readme.md for supported systems and manual setup info.
|
||||
exitp 5
|
||||
fi
|
||||
echo system is based on $SYSTEM
|
||||
[ -n "$info" ] && printf "${info}\n"
|
||||
}
|
||||
|
||||
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 zapret2 service
|
||||
|
||||
"$SYSTEMCTL" start zapret2 || {
|
||||
echo could not start zapret2 service
|
||||
exitp 30
|
||||
}
|
||||
}
|
||||
service_stop_systemd()
|
||||
{
|
||||
echo \* stopping zapret2 service
|
||||
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
"$SYSTEMCTL" disable zapret2
|
||||
"$SYSTEMCTL" stop zapret2
|
||||
}
|
||||
service_remove_systemd()
|
||||
{
|
||||
echo \* removing zapret2 service
|
||||
|
||||
rm -f "$SYSTEMD_SYSTEM_DIR/zapret2.service"
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
}
|
||||
timer_remove_systemd()
|
||||
{
|
||||
echo \* removing zapret2-list-update timer
|
||||
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
"$SYSTEMCTL" disable zapret2-list-update.timer
|
||||
"$SYSTEMCTL" stop zapret2-list-update.timer
|
||||
rm -f "$SYSTEMD_SYSTEM_DIR/zapret2-list-update.service" "$SYSTEMD_SYSTEM_DIR/zapret2-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 zapret2
|
||||
}
|
||||
ln -fs "$INIT_SCRIPT_SRC" "$INIT_SCRIPT"
|
||||
[ "$1" != "0" ] && rc-update add zapret2
|
||||
}
|
||||
service_remove_openrc()
|
||||
{
|
||||
echo \* removing zapret2 service
|
||||
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
rc-update del zapret2
|
||||
"$INIT_SCRIPT" stop
|
||||
}
|
||||
rm -f "$INIT_SCRIPT"
|
||||
}
|
||||
service_start_sysv()
|
||||
{
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
echo \* starting zapret2 service
|
||||
"$INIT_SCRIPT" start || {
|
||||
echo could not start zapret2 service
|
||||
exitp 30
|
||||
}
|
||||
}
|
||||
}
|
||||
service_stop_sysv()
|
||||
{
|
||||
[ -x "$INIT_SCRIPT" ] && {
|
||||
echo \* stopping zapret2 service
|
||||
"$INIT_SCRIPT" stop
|
||||
}
|
||||
}
|
||||
service_remove_sysv()
|
||||
{
|
||||
echo \* removing zapret2 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 "$($OPENWRT_PACKAGER list $1)" ]
|
||||
}
|
||||
check_package_openwrt()
|
||||
{
|
||||
case $OPENWRT_PACKAGER in
|
||||
opkg)
|
||||
[ -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)" ]
|
||||
;;
|
||||
apk)
|
||||
apk info -e $1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
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/??-zapret2
|
||||
}
|
||||
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
|
||||
|
||||
local FW=fw4
|
||||
[ -n "$OPENWRT_FW3" ] && FW=fw3
|
||||
exists $FW && $FW -q restart || {
|
||||
echo could not restart firewall $FW
|
||||
}
|
||||
}
|
||||
remove_openwrt_firewall()
|
||||
{
|
||||
echo \* removing firewall script
|
||||
|
||||
openwrt_fw_section_del
|
||||
}
|
||||
|
||||
clear_ipset()
|
||||
{
|
||||
echo "* clearing ipset(s)"
|
||||
|
||||
# free some RAM
|
||||
"$IPSET_DIR/create_ipset.sh" clear
|
||||
}
|
||||
|
||||
|
||||
|
||||
write_config_var()
|
||||
{
|
||||
# $1 - mode var
|
||||
local M
|
||||
eval M="\$$1"
|
||||
# replace / => \/
|
||||
#M=${M//\//\\\/}
|
||||
M=$(echo $M | sed 's/\//\\\//g' | trim)
|
||||
grep -q "^[[:space:]]*$1=\|^#*[[:space:]]*$1=" "$ZAPRET_CONFIG" || {
|
||||
# var does not exist in config. add it
|
||||
echo $1= >>"$ZAPRET_CONFIG"
|
||||
}
|
||||
replace_var_def $1 "$M" "$ZAPRET_CONFIG"
|
||||
}
|
||||
|
||||
no_prereq_exit()
|
||||
{
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
check_prerequisites_linux()
|
||||
{
|
||||
echo \* checking prerequisites
|
||||
|
||||
local s cmd PKGS UTILS req="curl curl"
|
||||
local APTGET DNF YUM PACMAN ZYPPER EOPKG APK
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
req="$req iptables iptables ip6tables iptables ipset ipset"
|
||||
;;
|
||||
nftables)
|
||||
req="$req nft nftables"
|
||||
;;
|
||||
esac
|
||||
|
||||
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)
|
||||
DNF=$(whichq dnf)
|
||||
YUM=$(whichq yum)
|
||||
PACMAN=$(whichq pacman)
|
||||
ZYPPER=$(whichq zypper)
|
||||
EOPKG=$(whichq eopkg)
|
||||
APK=$(whichq apk)
|
||||
if [ -x "$APTGET" ] ; then
|
||||
"$APTGET" update
|
||||
"$APTGET" install -y --no-install-recommends $PKGS dnsutils || no_prereq_exit
|
||||
elif [ -x "$DNF" ] ; then
|
||||
"$DNF" -y install $PKGS || no_prereq_exit
|
||||
elif [ -x "$YUM" ] ; then
|
||||
"$YUM" -y install $PKGS || no_prereq_exit
|
||||
elif [ -x "$PACMAN" ] ; then
|
||||
"$PACMAN" -Syy
|
||||
"$PACMAN" --noconfirm -S $PKGS || no_prereq_exit
|
||||
elif [ -x "$ZYPPER" ] ; then
|
||||
"$ZYPPER" --non-interactive install $PKGS || no_prereq_exit
|
||||
elif [ -x "$EOPKG" ] ; then
|
||||
"$EOPKG" -y install $PKGS || no_prereq_exit
|
||||
elif [ -x "$APK" ] ; then
|
||||
"$APK" update
|
||||
# for alpine
|
||||
[ "$FWTYPE" = iptables ] && [ -n "$($APK list ip6tables)" ] && PKGS="$PKGS ip6tables"
|
||||
"$APK" add $PKGS || no_prereq_exit
|
||||
else
|
||||
echo supported package manager not found
|
||||
echo you must manually install : $UTILS
|
||||
exitp 5
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
removable_pkgs_openwrt()
|
||||
{
|
||||
local pkg PKGS2
|
||||
[ -n "$OPENWRT_FW4" ] && PKGS2="$PKGS2 iptables-zz-legacy iptables ip6tables-zz-legacy ip6tables"
|
||||
[ -n "$OPENWRT_FW3" ] && PKGS2="$PKGS2 nftables-json nftables-nojson nftables"
|
||||
PKGS=
|
||||
for pkg in $PKGS2; do
|
||||
check_package_exists_openwrt $pkg && PKGS="${PKGS:+$PKGS }$pkg"
|
||||
done
|
||||
PKGS="ipset iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32 ip6tables-mod-nat ip6tables-extra kmod-nft-queue gzip coreutils-sort coreutils-sleep curl $PKGS"
|
||||
}
|
||||
|
||||
openwrt_fix_broken_apk_uninstall_scripts()
|
||||
{
|
||||
# at least in early snapshots with apk removing gnu gzip, sort, ... does not restore links to busybox
|
||||
# system may become unusable
|
||||
exists sort || { echo fixing missing sort; ln -fs /bin/busybox /usr/bin/sort; }
|
||||
exists gzip || { echo fixing missing gzip; ln -fs /bin/busybox /bin/gzip; }
|
||||
exists sleep || { echo fixing missing sleep; ln -fs /bin/busybox /bin/sleep; }
|
||||
}
|
||||
|
||||
remove_extra_pkgs_openwrt()
|
||||
{
|
||||
local PKGS
|
||||
echo \* remove dependencies
|
||||
removable_pkgs_openwrt
|
||||
echo these packages may have been installed by install_easy.sh : $PKGS
|
||||
ask_yes_no N "do you want to remove them" && {
|
||||
case $OPENWRT_PACKAGER in
|
||||
opkg)
|
||||
opkg remove --autoremove $PKGS
|
||||
;;
|
||||
apk)
|
||||
apk del $PKGS
|
||||
openwrt_fix_broken_apk_uninstall_scripts
|
||||
;;
|
||||
esac
|
||||
}
|
||||
}
|
||||
|
||||
check_prerequisites_openwrt()
|
||||
{
|
||||
echo \* checking prerequisites
|
||||
|
||||
local PKGS="curl" UPD=0 local pkg_iptables
|
||||
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
pkg_iptables=iptables
|
||||
check_package_exists_openwrt iptables-zz-legacy && pkg_iptables=iptables-zz-legacy
|
||||
PKGS="$PKGS ipset $pkg_iptables iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra iptables-mod-u32"
|
||||
check_package_exists_openwrt ip6tables-zz-legacy && pkg_iptables=ip6tables-zz-legacy
|
||||
[ "$DISABLE_IPV6" = 1 ] || PKGS="$PKGS $pkg_iptables ip6tables-mod-nat ip6tables-extra"
|
||||
;;
|
||||
nftables)
|
||||
PKGS="$PKGS nftables kmod-nft-nat kmod-nft-offload kmod-nft-queue"
|
||||
;;
|
||||
esac
|
||||
|
||||
if check_packages_openwrt $PKGS ; then
|
||||
echo everything is present
|
||||
else
|
||||
echo \* installing prerequisites
|
||||
|
||||
$OPENWRT_PACKAGER_UPDATE
|
||||
UPD=1
|
||||
$OPENWRT_PACKAGER_INSTALL $PKGS || {
|
||||
echo could not install prerequisites
|
||||
exitp 6
|
||||
}
|
||||
fi
|
||||
|
||||
is_linked_to_busybox gzip && {
|
||||
echo
|
||||
echo your system uses default busybox gzip. its several times slower than GNU gzip.
|
||||
echo ip/host list scripts will run much faster with GNU gzip
|
||||
echo installer can install GNU gzip but it requires about 100 Kb space
|
||||
if ask_yes_no N "do you want to install GNU gzip"; then
|
||||
[ "$UPD" = "0" ] && {
|
||||
$OPENWRT_PACKAGER_UPDATE
|
||||
UPD=1
|
||||
}
|
||||
$OPENWRT_PACKAGER_INSTALL --force-overwrite gzip
|
||||
fi
|
||||
}
|
||||
is_linked_to_busybox sort && {
|
||||
echo
|
||||
echo your system uses default busybox sort. its much slower and consumes much more RAM than GNU sort
|
||||
echo ip/host list scripts will run much faster with GNU sort
|
||||
echo installer can install GNU sort but it requires about 100 Kb space
|
||||
if ask_yes_no N "do you want to install GNU sort"; then
|
||||
[ "$UPD" = "0" ] && {
|
||||
$OPENWRT_PACKAGER_UPDATE
|
||||
UPD=1
|
||||
}
|
||||
$OPENWRT_PACKAGER_INSTALL --force-overwrite coreutils-sort
|
||||
fi
|
||||
}
|
||||
[ "$FSLEEP" = 0 ] && is_linked_to_busybox sleep && {
|
||||
echo
|
||||
echo no methods of sub-second sleep were found.
|
||||
echo if you want to speed up blockcheck install coreutils-sleep. it requires about 40 Kb space
|
||||
if ask_yes_no N "do you want to install COREUTILS sleep"; then
|
||||
[ "$UPD" = "0" ] && {
|
||||
$OPENWRT_PACKAGER_UPDATE
|
||||
UPD=1
|
||||
}
|
||||
$OPENWRT_PACKAGER_INSTALL --force-overwrite coreutils-sleep
|
||||
fsleep_setup
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
select_ipv6()
|
||||
{
|
||||
local T=N
|
||||
|
||||
[ "$DISABLE_IPV6" != '1' ] && T=Y
|
||||
local old6=$DISABLE_IPV6
|
||||
echo
|
||||
if ask_yes_no $T "enable ipv6 support"; then
|
||||
DISABLE_IPV6=0
|
||||
else
|
||||
DISABLE_IPV6=1
|
||||
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
|
||||
}
|
||||
|
||||
dry_run_nfqws_()
|
||||
{
|
||||
local NFQWS="$ZAPRET_BASE/nfq2/nfqws2"
|
||||
echo verifying nfqws options
|
||||
"$NFQWS" --dry-run ${WS_USER:+--user=$WS_USER} "$@"
|
||||
}
|
||||
dry_run_nfqws()
|
||||
{
|
||||
[ "$NFQWS2_ENABLE" = 1 ] || return 0
|
||||
local opt="$NFQWS2_OPT" qn=${QNUM:-300}
|
||||
filter_apply_hostlist_target opt
|
||||
dry_run_nfqws_ --qnum=$qn $opt
|
||||
echo NOTE ! LUA code validity cannot be verified at this stage !
|
||||
}
|
||||
333
common/ipt.sh
Normal file
333
common/ipt.sh
Normal file
@@ -0,0 +1,333 @@
|
||||
std_ports
|
||||
ipt_connbytes="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes"
|
||||
IPSET_EXCLUDE="-m set ! --match-set nozapret"
|
||||
IPSET_EXCLUDE6="-m set ! --match-set nozapret6"
|
||||
IPBAN_EXCLUDE="-m set ! --match-set ipban"
|
||||
IPBAN_EXCLUDE6="-m set ! --match-set ipban6"
|
||||
|
||||
ipt()
|
||||
{
|
||||
iptables $FW_EXTRA_PRE -C "$@" $FW_EXTRA_POST >/dev/null 2>/dev/null || iptables $FW_EXTRA_PRE -I "$@" $FW_EXTRA_POST
|
||||
}
|
||||
ipta()
|
||||
{
|
||||
iptables $FW_EXTRA_PRE -C "$@" $FW_EXTRA_POST >/dev/null 2>/dev/null || iptables $FW_EXTRA_PRE -A "$@" $FW_EXTRA_POST
|
||||
}
|
||||
ipt_del()
|
||||
{
|
||||
iptables $FW_EXTRA_PRE -C "$@" $FW_EXTRA_POST >/dev/null 2>/dev/null && iptables $FW_EXTRA_PRE -D "$@" $FW_EXTRA_POST
|
||||
}
|
||||
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_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
|
||||
}
|
||||
|
||||
reverse_nfqws_rule_stream()
|
||||
{
|
||||
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' -e 's/--connbytes-dir=original/--connbytes-dir=reply/g' -e "s/-m mark ! --mark $DESYNC_MARK\/$DESYNC_MARK//g"
|
||||
}
|
||||
reverse_nfqws_rule()
|
||||
{
|
||||
echo "$@" | reverse_nfqws_rule_stream
|
||||
}
|
||||
|
||||
ipt_mark_filter()
|
||||
{
|
||||
[ -n "$FILTER_MARK" ] && echo "-m mark --mark $FILTER_MARK/$FILTER_MARK"
|
||||
}
|
||||
|
||||
ipt_print_op()
|
||||
{
|
||||
if [ "$1" = "1" ]; then
|
||||
echo "Inserting ip$4tables rule for $3 : $2"
|
||||
else
|
||||
echo "Deleting ip$4tables rule for $3 : $2"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
_fw_nfqws_post4()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - queue number
|
||||
# $4 - wan interface names space separated
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$2" ] || {
|
||||
local i
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)"
|
||||
|
||||
rule="$(ipt_mark_filter) -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE dst -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
ipt_add_del $1 POSTROUTING -t mangle -o $i $rule
|
||||
done
|
||||
else
|
||||
ipt_add_del $1 POSTROUTING -t mangle $rule
|
||||
fi
|
||||
}
|
||||
}
|
||||
_fw_nfqws_post6()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv6
|
||||
# $3 - queue number
|
||||
# $4 - wan interface names space separated
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$2" ] || {
|
||||
local i
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws postrouting (qnum $3)" 6
|
||||
|
||||
rule="$(ipt_mark_filter) -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK $2 $IPSET_EXCLUDE6 dst -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
ipt6_add_del $1 POSTROUTING -t mangle -o $i $rule
|
||||
done
|
||||
else
|
||||
ipt6_add_del $1 POSTROUTING -t mangle $rule
|
||||
fi
|
||||
}
|
||||
}
|
||||
fw_nfqws_post()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - iptable filter for ipv6
|
||||
# $4 - queue number
|
||||
fw_nfqws_post4 $1 "$2" $4
|
||||
fw_nfqws_post6 $1 "$3" $4
|
||||
}
|
||||
|
||||
_fw_nfqws_pre4()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - queue number
|
||||
# $4 - wan interface names space separated
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$2" ] || {
|
||||
local i
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws input+forward (qnum $3)"
|
||||
|
||||
rule="$2 $IPSET_EXCLUDE src -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
# iptables PREROUTING chain is before NAT. not possible to have DNATed ip's there
|
||||
ipt_add_del $1 INPUT -t mangle -i $i $rule
|
||||
ipt_add_del $1 FORWARD -t mangle -i $i $rule
|
||||
done
|
||||
else
|
||||
ipt_add_del $1 INPUT -t mangle $rule
|
||||
ipt_add_del $1 FORWARD -t mangle $rule
|
||||
fi
|
||||
}
|
||||
}
|
||||
_fw_nfqws_pre6()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv6
|
||||
# $3 - queue number
|
||||
# $4 - wan interface names space separated
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$2" ] || {
|
||||
local i
|
||||
|
||||
ipt_print_op $1 "$2" "nfqws input+forward (qnum $3)" 6
|
||||
|
||||
rule="$2 $IPSET_EXCLUDE6 src -j NFQUEUE --queue-num $3 --queue-bypass"
|
||||
if [ -n "$4" ] ; then
|
||||
for i in $4; do
|
||||
# iptables PREROUTING chain is before NAT. not possible to have DNATed ip's there
|
||||
ipt6_add_del $1 INPUT -t mangle -i $i $rule
|
||||
ipt6_add_del $1 FORWARD -t mangle -i $i $rule
|
||||
done
|
||||
else
|
||||
ipt6_add_del $1 INPUT -t mangle $rule
|
||||
ipt6_add_del $1 FORWARD -t mangle $rule
|
||||
fi
|
||||
}
|
||||
}
|
||||
fw_nfqws_pre()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - iptable filter for ipv4
|
||||
# $3 - iptable filter for ipv6
|
||||
# $4 - queue number
|
||||
fw_nfqws_pre4 $1 "$2" $4
|
||||
fw_nfqws_pre6 $1 "$3" $4
|
||||
}
|
||||
|
||||
|
||||
fw_reverse_nfqws_rule4()
|
||||
{
|
||||
fw_nfqws_pre4 $1 "$(reverse_nfqws_rule "$2")" $3
|
||||
}
|
||||
fw_reverse_nfqws_rule6()
|
||||
{
|
||||
fw_nfqws_pre6 $1 "$(reverse_nfqws_rule "$2")" $3
|
||||
}
|
||||
fw_reverse_nfqws_rule()
|
||||
{
|
||||
# ensure that modes relying on incoming traffic work
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - rule4
|
||||
# $3 - rule6
|
||||
# $4 - queue number
|
||||
fw_reverse_nfqws_rule4 $1 "$2" $4
|
||||
fw_reverse_nfqws_rule6 $1 "$3" $4
|
||||
}
|
||||
|
||||
ipt_first_packets()
|
||||
{
|
||||
# $1 - packet count
|
||||
[ -n "$1" -a "$1" != keepalive ] && [ "$1" -ge 1 ] && echo "$ipt_connbytes 1:$1"
|
||||
}
|
||||
ipt_do_nfqws_in_out()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - tcp,udp
|
||||
# $3 - ports
|
||||
# $4 - PKT_OUT. special value : 'keepalive'
|
||||
# $5 - PKT_IN
|
||||
local f4 f6 first_packets_only
|
||||
[ -n "$3" ] || return
|
||||
[ -n "$4" -a "$4" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(ipt_first_packets $4)"
|
||||
f4="-p $2 -m multiport --dports $3 $first_packets_only"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM
|
||||
}
|
||||
[ -n "$5" -a "$5" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(ipt_first_packets $5)"
|
||||
f4="-p $2 -m multiport --dports $3 $first_packets_only"
|
||||
f6=$f4
|
||||
filter_apply_ipset_target f4 f6
|
||||
fw_reverse_nfqws_rule $1 "$f4" "$f6" $QNUM
|
||||
}
|
||||
}
|
||||
|
||||
zapret_do_firewall_standard_nfqws_rules_ipt()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
[ "$NFQWS2_ENABLE" = 1 ] && {
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_IPT" "$NFQWS2_TCP_PKT_OUT" "$NFQWS2_TCP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 tcp "$NFQWS2_PORTS_TCP_KEEPALIVE_IPT" keepalive "$NFQWS2_TCP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_IPT" "$NFQWS2_UDP_PKT_OUT" "$NFQWS2_UDP_PKT_IN"
|
||||
ipt_do_nfqws_in_out $1 udp "$NFQWS2_PORTS_UDP_KEEPALIVE_IPT" keepalive "$NFQWS2_UDP_PKT_IN"
|
||||
}
|
||||
}
|
||||
zapret_do_firewall_standard_rules_ipt()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
zapret_do_firewall_standard_nfqws_rules_ipt $1
|
||||
}
|
||||
|
||||
zapret_do_firewall_rules_ipt()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
zapret_do_firewall_standard_rules_ipt $1
|
||||
custom_runner zapret_custom_firewall $1
|
||||
zapret_do_icmp_filter $1
|
||||
}
|
||||
|
||||
zapret_do_icmp_filter()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
local FW_EXTRA_PRE= FW_EXTRA_POST=
|
||||
|
||||
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
|
||||
[ "$DISABLE_IPV4" = 1 ] || {
|
||||
ipt_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
|
||||
ipt_add_del $1 INPUT -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
ipt_add_del $1 FORWARD -p icmp -m icmp --icmp-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
}
|
||||
[ "$DISABLE_IPV6" = 1 ] || {
|
||||
ipt6_add_del $1 POSTROUTING -t mangle -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CONNMARK --or-mark $DESYNC_MARK
|
||||
ipt6_add_del $1 INPUT -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
ipt6_add_del $1 FORWARD -p icmpv6 -m icmp6 --icmpv6-type time-exceeded -m connmark --mark $DESYNC_MARK/$DESYNC_MARK -j DROP
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zapret_do_firewall_ipt()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
|
||||
if [ "$1" = 1 ]; then
|
||||
echo Applying iptables
|
||||
else
|
||||
echo Clearing iptables
|
||||
fi
|
||||
|
||||
# always create ipsets. ip_exclude ipset is required
|
||||
[ "$1" = 1 ] && create_ipset no-update
|
||||
|
||||
zapret_do_firewall_rules_ipt "$@"
|
||||
|
||||
if [ "$1" = 1 ] ; then
|
||||
existf flow_offloading_exempt && flow_offloading_exempt
|
||||
else
|
||||
existf flow_offloading_unexempt && flow_offloading_unexempt
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
33
common/linux_daemons.sh
Normal file
33
common/linux_daemons.sh
Normal file
@@ -0,0 +1,33 @@
|
||||
standard_mode_nfqws()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
local opt
|
||||
[ "$NFQWS2_ENABLE" = 1 ] && check_bad_ws_options $1 "$NFQWS2_OPT" && {
|
||||
opt="--qnum=$QNUM $NFQWS2_OPT"
|
||||
filter_apply_hostlist_target opt
|
||||
do_nfqws $1 1 "$opt"
|
||||
}
|
||||
}
|
||||
standard_mode_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
standard_mode_nfqws $1
|
||||
}
|
||||
zapret_do_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
standard_mode_daemons $1
|
||||
custom_runner zapret_custom_daemons $1
|
||||
|
||||
return 0
|
||||
}
|
||||
zapret_run_daemons()
|
||||
{
|
||||
zapret_do_daemons 1 "$@"
|
||||
}
|
||||
zapret_stop_daemons()
|
||||
{
|
||||
zapret_do_daemons 0 "$@"
|
||||
}
|
||||
40
common/linux_fw.sh
Normal file
40
common/linux_fw.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
set_conntrack_liberal_mode()
|
||||
{
|
||||
[ -n "$SKIP_CONNTRACK_LIBERAL_MODE" ] || sysctl -w net.netfilter.nf_conntrack_tcp_be_liberal=$1
|
||||
}
|
||||
zapret_do_firewall()
|
||||
{
|
||||
linux_fwtype
|
||||
|
||||
[ "$1" = 1 -a -n "$INIT_FW_PRE_UP_HOOK" ] && $INIT_FW_PRE_UP_HOOK
|
||||
[ "$1" = 0 -a -n "$INIT_FW_PRE_DOWN_HOOK" ] && $INIT_FW_PRE_DOWN_HOOK
|
||||
|
||||
case "$FWTYPE" in
|
||||
iptables)
|
||||
zapret_do_firewall_ipt "$@"
|
||||
;;
|
||||
nftables)
|
||||
zapret_do_firewall_nft "$@"
|
||||
;;
|
||||
esac
|
||||
|
||||
# russian DPI sends RST,ACK with wrong ACK.
|
||||
# this is sometimes treated by conntrack as invalid and connbytes fw rules do not pass RST packet to nfqws.
|
||||
# switch on liberal mode on zapret firewall start and switch off on zapret firewall stop
|
||||
# this is only required for processing incoming bad RSTs. incoming rules are only applied in autohostlist mode
|
||||
# calling this after firewall because conntrack module can be not loaded before applying conntrack firewall rules
|
||||
[ "$MODE_FILTER" = "autohostlist" ] && set_conntrack_liberal_mode $1
|
||||
|
||||
[ "$1" = 1 -a -n "$INIT_FW_POST_UP_HOOK" ] && $INIT_FW_POST_UP_HOOK
|
||||
[ "$1" = 0 -a -n "$INIT_FW_POST_DOWN_HOOK" ] && $INIT_FW_POST_DOWN_HOOK
|
||||
|
||||
return 0
|
||||
}
|
||||
zapret_apply_firewall()
|
||||
{
|
||||
zapret_do_firewall 1 "$@"
|
||||
}
|
||||
zapret_unapply_firewall()
|
||||
{
|
||||
zapret_do_firewall 0 "$@"
|
||||
}
|
||||
24
common/linux_iphelper.sh
Normal file
24
common/linux_iphelper.sh
Normal file
@@ -0,0 +1,24 @@
|
||||
get_uevent_devtype()
|
||||
{
|
||||
local DEVTYPE INTERFACE IFINDEX OF_NAME OF_FULLNAME OF_COMPATIBLE_N
|
||||
[ -f "/sys/class/net/$1/uevent" ] && {
|
||||
. "/sys/class/net/$1/uevent"
|
||||
echo -n $DEVTYPE
|
||||
}
|
||||
}
|
||||
resolve_lower_devices()
|
||||
{
|
||||
# $1 - bridge interface name
|
||||
[ -d "/sys/class/net/$1" ] && {
|
||||
find "/sys/class/net/$1" -follow -maxdepth 1 -name "lower_*" |
|
||||
{
|
||||
local l lower lowers
|
||||
while read lower; do
|
||||
lower="$(basename "$lower")"
|
||||
l="${lower#lower_*}"
|
||||
[ "$l" != "$lower" ] && append_separator_list lowers ' ' '' "$l"
|
||||
done
|
||||
printf "$lowers"
|
||||
}
|
||||
}
|
||||
}
|
||||
55
common/list.sh
Normal file
55
common/list.sh
Normal file
@@ -0,0 +1,55 @@
|
||||
HOSTLIST_MARKER="<HOSTLIST>"
|
||||
HOSTLIST_NOAUTO_MARKER="<HOSTLIST_NOAUTO>"
|
||||
|
||||
find_hostlists()
|
||||
{
|
||||
[ -n "$HOSTLIST_BASE" ] || HOSTLIST_BASE="$ZAPRET_BASE/ipset"
|
||||
|
||||
HOSTLIST="$HOSTLIST_BASE/zapret-hosts.txt.gz"
|
||||
[ -f "$HOSTLIST" ] || HOSTLIST="$HOSTLIST_BASE/zapret-hosts.txt"
|
||||
[ -f "$HOSTLIST" ] || HOSTLIST=
|
||||
|
||||
HOSTLIST_USER="$HOSTLIST_BASE/zapret-hosts-user.txt.gz"
|
||||
[ -f "$HOSTLIST_USER" ] || HOSTLIST_USER="$HOSTLIST_BASE/zapret-hosts-user.txt"
|
||||
[ -f "$HOSTLIST_USER" ] || HOSTLIST_USER=
|
||||
|
||||
HOSTLIST_EXCLUDE="$HOSTLIST_BASE/zapret-hosts-user-exclude.txt.gz"
|
||||
[ -f "$HOSTLIST_EXCLUDE" ] || HOSTLIST_EXCLUDE="$HOSTLIST_BASE/zapret-hosts-user-exclude.txt"
|
||||
[ -f "$HOSTLIST_EXCLUDE" ] || HOSTLIST_EXCLUDE=
|
||||
|
||||
HOSTLIST_AUTO="$HOSTLIST_BASE/zapret-hosts-auto.txt"
|
||||
HOSTLIST_AUTO_DEBUGLOG="$HOSTLIST_BASE/zapret-hosts-auto-debug.log"
|
||||
}
|
||||
|
||||
filter_apply_hostlist_target()
|
||||
{
|
||||
# $1 - var name of nfqws params
|
||||
|
||||
local v parm parm1 parm2 parm3 parm4 parm5 parm6 parm7 parm8 parmNA
|
||||
eval v="\$$1"
|
||||
if contains "$v" "$HOSTLIST_MARKER" || contains "$v" "$HOSTLIST_NOAUTO_MARKER"; then
|
||||
[ "$MODE_FILTER" = hostlist -o "$MODE_FILTER" = autohostlist ] &&
|
||||
{
|
||||
find_hostlists
|
||||
parm1="${HOSTLIST_USER:+--hostlist=$HOSTLIST_USER}"
|
||||
parm2="${HOSTLIST:+--hostlist=$HOSTLIST}"
|
||||
parm3="${HOSTLIST_EXCLUDE:+--hostlist-exclude=$HOSTLIST_EXCLUDE}"
|
||||
[ "$MODE_FILTER" = autohostlist ] &&
|
||||
{
|
||||
parm4="--hostlist-auto=$HOSTLIST_AUTO"
|
||||
parm5="${AUTOHOSTLIST_FAIL_THRESHOLD:+--hostlist-auto-fail-threshold=$AUTOHOSTLIST_FAIL_THRESHOLD}"
|
||||
parm6="${AUTOHOSTLIST_FAIL_TIME:+--hostlist-auto-fail-time=$AUTOHOSTLIST_FAIL_TIME}"
|
||||
parm7="${AUTOHOSTLIST_RETRANS_THRESHOLD:+--hostlist-auto-retrans-threshold=$AUTOHOSTLIST_RETRANS_THRESHOLD}"
|
||||
parm8="--hostlist=$HOSTLIST_AUTO"
|
||||
}
|
||||
parm="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm4:+ $parm4}${parm5:+ $parm5}${parm6:+ $parm6}${parm7:+ $parm7}"
|
||||
parmNA="$parm1${parm2:+ $parm2}${parm3:+ $parm3}${parm8:+ $parm8}"
|
||||
}
|
||||
v="$(replace_str $HOSTLIST_NOAUTO_MARKER "$parmNA" "$v")"
|
||||
v="$(replace_str $HOSTLIST_MARKER "$parm" "$v")"
|
||||
[ "$MODE_FILTER" = autohostlist -a "$AUTOHOSTLIST_DEBUGLOG" = 1 ] && {
|
||||
v="$v --hostlist-auto-debug=$HOSTLIST_AUTO_DEBUGLOG"
|
||||
}
|
||||
eval $1=\""$v"\"
|
||||
fi
|
||||
}
|
||||
708
common/nft.sh
Normal file
708
common/nft.sh
Normal file
@@ -0,0 +1,708 @@
|
||||
[ -n "$ZAPRET_NFT_TABLE" ] || ZAPRET_NFT_TABLE=zapret2
|
||||
nft_connbytes="ct original packets"
|
||||
|
||||
# required for : nft -f -
|
||||
create_dev_stdin
|
||||
std_ports
|
||||
|
||||
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_flush_chain()
|
||||
{
|
||||
# $1 - set name
|
||||
nft flush chain 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_flush_chain()
|
||||
{
|
||||
# $1 - chain name
|
||||
nft flush chain inet $ZAPRET_NFT_TABLE $1
|
||||
}
|
||||
nft_chain_empty()
|
||||
{
|
||||
# $1 - chain name
|
||||
local count=$(nft list chain inet $ZAPRET_NFT_TABLE prerouting | wc -l)
|
||||
[ "$count" -le 4 ]
|
||||
}
|
||||
nft_rule_exists()
|
||||
{
|
||||
# $1 - chain
|
||||
# $2 - rule
|
||||
local rule
|
||||
# convert rule to nft output form
|
||||
nft_flush_chain ruletest
|
||||
nft_add_rule ruletest "$2"
|
||||
rule=$(nft list chain inet $ZAPRET_NFT_TABLE ruletest | sed -n '3s/\t//gp')
|
||||
nft_flush_chain ruletest
|
||||
local yes=$(nft list chain inet $ZAPRET_NFT_TABLE $1 | sed -n "s/^[\t]*$rule\$/1/p")
|
||||
[ -n "$yes" ]
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
# ipset checks cost some CPU. do not populate jump from hook until something is added to the chain
|
||||
nft_activate_chain4()
|
||||
{
|
||||
# $1 - chain name
|
||||
# $2 - saddr/daddr
|
||||
local b rule markf= act
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
eval act="\$${1}_act4"
|
||||
[ -n "$act" ] && return
|
||||
|
||||
b=0
|
||||
nft_wanif_filter_present && b=1
|
||||
|
||||
[ "$2" = daddr ] && markf=$(nft_mark_filter)
|
||||
rule="meta mark and $DESYNC_MARK == 0 $markf"
|
||||
[ $b = 1 ] && rule="$rule oifname @wanif"
|
||||
rule="$rule ip $2 != @nozapret jump $1"
|
||||
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
||||
|
||||
eval ${1}_act4=1
|
||||
}
|
||||
}
|
||||
nft_activate_chain6()
|
||||
{
|
||||
# $1 - chain name
|
||||
# $2 - saddr/daddr
|
||||
local b rule markf=
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
eval act="\$${1}_act6"
|
||||
[ -n "$act" ] && return
|
||||
|
||||
b=0
|
||||
nft_wanif6_filter_present && b=1
|
||||
|
||||
[ "$2" = daddr ] && markf=$(nft_mark_filter)
|
||||
rule="meta mark and $DESYNC_MARK == 0 $markf"
|
||||
[ $b = 1 ] && rule="$rule oifname @wanif6"
|
||||
rule="$rule ip6 $2 != @nozapret6 jump $1"
|
||||
nft_rule_exists ${1}_hook "$rule" || nft_add_rule ${1}_hook $rule
|
||||
|
||||
eval ${1}_act6=1
|
||||
}
|
||||
}
|
||||
|
||||
nft_create_chains()
|
||||
{
|
||||
cat << EOF | nft -f -
|
||||
add chain inet $ZAPRET_NFT_TABLE forward_hook { type filter hook forward priority -1; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE forward_hook
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE flow_offload
|
||||
flush chain inet $ZAPRET_NFT_TABLE flow_offload
|
||||
add chain inet $ZAPRET_NFT_TABLE flow_offload_zapret
|
||||
flush chain inet $ZAPRET_NFT_TABLE flow_offload_zapret
|
||||
add chain inet $ZAPRET_NFT_TABLE flow_offload_always
|
||||
flush chain inet $ZAPRET_NFT_TABLE flow_offload_always
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE postrouting
|
||||
flush chain inet $ZAPRET_NFT_TABLE postrouting
|
||||
add chain inet $ZAPRET_NFT_TABLE postrouting_hook { type filter hook postrouting priority 99; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE postrouting_hook
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE postnat
|
||||
flush chain inet $ZAPRET_NFT_TABLE postnat
|
||||
add chain inet $ZAPRET_NFT_TABLE postnat_hook { type filter hook postrouting priority 101; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE postnat_hook
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE prerouting_hook { type filter hook prerouting priority -99; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE prerouting_hook
|
||||
add chain inet $ZAPRET_NFT_TABLE prerouting
|
||||
flush chain inet $ZAPRET_NFT_TABLE prerouting
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE prenat_hook { type filter hook prerouting priority -101; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE prenat_hook
|
||||
add chain inet $ZAPRET_NFT_TABLE prenat
|
||||
flush chain inet $ZAPRET_NFT_TABLE prenat
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE predefrag { type filter hook output priority -401; }
|
||||
flush chain inet $ZAPRET_NFT_TABLE predefrag
|
||||
add chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
|
||||
flush chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag mark and $DESYNC_MARK !=0 jump predefrag_nfqws comment "nfqws generated : avoid drop by INVALID conntrack state"
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws mark and $DESYNC_MARK_POSTNAT !=0 notrack comment "postnat traffic"
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws ip frag-off & 0x1fff != 0 notrack comment "ipfrag"
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws exthdr frag exists notrack comment "ipfrag"
|
||||
add rule inet $ZAPRET_NFT_TABLE predefrag_nfqws tcp flags ! syn,rst,ack notrack comment "datanoack"
|
||||
|
||||
add set inet $ZAPRET_NFT_TABLE wanif { type ifname; }
|
||||
add set inet $ZAPRET_NFT_TABLE wanif6 { type ifname; }
|
||||
|
||||
add chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
flush chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
EOF
|
||||
[ -n "$POSTNAT_ALL" ] && {
|
||||
nft_flush_chain predefrag_nfqws
|
||||
nft_add_rule predefrag_nfqws notrack comment \"do not track nfqws generated packets to avoid nat tampering and defragmentation\"
|
||||
}
|
||||
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && {
|
||||
if is_postnat; then
|
||||
# can be caused by untracked nfqws-generated packets
|
||||
nft_add_rule prerouting_hook icmp type time-exceeded ct state invalid drop
|
||||
else
|
||||
nft_add_rule postrouting_hook mark and $DESYNC_MARK != 0 ct mark set ct mark or $DESYNC_MARK comment \"nfqws related : prevent ttl expired socket errors\"
|
||||
fi
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
nft_add_rule prerouting_hook icmp type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
|
||||
}
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
nft_add_rule prerouting_hook icmpv6 type time-exceeded ct mark and $DESYNC_MARK != 0 drop comment \"nfqws related : prevent ttl expired socket errors\"
|
||||
}
|
||||
}
|
||||
}
|
||||
nft_del_chains()
|
||||
{
|
||||
# do not delete all chains because of additional user hooks
|
||||
# they must be inside zapret table to use nfsets
|
||||
|
||||
cat << EOF | nft -f - 2>/dev/null
|
||||
delete chain inet $ZAPRET_NFT_TABLE postrouting_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE postnat_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE prerouting_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE prenat_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE forward_hook
|
||||
delete chain inet $ZAPRET_NFT_TABLE postrouting
|
||||
delete chain inet $ZAPRET_NFT_TABLE postnat
|
||||
delete chain inet $ZAPRET_NFT_TABLE prerouting
|
||||
delete chain inet $ZAPRET_NFT_TABLE prenat
|
||||
delete chain inet $ZAPRET_NFT_TABLE predefrag
|
||||
delete chain inet $ZAPRET_NFT_TABLE predefrag_nfqws
|
||||
delete chain inet $ZAPRET_NFT_TABLE flow_offload
|
||||
delete chain inet $ZAPRET_NFT_TABLE flow_offload_zapret
|
||||
delete chain inet $ZAPRET_NFT_TABLE flow_offload_always
|
||||
delete chain inet $ZAPRET_NFT_TABLE ruletest
|
||||
EOF
|
||||
# unfortunately this approach breaks udp desync of the connection initiating packet (new, first one)
|
||||
# delete chain inet $ZAPRET_NFT_TABLE predefrag
|
||||
}
|
||||
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 makelist
|
||||
shift
|
||||
# warning ! nft versions at least up to 1.0.1 do not allow interface names starting with digit in flowtable and do not allow quoting
|
||||
# warning ! openwrt fixes this in post-21.x snapshots with special nft patch
|
||||
# warning ! in traditional linux distros nft is unpatched and will fail with quoted interface definitions if unfixed
|
||||
[ -n "$flags" ] && flags="flags $flags;"
|
||||
for makelist in make_quoted_comma_list make_comma_list; do
|
||||
$makelist devices "$@"
|
||||
[ -n "$devices" ] && devices="devices={$devices};"
|
||||
nft add flowtable inet $ZAPRET_NFT_TABLE ft "{ hook ingress priority -1; $flags $devices }" && break
|
||||
done
|
||||
}
|
||||
nft_flush_ifsets()
|
||||
{
|
||||
cat << EOF | nft -f - 2>/dev/null
|
||||
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 wanif
|
||||
nft list set inet $ZAPRET_NFT_TABLE wanif6
|
||||
nft list flowtable inet $ZAPRET_NFT_TABLE ft 2>/dev/null
|
||||
}
|
||||
|
||||
nft_create_firewall()
|
||||
{
|
||||
nft_create_table
|
||||
nft_del_flowtable
|
||||
nft_create_chains
|
||||
}
|
||||
nft_del_firewall()
|
||||
{
|
||||
nft_del_chains
|
||||
nft_del_flowtable
|
||||
# leave ifsets and ipsets because they may be used by custom rules
|
||||
}
|
||||
|
||||
nft_add_rule()
|
||||
{
|
||||
# $1 - chain
|
||||
# $2,$3,... - rule(s)
|
||||
local chain="$1"
|
||||
shift
|
||||
nft add rule inet $ZAPRET_NFT_TABLE $chain $FW_EXTRA_PRE "$@"
|
||||
}
|
||||
nft_insert_rule()
|
||||
{
|
||||
# $1 - chain
|
||||
# $2,$3,... - rule(s)
|
||||
local chain="$1"
|
||||
shift
|
||||
nft insert rule inet $ZAPRET_NFT_TABLE $chain $FW_EXTRA_PRE "$@"
|
||||
}
|
||||
nft_add_set_element()
|
||||
{
|
||||
# $1 - set or map name
|
||||
# $2 - element
|
||||
[ -z "$2" ] || nft add element inet $ZAPRET_NFT_TABLE $1 "{ $2 }"
|
||||
}
|
||||
nft_add_set_elements()
|
||||
{
|
||||
# $1 - set or map name
|
||||
# $2,$3,... - element(s)
|
||||
local set="$1" elements
|
||||
shift
|
||||
make_comma_list elements "$@"
|
||||
nft_add_set_element $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_add_nfqws_flow_exempt_rule()
|
||||
{
|
||||
# $1 - rule (must be all filters in one var)
|
||||
local FW_EXTRA_POST= FW_EXTRA_PRE=
|
||||
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && \
|
||||
nft_insert_rule flow_offload_zapret "$1" return comment \"direct flow offloading exemption\"
|
||||
}
|
||||
|
||||
nft_apply_flow_offloading()
|
||||
{
|
||||
# ft can be absent
|
||||
nft_add_rule flow_offload_always flow add @ft 2>/dev/null && {
|
||||
nft_add_rule flow_offload_always counter comment \"if offload works here must not be too much traffic\"
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
# allow only outgoing packets to initiate flow offload
|
||||
nft_add_rule forward_hook meta l4proto "{ tcp, udp }" oifname @wanif jump flow_offload
|
||||
nft_add_rule flow_offload ip daddr == @nozapret goto flow_offload_always
|
||||
}
|
||||
[ "$DISABLE_IPV6" = "1" ] || {
|
||||
nft_add_rule forward_hook meta l4proto "{ tcp, udp }" oifname @wanif6 jump flow_offload
|
||||
nft_add_rule flow_offload ip6 daddr == @nozapret6 goto flow_offload_always
|
||||
}
|
||||
nft_add_rule flow_offload jump flow_offload_zapret
|
||||
|
||||
nft_add_rule flow_offload_zapret goto flow_offload_always
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
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_mark_filter()
|
||||
{
|
||||
[ -n "$FILTER_MARK" ] && echo "mark and $FILTER_MARK != 0"
|
||||
}
|
||||
|
||||
nft_script_add_ifset_element()
|
||||
{
|
||||
# $1 - set name
|
||||
# $2 - space separated elements
|
||||
local elements
|
||||
[ -n "$2" ] && {
|
||||
make_quoted_comma_list elements $2
|
||||
script="${script}
|
||||
add element inet $ZAPRET_NFT_TABLE $1 { $elements }"
|
||||
}
|
||||
}
|
||||
nft_fill_ifsets()
|
||||
{
|
||||
# $1 - space separated lan interface names
|
||||
# $2 - space separated wan interface names
|
||||
# $3 - space separated wan6 interface names
|
||||
# 4,5,6 is needed for pppoe+openwrt case. looks like it's not easily possible to resolve ethernet device behind a pppoe interface
|
||||
# $4 - space separated lan physical interface names (optional)
|
||||
# $5 - space separated wan physical interface names (optional)
|
||||
# $6 - space separated wan6 physical interface names (optional)
|
||||
|
||||
local script i j ALLDEVS devs b
|
||||
|
||||
# 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"
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || nft_script_add_ifset_element wanif "$2"
|
||||
[ "$DISABLE_IPV6" = "1" ] || nft_script_add_ifset_element wanif6 "$3"
|
||||
|
||||
echo "$script" | nft -f -
|
||||
|
||||
case "$FLOWOFFLOAD" in
|
||||
software)
|
||||
ALLDEVS=$(unique $1 $2 $3)
|
||||
# unbound flowtable may cause error in older nft version
|
||||
nft_create_or_update_flowtable '' $ALLDEVS 2>/dev/null
|
||||
;;
|
||||
hardware)
|
||||
ALLDEVS=$(unique $1 $2 $3 $4 $5 $6)
|
||||
# first create unbound flowtable. may cause error in older nft version
|
||||
nft_create_or_update_flowtable 'offload' 2>/dev/null
|
||||
# then add elements. some of them can cause error because unsupported
|
||||
for i in $ALLDEVS; do
|
||||
# bridge members must be added instead of the bridge itself
|
||||
# some members may not support hw offload. example : lan1 lan2 lan3 support, wlan0 wlan1 - not
|
||||
b=
|
||||
devs=$(resolve_lower_devices $i)
|
||||
for j in $devs; do
|
||||
# do not display error if addition failed
|
||||
nft_create_or_update_flowtable 'offload' $j && b=1 2>/dev/null
|
||||
done
|
||||
[ -n "$b" ] || {
|
||||
# no lower devices added ? try to add interface itself
|
||||
nft_create_or_update_flowtable 'offload' $i 2>/dev/null
|
||||
}
|
||||
done
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
nft_only()
|
||||
{
|
||||
linux_fwtype
|
||||
|
||||
case "$FWTYPE" in
|
||||
nftables)
|
||||
"$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
nft_print_op()
|
||||
{
|
||||
echo "Inserting nftables ipv$3 rule for $2 : $1"
|
||||
}
|
||||
is_postnat()
|
||||
{
|
||||
[ "$POSTNAT" != 0 -o "$POSTNAT_ALL" = 1 ]
|
||||
}
|
||||
get_postchain()
|
||||
{
|
||||
if is_postnat ; then
|
||||
echo -n postnat
|
||||
else
|
||||
echo -n postrouting
|
||||
fi
|
||||
}
|
||||
get_prechain()
|
||||
{
|
||||
if is_postnat ; then
|
||||
echo -n prenat
|
||||
else
|
||||
echo -n prerouting
|
||||
fi
|
||||
}
|
||||
_nft_fw_nfqws_post4()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - queue number
|
||||
# $3 - not-empty if wan interface filtering required
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_postchain) setmark
|
||||
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 4
|
||||
rule="meta nfproto ipv4 $filter"
|
||||
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
|
||||
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||
nft_activate_chain4 $chain daddr
|
||||
}
|
||||
}
|
||||
_nft_fw_nfqws_post6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - queue number
|
||||
# $3 - not-empty if wan interface filtering required
|
||||
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_postchain) setmark
|
||||
nft_print_op "$filter" "nfqws postrouting (qnum $port)" 6
|
||||
rule="meta nfproto ipv6 $filter"
|
||||
is_postnat && setmark="meta mark set meta mark or $DESYNC_MARK_POSTNAT"
|
||||
nft_insert_rule $chain $rule $setmark $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_add_nfqws_flow_exempt_rule "$rule"
|
||||
nft_activate_chain6 $chain daddr
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
_nft_fw_nfqws_pre4()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - queue number
|
||||
# $3 - not-empty if wan interface filtering required
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_prechain)
|
||||
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 4
|
||||
rule="meta nfproto ipv4 $filter"
|
||||
nft_insert_rule $chain $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_activate_chain4 $chain saddr
|
||||
}
|
||||
}
|
||||
_nft_fw_nfqws_pre6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - queue number
|
||||
# $3 - not-empty if wan interface filtering required
|
||||
|
||||
[ "$DISABLE_IPV6" = "1" -o -z "$1" ] || {
|
||||
local filter="$1" port="$2" rule chain=$(get_prechain)
|
||||
nft_print_op "$filter" "nfqws prerouting (qnum $port)" 6
|
||||
rule="meta nfproto ipv6 $filter"
|
||||
nft_insert_rule $chain $rule $CONNMARKER $FW_EXTRA_POST queue num $port bypass
|
||||
nft_activate_chain6 $chain saddr
|
||||
}
|
||||
}
|
||||
nft_fw_nfqws_pre()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - filter ipv6
|
||||
# $3 - queue number
|
||||
|
||||
nft_fw_nfqws_pre4 "$1" $3
|
||||
nft_fw_nfqws_pre6 "$2" $3
|
||||
}
|
||||
|
||||
nft_fw_nfqws_both4()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - queue number
|
||||
nft_fw_nfqws_post4 "$@"
|
||||
nft_fw_nfqws_pre4 "$(nft_reverse_nfqws_rule $1)" $2
|
||||
}
|
||||
nft_fw_nfqws_both6()
|
||||
{
|
||||
# $1 - filter ipv6
|
||||
# $2 - queue number
|
||||
nft_fw_nfqws_post6 "$@"
|
||||
nft_fw_nfqws_pre6 "$(nft_reverse_nfqws_rule $1)" $2
|
||||
}
|
||||
nft_fw_nfqws_both()
|
||||
{
|
||||
# $1 - filter ipv4
|
||||
# $2 - filter ipv6
|
||||
# $3 - queue number
|
||||
nft_fw_nfqws_both4 "$1" "$3"
|
||||
nft_fw_nfqws_both6 "$2" "$3"
|
||||
}
|
||||
|
||||
zapret_reload_ifsets()
|
||||
{
|
||||
nft_only nft_create_table ; nft_fill_ifsets_overload
|
||||
return 0
|
||||
}
|
||||
zapret_list_ifsets()
|
||||
{
|
||||
nft_only nft_list_ifsets
|
||||
return 0
|
||||
}
|
||||
zapret_list_table()
|
||||
{
|
||||
nft_only nft_list_table
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
nft_fw_reverse_nfqws_rule4()
|
||||
{
|
||||
nft_fw_nfqws_pre4 "$(nft_reverse_nfqws_rule "$1")" $2
|
||||
}
|
||||
nft_fw_reverse_nfqws_rule6()
|
||||
{
|
||||
nft_fw_nfqws_pre6 "$(nft_reverse_nfqws_rule "$1")" $2
|
||||
}
|
||||
nft_fw_reverse_nfqws_rule()
|
||||
{
|
||||
# ensure that modes relying on incoming traffic work
|
||||
# $1 - rule4
|
||||
# $2 - rule6
|
||||
# $3 - queue number
|
||||
nft_fw_reverse_nfqws_rule4 "$1" $3
|
||||
nft_fw_reverse_nfqws_rule6 "$2" $3
|
||||
}
|
||||
|
||||
nft_first_packets()
|
||||
{
|
||||
# $1 - packet count
|
||||
[ -n "$1" -a "$1" != keepalive ] && [ "$1" -ge 1 ] &&
|
||||
{
|
||||
if [ "$1" = 1 ] ; then
|
||||
echo "$nft_connbytes 1"
|
||||
else
|
||||
echo "$nft_connbytes 1-$1"
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
nft_apply_nfqws_in_out()
|
||||
{
|
||||
# $1 - tcp,udp
|
||||
# $2 - ports
|
||||
# $3 - PKT_OUT. special value : 'keepalive'
|
||||
# $4 - PKT_IN
|
||||
local f4 f6 first_packets_only
|
||||
[ -n "$2" ] || return
|
||||
[ -n "$3" -a "$3" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(nft_first_packets $3)"
|
||||
f4="$1 dport {$2} $first_packets_only"
|
||||
f6=$f4
|
||||
nft_filter_apply_ipset_target f4 f6
|
||||
nft_fw_nfqws_post "$f4" "$f6" $QNUM
|
||||
}
|
||||
[ -n "$4" -a "$4" != 0 ] &&
|
||||
{
|
||||
first_packets_only="$(nft_first_packets $4)"
|
||||
f4="$1 dport {$2} $first_packets_only"
|
||||
f6=$f4
|
||||
nft_filter_apply_ipset_target f4 f6
|
||||
nft_fw_reverse_nfqws_rule "$f4" "$f6" $QNUM
|
||||
}
|
||||
}
|
||||
|
||||
zapret_apply_firewall_standard_nfqws_rules_nft()
|
||||
{
|
||||
[ "$NFQWS2_ENABLE" = 1 ] && {
|
||||
nft_apply_nfqws_in_out tcp "$NFQWS2_PORTS_TCP" "$NFQWS2_TCP_PKT_OUT" "$NFQWS2_TCP_PKT_IN"
|
||||
nft_apply_nfqws_in_out tcp "$NFQWS2_PORTS_TCP_KEEPALIVE" keepalive "$NFQWS2_TCP_PKT_IN"
|
||||
nft_apply_nfqws_in_out udp "$NFQWS2_PORTS_UDP" "$NFQWS2_UDP_PKT_OUT" "$NFQWS2_UDP_PKT_IN"
|
||||
nft_apply_nfqws_in_out udp "$NFQWS2_PORTS_UDP_KEEPALIVE" keepalive "$NFQWS2_UDP_PKT_IN"
|
||||
}
|
||||
}
|
||||
zapret_apply_firewall_standard_rules_nft()
|
||||
{
|
||||
zapret_apply_firewall_standard_nfqws_rules_nft
|
||||
}
|
||||
|
||||
zapret_apply_firewall_rules_nft()
|
||||
{
|
||||
zapret_apply_firewall_standard_rules_nft
|
||||
custom_runner zapret_custom_firewall_nft
|
||||
}
|
||||
|
||||
zapret_apply_firewall_nft()
|
||||
{
|
||||
echo Applying nftables
|
||||
|
||||
create_ipset no-update
|
||||
nft_create_firewall
|
||||
nft_fill_ifsets_overload
|
||||
|
||||
zapret_apply_firewall_rules_nft
|
||||
|
||||
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && nft_apply_flow_offloading
|
||||
|
||||
return 0
|
||||
}
|
||||
zapret_unapply_firewall_nft()
|
||||
{
|
||||
echo Clearing nftables
|
||||
|
||||
nft_del_firewall
|
||||
custom_runner zapret_custom_firewall_nft_flush
|
||||
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
|
||||
}
|
||||
|
||||
# ctmark is not available in POSTNAT mode
|
||||
CONNMARKER=
|
||||
[ "$FILTER_TTL_EXPIRED_ICMP" = 1 ] && is_postnat && CONNMARKER="ct mark set ct mark or $DESYNC_MARK"
|
||||
@@ -2,7 +2,7 @@
|
||||
# change values here
|
||||
|
||||
# can help in case /tmp has not enough space
|
||||
#TMPDIR=/opt/zapret/tmp
|
||||
#TMPDIR=/opt/zapret2/tmp
|
||||
|
||||
# redefine user for zapret daemons. required on Keenetic
|
||||
#WS_USER=nobody
|
||||
@@ -20,7 +20,7 @@ SET_MAXELEM=522288
|
||||
# too large hashsize will waste lots of RAM
|
||||
IPSET_OPT="hashsize 262144 maxelem $SET_MAXELEM"
|
||||
# dynamically generate additional ip. $1 = ipset/nfset/table name
|
||||
#IPSET_HOOK="/etc/zapret.ipset.hook"
|
||||
#IPSET_HOOK="/etc/zapret2.ipset.hook"
|
||||
|
||||
# options for ip2net. "-4" or "-6" auto added by ipset create script
|
||||
IP2NET_OPT4="--prefix-length=22-30 --v4-threshold=3/4"
|
||||
@@ -75,9 +75,9 @@ NFQWS2_UDP_PKT_IN=0
|
||||
# hostlist markers are replaced to empty string if MODE_FILTER does not satisfy
|
||||
# <HOSTLIST_NOAUTO> appends ipset/zapret-hosts-auto.txt as normal list
|
||||
NFQWS2_OPT="
|
||||
--filter-tcp=80 --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_md5 --lua-desync=multisplit:pos=method+2 <HOSTLIST> --new
|
||||
--filter-tcp=443 --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_md5:tcp_seq=-10000 --lua-desync=multidisorder:pos=1,midsld <HOSTLIST> --new
|
||||
--filter-udp=443 --payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=6 <HOSTLIST_NOAUTO> --new
|
||||
--filter-tcp=80 --filter-l7=http <HOSTLIST> --payload=http_req --lua-desync=fake:blob=fake_default_http:tcp_md5 --lua-desync=multisplit:pos=method+2 --new
|
||||
--filter-tcp=443 --filter-l7=tls <HOSTLIST> --payload=tls_client_hello --lua-desync=fake:blob=fake_default_tls:tcp_md5:tcp_seq=-10000 --lua-desync=multidisorder:pos=1,midsld --new
|
||||
--filter-udp=443 --filter-l7=quic <HOSTLIST_NOAUTO> --payload=quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=6
|
||||
"
|
||||
|
||||
# none,ipset,hostlist,autohostlist
|
||||
@@ -86,12 +86,14 @@ MODE_FILTER=none
|
||||
# donttouch,none,software,hardware
|
||||
FLOWOFFLOAD=donttouch
|
||||
|
||||
# openwrt: specify networks to be treated as LAN. default is "lan"
|
||||
#OPENWRT_LAN="lan lan2 lan3"
|
||||
# openwrt: specify networks to be treated as WAN. default wans are interfaces with default route
|
||||
#OPENWRT_WAN4="wan vpn"
|
||||
#OPENWRT_WAN6="wan6 vpn6"
|
||||
|
||||
# for routers based on desktop linux and macos. has no effect in openwrt.
|
||||
# optionally CHOOSE WAN/WAN6 NETWORK INTERFACES
|
||||
# CHOOSE LAN and optinally WAN/WAN6 NETWORK INTERFACES
|
||||
# or leave them commented if its not router
|
||||
# it's possible to specify multiple interfaces like this : IFACE_WAN="eth0 eth1 eth2"
|
||||
# if IFACE_WAN6 is not defined it take the value of IFACE_WAN
|
||||
@@ -102,10 +104,10 @@ FLOWOFFLOAD=donttouch
|
||||
# not applicable to openwrt with firewall3+iptables
|
||||
INIT_APPLY_FW=1
|
||||
# firewall apply hooks
|
||||
#INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret.hook.pre_up"
|
||||
#INIT_FW_POST_UP_HOOK="/etc/firewall.zapret.hook.post_up"
|
||||
#INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret.hook.pre_down"
|
||||
#INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret.hook.post_down"
|
||||
#INIT_FW_PRE_UP_HOOK="/etc/firewall.zapret2.hook.pre_up"
|
||||
#INIT_FW_POST_UP_HOOK="/etc/firewall.zapret2.hook.post_up"
|
||||
#INIT_FW_PRE_DOWN_HOOK="/etc/firewall.zapret2.hook.pre_down"
|
||||
#INIT_FW_POST_DOWN_HOOK="/etc/firewall.zapret2.hook.post_down"
|
||||
|
||||
# do not work with ipv4
|
||||
#DISABLE_IPV4=1
|
||||
|
||||
@@ -34,3 +34,18 @@ v0.2
|
||||
* zapret-lib: bugfixes
|
||||
* zapret-lib: remove ip6_hopbyhop_x2 fooling, separately add second hopbyhop header using ip6_hopbyhop2
|
||||
* zapret-pcap
|
||||
|
||||
v0.3
|
||||
|
||||
* init.d launch scripts
|
||||
* init.d: 40-webserver custom script
|
||||
* install_easy
|
||||
|
||||
v0.4
|
||||
|
||||
* nfqws2: profile names and cookies
|
||||
* nfqws2: profile templates
|
||||
* nfqws2: remove stun_binding_req, replace to stun. no more message type details
|
||||
* nfqws2: proper conntack position for replayed packets
|
||||
* blockcheck2: fix broken dns cache
|
||||
* nfqws2: LUA_COMPAT_VER tracking
|
||||
|
||||
7
docs/changes_compat.txt
Normal file
7
docs/changes_compat.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Here listed all api breaking changes.
|
||||
When something changes capable of breaking things NFQWS2_COMPAT_VER increases.
|
||||
|
||||
v2
|
||||
* removed "stun_binding_req" specialized payload. replaced with common "stun" - any stun packets, not only binding request.
|
||||
every LUA relying on desync.l7payload should be revised.
|
||||
nfqws2 --payload option and init.d custom scripts must be updated.
|
||||
@@ -24,8 +24,8 @@ define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/ip2net/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_DIR) $(1)/opt/zapret2/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip2net $(1)/opt/zapret2/binaries/my
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,ip2net))
|
||||
|
||||
@@ -24,8 +24,8 @@ define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/mdig/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_DIR) $(1)/opt/zapret2/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mdig $(1)/opt/zapret2/binaries/my
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,mdig))
|
||||
|
||||
@@ -31,7 +31,7 @@ endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) ./nfq/* $(PKG_BUILD_DIR)/
|
||||
$(CP) ./nfq2/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
@@ -39,8 +39,8 @@ define Build/Compile
|
||||
endef
|
||||
|
||||
define Package/nfqws2/install
|
||||
$(INSTALL_DIR) $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws2 $(1)/opt/zapret/binaries/my
|
||||
$(INSTALL_DIR) $(1)/opt/zapret2/binaries/my
|
||||
$(INSTALL_BIN) $(PKG_BUILD_DIR)/nfqws2 $(1)/opt/zapret2/binaries/my
|
||||
endef
|
||||
|
||||
$(eval $(call BuildPackage,nfqws2))
|
||||
|
||||
@@ -1 +1 @@
|
||||
Copy "nfq" folder here !
|
||||
Copy "nfq2" folder here !
|
||||
|
||||
@@ -361,7 +361,7 @@ start "zapret: http,https,quic" /min "%~dp0winws2.exe" ^
|
||||
--new ^
|
||||
--filter-l7=wireguard,stun,discord ^
|
||||
--out-range=-d10 ^
|
||||
--payload=wireguard_initiation,wireguard_cookie,stun_binding_req,discord_ip_discovery ^
|
||||
--payload=wireguard_initiation,wireguard_cookie,stun,discord_ip_discovery ^
|
||||
--lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2
|
||||
```
|
||||
|
||||
|
||||
22
init.d/custom.d.examples.linux/10-keenetic-udp-fix
Normal file
22
init.d/custom.d.examples.linux/10-keenetic-udp-fix
Normal file
@@ -0,0 +1,22 @@
|
||||
# This script fixes keenetic issue with nfqws generated udp packets
|
||||
# Keenetic uses proprietary ndmmark and does not masquerade without this mark
|
||||
# If not masqueraded packets go to WAN with LAN IP and get dropped by ISP
|
||||
|
||||
# It's advised to set IFACE_WAN in config
|
||||
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local wan wanif rule
|
||||
|
||||
[ "$DISABLE_IPV4" = "1" ] || {
|
||||
# use IFACE_WAN if defined. if not - search for interfaces with default route.
|
||||
wanif=${IFACE_WAN:-$(sed -nre 's/^([^\t]+)\t00000000\t[0-9A-F]{8}\t[0-9A-F]{4}\t[0-9]+\t[0-9]+\t[0-9]+\t00000000.*$/\1/p' /proc/net/route | sort -u | xargs)}
|
||||
for wan in $wanif; do
|
||||
rule="-o $wan -p udp -m mark --mark $DESYNC_MARK/$DESYNC_MARK"
|
||||
ipt_print_op $1 "$rule" "keenetic udp fix"
|
||||
ipt_add_del $1 POSTROUTING -t nat $rule -j MASQUERADE
|
||||
done
|
||||
}
|
||||
}
|
||||
66
init.d/custom.d.examples.linux/20-fw-extra
Normal file
66
init.d/custom.d.examples.linux/20-fw-extra
Normal file
@@ -0,0 +1,66 @@
|
||||
# this custom script runs standard mode with extra firewall rules
|
||||
|
||||
# config: use TPWS_ENABLE_OVERRIDE, NFQWS_ENABLE_OVERRIDE to enable standard mode daemons
|
||||
# standard and override switches cannot be enabled simultaneously !
|
||||
|
||||
TPWS_ENABLE_OVERRIDE=${TPWS_ENABLE_OVERRIDE:-0}
|
||||
NFQWS_ENABLE_OVERRIDE=${NFQWS_ENABLE_OVERRIDE:-0}
|
||||
|
||||
# config: some if these values must be set in config. not setting any of these makes this script meaningless.
|
||||
# pre vars put ipt/nft code to the rule beginning
|
||||
#FW_EXTRA_PRE_TPWS_IPT=
|
||||
#FW_EXTRA_PRE_TPWS_NFT=
|
||||
#FW_EXTRA_PRE_NFQWS_IPT="-m mark --mark 0x10000000/0x10000000"
|
||||
#FW_EXTRA_PRE_NFQWS_NFT="mark and 0x10000000 != 0"
|
||||
# post vars put ipt/nft code to the rule end
|
||||
#FW_EXTRA_POST_TPWS_IPT=
|
||||
#FW_EXTRA_POST_TPWS_NFT=
|
||||
#FW_EXTRA_POST_NFQWS_IPT=
|
||||
#FW_EXTRA_POST_NFQWS_NFT=
|
||||
|
||||
check_std_intersect()
|
||||
{
|
||||
[ "$TPWS_ENABLE_OVERRIDE" = 1 -a "$TPWS_ENABLE" = 1 ] && {
|
||||
echo "ERROR ! both TPWS_ENABLE_OVERRIDE and TPWS_ENABLE are enabled"
|
||||
return 1
|
||||
}
|
||||
[ "$NFQWS_ENABLE_OVERRIDE" = 1 -a "$NFQWS_ENABLE" = 1 ] && {
|
||||
echo "ERROR ! both NFQWS_ENABLE_OVERRIDE and NFQWS_ENABLE are enabled"
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
check_std_intersect || return
|
||||
|
||||
local TPWS_SOCKS_ENABLE=0 TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE
|
||||
standard_mode_daemons "$1"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
check_std_intersect || return
|
||||
|
||||
local FW_EXTRA_PRE FW_EXTRA_POST TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_TPWS_IPT" FW_EXTRA_POST="$FW_EXTRA_POST_TPWS_IPT"
|
||||
zapret_do_firewall_standard_tpws_rules_ipt $1
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS_IPT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS_IPT"
|
||||
zapret_do_firewall_standard_nfqws_rules_ipt $1
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
check_std_intersect || return
|
||||
|
||||
local FW_EXTRA_PRE FW_EXTRA_POST TPWS_ENABLE=$TPWS_ENABLE_OVERRIDE NFQWS_ENABLE=$NFQWS_ENABLE_OVERRIDE
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_TPWS_NFT" FW_EXTRA_POST="$FW_EXTRA_POST_TPWS_NFT"
|
||||
zapret_apply_firewall_standard_tpws_rules_nft
|
||||
FW_EXTRA_PRE="$FW_EXTRA_PRE_NFQWS_NFT" FW_EXTRA_POST="$FW_EXTRA_POST_NFQWS_NFT"
|
||||
zapret_apply_firewall_standard_nfqws_rules_nft
|
||||
}
|
||||
39
init.d/custom.d.examples.linux/40-webserver
Normal file
39
init.d/custom.d.examples.linux/40-webserver
Normal file
@@ -0,0 +1,39 @@
|
||||
# this custom script runs nfqws2 in server mode for typical webserver
|
||||
|
||||
WEBSERVER_DEFAULT_STRATEGY="
|
||||
--server
|
||||
--payload http_reply,tls_server_hello --lua-desync=fake:blob=0x00000000000000000000000000000000:badsum:repeats=2 --lua-desync=multisplit
|
||||
--payload empty --lua-desync=synack_split"
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_WEBSERVER="${NFQWS_OPT_DESYNC_WEBSERVER:-$WEBSERVER_DEFAULT_STRATEGY}"
|
||||
WEBSERVER_PORTS="${WEBSERVER_PORTS:-80,443}"
|
||||
WEBSERVER_PKT_OUT="${WEBSERVER_PKT_OUT:-15}"
|
||||
|
||||
alloc_dnum DNUM_WEBSERVER
|
||||
alloc_qnum QNUM_WEBSERVER
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_WEBSERVER $NFQWS_OPT_DESYNC_WEBSERVER"
|
||||
do_nfqws $1 $DNUM_WEBSERVER "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local PORTS=$(replace_char - : $WEBSERVER_PORTS)
|
||||
local first_packets=$(ipt_first_packets $WEBSERVER_PKT_OUT)
|
||||
local f="-p tcp -m multiport --sports $PORTS $first_packets"
|
||||
fw_nfqws_post $1 "$f" "$f" $QNUM_WEBSERVER
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local first_packets=$(nft_first_packets $WEBSERVER_PKT_OUT)
|
||||
local f="tcp sport {$WEBSERVER_PORTS} $first_packets"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WEBSERVER
|
||||
}
|
||||
38
init.d/custom.d.examples.linux/50-dht4all
Normal file
38
init.d/custom.d.examples.linux/50-dht4all
Normal file
@@ -0,0 +1,38 @@
|
||||
# this custom script runs desync to DHT packets with udp payload length 101..399 , without ipset/hostlist filtering
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_DHT="${NFQWS_OPT_DESYNC_DHT:---payload dht --lua-desync=dht_dn}"
|
||||
|
||||
alloc_dnum DNUM_DHT4ALL
|
||||
alloc_qnum QNUM_DHT4ALL
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_DHT4ALL $NFQWS_OPT_DESYNC_DHT"
|
||||
do_nfqws $1 $DNUM_DHT4ALL "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f uf4 uf6
|
||||
local first_packet_only="$ipt_connbytes 1:1"
|
||||
|
||||
f='-p udp -m length --length 109:407 -m u32 --u32'
|
||||
uf4='0>>22&0x3C@8>>16=0x6431'
|
||||
uf6='48>>16=0x6431'
|
||||
fw_nfqws_post $1 "$f $uf4 $first_packet_only" "$f $uf6 $first_packet_only" $QNUM_DHT4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local f
|
||||
local first_packet_only="$nft_connbytes 1"
|
||||
|
||||
f="meta length 109-407 meta l4proto udp @ih,0,16 0x6431"
|
||||
nft_fw_nfqws_post "$f $first_packet_only" "$f $first_packet_only" $QNUM_DHT4ALL
|
||||
}
|
||||
35
init.d/custom.d.examples.linux/50-discord-media
Normal file
35
init.d/custom.d.examples.linux/50-discord-media
Normal file
@@ -0,0 +1,35 @@
|
||||
# this custom script runs desync to all discord media packets
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_DISCORD_MEDIA="${NFQWS_OPT_DESYNC_DISCORD_MEDIA:---payload discord_ip_discovery --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
DISCORD_MEDIA_PORT_RANGE="${DISCORD_MEDIA_PORT_RANGE:-50000-50099}"
|
||||
|
||||
alloc_dnum DNUM_DISCORD_MEDIA
|
||||
alloc_qnum QNUM_DISCORD_MEDIA
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_DISCORD_MEDIA $NFQWS_OPT_DESYNC_DISCORD_MEDIA"
|
||||
do_nfqws $1 $DNUM_DISCORD_MEDIA "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local DISABLE_IPV6=1
|
||||
local port_range=$(replace_char - : $DISCORD_MEDIA_PORT_RANGE)
|
||||
local f="-p udp --dport $port_range -m u32 --u32"
|
||||
# this is simplified test to skip writing monstrous rule. instead of checking 64 bytes for zeroes only check 2 dwords for zero
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x52&&0>>22&0x3C@8=0x00010046&&0>>22&0x3C@16=0&&0>>22&0x3C@76=0" '' $QNUM_DISCORD_MEDIA
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local DISABLE_IPV6=1
|
||||
local f="udp dport $DISCORD_MEDIA_PORT_RANGE udp length == 82 @ih,0,32 0x00010046 @ih,64,128 0x00000000000000000000000000000000 @ih,192,128 0x00000000000000000000000000000000 @ih,320,128 0x00000000000000000000000000000000 @ih,448,128 0x00000000000000000000000000000000"
|
||||
nft_fw_nfqws_post "$f" '' $QNUM_DISCORD_MEDIA
|
||||
}
|
||||
144
init.d/custom.d.examples.linux/50-nfqws-ipset
Normal file
144
init.d/custom.d.examples.linux/50-nfqws-ipset
Normal file
@@ -0,0 +1,144 @@
|
||||
# this custom script demonstrates how to launch extra nfqws instance limited by ipset
|
||||
|
||||
# can override in config :
|
||||
NFQWS_MY1_OPT="${NFQWS_MY1_OPT:---filter-udp=* --payload known,unknown --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2:payload=all --new --filter-tcp=* --payload=known,unknown --lua-desync=multisplit}"
|
||||
NFQWS_MY1_SUBNETS4="${NFQWS_MY1_SUBNETS4:-173.194.0.0/16 108.177.0.0/17 74.125.0.0/16 64.233.160.0/19 172.217.0.0/16}"
|
||||
NFQWS_MY1_SUBNETS6="${NFQWS_MY1_SUBNETS6:-2a00:1450::/29}"
|
||||
NFQWS_MY1_PORTS_TCP=${NFQWS_MY1_PORTS_TCP:-$NFQWS_PORTS_TCP}
|
||||
NFQWS_MY1_PORTS_UDP=${NFQWS_MY1_PORTS_UDP:-$NFQWS_PORTS_UDP}
|
||||
NFQWS_MY1_TCP_PKT_OUT=${NFQWS_MY1_TCP_PKT_OUT:-$NFQWS_TCP_PKT_OUT}
|
||||
NFQWS_MY1_UDP_PKT_OUT=${NFQWS_MY1_UDP_PKT_OUT:-$NFQWS_UDP_PKT_OUT}
|
||||
NFQWS_MY1_TCP_PKT_IN=${NFQWS_MY1_TCP_PKT_IN:-$NFQWS_TCP_PKT_IN}
|
||||
NFQWS_MY1_UDP_PKT_IN=${NFQWS_MY1_UDP_PKT_IN:-$NFQWS_UDP_PKT_IN}
|
||||
|
||||
NFQWS_MY1_IPSET_SIZE=${NFQWS_MY1_IPSET_SIZE:-4096}
|
||||
NFQWS_MY1_IPSET_OPT="${NFQWS_MY1_IPSET_OPT:-hash:net hashsize 8192 maxelem $NFQWS_MY1_IPSET_SIZE}"
|
||||
|
||||
alloc_dnum DNUM_NFQWS_MY1
|
||||
alloc_qnum QNUM_NFQWS_MY1
|
||||
NFQWS_MY1_NAME4=my1nfqws4
|
||||
NFQWS_MY1_NAME6=my1nfqws6
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_NFQWS_MY1 $NFQWS_MY1_OPT"
|
||||
do_nfqws $1 $DNUM_NFQWS_MY1 "$opt"
|
||||
}
|
||||
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f4 f6 subnet
|
||||
local NFQWS_MY1_PORTS_TCP=$(replace_char - : $NFQWS_MY1_PORTS_TCP)
|
||||
local NFQWS_MY1_PORTS_UDP=$(replace_char - : $NFQWS_MY1_PORTS_UDP)
|
||||
|
||||
[ "$1" = 1 -a "$DISABLE_IPV4" != 1 ] && {
|
||||
ipset create $NFQWS_MY1_NAME4 $NFQWS_MY1_IPSET_OPT family inet 2>/dev/null
|
||||
ipset flush $NFQWS_MY1_NAME4
|
||||
for subnet in $NFQWS_MY1_SUBNETS4; do
|
||||
echo add $NFQWS_MY1_NAME4 $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
[ "$1" = 1 -a "$DISABLE_IPV6" != 1 ] && {
|
||||
ipset create $NFQWS_MY1_NAME6 $NFQWS_MY1_IPSET_OPT family inet6 2>/dev/null
|
||||
ipset flush $NFQWS_MY1_NAME6
|
||||
for subnet in $NFQWS_MY1_SUBNETS6; do
|
||||
echo add $NFQWS_MY1_NAME6 $subnet
|
||||
done | ipset -! restore
|
||||
}
|
||||
|
||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="-p tcp -m multiport --dports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="-p tcp -m multiport --sports $NFQWS_MY1_PORTS_TCP $ipt_connbytes 1:$NFQWS_MY1_TCP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
}
|
||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="-p udp -m multiport --dports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_OUT -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 dst"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 dst"
|
||||
fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="-p udp -m multiport --sports $NFQWS_MY1_PORTS_UDP $ipt_connbytes 1:$NFQWS_MY1_UDP_PKT_IN -m set --match-set"
|
||||
f6="$f4 $NFQWS_MY1_NAME6 src"
|
||||
f4="$f4 $NFQWS_MY1_NAME4 src"
|
||||
fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
}
|
||||
|
||||
[ "$1" = 1 ] || {
|
||||
ipset destroy $NFQWS_MY1_NAME4 2>/dev/null
|
||||
ipset destroy $NFQWS_MY1_NAME6 2>/dev/null
|
||||
}
|
||||
}
|
||||
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
local f4 f6 subnets
|
||||
local first_packets_only="$nft_connbytes 1-$NFQWS_MY1_PKT_OUT"
|
||||
|
||||
[ "$DISABLE_IPV4" != 1 ] && {
|
||||
make_comma_list subnets $NFQWS_MY1_SUBNETS4
|
||||
nft_create_set $NFQWS_MY1_NAME4 "type ipv4_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS_MY1_NAME4
|
||||
nft_add_set_element $NFQWS_MY1_NAME4 "$subnets"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != 1 ] && {
|
||||
make_comma_list subnets $NFQWS_MY1_SUBNETS6
|
||||
nft_create_set $NFQWS_MY1_NAME6 "type ipv6_addr; size $NFQWS_MY1_IPSET_SIZE; auto-merge; flags interval;"
|
||||
nft_flush_set $NFQWS_MY1_NAME6
|
||||
nft_add_set_element $NFQWS_MY1_NAME6 "$subnets"
|
||||
}
|
||||
|
||||
[ -n "$NFQWS_MY1_PORTS_TCP" ] && {
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_OUT" -a "$NFQWS_MY1_TCP_PKT_OUT" != 0 ] && {
|
||||
f4="tcp dport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_TCP_PKT_IN" -a "$NFQWS_MY1_TCP_PKT_IN" != 0 ] && {
|
||||
f4="tcp sport {$NFQWS_MY1_PORTS_TCP} $(nft_first_packets $NFQWS_MY1_TCP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
}
|
||||
[ -n "$NFQWS_MY1_PORTS_UDP" ] && {
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_OUT" -a "$NFQWS_MY1_UDP_PKT_OUT" != 0 ] && {
|
||||
f4="udp dport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_OUT)"
|
||||
f6="$f4 ip6 daddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip daddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_post $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
[ -n "$NFQWS_MY1_UDP_PKT_IN" -a "$NFQWS_MY1_UDP_PKT_IN" != 0 ] && {
|
||||
f4="udp sport {$NFQWS_MY1_PORTS_UDP} $(nft_first_packets $NFQWS_MY1_UDP_PKT_IN)"
|
||||
f6="$f4 ip6 saddr @$NFQWS_MY1_NAME6"
|
||||
f4="$f4 ip saddr @$NFQWS_MY1_NAME4"
|
||||
nft_fw_nfqws_pre $1 "$f4" "$f6" $QNUM_NFQWS_MY1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
zapret_custom_firewall_nft_flush()
|
||||
{
|
||||
# this function is called after all nft fw rules are deleted
|
||||
# however sets are not deleted. it's desired to clear sets here.
|
||||
|
||||
nft_del_set $NFQWS_MY1_NAME4 2>/dev/null
|
||||
nft_del_set $NFQWS_MY1_NAME6 2>/dev/null
|
||||
}
|
||||
30
init.d/custom.d.examples.linux/50-quic4all
Normal file
30
init.d/custom.d.examples.linux/50-quic4all
Normal file
@@ -0,0 +1,30 @@
|
||||
# this custom script runs desync to all IETF QUIC initials
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_QUIC="${NFQWS_OPT_DESYNC_QUIC:---payload quic_initial --lua-desync=fake:blob=fake_default_quic:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_QUIC4ALL
|
||||
alloc_qnum QNUM_QUIC4ALL
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_QUIC4ALL $NFQWS_OPT_DESYNC_QUIC"
|
||||
do_nfqws $1 $DNUM_QUIC4ALL "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f='-p udp -m u32 --u32'
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=264:65535&&0>>22&0x3C@8>>28=0xC&&0>>22&0x3C@9=0x00000001" "$f 44>>16=264:65535&&48>>28=0xC&&49=0x00000001" $QNUM_QUIC4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local f="udp length >= 264 @ih,0,4 0xC @ih,8,32 0x00000001"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_QUIC4ALL
|
||||
}
|
||||
30
init.d/custom.d.examples.linux/50-stun4all
Normal file
30
init.d/custom.d.examples.linux/50-stun4all
Normal file
@@ -0,0 +1,30 @@
|
||||
# this custom script runs desync to all stun packets
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_STUN="${NFQWS_OPT_DESYNC_STUN:---payload stun --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_STUN4ALL
|
||||
alloc_qnum QNUM_STUN4ALL
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_STUN4ALL $NFQWS_OPT_DESYNC_STUN"
|
||||
do_nfqws $1 $DNUM_STUN4ALL "$opt"
|
||||
}
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f='-p udp -m u32 --u32'
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=28:65535&&0>>22&0x3C@12=0x2112A442&&0>>22&0x3C@8&0xC0000003=0" "$f 44>>16=28:65535&&52=0x2112A442&&48&0xC0000003=0" $QNUM_STUN4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local f="udp length >= 28 @ih,32,32 0x2112A442 @ih,0,2 0 @ih,30,2 0"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_STUN4ALL
|
||||
}
|
||||
32
init.d/custom.d.examples.linux/50-wg4all
Normal file
32
init.d/custom.d.examples.linux/50-wg4all
Normal file
@@ -0,0 +1,32 @@
|
||||
# this custom script runs desync to all wireguard handshake initiation packets
|
||||
# NOTE: this works for original wireguard and may not work for 3rd party implementations such as xray
|
||||
# NOTE: @ih requires nft 1.0.1+ and updated kernel version. it's confirmed to work on 5.15 (openwrt 23) and not work on 5.10 (openwrt 22)
|
||||
|
||||
# can override in config :
|
||||
NFQWS_OPT_DESYNC_WG="${NFQWS_OPT_DESYNC_WG:---payload wireguard_initiation --lua-desync=fake:blob=0x00000000000000000000000000000000:repeats=2}"
|
||||
|
||||
alloc_dnum DNUM_WG4ALL
|
||||
alloc_qnum QNUM_WG4ALL
|
||||
|
||||
zapret_custom_daemons()
|
||||
{
|
||||
# $1 - 1 - add, 0 - stop
|
||||
|
||||
local opt="--qnum=$QNUM_WG4ALL $NFQWS_OPT_DESYNC_WG"
|
||||
do_nfqws $1 $DNUM_WG4ALL "$opt"
|
||||
}
|
||||
# size = 156 (8 udp header + 148 payload) && payload starts with 0x01000000
|
||||
zapret_custom_firewall()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
|
||||
local f='-p udp -m u32 --u32'
|
||||
fw_nfqws_post $1 "$f 0>>22&0x3C@4>>16=0x9c&&0>>22&0x3C@8=0x01000000" "$f 44>>16=0x9c&&48=0x01000000" $QNUM_WG4ALL
|
||||
}
|
||||
zapret_custom_firewall_nft()
|
||||
{
|
||||
# stop logic is not required
|
||||
|
||||
local f="udp length 156 @ih,0,32 0x01000000"
|
||||
nft_fw_nfqws_post "$f" "$f" $QNUM_WG4ALL
|
||||
}
|
||||
69
init.d/openrc/zapret2
Executable file
69
init.d/openrc/zapret2
Executable 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/zapret2"
|
||||
|
||||
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
|
||||
}
|
||||
46
init.d/openwrt/90-zapret2
Normal file
46
init.d/openwrt/90-zapret2
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/bin/sh
|
||||
|
||||
ZAPRET=/etc/init.d/zapret2
|
||||
|
||||
check_lan()
|
||||
{
|
||||
IS_LAN=
|
||||
[ -n "$OPENWRT_LAN" ] || OPENWRT_LAN=lan
|
||||
for lan in $OPENWRT_LAN; do
|
||||
[ "$INTERFACE" = "$lan" ] && {
|
||||
IS_LAN=1
|
||||
break
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
[ -n "$INTERFACE" ] && [ "$ACTION" = ifup -o "$ACTION" = ifdown ] && [ -x "$ZAPRET" ] && "$ZAPRET" enabled && {
|
||||
SCRIPT=$(readlink "$ZAPRET")
|
||||
if [ -n "$SCRIPT" ]; then
|
||||
EXEDIR=$(dirname "$SCRIPT")
|
||||
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
|
||||
else
|
||||
ZAPRET_BASE=/opt/zapret2
|
||||
fi
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt"
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$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
|
||||
}
|
||||
0
init.d/openwrt/custom.d/.keep
Normal file
0
init.d/openwrt/custom.d/.keep
Normal file
11
init.d/openwrt/firewall.zapret2
Normal file
11
init.d/openwrt/firewall.zapret2
Normal file
@@ -0,0 +1,11 @@
|
||||
SCRIPT=$(readlink /etc/init.d/zapret2)
|
||||
if [ -n "$SCRIPT" ]; then
|
||||
EXEDIR=$(dirname "$SCRIPT")
|
||||
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
|
||||
else
|
||||
ZAPRET_BASE=/opt/zapret2
|
||||
fi
|
||||
|
||||
. "$ZAPRET_BASE/init.d/openwrt/functions"
|
||||
|
||||
zapret_apply_firewall
|
||||
218
init.d/openwrt/functions
Normal file
218
init.d/openwrt/functions
Normal file
@@ -0,0 +1,218 @@
|
||||
. /lib/functions/network.sh
|
||||
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-/opt/zapret2}
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/common/linux_iphelper.sh"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
. "$ZAPRET_BASE/common/nft.sh"
|
||||
. "$ZAPRET_BASE/common/linux_fw.sh"
|
||||
. "$ZAPRET_BASE/common/linux_daemons.sh"
|
||||
. "$ZAPRET_BASE/common/list.sh"
|
||||
. "$ZAPRET_BASE/common/custom.sh"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt"
|
||||
|
||||
QNUM=${QNUM:-300}
|
||||
WS_USER=${WS_USER:-daemon}
|
||||
DESYNC_MARK=${DESYNC_MARK:-0x40000000}
|
||||
DESYNC_MARK_POSTNAT=${DESYNC_MARK_POSTNAT:-0x20000000}
|
||||
OPENWRT_LAN=${OPENWRT_LAN:-lan}
|
||||
|
||||
IPSET_CR="$ZAPRET_BASE/ipset/create_ipset.sh"
|
||||
|
||||
# can be multiple ipv6 outgoing interfaces
|
||||
# uplink from isp, tunnelbroker, vpn, ...
|
||||
# want them all. who knows what's the real one that blocks sites
|
||||
# dont want any manual configuration - want to do it automatically
|
||||
# standard network_find_wan[6] return only the first
|
||||
# we use low level function from network.sh to avoid this limitation
|
||||
# it can change theoretically and stop working
|
||||
|
||||
network_find_wan4_all()
|
||||
{
|
||||
if [ -n "$OPENWRT_WAN4" ]; then
|
||||
eval $1="\$OPENWRT_WAN4"
|
||||
else
|
||||
__network_ifstatus "$1" "" "[@.route[@.target='0.0.0.0' && !@.table]].interface" "" 10 2>/dev/null && return
|
||||
network_find_wan $1
|
||||
fi
|
||||
}
|
||||
network_find_wan_all()
|
||||
{
|
||||
network_find_wan4_all "$@"
|
||||
}
|
||||
network_find_wan6_all()
|
||||
{
|
||||
if [ -n "$OPENWRT_WAN6" ]; then
|
||||
eval $1="\$OPENWRT_WAN6"
|
||||
else
|
||||
__network_ifstatus "$1" "" "[@.route[@.target='::' && !@.table]].interface" "" 10 2>/dev/null && return
|
||||
network_find_wan6 $1
|
||||
fi
|
||||
}
|
||||
network_find_wanX_devices()
|
||||
{
|
||||
# $1 - ip version: 4 or 6
|
||||
# $2 - variable to put result to
|
||||
local ifaces
|
||||
network_find_wan${1}_all ifaces
|
||||
call_for_multiple_items network_get_device $2 "$ifaces"
|
||||
}
|
||||
|
||||
|
||||
fw_nfqws_prepost_x()
|
||||
{
|
||||
# $1 - 1 - add, 0 - del
|
||||
# $2 - filter
|
||||
# $3 - queue number
|
||||
# $4 - 4/6
|
||||
# $5 - post/pre
|
||||
|
||||
local ifaces DWAN
|
||||
network_find_wan${4}_all ifaces
|
||||
call_for_multiple_items network_get_device DWAN "$ifaces"
|
||||
|
||||
[ -n "$DWAN" ] && _fw_nfqws_${5}${4} $1 "$2" $3 "$(unique $DWAN)"
|
||||
}
|
||||
fw_nfqws_post4()
|
||||
{
|
||||
fw_nfqws_prepost_x $1 "$2" $3 4 post
|
||||
}
|
||||
fw_nfqws_post6()
|
||||
{
|
||||
fw_nfqws_prepost_x $1 "$2" $3 6 post
|
||||
}
|
||||
fw_nfqws_pre4()
|
||||
{
|
||||
fw_nfqws_prepost_x $1 "$2" $3 4 pre
|
||||
}
|
||||
fw_nfqws_pre6()
|
||||
{
|
||||
fw_nfqws_prepost_x $1 "$2" $3 6 pre
|
||||
}
|
||||
|
||||
create_ipset()
|
||||
{
|
||||
echo "Creating ip list table (firewall type $FWTYPE)"
|
||||
"$IPSET_CR" "$@"
|
||||
}
|
||||
|
||||
list_nfqws_rules()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
ip$1tables -S POSTROUTING -t mangle | \
|
||||
grep -E "NFQUEUE --queue-num $QNUM --queue-bypass|NFQUEUE --queue-num $(($QNUM+1)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+2)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+3)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+10)) --queue-bypass|NFQUEUE --queue-num $(($QNUM+11)) --queue-bypass" | \
|
||||
sed -re 's/^-A POSTROUTING (.*) -j NFQUEUE.*$/\1/' -e "s/-m mark ! --mark $DESYNC_MARK\/$DESYNC_MARK//"
|
||||
}
|
||||
apply_flow_offloading_enable_rule()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
local i off='-j FLOWOFFLOAD'
|
||||
[ "$FLOWOFFLOAD" = "hardware" ] && off="$off --hw"
|
||||
i="forwarding_rule_zapret -m comment --comment zapret_traffic_offloading_enable -m conntrack --ctstate RELATED,ESTABLISHED $off"
|
||||
echo enabling ipv${1:-4} flow offloading : $i
|
||||
ip$1tables -A $i
|
||||
}
|
||||
apply_flow_offloading_exempt_rule()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
local i v
|
||||
v=$1
|
||||
shift
|
||||
i="forwarding_rule_zapret $@ -m comment --comment zapret_traffic_offloading_exemption -j RETURN"
|
||||
echo applying ipv${v:-4} flow offloading exemption : $i
|
||||
ip${v}tables -A $i
|
||||
}
|
||||
flow_offloading_unexempt_v()
|
||||
{
|
||||
# $1 = '' for ipv4, '6' for ipv6
|
||||
local DWAN
|
||||
network_find_wanX_devices ${1:-4} DWAN
|
||||
for i in $DWAN; do ipt$1_del FORWARD -o $i -j forwarding_rule_zapret ; done
|
||||
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_ipt_flow_offload_avail $1 || return 0
|
||||
|
||||
flow_offloading_unexempt_v $1
|
||||
|
||||
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && {
|
||||
ip$1tables -N forwarding_rule_zapret
|
||||
|
||||
# remove outgoing interface
|
||||
list_nfqws_rules $1 | sed -re 's/-o +[^ ]+//g' |
|
||||
while read rule; do
|
||||
apply_flow_offloading_exempt_rule "$1" $rule
|
||||
done
|
||||
|
||||
apply_flow_offloading_enable_rule $1
|
||||
|
||||
# only outgoing to WAN packets trigger flow offloading
|
||||
local DWAN
|
||||
network_find_wanX_devices ${1:-4} DWAN
|
||||
for i in $DWAN; do ipt$1 FORWARD -o $i -j forwarding_rule_zapret; done
|
||||
}
|
||||
return 0
|
||||
}
|
||||
flow_offloading_exempt()
|
||||
{
|
||||
[ "$DISABLE_IPV4" = "1" ] || flow_offloading_exempt_v
|
||||
[ "$DISABLE_IPV6" = "1" ] || flow_offloading_exempt_v 6
|
||||
}
|
||||
flow_offloading_unexempt()
|
||||
{
|
||||
[ "$DISABLE_IPV4" = "1" ] || flow_offloading_unexempt_v
|
||||
[ "$DISABLE_IPV6" = "1" ] || flow_offloading_unexempt_v 6
|
||||
}
|
||||
|
||||
nft_fill_ifsets_overload()
|
||||
{
|
||||
local ifaces DLAN DWAN DWAN6 PDLAN PDWAN PDWAN6
|
||||
|
||||
call_for_multiple_items network_get_device DLAN "$OPENWRT_LAN"
|
||||
call_for_multiple_items network_get_physdev PDLAN "$OPENWRT_LAN"
|
||||
|
||||
network_find_wan4_all ifaces
|
||||
call_for_multiple_items network_get_device DWAN "$ifaces"
|
||||
call_for_multiple_items network_get_physdev PDWAN "$ifaces"
|
||||
|
||||
network_find_wan6_all ifaces
|
||||
call_for_multiple_items network_get_device DWAN6 "$ifaces"
|
||||
call_for_multiple_items network_get_physdev PDWAN6 "$ifaces"
|
||||
|
||||
nft_fill_ifsets "$DLAN" "$DWAN" "$DWAN6" "$PDLAN" "$PDWAN" "$PDWAN6"
|
||||
}
|
||||
nft_wanif_filter_present()
|
||||
{
|
||||
# in openwrt we always use wanif filter
|
||||
return 0
|
||||
}
|
||||
nft_wanif6_filter_present()
|
||||
{
|
||||
# in openwrt we always use wanif6 filter
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
nft_fw_nfqws_post4()
|
||||
{
|
||||
_nft_fw_nfqws_post4 "$1" $2 always_apply_wan_filter
|
||||
}
|
||||
nft_fw_nfqws_post6()
|
||||
{
|
||||
_nft_fw_nfqws_post6 "$1" $2 always_apply_wan_filter
|
||||
}
|
||||
nft_fw_nfqws_pre4()
|
||||
{
|
||||
_nft_fw_nfqws_pre4 "$1" $2 always_apply_wan_filter
|
||||
}
|
||||
nft_fw_nfqws_pre6()
|
||||
{
|
||||
_nft_fw_nfqws_pre6 "$1" $2 always_apply_wan_filter
|
||||
}
|
||||
135
init.d/openwrt/zapret2
Executable file
135
init.d/openwrt/zapret2
Executable file
@@ -0,0 +1,135 @@
|
||||
#!/bin/sh /etc/rc.common
|
||||
|
||||
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/zapret2)
|
||||
if [ -n "$SCRIPT" ]; then
|
||||
EXEDIR=$(dirname "$SCRIPT")
|
||||
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
|
||||
else
|
||||
ZAPRET_BASE=/opt/zapret2
|
||||
fi
|
||||
|
||||
. "$ZAPRET_BASE/init.d/openwrt/functions"
|
||||
|
||||
|
||||
# !!!!! 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
|
||||
|
||||
USEROPT="--user=$WS_USER"
|
||||
NFQWS2="${NFQWS2:-$ZAPRET_BASE/nfq2/nfqws2}"
|
||||
LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua"
|
||||
NFQWS2_OPT_BASE="$USEROPT --fwmark=$DESYNC_MARK $LUAOPT"
|
||||
|
||||
run_daemon()
|
||||
{
|
||||
# $1 - daemon string id or number. can use 1,2,3,...
|
||||
# $2 - daemon
|
||||
# $3 - daemon args
|
||||
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
|
||||
local DAEMONBASE="$(basename "$2")"
|
||||
echo "Starting daemon $1: $2 $3"
|
||||
procd_open_instance
|
||||
procd_set_param command $2 $3
|
||||
procd_set_param pidfile $PIDDIR/${DAEMONBASE}_$1.pid
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
run_nfqws()
|
||||
{
|
||||
run_daemon $1 "$NFQWS2" "$NFQWS2_OPT_BASE $2"
|
||||
}
|
||||
do_nfqws()
|
||||
{
|
||||
[ "$1" = 0 ] || { shift; run_nfqws "$@"; }
|
||||
}
|
||||
|
||||
start_daemons_procd()
|
||||
{
|
||||
standard_mode_daemons 1
|
||||
custom_runner zapret_custom_daemons 1
|
||||
|
||||
return 0
|
||||
}
|
||||
start_daemons()
|
||||
{
|
||||
rc_procd start_daemons_procd "$@"
|
||||
}
|
||||
stop_daemons()
|
||||
{
|
||||
local svc="$(basename ${basescript:-$initscript})"
|
||||
procd_running "$svc" "$1" && procd_kill "$svc" "$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
|
||||
}
|
||||
}
|
||||
27
init.d/pfsense/zapret2.sh
Executable file
27
init.d/pfsense/zapret2.sh
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
# this file should be placed to /usr/local/etc/rc.d and chmod 755
|
||||
|
||||
# copy 'lua' dir there
|
||||
ZDIR=/usr/local/etc/zapret2
|
||||
|
||||
# prepare system
|
||||
|
||||
kldload ipfw
|
||||
kldload ipdivert
|
||||
|
||||
# for older pfsense versions. newer do not have these sysctls
|
||||
sysctl net.inet.ip.pfil.outbound=ipfw,pf
|
||||
sysctl net.inet.ip.pfil.inbound=ipfw,pf
|
||||
sysctl net.inet6.ip6.pfil.outbound=ipfw,pf
|
||||
sysctl net.inet6.ip6.pfil.inbound=ipfw,pf
|
||||
|
||||
# required for newer pfsense versions (2.6.0 tested) to return ipfw to functional state
|
||||
pfctl -d ; pfctl -e
|
||||
|
||||
# add ipfw rules and start daemon
|
||||
|
||||
ipfw delete 100
|
||||
ipfw add 100 divert 990 tcp from any to any 80,443 out not diverted not sockarg
|
||||
pkill ^dvtws2$
|
||||
dvtws2 --daemon --port 990 --lua-init=@$ZDIR/zapret-lib.lua --lua-init=@$ZDIR/zapret-antidpi.lua --lua-desync=multisplit
|
||||
2
init.d/runit/zapret2/finish
Executable file
2
init.d/runit/zapret2/finish
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
/opt/zapret2/init.d/sysv/zapret2 stop
|
||||
3
init.d/runit/zapret2/run
Executable file
3
init.d/runit/zapret2/run
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
/opt/zapret2/init.d/sysv/zapret2 start
|
||||
exec chpst -b zapret2 sleep infinity
|
||||
2
init.d/s6/zapret2/down
Executable file
2
init.d/s6/zapret2/down
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/execlineb -P
|
||||
exec /opt/zapret2/init.d/sysv/zapret2 stop
|
||||
1
init.d/s6/zapret2/type
Normal file
1
init.d/s6/zapret2/type
Normal file
@@ -0,0 +1 @@
|
||||
oneshot
|
||||
2
init.d/s6/zapret2/up
Executable file
2
init.d/s6/zapret2/up
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/execlineb -P
|
||||
exec /opt/zapret2/init.d/sysv/zapret2 start
|
||||
62
init.d/systemd/nfqws2@.service
Normal file
62
init.d/systemd/nfqws2@.service
Normal file
@@ -0,0 +1,62 @@
|
||||
# Example systemd service unit for nfqws. Adjust for your installation.
|
||||
|
||||
# WARNING ! This unit requires to compile nfqws using `make systemd`
|
||||
# WARNING ! This makefile target enables special systemd notify support.
|
||||
|
||||
# PREPARE
|
||||
# install build depends
|
||||
# make -C /opt/zapret2 systemd
|
||||
# cp nfqws2\@.service /lib/systemd/system
|
||||
# systemctl daemon-reload
|
||||
|
||||
# MANAGE INSTANCE
|
||||
# prepare /etc/zapret2/nfqws1.conf with nfqws parameters
|
||||
# systemctl start nfqws2@nfqws1
|
||||
# systemctl status nfqws2@nfqws1
|
||||
# systemctl restart nfqws2@nfqws1
|
||||
# systemctl enable nfqws2@nfqws1
|
||||
# systemctl disable nfqws2@nfqws1
|
||||
# systemctl stop nfqws2@nfqws1
|
||||
|
||||
# DELETE
|
||||
# rm /lib/systemd/system/nfqws@.service
|
||||
# systemctl daemon-reload
|
||||
|
||||
|
||||
[Unit]
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
Restart=on-failure
|
||||
|
||||
ExecSearchPath=/opt/zapret2/nfq2
|
||||
ExecStart=nfqws2 @${CONFIG_DIR}/${INSTANCE}.conf
|
||||
Environment=CONFIG_DIR=/etc/zapret2
|
||||
Environment=INSTANCE=%i
|
||||
|
||||
RestrictAddressFamilies=AF_NETLINK AF_UNIX AF_INET6 AF_INET
|
||||
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
PrivateDevices=true
|
||||
PrivateMounts=true
|
||||
PrivateTmp=true
|
||||
ProcSubset=pid
|
||||
ProtectClock=true
|
||||
ProtectControlGroups=true
|
||||
ProtectHome=true
|
||||
ProtectHostname=true
|
||||
ProtectKernelLogs=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectProc=invisible
|
||||
ProtectSystem=full
|
||||
RemoveIPC=true
|
||||
RestrictNamespaces=true
|
||||
RestrictRealtime=true
|
||||
RestrictSUIDSGID=true
|
||||
UMask=0077
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
13
init.d/systemd/zapret2-list-update.service
Normal file
13
init.d/systemd/zapret2-list-update.service
Normal file
@@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=zapret2 ip/host list update
|
||||
|
||||
[Service]
|
||||
Restart=no
|
||||
IgnoreSIGPIPE=no
|
||||
KillMode=control-group
|
||||
GuessMainPID=no
|
||||
RemainAfterExit=no
|
||||
ExecStart=/opt/zapret2/ipset/get_config.sh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
11
init.d/systemd/zapret2-list-update.timer
Normal file
11
init.d/systemd/zapret2-list-update.timer
Normal file
@@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=zapret2 ip/host list update timer
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-2,4,6,8,10,12,14,16,18,20,22,24,26,28,30 00:00:00
|
||||
RandomizedDelaySec=86400
|
||||
Persistent=true
|
||||
Unit=zapret2-list-update.service
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
17
init.d/systemd/zapret2.service
Normal file
17
init.d/systemd/zapret2.service
Normal file
@@ -0,0 +1,17 @@
|
||||
[Unit]
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
Restart=no
|
||||
TimeoutSec=30sec
|
||||
IgnoreSIGPIPE=no
|
||||
KillMode=none
|
||||
GuessMainPID=no
|
||||
RemainAfterExit=no
|
||||
ExecStart=/opt/zapret2/init.d/sysv/zapret2 start
|
||||
ExecStop=/opt/zapret2/init.d/sysv/zapret2 stop
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
0
init.d/sysv/custom.d/.keep
Normal file
0
init.d/sysv/custom.d/.keep
Normal file
191
init.d/sysv/functions
Normal file
191
init.d/sysv/functions
Normal file
@@ -0,0 +1,191 @@
|
||||
# init script functions library for desktop linux systems
|
||||
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-/opt/zapret2}
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
. "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/common/linux_iphelper.sh"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
. "$ZAPRET_BASE/common/nft.sh"
|
||||
. "$ZAPRET_BASE/common/linux_fw.sh"
|
||||
. "$ZAPRET_BASE/common/linux_daemons.sh"
|
||||
. "$ZAPRET_BASE/common/list.sh"
|
||||
. "$ZAPRET_BASE/common/custom.sh"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
|
||||
|
||||
|
||||
user_exists()
|
||||
{
|
||||
id -u $1 >/dev/null 2>/dev/null
|
||||
}
|
||||
useradd_compat()
|
||||
{
|
||||
# $1 - username
|
||||
# skip for readonly systems
|
||||
[ -w "/etc" ] && {
|
||||
if exists useradd ; then
|
||||
useradd --no-create-home --system --shell /bin/false $1
|
||||
elif is_linked_to_busybox adduser ; then
|
||||
# some systems may miss nogroup group in /etc/group
|
||||
# adduser fails if it's absent and no group is specified
|
||||
addgroup nogroup 2>/dev/null
|
||||
# busybox has special adduser syntax
|
||||
adduser -S -H -D $1
|
||||
elif exists adduser; then
|
||||
adduser --no-create-home --system --disabled-login $1
|
||||
fi
|
||||
}
|
||||
user_exists $1
|
||||
}
|
||||
prepare_user()
|
||||
{
|
||||
user_exists $WS_USER || {
|
||||
# fallback to daemon if we cant add WS_USER
|
||||
useradd_compat $WS_USER || {
|
||||
for user in daemon nobody; do
|
||||
user_exists $user && {
|
||||
WS_USER=$user
|
||||
return 0
|
||||
}
|
||||
done
|
||||
return 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# this complex user selection allows to survive in any locked/readonly/minimalistic environment
|
||||
[ -n "$WS_USER" ] || WS_USER=tpws
|
||||
if prepare_user; then
|
||||
USEROPT="--user=$WS_USER"
|
||||
else
|
||||
WS_USER=1
|
||||
USEROPT="--uid $WS_USER:$WS_USER"
|
||||
fi
|
||||
|
||||
PIDDIR=/var/run
|
||||
IPSET_CR="$ZAPRET_BASE/ipset/create_ipset.sh"
|
||||
|
||||
DESYNC_MARK=${DESYNC_MARK:-0x40000000}
|
||||
DESYNC_MARK_POSTNAT=${DESYNC_MARK_POSTNAT:-0x20000000}
|
||||
|
||||
QNUM=${QNUM:-300}
|
||||
NFQWS2="${NFQWS2:-$ZAPRET_BASE/nfq2/nfqws2}"
|
||||
LUAOPT="--lua-init=@$ZAPRET_BASE/lua/zapret-lib.lua --lua-init=@$ZAPRET_BASE/lua/zapret-antidpi.lua"
|
||||
NFQWS2_OPT_BASE="$USEROPT --fwmark=$DESYNC_MARK $LUAOPT"
|
||||
|
||||
|
||||
fw_nfqws_post4()
|
||||
{
|
||||
_fw_nfqws_post4 $1 "$2" $3 "$IFACE_WAN"
|
||||
}
|
||||
fw_nfqws_post6()
|
||||
{
|
||||
_fw_nfqws_post6 $1 "$2" $3 "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
fw_nfqws_pre4()
|
||||
{
|
||||
_fw_nfqws_pre4 $1 "$2" $3 "$IFACE_WAN"
|
||||
}
|
||||
fw_nfqws_pre6()
|
||||
{
|
||||
_fw_nfqws_pre6 $1 "$2" $3 "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
nft_fw_nfqws_post4()
|
||||
{
|
||||
_nft_fw_nfqws_post4 "$1" $2 "$IFACE_WAN"
|
||||
}
|
||||
nft_fw_nfqws_post6()
|
||||
{
|
||||
_nft_fw_nfqws_post6 "$1" $2 "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
nft_fw_nfqws_pre4()
|
||||
{
|
||||
_nft_fw_nfqws_pre4 "$1" $2 "$IFACE_WAN"
|
||||
}
|
||||
nft_fw_nfqws_pre6()
|
||||
{
|
||||
_nft_fw_nfqws_pre6 "$1" $2 "${IFACE_WAN6:-$IFACE_WAN}"
|
||||
}
|
||||
|
||||
nft_wanif_filter_present()
|
||||
{
|
||||
[ -n "$IFACE_WAN" ]
|
||||
}
|
||||
nft_wanif6_filter_present()
|
||||
{
|
||||
[ -n "${IFACE_WAN6:-$IFACE_WAN}" ]
|
||||
}
|
||||
nft_fill_ifsets_overload()
|
||||
{
|
||||
nft_fill_ifsets "$IFACE_WAN" "${IFACE_WAN6:-$IFACE_WAN}" "$IFACE_LAN"
|
||||
}
|
||||
|
||||
|
||||
run_daemon()
|
||||
{
|
||||
# $1 - daemon number : 1,2,3,...
|
||||
# $2 - daemon
|
||||
# $3 - daemon args
|
||||
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
|
||||
|
||||
local DAEMONBASE="$(basename "$2")"
|
||||
local PID= PIDFILE=$PIDDIR/${DAEMONBASE}_$1.pid
|
||||
echo "Starting daemon $1: $2 $3"
|
||||
|
||||
[ -f "$PIDFILE" ] && {
|
||||
read PID <"$PIDFILE"
|
||||
[ -d "/proc/$PID" ] || PID=
|
||||
}
|
||||
|
||||
if [ -n "$PID" ]; then
|
||||
echo already running
|
||||
else
|
||||
"$2" $3 >/dev/null &
|
||||
PID=$!
|
||||
if [ -n "$PID" ]; then
|
||||
echo $PID >$PIDFILE
|
||||
else
|
||||
echo could not start daemon $1 : $2 $3
|
||||
false
|
||||
fi
|
||||
fi
|
||||
}
|
||||
stop_daemon()
|
||||
{
|
||||
# $1 - daemon number : 1,2,3,...
|
||||
# $2 - daemon
|
||||
# use $PIDDIR/$DAEMONBASE$1.pid as pidfile
|
||||
local DAEMONBASE="$(basename "$2")"
|
||||
local PID PIDFILE=$PIDDIR/${DAEMONBASE}_$1.pid
|
||||
echo "Stopping daemon $1: $2"
|
||||
if [ -f "$PIDFILE" ]; then
|
||||
read PID <"$PIDFILE"
|
||||
kill $PID
|
||||
rm -f "$PIDFILE"
|
||||
else
|
||||
echo no pidfile : $PIDFILE
|
||||
fi
|
||||
}
|
||||
do_daemon()
|
||||
{
|
||||
# $1 - 1 - run, 0 - stop
|
||||
on_off_function run_daemon stop_daemon "$@"
|
||||
}
|
||||
|
||||
do_nfqws()
|
||||
{
|
||||
# $1 : 1 - run, 0 - stop
|
||||
# $2 : daemon number
|
||||
# $3 : daemon args
|
||||
|
||||
do_daemon $1 $2 "$NFQWS2" "$NFQWS2_OPT_BASE $3"
|
||||
}
|
||||
|
||||
|
||||
create_ipset()
|
||||
{
|
||||
echo "Creating ip list table (firewall type $FWTYPE)"
|
||||
"$IPSET_CR" "$@"
|
||||
}
|
||||
82
init.d/sysv/zapret2
Executable file
82
init.d/sysv/zapret2
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: zapret
|
||||
# Required-Start: $local_fs $network
|
||||
# Required-Stop: $local_fs $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
### END INIT INFO
|
||||
|
||||
SCRIPT=$(readlink -f "$0")
|
||||
EXEDIR=$(dirname "$SCRIPT")
|
||||
ZAPRET_BASE=$(readlink -f "$EXEDIR/../..")
|
||||
. "$EXEDIR/functions"
|
||||
|
||||
NAME=zapret
|
||||
DESC=anti-zapret
|
||||
|
||||
do_start()
|
||||
{
|
||||
zapret_run_daemons
|
||||
[ "$INIT_APPLY_FW" != "1" ] || { zapret_apply_firewall; }
|
||||
}
|
||||
do_stop()
|
||||
{
|
||||
zapret_stop_daemons
|
||||
[ "$INIT_APPLY_FW" != "1" ] || zapret_unapply_firewall
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
do_start
|
||||
;;
|
||||
|
||||
stop)
|
||||
do_stop
|
||||
;;
|
||||
|
||||
restart)
|
||||
do_stop
|
||||
do_start
|
||||
;;
|
||||
|
||||
start-fw|start_fw)
|
||||
zapret_apply_firewall
|
||||
;;
|
||||
stop-fw|stop_fw)
|
||||
zapret_unapply_firewall
|
||||
;;
|
||||
|
||||
restart-fw|restart_fw)
|
||||
zapret_unapply_firewall
|
||||
zapret_apply_firewall
|
||||
;;
|
||||
|
||||
start-daemons|start_daemons)
|
||||
zapret_run_daemons
|
||||
;;
|
||||
stop-daemons|stop_daemons)
|
||||
zapret_stop_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
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $SCRIPT {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
|
||||
|
||||
exit 0
|
||||
14
init.d/windivert.filter.examples/README.txt
Normal file
14
init.d/windivert.filter.examples/README.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Цель этих фильтров - отсекать полезную нагрузку в режиме ядра, не насилуя процессор перенаправлением целого потока на winws.
|
||||
Задействуются через `winws --wf-raw-part=@filename`. Может быть несколько частичных фильтров. Они могут сочетаться с --wf-tcp и --wf-udp.
|
||||
Однако, язык фильтров windivert не содержит операций с битовыми полями, сдвигов и побитовой логики.
|
||||
Поэтому фильтры получились более слабыми, способными передавать неправильную нагрузку.
|
||||
Дофильтрация производится силами winws.
|
||||
|
||||
Описание языка фильтров : https://reqrypt.org/windivert-doc.html#filter_language
|
||||
Пример инстанса для пробития медиапотоков в discord : `winws --wf-raw-part=@windivert_part.discord_media.txt --wf-raw-part=@windivert_part.stun.txt --filter-l7=stun,discord --dpi-desync=fake`
|
||||
|
||||
|
||||
These filters are invoked using `winws --wf-raw-part=@filename`. Multiple filter parts are supported. They can be combined with --wf-tcp and --wf-udp.
|
||||
Filters are kernel mode and save great amount of CPU.
|
||||
However windivert cannot filter by bit fields, lacks shift and bitwise logic operations.
|
||||
Filters are relaxed and can pass wrong payloads. Finer filtering is done by winws.
|
||||
@@ -0,0 +1,20 @@
|
||||
outbound and ip and
|
||||
udp.DstPort>=50000 and udp.DstPort<=50099 and
|
||||
udp.PayloadLength=74 and
|
||||
udp.Payload32[0]=0x00010046 and
|
||||
udp.Payload32[2]=0 and
|
||||
udp.Payload32[3]=0 and
|
||||
udp.Payload32[4]=0 and
|
||||
udp.Payload32[5]=0 and
|
||||
udp.Payload32[6]=0 and
|
||||
udp.Payload32[7]=0 and
|
||||
udp.Payload32[8]=0 and
|
||||
udp.Payload32[9]=0 and
|
||||
udp.Payload32[10]=0 and
|
||||
udp.Payload32[11]=0 and
|
||||
udp.Payload32[12]=0 and
|
||||
udp.Payload32[13]=0 and
|
||||
udp.Payload32[14]=0 and
|
||||
udp.Payload32[15]=0 and
|
||||
udp.Payload32[16]=0 and
|
||||
udp.Payload32[17]=0
|
||||
@@ -0,0 +1,4 @@
|
||||
outbound and
|
||||
udp.PayloadLength>=256 and
|
||||
udp.Payload[0]>=0xC0 and udp.Payload[0]<0xD0 and
|
||||
udp.Payload[1]=0 and udp.Payload16[1]=0 and udp.Payload[4]=1
|
||||
3
init.d/windivert.filter.examples/windivert_part.stun.txt
Normal file
3
init.d/windivert.filter.examples/windivert_part.stun.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
outbound and
|
||||
udp.PayloadLength>=20 and
|
||||
udp.Payload32[1]=0x2112A442 and udp.Payload[0]<0x40
|
||||
@@ -0,0 +1,3 @@
|
||||
outbound and
|
||||
udp.PayloadLength=148 and
|
||||
udp.Payload[0]=0x01
|
||||
@@ -30,7 +30,7 @@ select_test_method()
|
||||
TEST=bash
|
||||
elif exists zsh && [ "$UNAME" != CYGWIN ] ; then
|
||||
TEST=zsh
|
||||
elif [ "$UNAME" != Darwin -a "$UNAME" != CYGWIN ]; then
|
||||
elif [ "$UNAME" != CYGWIN ]; then
|
||||
if exists hexdump and exists dd; then
|
||||
# macos does not use ELF
|
||||
TEST=elf
|
||||
@@ -64,12 +64,6 @@ select_test_method()
|
||||
|
||||
}
|
||||
|
||||
disable_antivirus()
|
||||
{
|
||||
# $1 - dir
|
||||
[ "$UNAME" = Darwin ] && find "$1" -maxdepth 1 -type f -perm +111 -exec xattr -d com.apple.quarantine {} \; 2>/dev/null
|
||||
}
|
||||
|
||||
check_dir()
|
||||
{
|
||||
local dir="$BINDIR/$1"
|
||||
@@ -77,7 +71,6 @@ check_dir()
|
||||
local out
|
||||
if [ -f "$exe" ]; then
|
||||
if [ -x "$exe" ]; then
|
||||
disable_antivirus "$dir"
|
||||
case $TEST in
|
||||
bash)
|
||||
out=$(echo 0.0.0.0 | bash -c "\"$exe"\" 2>/dev/null)
|
||||
@@ -143,8 +136,7 @@ if [ ! -d "$BINDIR" ] || ! dir_is_not_empty "$BINDIR" ]; then
|
||||
echo "to compile on other systems : make"
|
||||
;;
|
||||
Darwin)
|
||||
echo "you need to download release from github or build binaries from source"
|
||||
echo "to compile : make mac"
|
||||
echo "macos is not supported"
|
||||
;;
|
||||
FreeBSD)
|
||||
echo "you need to download release from github or build binaries from source"
|
||||
@@ -168,9 +160,6 @@ case $UNAME in
|
||||
ARCHLIST="my linux-x86_64 linux-x86 linux-arm64 linux-arm linux-mips64 linux-mipsel linux-mips linux-lexra linux-ppc"
|
||||
PKTWS=nfqws2
|
||||
;;
|
||||
Darwin)
|
||||
ARCHLIST="my mac64"
|
||||
;;
|
||||
FreeBSD)
|
||||
ARCHLIST="my freebsd-x86_64"
|
||||
PKTWS=dvtws2
|
||||
|
||||
833
install_easy.sh
Executable file
833
install_easy.sh
Executable file
@@ -0,0 +1,833 @@
|
||||
#!/bin/sh
|
||||
|
||||
# automated script for easy installing zapret
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-"$EXEDIR"}
|
||||
ZAPRET_TARGET=${ZAPRET_TARGET:-/opt/zapret2}
|
||||
ZAPRET_TARGET_RW=${ZAPRET_RW:-"$ZAPRET_TARGET"}
|
||||
ZAPRET_TARGET_CONFIG="$ZAPRET_TARGET_RW/config"
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
ZAPRET_CONFIG_DEFAULT="$ZAPRET_BASE/config.default"
|
||||
IPSET_DIR="$ZAPRET_BASE/ipset"
|
||||
|
||||
[ -f "$ZAPRET_CONFIG" ] || {
|
||||
ZAPRET_CONFIG_DIR="$(dirname "$ZAPRET_CONFIG")"
|
||||
[ -d "$ZAPRET_CONFIG_DIR" ] || mkdir -p "$ZAPRET_CONFIG_DIR"
|
||||
cp "$ZAPRET_CONFIG_DEFAULT" "$ZAPRET_CONFIG"
|
||||
}
|
||||
. "$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"
|
||||
. "$ZAPRET_BASE/common/virt.sh"
|
||||
. "$ZAPRET_BASE/common/list.sh"
|
||||
|
||||
GET_LIST="$IPSET_DIR/get_config.sh"
|
||||
|
||||
check_readonly_system()
|
||||
{
|
||||
local RO
|
||||
echo \* checking readonly system
|
||||
case $SYSTEM in
|
||||
systemd)
|
||||
[ -w "$SYSTEMD_SYSTEM_DIR" ] || RO=1
|
||||
;;
|
||||
openrc)
|
||||
[ -w "$(dirname "$INIT_SCRIPT")" ] || RO=1
|
||||
;;
|
||||
esac
|
||||
[ -z "$RO" ] || {
|
||||
echo '!!! READONLY SYSTEM DETECTED !!!'
|
||||
echo '!!! WILL NOT BE ABLE TO CONFIGURE STARTUP !!!'
|
||||
echo '!!! MANUAL STARTUP CONFIGURATION IS REQUIRED !!!'
|
||||
ask_yes_no N "do you want to continue" || exitp 5
|
||||
}
|
||||
}
|
||||
|
||||
check_source()
|
||||
{
|
||||
local bad=0
|
||||
|
||||
echo \* checking source files
|
||||
case $SYSTEM in
|
||||
systemd)
|
||||
[ -f "$EXEDIR/init.d/systemd/zapret2.service" ] || bad=1
|
||||
;;
|
||||
openrc)
|
||||
[ -f "$EXEDIR/init.d/openrc/zapret2" ] || bad=1
|
||||
;;
|
||||
esac
|
||||
[ "$bad" = 1 ] && {
|
||||
echo 'some critical files are missing'
|
||||
echo 'are you sure you are not using embedded release ? you need full version for traditional systems'
|
||||
exitp 5
|
||||
}
|
||||
}
|
||||
|
||||
check_bins()
|
||||
{
|
||||
echo \* checking executables
|
||||
|
||||
fix_perms_bin_test "$EXEDIR"
|
||||
local arch="$(get_bin_arch)"
|
||||
local make_target
|
||||
local cf="-march=native"
|
||||
[ "$FORCE_BUILD" = "1" ] && {
|
||||
echo forced build mode
|
||||
if [ "$arch" = "my" ]; then
|
||||
echo already compiled
|
||||
else
|
||||
arch=""
|
||||
fi
|
||||
}
|
||||
if [ -n "$arch" ] ; then
|
||||
echo found architecture "\"$arch\""
|
||||
elif [ -f "$EXEDIR/Makefile" ] && exists make; then
|
||||
echo trying to compile
|
||||
case $SYSTEM in
|
||||
systemd)
|
||||
make_target=systemd
|
||||
;;
|
||||
esac
|
||||
CFLAGS="${cf:+$cf }${CFLAGS}" OPTIMIZE=-O2 make -C "$EXEDIR" $make_target || {
|
||||
echo could not compile
|
||||
make -C "$EXEDIR" clean
|
||||
exitp 8
|
||||
}
|
||||
echo compiled
|
||||
else
|
||||
echo build tools not found
|
||||
exitp 8
|
||||
fi
|
||||
}
|
||||
|
||||
call_install_bin()
|
||||
{
|
||||
sh "$EXEDIR/install_bin.sh" $1
|
||||
}
|
||||
get_bin_arch()
|
||||
{
|
||||
call_install_bin getarch
|
||||
}
|
||||
|
||||
install_binaries()
|
||||
{
|
||||
echo \* installing binaries
|
||||
|
||||
call_install_bin || {
|
||||
echo compatible binaries not found
|
||||
exitp 8
|
||||
}
|
||||
}
|
||||
|
||||
ws_opt_validate()
|
||||
{
|
||||
# ПРИМЕЧАНИЕ ДЛЯ РАСПРОСТРАНИТЕЛЕЙ КОПИПАСТЫ
|
||||
# ЭТОТ КОД СДЕЛАН СПЕЦИАЛЬНО ДЛЯ ВАС, ЧТОБЫ ВЫ НЕ ПОСТИЛИ В СЕТЬ ПЛОХИЕ РЕЦЕПТЫ
|
||||
# ЕСЛИ ВАМ ХОЧЕТСЯ ЕГО УДАЛИТЬ И НАПИСАТЬ ИНСТРУКЦИЮ КАК ЕГО УДАЛЯТЬ, ВЫ ДЕЛАЕТЕ ХРЕНОВУЮ УСЛУГУ. НАПИШИТЕ ЛУЧШЕ custom script.
|
||||
# custom script - ЭТО ФАЙЛИК, КОТОРЫЙ ДОСТАТОЧНО СКОПИРОВАТЬ В НУЖНУЮ ДИРЕКТОРИЮ, ЧТОБЫ ОН СДЕЛАЛ ТОЖЕ САМОЕ, НО ЭФФЕКТИВНО.
|
||||
# ФИЛЬТРАЦИЯ ПО IPSET В ЯДРЕ НЕСРАВНИМО ЭФФЕКТИВНЕЕ, ЧЕМ ПЕРЕКИДЫВАТЬ ВСЕ ПАКЕТЫ В nfqws И ТАМ ФИЛЬТРОВАТЬ
|
||||
# --ipset СУЩЕСТВУЕТ ТОЛЬКО ДЛЯ ВИНДЫ И LINUX СИСТЕМ БЕЗ ipset (НАПРИМЕР, Android).
|
||||
# И ТОЛЬКО ПО ЭТОЙ ПРИЧИНЕ ОНО НЕ ВЫКИНУТО ПОЛНОСТЬЮ ИЗ LINUX ВЕРСИИ
|
||||
has_bad_ws_options "$1" && {
|
||||
help_bad_ws_options
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
nfqws_opt_validate()
|
||||
{
|
||||
ws_opt_validate "$1" || return 1
|
||||
dry_run_nfqws || {
|
||||
echo invalid nfqws2 options
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
select_mode_group()
|
||||
{
|
||||
# $1 - ENABLE var name
|
||||
# $2 - ask text
|
||||
# $3 - vars
|
||||
# $4 - validator func
|
||||
# $5 - validator func param var
|
||||
|
||||
local enabled var v edited bad Y param
|
||||
|
||||
echo
|
||||
ask_yes_no_var $1 "$2"
|
||||
write_config_var $1
|
||||
eval enabled=\$$1
|
||||
[ "$enabled" = 1 ] && {
|
||||
echo
|
||||
while : ; do
|
||||
list_vars $3
|
||||
bad=0; Y=N
|
||||
[ -n "$4" ] && {
|
||||
eval param="\$$5"
|
||||
$4 "$param"; bad=$?
|
||||
[ "$bad" = 1 ] && Y=Y
|
||||
}
|
||||
ask_yes_no $Y "do you want to edit the options" || {
|
||||
[ "$bad" = 1 ] && {
|
||||
echo installer will not allow to use bad options. exiting.
|
||||
exitp 3
|
||||
}
|
||||
[ -n "$edited" ] && {
|
||||
for var in $3; do
|
||||
write_config_var $var
|
||||
done
|
||||
}
|
||||
break
|
||||
}
|
||||
edit_vars $3
|
||||
edited=1
|
||||
echo ..edited..
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
select_mode_nfqws()
|
||||
{
|
||||
local EDITVAR_NEWLINE_DELIMETERS="--new --out-range --in-range --payload" EDITVAR_NEWLINE_VARS="NFQWS2_OPT"
|
||||
select_mode_group NFQWS2_ENABLE "enable nfqws2 ?" "NFQWS2_PORTS_TCP NFQWS2_PORTS_UDP NFQWS2_TCP_PKT_OUT NFQWS2_TCP_PKT_IN NFQWS2_UDP_PKT_OUT NFQWS2_UDP_PKT_IN NFQWS2_PORTS_TCP_KEEPALIVE NFQWS2_PORTS_UDP_KEEPALIVE NFQWS2_OPT" nfqws_opt_validate NFQWS2_OPT
|
||||
}
|
||||
|
||||
select_mode_mode()
|
||||
{
|
||||
select_mode_nfqws
|
||||
|
||||
echo
|
||||
echo "current custom scripts in $CUSTOM_DIR/custom.d:"
|
||||
[ -d "$CUSTOM_DIR/custom.d" ] && ls "$CUSTOM_DIR/custom.d"
|
||||
echo "Make sure this is ok"
|
||||
echo
|
||||
}
|
||||
|
||||
select_mode_filter()
|
||||
{
|
||||
local filter="none ipset hostlist autohostlist"
|
||||
echo
|
||||
echo select filtering :
|
||||
ask_list MODE_FILTER "$filter" none && write_config_var MODE_FILTER
|
||||
}
|
||||
|
||||
select_mode()
|
||||
{
|
||||
select_mode_filter
|
||||
select_mode_mode
|
||||
select_mode_iface
|
||||
}
|
||||
|
||||
select_getlist()
|
||||
{
|
||||
if [ "$MODE_FILTER" = "ipset" -o "$MODE_FILTER" = "hostlist" -o "$MODE_FILTER" = "autohostlist" ]; then
|
||||
local D=N
|
||||
[ -n "$GETLIST" ] && D=Y
|
||||
echo
|
||||
if ask_yes_no $D "do you want to auto download ip/host list"; then
|
||||
if [ "$MODE_FILTER" = "hostlist" -o "$MODE_FILTER" = "autohostlist" ] ; then
|
||||
GETLISTS="get_refilter_domains.sh get_antizapret_domains.sh get_reestr_resolvable_domains.sh get_reestr_hostlist.sh"
|
||||
GETLIST_DEF="get_antizapret_domains.sh"
|
||||
else
|
||||
GETLISTS="get_user.sh get_refilter_ipsum.sh get_antifilter_ip.sh get_antifilter_ipsmart.sh get_antifilter_ipsum.sh get_antifilter_ipresolve.sh get_antifilter_allyouneed.sh get_reestr_resolve.sh get_reestr_preresolved.sh get_reestr_preresolved_smart.sh"
|
||||
GETLIST_DEF="get_antifilter_allyouneed.sh"
|
||||
fi
|
||||
ask_list GETLIST "$GETLISTS" "$GETLIST_DEF" && write_config_var GETLIST
|
||||
return
|
||||
fi
|
||||
fi
|
||||
GETLIST=""
|
||||
write_config_var GETLIST
|
||||
}
|
||||
|
||||
ask_config()
|
||||
{
|
||||
select_mode
|
||||
select_getlist
|
||||
}
|
||||
|
||||
ask_config_offload()
|
||||
{
|
||||
[ "$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\)
|
||||
if [ "$SYSTEM" = openwrt ]; then
|
||||
echo unfortuantely its not compatible with most nfqws options. nfqws traffic must be exempted from flow offloading.
|
||||
echo donttouch = disable system flow offloading setting if nfqws mode was selected, dont touch it otherwise and dont configure selective flow offloading
|
||||
echo none = always disable system flow offloading setting and dont configure selective flow offloading
|
||||
echo software = always disable system flow offloading setting and configure selective software flow offloading
|
||||
echo hardware = always disable system flow offloading setting and configure selective hardware flow offloading
|
||||
else
|
||||
echo offloading is applicable only to forwarded traffic. it has no effect on outgoing traffic
|
||||
echo hardware flow offloading is available only on specific supporting hardware. most likely will not work on a generic system
|
||||
fi
|
||||
echo offloading likely breaks traffic shaper
|
||||
echo select flow offloading :
|
||||
local options="none software hardware"
|
||||
local default="none"
|
||||
[ "$SYSTEM" = openwrt ] && {
|
||||
options="donttouch none software hardware"
|
||||
default="donttouch"
|
||||
}
|
||||
ask_list FLOWOFFLOAD "$options" $default && write_config_var FLOWOFFLOAD
|
||||
}
|
||||
}
|
||||
|
||||
ask_config_tmpdir()
|
||||
{
|
||||
# ask tmpdir change for low ram systems with enough free disk space
|
||||
[ -n "$GETLIST" ] && [ $(get_free_space_mb "$EXEDIR/tmp") -ge 128 ] && [ $(get_ram_mb) -le 400 ] && {
|
||||
echo
|
||||
echo /tmp in openwrt is tmpfs. on low RAM systems there may be not enough RAM to store downloaded files
|
||||
echo default tmpfs has size of 50% RAM
|
||||
echo "RAM : $(get_ram_mb) Mb"
|
||||
echo "DISK : $(get_free_space_mb) Mb"
|
||||
echo select temp file location
|
||||
[ -z "$TMPDIR" ] && TMPDIR=/tmp
|
||||
ask_list TMPDIR "/tmp $EXEDIR/tmp" && {
|
||||
[ "$TMPDIR" = "/tmp" ] && TMPDIR=
|
||||
write_config_var TMPDIR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nft_flow_offload()
|
||||
{
|
||||
[ "$UNAME" = Linux -a "$FWTYPE" = nftables ] && [ "$FLOWOFFLOAD" = software -o "$FLOWOFFLOAD" = hardware ]
|
||||
}
|
||||
|
||||
ask_iface()
|
||||
{
|
||||
# $1 - var to ask
|
||||
# $2 - additional name for empty string synonim
|
||||
|
||||
local ifs i0 def new
|
||||
eval def="\$$1"
|
||||
|
||||
[ -n "$2" ] && i0="$2 "
|
||||
ifs="$(ls /sys/class/net)"
|
||||
[ -z "$def" ] && eval $1="$2"
|
||||
ask_list $1 "$i0$ifs" && {
|
||||
eval new="\$$1"
|
||||
[ "$new" = "$2" ] && eval $1=""
|
||||
write_config_var $1
|
||||
}
|
||||
}
|
||||
ask_iface_lan()
|
||||
{
|
||||
echo LAN interface :
|
||||
local opt
|
||||
nft_flow_offload || opt=NONE
|
||||
ask_iface IFACE_LAN $opt
|
||||
}
|
||||
ask_iface_wan()
|
||||
{
|
||||
echo WAN interface :
|
||||
local opt
|
||||
nft_flow_offload || opt=ANY
|
||||
ask_iface IFACE_WAN $opt
|
||||
}
|
||||
|
||||
select_mode_iface()
|
||||
{
|
||||
# openwrt has its own interface management scheme
|
||||
# LAN interface names are used only to setup flow offloading rules
|
||||
|
||||
[ "$SYSTEM" = "openwrt" ] && return
|
||||
|
||||
ask_iface_lan
|
||||
ask_iface_wan
|
||||
}
|
||||
|
||||
default_files()
|
||||
{
|
||||
# $1 - ro location
|
||||
# $2 - rw location (can be equal to $1)
|
||||
[ -d "$2/ipset" ] || mkdir -p "$2/ipset"
|
||||
[ -f "$2/ipset/zapret-hosts-user-exclude.txt" ] || cp "$1/ipset/zapret-hosts-user-exclude.txt.default" "$2/ipset/zapret-hosts-user-exclude.txt"
|
||||
[ -f "$2/ipset/zapret-hosts-user.txt" ] || echo nonexistent.domain >> "$2/ipset/zapret-hosts-user.txt"
|
||||
[ -f "$2/ipset/zapret-hosts-user-ipban.txt" ] || touch "$2/ipset/zapret-hosts-user-ipban.txt"
|
||||
for dir in openwrt sysv macos; do
|
||||
[ -d "$1/init.d/$dir" ] && {
|
||||
[ -d "$2/init.d/$dir" ] || mkdir -p "$2/init.d/$dir"
|
||||
[ -d "$2/init.d/$dir/custom.d" ] || mkdir -p "$2/init.d/$dir/custom.d"
|
||||
}
|
||||
done
|
||||
}
|
||||
copy_all()
|
||||
{
|
||||
local dir
|
||||
|
||||
cp -R "$1" "$2"
|
||||
[ -d "$2/tmp" ] || mkdir "$2/tmp"
|
||||
}
|
||||
copy_openwrt()
|
||||
{
|
||||
local ARCH="$(get_bin_arch)"
|
||||
local BINDIR="$1/binaries/$ARCH"
|
||||
local file
|
||||
|
||||
[ -d "$2" ] || mkdir -p "$2"
|
||||
|
||||
mkdir "$2/nfq2" "$2/ip2net" "$2/mdig" "$2/binaries" "$2/binaries/$ARCH" "$2/init.d" "$2/tmp" "$2/files"
|
||||
cp -R "$1/files/fake" "$2/files"
|
||||
cp -R "$1/common" "$1/ipset" "$1/blockcheck2.d" "$1/lua" "$2"
|
||||
cp -R "$1/init.d/openwrt" "$1/init.d/custom.d.examples.linux" "$2/init.d"
|
||||
cp "$1/config" "$1/config.default" "$1/install_easy.sh" "$1/uninstall_easy.sh" "$1/install_bin.sh" "$1/install_prereq.sh" "$1/blockcheck2.sh" "$2"
|
||||
cp "$BINDIR/nfqws2" "$BINDIR/ip2net" "$BINDIR/mdig" "$2/binaries/$ARCH"
|
||||
}
|
||||
|
||||
fix_perms_bin_test()
|
||||
{
|
||||
[ -d "$1" ] || return
|
||||
find "$1/binaries" -name ip2net ! -perm -111 -exec chmod +x {} \;
|
||||
}
|
||||
fix_perms()
|
||||
{
|
||||
[ -d "$1" ] || return
|
||||
find "$1" -type d -exec chmod 755 {} \;
|
||||
find "$1" -type f -exec chmod 644 {} \;
|
||||
local chow
|
||||
case "$UNAME" in
|
||||
Linux)
|
||||
chow=root:root
|
||||
;;
|
||||
*)
|
||||
chow=root:wheel
|
||||
esac
|
||||
chown -R $chow "$1"
|
||||
find "$1/binaries" '(' -name dvtws2 -o -name nfqws2 -o -name ip2net -o -name mdig ')' -exec chmod 755 {} \;
|
||||
for f in \
|
||||
install_bin.sh \
|
||||
blockcheck2.sh \
|
||||
install_easy.sh \
|
||||
install_prereq.sh \
|
||||
files/huawei/E8372/zapret-ip \
|
||||
files/huawei/E8372/unzapret-ip \
|
||||
files/huawei/E8372/run-zapret-hostlist \
|
||||
files/huawei/E8372/unzapret \
|
||||
files/huawei/E8372/zapret \
|
||||
files/huawei/E8372/run-zapret-ip \
|
||||
ipset/get_exclude.sh \
|
||||
ipset/clear_lists.sh \
|
||||
ipset/create_ipset.sh \
|
||||
ipset/get_config.sh \
|
||||
ipset/get_user.sh \
|
||||
ipset/get_ipban.sh \
|
||||
ipset/get_refilter_domains.sh \
|
||||
ipset/get_refilter_ipsum.sh \
|
||||
ipset/get_reestr_resolvable_domains.sh \
|
||||
ipset/get_reestr_preresolved.sh \
|
||||
ipset/get_reestr_preresolved_smart.sh \
|
||||
ipset/get_reestr_resolve.sh \
|
||||
ipset/get_reestr_hostlist.sh \
|
||||
ipset/get_antifilter_allyouneed.sh \
|
||||
ipset/get_antifilter_ipsum.sh \
|
||||
ipset/get_antifilter_ipsmart.sh \
|
||||
ipset/get_antifilter_ip.sh \
|
||||
ipset/get_antifilter_ipresolve.sh \
|
||||
ipset/get_antizapret_domains.sh \
|
||||
init.d/pfsense/zapret2.sh \
|
||||
init.d/runit/zapret2/run \
|
||||
init.d/runit/zapret2/finish \
|
||||
init.d/openrc/zapret2 \
|
||||
init.d/sysv/zapret2 \
|
||||
init.d/openwrt/zapret2 \
|
||||
uninstall_easy.sh \
|
||||
; do chmod 755 "$1/$f" 2>/dev/null ; done
|
||||
}
|
||||
|
||||
|
||||
_backup_settings()
|
||||
{
|
||||
local i=0
|
||||
for f in "$@"; do
|
||||
# safety check
|
||||
[ -z "$f" -o "$f" = "/" ] && continue
|
||||
|
||||
[ -f "$ZAPRET_TARGET/$f" ] && cp -f "$ZAPRET_TARGET/$f" "/tmp/zapret2-bkp-$i"
|
||||
[ -d "$ZAPRET_TARGET/$f" ] && cp -rf "$ZAPRET_TARGET/$f" "/tmp/zapret2-bkp-$i"
|
||||
i=$(($i+1))
|
||||
done
|
||||
}
|
||||
_restore_settings()
|
||||
{
|
||||
local i=0
|
||||
for f in "$@"; do
|
||||
# safety check
|
||||
[ -z "$f" -o "$f" = "/" ] && continue
|
||||
|
||||
[ -f "/tmp/zapret2-bkp-$i" ] && {
|
||||
mv -f "/tmp/zapret2-bkp-$i" "$ZAPRET_TARGET/$f" || rm -f "/tmp/zapret2-bkp-$i"
|
||||
}
|
||||
[ -d "/tmp/zapret2-bkp-$i" ] && {
|
||||
[ -d "$ZAPRET_TARGET/$f" ] && rm -r "$ZAPRET_TARGET/$f"
|
||||
mv -f "/tmp/zapret2-bkp-$i" "$ZAPRET_TARGET/$f" || rm -r "/tmp/zapret2-bkp-$i"
|
||||
}
|
||||
i=$(($i+1))
|
||||
done
|
||||
}
|
||||
backup_restore_settings()
|
||||
{
|
||||
# $1 - 1 - backup, 0 - restore
|
||||
local mode=$1
|
||||
on_off_function _backup_settings _restore_settings $mode "config" "init.d/sysv/custom.d" "init.d/openwrt/custom.d" "ipset/zapret-hosts-user.txt" "ipset/zapret-hosts-user-exclude.txt" "ipset/zapret-hosts-user-ipban.txt" "ipset/zapret-hosts-auto.txt"
|
||||
}
|
||||
|
||||
check_location()
|
||||
{
|
||||
# $1 - copy function
|
||||
|
||||
echo \* checking location
|
||||
# use inodes in case something is linked
|
||||
if [ -d "$ZAPRET_TARGET" ] && [ $(get_dir_inode "$EXEDIR") = $(get_dir_inode "$ZAPRET_TARGET") ]; then
|
||||
default_files "$ZAPRET_TARGET" "$ZAPRET_RW"
|
||||
else
|
||||
local rwdir=0
|
||||
[ $(get_dir_inode "$ZAPRET_BASE") = $(get_dir_inode "$ZAPRET_RW") ] || rwdir=1
|
||||
echo
|
||||
echo easy install is supported only from default location : $ZAPRET_TARGET
|
||||
echo currently its run from $EXEDIR
|
||||
if ask_yes_no N "do you want the installer to copy it for you"; then
|
||||
local keep=N
|
||||
if [ -d "$ZAPRET_TARGET" ]; then
|
||||
echo
|
||||
echo installer found existing $ZAPRET_TARGET
|
||||
echo directory needs to be replaced. config and custom scripts can be kept or replaced with clean version
|
||||
if ask_yes_no N "do you want to delete all files there and copy this version"; then
|
||||
echo
|
||||
if [ $rwdir != 1 ]; then
|
||||
ask_yes_no Y "keep config, custom scripts and user lists" && keep=Y
|
||||
[ "$keep" = "Y" ] && backup_restore_settings 1
|
||||
fi
|
||||
rm -r "$ZAPRET_TARGET"
|
||||
else
|
||||
echo refused to overwrite $ZAPRET_TARGET. exiting
|
||||
exitp 3
|
||||
fi
|
||||
fi
|
||||
local B="$(dirname "$ZAPRET_TARGET")"
|
||||
[ -d "$B" ] || mkdir -p "$B"
|
||||
$1 "$EXEDIR" "$ZAPRET_TARGET"
|
||||
fix_perms "$ZAPRET_TARGET"
|
||||
[ "$keep" = "Y" ] && backup_restore_settings 0
|
||||
echo relaunching itself from $ZAPRET_TARGET
|
||||
exec "$ZAPRET_TARGET/$(basename "$0")"
|
||||
else
|
||||
echo copying aborted. exiting
|
||||
exitp 3
|
||||
fi
|
||||
fi
|
||||
echo running from $EXEDIR
|
||||
}
|
||||
|
||||
|
||||
service_install_systemd()
|
||||
{
|
||||
echo \* installing zapret service
|
||||
|
||||
if [ -w "$SYSTEMD_SYSTEM_DIR" ] ; then
|
||||
rm -f "$INIT_SCRIPT"
|
||||
cp -f "$EXEDIR/init.d/systemd/zapret2.service" "$SYSTEMD_SYSTEM_DIR"
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
"$SYSTEMCTL" enable zapret2 || {
|
||||
echo could not enable systemd service
|
||||
exitp 20
|
||||
}
|
||||
else
|
||||
echo '!!! READONLY SYSTEM DETECTED !!! CANNOT INSTALL SYSTEMD UNITS !!!'
|
||||
fi
|
||||
}
|
||||
|
||||
timer_install_systemd()
|
||||
{
|
||||
echo \* installing zapret2-list-update timer
|
||||
|
||||
if [ -w "$SYSTEMD_SYSTEM_DIR" ] ; then
|
||||
"$SYSTEMCTL" disable zapret2-list-update.timer
|
||||
"$SYSTEMCTL" stop zapret2-list-update.timer
|
||||
cp -f "$EXEDIR/init.d/systemd/zapret2-list-update.service" "$SYSTEMD_SYSTEM_DIR"
|
||||
cp -f "$EXEDIR/init.d/systemd/zapret2-list-update.timer" "$SYSTEMD_SYSTEM_DIR"
|
||||
"$SYSTEMCTL" daemon-reload
|
||||
"$SYSTEMCTL" enable zapret2-list-update.timer || {
|
||||
echo could not enable zapret2-list-update.timer
|
||||
exitp 20
|
||||
}
|
||||
"$SYSTEMCTL" start zapret2-list-update.timer || {
|
||||
echo could not start zapret2-list-update.timer
|
||||
exitp 30
|
||||
}
|
||||
else
|
||||
echo '!!! READONLY SYSTEM DETECTED !!! CANNOT INSTALL SYSTEMD UNITS !!!'
|
||||
fi
|
||||
}
|
||||
|
||||
download_list()
|
||||
{
|
||||
[ -x "$GET_LIST" ] && {
|
||||
echo \* downloading blocked ip/host list
|
||||
|
||||
# can be txt or txt.gz
|
||||
"$IPSET_DIR/clear_lists.sh"
|
||||
"$GET_LIST"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dnstest()
|
||||
{
|
||||
# $1 - dns server. empty for system resolver
|
||||
nslookup w3.org $1 >/dev/null 2>/dev/null
|
||||
}
|
||||
check_dns()
|
||||
{
|
||||
echo \* checking DNS
|
||||
|
||||
dnstest || {
|
||||
echo -- DNS is not working. It's either misconfigured or blocked or you don't have inet access.
|
||||
return 1
|
||||
}
|
||||
echo system DNS is working
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
install_systemd()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
|
||||
|
||||
check_bins
|
||||
require_root
|
||||
check_readonly_system
|
||||
check_location copy_all
|
||||
check_dns
|
||||
check_virt
|
||||
service_stop_systemd
|
||||
select_fwtype
|
||||
check_prerequisites_linux
|
||||
install_binaries
|
||||
select_ipv6
|
||||
ask_config_offload
|
||||
ask_config
|
||||
service_install_systemd
|
||||
download_list
|
||||
# in case its left from old version of zapret
|
||||
crontab_del_quiet
|
||||
# now we use systemd timers
|
||||
timer_install_systemd
|
||||
service_start_systemd
|
||||
}
|
||||
|
||||
_install_sysv()
|
||||
{
|
||||
# $1 - install init script
|
||||
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
|
||||
|
||||
check_bins
|
||||
require_root
|
||||
check_readonly_system
|
||||
check_location copy_all
|
||||
check_dns
|
||||
check_virt
|
||||
service_stop_sysv
|
||||
select_fwtype
|
||||
check_prerequisites_linux
|
||||
install_binaries
|
||||
select_ipv6
|
||||
ask_config_offload
|
||||
ask_config
|
||||
$1
|
||||
download_list
|
||||
crontab_del_quiet
|
||||
# desktop system. more likely up at daytime
|
||||
crontab_add 10 22
|
||||
service_start_sysv
|
||||
}
|
||||
|
||||
install_sysv()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret2"
|
||||
_install_sysv install_sysv_init
|
||||
}
|
||||
|
||||
install_openrc()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/openrc/zapret2"
|
||||
_install_sysv install_openrc_init
|
||||
}
|
||||
|
||||
|
||||
install_linux()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret2"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/sysv"
|
||||
|
||||
check_bins
|
||||
require_root
|
||||
check_location copy_all
|
||||
check_dns
|
||||
check_virt
|
||||
select_fwtype
|
||||
check_prerequisites_linux
|
||||
install_binaries
|
||||
select_ipv6
|
||||
ask_config_offload
|
||||
ask_config
|
||||
download_list
|
||||
crontab_del_quiet
|
||||
# desktop system. more likely up at daytime
|
||||
crontab_add 10 22
|
||||
|
||||
echo
|
||||
echo '!!! WARNING. YOUR SETUP IS INCOMPLETE !!!'
|
||||
echo you must manually add to auto start : $INIT_SCRIPT_SRC start
|
||||
echo make sure it\'s executed after your custom/firewall iptables configuration
|
||||
echo "if your system uses sysv init : ln -fs $INIT_SCRIPT_SRC /etc/init.d/zapret ; chkconfig zapret on"
|
||||
}
|
||||
|
||||
|
||||
deoffload_openwrt_firewall()
|
||||
{
|
||||
echo \* checking flow offloading
|
||||
|
||||
[ "$FWTYPE" = "nftables" ] || is_ipt_flow_offload_avail || {
|
||||
echo unavailable
|
||||
return
|
||||
}
|
||||
|
||||
local fo=$(uci -q get firewall.@defaults[0].flow_offloading)
|
||||
|
||||
if [ "$fo" = "1" ] ; then
|
||||
local mod=0
|
||||
printf "system wide flow offloading detected. "
|
||||
case $FLOWOFFLOAD in
|
||||
donttouch)
|
||||
if [ "$NFQWS2_ENABLE" = "1" ]; then
|
||||
echo its incompatible with nfqws tcp data tampering. disabling
|
||||
uci set firewall.@defaults[0].flow_offloading=0
|
||||
mod=1
|
||||
else
|
||||
if dir_is_not_empty "$CUSTOM_DIR/custom.d" ; then
|
||||
echo
|
||||
echo !!! CUSTOM SCRIPTS ARE PRESENT !!! only you can decide whether flow offloading is compatible.
|
||||
echo !!! CUSTOM SCRIPTS ARE PRESENT !!! if they use nfqws they will not work. you have to disable system-wide offloading.
|
||||
else
|
||||
echo its compatible with selected options. not disabling
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo zapret will disable system wide offloading setting and add selective rules if required
|
||||
uci set firewall.@defaults[0].flow_offloading=0
|
||||
mod=1
|
||||
esac
|
||||
[ "$mod" = "1" ] && uci commit firewall
|
||||
else
|
||||
echo system wide software flow offloading disabled. ok
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
install_openwrt()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/openwrt/zapret2"
|
||||
CUSTOM_DIR="$ZAPRET_RW/init.d/openwrt"
|
||||
FW_SCRIPT_SRC="$EXEDIR/init.d/openwrt/firewall.zapret2"
|
||||
OPENWRT_FW_INCLUDE=/etc/firewall.zapret2
|
||||
OPENWRT_IFACE_HOOK="$EXEDIR/init.d/openwrt/90-zapret2"
|
||||
|
||||
check_bins
|
||||
require_root
|
||||
check_location copy_openwrt
|
||||
install_binaries
|
||||
check_dns
|
||||
check_virt
|
||||
|
||||
local FWTYPE_OLD=$FWTYPE
|
||||
|
||||
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
|
||||
[ "$FWTYPE_OLD" != "$FWTYPE" -a "$FWTYPE_OLD" = iptables -a -n "$OPENWRT_FW3" ] && remove_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
|
||||
install_openwrt_iface_hook
|
||||
# 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
|
||||
}
|
||||
|
||||
|
||||
|
||||
remove_pf_zapret_hooks()
|
||||
{
|
||||
echo \* removing zapret PF hooks
|
||||
|
||||
pf_anchors_clear
|
||||
}
|
||||
|
||||
macos_fw_reload_trigger_clear()
|
||||
{
|
||||
LISTS_RELOAD=
|
||||
write_config_var LISTS_RELOAD
|
||||
}
|
||||
macos_fw_reload_trigger_set()
|
||||
{
|
||||
LISTS_RELOAD="$INIT_SCRIPT_SRC reload-fw-tables"
|
||||
write_config_var LISTS_RELOAD
|
||||
}
|
||||
|
||||
|
||||
|
||||
# build binaries, do not use precompiled
|
||||
[ "$1" = "make" ] && FORCE_BUILD=1
|
||||
|
||||
umask 0022
|
||||
fix_sbin_path
|
||||
fsleep_setup
|
||||
check_system
|
||||
check_source
|
||||
|
||||
case $SYSTEM in
|
||||
systemd)
|
||||
install_systemd
|
||||
;;
|
||||
openrc)
|
||||
install_openrc
|
||||
;;
|
||||
linux)
|
||||
install_linux
|
||||
;;
|
||||
openwrt)
|
||||
install_openwrt
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
exitp 0
|
||||
51
install_prereq.sh
Executable file
51
install_prereq.sh
Executable file
@@ -0,0 +1,51 @@
|
||||
#!/bin/sh
|
||||
|
||||
# install prerequisites
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-"$EXEDIR"}
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
ZAPRET_CONFIG_DEFAULT="$ZAPRET_BASE/config.default"
|
||||
|
||||
[ -f "$ZAPRET_CONFIG" ] || {
|
||||
ZAPRET_CONFIG_DIR="$(dirname "$ZAPRET_CONFIG")"
|
||||
[ -d "$ZAPRET_CONFIG_DIR" ] || mkdir -p "$ZAPRET_CONFIG_DIR"
|
||||
cp "$ZAPRET_CONFIG_DEFAULT" "$ZAPRET_CONFIG"
|
||||
}
|
||||
|
||||
. "$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/installer.sh"
|
||||
. "$ZAPRET_BASE/common/ipt.sh"
|
||||
|
||||
umask 0022
|
||||
fix_sbin_path
|
||||
fsleep_setup
|
||||
check_system accept_unknown_rc
|
||||
[ $UNAME = "Linux" ] || {
|
||||
echo no prerequisites required for $UNAME
|
||||
exitp 0
|
||||
}
|
||||
require_root
|
||||
|
||||
case $UNAME in
|
||||
Linux)
|
||||
select_fwtype
|
||||
case $SYSTEM in
|
||||
openwrt)
|
||||
select_ipv6
|
||||
check_prerequisites_openwrt
|
||||
;;
|
||||
*)
|
||||
check_prerequisites_linux
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
exitp 0
|
||||
19
ipset/antifilter.helper
Normal file
19
ipset/antifilter.helper
Normal file
@@ -0,0 +1,19 @@
|
||||
get_antifilter()
|
||||
{
|
||||
# $1 - list url
|
||||
# $2 - target file
|
||||
local ZIPLISTTMP="$TMPDIR/zapret-ip.txt"
|
||||
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
curl --fail --max-time 150 --connect-timeout 20 --max-filesize 41943040 -k -L "$1" | cut_local >"$ZIPLISTTMP" &&
|
||||
{
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$ZIPLISTTMP" | xargs | cut -f 1 -d ' ')
|
||||
if [ $dlsize -lt 102400 ]; then
|
||||
echo list file is too small. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
ip2net4 <"$ZIPLISTTMP" | zz "$2"
|
||||
rm -f "$ZIPLISTTMP"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
ipset/clear_lists.sh
Executable file
8
ipset/clear_lists.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
rm -f "$ZIPLIST"* "$ZIPLIST6"* "$ZIPLIST_USER" "$ZIPLIST_USER6" "$ZIPLIST_IPBAN"* "$ZIPLIST_IPBAN6"* "$ZIPLIST_USER_IPBAN" "$ZIPLIST_USER_IPBAN6" "$ZIPLIST_EXCLUDE" "$ZIPLIST_EXCLUDE6" "$ZHOSTLIST"*
|
||||
308
ipset/create_ipset.sh
Executable file
308
ipset/create_ipset.sh
Executable file
@@ -0,0 +1,308 @@
|
||||
#!/bin/sh
|
||||
|
||||
# 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
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
|
||||
. "$EXEDIR/def.sh"
|
||||
. "$ZAPRET_BASE/common/fwtype.sh"
|
||||
. "$ZAPRET_BASE/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
|
||||
|
||||
IPSET_HOOK_TEMP="$TMPDIR/ipset_hook.txt"
|
||||
|
||||
while [ -n "$1" ]; do
|
||||
[ "$1" = "no-update" ] && NO_UPDATE=1
|
||||
[ "$1" = "clear" ] && DO_CLEAR=1
|
||||
shift
|
||||
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"
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
ipset_get_script()
|
||||
{
|
||||
# $1 - ipset name
|
||||
sed -nEe "s/^.+$/add $1 &/p"
|
||||
}
|
||||
ipset_get_script_from_file()
|
||||
{
|
||||
# $1 - filename
|
||||
# $2 - ipset name
|
||||
zzcat "$1" | sort -u | ipset_get_script $2
|
||||
}
|
||||
ipset_restore()
|
||||
{
|
||||
# $1 - ipset name
|
||||
# $2 - filename
|
||||
|
||||
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
|
||||
|
||||
local T="Adding to ipset $1 "
|
||||
[ "$svram" = "1" ] && T="$T (saveram)"
|
||||
T="$T : $f"
|
||||
echo $T
|
||||
|
||||
if [ "$svram" = "1" ]; then
|
||||
ipset_get_script_from_file "$2" "$1" >"$IPSET_CMD"
|
||||
ipset_restore_chunked "$IPSET_CMD" $IPSET_SAVERAM_CHUNK_SIZE
|
||||
rm -f "$IPSET_CMD"
|
||||
else
|
||||
ipset_get_script_from_file "$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 0
|
||||
}
|
||||
ipset flush $2
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
for f in "$5" "$6" ; do
|
||||
ipset_restore "$2" "$f"
|
||||
done
|
||||
[ -n "$IPSET_HOOK" ] && $IPSET_HOOK $2 | ipset_get_script $2 | ipset -! restore
|
||||
}
|
||||
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" 2>/dev/null | 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"
|
||||
local hookfile
|
||||
[ -n "$IPSET_HOOK" ] && {
|
||||
$IPSET_HOOK $1 >"$IPSET_HOOK_TEMP"
|
||||
[ -s "$IPSET_HOOK_TEMP" ] && hookfile=$IPSET_HOOK_TEMP
|
||||
}
|
||||
nfset_get_script_multi "$@" $hookfile | nft -f -
|
||||
rm -f "$IPSET_HOOK_TEMP"
|
||||
}
|
||||
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 0
|
||||
nft flush set inet $ZAPRET_NFT_TABLE $2
|
||||
}
|
||||
[ "$DO_CLEAR" = "1" ] || {
|
||||
nfset_restore $2 $4 $5
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
add_ipfw_table()
|
||||
{
|
||||
# $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
|
||||
}
|
||||
create_ipfw_table()
|
||||
{
|
||||
# $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 0
|
||||
}
|
||||
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
|
||||
[ -n "$IPSET_HOOK" ] && $IPSET_HOOK $name | add_ipfw_table $name
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
print_reloading_backend()
|
||||
{
|
||||
# $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
|
||||
[ -n "$IPSET_HOOK" ] && $IPSET_HOOK
|
||||
fi
|
||||
else
|
||||
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
|
||||
283
ipset/def.sh
Normal file
283
ipset/def.sh
Normal file
@@ -0,0 +1,283 @@
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-"$(cd "$EXEDIR/.."; pwd)"}
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
IPSET_RW_DIR="$ZAPRET_RW/ipset"
|
||||
|
||||
[ -f "$ZAPRET_CONFIG" ] && . "$ZAPRET_CONFIG"
|
||||
. "$ZAPRET_BASE/common/base.sh"
|
||||
|
||||
[ -z "$TMPDIR" ] && TMPDIR=/tmp
|
||||
[ -z "$GZIP_LISTS" ] && GZIP_LISTS=1
|
||||
|
||||
[ -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
|
||||
ZIPSET_EXCLUDE6=nozapret6
|
||||
ZIPLIST="$IPSET_RW_DIR/zapret-ip.txt"
|
||||
ZIPLIST6="$IPSET_RW_DIR/zapret-ip6.txt"
|
||||
ZIPLIST_EXCLUDE="$IPSET_RW_DIR/zapret-ip-exclude.txt"
|
||||
ZIPLIST_EXCLUDE6="$IPSET_RW_DIR/zapret-ip-exclude6.txt"
|
||||
ZIPLIST_USER="$IPSET_RW_DIR/zapret-ip-user.txt"
|
||||
ZIPLIST_USER6="$IPSET_RW_DIR/zapret-ip-user6.txt"
|
||||
ZUSERLIST="$IPSET_RW_DIR/zapret-hosts-user.txt"
|
||||
ZHOSTLIST="$IPSET_RW_DIR/zapret-hosts.txt"
|
||||
|
||||
ZIPSET_IPBAN=ipban
|
||||
ZIPSET_IPBAN6=ipban6
|
||||
ZIPLIST_IPBAN="$IPSET_RW_DIR/zapret-ip-ipban.txt"
|
||||
ZIPLIST_IPBAN6="$IPSET_RW_DIR/zapret-ip-ipban6.txt"
|
||||
ZIPLIST_USER_IPBAN="$IPSET_RW_DIR/zapret-ip-user-ipban.txt"
|
||||
ZIPLIST_USER_IPBAN6="$IPSET_RW_DIR/zapret-ip-user-ipban6.txt"
|
||||
ZUSERLIST_IPBAN="$IPSET_RW_DIR/zapret-hosts-user-ipban.txt"
|
||||
ZUSERLIST_EXCLUDE="$IPSET_RW_DIR/zapret-hosts-user-exclude.txt"
|
||||
|
||||
|
||||
[ -n "$IP2NET" ] || IP2NET="$ZAPRET_BASE/ip2net/ip2net"
|
||||
[ -n "$MDIG" ] || MDIG="$ZAPRET_BASE/mdig/mdig"
|
||||
[ -z "$MDIG_THREADS" ] && MDIG_THREADS=30
|
||||
|
||||
|
||||
|
||||
# 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
|
||||
if [ -x /usr/local/bin/ggrep ] ; then
|
||||
GREP=/usr/local/bin/ggrep
|
||||
elif [ -x /usr/local/bin/grep ] ; then
|
||||
GREP=/usr/local/bin/grep
|
||||
elif exists ggrep; then
|
||||
GREP=$(whichq ggrep)
|
||||
else
|
||||
GREP=$(whichq grep)
|
||||
fi
|
||||
|
||||
# GNU awk is faster
|
||||
if exists gawk; then
|
||||
AWK=gawk
|
||||
else
|
||||
AWK=awk
|
||||
fi
|
||||
|
||||
grep_supports_b()
|
||||
{
|
||||
# \b does not work with BSD grep
|
||||
$GREP --version 2>&1 | $GREP -qE "BusyBox|GNU"
|
||||
}
|
||||
get_ip_regex()
|
||||
{
|
||||
REG_IPV4='((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\/([0-9]|[12][0-9]|3[012]))?'
|
||||
REG_IPV6='[0-9a-fA-F]{1,4}:([0-9a-fA-F]{1,4}|:)+(\/([0-9][0-9]?|1[01][0-9]|12[0-8]))?'
|
||||
# good but too slow
|
||||
# REG_IPV6='([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,7}:(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}(/[0-9]+)?|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}(/[0-9]+)?|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})(/[0-9]+)?|:((:[0-9a-fA-F]{1,4}){1,7}|:)(/([0-9][0-9]?|1[01][0-9]|12[0-8]))?'
|
||||
# grep_supports_b && {
|
||||
# REG_IPV4="\b$REG_IPV4\b"
|
||||
# REG_IPV6="\b$REG_IPV6\b"
|
||||
# }
|
||||
}
|
||||
|
||||
ip2net4()
|
||||
{
|
||||
if [ -x "$IP2NET" ]; then
|
||||
"$IP2NET" -4 $IP2NET_OPT4
|
||||
else
|
||||
sort -u
|
||||
fi
|
||||
}
|
||||
ip2net6()
|
||||
{
|
||||
if [ -x "$IP2NET" ]; then
|
||||
"$IP2NET" -6 $IP2NET_OPT6
|
||||
else
|
||||
sort -u
|
||||
fi
|
||||
}
|
||||
|
||||
zzexist()
|
||||
{
|
||||
[ -f "$1.gz" ] || [ -f "$1" ]
|
||||
}
|
||||
zztest()
|
||||
{
|
||||
gzip -t "$1" 2>/dev/null
|
||||
}
|
||||
zzcat()
|
||||
{
|
||||
if [ -f "$1.gz" ]; then
|
||||
gunzip -c "$1.gz"
|
||||
elif [ -f "$1" ]; then
|
||||
if zztest "$1"; then
|
||||
gunzip -c "$1"
|
||||
else
|
||||
cat "$1"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
zz()
|
||||
{
|
||||
if [ "$GZIP_LISTS" = "1" ]; then
|
||||
gzip -c >"$1.gz"
|
||||
rm -f "$1"
|
||||
else
|
||||
cat >"$1"
|
||||
rm -f "$1.gz"
|
||||
fi
|
||||
}
|
||||
zzsize()
|
||||
{
|
||||
local f="$1"
|
||||
[ -f "$1.gz" ] && f="$1.gz"
|
||||
if [ -f "$f" ]; then
|
||||
wc -c <"$f" | xargs
|
||||
else
|
||||
printf 0
|
||||
fi
|
||||
}
|
||||
zzcopy()
|
||||
{
|
||||
local is_gz=0
|
||||
zztest "$1" && is_gz=1
|
||||
if [ "$GZIP_LISTS" = 1 -a $is_gz = 1 ]; then
|
||||
cp "$1" "${2}.gz"
|
||||
elif [ "$GZIP_LISTS" != 1 -a $is_gz != 1 ]; then
|
||||
cp "$1" "$2"
|
||||
else
|
||||
zzcat "$1" | zz "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
digger()
|
||||
{
|
||||
# $1 - family (4|6)
|
||||
# $2 - s=enable mdig stats
|
||||
if [ -x "$MDIG" ]; then
|
||||
local cmd
|
||||
[ "$2" = "s" ] && cmd=--stats=1000
|
||||
"$MDIG" --family=$1 --threads=$MDIG_THREADS $cmd
|
||||
else
|
||||
local A=A
|
||||
[ "$1" = "6" ] && A=AAAA
|
||||
dig $A +short +time=8 +tries=2 -f - | $GREP -E '^[^;].*[^\.]$'
|
||||
fi
|
||||
}
|
||||
filedigger()
|
||||
{
|
||||
# $1 - hostlist
|
||||
# $2 - family (4|6)
|
||||
>&2 echo digging $(wc -l <"$1" | xargs) ipv$2 domains : "$1"
|
||||
zzcat "$1" | digger $2 s
|
||||
}
|
||||
flush_dns_cache()
|
||||
{
|
||||
echo clearing all known DNS caches
|
||||
|
||||
if exists killall; then
|
||||
killall -HUP dnsmasq 2>/dev/null
|
||||
# MacOS
|
||||
killall -HUP mDNSResponder 2>/dev/null
|
||||
elif exists pkill; then
|
||||
pkill -HUP ^dnsmasq$
|
||||
else
|
||||
echo no mass killer available ! cant flush dnsmasq
|
||||
fi
|
||||
|
||||
if exists rndc; then
|
||||
rndc flush
|
||||
fi
|
||||
|
||||
if exists systemd-resolve; then
|
||||
systemd-resolve --flush-caches
|
||||
fi
|
||||
|
||||
}
|
||||
dnstest()
|
||||
{
|
||||
local ip="$(echo w3.org | digger 46)"
|
||||
[ -n "$ip" ]
|
||||
}
|
||||
dnstest_with_cache_clear()
|
||||
{
|
||||
flush_dns_cache
|
||||
if dnstest ; then
|
||||
echo DNS is working
|
||||
return 0
|
||||
else
|
||||
echo "! DNS is not working"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
cut_local()
|
||||
{
|
||||
$GREP -vE '^192\.168\.|^127\.|^10\.'
|
||||
}
|
||||
cut_local6()
|
||||
{
|
||||
$GREP -vE '^::|^fc..:|^fd..:|^fe8.:|^fe9.:|^fea.:|^feb.:|^FC..:|^FD..:|^FE8.:|^FE9.:|^FEA.:|^FEB.:'
|
||||
}
|
||||
|
||||
oom_adjust_high()
|
||||
{
|
||||
[ -f /proc/$$/oom_score_adj ] && {
|
||||
echo setting high oom kill priority
|
||||
echo -n 100 >/proc/$$/oom_score_adj
|
||||
}
|
||||
}
|
||||
|
||||
getexclude()
|
||||
{
|
||||
oom_adjust_high
|
||||
dnstest_with_cache_clear || return
|
||||
[ -f "$ZUSERLIST_EXCLUDE" ] && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && filedigger "$ZUSERLIST_EXCLUDE" 4 | sort -u > "$ZIPLIST_EXCLUDE"
|
||||
[ "$DISABLE_IPV6" != "1" ] && filedigger "$ZUSERLIST_EXCLUDE" 6 | sort -u > "$ZIPLIST_EXCLUDE6"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
_get_ipban()
|
||||
{
|
||||
[ -f "$ZUSERLIST_IPBAN" ] && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && filedigger "$ZUSERLIST_IPBAN" 4 | cut_local | sort -u > "$ZIPLIST_USER_IPBAN"
|
||||
[ "$DISABLE_IPV6" != "1" ] && filedigger "$ZUSERLIST_IPBAN" 6 | cut_local6 | sort -u > "$ZIPLIST_USER_IPBAN6"
|
||||
}
|
||||
}
|
||||
getuser()
|
||||
{
|
||||
getexclude || return
|
||||
[ -f "$ZUSERLIST" ] && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && filedigger "$ZUSERLIST" 4 | cut_local | sort -u > "$ZIPLIST_USER"
|
||||
[ "$DISABLE_IPV6" != "1" ] && filedigger "$ZUSERLIST" 6 | cut_local6 | sort -u > "$ZIPLIST_USER6"
|
||||
}
|
||||
_get_ipban
|
||||
return 0
|
||||
}
|
||||
getipban()
|
||||
{
|
||||
getexclude || return
|
||||
_get_ipban
|
||||
return 0
|
||||
}
|
||||
|
||||
hup_zapret_daemons()
|
||||
{
|
||||
echo forcing zapret daemons to reload their hostlist
|
||||
if exists killall; then
|
||||
killall -HUP tpws nfqws dvtws 2>/dev/null
|
||||
elif exists pkill; then
|
||||
pkill -HUP ^tpws$
|
||||
pkill -HUP ^nfqws$
|
||||
pkill -HUP ^dvtws$
|
||||
else
|
||||
echo no mass killer available ! cant HUP zapret daemons
|
||||
fi
|
||||
}
|
||||
13
ipset/get_antifilter_allyouneed.sh
Executable file
13
ipset/get_antifilter_allyouneed.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.download/list/allyouneed.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
13
ipset/get_antifilter_ip.sh
Executable file
13
ipset/get_antifilter_ip.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.download/list/ip.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
13
ipset/get_antifilter_ipresolve.sh
Executable file
13
ipset/get_antifilter_ipresolve.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.download/list/ipresolve.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
13
ipset/get_antifilter_ipsmart.sh
Executable file
13
ipset/get_antifilter_ipsmart.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.network/download/ipsmart.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
13
ipset/get_antifilter_ipsum.sh
Executable file
13
ipset/get_antifilter_ipsum.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser && {
|
||||
. "$IPSET_DIR/antifilter.helper"
|
||||
get_antifilter https://antifilter.download/list/ipsum.lst "$ZIPLIST"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
36
ipset/get_antizapret_domains.sh
Executable file
36
ipset/get_antizapret_domains.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
# useful in case ipban set is used in custom scripts
|
||||
FAIL=
|
||||
getipban || FAIL=1
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
[ -n "$FAIL" ] && exit
|
||||
|
||||
ZURL=https://antizapret.prostovpn.org:8443/domains-export.txt
|
||||
ZDOM="$TMPDIR/zapret.txt"
|
||||
|
||||
|
||||
curl -H "Accept-Encoding: gzip" -k --fail --max-time 600 --connect-timeout 5 --retry 3 --max-filesize 251658240 "$ZURL" | gunzip - >"$ZDOM" ||
|
||||
{
|
||||
echo domain list download failed
|
||||
exit 2
|
||||
}
|
||||
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$ZDOM" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt 102400; then
|
||||
echo list file is too small. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
|
||||
sort -u "$ZDOM" | zz "$ZHOSTLIST"
|
||||
|
||||
rm -f "$ZDOM"
|
||||
|
||||
hup_zapret_daemons
|
||||
|
||||
exit 0
|
||||
10
ipset/get_config.sh
Executable file
10
ipset/get_config.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
# run script specified in config
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
[ -f "$IPSET_DIR/../config" ] && . "$IPSET_DIR/../config"
|
||||
|
||||
[ -z "$GETLIST" ] && GETLIST=get_ipban.sh
|
||||
[ -x "$IPSET_DIR/$GETLIST" ] && exec "$IPSET_DIR/$GETLIST"
|
||||
11
ipset/get_exclude.sh
Executable file
11
ipset/get_exclude.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# resolve user host list
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getexclude
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
11
ipset/get_ipban.sh
Executable file
11
ipset/get_ipban.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# resolve only ipban user host list
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getipban
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
65
ipset/get_reestr_hostlist.sh
Executable file
65
ipset/get_reestr_hostlist.sh
Executable file
@@ -0,0 +1,65 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
ZREESTR="$TMPDIR/zapret.txt.gz"
|
||||
IPB="$TMPDIR/ipb.txt"
|
||||
ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv.gz
|
||||
|
||||
dl_checked()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
# $5 - maxtime
|
||||
curl -k --fail --max-time $5 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$2" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
return 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
return 2
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
reestr_list()
|
||||
{
|
||||
LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }'
|
||||
}
|
||||
reestr_extract_ip()
|
||||
{
|
||||
LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}'
|
||||
}
|
||||
|
||||
ipban_fin()
|
||||
{
|
||||
getipban
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
}
|
||||
|
||||
dl_checked "$ZURL_REESTR" "$ZREESTR" 204800 251658240 600 || {
|
||||
ipban_fin
|
||||
exit 2
|
||||
}
|
||||
|
||||
reestr_list | sort -u | zz "$ZHOSTLIST"
|
||||
|
||||
reestr_extract_ip <"$ZREESTR" >"$IPB"
|
||||
|
||||
rm -f "$ZREESTR"
|
||||
[ "$DISABLE_IPV4" != "1" ] && $AWK '/^([0-9]{1,3}\.){3}[0-9]{1,3}($|(\/[0-9]{2}$))/' "$IPB" | cut_local | ip2net4 | zz "$ZIPLIST_IPBAN"
|
||||
[ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6"
|
||||
rm -f "$IPB"
|
||||
|
||||
hup_zapret_daemons
|
||||
|
||||
ipban_fin
|
||||
|
||||
exit 0
|
||||
47
ipset/get_reestr_preresolved.sh
Executable file
47
ipset/get_reestr_preresolved.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
TMPLIST="$TMPDIR/list.txt"
|
||||
|
||||
BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main"
|
||||
URL4="$BASEURL/reestr_resolved4.txt"
|
||||
URL6="$BASEURL/reestr_resolved6.txt"
|
||||
IPB4="$BASEURL/reestr_ipban4.txt"
|
||||
IPB6="$BASEURL/reestr_ipban6.txt"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -H "Accept-Encoding: gzip" -k --fail --max-time 120 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
getuser && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
dl "$URL4" "$ZIPLIST" 32768 4194304
|
||||
dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
dl "$URL6" "$ZIPLIST6" 8192 4194304
|
||||
dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
}
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
47
ipset/get_reestr_preresolved_smart.sh
Executable file
47
ipset/get_reestr_preresolved_smart.sh
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
TMPLIST="$TMPDIR/list.txt"
|
||||
|
||||
BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main"
|
||||
URL4="$BASEURL/reestr_smart4.txt"
|
||||
URL6="$BASEURL/reestr_smart6.txt"
|
||||
IPB4="$BASEURL/reestr_ipban4.txt"
|
||||
IPB6="$BASEURL/reestr_ipban6.txt"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -H "Accept-Encoding: gzip" -k --fail --max-time 120 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
getuser && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
dl "$URL4" "$ZIPLIST" 32768 4194304
|
||||
dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
dl "$URL6" "$ZIPLIST6" 8192 4194304
|
||||
dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
}
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
45
ipset/get_reestr_resolvable_domains.sh
Executable file
45
ipset/get_reestr_resolvable_domains.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
TMPLIST="$TMPDIR/list_nethub.txt"
|
||||
|
||||
BASEURL="https://raw.githubusercontent.com/bol-van/rulist/main"
|
||||
URL="$BASEURL/reestr_hostname_resolvable.txt"
|
||||
IPB4="$BASEURL/reestr_ipban4.txt"
|
||||
IPB6="$BASEURL/reestr_ipban6.txt"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -H "Accept-Encoding: gzip" -k --fail --max-time 120 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
dl "$URL" "$ZHOSTLIST" 65536 67108864
|
||||
|
||||
hup_zapret_daemons
|
||||
|
||||
[ "$DISABLE_IPV4" != "1" ] && dl "$IPB4" "$ZIPLIST_IPBAN" 8192 1048576
|
||||
[ "$DISABLE_IPV6" != "1" ] && dl "$IPB6" "$ZIPLIST_IPBAN6" 128 1048576
|
||||
|
||||
getipban
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
|
||||
exit 0
|
||||
83
ipset/get_reestr_resolve.sh
Executable file
83
ipset/get_reestr_resolve.sh
Executable file
@@ -0,0 +1,83 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
ZREESTR="$TMPDIR/zapret.txt.gz"
|
||||
ZDIG="$TMPDIR/zapret-dig.txt"
|
||||
IPB="$TMPDIR/ipb.txt"
|
||||
ZIPLISTTMP="$TMPDIR/zapret-ip.txt"
|
||||
#ZURL=https://reestr.rublacklist.net/api/current
|
||||
ZURL_REESTR=https://raw.githubusercontent.com/zapret-info/z-i/master/dump.csv.gz
|
||||
|
||||
dl_checked()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
# $5 - maxtime
|
||||
curl -k --fail --max-time $5 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$2" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
return 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$2" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
return 2
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
reestr_list()
|
||||
{
|
||||
LC_ALL=C LANG=C gunzip -c "$ZREESTR" | cut -s -f2 -d';' | LC_ALL=C LANG=C nice -n 5 sed -Ee 's/^\*\.(.+)$/\1/' -ne 's/^[a-z0-9A-Z._-]+$/&/p' | $AWK '{ print tolower($0) }'
|
||||
}
|
||||
reestr_extract_ip()
|
||||
{
|
||||
LC_ALL=C LANG=C gunzip -c | nice -n 5 $AWK -F ';' '($1 ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}/) && (($2 == "" && $3 == "") || ($1 == $2)) {gsub(/ \| /, RS); print $1}' | LC_ALL=C LANG=C $AWK '{split($1, a, /\|/); for (i in a) {print a[i]}}'
|
||||
}
|
||||
|
||||
getuser && {
|
||||
# both disabled
|
||||
[ "$DISABLE_IPV4" = "1" ] && [ "$DISABLE_IPV6" = "1" ] && exit 0
|
||||
|
||||
dl_checked "$ZURL_REESTR" "$ZREESTR" 204800 251658240 600 || exit 2
|
||||
|
||||
echo preparing ipban list ..
|
||||
|
||||
reestr_extract_ip <"$ZREESTR" >"$IPB"
|
||||
[ "$DISABLE_IPV4" != "1" ] && $AWK '/^([0-9]{1,3}\.){3}[0-9]{1,3}($|(\/[0-9]{2}$))/' "$IPB" | cut_local | ip2net4 | zz "$ZIPLIST_IPBAN"
|
||||
[ "$DISABLE_IPV6" != "1" ] && $AWK '/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}($|(\/[0-9]{2,3}$))/' "$IPB" | cut_local6 | ip2net6 | zz "$ZIPLIST_IPBAN6"
|
||||
rm -f "$IPB"
|
||||
|
||||
echo preparing dig list ..
|
||||
reestr_list | sort -u >"$ZDIG"
|
||||
|
||||
rm -f "$ZREESTR"
|
||||
|
||||
echo digging started. this can take long ...
|
||||
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
filedigger "$ZDIG" 4 | cut_local >"$ZIPLISTTMP" || {
|
||||
rm -f "$ZDIG"
|
||||
exit 1
|
||||
}
|
||||
ip2net4 <"$ZIPLISTTMP" | zz "$ZIPLIST"
|
||||
rm -f "$ZIPLISTTMP"
|
||||
}
|
||||
[ "$DISABLE_IPV6" != "1" ] && {
|
||||
filedigger "$ZDIG" 6 | cut_local6 >"$ZIPLISTTMP" || {
|
||||
rm -f "$ZDIG"
|
||||
exit 1
|
||||
}
|
||||
ip2net6 <"$ZIPLISTTMP" | zz "$ZIPLIST6"
|
||||
rm -f "$ZIPLISTTMP"
|
||||
}
|
||||
rm -f "$ZDIG"
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
42
ipset/get_refilter_domains.sh
Executable file
42
ipset/get_refilter_domains.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
TMPLIST="$TMPDIR/list.txt"
|
||||
|
||||
URL="https://github.com/1andrevich/Re-filter-lists/releases/latest/download/domains_all.lst"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -L -H "Accept-Encoding: gzip" -k --fail --max-time 60 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
# useful in case ipban set is used in custom scripts
|
||||
FAIL=
|
||||
getipban || FAIL=1
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
[ -n "$FAIL" ] && exit
|
||||
|
||||
dl "$URL" "$ZHOSTLIST" 32768 4194304
|
||||
|
||||
hup_zapret_daemons
|
||||
|
||||
exit 0
|
||||
38
ipset/get_refilter_ipsum.sh
Executable file
38
ipset/get_refilter_ipsum.sh
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
TMPLIST="$TMPDIR/list.txt"
|
||||
|
||||
URL="https://github.com/1andrevich/Re-filter-lists/releases/latest/download/ipsum.lst"
|
||||
|
||||
dl()
|
||||
{
|
||||
# $1 - url
|
||||
# $2 - file
|
||||
# $3 - minsize
|
||||
# $4 - maxsize
|
||||
curl -L -H "Accept-Encoding: gzip" -k --fail --max-time 60 --connect-timeout 10 --retry 4 --max-filesize $4 -o "$TMPLIST" "$1" ||
|
||||
{
|
||||
echo list download failed : $1
|
||||
exit 2
|
||||
}
|
||||
dlsize=$(LC_ALL=C LANG=C wc -c "$TMPLIST" | xargs | cut -f 1 -d ' ')
|
||||
if test $dlsize -lt $3; then
|
||||
echo list is too small : $dlsize bytes. can be bad.
|
||||
exit 2
|
||||
fi
|
||||
zzcopy "$TMPLIST" "$2"
|
||||
rm -f "$TMPLIST"
|
||||
}
|
||||
|
||||
getuser && {
|
||||
[ "$DISABLE_IPV4" != "1" ] && {
|
||||
dl "$URL" "$ZIPLIST" 32768 4194304
|
||||
}
|
||||
}
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
11
ipset/get_user.sh
Executable file
11
ipset/get_user.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# resolve user host list
|
||||
|
||||
IPSET_DIR="$(dirname "$0")"
|
||||
IPSET_DIR="$(cd "$IPSET_DIR"; pwd)"
|
||||
|
||||
. "$IPSET_DIR/def.sh"
|
||||
|
||||
getuser
|
||||
|
||||
"$IPSET_DIR/create_ipset.sh"
|
||||
9
ipset/zapret-hosts-user-exclude.txt.default
Normal file
9
ipset/zapret-hosts-user-exclude.txt.default
Normal file
@@ -0,0 +1,9 @@
|
||||
127.0.0.0/8
|
||||
10.0.0.0/8
|
||||
172.16.0.0/12
|
||||
192.168.0.0/16
|
||||
169.254.0.0/16
|
||||
100.64.0.0/10
|
||||
::1
|
||||
fc00::/7
|
||||
fe80::/10
|
||||
@@ -35,7 +35,135 @@ function pktdebug(ctx, desync)
|
||||
DLOG("desync:")
|
||||
var_debug(desync)
|
||||
end
|
||||
-- basic desync function
|
||||
-- prints function args
|
||||
function argdebug(ctx,desync)
|
||||
var_debug(desync.arg)
|
||||
end
|
||||
|
||||
-- basic desync function
|
||||
-- prints conntrack positions to DLOG
|
||||
function posdebug(ctx,desync)
|
||||
local s="posdebug:"
|
||||
for i,pos in pairs({'n','d','b','s'}) do
|
||||
s=s.." "..pos..pos_get(desync,pos)
|
||||
end
|
||||
s=s.." payload "..#desync.dis.payload
|
||||
if desync.reasm_data then
|
||||
s=s.." reasm "..#desync.reasm_data
|
||||
end
|
||||
if desync.decrypt_data then
|
||||
s=s.." decrypt "..#desync.decrypt_data
|
||||
end
|
||||
if desync.replay_piece_count then
|
||||
s=s.." replay "..desync.replay_piece.."/"..desync.replay_piece_count
|
||||
end
|
||||
DLOG(s)
|
||||
end
|
||||
|
||||
-- applies # and $ prefixes. #var means var length, %var means var value
|
||||
function apply_arg_prefix(arg)
|
||||
for a,v in pairs(arg) do
|
||||
local c = string.sub(v,1,1)
|
||||
if v=='#' then
|
||||
arg[a] = #_G[string.sub(v,2)]
|
||||
elseif v=='%' then
|
||||
arg[a] = _G[string.sub(v,2)]
|
||||
elseif v=='\\' then
|
||||
c = string.sub(v,2,2);
|
||||
if c=='#' or c=='%' then
|
||||
arg[a] = string.sub(v,2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- copy instance identification and args from execution plan to desync table
|
||||
function apply_execution_plan(desync, plan)
|
||||
desync.func = plan.func
|
||||
desync.func_n = plan.func_n
|
||||
desync.func_instance = plan.func_instance
|
||||
desync.arg = deepcopy(plan.arg)
|
||||
apply_arg_prefix(desync.arg)
|
||||
end
|
||||
-- redo what whould be done without orchestration
|
||||
function replay_execution_plan(desync, plan)
|
||||
for i=1,#plan do
|
||||
if not payload_match_filter(desync.l7payload, plan[i].payload_filter) then
|
||||
DLOG("orchestrator: not calling '"..desync.func_instance.."' because payload '"..desync.l7payload.."' does not match filter '"..plan[i].payload_filter.."'")
|
||||
elseif not pos_check_range(desync, plan[i].range) then
|
||||
DLOG("orchestrator: not calling '"..desync.func_instance.."' because pos "..pos_str(desync,plan[i].range.from).." "..pos_str(desync,plan[i].range.to).." is out of range '"..pos_range_str(plan[i].range).."'")
|
||||
else
|
||||
apply_execution_plan(desync, plan[i])
|
||||
DLOG("orchestrator: executing '"..desync.func_instance.."'")
|
||||
_G[plan[i].func](ctx, desync)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- this function demonstrates how to stop execution of upcoming desync instances and take over their job
|
||||
-- this can be used, for example, for orchestrating conditional processing without modifying of desync functions code
|
||||
-- test case : nfqws2 --qnum 200 --debug --lua-init=@zapret-lib.lua --lua-desync=desync_orchestrator_example --lua-desync=pass --lua-desync=pass
|
||||
function desync_orchestrator_example(ctx, desync)
|
||||
local plan = execution_plan(ctx)
|
||||
if #plan>0 then
|
||||
DLOG("orchestrator: taking over upcoming desync instances")
|
||||
local desync_copy = deepcopy(desync)
|
||||
execution_plan_cancel(ctx)
|
||||
replay_execution_plan(desync_copy, plan)
|
||||
end
|
||||
end
|
||||
|
||||
-- these function duplicate range check logic from C code
|
||||
-- mode must be n,d,b,s,x,a
|
||||
-- pos is {mode,pos}
|
||||
-- range is {from={mode,pos}, to={mode,pos}, upper_cutoff}
|
||||
-- upper_cutoff = true means non-inclusive upper boundary
|
||||
function pos_get(desync, mode)
|
||||
if desync.track then
|
||||
if mode=='n' then
|
||||
return desync.outgoing and desync.track.pcounter_orig or desync.track.pcounter_reply
|
||||
elseif mode=='d' then
|
||||
return desync.outgoing and desync.track.pdcounter_orig or desync.track.pdcounter_reply
|
||||
elseif mode=='b' then
|
||||
return desync.outgoing and desync.track.pbcounter_orig or desync.track.pbcounter_reply
|
||||
elseif mode=='s' and desync.track.tcp then
|
||||
return desync.outgoing and (desync.track.tcp.seq - desync.track.tcp.seq0) or (desync.track.tcp.ack - desync.track.tcp.ack0)
|
||||
end
|
||||
end
|
||||
return 0
|
||||
end
|
||||
function pos_check_from(desync, range)
|
||||
if range.from.mode == 'x' then return false end
|
||||
if range.from.mode ~= 'a' then
|
||||
if desync.track then
|
||||
return pos_get(desync, range.from.mode) >= range.from.pos
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true;
|
||||
end
|
||||
function pos_check_to(desync, range)
|
||||
local ps
|
||||
if range.to.mode == 'x' then return false end
|
||||
if range.to.mode ~= 'a' then
|
||||
if desync.track then
|
||||
ps = pos_get(desync, range.to.mode)
|
||||
return (ps < range.to.pos) or not range.upper_cutoff and (ps == range.to.pos)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true;
|
||||
end
|
||||
function pos_check_range(desync, range)
|
||||
return pos_check_from(desync,range) and pos_check_to(desync,range)
|
||||
end
|
||||
function pos_range_str(range)
|
||||
return range.from.mode..range.from.pos..(range.upper_cutoff and '<' or '-')..range.to.mode..range.to.pos
|
||||
end
|
||||
function pos_str(desync, pos)
|
||||
return pos.mode..pos_get(desync, pos.mode)
|
||||
end
|
||||
|
||||
|
||||
-- prepare standard rawsend options from desync
|
||||
@@ -802,17 +930,21 @@ function direction_cutoff_opposite(ctx, desync, def)
|
||||
instance_cutoff(ctx, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- return true if l7payload matches filter l7payload_filter - comma separated list of payload types
|
||||
function payload_match_filter(l7payload, l7payload_filter, def)
|
||||
local argpl = l7payload_filter or def or "known"
|
||||
local neg = string.sub(argpl,1,1)=="~"
|
||||
local pl = neg and string.sub(argpl,2) or argpl
|
||||
return neg ~= (in_list(pl, "all") or in_list(pl, l7payload) or in_list(pl, "known") and l7payload~="unknown" and l7payload~="empty")
|
||||
end
|
||||
-- check if desync payload type comply with payload type list in arg.payload
|
||||
-- if arg.payload is not present - check for known payload - not empty and not unknown (nfqws1 behavior without "--desync-any-protocol" option)
|
||||
-- if arg.payload is prefixed with '~' - it means negation
|
||||
function payload_check(desync, def)
|
||||
local b
|
||||
local argpl = desync.arg.payload or def or "known"
|
||||
local neg = string.sub(argpl,1,1)=="~"
|
||||
local pl = neg and string.sub(argpl,2) or argpl
|
||||
|
||||
b = neg ~= (in_list(pl, "all") or in_list(pl, desync.l7payload) or in_list(pl, "known") and desync.l7payload~="unknown" and desync.l7payload~="empty")
|
||||
if not b then
|
||||
local b = payload_match_filter(desync.l7payload, desync.arg.payload, def)
|
||||
if not b and b_debug then
|
||||
local argpl = desync.arg.payload or def or "known"
|
||||
DLOG("payload_check: payload '"..desync.l7payload.."' does not pass '"..argpl.."' filter")
|
||||
end
|
||||
return b
|
||||
@@ -1031,4 +1163,3 @@ function ipfrag2(dis, ipfrag_options)
|
||||
|
||||
return {dis1,dis2}
|
||||
end
|
||||
|
||||
|
||||
106
nfq2/conntrack.c
106
nfq2/conntrack.c
@@ -102,8 +102,8 @@ static void ConntrackInitTrack(t_ctrack *t)
|
||||
{
|
||||
memset(t, 0, sizeof(*t));
|
||||
t->l7proto = L7_UNKNOWN;
|
||||
t->scale_orig = t->scale_reply = SCALE_NONE;
|
||||
time(&t->t_start);
|
||||
t->pos.scale_orig = t->pos.scale_reply = SCALE_NONE;
|
||||
time(&t->pos.t_start);
|
||||
rawpacket_queue_init(&t->delayed);
|
||||
lua_newtable(params.L);
|
||||
t->lua_state = luaL_ref(params.L, LUA_REGISTRYINDEX);
|
||||
@@ -136,86 +136,86 @@ static void ConntrackFeedPacket(t_ctrack *t, bool bReverse, const struct tcphdr
|
||||
|
||||
if (bReverse)
|
||||
{
|
||||
t->pcounter_reply++;
|
||||
t->pdcounter_reply += !!len_payload;
|
||||
t->pbcounter_reply += len_payload;
|
||||
t->pos.pcounter_reply++;
|
||||
t->pos.pdcounter_reply += !!len_payload;
|
||||
t->pos.pbcounter_reply += len_payload;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
t->pcounter_orig++;
|
||||
t->pdcounter_orig += !!len_payload;
|
||||
t->pbcounter_orig += len_payload;
|
||||
t->pos.pcounter_orig++;
|
||||
t->pos.pdcounter_orig += !!len_payload;
|
||||
t->pos.pbcounter_orig += len_payload;
|
||||
}
|
||||
|
||||
if (tcphdr)
|
||||
{
|
||||
if (tcp_syn_segment(tcphdr))
|
||||
{
|
||||
if (t->state != SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
t->seq0 = ntohl(tcphdr->th_seq);
|
||||
if (t->pos.state != SYN) ConntrackReInitTrack(t); // erase current entry
|
||||
t->pos.seq0 = ntohl(tcphdr->th_seq);
|
||||
}
|
||||
else if (tcp_synack_segment(tcphdr))
|
||||
{
|
||||
// ignore SA dups
|
||||
uint32_t seq0 = ntohl(tcphdr->th_ack) - 1;
|
||||
if (t->state != SYN && t->seq0 != seq0)
|
||||
if (t->pos.state != SYN && t->pos.seq0 != seq0)
|
||||
ConntrackReInitTrack(t); // erase current entry
|
||||
if (!t->seq0) t->seq0 = seq0;
|
||||
t->ack0 = ntohl(tcphdr->th_seq);
|
||||
if (!t->pos.seq0) t->pos.seq0 = seq0;
|
||||
t->pos.ack0 = ntohl(tcphdr->th_seq);
|
||||
}
|
||||
else if (tcphdr->th_flags & (TH_FIN | TH_RST))
|
||||
{
|
||||
t->state = FIN;
|
||||
t->pos.state = FIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t->state == SYN)
|
||||
if (t->pos.state == SYN)
|
||||
{
|
||||
t->state = ESTABLISHED;
|
||||
if (!bReverse && !t->ack0) t->ack0 = ntohl(tcphdr->th_ack) - 1;
|
||||
t->pos.state = ESTABLISHED;
|
||||
if (!bReverse && !t->pos.ack0) t->pos.ack0 = ntohl(tcphdr->th_ack) - 1;
|
||||
}
|
||||
}
|
||||
scale = tcp_find_scale_factor(tcphdr);
|
||||
mss = ntohs(tcp_find_mss(tcphdr));
|
||||
if (bReverse)
|
||||
{
|
||||
t->pos_orig = t->seq_last = ntohl(tcphdr->th_ack);
|
||||
t->ack_last = ntohl(tcphdr->th_seq);
|
||||
t->pos_reply = t->ack_last + len_payload;
|
||||
t->winsize_reply = ntohs(tcphdr->th_win);
|
||||
t->winsize_reply_calc = t->winsize_reply;
|
||||
if (t->scale_reply != SCALE_NONE) t->winsize_reply_calc <<= t->scale_reply;
|
||||
if (mss && !t->mss_reply) t->mss_reply = mss;
|
||||
if (scale != SCALE_NONE) t->scale_reply = scale;
|
||||
t->pos.pos_orig = t->pos.seq_last = ntohl(tcphdr->th_ack);
|
||||
t->pos.ack_last = ntohl(tcphdr->th_seq);
|
||||
t->pos.pos_reply = t->pos.ack_last + len_payload;
|
||||
t->pos.winsize_reply = ntohs(tcphdr->th_win);
|
||||
t->pos.winsize_reply_calc = t->pos.winsize_reply;
|
||||
if (t->pos.scale_reply != SCALE_NONE) t->pos.winsize_reply_calc <<= t->pos.scale_reply;
|
||||
if (mss && !t->pos.mss_reply) t->pos.mss_reply = mss;
|
||||
if (scale != SCALE_NONE) t->pos.scale_reply = scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->seq_last = ntohl(tcphdr->th_seq);
|
||||
t->pos_orig = t->seq_last + len_payload;
|
||||
t->pos_reply = t->ack_last = ntohl(tcphdr->th_ack);
|
||||
t->winsize_orig = ntohs(tcphdr->th_win);
|
||||
t->winsize_orig_calc = t->winsize_orig;
|
||||
if (t->scale_orig != SCALE_NONE) t->winsize_orig_calc <<= t->scale_orig;
|
||||
if (mss && !t->mss_reply) t->mss_orig = mss;
|
||||
if (scale != SCALE_NONE) t->scale_orig = scale;
|
||||
t->pos.seq_last = ntohl(tcphdr->th_seq);
|
||||
t->pos.pos_orig = t->pos.seq_last + len_payload;
|
||||
t->pos.pos_reply = t->pos.ack_last = ntohl(tcphdr->th_ack);
|
||||
t->pos.winsize_orig = ntohs(tcphdr->th_win);
|
||||
t->pos.winsize_orig_calc = t->pos.winsize_orig;
|
||||
if (t->pos.scale_orig != SCALE_NONE) t->pos.winsize_orig_calc <<= t->pos.scale_orig;
|
||||
if (mss && !t->pos.mss_reply) t->pos.mss_orig = mss;
|
||||
if (scale != SCALE_NONE) t->pos.scale_orig = scale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bReverse)
|
||||
{
|
||||
t->ack_last = t->pos_reply;
|
||||
t->pos_reply += len_payload;
|
||||
t->pos.ack_last = t->pos.pos_reply;
|
||||
t->pos.pos_reply += len_payload;
|
||||
}
|
||||
else
|
||||
{
|
||||
t->seq_last = t->pos_orig;
|
||||
t->pos_orig += len_payload;
|
||||
t->pos.seq_last = t->pos.pos_orig;
|
||||
t->pos.pos_orig += len_payload;
|
||||
}
|
||||
}
|
||||
|
||||
time(&t->t_last);
|
||||
time(&t->pos.t_last);
|
||||
}
|
||||
|
||||
static bool ConntrackPoolDoubleSearchPool(t_conntrack_pool **pp, const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcphdr, const struct udphdr *udphdr, t_ctrack **ctrack, bool *bReverse)
|
||||
@@ -317,12 +317,12 @@ void ConntrackPoolPurge(t_conntrack *p)
|
||||
if ((tnow - p->t_last_purge) >= p->t_purge_interval)
|
||||
{
|
||||
HASH_ITER(hh, p->pool, t, tmp) {
|
||||
tidle = tnow - t->track.t_last;
|
||||
tidle = tnow - t->track.pos.t_last;
|
||||
if (t->track.b_cutoff ||
|
||||
(t->conn.l4proto == IPPROTO_TCP && (
|
||||
(t->track.state == SYN && tidle >= p->timeout_syn) ||
|
||||
(t->track.state == ESTABLISHED && tidle >= p->timeout_established) ||
|
||||
(t->track.state == FIN && tidle >= p->timeout_fin))
|
||||
(t->track.pos.state == SYN && tidle >= p->timeout_syn) ||
|
||||
(t->track.pos.state == ESTABLISHED && tidle >= p->timeout_established) ||
|
||||
(t->track.pos.state == FIN && tidle >= p->timeout_fin))
|
||||
) || (t->conn.l4proto == IPPROTO_UDP && tidle >= p->timeout_udp)
|
||||
)
|
||||
{
|
||||
@@ -349,21 +349,21 @@ void ConntrackPoolDump(const t_conntrack *p)
|
||||
printf("%s [%s]:%u => [%s]:%u : %s : t0=%llu last=t0+%llu now=last+%llu orig=d%llu/n%llu/b%llu reply=d%llu/n%llu/b%lld ",
|
||||
proto_name(t->conn.l4proto),
|
||||
sa1, t->conn.sport, sa2, t->conn.dport,
|
||||
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.state] : "-",
|
||||
(unsigned long long)t->track.t_start, (unsigned long long)(t->track.t_last - t->track.t_start), (unsigned long long)(tnow - t->track.t_last),
|
||||
(unsigned long long)t->track.pdcounter_orig, (unsigned long long)t->track.pcounter_orig, (unsigned long long)t->track.pbcounter_orig,
|
||||
(unsigned long long)t->track.pdcounter_reply, (unsigned long long)t->track.pcounter_reply, (unsigned long long)t->track.pbcounter_reply);
|
||||
t->conn.l4proto == IPPROTO_TCP ? connstate_s[t->track.pos.state] : "-",
|
||||
(unsigned long long)t->track.pos.t_start, (unsigned long long)(t->track.pos.t_last - t->track.pos.t_start), (unsigned long long)(tnow - t->track.pos.t_last),
|
||||
(unsigned long long)t->track.pos.pdcounter_orig, (unsigned long long)t->track.pos.pcounter_orig, (unsigned long long)t->track.pos.pbcounter_orig,
|
||||
(unsigned long long)t->track.pos.pdcounter_reply, (unsigned long long)t->track.pos.pcounter_reply, (unsigned long long)t->track.pos.pbcounter_reply);
|
||||
if (t->conn.l4proto == IPPROTO_TCP)
|
||||
printf("seq0=%u rseq=%u pos_orig=%u ack0=%u rack=%u pos_reply=%u mss_orig=%u mss_reply=%u wsize_orig=%u:%d wsize_reply=%u:%d",
|
||||
t->track.seq0, t->track.seq_last - t->track.seq0, t->track.pos_orig - t->track.seq0,
|
||||
t->track.ack0, t->track.ack_last - t->track.ack0, t->track.pos_reply - t->track.ack0,
|
||||
t->track.mss_orig, t->track.mss_reply,
|
||||
t->track.winsize_orig, t->track.scale_orig == SCALE_NONE ? -1 : t->track.scale_orig,
|
||||
t->track.winsize_reply, t->track.scale_reply == SCALE_NONE ? -1 : t->track.scale_reply);
|
||||
t->track.pos.seq0, t->track.pos.seq_last - t->track.pos.seq0, t->track.pos.pos_orig - t->track.pos.seq0,
|
||||
t->track.pos.ack0, t->track.pos.ack_last - t->track.pos.ack0, t->track.pos.pos_reply - t->track.pos.ack0,
|
||||
t->track.pos.mss_orig, t->track.pos.mss_reply,
|
||||
t->track.pos.winsize_orig, t->track.pos.scale_orig == SCALE_NONE ? -1 : t->track.pos.scale_orig,
|
||||
t->track.pos.winsize_reply, t->track.pos.scale_reply == SCALE_NONE ? -1 : t->track.pos.scale_reply);
|
||||
else
|
||||
printf("rseq=%u pos_orig=%u rack=%u pos_reply=%u",
|
||||
t->track.seq_last, t->track.pos_orig,
|
||||
t->track.ack_last, t->track.pos_reply);
|
||||
t->track.pos.seq_last, t->track.pos.pos_orig,
|
||||
t->track.pos.ack_last, t->track.pos.pos_reply);
|
||||
printf(" req_retrans=%u cutoff=%u lua_in_cutoff=%u lua_out_cutoff=%u hostname=%s l7proto=%s\n",
|
||||
t->track.req_retrans_counter, t->track.b_cutoff, t->track.b_lua_in_cutoff, t->track.b_lua_out_cutoff, t->track.hostname, l7proto_str(t->track.l7proto));
|
||||
};
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#define __FAVOR_BSD
|
||||
@@ -17,6 +16,7 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include "conntrack_base.h"
|
||||
#include "packet_queue.h"
|
||||
#include "protocol.h"
|
||||
|
||||
@@ -48,35 +48,18 @@ typedef struct {
|
||||
size_t size_present; // how many bytes already stored in 'packet'
|
||||
} t_reassemble;
|
||||
|
||||
// SYN - SYN or SYN/ACK received
|
||||
// ESTABLISHED - any except SYN or SYN/ACK received
|
||||
// FIN - FIN or RST received
|
||||
typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool bCheckDone, bCheckResult, bCheckExcluded; // hostlist check result cache
|
||||
uint8_t ipproto;
|
||||
|
||||
// this block of data can change between delayed (queued) packets. need to remeber this data for each packet for further replay
|
||||
t_ctrack_position pos;
|
||||
|
||||
struct desync_profile *dp; // desync profile cache
|
||||
bool dp_search_complete;
|
||||
|
||||
// common state
|
||||
time_t t_start, t_last;
|
||||
uint64_t pcounter_orig, pcounter_reply; // packet counter
|
||||
uint64_t pdcounter_orig, pdcounter_reply; // data packet counter (with payload)
|
||||
uint64_t pbcounter_orig, pbcounter_reply; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
||||
uint32_t pos_orig, pos_reply; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||
uint32_t seq_last, ack_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
|
||||
|
||||
// tcp only state, not used in udp
|
||||
t_connstate state;
|
||||
uint32_t seq0, ack0; // starting seq and ack
|
||||
uint16_t winsize_orig, winsize_reply; // last seen window size
|
||||
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
|
||||
uint32_t winsize_orig_calc, winsize_reply_calc; // calculated window size
|
||||
uint16_t mss_orig, mss_reply;
|
||||
|
||||
uint8_t req_retrans_counter; // number of request retransmissions
|
||||
bool req_seq_present,req_seq_finalized,req_seq_abandoned;
|
||||
uint32_t req_seq_start,req_seq_end; // sequence interval of the request (to track retransmissions)
|
||||
|
||||
32
nfq2/conntrack_base.h
Normal file
32
nfq2/conntrack_base.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define CTRACK_T_SYN 60
|
||||
#define CTRACK_T_FIN 60
|
||||
#define CTRACK_T_EST 300
|
||||
#define CTRACK_T_UDP 60
|
||||
|
||||
// SYN - SYN or SYN/ACK received
|
||||
// ESTABLISHED - any except SYN or SYN/ACK received
|
||||
// FIN - FIN or RST received
|
||||
typedef enum {SYN=0, ESTABLISHED, FIN} t_connstate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
time_t t_last, t_start;
|
||||
|
||||
uint64_t pcounter_orig, pcounter_reply; // packet counter
|
||||
uint64_t pdcounter_orig, pdcounter_reply; // data packet counter (with payload)
|
||||
uint64_t pbcounter_orig, pbcounter_reply; // transferred byte counter. includes retransmissions. it's not the same as relative seq.
|
||||
uint32_t pos_orig, pos_reply; // TCP: seq_last+payload, ack_last+payload UDP: sum of all seen payload lenghts including current
|
||||
uint32_t seq_last, ack_last; // TCP: last seen seq and ack UDP: sum of all seen payload lenghts NOT including current
|
||||
|
||||
// tcp only state, not used in udp
|
||||
t_connstate state;
|
||||
uint32_t seq0, ack0; // starting seq and ack
|
||||
uint16_t winsize_orig, winsize_reply; // last seen window size
|
||||
uint8_t scale_orig, scale_reply; // last seen window scale factor. SCALE_NONE if none
|
||||
uint32_t winsize_orig_calc, winsize_reply_calc; // calculated window size
|
||||
uint16_t mss_orig, mss_reply;
|
||||
} t_ctrack_position;
|
||||
231
nfq2/desync.c
231
nfq2/desync.c
@@ -209,7 +209,7 @@ static struct desync_profile *dp_find(
|
||||
{
|
||||
if (dp_match(&dpl->dp, l3proto, ip, ip6, port, hostname, bNoSubdom, l7proto, ssid, bCheckDone, bCheckResult, bExcluded))
|
||||
{
|
||||
DLOG("desync profile %u matches\n", dpl->dp.n);
|
||||
DLOG("desync profile %u (%s) matches\n", dpl->dp.n, PROFILE_NAME(&dpl->dp));
|
||||
return &dpl->dp;
|
||||
}
|
||||
}
|
||||
@@ -234,8 +234,8 @@ static void auto_hostlist_reset_fail_counter(struct desync_profile *dp, const ch
|
||||
if (fail_counter)
|
||||
{
|
||||
HostFailPoolDel(&dp->hostlist_auto_fail_counters, fail_counter);
|
||||
DLOG("auto hostlist (profile %u) : %s : fail counter reset. website is working.\n", dp->n, hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u : client %s : proto %s : fail counter reset. website is working.", hostname, dp->n, client_ip_port, l7proto_str(l7proto));
|
||||
DLOG("auto hostlist (profile %u (%s)) : %s : fail counter reset. website is working.\n", dp->n, PROFILE_NAME(dp), hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : fail counter reset. website is working.", hostname, dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,9 +249,9 @@ static bool auto_hostlist_retrans(t_ctrack *ctrack, uint8_t l4proto, int thresho
|
||||
{
|
||||
if (!ctrack->req_seq_finalized || ctrack->req_seq_abandoned)
|
||||
return false;
|
||||
if (!seq_within(ctrack->seq_last, ctrack->req_seq_start, ctrack->req_seq_end))
|
||||
if (!seq_within(ctrack->pos.seq_last, ctrack->req_seq_start, ctrack->req_seq_end))
|
||||
{
|
||||
DLOG("req retrans : tcp seq %u not within the req range %u-%u. stop tracking.\n", ctrack->seq_last, ctrack->req_seq_start, ctrack->req_seq_end);
|
||||
DLOG("req retrans : tcp seq %u not within the req range %u-%u. stop tracking.\n", ctrack->pos.seq_last, ctrack->req_seq_start, ctrack->req_seq_end);
|
||||
ctrack_stop_retrans_counter(ctrack);
|
||||
auto_hostlist_reset_fail_counter(ctrack->dp, ctrack->hostname, client_ip_port, l7proto);
|
||||
return false;
|
||||
@@ -283,19 +283,19 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
||||
}
|
||||
}
|
||||
fail_counter->counter++;
|
||||
DLOG("auto hostlist (profile %u) : %s : fail counter %d/%d\n", dp->n, hostname, fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u : client %s : proto %s : fail counter %d/%d", hostname, dp->n, client_ip_port, l7proto_str(l7proto), fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
DLOG("auto hostlist (profile %u (%s)) : %s : fail counter %d/%d\n", dp->n, PROFILE_NAME(dp), hostname, fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : fail counter %d/%d", hostname, dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto), fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
if (fail_counter->counter >= dp->hostlist_auto_fail_threshold)
|
||||
{
|
||||
DLOG("auto hostlist (profile %u) : fail threshold reached. about to add %s to auto hostlist\n", dp->n, hostname);
|
||||
DLOG("auto hostlist (profile %u (%s)) : fail threshold reached. about to add %s to auto hostlist\n", dp->n, PROFILE_NAME(dp), hostname);
|
||||
HostFailPoolDel(&dp->hostlist_auto_fail_counters, fail_counter);
|
||||
|
||||
DLOG("auto hostlist (profile %u) : rechecking %s to avoid duplicates\n", dp->n, hostname);
|
||||
DLOG("auto hostlist (profile %u (%s)) : rechecking %s to avoid duplicates\n", dp->n, PROFILE_NAME(dp), hostname);
|
||||
bool bExcluded = false;
|
||||
if (!HostlistCheck(dp, hostname, bNoSubdom, &bExcluded, false) && !bExcluded)
|
||||
{
|
||||
DLOG("auto hostlist (profile %u) : adding %s to %s\n", dp->n, hostname, dp->hostlist_auto->filename);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u : client %s : proto %s : adding to %s", hostname, dp->n, client_ip_port, l7proto_str(l7proto), dp->hostlist_auto->filename);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : adding to %s", hostname, dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto), dp->hostlist_auto->filename);
|
||||
if (!HostlistPoolAddStr(&dp->hostlist_auto->hostlist, hostname, 0))
|
||||
{
|
||||
DLOG_ERR("StrPoolAddStr out of memory\n");
|
||||
@@ -312,7 +312,7 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
||||
else
|
||||
{
|
||||
DLOG("auto hostlist (profile %u) : NOT adding %s\n", dp->n, hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u : client %s : proto %s : NOT adding, duplicate detected", hostname, dp->n, client_ip_port, l7proto_str(l7proto));
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : NOT adding, duplicate detected", hostname, dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,7 +328,7 @@ static void process_retrans_fail(t_ctrack *ctrack, uint8_t proto, const struct s
|
||||
*client_ip_port = 0;
|
||||
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, proto, ctrack->dp->hostlist_auto_retrans_threshold, client_ip_port, ctrack->l7proto))
|
||||
{
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u : client %s : proto %s : retrans threshold reached", ctrack->hostname, ctrack->dp->n, client_ip_port, l7proto_str(ctrack->l7proto));
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : retrans threshold reached", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(ctrack->dp), client_ip_port, l7proto_str(ctrack->l7proto));
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname, ctrack->hostname_is_ip, client_ip_port, ctrack->l7proto);
|
||||
}
|
||||
}
|
||||
@@ -344,14 +344,14 @@ static bool send_delayed(t_ctrack *ctrack)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool rawpacket_queue_csum_fix(struct rawpacket_tailhead *q, const struct dissect *dis, const struct sockaddr_storage* dst, uint32_t fwmark, uint32_t desync_fwmark, const char *ifin, const char *ifout)
|
||||
static bool rawpacket_queue_csum_fix(struct rawpacket_tailhead *q, const struct dissect *dis, const t_ctrack_position *pos, const struct sockaddr_storage* dst, uint32_t fwmark, uint32_t desync_fwmark, const char *ifin, const char *ifout)
|
||||
{
|
||||
// this breaks const pointer to l4 header
|
||||
if (dis->tcp)
|
||||
verdict_tcp_csum_fix(VERDICT_PASS, (struct tcphdr *)dis->tcp, dis->transport_len, dis->ip, dis->ip6);
|
||||
else if (dis->udp)
|
||||
verdict_udp_csum_fix(VERDICT_PASS, (struct udphdr *)dis->udp, dis->transport_len, dis->ip, dis->ip6);
|
||||
return rawpacket_queue(q, dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload);
|
||||
return rawpacket_queue(q, dst, fwmark, desync_fwmark, ifin, ifout, dis->data_pkt, dis->len_pkt, dis->len_payload, pos);
|
||||
}
|
||||
|
||||
|
||||
@@ -360,7 +360,7 @@ static bool reasm_start(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, si
|
||||
ReasmClear(reasm);
|
||||
if (sz <= szMax)
|
||||
{
|
||||
uint32_t seq = (proto == IPPROTO_TCP) ? ctrack->seq_last : 0;
|
||||
uint32_t seq = (proto == IPPROTO_TCP) ? ctrack->pos.seq_last : 0;
|
||||
if (ReasmInit(reasm, sz, seq))
|
||||
{
|
||||
ReasmFeed(reasm, seq, data_payload, len_payload);
|
||||
@@ -382,7 +382,7 @@ static bool reasm_feed(t_ctrack *ctrack, t_reassemble *reasm, uint8_t proto, con
|
||||
{
|
||||
if (ctrack && !ReasmIsEmpty(reasm))
|
||||
{
|
||||
uint32_t seq = (proto == IPPROTO_TCP) ? ctrack->seq_last : (uint32_t)reasm->size_present;
|
||||
uint32_t seq = (proto == IPPROTO_TCP) ? ctrack->pos.seq_last : (uint32_t)reasm->size_present;
|
||||
if (ReasmFeed(reasm, seq, data_payload, len_payload))
|
||||
{
|
||||
DLOG("reassemble : feeding data payload size=%zu. now we have %zu/%zu\n", len_payload, reasm->size_present, reasm->size);
|
||||
@@ -429,7 +429,7 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, const struct dissect *
|
||||
// if used in postnat chain, dropping initial packet will cause conntrack connection teardown
|
||||
// so we need to workaround this.
|
||||
// SYN and SYN,ACK checks are for conntrack-less mode
|
||||
if (ctrack && (params.server ? ctrack->pcounter_reply : ctrack->pcounter_orig) == 1 || dis->tcp && (tcp_syn_segment(dis->tcp) || tcp_synack_segment(dis->tcp)))
|
||||
if (ctrack && (params.server ? ctrack->pos.pcounter_reply : ctrack->pos.pcounter_orig) == 1 || dis->tcp && (tcp_syn_segment(dis->tcp) || tcp_synack_segment(dis->tcp)))
|
||||
{
|
||||
if (dis->len_pkt > *len_mod_pkt)
|
||||
DLOG_ERR("linux postnat conntrack workaround cannot be applied\n");
|
||||
@@ -458,60 +458,60 @@ static uint8_t ct_new_postnat_fix(const t_ctrack *ctrack, const struct dissect *
|
||||
}
|
||||
|
||||
|
||||
static uint64_t pos_get(const t_ctrack *ctrack, char mode, bool bReply)
|
||||
static uint64_t pos_get(const t_ctrack_position *pos, char mode, bool bReply)
|
||||
{
|
||||
if (ctrack)
|
||||
if (pos)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case 'n': return bReply ? ctrack->pcounter_reply : ctrack->pcounter_orig;
|
||||
case 'd': return bReply ? ctrack->pdcounter_reply : ctrack->pdcounter_orig;
|
||||
case 's': return bReply ? (ctrack->ack_last - ctrack->ack0) : (ctrack->seq_last - ctrack->seq0);
|
||||
case 'b': return bReply ? ctrack->pbcounter_reply : ctrack->pbcounter_orig;
|
||||
case 'n': return bReply ? pos->pcounter_reply : pos->pcounter_orig;
|
||||
case 'd': return bReply ? pos->pdcounter_reply : pos->pdcounter_orig;
|
||||
case 's': return bReply ? (pos->ack_last - pos->ack0) : (pos->seq_last - pos->seq0);
|
||||
case 'b': return bReply ? pos->pbcounter_reply : pos->pbcounter_orig;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static bool check_pos_from(const t_ctrack *ctrack, bool bReply, const struct packet_range *range)
|
||||
static bool check_pos_from(const t_ctrack_position *pos, bool bReply, const struct packet_range *range)
|
||||
{
|
||||
uint64_t pos;
|
||||
uint64_t ps;
|
||||
if (range->from.mode == 'x') return false;
|
||||
if (range->from.mode != 'a')
|
||||
{
|
||||
if (ctrack)
|
||||
if (pos)
|
||||
{
|
||||
pos = pos_get(ctrack, range->from.mode, bReply);
|
||||
return pos >= range->from.pos;
|
||||
ps = pos_get(pos, range->from.mode, bReply);
|
||||
return ps >= range->from.pos;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool check_pos_to(const t_ctrack *ctrack, bool bReply, const struct packet_range *range)
|
||||
static bool check_pos_to(const t_ctrack_position *pos, bool bReply, const struct packet_range *range)
|
||||
{
|
||||
uint64_t pos;
|
||||
uint64_t ps;
|
||||
if (range->to.mode == 'x') return false;
|
||||
if (range->to.mode != 'a')
|
||||
{
|
||||
if (ctrack)
|
||||
if (pos)
|
||||
{
|
||||
pos = pos_get(ctrack, range->to.mode, bReply);
|
||||
return (pos < range->to.pos) || !range->upper_cutoff && (pos == range->to.pos);
|
||||
ps = pos_get(pos, range->to.mode, bReply);
|
||||
return (ps < range->to.pos) || !range->upper_cutoff && (ps == range->to.pos);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool check_pos_cutoff(const t_ctrack *ctrack, bool bReply, const struct packet_range *range)
|
||||
static bool check_pos_cutoff(const t_ctrack_position *pos, bool bReply, const struct packet_range *range)
|
||||
{
|
||||
bool bto = check_pos_to(ctrack, bReply, range);
|
||||
return ctrack ? !bto : (!bto || !check_pos_from(ctrack, bReply, range));
|
||||
bool bto = check_pos_to(pos, bReply, range);
|
||||
return pos ? !bto : (!bto || !check_pos_from(pos, bReply, range));
|
||||
}
|
||||
static bool check_pos_range(const t_ctrack *ctrack, bool bReply, const struct packet_range *range)
|
||||
static bool check_pos_range(const t_ctrack_position *pos, bool bReply, const struct packet_range *range)
|
||||
{
|
||||
return check_pos_from(ctrack, bReply, range) && check_pos_to(ctrack, bReply, range);
|
||||
return check_pos_from(pos, bReply, range) && check_pos_to(pos, bReply, range);
|
||||
}
|
||||
|
||||
|
||||
@@ -638,10 +638,6 @@ err:
|
||||
lua_pop(params.L, rescount);
|
||||
return false;
|
||||
}
|
||||
static void desync_instance(const char *func, unsigned int dp_n, unsigned int func_n, char *instance, size_t inst_size)
|
||||
{
|
||||
snprintf(instance, inst_size, "%s_%u_%u", func, dp_n, func_n);
|
||||
}
|
||||
static uint8_t desync(
|
||||
struct desync_profile *dp,
|
||||
uint32_t fwmark,
|
||||
@@ -649,6 +645,7 @@ static uint8_t desync(
|
||||
const char *ifout,
|
||||
bool bIncoming,
|
||||
t_ctrack *ctrack,
|
||||
const t_ctrack_position *pos,
|
||||
t_l7payload l7payload,
|
||||
const struct dissect *dis,
|
||||
uint8_t *mod_pkt, size_t *len_mod_pkt,
|
||||
@@ -659,7 +656,7 @@ static uint8_t desync(
|
||||
struct func_list *func;
|
||||
int ref_arg = LUA_NOREF, status;
|
||||
bool b, b_cutoff_all, b_unwanted_payload;
|
||||
t_lua_desync_context ctx = { .dp = dp, .ctrack = ctrack, .dis = dis };
|
||||
t_lua_desync_context ctx = { .dp = dp, .ctrack = ctrack, .dis = dis, .cancel = false, .incoming = bIncoming };
|
||||
const char *sDirection = bIncoming ? "in" : "out";
|
||||
struct packet_range *range;
|
||||
size_t l;
|
||||
@@ -678,17 +675,16 @@ static uint8_t desync(
|
||||
DLOG("lua out cutoff\n");
|
||||
return verdict;
|
||||
}
|
||||
if (!pos) pos = &ctrack->pos;
|
||||
}
|
||||
if (LIST_FIRST(&dp->lua_desync))
|
||||
{
|
||||
unsigned int func_n;
|
||||
|
||||
b_cutoff_all = b_unwanted_payload = true;
|
||||
func_n = 1;
|
||||
ctx.func_n = 1;
|
||||
LIST_FOREACH(func, &dp->lua_desync, next)
|
||||
{
|
||||
ctx.func = func->func;
|
||||
desync_instance(func->func, dp->n, func_n, instance, sizeof(instance));
|
||||
desync_instance(func->func, dp->n, ctx.func_n, instance, sizeof(instance));
|
||||
ctx.instance = instance;
|
||||
range = bIncoming ? &func->range_in : &func->range_out;
|
||||
|
||||
@@ -699,12 +695,12 @@ static uint8_t desync(
|
||||
{
|
||||
if (lua_instance_cutoff_check(&ctx, bIncoming))
|
||||
DLOG("* lua '%s' : voluntary cutoff\n", instance);
|
||||
else if (check_pos_cutoff(ctrack, bIncoming, range))
|
||||
else if (check_pos_cutoff(pos, bIncoming, range))
|
||||
{
|
||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu is beyond range %c%u%c%c%u (ctrack %s)\n",
|
||||
instance, sDirection,
|
||||
range->from.mode, pos_get(ctrack, range->from.mode, bIncoming),
|
||||
range->to.mode, pos_get(ctrack, range->to.mode, bIncoming),
|
||||
range->from.mode, pos_get(pos, range->from.mode, bIncoming),
|
||||
range->to.mode, pos_get(pos, range->to.mode, bIncoming),
|
||||
range->from.mode, range->from.pos,
|
||||
range->upper_cutoff ? '<' : '-',
|
||||
range->to.mode, range->to.pos,
|
||||
@@ -713,7 +709,7 @@ static uint8_t desync(
|
||||
else
|
||||
b_cutoff_all = false;
|
||||
}
|
||||
func_n++;
|
||||
ctx.func_n++;
|
||||
}
|
||||
if (b_cutoff_all)
|
||||
{
|
||||
@@ -725,10 +721,14 @@ static uint8_t desync(
|
||||
else
|
||||
{
|
||||
// create arg table that persists across multiple desync function calls
|
||||
lua_createtable(params.L, 0, 12 + !!ctrack + !!dis->tcp + 3*!!replay_piece_count);
|
||||
lua_newtable(params.L);
|
||||
lua_pushf_dissect(dis);
|
||||
lua_pushf_ctrack(ctrack);
|
||||
lua_pushf_ctrack(ctrack, pos);
|
||||
lua_pushf_int("profile_n", dp->n);
|
||||
if (dp->name) lua_pushf_str("profile_name", dp->name);
|
||||
if (dp->n_tpl) lua_pushf_int("template_n", dp->n_tpl);
|
||||
if (dp->name_tpl) lua_pushf_str("template_name", dp->name_tpl);
|
||||
if (dp->cookie) lua_pushf_str("cookie", dp->cookie);
|
||||
lua_pushf_bool("outgoing", !bIncoming);
|
||||
lua_pushf_str("ifin", (ifin && *ifin) ? ifin : NULL);
|
||||
lua_pushf_str("ifout", (ifout && *ifout) ? ifout : NULL);
|
||||
@@ -748,29 +748,29 @@ static uint8_t desync(
|
||||
if (dis->tcp)
|
||||
{
|
||||
// recommended mss value for generated packets
|
||||
if (ctrack && ctrack->mss_orig)
|
||||
lua_pushf_int("tcp_mss", ctrack->mss_orig);
|
||||
if (pos && pos->mss_orig)
|
||||
lua_pushf_int("tcp_mss", pos->mss_orig);
|
||||
else
|
||||
lua_pushf_global("tcp_mss", "DEFAULT_MSS");
|
||||
}
|
||||
ref_arg = luaL_ref(params.L, LUA_REGISTRYINDEX);
|
||||
|
||||
func_n = 1;
|
||||
ctx.func_n = 1;
|
||||
LIST_FOREACH(func, &dp->lua_desync, next)
|
||||
{
|
||||
ctx.func = func->func;
|
||||
desync_instance(func->func, dp->n, func_n, instance, sizeof(instance));
|
||||
desync_instance(func->func, dp->n, ctx.func_n, instance, sizeof(instance));
|
||||
ctx.instance = instance;
|
||||
|
||||
if (!lua_instance_cutoff_check(&ctx, bIncoming))
|
||||
{
|
||||
range = bIncoming ? &func->range_in : &func->range_out;
|
||||
if (check_pos_range(ctrack, bIncoming, range))
|
||||
if (check_pos_range(pos, bIncoming, range))
|
||||
{
|
||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu in range %c%u%c%c%u\n",
|
||||
instance, sDirection,
|
||||
range->from.mode, pos_get(ctrack, range->from.mode, bIncoming),
|
||||
range->to.mode, pos_get(ctrack, range->to.mode, bIncoming),
|
||||
range->from.mode, pos_get(pos, range->from.mode, bIncoming),
|
||||
range->to.mode, pos_get(pos, range->to.mode, bIncoming),
|
||||
range->from.mode, range->from.pos,
|
||||
range->upper_cutoff ? '<' : '-',
|
||||
range->to.mode, range->to.pos);
|
||||
@@ -789,7 +789,7 @@ static uint8_t desync(
|
||||
lua_rawgeti(params.L, LUA_REGISTRYINDEX, ref_arg);
|
||||
lua_pushf_args(&func->args, -1);
|
||||
lua_pushf_str("func", func->func);
|
||||
lua_pushf_int("func_n", func_n);
|
||||
lua_pushf_int("func_n", ctx.func_n);
|
||||
lua_pushf_str("func_instance", instance);
|
||||
int initial_stack_top = lua_gettop(params.L);
|
||||
status = lua_pcall(params.L, 2, LUA_MULTRET, 0);
|
||||
@@ -808,37 +808,6 @@ static uint8_t desync(
|
||||
case VERDICT_DROP:
|
||||
verdict = VERDICT_DROP;
|
||||
}
|
||||
|
||||
if (ctrack)
|
||||
{
|
||||
// lua cutoff
|
||||
lua_rawgeti(params.L, LUA_REGISTRYINDEX, ref_arg);
|
||||
lua_getfield(params.L, -1, "track");
|
||||
if (lua_istable(params.L, -1))
|
||||
{
|
||||
if (!ctrack->b_lua_in_cutoff)
|
||||
{
|
||||
lua_getfield(params.L, -1, "lua_in_cutoff");
|
||||
if (lua_toboolean(params.L, -1))
|
||||
{
|
||||
ctrack->b_lua_in_cutoff = true;
|
||||
DLOG("* lua in cutoff set\n");
|
||||
}
|
||||
lua_pop(params.L, 1);
|
||||
}
|
||||
if (!ctrack->b_lua_out_cutoff)
|
||||
{
|
||||
lua_getfield(params.L, -1, "lua_out_cutoff");
|
||||
if (lua_toboolean(params.L, -1))
|
||||
{
|
||||
ctrack->b_lua_out_cutoff = true;
|
||||
DLOG("* lua out cutoff set\n");
|
||||
}
|
||||
lua_pop(params.L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(params.L, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
DLOG("* lua '%s' : payload_type '%s' does not satisfy filter\n", instance, l7payload_str(l7payload));
|
||||
@@ -846,13 +815,14 @@ static uint8_t desync(
|
||||
else
|
||||
DLOG("* lua '%s' : %s pos %c%llu %c%llu out of range %c%u%c%c%u\n",
|
||||
instance, sDirection,
|
||||
range->from.mode, pos_get(ctrack, range->from.mode, bIncoming),
|
||||
range->to.mode, pos_get(ctrack, range->to.mode, bIncoming),
|
||||
range->from.mode, pos_get(pos, range->from.mode, bIncoming),
|
||||
range->to.mode, pos_get(pos, range->to.mode, bIncoming),
|
||||
range->from.mode, range->from.pos,
|
||||
range->upper_cutoff ? '<' : '-',
|
||||
range->to.mode, range->to.pos);
|
||||
}
|
||||
func_n++;
|
||||
if (ctx.cancel) break;
|
||||
ctx.func_n++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -940,7 +910,13 @@ static void setup_direction(
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset, uint32_t fwmark, const char *ifin, const char *ifout, const struct dissect *dis, uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
static uint8_t dpi_desync_tcp_packet_play(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||
uint32_t fwmark,
|
||||
const char *ifin, const char *ifout,
|
||||
const t_ctrack_position *pos,
|
||||
const struct dissect *dis,
|
||||
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
{
|
||||
uint8_t verdict = VERDICT_PASS;
|
||||
|
||||
@@ -979,7 +955,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
l7proto = ctrack_replay->l7proto;
|
||||
dp = ctrack_replay->dp;
|
||||
if (dp)
|
||||
DLOG("using cached desync profile %u\n", dp->n);
|
||||
DLOG("using cached desync profile %u (%s)\n", dp->n, PROFILE_NAME(dp));
|
||||
else if (!ctrack_replay->dp_search_complete)
|
||||
{
|
||||
dp = ctrack_replay->dp = dp_find(¶ms.desync_profiles, IPPROTO_TCP, sdip4, sdip6, sdport, ctrack_replay->hostname, ctrack_replay->hostname_is_ip, l7proto, ssid, NULL, NULL, NULL);
|
||||
@@ -1007,7 +983,6 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
// in absence of conntrack guess direction by presence of interface names. won't work on BSD
|
||||
bReverseFixed = ctrack ? (bReverse ^ params.server) : (bReverse = ifin && ifin && (!ifout || !*ifout));
|
||||
setup_direction(dis, bReverseFixed, &src, &dst, &sdip4, &sdip6, &sdport);
|
||||
|
||||
ifname = bReverse ? ifin : ifout;
|
||||
#ifdef HAS_FILTER_SSID
|
||||
ssid = wlan_ssid_search_ifname(ifname);
|
||||
@@ -1015,7 +990,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
#endif
|
||||
if (ctrack) l7proto = ctrack->l7proto;
|
||||
if (dp)
|
||||
DLOG("using cached desync profile %u\n", dp->n);
|
||||
DLOG("using cached desync profile %u (%s)\n", dp->n, PROFILE_NAME(dp));
|
||||
else if (!ctrack || !ctrack->dp_search_complete)
|
||||
{
|
||||
const char *hostname = NULL;
|
||||
@@ -1027,7 +1002,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
if (!hostname && !bReverse)
|
||||
{
|
||||
if (ipcache_get_hostname(sdip4, sdip6, host, sizeof(host), &hostname_is_ip) && *host)
|
||||
if (!(hostname = ctrack_replay->hostname = strdup(host)))
|
||||
if (!(hostname = ctrack->hostname = strdup(host)))
|
||||
DLOG_ERR("strdup(host): out of memory\n");
|
||||
}
|
||||
}
|
||||
@@ -1096,7 +1071,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
// process reply packets for auto hostlist mode
|
||||
// by looking at RSTs or HTTP replies we decide whether original request looks like DPI blocked
|
||||
// we only process first-sequence replies. do not react to subsequent redirects or RSTs
|
||||
if (!params.server && ctrack && ctrack->hostname && ctrack->hostname_ah_check && (ctrack->ack_last - ctrack->ack0) == 1)
|
||||
if (!params.server && ctrack && ctrack->hostname && ctrack->hostname_ah_check && (ctrack->pos.ack_last - ctrack->pos.ack0) == 1)
|
||||
{
|
||||
bool bFail = false;
|
||||
|
||||
@@ -1109,7 +1084,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
if (dis->tcp->th_flags & TH_RST)
|
||||
{
|
||||
DLOG("incoming RST detected for hostname %s\n", ctrack->hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u : client %s : proto %s : incoming RST", ctrack->hostname, ctrack->dp->n, client_ip_port, l7proto_str(l7proto));
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : incoming RST", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto));
|
||||
bFail = true;
|
||||
}
|
||||
else if (dis->len_payload && l7proto == L7_HTTP)
|
||||
@@ -1121,7 +1096,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
if (bFail)
|
||||
{
|
||||
DLOG("redirect to another domain detected. possibly DPI redirect.\n");
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u : client %s : proto %s : redirect to another domain", ctrack->hostname, ctrack->dp->n, client_ip_port, l7proto_str(l7proto));
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %u (%s) : client %s : proto %s : redirect to another domain", ctrack->hostname, ctrack->dp->n, PROFILE_NAME(dp), client_ip_port, l7proto_str(l7proto));
|
||||
}
|
||||
else
|
||||
DLOG("local or in-domain redirect detected. it's not a DPI redirect.\n");
|
||||
@@ -1186,8 +1161,8 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
// we do not reassemble http
|
||||
if (!ctrack->req_seq_present)
|
||||
{
|
||||
ctrack->req_seq_start = ctrack->seq_last;
|
||||
ctrack->req_seq_end = ctrack->pos_orig - 1;
|
||||
ctrack->req_seq_start = ctrack->pos.seq_last;
|
||||
ctrack->req_seq_end = ctrack->pos.pos_orig - 1;
|
||||
ctrack->req_seq_present = ctrack->req_seq_finalized = true;
|
||||
DLOG("req retrans : tcp seq interval %u-%u\n", ctrack->req_seq_start, ctrack->req_seq_end);
|
||||
}
|
||||
@@ -1211,7 +1186,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
{
|
||||
// do not reasm retransmissions
|
||||
if (!bReqFull && ReasmIsEmpty(&ctrack->reasm_orig) && !ctrack->req_seq_abandoned &&
|
||||
!(ctrack->req_seq_finalized && seq_within(ctrack->seq_last, ctrack->req_seq_start, ctrack->req_seq_end)))
|
||||
!(ctrack->req_seq_finalized && seq_within(ctrack->pos.seq_last, ctrack->req_seq_start, ctrack->req_seq_end)))
|
||||
{
|
||||
// do not reconstruct unexpected large payload (they are feeding garbage ?)
|
||||
if (!reasm_orig_start(ctrack, IPPROTO_TCP, TLSRecordLen(dis->data_payload), TCP_MAX_REASM, dis->data_payload, dis->len_payload))
|
||||
@@ -1222,19 +1197,19 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
if (!ctrack->req_seq_present)
|
||||
{
|
||||
// lower bound of request seq interval
|
||||
ctrack->req_seq_start = ctrack->seq_last;
|
||||
ctrack->req_seq_start = ctrack->pos.seq_last;
|
||||
ctrack->req_seq_present = true;
|
||||
}
|
||||
// upper bound of request seq interval
|
||||
// it can grow on every packet until request is complete. then interval is finalized and never touched again.
|
||||
ctrack->req_seq_end = ctrack->pos_orig - 1;
|
||||
ctrack->req_seq_end = ctrack->pos.pos_orig - 1;
|
||||
DLOG("req retrans : seq interval %u-%u\n", ctrack->req_seq_start, ctrack->req_seq_end);
|
||||
ctrack->req_seq_finalized |= bReqFull;
|
||||
}
|
||||
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_orig))
|
||||
{
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
{
|
||||
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed));
|
||||
}
|
||||
@@ -1252,7 +1227,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ctrack && (ctrack->seq_last - ctrack->seq0)==1 && IsMTProto(dis->data_payload, dis->len_payload))
|
||||
else if (ctrack && (ctrack->pos.seq_last - ctrack->pos.seq0)==1 && IsMTProto(dis->data_payload, dis->len_payload))
|
||||
{
|
||||
DLOG("packet contains telegram mtproto2 initial\n");
|
||||
// mtproto detection requires aes. react only on the first tcp data packet. do not detect if ctrack unavailable.
|
||||
@@ -1273,7 +1248,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
}
|
||||
if (ctrack && ctrack->req_seq_finalized)
|
||||
{
|
||||
uint32_t dseq = ctrack->seq_last - ctrack->req_seq_end;
|
||||
uint32_t dseq = ctrack->pos.seq_last - ctrack->req_seq_end;
|
||||
// do not react to 32-bit overflowed sequence numbers. allow 16 Mb grace window then cutoff.
|
||||
if (dseq >= 0x1000000 && !(dseq & 0x80000000)) ctrack->req_seq_abandoned = true;
|
||||
}
|
||||
@@ -1379,7 +1354,7 @@ static uint8_t dpi_desync_tcp_packet_play(unsigned int replay_piece, unsigned in
|
||||
ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2));
|
||||
DLOG("dpi desync src=%s dst=%s track_direction=%s fixed_direction=%s connection_proto=%s payload_type=%s\n", s1, s2, bReverse ? "in" : "out", bReverseFixed ? "in" : "out", l7proto_str(l7proto), l7payload_str(l7payload));
|
||||
}
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, l7payload, dis, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, rdata_payload, rlen_payload, NULL, 0);
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, pos, l7payload, dis, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, rdata_payload, rlen_payload, NULL, 0);
|
||||
|
||||
pass:
|
||||
return (!bReverseFixed && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
||||
@@ -1396,7 +1371,13 @@ static void quic_reasm_cancel(t_ctrack *ctrack, const char *reason)
|
||||
}
|
||||
|
||||
|
||||
static uint8_t dpi_desync_udp_packet_play(unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset, uint32_t fwmark, const char *ifin, const char *ifout, const struct dissect *dis, uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
static uint8_t dpi_desync_udp_packet_play(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset,
|
||||
uint32_t fwmark,
|
||||
const char *ifin, const char *ifout,
|
||||
const t_ctrack_position *pos,
|
||||
const struct dissect *dis,
|
||||
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
{
|
||||
uint8_t verdict = VERDICT_PASS;
|
||||
|
||||
@@ -1452,7 +1433,7 @@ static uint8_t dpi_desync_udp_packet_play(unsigned int replay_piece, unsigned in
|
||||
l7proto = ctrack_replay->l7proto;
|
||||
dp = ctrack_replay->dp;
|
||||
if (dp)
|
||||
DLOG("using cached desync profile %u\n", dp->n);
|
||||
DLOG("using cached desync profile %u (%s)\n", dp->n, PROFILE_NAME(dp));
|
||||
else if (!ctrack_replay->dp_search_complete)
|
||||
{
|
||||
dp = ctrack_replay->dp = dp_find(¶ms.desync_profiles, IPPROTO_UDP, sdip4, sdip6, sdport, ctrack_replay->hostname, ctrack_replay->hostname_is_ip, l7proto, ssid, NULL, NULL, NULL);
|
||||
@@ -1488,7 +1469,7 @@ static uint8_t dpi_desync_udp_packet_play(unsigned int replay_piece, unsigned in
|
||||
#endif
|
||||
if (ctrack) l7proto = ctrack->l7proto;
|
||||
if (dp)
|
||||
DLOG("using cached desync profile %u\n", dp->n);
|
||||
DLOG("using cached desync profile %u (%s)\n", dp->n, PROFILE_NAME(dp));
|
||||
else if (!ctrack || !ctrack->dp_search_complete)
|
||||
{
|
||||
const char *hostname = NULL;
|
||||
@@ -1500,7 +1481,7 @@ static uint8_t dpi_desync_udp_packet_play(unsigned int replay_piece, unsigned in
|
||||
if (!hostname && !bReverse)
|
||||
{
|
||||
if (ipcache_get_hostname(sdip4, sdip6, host, sizeof(host), &hostname_is_ip) && *host)
|
||||
if (!(hostname = ctrack_replay->hostname = strdup(host)))
|
||||
if (!(hostname = ctrack->hostname = strdup(host)))
|
||||
DLOG_ERR("strdup(host): out of memory\n");
|
||||
}
|
||||
}
|
||||
@@ -1553,6 +1534,7 @@ static uint8_t dpi_desync_udp_packet_play(unsigned int replay_piece, unsigned in
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_DNS_RESPONSE,L7_DNS,IsDNSResponse,false},
|
||||
{L7P_DHT,L7_DHT,IsDht,false},
|
||||
{L7P_STUN,L7_STUN,IsStunMessage,false},
|
||||
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
|
||||
{L7P_WIREGUARD_RESPONSE,L7_WIREGUARD,IsWireguardHandshakeResponse,false},
|
||||
{L7P_WIREGUARD_COOKIE,L7_WIREGUARD,IsWireguardHandshakeCookie,false},
|
||||
@@ -1629,7 +1611,7 @@ static uint8_t dpi_desync_udp_packet_play(unsigned int replay_piece, unsigned in
|
||||
}
|
||||
if (!ReasmIsEmpty(&ctrack->reasm_orig))
|
||||
{
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
{
|
||||
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed));
|
||||
}
|
||||
@@ -1669,7 +1651,7 @@ static uint8_t dpi_desync_udp_packet_play(unsigned int replay_piece, unsigned in
|
||||
if (!reasm_orig_start(ctrack, IPPROTO_UDP, UDP_MAX_REASM, UDP_MAX_REASM, clean, clean_len))
|
||||
goto pass_reasm_cancel;
|
||||
}
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
if (rawpacket_queue_csum_fix(&ctrack->delayed, dis, &ctrack->pos, &dst, fwmark, desync_fwmark, ifin, ifout))
|
||||
{
|
||||
DLOG("DELAY desync until reasm is complete (#%u)\n", rawpacket_queue_count(&ctrack->delayed));
|
||||
}
|
||||
@@ -1704,7 +1686,7 @@ static uint8_t dpi_desync_udp_packet_play(unsigned int replay_piece, unsigned in
|
||||
|
||||
t_protocol_probe testers[] = {
|
||||
{L7P_DISCORD_IP_DISCOVERY,L7_DISCORD,IsDiscordIpDiscoveryRequest,false},
|
||||
{L7P_STUN_BINDING_REQ,L7_STUN,IsStunBindingRequest,false},
|
||||
{L7P_STUN,L7_STUN,IsStunMessage,false},
|
||||
{L7P_DNS_QUERY,L7_DNS,IsDNSQuery,false},
|
||||
{L7P_DHT,L7_DHT,IsDht,false},
|
||||
{L7P_WIREGUARD_INITIATION,L7_WIREGUARD,IsWireguardHandshakeInitiation,false},
|
||||
@@ -1828,7 +1810,7 @@ static uint8_t dpi_desync_udp_packet_play(unsigned int replay_piece, unsigned in
|
||||
ntop46_port((struct sockaddr *)&dst, s2, sizeof(s2));
|
||||
DLOG("dpi desync src=%s dst=%s track_direction=%s fixed_direction=%s connection_proto=%s payload_type=%s\n", s1, s2, bReverse ? "in" : "out", bReverseFixed ? "in" : "out", l7proto_str(l7proto), l7payload_str(l7payload));
|
||||
}
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, l7payload, dis, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, NULL, 0, data_decrypt, len_decrypt);
|
||||
verdict = desync(dp, fwmark, ifin, ifout, bReverseFixed, ctrack_replay, pos, l7payload, dis, mod_pkt, len_mod_pkt, replay_piece, replay_piece_count, reasm_offset, NULL, 0, data_decrypt, len_decrypt);
|
||||
|
||||
pass:
|
||||
return (!bReverse && (verdict & VERDICT_MASK) == VERDICT_DROP) ? ct_new_postnat_fix(ctrack, dis, mod_pkt, len_mod_pkt) : verdict;
|
||||
@@ -1877,6 +1859,7 @@ static void packet_debug(bool replay, const struct dissect *dis)
|
||||
|
||||
static uint8_t dpi_desync_packet_play(
|
||||
unsigned int replay_piece, unsigned int replay_piece_count, size_t reasm_offset, uint32_t fwmark, const char *ifin, const char *ifout,
|
||||
const t_ctrack_position *pos,
|
||||
const uint8_t *data_pkt, size_t len_pkt,
|
||||
uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
{
|
||||
@@ -1892,7 +1875,7 @@ static uint8_t dpi_desync_packet_play(
|
||||
case IPPROTO_TCP:
|
||||
if (dis.tcp)
|
||||
{
|
||||
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict = dpi_desync_tcp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, pos, &dis, mod_pkt, len_mod_pkt);
|
||||
// we fix csum before pushing to replay queue
|
||||
if (!replay_piece_count) verdict_tcp_csum_fix(verdict, (struct tcphdr *)dis.tcp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
@@ -1900,7 +1883,7 @@ static uint8_t dpi_desync_packet_play(
|
||||
case IPPROTO_UDP:
|
||||
if (dis.udp)
|
||||
{
|
||||
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, &dis, mod_pkt, len_mod_pkt);
|
||||
verdict = dpi_desync_udp_packet_play(replay_piece, replay_piece_count, reasm_offset, fwmark, ifin, ifout, pos, &dis, mod_pkt, len_mod_pkt);
|
||||
// we fix csum before pushing to replay queue
|
||||
if (!replay_piece_count) verdict_udp_csum_fix(verdict, (struct udphdr *)dis.udp, dis.transport_len, dis.ip, dis.ip6);
|
||||
}
|
||||
@@ -1912,7 +1895,7 @@ static uint8_t dpi_desync_packet_play(
|
||||
uint8_t dpi_desync_packet(uint32_t fwmark, const char *ifin, const char *ifout, const uint8_t *data_pkt, size_t len_pkt, uint8_t *mod_pkt, size_t *len_mod_pkt)
|
||||
{
|
||||
ipcachePurgeRateLimited(¶ms.ipcache, params.ipcache_lifetime);
|
||||
return dpi_desync_packet_play(0, 0, 0, fwmark, ifin, ifout, data_pkt, len_pkt, mod_pkt, len_mod_pkt);
|
||||
return dpi_desync_packet_play(0, 0, 0, fwmark, ifin, ifout, NULL, data_pkt, len_pkt, mod_pkt, len_mod_pkt);
|
||||
}
|
||||
|
||||
|
||||
@@ -1930,7 +1913,7 @@ static bool replay_queue(struct rawpacket_tailhead *q)
|
||||
{
|
||||
DLOG("REPLAYING delayed packet #%u offset %zu\n", i+1, offset);
|
||||
modlen = sizeof(mod);
|
||||
uint8_t verdict = dpi_desync_packet_play(i, count, offset, rp->fwmark_orig, rp->ifin, rp->ifout, rp->packet, rp->len, mod, &modlen);
|
||||
uint8_t verdict = dpi_desync_packet_play(i, count, offset, rp->fwmark_orig, rp->ifin, rp->ifout, rp->pos_present ? &rp->pos : NULL, rp->packet, rp->len, mod, &modlen);
|
||||
switch (verdict & VERDICT_MASK)
|
||||
{
|
||||
case VERDICT_MODIFY:
|
||||
|
||||
@@ -258,7 +258,7 @@ static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, con
|
||||
// return : true = apply fooling, false = do not apply
|
||||
bool HostlistCheck(const struct desync_profile *dp, const char *host, bool no_match_subdomains, bool *excluded, bool bSkipReloadCheck)
|
||||
{
|
||||
DLOG("* hostlist check for profile %u\n",dp->n);
|
||||
DLOG("* hostlist check for profile %u (%s)\n",dp->n,PROFILE_NAME(dp));
|
||||
return HostlistCheck_(&dp->hl_collection, &dp->hl_collection_exclude, host, no_match_subdomains, excluded, bSkipReloadCheck);
|
||||
}
|
||||
|
||||
@@ -301,13 +301,34 @@ struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude,
|
||||
filename);
|
||||
}
|
||||
|
||||
static void HostlistsDebugProfile(const struct desync_profile *dp, const char *entity)
|
||||
{
|
||||
struct hostlist_item *hl_item;
|
||||
|
||||
LIST_FOREACH(hl_item, &dp->hl_collection, next)
|
||||
if (hl_item->hfile!=dp->hostlist_auto)
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("%s %u (%s) include hostlist %s%s\n",entity, dp->n, PROFILE_NAME(dp), hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("%s %u (%s) include fixed hostlist%s\n",entity, dp->n, PROFILE_NAME(dp), hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
LIST_FOREACH(hl_item, &dp->hl_collection_exclude, next)
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("%s %u (%s) exclude hostlist %s%s\n",entity, dp->n,PROFILE_NAME(dp),hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("%s %u (%s) exclude fixed hostlist%s\n",entity, dp->n,PROFILE_NAME(dp),hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
if (dp->hostlist_auto)
|
||||
DLOG("%s %u (%s) auto hostlist %s%s\n",entity, dp->n,PROFILE_NAME(dp),dp->hostlist_auto->filename,dp->hostlist_auto->hostlist ? "" : " (empty)");
|
||||
}
|
||||
void HostlistsDebug()
|
||||
{
|
||||
if (!params.debug) return;
|
||||
|
||||
struct hostlist_file *hfile;
|
||||
struct desync_profile_list *dpl;
|
||||
struct hostlist_item *hl_item;
|
||||
|
||||
LIST_FOREACH(hfile, ¶ms.hostlists, next)
|
||||
{
|
||||
@@ -319,22 +340,10 @@ void HostlistsDebug()
|
||||
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next)
|
||||
if (hl_item->hfile!=dpl->dp.hostlist_auto)
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("profile %u include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("profile %u include fixed hostlist%s\n",dpl->dp.n, hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next)
|
||||
{
|
||||
if (hl_item->hfile->filename)
|
||||
DLOG("profile %u exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
else
|
||||
DLOG("profile %u exclude fixed hostlist%s\n",dpl->dp.n,hl_item->hfile->hostlist ? "" : " (empty)");
|
||||
}
|
||||
if (dpl->dp.hostlist_auto)
|
||||
DLOG("profile %u auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)");
|
||||
HostlistsDebugProfile(&dpl->dp, "profile");
|
||||
}
|
||||
LIST_FOREACH(dpl, ¶ms.desync_templates, next)
|
||||
{
|
||||
HostlistsDebugProfile(&dpl->dp, "template");
|
||||
}
|
||||
}
|
||||
|
||||
37
nfq2/ipset.c
37
nfq2/ipset.c
@@ -235,7 +235,7 @@ static bool IpsetCheck_(const struct ipset_collection_head *ips, const struct ip
|
||||
bool IpsetCheck(const struct desync_profile *dp, const struct in_addr *ipv4, const struct in6_addr *ipv6)
|
||||
{
|
||||
if (PROFILE_IPSETS_ABSENT(dp)) return true;
|
||||
DLOG("* ipset check for profile %u\n",dp->n);
|
||||
DLOG("* ipset check for profile %u (%s)\n",dp->n,PROFILE_NAME(dp));
|
||||
return IpsetCheck_(&dp->ips_collection,&dp->ips_collection_exclude,ipv4,ipv6);
|
||||
}
|
||||
|
||||
@@ -287,13 +287,31 @@ static const char *dbg_ipset_fill(const ipset *ips)
|
||||
else
|
||||
return "empty";
|
||||
}
|
||||
void IpsetsDebugProfile(const struct desync_profile *dp, const char *entity)
|
||||
{
|
||||
struct ipset_item *ips_item;
|
||||
|
||||
LIST_FOREACH(ips_item, &dp->ips_collection, next)
|
||||
{
|
||||
if (ips_item->hfile->filename)
|
||||
DLOG("%s %u (%s) include ipset %s (%s)\n",entity,dp->n,PROFILE_NAME(dp),ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
else
|
||||
DLOG("%s %u (%s) include fixed ipset (%s)\n",entity,dp->n,PROFILE_NAME(dp),dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
}
|
||||
LIST_FOREACH(ips_item, &dp->ips_collection_exclude, next)
|
||||
{
|
||||
if (ips_item->hfile->filename)
|
||||
DLOG("%s %u (%s) exclude ipset %s (%s)\n",entity,dp->n,PROFILE_NAME(dp),ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
else
|
||||
DLOG("%s %u (%s) exclude fixed ipset (%s)\n",entity,dp->n,PROFILE_NAME(dp),dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
}
|
||||
}
|
||||
void IpsetsDebug()
|
||||
{
|
||||
if (!params.debug) return;
|
||||
|
||||
struct ipset_file *hfile;
|
||||
struct desync_profile_list *dpl;
|
||||
struct ipset_item *ips_item;
|
||||
|
||||
LIST_FOREACH(hfile, ¶ms.ipsets, next)
|
||||
{
|
||||
@@ -305,15 +323,10 @@ void IpsetsDebug()
|
||||
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
LIST_FOREACH(ips_item, &dpl->dp.ips_collection, next)
|
||||
if (ips_item->hfile->filename)
|
||||
DLOG("profile %u include ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
else
|
||||
DLOG("profile %u include fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
LIST_FOREACH(ips_item, &dpl->dp.ips_collection_exclude, next)
|
||||
if (ips_item->hfile->filename)
|
||||
DLOG("profile %u exclude ipset %s (%s)\n",dpl->dp.n,ips_item->hfile->filename,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
else
|
||||
DLOG("profile %u exclude fixed ipset (%s)\n",dpl->dp.n,dbg_ipset_fill(&ips_item->hfile->ipset));
|
||||
IpsetsDebugProfile(&dpl->dp, "profile");
|
||||
}
|
||||
LIST_FOREACH(dpl, ¶ms.desync_templates, next)
|
||||
{
|
||||
IpsetsDebugProfile(&dpl->dp, "template");
|
||||
}
|
||||
}
|
||||
|
||||
207
nfq2/lua.c
207
nfq2/lua.c
@@ -19,6 +19,11 @@
|
||||
#include "crypto/aes-ctr.h"
|
||||
|
||||
|
||||
void desync_instance(const char *func, unsigned int dp_n, unsigned int func_n, char *instance, size_t inst_size)
|
||||
{
|
||||
snprintf(instance, inst_size, "%s_%u_%u", func, dp_n, func_n);
|
||||
}
|
||||
|
||||
static void lua_check_argc(lua_State *L, const char *where, int argc)
|
||||
{
|
||||
int num_args = lua_gettop(L);
|
||||
@@ -605,7 +610,7 @@ static int luacall_uname(lua_State *L)
|
||||
}
|
||||
static int luacall_clock_gettime(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"uname", 0);
|
||||
lua_check_argc(L,"clock_gettime", 0);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
@@ -639,7 +644,7 @@ static int luacall_instance_cutoff(lua_State *L)
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
bool bIn,bOut;
|
||||
if (argc>=2)
|
||||
if (argc>=2 && lua_type(L,2)!=LUA_TNIL)
|
||||
{
|
||||
luaL_checktype(L,2,LUA_TBOOLEAN);
|
||||
bOut = lua_toboolean(L,2);
|
||||
@@ -705,6 +710,102 @@ bool lua_instance_cutoff_check(const t_lua_desync_context *ctx, bool bIn)
|
||||
return b;
|
||||
}
|
||||
|
||||
static int luacall_lua_cutoff(lua_State *L)
|
||||
{
|
||||
lua_check_argc_range(L,"lua_cutoff",1,2);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "lua_cutoff expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
bool bIn,bOut;
|
||||
if (argc>=2 && lua_type(L,2)!=LUA_TNIL)
|
||||
{
|
||||
luaL_checktype(L,2,LUA_TBOOLEAN);
|
||||
bOut = lua_toboolean(L,2);
|
||||
bIn = !bOut;
|
||||
}
|
||||
else
|
||||
bIn = bOut = true;
|
||||
|
||||
if (ctx->ctrack)
|
||||
{
|
||||
DLOG("lua cutoff from '%s' in=%u out=%u\n",ctx->instance,bIn,bOut);
|
||||
// lua cutoff is one way transition
|
||||
if (bIn) ctx->ctrack->b_lua_in_cutoff = true;
|
||||
if (bOut) ctx->ctrack->b_lua_out_cutoff = true;
|
||||
}
|
||||
else
|
||||
DLOG("lua cutoff requested from '%s' in=%u out=%u but not possible without conntrack\n",ctx->instance,bIn,bOut);
|
||||
|
||||
LUA_STACK_GUARD_RETURN(L,0)
|
||||
}
|
||||
|
||||
static int luacall_execution_plan(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"execution_plan",1);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
const t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "execution_plan expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
|
||||
lua_newtable(L);
|
||||
|
||||
struct func_list *func;
|
||||
char instance[256], pls[2048];
|
||||
struct packet_range *range;
|
||||
unsigned int n=1;
|
||||
LIST_FOREACH(func, &ctx->dp->lua_desync, next)
|
||||
{
|
||||
if (n > ctx->func_n)
|
||||
{
|
||||
desync_instance(func->func, ctx->dp->n, n, instance, sizeof(instance));
|
||||
range = ctx->incoming ? &func->range_in : &func->range_out;
|
||||
lua_pushinteger(params.L, n - ctx->func_n);
|
||||
lua_createtable(params.L, 0, 6);
|
||||
lua_pushf_args(&func->args, -1);
|
||||
lua_pushf_str("func", func->func);
|
||||
lua_pushf_int("func_n", ctx->func_n);
|
||||
lua_pushf_str("func_instance", instance);
|
||||
lua_pushf_range("range", range);
|
||||
if (l7_payload_str_list(func->payload_type, pls, sizeof(pls)))
|
||||
lua_pushf_str("payload_filter", pls);
|
||||
else
|
||||
lua_pushf_nil("payload_filter");
|
||||
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
LUA_STACK_GUARD_RETURN(L,1)
|
||||
}
|
||||
static int luacall_execution_plan_cancel(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"execution_plan_cancel",1);
|
||||
|
||||
t_lua_desync_context *ctx;
|
||||
|
||||
if (!lua_islightuserdata(L,1))
|
||||
luaL_error(L, "execution_plan_cancel expect desync context in the first argument");
|
||||
ctx = lua_touserdata(L,1);
|
||||
|
||||
DLOG("execution plan cancel from '%s'\n",ctx->instance);
|
||||
|
||||
ctx->cancel = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int luacall_raw_packet(lua_State *L)
|
||||
{
|
||||
lua_check_argc(L,"raw_packet",1);
|
||||
@@ -1066,21 +1167,23 @@ void lua_pushf_dissect(const struct dissect *dis)
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack)
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
if (!pos) pos = &ctrack->pos;
|
||||
|
||||
lua_pushliteral(params.L, "track");
|
||||
if (ctrack)
|
||||
{
|
||||
lua_createtable(params.L, 0, 13 + (ctrack->ipproto == IPPROTO_TCP));
|
||||
|
||||
lua_pushf_int("pcounter_orig", ctrack->pcounter_orig);
|
||||
lua_pushf_int("pdcounter_orig", ctrack->pdcounter_orig);
|
||||
lua_pushf_int("pbcounter_orig", ctrack->pbcounter_orig);
|
||||
lua_pushf_int("pcounter_reply", ctrack->pcounter_reply);
|
||||
lua_pushf_int("pdcounter_reply", ctrack->pdcounter_reply);
|
||||
lua_pushf_int("pbcounter_reply", ctrack->pbcounter_reply);
|
||||
lua_pushf_int("pcounter_orig", pos->pcounter_orig);
|
||||
lua_pushf_int("pdcounter_orig", pos->pdcounter_orig);
|
||||
lua_pushf_int("pbcounter_orig", pos->pbcounter_orig);
|
||||
lua_pushf_int("pcounter_reply", pos->pcounter_reply);
|
||||
lua_pushf_int("pdcounter_reply", pos->pdcounter_reply);
|
||||
lua_pushf_int("pbcounter_reply", pos->pbcounter_reply);
|
||||
if (ctrack->incoming_ttl)
|
||||
lua_pushf_int("incoming_ttl", ctrack->incoming_ttl);
|
||||
else
|
||||
@@ -1096,20 +1199,20 @@ void lua_pushf_ctrack(const t_ctrack *ctrack)
|
||||
{
|
||||
lua_pushliteral(params.L, "tcp");
|
||||
lua_createtable(params.L, 0, 14);
|
||||
lua_pushf_int("seq0", ctrack->seq0);
|
||||
lua_pushf_int("seq", ctrack->seq_last);
|
||||
lua_pushf_int("ack0", ctrack->ack0);
|
||||
lua_pushf_int("ack", ctrack->ack_last);
|
||||
lua_pushf_int("pos_orig", ctrack->pos_orig - ctrack->seq0);
|
||||
lua_pushf_int("winsize_orig", ctrack->winsize_orig);
|
||||
lua_pushf_int("winsize_orig_calc", ctrack->winsize_orig_calc);
|
||||
lua_pushf_int("scale_orig", ctrack->scale_orig);
|
||||
lua_pushf_int("mss_orig", ctrack->mss_orig);
|
||||
lua_pushf_int("pos_reply", ctrack->pos_reply - ctrack->ack0);
|
||||
lua_pushf_int("winsize_reply", ctrack->winsize_reply);
|
||||
lua_pushf_int("winsize_reply_calc", ctrack->winsize_reply_calc);
|
||||
lua_pushf_int("scale_reply", ctrack->scale_reply);
|
||||
lua_pushf_int("mss_reply", ctrack->mss_reply);
|
||||
lua_pushf_int("seq0", pos->seq0);
|
||||
lua_pushf_int("seq", pos->seq_last);
|
||||
lua_pushf_int("ack0", pos->ack0);
|
||||
lua_pushf_int("ack", pos->ack_last);
|
||||
lua_pushf_int("pos_orig", pos->pos_orig - pos->seq0);
|
||||
lua_pushf_int("winsize_orig", pos->winsize_orig);
|
||||
lua_pushf_int("winsize_orig_calc", pos->winsize_orig_calc);
|
||||
lua_pushf_int("scale_orig", pos->scale_orig);
|
||||
lua_pushf_int("mss_orig", pos->mss_orig);
|
||||
lua_pushf_int("pos_reply", pos->pos_reply - pos->ack0);
|
||||
lua_pushf_int("winsize_reply", pos->winsize_reply);
|
||||
lua_pushf_int("winsize_reply_calc", pos->winsize_reply_calc);
|
||||
lua_pushf_int("scale_reply", pos->scale_reply);
|
||||
lua_pushf_int("mss_reply", pos->mss_reply);
|
||||
lua_rawset(params.L,-3);
|
||||
}
|
||||
}
|
||||
@@ -1120,7 +1223,7 @@ void lua_pushf_ctrack(const t_ctrack *ctrack)
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
|
||||
void lua_pushf_args(const struct ptr_list_head *args, int idx_desync)
|
||||
void lua_pushf_args(const struct str2_list_head *args, int idx_desync)
|
||||
{
|
||||
// var=val - pass val string
|
||||
// var=%val - subst 'val' blob
|
||||
@@ -1130,7 +1233,7 @@ void lua_pushf_args(const struct ptr_list_head *args, int idx_desync)
|
||||
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
struct ptr_list *arg;
|
||||
struct str2_list *arg;
|
||||
const char *var, *val;
|
||||
|
||||
idx_desync = lua_absindex(params.L, idx_desync);
|
||||
@@ -1139,8 +1242,8 @@ void lua_pushf_args(const struct ptr_list_head *args, int idx_desync)
|
||||
lua_newtable(params.L);
|
||||
LIST_FOREACH(arg, args, next)
|
||||
{
|
||||
var = (char*)arg->ptr1;
|
||||
val = arg->ptr2 ? (char*)arg->ptr2 : "";
|
||||
var = arg->str1;
|
||||
val = arg->str2 ? arg->str2 : "";
|
||||
if (val[0]=='\\' && (val[1]=='%' || val[1]=='#'))
|
||||
// escape char
|
||||
lua_pushf_str(var, val+1);
|
||||
@@ -1160,7 +1263,33 @@ void lua_pushf_args(const struct ptr_list_head *args, int idx_desync)
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
void lua_pushf_pos(const char *name, const struct packet_pos *pos)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
char smode[2]="?";
|
||||
lua_pushf_table(name);
|
||||
lua_getfield(params.L,-1,name);
|
||||
*smode=pos->mode;
|
||||
lua_pushf_str("mode",smode);
|
||||
lua_pushf_int("pos",pos->pos);
|
||||
lua_pop(params.L,1);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
void lua_pushf_range(const char *name, const struct packet_range *range)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
lua_pushf_table(name);
|
||||
lua_getfield(params.L,-1,"range");
|
||||
lua_pushf_bool("upper_cutoff",range->upper_cutoff);
|
||||
lua_pushf_pos("from", &range->from);
|
||||
lua_pushf_pos("to", &range->to);
|
||||
lua_pop(params.L,1);
|
||||
|
||||
LUA_STACK_GUARD_LEAVE(params.L, 0)
|
||||
}
|
||||
|
||||
|
||||
static void lua_reconstruct_extract_options(lua_State *L, int idx, bool *badsum, bool *ip6_preserve_next, uint8_t *ip6_last_proto)
|
||||
@@ -2663,6 +2792,21 @@ static void lua_init_const(void)
|
||||
{
|
||||
LUA_STACK_GUARD_ENTER(params.L)
|
||||
|
||||
const struct
|
||||
{
|
||||
const char *name, *v;
|
||||
} cstr[] = {
|
||||
{"NFQWS2_VER",params.verstr}
|
||||
};
|
||||
|
||||
DLOG("LUA STR:");
|
||||
for (int i=0;i<sizeof(cstr)/sizeof(*cstr);i++)
|
||||
{
|
||||
lua_pushstring(params.L, cstr[i].v);
|
||||
lua_setglobal(params.L, cstr[i].name);
|
||||
DLOG(" %s", cstr[i].name);
|
||||
}
|
||||
|
||||
const struct
|
||||
{
|
||||
const char *name;
|
||||
@@ -2674,6 +2818,7 @@ static void lua_init_const(void)
|
||||
{"divert_port",params.port},
|
||||
#endif
|
||||
{"desync_fwmark",params.desync_fwmark},
|
||||
{"NFQWS2_COMPAT_VER",LUA_COMPAT_VER},
|
||||
|
||||
{"VERDICT_PASS",VERDICT_PASS},
|
||||
{"VERDICT_MODIFY",VERDICT_MODIFY},
|
||||
@@ -2735,7 +2880,7 @@ static void lua_init_const(void)
|
||||
{"IPPROTO_SHIM6",IPPROTO_SHIM6},
|
||||
{"IPPROTO_NONE",IPPROTO_NONE}
|
||||
};
|
||||
DLOG("LUA NUMERIC:");
|
||||
DLOG("\nLUA NUMERIC:");
|
||||
for (int i=0;i<sizeof(cuint)/sizeof(*cuint);i++)
|
||||
{
|
||||
lua_pushinteger(params.L, (lua_Integer)cuint[i].v);
|
||||
@@ -2836,6 +2981,12 @@ static void lua_init_functions(void)
|
||||
|
||||
// voluntarily stop receiving packets
|
||||
{"instance_cutoff",luacall_instance_cutoff},
|
||||
// voluntarily stop receiving packets of the current connection for all instances
|
||||
{"lua_cutoff",luacall_lua_cutoff},
|
||||
// get info about upcoming desync instances and their arguments
|
||||
{"execution_plan",luacall_execution_plan},
|
||||
// cancel execution of upcoming desync instances and their arguments
|
||||
{"execution_plan_cancel",luacall_execution_plan_cancel},
|
||||
// get raw packet data
|
||||
{"raw_packet",luacall_raw_packet},
|
||||
|
||||
|
||||
13
nfq2/lua.h
13
nfq2/lua.h
@@ -28,6 +28,9 @@
|
||||
#define LUA_STACK_GUARD_RETURN(L,N) LUA_STACK_GUARD_LEAVE(L,N); return N;
|
||||
|
||||
|
||||
void desync_instance(const char *func, unsigned int dp_n, unsigned int func_n, char *instance, size_t inst_size);
|
||||
|
||||
|
||||
bool lua_test_init_script_files(void);
|
||||
bool lua_init(void);
|
||||
void lua_shutdown(void);
|
||||
@@ -68,8 +71,10 @@ void lua_pushf_iphdr(const struct ip *ip, size_t len);
|
||||
void lua_pushf_ip6hdr(const struct ip6_hdr *ip6, size_t len);
|
||||
void lua_push_dissect(const struct dissect *dis);
|
||||
void lua_pushf_dissect(const struct dissect *dis);
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack);
|
||||
void lua_pushf_args(const struct ptr_list_head *args, int idx_desync);
|
||||
void lua_pushf_ctrack(const t_ctrack *ctrack, const t_ctrack_position *pos);
|
||||
void lua_pushf_args(const struct str2_list_head *args, int idx_desync);
|
||||
void lua_pushf_pos(const char *name, const struct packet_pos *pos);
|
||||
void lua_pushf_range(const char *name, const struct packet_range *range);
|
||||
void lua_pushf_global(const char *field, const char *global);
|
||||
|
||||
bool lua_reconstruct_ip6hdr(int idx, struct ip6_hdr *ip6, size_t *len, uint8_t last_proto, bool preserve_next);
|
||||
@@ -79,10 +84,12 @@ bool lua_reconstruct_udphdr(int idx, struct udphdr *udp);
|
||||
bool lua_reconstruct_dissect(int idx, uint8_t *buf, size_t *len, bool badsum, bool ip6_preserve_next);
|
||||
|
||||
typedef struct {
|
||||
unsigned int func_n;
|
||||
const char *func, *instance;
|
||||
const struct desync_profile *dp;
|
||||
const t_ctrack *ctrack;
|
||||
const struct dissect *dis;
|
||||
t_ctrack *ctrack;
|
||||
bool incoming,cancel;
|
||||
} t_lua_desync_context;
|
||||
|
||||
bool lua_instance_cutoff_check(const t_lua_desync_context *ctx, bool bIn);
|
||||
|
||||
232
nfq2/nfqws.c
232
nfq2/nfqws.c
@@ -48,11 +48,6 @@
|
||||
#define NF_ACCEPT 1
|
||||
#endif
|
||||
|
||||
#define CTRACK_T_SYN 60
|
||||
#define CTRACK_T_FIN 60
|
||||
#define CTRACK_T_EST 300
|
||||
#define CTRACK_T_UDP 60
|
||||
|
||||
#define MAX_CONFIG_FILE_SIZE 16384
|
||||
|
||||
struct params_s params;
|
||||
@@ -99,7 +94,7 @@ static void onusr2(int sig)
|
||||
struct desync_profile_list *dpl;
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
printf("\nDESYNC profile %u\n", dpl->dp.n);
|
||||
printf("\nDESYNC profile %u (%s)\n", dpl->dp.n, PROFILE_NAME(&dpl->dp));
|
||||
HostFailPoolDump(dpl->dp.hostlist_auto_fail_counters);
|
||||
}
|
||||
printf("\nIPCACHE\n");
|
||||
@@ -1007,27 +1002,28 @@ static bool parse_pf_list(char *opt, struct port_filters_head *pfl)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lua_call_param_add(char *opt, struct ptr_list_head *args)
|
||||
bool lua_call_param_add(char *opt, struct str2_list_head *args)
|
||||
{
|
||||
char c,*p;
|
||||
struct ptr_list *arg;
|
||||
struct str2_list *arg;
|
||||
|
||||
if ((p = strchr(opt,'=')))
|
||||
{
|
||||
c = *p; *p = 0;
|
||||
}
|
||||
if (!is_identifier(opt) || !(arg=ptrlist_add(args)))
|
||||
if (!is_identifier(opt) || !(arg=str2list_add(args)))
|
||||
{
|
||||
if (p) *p = c;
|
||||
return false;
|
||||
}
|
||||
arg->ptr1 = strdup(opt);
|
||||
arg->str1 = strdup(opt);
|
||||
if (p)
|
||||
{
|
||||
arg->ptr2 = strdup(p+1);
|
||||
arg->str2 = strdup(p+1);
|
||||
*p = c;
|
||||
if (!arg->str2) return false;
|
||||
}
|
||||
return arg->ptr1;
|
||||
return !!arg->str1;
|
||||
}
|
||||
|
||||
struct func_list *parse_lua_call(char *opt, struct func_list_head *flist)
|
||||
@@ -1053,7 +1049,6 @@ struct func_list *parse_lua_call(char *opt, struct func_list_head *flist)
|
||||
last = !*e;
|
||||
c = *e;
|
||||
*e = 0;
|
||||
|
||||
b = lua_call_param_add(p, &f->args);
|
||||
if (!last) *e++ = c;
|
||||
if (!b) goto err;
|
||||
@@ -1156,21 +1151,21 @@ static void BlobDebug()
|
||||
}
|
||||
}
|
||||
|
||||
static void LuaDesyncDebug(struct desync_profile *dp)
|
||||
static void LuaDesyncDebug(struct desync_profile *dp, const char *entity)
|
||||
{
|
||||
if (params.debug)
|
||||
{
|
||||
struct func_list *func;
|
||||
struct ptr_list *arg;
|
||||
struct str2_list *arg;
|
||||
int n,i;
|
||||
LIST_FOREACH(func, &dp->lua_desync, next)
|
||||
{
|
||||
DLOG("profile %u lua %s(",dp->n,func->func);
|
||||
DLOG("%s %u (%s) lua %s(",entity,dp->n,PROFILE_NAME(dp),func->func);
|
||||
n=0;
|
||||
LIST_FOREACH(arg, &func->args, next)
|
||||
{
|
||||
if (n) DLOG(",");
|
||||
DLOG(arg->ptr2 ? "%s=\"%s\"" : "%s=\"\"", (char*)arg->ptr1, (char*)arg->ptr2);
|
||||
DLOG(arg->str2 ? "%s=\"%s\"" : "%s=\"\"", arg->str1, arg->str2);
|
||||
n++;
|
||||
}
|
||||
DLOG(" range_in=%c%u%c%c%u range_out=%c%u%c%c%u payload_type=",
|
||||
@@ -1412,8 +1407,12 @@ static void exithelp(void)
|
||||
" --lua-init=@<filename>|<lua_text>\t\t\t; load LUA program from a file or string. if multiple parameters present order of execution is preserved.\n"
|
||||
" --lua-gc=<int>\t\t\t\t\t\t; forced garbage collection every N sec. default %u sec. triggers only when a packet arrives. 0 = disable.\n"
|
||||
"\nMULTI-STRATEGY:\n"
|
||||
" --new\t\t\t\t\t\t\t; begin new strategy\n"
|
||||
" --skip\t\t\t\t\t\t\t; do not use this strategy\n"
|
||||
" --new\t\t\t\t\t\t\t; begin new profile\n"
|
||||
" --skip\t\t\t\t\t\t\t; do not use this profile\n"
|
||||
" --name=<name>\t\t\t\t\t\t; set profile name\n"
|
||||
" --template[=<name>]\t\t\t\t\t; use this profile as template (must be named or will be useless)\n"
|
||||
" --cookie[=<string>]\t\t\t\t\t; pass this profile-bound string to LUA\n"
|
||||
" --import=<name>\t\t\t\t\t; populate current profile with template data\n"
|
||||
" --filter-l3=ipv4|ipv6\t\t\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --filter-tcp=[~]port1[-port2]|*\t\t\t; TCP port filter. ~ means negation. setting tcp and not setting udp filter denies udp. comma separated list allowed.\n"
|
||||
" --filter-udp=[~]port1[-port2]|*\t\t\t; UDP port filter. ~ means negation. setting udp and not setting tcp filter denies tcp. comma separated list allowed.\n"
|
||||
@@ -1500,22 +1499,6 @@ static void ApplyDefaultBlobs(struct blob_collection_head *blobs)
|
||||
load_const_blob_to_collection("fake_default_quic",buf,620,blobs,0);
|
||||
}
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
|
||||
#ifdef __ANDROID__
|
||||
#define PRINT_VER printf("github android version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
|
||||
#else
|
||||
#define PRINT_VER printf("github version %s (%s)\n\n", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH))
|
||||
#endif
|
||||
#else
|
||||
#ifdef __ANDROID__
|
||||
#define PRINT_VER printf("self-built android version %s %s\n\n", __DATE__, __TIME__)
|
||||
#else
|
||||
#define PRINT_VER printf("self-built version %s %s\n\n", __DATE__, __TIME__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
enum opt_indices {
|
||||
IDX_DEBUG,
|
||||
IDX_DRY_RUN,
|
||||
@@ -1563,6 +1546,10 @@ enum opt_indices {
|
||||
IDX_HOSTLIST_AUTO_DEBUG,
|
||||
IDX_NEW,
|
||||
IDX_SKIP,
|
||||
IDX_NAME,
|
||||
IDX_TEMPLATE,
|
||||
IDX_IMPORT,
|
||||
IDX_COOKIE,
|
||||
IDX_FILTER_L3,
|
||||
IDX_FILTER_TCP,
|
||||
IDX_FILTER_UDP,
|
||||
@@ -1643,6 +1630,10 @@ static const struct option long_options[] = {
|
||||
[IDX_HOSTLIST_AUTO_DEBUG] = {"hostlist-auto-debug", required_argument, 0, 0},
|
||||
[IDX_NEW] = {"new", no_argument, 0, 0},
|
||||
[IDX_SKIP] = {"skip", no_argument, 0, 0},
|
||||
[IDX_NAME] = {"name", required_argument, 0, 0},
|
||||
[IDX_TEMPLATE] = {"template", optional_argument, 0, 0},
|
||||
[IDX_IMPORT] = {"import", required_argument, 0, 0},
|
||||
[IDX_COOKIE] = {"cookie", required_argument, 0, 0},
|
||||
[IDX_FILTER_L3] = {"filter-l3", required_argument, 0, 0},
|
||||
[IDX_FILTER_TCP] = {"filter-tcp", required_argument, 0, 0},
|
||||
[IDX_FILTER_UDP] = {"filter-udp", required_argument, 0, 0},
|
||||
@@ -1679,16 +1670,26 @@ static const struct option long_options[] = {
|
||||
[IDX_LAST] = {NULL, 0, NULL, 0},
|
||||
};
|
||||
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
#if defined(ZAPRET_GH_VER) || defined (ZAPRET_GH_HASH)
|
||||
#ifdef __ANDROID__
|
||||
#define MAKE_VER(s,size) snprintf(s,size,"github android version %s (%s) lua_compat_ver %u", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH), LUA_COMPAT_VER)
|
||||
#else
|
||||
#define MAKE_VER(s,size) snprintf(s,size,"github version %s (%s) lua_compat_ver %u", TOSTRING(ZAPRET_GH_VER), TOSTRING(ZAPRET_GH_HASH), LUA_COMPAT_VER)
|
||||
#endif
|
||||
#else
|
||||
#ifdef __ANDROID__
|
||||
#define MAKE_VER(s,size) snprintf(s,size,"self-built android version %s %s lua_compat_ver %u", __DATE__, __TIME__, LUA_COMPAT_VER)
|
||||
#else
|
||||
#define MAKE_VER(s,size) snprintf(s,size,"self-built version %s %s lua_compat_ver %u", __DATE__, __TIME__, LUA_COMPAT_VER)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) exithelp();
|
||||
|
||||
aes_init_keygen_tables(); // required for aes
|
||||
set_console_io_buffering();
|
||||
set_env_exedir(argv[0]);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
prepare_low_appdata();
|
||||
if (service_run(argc, argv))
|
||||
{
|
||||
// we were running as service. now exit.
|
||||
@@ -1697,7 +1698,7 @@ int main(int argc, char **argv)
|
||||
#endif
|
||||
int result, v;
|
||||
int option_index = 0;
|
||||
bool bSkip = false, bDry = false;
|
||||
bool bSkip = false, bDry = false, bTemplate;
|
||||
struct hostlist_file *anon_hl = NULL, *anon_hl_exclude = NULL;
|
||||
struct ipset_file *anon_ips = NULL, *anon_ips_exclude = NULL;
|
||||
uint64_t payload_type=0;
|
||||
@@ -1709,17 +1710,29 @@ int main(int argc, char **argv)
|
||||
unsigned int hash_wf_tcp_in = 0, hash_wf_udp_in = 0, hash_wf_tcp_out = 0, hash_wf_udp_out = 0, hash_wf_raw = 0, hash_wf_raw_part = 0, hash_ssid_filter = 0, hash_nlm_filter = 0;
|
||||
#endif
|
||||
|
||||
if (argc < 2) exithelp();
|
||||
|
||||
srandom(time(NULL));
|
||||
aes_init_keygen_tables(); // required for aes
|
||||
mask_from_preflen6_prepare();
|
||||
set_env_exedir(argv[0]);
|
||||
set_console_io_buffering();
|
||||
#ifdef __CYGWIN__
|
||||
prepare_low_appdata();
|
||||
#endif
|
||||
|
||||
PRINT_VER;
|
||||
init_params(¶ms);
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
MAKE_VER(params.verstr, sizeof(params.verstr));
|
||||
printf("%s\n\n",params.verstr);
|
||||
|
||||
ApplyDefaultBlobs(¶ms.blobs);
|
||||
|
||||
struct desync_profile_list *dpl;
|
||||
struct desync_profile *dp;
|
||||
unsigned int desync_profile_count = 0;
|
||||
unsigned int desync_profile_count = 0, desync_template_count = 0;
|
||||
|
||||
bTemplate = false;
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
@@ -1728,39 +1741,6 @@ int main(int argc, char **argv)
|
||||
dp = &dpl->dp;
|
||||
dp->n = ++desync_profile_count;
|
||||
|
||||
#ifdef __linux__
|
||||
params.qnum = -1;
|
||||
#elif defined(BSD)
|
||||
params.port = 0;
|
||||
#endif
|
||||
params.desync_fwmark = DPI_DESYNC_FWMARK_DEFAULT;
|
||||
params.ctrack_t_syn = CTRACK_T_SYN;
|
||||
params.ctrack_t_est = CTRACK_T_EST;
|
||||
params.ctrack_t_fin = CTRACK_T_FIN;
|
||||
params.ctrack_t_udp = CTRACK_T_UDP;
|
||||
params.ipcache_lifetime = IPCACHE_LIFETIME;
|
||||
params.lua_gc = LUA_GC_INTERVAL;
|
||||
|
||||
LIST_INIT(¶ms.hostlists);
|
||||
LIST_INIT(¶ms.ipsets);
|
||||
LIST_INIT(¶ms.blobs);
|
||||
LIST_INIT(¶ms.lua_init_scripts);
|
||||
|
||||
ApplyDefaultBlobs(¶ms.blobs);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
LIST_INIT(¶ms.ssid_filter);
|
||||
LIST_INIT(¶ms.nlm_filter);
|
||||
LIST_INIT(¶ms.wf_raw_part);
|
||||
#else
|
||||
if (can_drop_root())
|
||||
{
|
||||
params.uid = params.gid[0] = 0x7FFFFFFF; // default uid:gid
|
||||
params.gid_count = 1;
|
||||
params.droproot = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
||||
if (argc >= 2 && (argv[1][0] == '@' || argv[1][0] == '$'))
|
||||
{
|
||||
@@ -2120,23 +2100,83 @@ int main(int argc, char **argv)
|
||||
else
|
||||
{
|
||||
check_dp(dp);
|
||||
if (bTemplate)
|
||||
{
|
||||
if (dp->name && dp_list_search_name(¶ms.desync_templates, dp->name))
|
||||
{
|
||||
DLOG_ERR("template '%s' already present\n", dp->name);
|
||||
exit_clean(1);
|
||||
}
|
||||
dpl->dp.n = ++desync_template_count;
|
||||
dp_list_move(¶ms.desync_templates, dpl);
|
||||
}
|
||||
else
|
||||
{
|
||||
desync_profile_count++;
|
||||
}
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp = &dpl->dp;
|
||||
dp->n = ++desync_profile_count;
|
||||
dp->n = desync_profile_count;
|
||||
}
|
||||
anon_hl = anon_hl_exclude = NULL;
|
||||
anon_ips = anon_ips_exclude = NULL;
|
||||
payload_type = 0;
|
||||
range_in = PACKET_RANGE_NEVER;
|
||||
range_out = PACKET_RANGE_ALWAYS;
|
||||
|
||||
bTemplate = false;
|
||||
break;
|
||||
case IDX_SKIP:
|
||||
bSkip = true;
|
||||
break;
|
||||
case IDX_TEMPLATE:
|
||||
bTemplate = true;
|
||||
case IDX_NAME:
|
||||
if (optarg)
|
||||
{
|
||||
free(dp->name);
|
||||
if (!(dp->name = strdup(optarg)))
|
||||
{
|
||||
DLOG_ERR("out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IDX_COOKIE:
|
||||
free(dp->cookie);
|
||||
if (!(dp->cookie = strdup(optarg)))
|
||||
{
|
||||
DLOG_ERR("out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case IDX_IMPORT:
|
||||
{
|
||||
struct desync_profile_list *tpl = dp_list_search_name(¶ms.desync_templates, optarg);
|
||||
if (!tpl)
|
||||
{
|
||||
DLOG_ERR("template '%s' not found\n", optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
if (!dp_list_copy(dp, &tpl->dp))
|
||||
{
|
||||
DLOG_ERR("could not copy template\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp->n = desync_profile_count;
|
||||
free(dp->name_tpl);
|
||||
if (tpl->dp.name && !(dp->name_tpl = strdup(tpl->dp.name)))
|
||||
{
|
||||
DLOG_ERR("out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp->n_tpl = tpl->dp.n;
|
||||
}
|
||||
break;
|
||||
|
||||
case IDX_FILTER_L3:
|
||||
if (!wf_make_l3(optarg, &dp->filter_ipv4, &dp->filter_ipv6))
|
||||
@@ -2399,7 +2439,20 @@ int main(int argc, char **argv)
|
||||
desync_profile_count--;
|
||||
}
|
||||
else
|
||||
{
|
||||
check_dp(dp);
|
||||
if (bTemplate)
|
||||
{
|
||||
if (dp->name && dp_list_search_name(¶ms.desync_templates, dp->name))
|
||||
{
|
||||
DLOG_ERR("template '%s' already present\n", dp->name);
|
||||
exit_clean(1);
|
||||
}
|
||||
dpl->dp.n = ++desync_template_count;
|
||||
dp_list_move(¶ms.desync_templates, dpl);
|
||||
desync_profile_count--;
|
||||
}
|
||||
}
|
||||
|
||||
// do not need args from file anymore
|
||||
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
||||
@@ -2423,13 +2476,14 @@ int main(int argc, char **argv)
|
||||
|
||||
DLOG("adding low-priority default empty desync profile\n");
|
||||
// add default empty profile
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)) || !(dpl->dp.name=strdup("no_action")))
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
|
||||
DLOG_CONDUP("we have %d user defined desync profile(s) and default low priority profile 0\n", desync_profile_count);
|
||||
DLOG_CONDUP("we have %u user defined desync profile(s) and default low priority profile 0\n", desync_profile_count);
|
||||
DLOG_CONDUP("we have %u user defined desync template(s)\n", desync_template_count);
|
||||
|
||||
if (params.writeable_dir_enable)
|
||||
{
|
||||
@@ -2463,11 +2517,16 @@ int main(int argc, char **argv)
|
||||
if (params.droproot)
|
||||
#endif
|
||||
{
|
||||
if (dp->hostlist_auto && ensure_file_access(dp->hostlist_auto->filename))
|
||||
if (dp->hostlist_auto && !ensure_file_access(dp->hostlist_auto->filename))
|
||||
DLOG_ERR("could not make '%s' accessible. auto hostlist file may not be writable after privilege drop\n", dp->hostlist_auto->filename);
|
||||
|
||||
}
|
||||
LuaDesyncDebug(dp);
|
||||
LuaDesyncDebug(dp,"profile");
|
||||
}
|
||||
LIST_FOREACH(dpl, ¶ms.desync_templates, next)
|
||||
{
|
||||
dp = &dpl->dp;
|
||||
LuaDesyncDebug(dp,"template");
|
||||
}
|
||||
|
||||
if (!test_list_files())
|
||||
@@ -2493,6 +2552,9 @@ int main(int argc, char **argv)
|
||||
BlobDebug();
|
||||
DLOG("\n");
|
||||
|
||||
// not required anymore. free memory
|
||||
dp_list_destroy(¶ms.desync_templates);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
if (!*params.windivert_filter)
|
||||
{
|
||||
@@ -2566,7 +2628,7 @@ int main(int argc, char **argv)
|
||||
exit_clean(1);
|
||||
#endif
|
||||
print_id();
|
||||
if (!test_list_files())
|
||||
if (!test_list_files() || !lua_test_init_script_files())
|
||||
exit_clean(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -10,3 +10,6 @@
|
||||
extern bool bQuit;
|
||||
#endif
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
// when something changes that can break LUA compatibility this version should be increased
|
||||
#define LUA_COMPAT_VER 2
|
||||
|
||||
@@ -26,7 +26,7 @@ void rawpacket_queue_destroy(struct rawpacket_tailhead *q)
|
||||
while((rp = rawpacket_dequeue(q))) rawpacket_free(rp);
|
||||
}
|
||||
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload)
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_position *pos)
|
||||
{
|
||||
struct rawpacket *rp = malloc(sizeof(struct rawpacket));
|
||||
if (!rp) return NULL;
|
||||
@@ -52,6 +52,15 @@ struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sock
|
||||
memcpy(rp->packet,data,len);
|
||||
rp->len=len;
|
||||
rp->len_payload=len_payload;
|
||||
|
||||
// make a copy for replay
|
||||
if (pos)
|
||||
{
|
||||
rp->pos = *pos;
|
||||
rp->pos_present = true;
|
||||
}
|
||||
else
|
||||
rp->pos_present = false;
|
||||
|
||||
TAILQ_INSERT_TAIL(q, rp, next);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <net/if.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "conntrack_base.h"
|
||||
|
||||
struct rawpacket
|
||||
{
|
||||
struct sockaddr_storage dst;
|
||||
@@ -14,6 +16,8 @@ struct rawpacket
|
||||
uint32_t fwmark;
|
||||
size_t len, len_payload;
|
||||
uint8_t *packet;
|
||||
t_ctrack_position pos;
|
||||
bool pos_present;
|
||||
TAILQ_ENTRY(rawpacket) next;
|
||||
};
|
||||
TAILQ_HEAD(rawpacket_tailhead, rawpacket);
|
||||
@@ -22,6 +26,6 @@ void rawpacket_queue_init(struct rawpacket_tailhead *q);
|
||||
void rawpacket_queue_destroy(struct rawpacket_tailhead *q);
|
||||
bool rawpacket_queue_empty(const struct rawpacket_tailhead *q);
|
||||
unsigned int rawpacket_queue_count(const struct rawpacket_tailhead *q);
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload);
|
||||
struct rawpacket *rawpacket_queue(struct rawpacket_tailhead *q,const struct sockaddr_storage* dst,uint32_t fwmark_orig,uint32_t fwmark,const char *ifin,const char *ifout,const void *data,size_t len,size_t len_payload,const t_ctrack_position *pos);
|
||||
struct rawpacket *rawpacket_dequeue(struct rawpacket_tailhead *q);
|
||||
void rawpacket_free(struct rawpacket *rp);
|
||||
|
||||
131
nfq2/params.c
131
nfq2/params.c
@@ -322,7 +322,7 @@ void hexdump_limited_dlog(const uint8_t *data, size_t size, size_t limit)
|
||||
}
|
||||
}
|
||||
|
||||
void dp_init(struct desync_profile *dp)
|
||||
void dp_init_dynamic(struct desync_profile *dp)
|
||||
{
|
||||
LIST_INIT(&dp->hl_collection);
|
||||
LIST_INIT(&dp->hl_collection_exclude);
|
||||
@@ -331,33 +331,25 @@ void dp_init(struct desync_profile *dp)
|
||||
LIST_INIT(&dp->pf_tcp);
|
||||
LIST_INIT(&dp->pf_udp);
|
||||
LIST_INIT(&dp->lua_desync);
|
||||
#ifdef HAS_FILTER_SSID
|
||||
LIST_INIT(&dp->filter_ssid);
|
||||
#endif
|
||||
}
|
||||
void dp_init(struct desync_profile *dp)
|
||||
{
|
||||
dp_init_dynamic(dp);
|
||||
|
||||
dp->hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
||||
dp->hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
dp->hostlist_auto_retrans_threshold = HOSTLIST_AUTO_RETRANS_THRESHOLD_DEFAULT;
|
||||
dp->filter_ipv4 = dp->filter_ipv6 = true;
|
||||
}
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
||||
{
|
||||
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
|
||||
if (!entry) return NULL;
|
||||
|
||||
dp_init(&entry->dp);
|
||||
|
||||
// add to the tail
|
||||
struct desync_profile_list *dpn,*dpl=LIST_FIRST(¶ms.desync_profiles);
|
||||
if (dpl)
|
||||
{
|
||||
while ((dpn=LIST_NEXT(dpl,next))) dpl = dpn;
|
||||
LIST_INSERT_AFTER(dpl, entry, next);
|
||||
}
|
||||
else
|
||||
LIST_INSERT_HEAD(¶ms.desync_profiles, entry, next);
|
||||
|
||||
return entry;
|
||||
}
|
||||
static void dp_clear_dynamic(struct desync_profile *dp)
|
||||
{
|
||||
free(dp->name);
|
||||
free(dp->name_tpl);
|
||||
free(dp->cookie);
|
||||
|
||||
hostlist_collection_destroy(&dp->hl_collection);
|
||||
hostlist_collection_destroy(&dp->hl_collection_exclude);
|
||||
ipset_collection_destroy(&dp->ips_collection);
|
||||
@@ -389,6 +381,67 @@ void dp_list_destroy(struct desync_profile_list_head *head)
|
||||
dp_entry_destroy(entry);
|
||||
}
|
||||
}
|
||||
|
||||
static struct desync_profile_list *desync_profile_entry_alloc()
|
||||
{
|
||||
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
|
||||
if (entry) dp_init(&entry->dp);
|
||||
return entry;
|
||||
}
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
||||
{
|
||||
struct desync_profile_list *entry = desync_profile_entry_alloc();
|
||||
if (!entry) return false;
|
||||
|
||||
struct desync_profile_list *tail, *item;
|
||||
LIST_TAIL(head, tail, item);
|
||||
LIST_INSERT_TAIL(head, tail, entry, next);
|
||||
|
||||
return entry;
|
||||
}
|
||||
bool dp_list_copy(struct desync_profile *to, const struct desync_profile *from)
|
||||
{
|
||||
// clear everything in target
|
||||
dp_clear(to);
|
||||
// first copy all simple type values
|
||||
*to = *from;
|
||||
// prepare empty dynamic structures
|
||||
dp_init_dynamic(to);
|
||||
// copy dynamic structures
|
||||
if (from->name && !(to->name = strdup(from->name))) return false;
|
||||
if (from->name_tpl && !(to->name_tpl = strdup(from->name_tpl))) return false;
|
||||
if (from->cookie && !(to->cookie = strdup(from->cookie))) return false;
|
||||
if (
|
||||
#ifdef HAS_FILTER_SSID
|
||||
!strlist_copy(&to->filter_ssid, &from->filter_ssid) ||
|
||||
#endif
|
||||
!funclist_copy(&to->lua_desync, &from->lua_desync) ||
|
||||
!ipset_collection_copy(&to->ips_collection, &from->ips_collection) ||
|
||||
!ipset_collection_copy(&to->ips_collection_exclude, &from->ips_collection_exclude) ||
|
||||
!hostlist_collection_copy(&to->hl_collection, &from->hl_collection) ||
|
||||
!hostlist_collection_copy(&to->hl_collection_exclude, &from->hl_collection_exclude))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void dp_list_move(struct desync_profile_list_head *target, struct desync_profile_list *dpl)
|
||||
{
|
||||
struct desync_profile_list *tail, *item;
|
||||
LIST_TAIL(target, tail, item);
|
||||
LIST_REMOVE(dpl, next);
|
||||
LIST_INSERT_TAIL(target, tail, dpl, next);
|
||||
}
|
||||
struct desync_profile_list *dp_list_search_name(struct desync_profile_list_head *head, const char *name)
|
||||
{
|
||||
struct desync_profile_list *dpl;
|
||||
if (name)
|
||||
LIST_FOREACH(dpl, head, next)
|
||||
if (dpl->dp.name && !strcmp(dpl->dp.name, name))
|
||||
return dpl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
|
||||
{
|
||||
struct desync_profile_list *dpl;
|
||||
@@ -427,6 +480,7 @@ void cleanup_params(struct params_s *params)
|
||||
|
||||
ConntrackPoolDestroy(¶ms->conntrack);
|
||||
dp_list_destroy(¶ms->desync_profiles);
|
||||
dp_list_destroy(¶ms->desync_templates);
|
||||
hostlist_files_destroy(¶ms->hostlists);
|
||||
ipset_files_destroy(¶ms->ipsets);
|
||||
ipcacheDestroy(¶ms->ipcache);
|
||||
@@ -440,3 +494,40 @@ void cleanup_params(struct params_s *params)
|
||||
free(params->user); params->user=NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void init_params(struct params_s *params)
|
||||
{
|
||||
memset(params, 0, sizeof(*params));
|
||||
|
||||
#ifdef __linux__
|
||||
params->qnum = -1;
|
||||
#elif defined(BSD)
|
||||
params->port = 0;
|
||||
#endif
|
||||
params->desync_fwmark = DPI_DESYNC_FWMARK_DEFAULT;
|
||||
params->ctrack_t_syn = CTRACK_T_SYN;
|
||||
params->ctrack_t_est = CTRACK_T_EST;
|
||||
params->ctrack_t_fin = CTRACK_T_FIN;
|
||||
params->ctrack_t_udp = CTRACK_T_UDP;
|
||||
params->ipcache_lifetime = IPCACHE_LIFETIME;
|
||||
params->lua_gc = LUA_GC_INTERVAL;
|
||||
|
||||
LIST_INIT(¶ms->hostlists);
|
||||
LIST_INIT(¶ms->ipsets);
|
||||
LIST_INIT(¶ms->blobs);
|
||||
LIST_INIT(¶ms->lua_init_scripts);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
LIST_INIT(¶ms->ssid_filter);
|
||||
LIST_INIT(¶ms->nlm_filter);
|
||||
LIST_INIT(¶ms->wf_raw_part);
|
||||
#else
|
||||
if (can_drop_root())
|
||||
{
|
||||
params->uid = params->gid[0] = 0x7FFFFFFF; // default uid:gid
|
||||
params->gid_count = 1;
|
||||
params->droproot = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "desync.h"
|
||||
#include "protocol.h"
|
||||
#include "helpers.h"
|
||||
#include "sec.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
@@ -53,6 +54,10 @@ enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG, LOG_
|
||||
struct desync_profile
|
||||
{
|
||||
unsigned int n; // number of the profile
|
||||
char *name; // optional malloced name string
|
||||
unsigned int n_tpl; // number of imported template
|
||||
char *name_tpl; // imported template name
|
||||
char *cookie; // optional malloced string
|
||||
|
||||
bool filter_ipv4,filter_ipv6;
|
||||
struct port_filters_head pf_tcp,pf_udp;
|
||||
@@ -78,6 +83,7 @@ struct desync_profile
|
||||
|
||||
struct func_list_head lua_desync;
|
||||
};
|
||||
#define PROFILE_NAME(dp) ((dp)->name ? (dp)->name : "noname")
|
||||
|
||||
#define PROFILE_IPSETS_ABSENT(dp) (!LIST_FIRST(&(dp)->ips_collection) && !LIST_FIRST(&(dp)->ips_collection_exclude))
|
||||
#define PROFILE_IPSETS_EMPTY(dp) (ipset_collection_is_empty(&(dp)->ips_collection) && ipset_collection_is_empty(&(dp)->ips_collection_exclude))
|
||||
@@ -89,6 +95,9 @@ struct desync_profile_list {
|
||||
};
|
||||
LIST_HEAD(desync_profile_list_head, desync_profile_list);
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
||||
void dp_list_move(struct desync_profile_list_head *target, struct desync_profile_list *dpl);
|
||||
bool dp_list_copy(struct desync_profile *to, const struct desync_profile *from);
|
||||
struct desync_profile_list *dp_list_search_name(struct desync_profile_list_head *head, const char *name);
|
||||
void dp_entry_destroy(struct desync_profile_list *entry);
|
||||
void dp_list_destroy(struct desync_profile_list_head *head);
|
||||
bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
|
||||
@@ -104,6 +113,7 @@ struct params_s
|
||||
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
||||
wordexp_t wexp; // for file based config
|
||||
#endif
|
||||
char verstr[128];
|
||||
|
||||
enum log_target debug_target;
|
||||
char debug_logfile[PATH_MAX];
|
||||
@@ -119,7 +129,7 @@ struct params_s
|
||||
bool bind_fix4,bind_fix6;
|
||||
uint32_t desync_fwmark; // unused in BSD
|
||||
|
||||
struct desync_profile_list_head desync_profiles;
|
||||
struct desync_profile_list_head desync_profiles, desync_templates;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
struct str_list_head ssid_filter,nlm_filter;
|
||||
@@ -170,6 +180,8 @@ struct params_s
|
||||
|
||||
extern struct params_s params;
|
||||
extern const char *progname;
|
||||
|
||||
void init_params(struct params_s *params);
|
||||
#if !defined( __OpenBSD__) && !defined(__ANDROID__)
|
||||
void cleanup_args(struct params_s *params);
|
||||
#endif
|
||||
|
||||
237
nfq2/pools.c
237
nfq2/pools.c
@@ -155,20 +155,33 @@ bool strlist_add(struct str_list_head *head, const char *str)
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
return true;
|
||||
}
|
||||
static struct str_list *strlist_entry_copy(const struct str_list *entry)
|
||||
{
|
||||
return strlist_entry_alloc(entry->str);
|
||||
}
|
||||
bool strlist_copy(struct str_list_head *to, const struct str_list_head *from)
|
||||
{
|
||||
struct str_list *tail, *item, *entry;
|
||||
|
||||
LIST_TAIL(to, tail, item);
|
||||
LIST_FOREACH(item, from, next)
|
||||
{
|
||||
if (!(entry = strlist_entry_copy(item))) return false;
|
||||
LIST_INSERT_TAIL(to, tail, entry, next);
|
||||
tail = tail ? LIST_NEXT(tail, next) : LIST_FIRST(to);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool strlist_add_tail(struct str_list_head *head, const char *str)
|
||||
{
|
||||
struct str_list *entry = strlist_entry_alloc(str);
|
||||
if (!entry) return false;
|
||||
|
||||
// add to the tail
|
||||
struct str_list *strn,*strl=LIST_FIRST(head);
|
||||
if (strl)
|
||||
{
|
||||
while ((strn=LIST_NEXT(strl,next))) strl = strn;
|
||||
LIST_INSERT_AFTER(strl, entry, next);
|
||||
}
|
||||
else
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
struct str_list *tail, *item;
|
||||
LIST_TAIL(head, tail, item);
|
||||
LIST_INSERT_TAIL(head, tail, entry, next);
|
||||
|
||||
return true;
|
||||
}
|
||||
static void strlist_entry_destroy(struct str_list *entry)
|
||||
@@ -200,35 +213,77 @@ bool strlist_search(const struct str_list_head *head, const char *str)
|
||||
}
|
||||
|
||||
|
||||
static struct ptr_list *ptrlist_entry_alloc()
|
||||
static void str2list_entry_destroy(struct str2_list *entry)
|
||||
{
|
||||
return (struct ptr_list*)calloc(1,sizeof(struct ptr_list));
|
||||
free(entry->str1);
|
||||
free(entry->str2);
|
||||
free(entry);
|
||||
}
|
||||
void str2list_destroy(struct str2_list_head *head)
|
||||
{
|
||||
struct str2_list *entry;
|
||||
while ((entry = LIST_FIRST(head)))
|
||||
{
|
||||
LIST_REMOVE(entry, next);
|
||||
str2list_entry_destroy(entry);
|
||||
}
|
||||
}
|
||||
static struct str2_list *str2list_entry_alloc()
|
||||
{
|
||||
return (struct str2_list*)calloc(1,sizeof(struct str2_list));
|
||||
}
|
||||
|
||||
struct ptr_list *ptrlist_add(struct ptr_list_head *head)
|
||||
struct str2_list *str2list_add(struct str2_list_head *head)
|
||||
{
|
||||
struct ptr_list *entry = ptrlist_entry_alloc();
|
||||
struct str2_list *entry = str2list_entry_alloc();
|
||||
if (!entry) return NULL;
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
return entry;
|
||||
}
|
||||
static void ptrlist_entry_destroy(struct ptr_list *entry)
|
||||
static struct str2_list *str2list_entry_copy(const struct str2_list *entry)
|
||||
{
|
||||
free(entry->ptr1);
|
||||
free(entry->ptr2);
|
||||
struct str2_list *e2 = str2list_entry_alloc();
|
||||
if (!e2) return NULL;
|
||||
e2->str1 = strdup(entry->str1);
|
||||
e2->str2 = strdup(entry->str2);
|
||||
if (!e2->str1 || !e2->str2)
|
||||
{
|
||||
str2list_entry_destroy(e2);
|
||||
return false;
|
||||
}
|
||||
return e2;
|
||||
}
|
||||
bool str2list_copy(struct str2_list_head *to, const struct str2_list_head *from)
|
||||
{
|
||||
struct str2_list *tail, *item, *entry;
|
||||
|
||||
LIST_TAIL(to, tail, item);
|
||||
LIST_FOREACH(item, from, next)
|
||||
{
|
||||
if (!(entry = str2list_entry_copy(item))) return false;
|
||||
LIST_INSERT_TAIL(to, tail, entry, next);
|
||||
tail = tail ? LIST_NEXT(tail, next) : LIST_FIRST(to);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void funclist_entry_destroy(struct func_list *entry)
|
||||
{
|
||||
free(entry->func);
|
||||
str2list_destroy(&entry->args);
|
||||
free(entry);
|
||||
}
|
||||
void ptrlist_destroy(struct ptr_list_head *head)
|
||||
void funclist_destroy(struct func_list_head *head)
|
||||
{
|
||||
struct ptr_list *entry;
|
||||
struct func_list *entry;
|
||||
while ((entry = LIST_FIRST(head)))
|
||||
{
|
||||
LIST_REMOVE(entry, next);
|
||||
ptrlist_entry_destroy(entry);
|
||||
funclist_entry_destroy(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct func_list *funclist_entry_alloc(const char *func)
|
||||
{
|
||||
struct func_list *entry = malloc(sizeof(struct func_list));
|
||||
@@ -250,31 +305,38 @@ struct func_list *funclist_add_tail(struct func_list_head *head, const char *fun
|
||||
struct func_list *entry = funclist_entry_alloc(func);
|
||||
if (!entry) return NULL;
|
||||
|
||||
// add to the tail
|
||||
struct func_list *funcn,*funcl=LIST_FIRST(head);
|
||||
if (funcl)
|
||||
{
|
||||
while ((funcn=LIST_NEXT(funcl,next))) funcl = funcn;
|
||||
LIST_INSERT_AFTER(funcl, entry, next);
|
||||
}
|
||||
else
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
struct func_list *tail, *item;
|
||||
LIST_TAIL(head, tail, item);
|
||||
LIST_INSERT_TAIL(head, tail, entry, next);
|
||||
|
||||
return entry;
|
||||
}
|
||||
static void funclist_entry_destroy(struct func_list *entry)
|
||||
static struct func_list *funclist_entry_copy(const struct func_list *entry)
|
||||
{
|
||||
free(entry->func);
|
||||
ptrlist_destroy(&entry->args);
|
||||
free(entry);
|
||||
}
|
||||
void funclist_destroy(struct func_list_head *head)
|
||||
{
|
||||
struct func_list *entry;
|
||||
while ((entry = LIST_FIRST(head)))
|
||||
struct func_list *e2 = funclist_entry_alloc(entry->func);
|
||||
if (!e2) return NULL;
|
||||
e2->payload_type = entry->payload_type;
|
||||
e2->range_in = entry->range_in;
|
||||
e2->range_out = entry->range_out;
|
||||
if (!str2list_copy(&e2->args, &entry->args))
|
||||
{
|
||||
LIST_REMOVE(entry, next);
|
||||
funclist_entry_destroy(entry);
|
||||
funclist_entry_destroy(e2);
|
||||
return false;
|
||||
}
|
||||
return e2;
|
||||
}
|
||||
bool funclist_copy(struct func_list_head *to, const struct func_list_head *from)
|
||||
{
|
||||
struct func_list *tail, *item, *entry;
|
||||
|
||||
LIST_TAIL(to, tail, item);
|
||||
LIST_FOREACH(item, from, next)
|
||||
{
|
||||
if (!(entry = funclist_entry_copy(item))) return false;
|
||||
LIST_INSERT_TAIL(to, tail, entry, next);
|
||||
tail = tail ? LIST_NEXT(tail, next) : LIST_FIRST(to);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -333,16 +395,36 @@ void hostlist_files_reset_modtime(struct hostlist_files_head *list)
|
||||
FILE_MOD_RESET(&hfile->mod_sig);
|
||||
}
|
||||
|
||||
struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile)
|
||||
static struct hostlist_item *hostlist_collection_entry_alloc(struct hostlist_file *hfile)
|
||||
{
|
||||
struct hostlist_item *entry = malloc(sizeof(struct hostlist_item));
|
||||
if (entry)
|
||||
{
|
||||
entry->hfile = hfile;
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
}
|
||||
if (entry) entry->hfile = hfile;
|
||||
return entry;
|
||||
}
|
||||
struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile)
|
||||
{
|
||||
struct hostlist_item *entry = hostlist_collection_entry_alloc(hfile);
|
||||
if (entry) LIST_INSERT_HEAD(head, entry, next);
|
||||
return entry;
|
||||
}
|
||||
static struct hostlist_item *hostlist_collection_entry_copy(const struct hostlist_item *entry)
|
||||
{
|
||||
return hostlist_collection_entry_alloc(entry->hfile);
|
||||
}
|
||||
bool hostlist_collection_copy(struct hostlist_collection_head *to, const struct hostlist_collection_head *from)
|
||||
{
|
||||
struct hostlist_item *tail, *item, *entry;
|
||||
|
||||
LIST_TAIL(to, tail, item);
|
||||
LIST_FOREACH(item, from, next)
|
||||
{
|
||||
if (!(entry = hostlist_collection_entry_copy(item))) return false;
|
||||
LIST_INSERT_TAIL(to, tail, entry, next);
|
||||
tail = tail ? LIST_NEXT(tail, next) : LIST_FIRST(to);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void hostlist_collection_destroy(struct hostlist_collection_head *head)
|
||||
{
|
||||
struct hostlist_item *entry;
|
||||
@@ -579,16 +661,36 @@ void ipset_files_reset_modtime(struct ipset_files_head *list)
|
||||
FILE_MOD_RESET(&hfile->mod_sig);
|
||||
}
|
||||
|
||||
struct ipset_item *ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile)
|
||||
static struct ipset_item *ipset_collection_entry_alloc(struct ipset_file *hfile)
|
||||
{
|
||||
struct ipset_item *entry = malloc(sizeof(struct ipset_item));
|
||||
if (entry)
|
||||
{
|
||||
entry->hfile = hfile;
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
}
|
||||
if (entry) entry->hfile = hfile;
|
||||
return entry;
|
||||
}
|
||||
struct ipset_item *ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile)
|
||||
{
|
||||
struct ipset_item *entry = ipset_collection_entry_alloc(hfile);
|
||||
if (entry) LIST_INSERT_HEAD(head, entry, next);
|
||||
return entry;
|
||||
}
|
||||
static struct ipset_item *ipset_collection_entry_copy(const struct ipset_item *entry)
|
||||
{
|
||||
return ipset_collection_entry_alloc(entry->hfile);
|
||||
}
|
||||
bool ipset_collection_copy(struct ipset_collection_head *to, const struct ipset_collection_head *from)
|
||||
{
|
||||
struct ipset_item *tail, *item, *entry;
|
||||
|
||||
LIST_TAIL(to, tail, item);
|
||||
LIST_FOREACH(item, from, next)
|
||||
{
|
||||
if (!(entry = ipset_collection_entry_copy(item))) return false;
|
||||
LIST_INSERT_TAIL(to, tail, entry, next);
|
||||
tail = tail ? LIST_NEXT(tail, next) : LIST_FIRST(to);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ipset_collection_destroy(struct ipset_collection_head *head)
|
||||
{
|
||||
struct ipset_item *entry;
|
||||
@@ -645,7 +747,7 @@ bool port_filters_in_range(const struct port_filters_head *head, uint16_t port)
|
||||
{
|
||||
const struct port_filter_item *item;
|
||||
|
||||
if (!LIST_FIRST(head)) return true;
|
||||
if (LIST_EMPTY(head)) return true;
|
||||
LIST_FOREACH(item, head, next)
|
||||
{
|
||||
if (pf_in_range(port, &item->pf))
|
||||
@@ -656,7 +758,7 @@ bool port_filters_in_range(const struct port_filters_head *head, uint16_t port)
|
||||
bool port_filters_deny_if_empty(struct port_filters_head *head)
|
||||
{
|
||||
port_filter pf;
|
||||
if (LIST_FIRST(head)) return true;
|
||||
if (!LIST_EMPTY(head)) return true;
|
||||
return pf_parse("0",&pf) && port_filter_add(head,&pf);
|
||||
}
|
||||
|
||||
@@ -667,15 +769,9 @@ struct blob_item *blob_collection_add(struct blob_collection_head *head)
|
||||
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
|
||||
if (entry)
|
||||
{
|
||||
// insert to the end
|
||||
struct blob_item *itemc,*iteml=LIST_FIRST(head);
|
||||
if (iteml)
|
||||
{
|
||||
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
|
||||
LIST_INSERT_AFTER(iteml, entry, next);
|
||||
}
|
||||
else
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
struct blob_item *tail, *item;
|
||||
LIST_TAIL(head, tail, item);
|
||||
LIST_INSERT_TAIL(head, tail, entry, next);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
@@ -693,14 +789,9 @@ struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, co
|
||||
entry->size_buf = size+size_reserve;
|
||||
|
||||
// insert to the end
|
||||
struct blob_item *itemc,*iteml=LIST_FIRST(head);
|
||||
if (iteml)
|
||||
{
|
||||
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
|
||||
LIST_INSERT_AFTER(iteml, entry, next);
|
||||
}
|
||||
else
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
struct blob_item *tail, *item;
|
||||
LIST_TAIL(head, tail, item);
|
||||
LIST_INSERT_TAIL(head, tail, entry, next);
|
||||
|
||||
return entry;
|
||||
}
|
||||
@@ -725,7 +816,7 @@ void blob_collection_destroy(struct blob_collection_head *head)
|
||||
}
|
||||
bool blob_collection_empty(const struct blob_collection_head *head)
|
||||
{
|
||||
return !LIST_FIRST(head);
|
||||
return LIST_EMPTY(head);
|
||||
}
|
||||
struct blob_item *blob_collection_search_name(struct blob_collection_head *head, const char *name)
|
||||
{
|
||||
|
||||
30
nfq2/pools.h
30
nfq2/pools.h
@@ -17,6 +17,17 @@
|
||||
|
||||
#define HOSTLIST_POOL_FLAG_STRICT_MATCH 1
|
||||
|
||||
#define LIST_TAIL(head, tail, temp) {\
|
||||
tail=LIST_FIRST(head); \
|
||||
if (tail) while ((temp=LIST_NEXT(tail,next))) tail = temp; }
|
||||
|
||||
#define LIST_INSERT_TAIL(head, tail, elm, field) { \
|
||||
if (LIST_FIRST(head)) \
|
||||
LIST_INSERT_AFTER(tail, elm, field); \
|
||||
else \
|
||||
LIST_INSERT_HEAD(head, elm, field); }
|
||||
|
||||
|
||||
typedef struct hostlist_pool {
|
||||
char *str; /* key */
|
||||
uint32_t flags; /* custom data */
|
||||
@@ -38,25 +49,28 @@ bool strlist_add(struct str_list_head *head, const char *str);
|
||||
bool strlist_add_tail(struct str_list_head *head, const char *str);
|
||||
void strlist_destroy(struct str_list_head *head);
|
||||
bool strlist_search(const struct str_list_head *head, const char *str);
|
||||
bool strlist_copy(struct str_list_head *to, const struct str_list_head *from);
|
||||
|
||||
struct ptr_list {
|
||||
void *ptr1,*ptr2;
|
||||
LIST_ENTRY(ptr_list) next;
|
||||
struct str2_list {
|
||||
char *str1,*str2;
|
||||
LIST_ENTRY(str2_list) next;
|
||||
};
|
||||
LIST_HEAD(ptr_list_head, ptr_list);
|
||||
LIST_HEAD(str2_list_head, str2_list);
|
||||
|
||||
struct ptr_list *ptrlist_add(struct ptr_list_head *head);
|
||||
void ptrlist_destroy(struct ptr_list_head *head);
|
||||
struct str2_list *str2list_add(struct str2_list_head *head);
|
||||
bool str2list_copy(struct str2_list_head *to, const struct str2_list_head *from);
|
||||
void str2list_destroy(struct str2_list_head *head);
|
||||
|
||||
struct func_list {
|
||||
char *func;
|
||||
uint64_t payload_type;
|
||||
struct packet_range range_in, range_out;
|
||||
struct ptr_list_head args;
|
||||
struct str2_list_head args;
|
||||
LIST_ENTRY(func_list) next;
|
||||
};
|
||||
LIST_HEAD(func_list_head, func_list);
|
||||
struct func_list *funclist_add_tail(struct func_list_head *head, const char *func);
|
||||
bool funclist_copy(struct func_list_head *to, const struct func_list_head *from);
|
||||
void funclist_destroy(struct func_list_head *head);
|
||||
|
||||
|
||||
@@ -96,6 +110,7 @@ struct hostlist_item {
|
||||
LIST_HEAD(hostlist_collection_head, hostlist_item);
|
||||
struct hostlist_item *hostlist_collection_add(struct hostlist_collection_head *head, struct hostlist_file *hfile);
|
||||
void hostlist_collection_destroy(struct hostlist_collection_head *head);
|
||||
bool hostlist_collection_copy(struct hostlist_collection_head *to, const struct hostlist_collection_head *from);
|
||||
struct hostlist_item *hostlist_collection_search(struct hostlist_collection_head *head, const char *filename);
|
||||
bool hostlist_collection_is_empty(const struct hostlist_collection_head *head);
|
||||
|
||||
@@ -158,6 +173,7 @@ struct ipset_item {
|
||||
};
|
||||
LIST_HEAD(ipset_collection_head, ipset_item);
|
||||
struct ipset_item * ipset_collection_add(struct ipset_collection_head *head, struct ipset_file *hfile);
|
||||
bool ipset_collection_copy(struct ipset_collection_head *to, const struct ipset_collection_head *from);
|
||||
void ipset_collection_destroy(struct ipset_collection_head *head);
|
||||
struct ipset_item *ipset_collection_search(struct ipset_collection_head *head, const char *filename);
|
||||
bool ipset_collection_is_empty(const struct ipset_collection_head *head);
|
||||
|
||||
@@ -48,7 +48,7 @@ bool l7_proto_match(t_l7proto l7proto, uint64_t filter_l7)
|
||||
static const char *l7payload_name[] = {
|
||||
"all","unknown","empty","known","http_req","http_reply","tls_client_hello","tls_server_hello","quic_initial",
|
||||
"wireguard_initiation","wireguard_response","wireguard_cookie","wireguard_keepalive","wireguard_data",
|
||||
"dht","discord_ip_discovery","stun_binding_req",
|
||||
"dht","discord_ip_discovery","stun",
|
||||
"xmpp_stream", "xmpp_starttls", "xmpp_proceed", "xmpp_features",
|
||||
"dns_query", "dns_response",
|
||||
"mtproto_initial"};
|
||||
@@ -66,6 +66,35 @@ bool l7_payload_match(t_l7payload l7payload, uint64_t filter_l7p)
|
||||
{
|
||||
return filter_l7p==L7P_ALL || (filter_l7p & (1<<l7payload)) || (filter_l7p & (1<<L7P_KNOWN)) && l7payload>L7P_KNOWN && l7payload<L7P_LAST;
|
||||
}
|
||||
bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size)
|
||||
{
|
||||
char *p;
|
||||
const char *pstr;
|
||||
size_t lstr;
|
||||
t_l7payload pl;
|
||||
|
||||
if (!size) return false;
|
||||
if (l7p==L7P_ALL)
|
||||
{
|
||||
if (size<4) return false;
|
||||
memcpy(buf,"all",4);
|
||||
return true;
|
||||
}
|
||||
for(pl=0, p=buf, *buf=0 ; pl<L7P_LAST ; pl++)
|
||||
{
|
||||
if (l7p & (1<<pl))
|
||||
{
|
||||
pstr = l7payload_str(pl);
|
||||
lstr = strlen(pstr);
|
||||
if (size < ((p!=buf) + lstr + 1)) return false;
|
||||
if (p!=buf) *p++=','; // not first
|
||||
memcpy(p,pstr,lstr);
|
||||
p[lstr]=0;
|
||||
p+=lstr;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static const char *posmarker_names[] = {"abs","host","endhost","sld","midsld","endsld","method","extlen","sniext"};
|
||||
@@ -1380,11 +1409,11 @@ bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len)
|
||||
!memcmp(data+8,"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",64);
|
||||
// address is not set in request
|
||||
}
|
||||
bool IsStunBindingRequest(const uint8_t *data, size_t len)
|
||||
bool IsStunMessage(const uint8_t *data, size_t len)
|
||||
{
|
||||
return len>=20 && // header size
|
||||
data[0]==0 && data[1]==1 &&
|
||||
(data[3]&0b11)==0 && // length must be a multiple of 4
|
||||
(data[0]&0xC0)==0 && // 2 most significant bits must be zeroes
|
||||
(data[3]&3)==0 && // length must be a multiple of 4
|
||||
ntohl(*(uint32_t*)(&data[4]))==0x2112A442 && // magic cookie
|
||||
ntohs(*(uint16_t*)(&data[2]))==len-20;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ typedef enum {
|
||||
L7P_WIREGUARD_DATA,
|
||||
L7P_DHT,
|
||||
L7P_DISCORD_IP_DISCOVERY,
|
||||
L7P_STUN_BINDING_REQ,
|
||||
L7P_STUN,
|
||||
L7P_XMPP_STREAM,
|
||||
L7P_XMPP_STARTTLS,
|
||||
L7P_XMPP_PROCEED,
|
||||
@@ -55,6 +55,7 @@ typedef enum {
|
||||
t_l7payload l7payload_from_name(const char *name);
|
||||
const char *l7payload_str(t_l7payload l7);
|
||||
bool l7_payload_match(t_l7payload l7payload, uint64_t filter_l7p);
|
||||
bool l7_payload_str_list(uint64_t l7p, char *buf, size_t size);
|
||||
|
||||
typedef enum {
|
||||
PM_ABS=0,
|
||||
@@ -152,7 +153,7 @@ bool IsWireguardKeepalive(const uint8_t *data, size_t len);
|
||||
bool IsWireguardData(const uint8_t *data, size_t len);
|
||||
bool IsDht(const uint8_t *data, size_t len);
|
||||
bool IsDiscordIpDiscoveryRequest(const uint8_t *data, size_t len);
|
||||
bool IsStunBindingRequest(const uint8_t *data, size_t len);
|
||||
bool IsStunMessage(const uint8_t *data, size_t len);
|
||||
bool IsMTProto(const uint8_t *data, size_t len);
|
||||
|
||||
#define QUIC_MAX_CID_LENGTH 20
|
||||
|
||||
99
uninstall_easy.sh
Executable file
99
uninstall_easy.sh
Executable file
@@ -0,0 +1,99 @@
|
||||
#!/bin/sh
|
||||
|
||||
# automated script for easy uninstalling zapret
|
||||
|
||||
EXEDIR="$(dirname "$0")"
|
||||
EXEDIR="$(cd "$EXEDIR"; pwd)"
|
||||
ZAPRET_BASE=${ZAPRET_BASE:-"$EXEDIR"}
|
||||
ZAPRET_RW=${ZAPRET_RW:-"$ZAPRET_BASE"}
|
||||
ZAPRET_CONFIG=${ZAPRET_CONFIG:-"$ZAPRET_RW/config"}
|
||||
ZAPRET_CONFIG_DEFAULT="$ZAPRET_BASE/config.default"
|
||||
IPSET_DIR="$ZAPRET_BASE/ipset"
|
||||
|
||||
[ -f "$ZAPRET_CONFIG" ] || {
|
||||
ZAPRET_CONFIG_DIR="$(dirname "$ZAPRET_CONFIG")"
|
||||
[ -d "$ZAPRET_CONFIG_DIR" ] || mkdir -p "$ZAPRET_CONFIG_DIR"
|
||||
cp "$ZAPRET_CONFIG_DEFAULT" "$ZAPRET_CONFIG"
|
||||
}
|
||||
|
||||
. "$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/nft.sh"
|
||||
. "$ZAPRET_BASE/common/installer.sh"
|
||||
|
||||
remove_systemd()
|
||||
{
|
||||
clear_ipset
|
||||
service_stop_systemd
|
||||
service_remove_systemd
|
||||
timer_remove_systemd
|
||||
nft_del_table
|
||||
crontab_del
|
||||
}
|
||||
|
||||
remove_openrc()
|
||||
{
|
||||
clear_ipset
|
||||
service_remove_openrc
|
||||
nft_del_table
|
||||
crontab_del
|
||||
}
|
||||
|
||||
remove_linux()
|
||||
{
|
||||
INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret2"
|
||||
|
||||
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'
|
||||
}
|
||||
|
||||
remove_openwrt()
|
||||
{
|
||||
OPENWRT_FW_INCLUDE=/etc/firewall.zapret2
|
||||
|
||||
clear_ipset
|
||||
service_remove_sysv
|
||||
remove_openwrt_firewall
|
||||
remove_openwrt_iface_hook
|
||||
nft_del_table
|
||||
restart_openwrt_firewall
|
||||
crontab_del
|
||||
remove_extra_pkgs_openwrt
|
||||
echo
|
||||
echo to fully remove zapret : rm -r \"$ZAPRET_BASE\"
|
||||
}
|
||||
|
||||
fix_sbin_path
|
||||
check_system
|
||||
require_root
|
||||
|
||||
case $SYSTEM in
|
||||
systemd)
|
||||
remove_systemd
|
||||
;;
|
||||
openrc)
|
||||
remove_openrc
|
||||
;;
|
||||
linux)
|
||||
remove_linux
|
||||
;;
|
||||
openwrt)
|
||||
remove_openwrt
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
exitp 0
|
||||
Reference in New Issue
Block a user