nftables support

This commit is contained in:
bol-van
2022-02-15 17:15:36 +03:00
parent b7aa3a878c
commit 95667733a6
35 changed files with 3099 additions and 2000 deletions

135
common/base.sh Normal file
View File

@@ -0,0 +1,135 @@
exists()
{
which "$1" >/dev/null 2>/dev/null
}
existf()
{
type "$1" >/dev/null 2>/dev/null
}
whichq()
{
which $1 2>/dev/null
}
exist_all()
{
while [ -n "$1" ]; do
exists "$1" || return 1
shift
done
return 0
}
on_off_function()
{
# $1 : function name on
# $2 : function name off
# $3 : 0 - off, 1 - on
local F="$1"
[ "$3" = "1" ] || F="$2"
shift
shift
shift
"$F" "$@"
}
contains()
{
# check if substring $2 contains in $1
[ "${1#*$2}" != "$1" ]
}
find_str_in_list()
{
[ -n "$1" ] && {
for v in $2; do
[ "$v" = "$1" ] && return 0
done
}
return 1
}
end_with_newline()
{
local c=$(tail -c 1)
[ "$c" = "" ]
}
make_separator_list()
{
# $1 - var name to receive result
# $2 - separator
# $3,$4,... - elements
local var="$1" sep="$2" i
shift; shift
while [ -n "$1" ]; do
if [ -n "$i" ] ; then
i=$i$sep$1
else
i=$1
fi
shift
done
eval $var=$i
}
make_comma_list()
{
# $1 - var name to receive result
# $2,$3,... - elements
local var="$1"
shift
make_separator_list $var , "$@"
}
is_linked_to_busybox()
{
local IFS F P
IFS=:
for path in $PATH; do
F=$path/$1
P="$(readlink $F)"
if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi
[ "${P%busybox*}" != "$P" ] && return
done
}
get_dir_inode()
{
local dir="$1"
[ -L "$dir" ] && dir=$(readlink "$dir")
ls -id "$dir" | awk '{print $1}'
}
linux_min_version()
{
# $1 - major ver
# $2 - minor ver
local V1=$(sed -nre 's/^Linux version ([0-9]+)\.[0-9]+.*$/\1/p' /proc/version)
local V2=$(sed -nre 's/^Linux version [0-9]+\.([0-9]+).*$/\1/p' /proc/version)
[ -n "$V1" -a -n "$V2" ] && [ "$V1" -gt "$1" -o "$V1" -eq "$1" -a "$V2" -ge "$2" ]
}
linux_get_subsys()
{
local INIT=$(sed 's/\x0/\n/g' /proc/1/cmdline | head -n 1)
[ -L "$INIT" ] && INIT=$(readlink "$INIT")
INIT=$(basename "$INIT")
if [ -f "/etc/openwrt_release" ] && [ "$INIT" = "procd" ] ; then
SUBSYS=openwrt
else
# generic linux
SUBSYS=
fi
}
openwrt_fw3()
{
[ ! -x /sbin/fw4 -a -x /sbin/fw3 ]
}
openwrt_fw4()
{
[ -x /sbin/fw4 ]
}
openwrt_fw3_integration()
{
[ "$FWTYPE" = iptables ] && openwrt_fw3
}
create_dev_stdin()
{
[ -e /dev/stdin ] || ln -s /proc/self/fd/0 /dev/stdin
}

58
common/dialog.sh Normal file
View File

@@ -0,0 +1,58 @@
read_yes_no()
{
# $1 - default (Y/N)
local A
read A
[ -z "$A" ] || ([ "$A" != "Y" ] && [ "$A" != "y" ] && [ "$A" != "N" ] && [ "$A" != "n" ]) && A=$1
[ "$A" = "Y" ] || [ "$A" = "y" ] || [ "$A" = "1" ]
}
ask_yes_no()
{
# $1 - default (Y/N or 0/1)
# $2 - text
local DEFAULT=$1
[ "$1" = "1" ] && DEFAULT=Y
[ "$1" = "0" ] && DEFAULT=N
[ -z "$DEFAULT" ] && DEFAULT=N
printf "$2 (default : $DEFAULT) (Y/N) ? "
read_yes_no $DEFAULT
}
ask_yes_no_var()
{
# $1 - variable name for answer : 0/1
# $2 - text
local DEFAULT
eval DEFAULT="\$$1"
if ask_yes_no "$DEFAULT" "$2"; then
eval $1=1
else
eval $1=0
fi
}
ask_list()
{
# $1 - mode var
# $2 - space separated value list
# $3 - (optional) default value
local M_DEFAULT
eval M_DEFAULT="\$$1"
local M_ALL=$M_DEFAULT
local M=""
local m
[ -n "$3" ] && { find_str_in_list "$M_DEFAULT" "$2" || M_DEFAULT="$3" ;}
n=1
for m in $2; do
echo $n : $m
n=$(($n+1))
done
printf "your choice (default : $M_DEFAULT) : "
read m
[ -n "$m" ] && M=$(echo $2 | cut -d ' ' -f$m 2>/dev/null)
[ -z "$M" ] && M="$M_DEFAULT"
echo selected : $M
eval $1="\"$M\""
[ "$M" != "$M_OLD" ]
}

13
common/elevate.sh Normal file
View File

@@ -0,0 +1,13 @@
require_root()
{
local exe
echo \* checking privileges
[ $(id -u) -ne "0" ] && {
echo root is required
exe="$EXEDIR/$(basename "$0")"
exists sudo && exec sudo "$exe"
exists su && exec su root -c "$exe"
echo su or sudo not found
exitp 2
}
}

64
common/fwtype.sh Normal file
View File

