#!/bin/sh # automated script for easy installing zapret EXEDIR="$(dirname "$0")" EXEDIR="$(cd "$EXEDIR"; pwd)" IPSET_DIR="$EXEDIR/ipset" ZAPRET_CONFIG="$EXEDIR/config" ZAPRET_BASE="$EXEDIR" . "$ZAPRET_CONFIG" # install target ZAPRET_TARGET=/opt/zapret GET_LIST="$IPSET_DIR/get_config.sh" GET_LIST_PREFIX=/ipset/get_ INIT_SCRIPT=/etc/init.d/zapret DNSCHECK_DNS="8.8.8.8 1.1.1.1 77.88.8.8" DNSCHECK_DOM="pornhub.com putinhuylo.com rutracker.org nnmclub.to kinozal.tv" DNSCHECK_DIG1=/tmp/dig1.txt DNSCHECK_DIG2=/tmp/dig2.txt DNSCHECK_DIGS=/tmp/digs.txt [ -n "$TPPORT" ] || TPPORT=988 SYSTEMD_SYSTEM_DIR=/lib/systemd/system [ -d "$SYSTEMD_SYSTEM_DIR" ] || SYSTEMD_SYSTEM_DIR=/usr/lib/systemd/system ECHON="echo -n" exists() { which $1 >/dev/null 2>/dev/null } whichq() { which $1 2>/dev/null } MD5=md5sum exists $MD5 || MD5=md5 contains() { # check if substring $2 contains in $1 [ "${1#*$2}" != "$1" ] } exitp() { local A echo echo press enter to continue read A exit $1 } require_root() { [ $(id -u) -ne "0" ] && { echo root is required exists sudo && exec sudo "$0" exists su && exec su -c "$0" echo su or sudo not found exitp 2 } } sedi() { # MacOS doesnt support -i without parameter. busybox doesnt support -i with parameter. # its not possible to put "sed -i ''" to a variable and then use it if [ "$SYSTEM" = "macos" ]; then sed -i '' "$@" else sed -i "$@" fi } read_yes_no() { # $1 - default (Y/N) local A read A [ -z "$A" ] || ([ "$A" != "Y" ] && [ "$A" != "y" ] && [ "$A" != "N" ] && [ "$A" != "n" ]) && A=$1 [ "$A" = "Y" ] || [ "$A" = "y" ] || [ "$A" = "1" ] } ask_yes_no() { # $1 - default (Y/N or 0/1) # $2 - text local DEFAULT=$1 [ "$1" = "1" ] && DEFAULT=Y [ "$1" = "0" ] && DEFAULT=N [ -z "$DEFAULT" ] && DEFAULT=N $ECHON "$2 (default : $DEFAULT) (Y/N) ? " read_yes_no $DEFAULT } ask_yes_no_var() { # $1 - variable name for answer : 0/1 # $2 - text local DEFAULT eval DEFAULT="\$$1" if ask_yes_no "$DEFAULT" "$2"; then eval $1=1 else eval $1=0 fi } on_off_function() { # $1 : function name on # $2 : function name off # $3 : 0 - off, 1 - on local F="$1" [ "$3" = "1" ] || F="$2" shift shift shift "$F" "$@" } get_dir_inode() { local dir="$1" [ -L "$dir" ] && dir=$(readlink "$dir") ls -id "$dir" | awk '{print $1}' } random() { # $1 - min, $2 - max local r rs if [ -c /dev/urandom ]; then read rs /dev/null) [ -z "$M" ] && M="$M_DEFAULT" echo selected : $M eval $1="\"$M\"" [ "$M" != "$M_OLD" ] } write_config_var() { # $1 - mode var local M eval M="\$$1" if grep -q "^$1=\|^#$1=" "$ZAPRET_CONFIG"; then # replace / => \/ #M=${M//\//\\\/} M=$(echo $M | sed 's/\//\\\//g') if [ -n "$M" ]; then if contains "$M" " "; then sedi -Ee "s/^#?$1=.*$/$1=\"$M\"/" "$ZAPRET_CONFIG" else sedi -Ee "s/^#?$1=.*$/$1=$M/" "$ZAPRET_CONFIG" fi else # write with comment at the beginning sedi -Ee "s/^#?$1=.*$/#$1=/" "$ZAPRET_CONFIG" fi else # var does not exist in config. add it if [ -n "$M" ]; then echo "$1=$M" >>"$ZAPRET_CONFIG" else echo "#$1=$M" >>"$ZAPRET_CONFIG" fi fi } select_mode_mode() { local MODES="tpws tpws-socks nfqws filter custom" [ "$SYSTEM" = "macos" ] && MODES="tpws tpws-socks filter custom" echo echo select MODE : ask_list MODE "$MODES" tpws && write_config_var MODE case $MODE in tpws) echo echo tpws options : $TPWS_OPT echo to change : edit TPWS_OPT in $ZAPRET_CONFIG ;; nfqws) echo echo "nfqws options (default) : $NFQWS_OPT_DESYNC" echo "nfqws options (http) : $NFQWS_OPT_DESYNC_HTTP" echo "nfqws options (https) : $NFQWS_OPT_DESYNC_HTTPS" echo to change : edit NFQWS_OPT_DESYNC, NFQWS_OPT_DESYNC_HTTP, NFQWS_OPT_DESYNC_HTTPS in $ZAPRET_CONFIG ;; esac } select_mode_http() { [ "$MODE" != "filter" ] && [ "$MODE" != "tpws-socks" ] && { echo ask_yes_no_var MODE_HTTP "enable http support" write_config_var MODE_HTTP } } select_mode_keepalive() { [ "$MODE" = "nfqws" ] && [ "$MODE_HTTP" = "1" ] && { echo echo enable keep alive support only if DPI checks every outgoing packet for http signature echo dont enable otherwise because it consumes more cpu resources ask_yes_no_var MODE_HTTP_KEEPALIVE "enable http keep alive support" write_config_var MODE_HTTP_KEEPALIVE } } select_mode_https() { [ "$MODE" != "filter" ] && [ "$MODE" != "tpws-socks" ] && { echo ask_yes_no_var MODE_HTTPS "enable https support" write_config_var MODE_HTTPS } } select_mode_filter() { local filter="none ipset hostlist" [ "$MODE" = "tpws-socks" ] && filter="none hostlist" echo echo select filtering : ask_list MODE_FILTER "$filter" none && write_config_var MODE_FILTER } select_mode() { select_mode_mode select_mode_iface select_mode_http select_mode_keepalive select_mode_https select_mode_filter } select_getlist() { if [ "$MODE_FILTER" = "ipset" -o "$MODE_FILTER" = "hostlist" ]; 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" ] ; then local GL_OLD=$GETLIST GETLIST="get_reestr_hostlist.sh" [ "$GL_OLD" != "$GET_LIST" ] && write_config_var GETLIST else GETLISTS="get_user.sh get_antifilter_ip.sh get_antifilter_ipsmart.sh get_antifilter_ipsum.sh get_reestr_ip.sh get_reestr_combined.sh get_reestr_resolve.sh" GETLIST_DEF="get_antifilter_ipsmart.sh" ask_list GETLIST "$GETLISTS" "$GETLIST_DEF" && write_config_var GETLIST fi return fi fi GETLIST="" write_config_var GETLIST } 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 } ask_config() { select_mode select_getlist } ask_config_offload() { is_flow_offload_avail && { echo echo flow offloading can greatly increase speed on slow devices and high speed links \(usually 150+ mbits\) echo unfortuantely its not compatible with most nfqws options. nfqws traffic must be exempted from flow offloading. 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 echo select flow offloading : ask_list FLOWOFFLOAD "donttouch none software hardware" donttouch && write_config_var FLOWOFFLOAD } } get_free_space_mb() { df -m $PWD | awk '/[0-9]%/{print $(NF-2)}' } get_ram_kb() { grep MemTotal /proc/meminfo | awk '{print $2}' } get_ram_mb() { local R=$(get_ram_kb) echo $(($R/1024)) } ask_config_tmpdir() { # ask tmpdir change for low ram systems with enough free disk space [ -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 } } } 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 " case $SYSTEM in macos) ifs="$(ifconfig -l)" ;; *) ifs="$(ls /sys/class/net)" ;; esac [ -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 : ask_iface IFACE_LAN "NONE" } ask_iface_wan() { echo WAN interface : ask_iface IFACE_WAN "ANY" } select_mode_iface() { # openwrt has its own interface management scheme # filter just creates ip tables, no daemons involved # nfqws sits in POSTROUTING chain and unable to filter by incoming interface # tpws redirection works in PREROUTING chain # in tpws-socks mode IFACE_LAN specifies additional bind interface for the socks listener # it's not possible to instruct tpws to route outgoing connection to an interface (OS routing table decides) # custom mode can also benefit from interface names (depends on custom script code) if [ "$SYSTEM" = "openwrt" ] || [ "$MODE" = "filter" ]; then return; fi echo case "$MODE" in tpws-socks) echo "select LAN interface to allow socks access from your LAN. select NONE for localhost only." echo "expect socks on tcp port $TPPORT" ask_iface_lan ;; tpws) echo "select LAN interface to operate in router mode. select NONE for local outgoing traffic only." if [ "$SYSTEM" = "macos" ]; then echo "WARNING ! OS feature \"internet sharing\" is not supported." echo "Only manually configured PF router is supported." else echo "WARNING ! This installer will not configure routing, NAT, ... for you. Its your responsibility." fi ask_iface_lan ;; custom) echo "select LAN interface for your custom script (how it works depends on your code)" ask_iface_lan ;; esac case "$MODE" in tpws) echo "select WAN interface for $MODE operations. select ANY to operate on any interface." [ -n "$IFACE_LAN" ] && echo "WAN filtering works only for local outgoing traffic !" ask_iface_wan ;; nfqws) echo "select WAN interface for $MODE operations. select ANY to operate on any interface." ask_iface_wan ;; custom) echo "select WAN interface for your custom script (how it works depends on your code)" ask_iface_wan ;; esac } copy_all() { cp -R "$1" "$2" [ -d "$2/tmp" ] || mkdir "$2/tmp" } copy_openwrt() { local ARCH=$(get_bin_arch) local BINDIR="$1/binaries/$ARCH" [ -d "$2" ] || mkdir -p "$2" mkdir "$2/tpws" "$2/nfq" "$2/ip2net" "$2/mdig" "$2/binaries" "$2/binaries/$ARCH" "$2/init.d" "$2/tmp" cp -R "$1/ipset" "$2" cp -R "$1/init.d/openwrt" "$2/init.d" cp "$1/config" "$1/install_easy.sh" "$1/uninstall_easy.sh" "$1/install_bin.sh" "$2" cp "$BINDIR/tpws" "$BINDIR/nfqws" "$BINDIR/ip2net" "$BINDIR/mdig" "$2/binaries/$ARCH" } _backup_settings() { local i=0 for f in "$@"; do [ -f "$ZAPRET_TARGET/$f" ] && cp -f "$ZAPRET_TARGET/$f" "/tmp/zapret-bkp-$i" i=$(($i+1)) done } _restore_settings() { local i=0 for f in "$@"; do [ -f "/tmp/zapret-bkp-$i" ] && mv -f "/tmp/zapret-bkp-$i" "$ZAPRET_TARGET/$f" || rm -f "/tmp/zapret-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" "init.d/openwrt/custom" "init.d/macos/custom" "ipset/zapret-hosts-user.txt" "ipset/zapret-hosts-user-exclude.txt" "ipset/zapret-hosts-user-ipban.txt" } check_location() { # $1 - copy function echo \* checking location # use inodes in case something is linked [ -d "$ZAPRET_TARGET" ] && [ $(get_dir_inode "$EXEDIR") = $(get_dir_inode "$ZAPRET_TARGET") ] || { 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 ask_yes_no Y "keep config, custom scripts and user lists" && keep=Y [ "$keep" = "Y" ] && backup_restore_settings 1 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" [ "$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 } echo running from $EXEDIR } check_prerequisites_linux() { echo \* checking prerequisites if exists ipset && exists curl ; then echo everything is present else echo \* installing prerequisites APTGET=$(whichq apt-get) YUM=$(whichq yum) PACMAN=$(whichq pacman) ZYPPER=$(whichq zypper) EOPKG=$(whichq eopkg) if [ -x "$APTGET" ] ; then "$APTGET" update "$APTGET" install -y --no-install-recommends ipset curl dnsutils || { echo could not install prerequisites exitp 6 } elif [ -x "$YUM" ] ; then "$YUM" -y install curl ipset || { echo could not install prerequisites exitp 6 } elif [ -x "$PACMAN" ] ; then "$PACMAN" -Syy "$PACMAN" --noconfirm -S ipset curl || { echo could not install prerequisites exitp 6 } elif [ -x "$ZYPPER" ] ; then "$ZYPPER" --non-interactive install ipset curl || { echo could not install prerequisites exitp 6 } elif [ -x "$EOPKG" ] ; then "$EOPKG" -y install ipset curl || { echo could not install prerequisites exitp 6 } else echo supported package manager not found echo you must manually install : ipset curl exitp 5 fi fi } service_install_systemd() { echo \* installing zapret service rm -f "$INIT_SCRIPT" ln -fs "$EXEDIR/init.d/systemd/zapret.service" "$SYSTEMD_SYSTEM_DIR" "$SYSTEMCTL" daemon-reload "$SYSTEMCTL" enable zapret || { echo could not enable systemd service exitp 20 } } service_stop_systemd() { echo \* stopping zapret service "$SYSTEMCTL" daemon-reload "$SYSTEMCTL" disable zapret "$SYSTEMCTL" stop zapret } service_start_systemd() { echo \* starting zapret service "$SYSTEMCTL" start zapret || { echo could not start zapret service exitp 30 } } timer_install_systemd() { echo \* installing zapret-list-update timer "$SYSTEMCTL" disable zapret-list-update.timer "$SYSTEMCTL" stop zapret-list-update.timer ln -fs "$EXEDIR/init.d/systemd/zapret-list-update.service" "$SYSTEMD_SYSTEM_DIR" ln -fs "$EXEDIR/init.d/systemd/zapret-list-update.timer" "$SYSTEMD_SYSTEM_DIR" "$SYSTEMCTL" daemon-reload "$SYSTEMCTL" enable zapret-list-update.timer || { echo could not enable zapret-list-update.timer exitp 20 } "$SYSTEMCTL" start zapret-list-update.timer || { echo could not start zapret-list-update.timer exitp 30 } } download_list() { [ -x "$GET_LIST" ] && { echo \* downloading blocked ip/host list # can be txt or txt.gz "$IPSET_DIR/clear_lists.sh" "$GET_LIST" || { echo could not download ip list exitp 25 } } } end_with_newline() { local c=$(tail -c 1) [ "$c" = "" ] } crontab_del_quiet() { exists crontab || return CRONTMP=/tmp/cron.tmp crontab -l >$CRONTMP 2>/dev/null if grep -q "$GET_LIST_PREFIX" $CRONTMP; then grep -v "$GET_LIST_PREFIX" $CRONTMP >$CRONTMP.2 crontab $CRONTMP.2 rm -f $CRONTMP.2 fi rm -f $CRONTMP } crontab_add() { # $1 - hour min # $2 - hour max [ -x "$GET_LIST" ] && { echo \* adding crontab entry 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 } } 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 } } pingtest() { ping -c 1 -W 1 $1 >/dev/null } find_working_public_dns() { for dns in $DNSCHECK_DNS; do pingtest $dns && nslookup w3.org $dns >/dev/null 2>/dev/null && { PUBDNS=$dns return 0 } done return 1 } check_dns_spoof() { # $1 - domain # $2 - public DNS echo $1 | "$EXEDIR/mdig/mdig" --family=4 >"$DNSCHECK_DIG1" nslookup $1 $2 | sed -n '/Name:/,$p' | grep ^Address | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' >"$DNSCHECK_DIG2" # check whether system resolver returns anything other than public DNS grep -qvFf "$DNSCHECK_DIG2" "$DNSCHECK_DIG1" } check_dns_cleanup() { rm -f "$DNSCHECK_DIG1" "$DNSCHECK_DIG2" "$DNSCHECK_DIGS" 2>/dev/null } check_dns() { local C1 C2 echo \* checking DNS [ -f "$DNSCHECK_DIGS" ] && rm -f "$DNSCHECK_DIGS" if find_working_public_dns ; then echo comparing system resolver to public DNS : $PUBDNS for dom in $DNSCHECK_DOM; do if check_dns_spoof $dom $PUBDNS ; then echo $dom : MISMATCH echo -- system resolver : cat "$DNSCHECK_DIG1" echo -- $PUBDNS : cat "$DNSCHECK_DIG2" check_dns_cleanup echo -- POSSIBLE DNS HIJACK DETECTED. ZAPRET WILL NOT HELP YOU IN CASE DNS IS SPOOFED !!! echo -- DNS CHANGE OR DNSCRYPT MAY BE REQUIRED return 1 else echo $dom : OK cat "$DNSCHECK_DIG1" >>"$DNSCHECK_DIGS" fi done else echo no working public DNS was found. looks like public DNS blocked. for dom in $DNSCHECK_DOM; do echo $dom; done | "$EXEDIR/mdig/mdig" --threads=10 --family=4 >"$DNSCHECK_DIGS" fi echo checking resolved IP uniqueness for : $DNSCHECK_DOM echo censor\'s DNS can return equal result for multiple blocked domains. C1=$(wc -l <"$DNSCHECK_DIGS") C2=$(sort -u "$DNSCHECK_DIGS" | wc -l) [ "$C1" -eq 0 ] && { echo -- DNS is not working. It's either misconfigured or blocked or you don't have inet access. check_dns_cleanup return 1 } [ "$C1" = "$C2" ] || { echo system dns resolver has returned equal IPs for some domains checked above \($C1 total, $C2 unique\) echo non-unique IPs : sort "$DNSCHECK_DIGS" | uniq -d echo -- POSSIBLE DNS HIJACK DETECTED. ZAPRET WILL NOT HELP YOU IN CASE DNS IS SPOOFED !!! echo -- DNSCRYPT MAY BE REQUIRED check_dns_cleanup return 1 } echo all resolved IPs are unique echo -- DNS looks good echo -- NOTE this check is Russia targeted. In your country other domains may be blocked. check_dns_cleanup return 0 } install_systemd() { INIT_SCRIPT_SRC="$EXEDIR/init.d/sysv/zapret" check_bins require_root check_location copy_all check_prerequisites_linux service_stop_systemd install_binaries check_dns select_ipv6 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 } check_kmod() { [ -f "/lib/modules/$(uname -r)/$1.ko" ] } check_package_exists_openwrt() { [ -n "$(opkg list $1)" ] } check_package_openwrt() { [ -n "$(opkg list-installed $1)" ] } check_packages_openwrt() { for pkg in $@; do check_package_openwrt $pkg || return done } is_linked_to_busybox() { local F P F=/usr/bin/$1 P="$(readlink $F)" if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi [ "${P%busybox*}" != "$P" ] && return F=/bin/$1 P="$(readlink $F)" if [ -z "$P" ] && [ -x $F ] && [ ! -L $F ]; then return 1; fi [ "${P%busybox*}" != "$P" ] } check_prerequisites_openwrt() { echo \* checking prerequisites local PKGS="iptables-mod-extra iptables-mod-nfqueue iptables-mod-filter iptables-mod-ipopt iptables-mod-conntrack-extra ipset curl" [ "$DISABLE_IPV6" != "1" ] && PKGS="$PKGS ip6tables-mod-nat" local UPD=0 if check_packages_openwrt $PKGS ; then echo everything is present else echo \* installing prerequisites opkg update UPD=1 opkg 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" ] && { opkg update UPD=1 } opkg 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" ] && { opkg update UPD=1 } opkg install --force-overwrite coreutils-sort fi } is_linked_to_busybox grep && { echo echo your system uses default busybox grep. its damn infinite slow with -f option echo get_combined.sh will be severely impacted echo installer can install GNU grep but it requires about 0.5 Mb space if ask_yes_no N "do you want to install GNU grep"; then [ "$UPD" = "0" ] && { opkg update UPD=1 } opkg install --force-overwrite grep # someone reported device partially fail if /bin/grep is absent # grep package deletes /bin/grep [ -f /bin/grep ] || ln -s busybox /bin/grep fi } } openwrt_fw_section_find() { # $1 - fw include postfix # echoes section number i=0 while true do path=$(uci -q get firewall.@include[$i].path) [ -n "$path" ] || break [ "$path" = "$OPENWRT_FW_INCLUDE$1" ] && { echo $i return 0 } i=$(($i+1)) done return 1 } openwrt_fw_section_del() { # $1 - fw include postfix local id=$(openwrt_fw_section_find $1) [ -n "$id" ] && { uci delete firewall.@include[$id] && uci commit firewall rm -f "$OPENWRT_FW_INCLUDE$1" } } openwrt_fw_section_add() { openwrt_fw_section_find || { uci add firewall include >/dev/null || return echo -1 } } openwrt_fw_section_configure() { local id=$(openwrt_fw_section_add $1) [ -z "$id" ] || ! uci set firewall.@include[$id].path="$OPENWRT_FW_INCLUDE" || ! uci set firewall.@include[$id].reload="1" || ! uci commit firewall && { echo could not add firewall include exitp 50 } } install_openwrt_firewall() { echo \* installing firewall script $1 [ -n "MODE" ] || { echo should specify MODE in $ZAPRET_CONFIG exitp 7 } echo "linking : $FW_SCRIPT_SRC => $OPENWRT_FW_INCLUDE" ln -fs "$FW_SCRIPT_SRC" "$OPENWRT_FW_INCLUDE" openwrt_fw_section_configure $1 } restart_openwrt_firewall() { echo \* restarting firewall fw3 -q restart || { echo could not restart firewall exitp 30 } } remove_openwrt_firewall() { echo \* removing firewall script openwrt_fw_section_del # from old zapret versions. now we use single include openwrt_fw_section_del 6 # free some RAM "$IPSET_DIR/create_ipset.sh" clear } install_openwrt_iface_hook() { echo \* installing ifup hook ln -fs "$OPENWRT_IFACE_HOOK" /etc/hotplug.d/iface } is_flow_offload_avail() { # $1 = '' for ipv4, '6' for ipv6 grep -q FLOWOFFLOAD /proc/net/ip$1_tables_targets } deoffload_openwrt_firewall() { echo \* checking flow offloading is_flow_offload_avail || { echo unavailable return } local fo=$(uci -q get firewall.@defaults[0].flow_offloading) if [ "$fo" = "1" ] ; then local mod=0 $ECHON "system wide flow offloading detected. " case $FLOWOFFLOAD in donttouch) if [ "$MODE" = "nfqws" ]; then echo its incompatible with nfqws tcp data tampering. disabling uci set firewall.@defaults[0].flow_offloading=0 mod=1 else if [ "$MODE" = "custom" ] ; then echo custom mode selected !!! only you can decide whether flow offloading is compatible 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_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 } service_start_sysv() { echo \* starting zapret service "$INIT_SCRIPT" start || { echo could not start zapret service exitp 30 } } install_openwrt() { INIT_SCRIPT_SRC="$EXEDIR/init.d/openwrt/zapret" FW_SCRIPT_SRC="$EXEDIR/init.d/openwrt/firewall.zapret" OPENWRT_FW_INCLUDE=/etc/firewall.zapret OPENWRT_IFACE_HOOK="$EXEDIR/init.d/openwrt/90-zapret" check_bins require_root check_location copy_openwrt install_binaries check_dns select_ipv6 check_prerequisites_openwrt ask_config ask_config_tmpdir ask_config_offload install_sysv_init # can be previous firewall preventing access remove_openwrt_firewall restart_openwrt_firewall download_list crontab_del_quiet # router system : works 24/7. night is the best time crontab_add 0 6 cron_ensure_running service_start_sysv install_openwrt_iface_hook install_openwrt_firewall deoffload_openwrt_firewall restart_openwrt_firewall } remove_pf_zapret_hooks() { echo \* removing zapret PF hooks pf_anchors_clear } service_install_macos() { echo \* installing zapret service ln -fs /opt/zapret/init.d/macos/zapret.plist /Library/LaunchDaemons } service_start_macos() { echo \* starting zapret service "$INIT_SCRIPT_SRC" start } service_stop_macos() { echo \* stopping zapret service "$INIT_SCRIPT_SRC" stop } macos_fw_reload_trigger_clear() { case "$MODE" in tpws|tpws-socks|custom) LISTS_RELOAD= write_config_var LISTS_RELOAD ;; esac } macos_fw_reload_trigger_set() { case "$MODE" in tpws|custom) LISTS_RELOAD="$INIT_SCRIPT_SRC reload-fw-tables" write_config_var LISTS_RELOAD ;; esac } install_macos() { INIT_SCRIPT_SRC="$EXEDIR/init.d/macos/zapret" # compile before root check_bins require_root check_location copy_all service_stop_macos remove_pf_zapret_hooks install_binaries check_dns select_ipv6 ask_config service_install_macos macos_fw_reload_trigger_clear # gzip lists are incompatible with PF GZIP_LISTS=0 write_config_var GZIP_LISTS download_list macos_fw_reload_trigger_set crontab_del_quiet # desktop system. more likely up at daytime crontab_add 10 22 service_start_macos } # build binaries, do not use precompiled [ "$1" = "make" ] && FORCE_BUILD=1 check_system [ "$SYSTEM" = "macos" ] && . "$EXEDIR/init.d/macos/functions" case $SYSTEM in systemd) install_systemd ;; openwrt) install_openwrt ;; macos) install_macos ;; esac exitp 0