# init script functions library for desktop linux systems [ -n "$ZAPRET_BASE" ] || ZAPRET_BASE=/opt/zapret # SHOULD EDIT config . "$ZAPRET_BASE/config" PIDDIR=/var/run IPSET_CR=$ZAPRET_BASE/ipset/create_ipset.sh WS_USER=tpws QNUM=200 NFQWS=$ZAPRET_BASE/nfq/nfqws NFQWS_OPT_BASE="--qnum=$QNUM --user=$WS_USER" TPPORT_HTTP=1188 TPPORT_HTTPS=1189 TPWS=$ZAPRET_BASE/tpws/tpws TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts.txt.gz [ -f "$TPWS_HOSTLIST" ] || TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts-user.txt TPWS_OPT_BASE="--user=$WS_USER --bind-addr=127.0.0.1" TPWS_OPT_BASE6="--user=$WS_USER --bind-addr=::1" # first wait for lan to ifup, then wait for bind-wait-ip-linklocal seconds for link local address and bind-wait-ip for any ipv6 as the worst case TPWS_OPT_BASE6_PRE="--user=$WS_USER --bind-linklocal=prefer --bind-wait-ifup=30 --bind-wait-ip=30 --bind-wait-ip-linklocal=3" TPWS_OPT_BASE_HTTP="--port=$TPPORT_HTTP" TPWS_OPT_BASE_HTTPS="--port=$TPPORT_HTTPS" [ -n "$IFACE_WAN" ] && IPT_OWAN="-o $IFACE_WAN" [ -n "$IFACE_WAN" ] && IPT_IWAN="-i $IFACE_WAN" [ -n "$IFACE_LAN" ] && IPT_ILAN="-i $IFACE_LAN" # max wait time for the link local ipv6 on the LAN interface LINKLOCAL_WAIT_SEC=5 exists() { which $1 >/dev/null 2>/dev/null } on_off_function() { # $1 : function name on # $2 : function name off # $3 : 0 - off, 1 - on local F="$1" [ "$3" = "1" ] || F="$2" shift shift shift "$F" "$@" } ipt() { iptables -C "$@" 2>/dev/null || iptables -I "$@" } ipt_del() { iptables -C "$@" 2>/dev/null && iptables -D "$@" } ipt_add_del() { on_off_function ipt ipt_del "$@" } ipt6() { ip6tables -C "$@" 2>/dev/null || ip6tables -I "$@" } ipt6_del() { ip6tables -C "$@" 2>/dev/null && ip6tables -D "$@" } ipt6_add_del() { on_off_function ipt6 ipt6_del "$@" } # there's no route_localnet for ipv6 # the best we can is to route to link local of the incoming interface # OUTPUT - can DNAT to ::1 # PREROUTING - can't DNAT to ::1. can DNAT to link local of -i interface or to any global addr # not a good idea to expose tpws to the world (bind to ::) get_ipv6_linklocal() { # $1 - interface name. if empty - any interface local dev [ -n "$1" ] && dev="dev $1" ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope link.*$/\1/;t;d' | head -n 1 } get_ipv6_global() { # $1 - interface name. if empty - any interface local dev [ -n "$1" ] && dev="dev $1" ip addr show $dev | sed -e 's/^.*inet6 \([^ ]*\)\/[0-9]* scope global.*$/\1/;t;d' | head -n 1 } iface_is_up() { # $1 - interface name [ -f /sys/class/net/$1/operstate ] || return local state read state /dev/null; then echo already running else "$2" $3 >/dev/null 2>/dev/null & PID=$! if [ -n "$PID" ]; then echo $PID >$PIDFILE else echo could not start daemon $1 : $2 $3 false fi fi fi } stop_daemon() { # $1 - daemon number : 1,2,3,... # $2 - daemon # use $PIDDIR/$DAEMONBASE$1.pid as pidfile local DAEMONBASE=$(basename $2) local PIDFILE=$PIDDIR/$DAEMONBASE$1.pid echo "Stopping daemon $1: $2" if exists start-stop-daemon ; then start-stop-daemon --stop --pidfile "$PIDFILE" --exec "$2" else if [ -f "$PIDFILE" ]; then read PID <"$PIDFILE" kill $PID rm -f "$PIDFILE" else echo no pidfile : $PIDFILE fi fi } do_daemon() { # $1 - 1 - run, 0 - stop on_off_function run_daemon stop_daemon "$@" } prepare_user() { # $WS_USER is required to prevent redirection of the traffic originating from TPWS itself # otherwise infinite loop will occur # also its good idea not to run tpws as root id -u $WS_USER >/dev/null 2>/dev/null || useradd --no-create-home --system --shell /bin/false $WS_USER } prepare_tpws() { prepare_user # otherwise linux kernel will treat 127.0.0.1 as "martian" ip and refuse routing to it # NOTE : kernels <3.6 do not have this feature. consider upgrading or change DNAT to REDIRECT and do not bind to 127.0.0.1 [ -n "$IFACE_LAN" ] && sysctl -qw net.ipv4.conf.$IFACE_LAN.route_localnet=1 } prepare_nfqws() { prepare_user } do_tpws() { # $1 : 1 - run, 0 - stop # $2 : daemon number # $3 : daemon args [ "$1" = "1" ] && prepare_tpws [ "$DISABLE_IPV4" = "1" ] || do_daemon $1 $2 $TPWS "$TPWS_OPT_BASE $3" [ "$DISABLE_IPV6" = "1" ] || { do_daemon $1 $((60+$2)) $TPWS "$TPWS_OPT_BASE6 $3" [ -n "$IFACE_LAN" ] && do_daemon $1 $((660+$2)) $TPWS "$TPWS_OPT_BASE6_PRE --bind-iface6=$IFACE_LAN $3" } } do_nfqws() { # $1 : 1 - run, 0 - stop # $2 : daemon number # $3 : daemon args [ "$1" = "1" ] && prepare_nfqws do_daemon $1 $2 $NFQWS "$NFQWS_OPT_BASE $3" } create_ipset() { echo "Creating ipset" "$IPSET_CR" "$@" } zapret_do_firewall() { # $1 - 1 - add, 0 - del case "${MODE}" in tpws_hostlist) [ "$1" = "1" ] && prepare_tpws fw_tpws $1 "--dport 80" "--dport 80" $TPPORT_HTTP ;; tpws_ipset) [ "$1" = "1" ] && create_ipset [ "$1" = "1" ] && prepare_tpws fw_tpws $1 "--dport 80 -m set --match-set zapret dst" "--dport 80 -m set --match-set zapret6 dst" $TPPORT_HTTP ;; tpws_ipset_https) [ "$1" = "1" ] && create_ipset [ "$1" = "1" ] && prepare_tpws fw_tpws $1 "--dport 80 -m set --match-set zapret dst" "--dport 80 -m set --match-set zapret6 dst" $TPPORT_HTTP fw_tpws $1 "--dport 443 -m set --match-set zapret dst" "--dport 443 -m set --match-set zapret6 dst" $TPPORT_HTTPS ;; tpws_all) [ "$1" = "1" ] && prepare_tpws fw_tpws $1 "--dport 80" "--dport 80" $TPPORT_HTTP ;; tpws_all_https) [ "$1" = "1" ] && prepare_tpws fw_tpws $1 "--dport 80" "--dport 80" $TPPORT_HTTP fw_tpws $1 "--dport 443" "--dport 443" $TPPORT_HTTPS ;; nfqws_ipset) [ "$1" = "1" ] && create_ipset fw_nfqws_pre $1 "--sport 80 -m set --match-set zapret src" "--sport 80 -m set --match-set zapret6 src" $QNUM fw_nfqws_post $1 "--dport 80 -m set --match-set zapret dst" "--dport 80 -m set --match-set zapret6 dst" $QNUM ;; nfqws_ipset_https) [ "$1" = "1" ] && create_ipset fw_nfqws_pre $1 "-m multiport --sports 80,443 -m set --match-set zapret src" "-m multiport --sports 80,443 -m set --match-set zapret6 src" $QNUM fw_nfqws_post $1 "--dport 80 -m set --match-set zapret dst" "--dport 80 -m set --match-set zapret6 dst" $QNUM ;; nfqws_all) fw_nfqws_pre $1 "--sport 80" "--sport 80" $QNUM fw_nfqws_post $1 "--dport 80" "--dport 80" $QNUM ;; nfqws_all_https) fw_nfqws_pre $1 "-m multiport --sports 80,443" "-m multiport --sports 80,443" $QNUM fw_nfqws_post $1 "--dport 80" "--dport 80" $QNUM ;; ipset) [ "$1" != "1" ] || create_ipset ;; custom) # PLACEHOLDER echo !!! NEED ATTENTION !!! echo Configure iptables for required actions echo Study how other sections work ;; esac } zapret_apply_firewall() { zapret_do_firewall 1 "$@" } zapret_unapply_firewall() { zapret_do_firewall 0 "$@" } zapret_do_daemons() { # $1 - 1 - run, 0 - stop case "${MODE}" in tpws_hostlist) do_tpws $1 1 "$TPWS_OPT_BASE_HTTP $TPWS_OPT_HTTP --hostlist=$TPWS_HOSTLIST" ;; tpws_ipset) do_tpws $1 1 "$TPWS_OPT_BASE_HTTP $TPWS_OPT_HTTP" ;; tpws_ipset_https|tpws_all_https) do_tpws $1 1 "$TPWS_OPT_BASE_HTTP $TPWS_OPT_HTTP" do_tpws $1 2 "$TPWS_OPT_BASE_HTTPS $TPWS_OPT_HTTPS" ;; tpws_all) do_tpws $1 1 "$TPWS_OPT_BASE_HTTP $TPWS_OPT_HTTP" ;; nfqws_ipset|nfqws_ipset_https|nfqws_all|nfqws_all_https) do_nfqws $1 1 "$NFQWS_OPT" ;; custom) # PLACEHOLDER echo !!! NEED ATTENTION !!! echo Start daemon\(s\) echo Study how other sections work do_daemon $1 1 /bin/sleep 20 ;; esac } zapret_run_daemons() { zapret_do_daemons 1 "$@" } zapret_stop_daemons() { zapret_do_daemons 0 "$@" }