@@ -0,0 +1,64 @@
linux_ipt_avail()
{
exists iptables && exists ip6tables
}
linux_maybe_iptables_fwtype()
{
linux_ipt_avail && FWTYPE=iptables
}
linux_nft_avail()
{
exists nft
}
linux_fwtype()
{
[ -n "$FWTYPE" ] && return
FWTYPE=unsupported
linux_get_subsys
if [ "$SUBSYS" = openwrt ] ; then
# linux kernel is new enough if fw4 is there
if [ -x /sbin/fw4 ] && linux_nft_avail ; then
FWTYPE=nftables
else
linux_maybe_iptables_fwtype
fi
else
SUBSYS=
# generic linux
# flowtable is implemented since kernel 4.16
if linux_nft_avail && linux_min_version 4 16; then
FWTYPE=nftables
else
linux_maybe_iptables_fwtype
fi
fi
export FWTYPE
}
get_fwtype()
{
[ -n "$FWTYPE" ] && return
local UNAME="$(uname)"
case "$UNAME" in
Linux)
linux_fwtype
;;
FreeBSD)
if exists ipfw ; then
FWTYPE=ipfw
else
FWTYPE=unsupported
fi
;;
*)
FWTYPE=unsupported
;;
esac
export FWTYPE
}

462
common/installer.sh Normal file
View File

@@ -0,0 +1,462 @@
GET_LIST_PREFIX=/ipset/get_
SYSTEMD_DIR=/lib/systemd
[ -d "$SYSTEMD_DIR" ] || SYSTEMD_DIR=/usr/lib/systemd
[ -d "$SYSTEMD_DIR" ] && SYSTEMD_SYSTEM_DIR="$SYSTEMD_DIR/system"
INIT_SCRIPT=/etc/init.d/zapret
exitp()
{
echo
echo press enter to continue
read A
exit $1
}
parse_var_checked()
{
# $1 - file name
# $2 - var name
local sed="sed -nre s/^[[:space:]]*$2=[\\\"|\']?([^\\\"|\']*)[\\\"|\']?/\1/p"
local v="$($sed <"$1" | tail -n 1)"
eval $2=\"$v\"
}
parse_vars_checked()
{
# $1 - file name
# $2,$3,... - var names
local f="$1"
shift
while [ -n "$1" ]; do
parse_var_checked "$f" $1
shift
done
}
edit_file()
{
# $1 - file name
local ed="$EDITOR"
[ -n "$ed" ] || {
for e in mcedit nano vi; do
exists "$e" && {
ed="$e"
break
}
done
}
[ -n "$ed" ] && "$ed" "$1"
}
edit_vars()
{
# $1,$2,... - var names
local n=1 var v tmp="/tmp/zvars"
rm -f "$tmp"
while [ 1=1 ]; do
eval var="\$$n"
[ -n "$var" ] || break
eval v="\$$var"
echo $var=\"$v\" >>"$tmp"
n=$(($n+1))
done
edit_file "$tmp" && parse_vars_checked "$tmp" "$@"
rm -f "$tmp"
}
openrc_test()
{
exists rc-update || return 1
# some systems do not usse openrc-init but launch openrc from inittab
[ "$INIT" = "openrc-init" ] || grep -qE "sysinit.*openrc" /etc/inittab 2>/dev/null
}
check_system()
{
echo \* checking system
SYSTEM=""
SYSTEMCTL=$(whichq systemctl)
get_fwtype
OPENWRT_FW3=
local info
local UNAME=$(uname)
if [ "$UNAME" = "Linux" ]; then
# do not use 'exe' because it requires root
local INIT=$(sed 's/\x0/\n/g' /proc/1/cmdline | head -n 1)
[ -L "$INIT" ] && INIT=$(readlink "$INIT")
INIT=$(basename "$INIT")
# some distros include systemctl without systemd
if [ -d "$SYSTEMD_DIR" ] && [ -x "$SYSTEMCTL" ] && [ "$INIT" = "systemd" ]; then
SYSTEM=systemd
elif [ -f "/etc/openwrt_release" ] && exists opkg && exists uci && [ "$INIT" = "procd" ] ; then
{
SYSTEM=openwrt
if openwrt_fw3 ; then
OPENWRT_FW3=1
info="openwrt firewall uses fw3"
if is_ipt_flow_offload_avail; then
info="$info. hardware flow offloading requires iptables."
else
info="$info. flow offloading unavailable."
fi
elif openwrt_fw4; then
info="openwrt firewall uses fw4. flow offloading requires nftables."
fi
}
elif openrc_test; then
SYSTEM=openrc
else
echo system is not either systemd, openrc or openwrt based
echo easy installer can set up config settings but can\'t configure auto start
echo you have to do it manually. check readme.txt for manual setup info.
if ask_yes_no N "do you want to continue"; then
SYSTEM=linux
else
exitp 5
fi
fi
elif [ "$UNAME" = "Darwin" ]; then
SYSTEM=macos
else
echo easy installer only supports Linux and MacOS. check readme.txt for supported systems and manual setup info.
exitp 5
fi
echo system is based on $SYSTEM
[ -n "$info" ] && echo $info
}
get_free_space_mb()
{
df -m $PWD | awk '/[0-9]%/{print $(NF-2)}'
}
get_ram_kb()
{
grep MemTotal /proc/meminfo | awk '{print $2}'
}
get_ram_mb()
{
local R=$(get_ram_kb)
echo $(($R/1024))
}
crontab_del()
{
exists crontab || return
echo \* removing crontab entry
CRONTMP=/tmp/cron.tmp
crontab -l >$CRONTMP 2>/dev/null
if grep -q "$GET_LIST_PREFIX" $CRONTMP; then
echo removing following entries from crontab :
grep "$GET_LIST_PREFIX" $CRONTMP
grep -v "$GET_LIST_PREFIX" $CRONTMP >$CRONTMP.2
crontab $CRONTMP.2
rm -f $CRONTMP.2
fi
rm -f $CRONTMP
}
crontab_del_quiet()
{
exists crontab || return
CRONTMP=/tmp/cron.tmp
crontab -l >$CRONTMP 2>/dev/null
if grep -q "$GET_LIST_PREFIX" $CRONTMP; then
grep -v "$GET_LIST_PREFIX" $CRONTMP >$CRONTMP.2
crontab $CRONTMP.2
rm -f $CRONTMP.2
fi
rm -f $CRONTMP
}
crontab_add()
{
# $1 - hour min
# $2 - hour max
[ -x "$GET_LIST" ] && {
echo \* adding crontab entry
if exists crontab; then
CRONTMP=/tmp/cron.tmp
crontab -l >$CRONTMP 2>/dev/null
if grep -q "$GET_LIST_PREFIX" $CRONTMP; then
echo some entries already exist in crontab. check if this is corrent :
grep "$GET_LIST_PREFIX" $CRONTMP
else
end_with_newline <"$CRONTMP" || echo >>"$CRONTMP"
echo "$(random 0 59) $(random $1 $2) */2 * * $GET_LIST" >>$CRONTMP
crontab $CRONTMP
fi
rm -f $CRONTMP
else
echo '!!! CRON IS ABSENT !!! LISTS AUTO UPDATE WILL NOT WORK !!!'
fi
}
}
cron_ensure_running()
{
# if no crontabs present in /etc/cron openwrt init script does not launch crond. this is default
[ "$SYSTEM" = "openwrt" ] && {
/etc/init.d/cron enable
/etc/init.d/cron start
}
}
service_start_systemd()
{
echo \* starting zapret service
"$SYSTEMCTL" start zapret || {
echo could not start zapret service
exitp 30
}
}
service_stop_systemd()
{
echo \* stopping zapret service
"$SYSTEMCTL" daemon-reload
"$SYSTEMCTL" disable zapret
"$SYSTEMCTL" stop zapret
}
service_remove_systemd()
{
echo \* removing zapret service
rm -f "$SYSTEMD_SYSTEM_DIR/zapret.service"
"$SYSTEMCTL" daemon-reload
}
timer_remove_systemd()
{
echo \* removing zapret-list-update timer
"$SYSTEMCTL" daemon-reload
"$SYSTEMCTL" disable zapret-list-update.timer
"$SYSTEMCTL" stop zapret-list-update.timer
rm -f "$SYSTEMD_SYSTEM_DIR/zapret-list-update.service" "$SYSTEMD_SYSTEM_DIR/zapret-list-update.timer"
"$SYSTEMCTL" daemon-reload
}
install_sysv_init()
{
# $1 - "0"=disable
echo \* installing init script
[ -x "$INIT_SCRIPT" ] && {
"$INIT_SCRIPT" stop
"$INIT_SCRIPT" disable
}
ln -fs "$INIT_SCRIPT_SRC" "$INIT_SCRIPT"
[ "$1" != "0" ] && "$INIT_SCRIPT" enable
}
install_openrc_init()
{
# $1 - "0"=disable
echo \* installing init script
[ -x "$INIT_SCRIPT" ] && {
"$INIT_SCRIPT" stop
rc-update del zapret
}
ln -fs "$INIT_SCRIPT_SRC" "$INIT_SCRIPT"
[ "$1" != "0" ] && rc-update add zapret
}
service_remove_openrc()
{
echo \* removing zapret service
[ -x "$INIT_SCRIPT" ] && {
rc-update del zapret
"$INIT_SCRIPT" stop
}
rm -f "$INIT_SCRIPT"
}
service_start_sysv()
{
[ -x "$INIT_SCRIPT" ] && {
echo \* starting zapret service
"$INIT_SCRIPT" start || {
echo could not start zapret service
exitp 30
}
}
}
service_stop_sysv()
{
[ -x "$INIT_SCRIPT" ] && {
echo \* stopping zapret service
"$INIT_SCRIPT" stop
}
}
service_remove_sysv()
{
echo \* removing zapret service
[ -x "$INIT_SCRIPT" ] && {
"$INIT_SCRIPT" disable
"$INIT_SCRIPT" stop
}
rm -f "$INIT_SCRIPT"
}
check_kmod()
{
[ -f "/lib/modules/$(uname -r)/$1.ko" ]
}
check_package_exists_openwrt()
{
[ -n "$(opkg list $1)" ]
}
check_package_openwrt()
{
[ -n "$(opkg list-installed $1)" ] && return 0
local what=$(opkg whatprovides $1 | tail -n +2 | head -n 1)
[ -n "$what" ] || return 1
[ -n "$(opkg list-installed $what)" ]
}
check_packages_openwrt()
{
for pkg in $@; do
check_package_openwrt $pkg || return
done
}
install_openwrt_iface_hook()
{
echo \* installing ifup hook
ln -fs "$OPENWRT_IFACE_HOOK" /etc/hotplug.d/iface
}
remove_openwrt_iface_hook()
{
echo \* removing ifup hook
rm -f /etc/hotplug.d/iface/??-zapret
}
openwrt_fw_section_find()
{
# $1 - fw include postfix
# echoes section number
i=0
while true
do
path=$(uci -q get firewall.@include[$i].path)
[ -n "$path" ] || break
[ "$path" = "$OPENWRT_FW_INCLUDE$1" ] && {
echo $i
return 0
}
i=$(($i+1))
done
return 1
}
openwrt_fw_section_del()
{
# $1 - fw include postfix
local id=$(openwrt_fw_section_find $1)
[ -n "$id" ] && {
uci delete firewall.@include[$id] && uci commit firewall
rm -f "$OPENWRT_FW_INCLUDE$1"
}
}
openwrt_fw_section_add()
{
openwrt_fw_section_find ||
{
uci add firewall include >/dev/null || return
echo -1
}
}
openwrt_fw_section_configure()
{
local id=$(openwrt_fw_section_add $1)
[ -z "$id" ] ||
! uci set firewall.@include[$id].path="$OPENWRT_FW_INCLUDE" ||
! uci set firewall.@include[$id].reload="1" ||
! uci commit firewall &&
{
echo could not add firewall include
exitp 50
}
}
install_openwrt_firewall()
{
echo \* installing firewall script $1
[ -n "MODE" ] || {
echo should specify MODE in $ZAPRET_CONFIG
exitp 7
}
echo "linking : $FW_SCRIPT_SRC => $OPENWRT_FW_INCLUDE"
ln -fs "$FW_SCRIPT_SRC" "$OPENWRT_FW_INCLUDE"
openwrt_fw_section_configure $1
}
restart_openwrt_firewall()
{
echo \* restarting firewall
fw3 -q restart || {
echo could not restart firewall
exitp 30
}
}
remove_openwrt_firewall()
{
echo \* removing firewall script
openwrt_fw_section_del
# from old zapret versions. now we use single include
openwrt_fw_section_del 6
}
clear_ipset()
{
echo "* clearing ipset(s)"
# free some RAM
"$IPSET_DIR/create_ipset.sh" clear
}
service_install_macos()
{
echo \* installing zapret service
ln -fs "$ZAPRET_BASE/init.d/macos/zapret.plist" /Library/LaunchDaemons
}
service_start_macos()
{
echo \* starting zapret service
"$INIT_SCRIPT_SRC" start
}
service_stop_macos()
{
echo \* stopping zapret service
"$INIT_SCRIPT_SRC" stop
}
service_remove_macos()
{
echo \* removing zapret service
rm -f /Library/LaunchDaemons/zapret.plist
zapret_stop_daemons
}
remove_macos_firewall()
{
echo \* removing zapret PF hooks
pf_anchors_clear
pf_anchors_del
pf_anchor_root_del
pf_anchor_root_reload
}

172
common/ipt.sh Normal file
View File

@@ -0,0 +1,172 @@
ipt()
{
iptables -C "$@" >/dev/null 2>/dev/null || iptables -I "$@"
}
ipta()
{
iptables -C "$@" >/dev/null 2>/dev/null || iptables -A "$@"
}
ipt_del()
{
iptables -C "$@" >/dev/null 2>/dev/null && iptables -D "$@"
}
ipt_add_del()
{
on_off_function ipt ipt_del "$@"
}
ipta_add_del()
{
on_off_function ipta ipt_del "$@"
}
ipt6()
{
ip6tables -C "$@" >/dev/null 2>/dev/null || ip6tables -I "$@"
}
ipt6a()
{
ip6tables -C "$@" >/dev/null 2>/dev/null || ip6tables -A "$@"
}
ipt6_del()
{
ip6tables -C "$@" >/dev/null 2>/dev/null && ip6tables -D "$@"
}
ipt6_add_del()
{
on_off_function ipt6 ipt6_del "$@"
}
ipt6a_add_del()
{
on_off_function ipt6 ipt6a_del "$@"
}
is_ipt_flow_offload_avail()
{
# $1 = '' for ipv4, '6' for ipv6
grep -q FLOWOFFLOAD 2>/dev/null /proc/net/ip$1_tables_targets
}
filter_apply_port_target()
{
# $1 - var name of iptables filter
local f
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then
f="-m multiport --dports 80,443"
elif [ "$MODE_HTTPS" = "1" ]; then
f="--dport 443"
elif [ "$MODE_HTTP" = "1" ]; then
f="--dport 80"
else
echo WARNING !!! HTTP and HTTPS are both disabled
fi
eval $1="\"\$$1 $f\""
}
filter_apply_ipset_target4()
{
# $1 - var name of ipv4 iptables filter
if [ "$MODE_FILTER" = "ipset" ]; then
eval $1="\"\$$1 -m set --match-set zapret dst\""
fi
}
filter_apply_ipset_target6()
{
# $1 - var name of ipv6 iptables filter
if [ "$MODE_FILTER" = "ipset" ]; then
eval $1="\"\$$1 -m set --match-set zapret6 dst\""
fi
}
filter_apply_ipset_target()
{
# $1 - var name of ipv4 iptables filter
# $2 - var name of ipv6 iptables filter
filter_apply_ipset_target4 $1
filter_apply_ipset_target6 $2
}
zapret_do_firewall_ipt()
{
# $1 - 1 - add, 0 - del
if [ "$1" = 1 ]; then
echo Applying iptables
else
echo Clearing iptables
fi
local mode="${MODE_OVERRIDE:-$MODE}"
[ "$mode" = "tpws-socks" ] && return 0
local first_packet_only="-m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:4"
local desync="-m mark ! --mark $DESYNC_MARK/$DESYNC_MARK"
local f4 f6 qn qns qn6 qns6
# always create ipsets. ip_exclude ipset is required
[ "$1" = 1 ] && create_ipset no-update
case "$mode" in
tpws)
if [ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ]; then
echo both http and https are disabled. not applying redirection.
else
filter_apply_port_target f4
f6=$f4
filter_apply_ipset_target f4 f6
fw_tpws $1 "$f4" "$f6" $TPPORT
fi
;;
nfqws)
# quite complex but we need to minimize nfqws processes to save RAM
get_nfqws_qnums qn qns qn6 qns6
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn" ] && [ "$qn" = "$qns" ]; then
filter_apply_port_target f4
f4="$f4 $first_packet_only"
filter_apply_ipset_target4 f4
fw_nfqws_post4 $1 "$f4 $desync" $qn
else
if [ -n "$qn" ]; then
f4="--dport 80"
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f4="$f4 $first_packet_only"
filter_apply_ipset_target4 f4
fw_nfqws_post4 $1 "$f4 $desync" $qn
fi
if [ -n "$qns" ]; then
f4="--dport 443 $first_packet_only"
filter_apply_ipset_target4 f4
fw_nfqws_post4 $1 "$f4 $desync" $qns
fi
fi
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn6" ] && [ "$qn6" = "$qns6" ]; then
filter_apply_port_target f6
f6="$f6 $first_packet_only"
filter_apply_ipset_target6 f6
fw_nfqws_post6 $1 "$f6 $desync" $qn6
else
if [ -n "$qn6" ]; then
f6="--dport 80"
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f6="$f6 $first_packet_only"
filter_apply_ipset_target6 f6
fw_nfqws_post6 $1 "$f6 $desync" $qn6
fi
if [ -n "$qns6" ]; then
f6="--dport 443 $first_packet_only"
filter_apply_ipset_target6 f6
fw_nfqws_post6 $1 "$f6 $desync" $qns6
fi
fi
;;
custom)
existf zapret_custom_firewall && zapret_custom_firewall $1
;;
esac
if [ "$1" = 1 ] ; then
existf flow_offloading_exempt && flow_offloading_exempt
else
existf flow_offloading_unexempt && flow_offloading_unexempt
unprepare_tpws_fw
fi
return 0
}

23
common/linux_fw.sh Normal file
View File

@@ -0,0 +1,23 @@
zapret_do_firewall()
{
linux_fwtype
case "$FWTYPE" in
iptables)
zapret_do_firewall_ipt "$@"
;;
nftables)
zapret_do_firewall_nft "$@"
;;
esac
return 0
}
zapret_apply_firewall()
{
zapret_do_firewall 1 "$@"
}
zapret_unapply_firewall()
{
zapret_do_firewall 0 "$@"
}

51
common/linux_iphelper.sh Normal file
View File

@@ -0,0 +1,51 @@
# there's no route_localnet for ipv6
# the best we can is to route to link local of the incoming interface
# OUTPUT - can DNAT to ::1
# PREROUTING - can't DNAT to ::1. can DNAT to link local of -i interface or to any global addr
# not a good idea to expose tpws to the world (bind to ::)
get_ipv6_linklocal()
{
# $1 - interface name. if empty - any interface
if exists ip ; then
local dev
[ -n "$1" ] && dev="dev $1"
ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope link.*$/\1/;t;d' | head -n 1
else
ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Link.*$/\1/;t;d' | head -n 1
fi
}
get_ipv6_global()
{
# $1 - interface name. if empty - any interface
if exists ip ; then
local dev
[ -n "$1" ] && dev="dev $1"
ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope global.*$/\1/;t;d' | head -n 1
else
ifconfig $1 | sed -re 's/^.*inet6 addr: ([^ ]*)\/[0-9]* Scope:Global.*$/\1/;t;d' | head -n 1
fi
}
iface_is_up()
{
# $1 - interface name
[ -f /sys/class/net/$1/operstate ] || return
local state
read state </sys/class/net/$1/operstate
[ "$state" != "down" ]
}
wait_ifup()
{
# $1 - interface name
local ct=0
while
iface_is_up $1 && return
[ "$ct" -ge "$IFUP_WAIT_SEC" ] && break
echo waiting for ifup of $1 for another $(($IFUP_WAIT_SEC - $ct)) seconds ...
ct=$(($ct+1))
sleep 1
do :; done
false
}

348
common/nft.sh Normal file
View File

@@ -0,0 +1,348 @@
[ -n "$ZAPRET_NFT_TABLE" ] || ZAPRET_NFT_TABLE=zapret
# required for : nft -f -
create_dev_stdin
nft_create_table()
{
nft add table inet $ZAPRET_NFT_TABLE
}
nft_del_table()
{
nft delete table inet $ZAPRET_NFT_TABLE 2>/dev/null
}
nft_list_table()
{
nft -t list table inet $ZAPRET_NFT_TABLE
}
nft_create_set()
{
# $1 - set name
# $2 - params
nft create set inet $ZAPRET_NFT_TABLE $1 "{ $2 }" 2>/dev/null
}
nft_del_set()
{
# $1 - set name
nft delete set inet $ZAPRET_NFT_TABLE $1
}
nft_flush_set()
{
# $1 - set name
nft flush set inet $ZAPRET_NFT_TABLE $1
}
nft_set_exists()
{
# $1 - set name
nft -t list set inet $ZAPRET_NFT_TABLE $1 2>/dev/null >/dev/null
}
nft_del_all_chains_from_table()
{
# $1 - table_name with or without family
# delete all chains with possible references to each other
# cannot just delete all in the list because of references
# avoid infinite loops
local chains deleted=1 error=1
while [ -n "$deleted" -a -n "$error" ]; do
chains=$(nft -t list table $1 2>/dev/null | sed -nre "s/^[ ]*chain ([^ ]+) \{/\1/p" | xargs)
[ -n "$chains" ] || break
deleted=
error=
for chain in $chains; do
if nft delete chain $1 $chain 2>/dev/null; then
deleted=1
else
error=1
fi
done
done
}
nft_del_chains()
{
nft_del_all_chains_from_table "inet $ZAPRET_NFT_TABLE"
}
nft_create_chains()
{
cat << EOF | nft -f -
add chain inet $ZAPRET_NFT_TABLE dnat_output { type nat hook output priority -101; }
flush chain inet $ZAPRET_NFT_TABLE dnat_output
add chain inet $ZAPRET_NFT_TABLE dnat_pre { type nat hook prerouting priority -101; }
flush chain inet $ZAPRET_NFT_TABLE dnat_pre
add chain inet $ZAPRET_NFT_TABLE forward { type filter hook forward priority -1; }
flush chain inet $ZAPRET_NFT_TABLE forward
add chain inet $ZAPRET_NFT_TABLE input { type filter hook input priority -1; }
flush chain inet $ZAPRET_NFT_TABLE input
add chain inet $ZAPRET_NFT_TABLE flow_offload
flush chain inet $ZAPRET_NFT_TABLE flow_offload
add chain inet $ZAPRET_NFT_TABLE localnet_protect
flush chain inet $ZAPRET_NFT_TABLE localnet_protect
add rule inet $ZAPRET_NFT_TABLE localnet_protect ip daddr $TPWS_LOCALHOST4 return comment "route_localnet allow access to tpws"
add rule inet $ZAPRET_NFT_TABLE localnet_protect ip daddr 127.0.0.0/8 drop comment "route_localnet remote access protection"
add rule inet $ZAPRET_NFT_TABLE input iifname != lo jump localnet_protect
add chain inet $ZAPRET_NFT_TABLE postrouting { type filter hook postrouting priority -151; }
flush chain inet $ZAPRET_NFT_TABLE postrouting
add set inet $ZAPRET_NFT_TABLE lanif { type ifname; }
add set inet $ZAPRET_NFT_TABLE wanif { type ifname; }
add set inet $ZAPRET_NFT_TABLE wanif6 { type ifname; }
EOF
}
nft_del_flowtable()
{
nft delete flowtable inet $ZAPRET_NFT_TABLE ft 2>/dev/null
}
nft_create_or_update_flowtable()
{
# $1 = flags ('offload' for hw offload)
# $2,$3,$4,... - interfaces
# can be called multiple times to add interfaces. interfaces can only be added , not removed
local flags=$1 devices
shift
make_comma_list devices "$@"
[ -n "$devices" ] && devices="devices={$devices};"
[ -n "$flags" ] && flags="flags $flags;"
nft add flowtable inet $ZAPRET_NFT_TABLE ft "{ hook ingress priority -1; $flags $devices }"
}
nft_flush_ifsets()
{
cat << EOF | nft -f - 2>/dev/null
flush set inet $ZAPRET_NFT_TABLE lanif
flush set inet $ZAPRET_NFT_TABLE wanif
flush set inet $ZAPRET_NFT_TABLE wanif6
EOF
}
nft_list_ifsets()
{
nft list set inet $ZAPRET_NFT_TABLE lanif
nft list set inet $ZAPRET_NFT_TABLE wanif
nft list set inet $ZAPRET_NFT_TABLE wanif6
nft list flowtable inet $ZAPRET_NFT_TABLE ft
}
nft_create_firewall()
{
nft_create_table
nft_del_flowtable
nft_create_chains
}
nft_del_firewall()
{
nft_del_chains
nft_del_flowtable
nft_flush_ifsets
}
nft_add_rule()
{
# $1 - chain
# $2,$3,... - rule(s)
local chain="$1"
shift
nft add rule inet $ZAPRET_NFT_TABLE $chain "$@"
}
nft_add_set_elements()
{
# $1 - set name
# $2,$3,... - element(s)
local set="$1" elements
shift
make_comma_list elements "$@"
[ -z "$elements" ] || nft add element inet $ZAPRET_NFT_TABLE $set "{ $elements }"
}
nft_reverse_nfqws_rule()
{
echo "$@" | sed -e 's/oifname /iifname /g' -e 's/dport /sport /g' -e 's/daddr /saddr /g' -e 's/ct original /ct reply /g' -e "s/mark and $DESYNC_MARK == 0//g"
}
nft_clean_nfqws_rule()
{
echo "$@" | sed -e "s/mark and $DESYNC_MARK == 0//g"
}
nft_add_nfqws_flow_exempt_rule()
{
# $1 - rule (must be all filters in one var)
nft_add_rule flow_offload $(nft_clean_nfqws_rule $1) return comment \"direct flow offloading exemption\"
nft_add_rule flow_offload $(nft_reverse_nfqws_rule $1) return comment \"reverse flow offloading exemption\"
}
nft_hw_offload_supported()
{
# $1,$2,... - interface names
local devices res=1
make_comma_list devices "$@"
[ -n "$devices" ] && devices="devices={$devices};"
nft add table ${ZAPRET_NFT_TABLE}_test && nft add flowtable ${ZAPRET_NFT_TABLE}_test ft "{ flags offload; $devices }" 2>/dev/null && res=0
nft delete table ${ZAPRET_NFT_TABLE}_test 2>/dev/null
return $res
}
nft_apply_flow_offloading()
{
# ft can be absent
nft_add_rule flow_offload meta l4proto "{ tcp, udp }" flow add @ft 2>/dev/null && nft_add_rule forward jump flow_offload
}
nft_filter_apply_port_target()
{
# $1 - var name of nftables filter
local f
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then
f="tcp dport {80,443}"
elif [ "$MODE_HTTPS" = "1" ]; then
f="tcp dport 443"
elif [ "$MODE_HTTP" = "1" ]; then
f="tcp dport 80"
else
echo WARNING !!! HTTP and HTTPS are both disabled
fi
eval $1="\"\$$1 $f\""
}
nft_filter_apply_ipset_target4()
{
# $1 - var name of ipv4 nftables filter
if [ "$MODE_FILTER" = "ipset" ]; then
eval $1="\"\$$1 ip daddr @zapret\""
fi
}
nft_filter_apply_ipset_target6()
{
# $1 - var name of ipv6 nftables filter
if [ "$MODE_FILTER" = "ipset" ]; then
eval $1="\"\$$1 ip6 daddr @zapret6\""
fi
}
nft_filter_apply_ipset_target()
{
# $1 - var name of ipv4 nftables filter
# $2 - var name of ipv6 nftables filter
nft_filter_apply_ipset_target4 $1
nft_filter_apply_ipset_target6 $2
}
nft_only()
{
linux_fwtype
case "$FWTYPE" in
nftables)
"$@"
;;
esac
}
zapret_reload_ifsets()
{
nft_only nft_create_table ; nft_fill_ifsets
return 0
}
zapret_list_ifsets()
{
nft_only nft_list_ifsets
return 0
}
zapret_list_table()
{
nft_only nft_list_table
return 0
}
zapret_apply_firewall_nft()
{
echo Applying nftables
local mode="${MODE_OVERRIDE:-$MODE}"
[ "$mode" = "tpws-socks" ] && return 0
local first_packet_only="ct original packets 1-4"
local desync="mark and $DESYNC_MARK == 0"
local f4 f6 qn qns qn6 qns6
create_ipset no-update
nft_create_firewall
nft_fill_ifsets
case "$mode" in
tpws)
if [ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ]; then
echo both http and https are disabled. not applying redirection.
else
nft_filter_apply_port_target f4
f6=$f4
nft_filter_apply_ipset_target f4 f6
nft_fw_tpws "$f4" "$f6" $TPPORT
fi
;;
nfqws)
# quite complex but we need to minimize nfqws processes to save RAM
get_nfqws_qnums qn qns qn6 qns6
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn" ] && [ "$qn" = "$qns" ]; then
nft_filter_apply_port_target f4
f4="$f4 $first_packet_only"
nft_filter_apply_ipset_target4 f4
nft_fw_nfqws_post4 "$f4 $desync" $qn
else
if [ -n "$qn" ]; then
f4="tcp dport 80"
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f4="$f4 $first_packet_only"
nft_filter_apply_ipset_target4 f4
nft_fw_nfqws_post4 "$f4 $desync" $qn
fi
if [ -n "$qns" ]; then
f4="tcp dport 443 $first_packet_only"
nft_filter_apply_ipset_target4 f4
nft_fw_nfqws_post4 "$f4 $desync" $qns
fi
fi
if [ "$MODE_HTTP_KEEPALIVE" != "1" ] && [ -n "$qn6" ] && [ "$qn6" = "$qns6" ]; then
nft_filter_apply_port_target f6
f6="$f6 $first_packet_only"
nft_filter_apply_ipset_target6 f6
nft_fw_nfqws_post6 "$f6 $desync" $qn6
else
if [ -n "$qn6" ]; then
f6="tcp dport 80"
[ "$MODE_HTTP_KEEPALIVE" = "1" ] || f6="$f6 $first_packet_only"
nft_filter_apply_ipset_target6 f6
nft_fw_nfqws_post6 "$f6 $desync" $qn6
fi
if [ -n "$qns6" ]; then
f6="tcp dport 443 $first_packet_only"
nft_filter_apply_ipset_target6 f6
nft_fw_nfqws_post6 "$f6 $desync" $qns6
fi
fi
;;
custom)
existf zapret_custom_firewall_nft && zapret_custom_firewall_nft
;;
esac
[ "$FLOWOFFLOAD" = 'software' -o "$FLOWOFFLOAD" = 'hardware' ] && nft_apply_flow_offloading
return 0
}
zapret_unapply_firewall_nft()
{
echo Clearing nftables
unprepare_route_localnet
nft_del_firewall
return 0
}
zapret_do_firewall_nft()
{
# $1 - 1 - add, 0 - del
if [ "$1" = 0 ] ; then
zapret_unapply_firewall_nft
else
zapret_apply_firewall_nft
fi
return 0
}

262
common/pf.sh Normal file
View File

@@ -0,0 +1,262 @@
PF_MAIN="/etc/pf.conf"
PF_ANCHOR_DIR=/etc/pf.anchors
PF_ANCHOR_ZAPRET="$PF_ANCHOR_DIR/zapret"
PF_ANCHOR_ZAPRET_V4="$PF_ANCHOR_DIR/zapret-v4"
PF_ANCHOR_ZAPRET_V6="$PF_ANCHOR_DIR/zapret-v6"
pf_anchor_root_reload()
{
echo reloading PF root anchor
pfctl -qf "$PF_MAIN"
}
pf_anchor_root()
{
local patch
[ -f "$PF_MAIN" ] && {
grep -q '^rdr-anchor "zapret"$' "$PF_MAIN" || {
echo patching rdr-anchor in $PF_MAIN
patch=1
sed -i '' -e '/^rdr-anchor "com\.apple\/\*"$/i \
rdr-anchor "zapret"
' $PF_MAIN
}
grep -q '^anchor "zapret"$' "$PF_MAIN" || {
echo patching anchor in $PF_MAIN
patch=1
sed -i '' -e '/^anchor "com\.apple\/\*"$/i \
anchor "zapret"
' $PF_MAIN
}
grep -q "^set limit table-entries" "$PF_MAIN" || {
echo patching table-entries limit
patch=1
sed -i '' -e '/^scrub-anchor "com\.apple\/\*"$/i \
set limit table-entries 5000000
' $PF_MAIN
}
grep -q '^anchor "zapret"$' "$PF_MAIN" &&
grep -q '^rdr-anchor "zapret"$' "$PF_MAIN" &&
grep -q '^set limit table-entries' "$PF_MAIN" && {
if [ -n "$patch" ]; then
echo successfully patched $PF_MAIN
pf_anchor_root_reload
else
echo successfully checked zapret anchors in $PF_MAIN
fi
return 0
}
}
echo ----------------------------------
echo Automatic $PF_MAIN patching failed. You must apply root anchors manually in your PF config.
echo rdr-anchor \"zapret\"
echo anchor \"zapret\"
echo ----------------------------------
return 1
}
pf_anchor_root_del()
{
sed -i '' -e '/^anchor "zapret"$/d' -e '/^rdr-anchor "zapret"$/d' -e '/^set limit table-entries/d' "$PF_MAIN"
}
pf_anchor_zapret()
{
[ "$DISABLE_IPV4" = "1" ] || {
if [ -f "$ZIPLIST_EXCLUDE" ]; then
echo "table <nozapret> persist file \"$ZIPLIST_EXCLUDE\""
else
echo "table <nozapret> persist"
fi
}
[ "$DISABLE_IPV6" = "1" ] || {
if [ -f "$ZIPLIST_EXCLUDE6" ]; then
echo "table <nozapret6> persist file \"$ZIPLIST_EXCLUDE6\""
else
echo "table <nozapret6> persist"
fi
}
[ "$DISABLE_IPV4" = "1" ] || echo "rdr-anchor \"/zapret-v4\" inet to !<nozapret>"
[ "$DISABLE_IPV6" = "1" ] || echo "rdr-anchor \"/zapret-v6\" inet6 to !<nozapret6>"
[ "$DISABLE_IPV4" = "1" ] || echo "anchor \"/zapret-v4\" inet to !<nozapret>"
[ "$DISABLE_IPV6" = "1" ] || echo "anchor \"/zapret-v6\" inet6 to !<nozapret6>"
}
pf_anchor_zapret_tables()
{
# $1 - variable to receive applied table names
# $2/$3 $4/$5 ... table_name/table_file
local tblv=$1
local _tbl
shift
[ "$MODE_FILTER" = "ipset" ] &&
{
while [ -n "$1" ] && [ -n "$2" ] ; do
[ -f "$2" ] && {
echo "table <$1> file \"$2\""
_tbl="$_tbl<$1> "
}
shift
shift
done
}
[ -n "$_tbl" ] || _tbl="any"
eval $tblv="\"\$_tbl\""
}
pf_anchor_port_target()
{
if [ "$MODE_HTTP" = "1" ] && [ "$MODE_HTTPS" = "1" ]; then
echo "{80,443}"
elif [ "$MODE_HTTPS" = "1" ]; then
echo "443"
elif [ "$MODE_HTTP" = "1" ]; then
echo "80"
fi
}
pf_anchor_zapret_v4_tpws()
{
# $1 - port
local rule port=$(pf_anchor_port_target)
for lan in $IFACE_LAN; do
for t in $tbl; do
echo "rdr on $lan inet proto tcp from any to $t port $port -> 127.0.0.1 port $1"
done
done
echo "rdr on lo0 inet proto tcp from !127.0.0.0/8 to any port $port -> 127.0.0.1 port $1"
for t in $tbl; do
rule="route-to (lo0 127.0.0.1) inet proto tcp from !127.0.0.0/8 to $t port $port user { >root }"
if [ -n "$IFACE_WAN" ] ; then
for wan in $IFACE_WAN; do
echo "pass out on $wan $rule"
done
else
echo "pass out $rule"
fi
done
}
pf_anchor_zapret_v4()
{
local tbl port
[ "$DISABLE_IPV4" = "1" ] || {
case $MODE in
tpws)
[ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ] && return
pf_anchor_zapret_tables tbl zapret-user "$ZIPLIST_USER" zapret "$ZIPLIST"
pf_anchor_zapret_v4_tpws $TPPORT
;;
custom)
pf_anchor_zapret_tables tbl zapret-user "$ZIPLIST_USER" zapret "$ZIPLIST"
existf zapret_custom_firewall_v4 && zapret_custom_firewall_v4
;;
esac
}
}
pf_anchor_zapret_v6_tpws()
{
# $1 - port
local LL_LAN rule port=$(pf_anchor_port_target)
# LAN link local is only for router
for lan in $IFACE_LAN; do
LL_LAN=$(get_ipv6_linklocal $lan)
[ -n "$LL_LAN" ] && {
for t in $tbl; do
echo "rdr on $lan inet6 proto tcp from any to $t port $port -> $LL_LAN port $1"
done
}
done
echo "rdr on lo0 inet6 proto tcp from !::1 to any port $port -> fe80::1 port $1"
for t in $tbl; do
rule="route-to (lo0 fe80::1) inet6 proto tcp from !::1 to $t port $port user { >root }"
if [ -n "$IFACE_WAN" ] ; then
for wan in $IFACE_WAN; do
echo "pass out on $wan $rule"
done
else
echo "pass out $rule"
fi
done
}
pf_anchor_zapret_v6()
{
local tbl port
[ "$DISABLE_IPV6" = "1" ] || {
case $MODE in
tpws)
[ ! "$MODE_HTTP" = "1" ] && [ ! "$MODE_HTTPS" = "1" ] && return
pf_anchor_zapret_tables tbl zapret6-user "$ZIPLIST_USER6" zapret6 "$ZIPLIST6"
pf_anchor_zapret_v6_tpws $TPPORT
;;
custom)
pf_anchor_zapret_tables tbl zapret6-user "$ZIPLIST_USER6" zapret6 "$ZIPLIST6"
existf zapret_custom_firewall_v6 && zapret_custom_firewall_v6
;;
esac
}
}
pf_anchors_create()
{
wait_lan_ll
pf_anchor_zapret >"$PF_ANCHOR_ZAPRET"
pf_anchor_zapret_v4 >"$PF_ANCHOR_ZAPRET_V4"
pf_anchor_zapret_v6 >"$PF_ANCHOR_ZAPRET_V6"
}
pf_anchors_del()
{
rm -f "$PF_ANCHOR_ZAPRET" "$PF_ANCHOR_ZAPRET_V4" "$PF_ANCHOR_ZAPRET_V6"
}
pf_anchors_load()
{
echo loading zapret anchor from "$PF_ANCHOR_ZAPRET"
pfctl -qa zapret -f "$PF_ANCHOR_ZAPRET" || {
echo error loading zapret anchor
return 1
}
if [ "$DISABLE_IPV4" = "1" ]; then
echo clearing zapret-v4 anchor
pfctl -qa zapret-v4 -F all 2>/dev/null
else
echo loading zapret-v4 anchor from "$PF_ANCHOR_ZAPRET_V4"
pfctl -qa zapret-v4 -f "$PF_ANCHOR_ZAPRET_V4" || {
echo error loading zapret-v4 anchor
return 1
}
fi
if [ "$DISABLE_IPV6" = "1" ]; then
echo clearing zapret-v6 anchor
pfctl -qa zapret-v6 -F all 2>/dev/null
else
echo loading zapret-v6 anchor from "$PF_ANCHOR_ZAPRET_V6"
pfctl -qa zapret-v6 -f "$PF_ANCHOR_ZAPRET_V6" || {
echo error loading zapret-v6 anchor
return 1
}
fi
echo successfully loaded PF anchors
return 0
}
pf_anchors_clear()
{
echo clearing zapret anchors
pfctl -qa zapret-v4 -F all 2>/dev/null
pfctl -qa zapret-v6 -F all 2>/dev/null
pfctl -qa zapret -F all 2>/dev/null
}
pf_enable()
{
echo enabling PF
pfctl -qe
}
pf_table_reload()
{
echo reloading zapret tables
[ "$DISABLE_IPV4" = "1" ] || pfctl -qTl -a zapret-v4 -f "$PF_ANCHOR_ZAPRET_V4"
[ "$DISABLE_IPV6" = "1" ] || pfctl -qTl -a zapret-v6 -f "$PF_ANCHOR_ZAPRET_V6"
pfctl -qTl -a zapret -f "$PF_ANCHOR_ZAPRET"
}

45
common/queue.sh Normal file
View File

@@ -0,0 +1,45 @@
get_nfqws_qnums()
{
# $1 - var name for ipv4 http
# $2 - var name for ipv4 https
# $3 - var name for ipv6 http
# $4 - var name for ipv6 https
local _qn _qns _qn6 _qns6
[ "$DISABLE_IPV4" = "1" ] || {
_qn=$QNUM
_qns=$_qn
[ "$NFQWS_OPT_DESYNC_HTTP" = "$NFQWS_OPT_DESYNC_HTTPS" ] || _qns=$(($QNUM+1))
}
[ "$DISABLE_IPV6" = "1" ] || {
_qn6=$(($QNUM+2))
_qns6=$(($QNUM+3))
[ "$DISABLE_IPV4" = "1" ] || {
if [ "$NFQWS_OPT_DESYNC_HTTP6" = "$NFQWS_OPT_DESYNC_HTTP" ]; then
_qn6=$_qn;
elif [ "$NFQWS_OPT_DESYNC_HTTP6" = "$NFQWS_OPT_DESYNC_HTTPS" ]; then
_qn6=$_qns;
fi
if [ "$NFQWS_OPT_DESYNC_HTTPS6" = "$NFQWS_OPT_DESYNC_HTTP" ]; then
_qns6=$_qn;
elif [ "$NFQWS_OPT_DESYNC_HTTPS6" = "$NFQWS_OPT_DESYNC_HTTPS" ]; then
_qns6=$_qns;
fi
}
[ "$NFQWS_OPT_DESYNC_HTTPS6" = "$NFQWS_OPT_DESYNC_HTTP6" ] && _qns6=$_qn6;
}
if [ "$MODE_HTTP" = 1 ]; then
eval $1=$_qn
eval $3=$_qn6
else
eval $1=
eval $3=
fi
if [ "$MODE_HTTPS" = 1 ]; then
eval $2=$_qns
eval $4=$_qns6
else
eval $2=
eval $4=
fi
}