From 44f9878655aa2805a3b315979628e674cfe7d8b4 Mon Sep 17 00:00:00 2001 From: bol-van Date: Thu, 14 Mar 2024 16:44:08 +0300 Subject: [PATCH] blockcheck: use socks mode for tpws tests --- blockcheck.sh | 145 ++++++++++++++++++-------------------------------- 1 file changed, 52 insertions(+), 93 deletions(-) diff --git a/blockcheck.sh b/blockcheck.sh index 0cf8b13..5b51c1d 100755 --- a/blockcheck.sh +++ b/blockcheck.sh @@ -12,7 +12,7 @@ ZAPRET_BASE="$EXEDIR" . "$ZAPRET_BASE/common/virt.sh" [ -n "$QNUM" ] || QNUM=59780 -[ -n "$TPPORT" ] || TPPORT=993 +[ -n "$SOCKS_PORT" ] || SOCKS_PORT=1993 [ -n "$TPWS_UID" ] || TPWS_UID=1 [ -n "$TPWS_GID" ] || TPWS_GID=3003 [ -n "$NFQWS" ] || NFQWS="$ZAPRET_BASE/nfq/nfqws" @@ -41,7 +41,7 @@ DNSCHECK_DIGS=/tmp/digs.txt unset PF_STATUS PF_RULES_SAVE=/tmp/pf-zapret-save.conf -CURL=curl +unset ALL_PROXY killwait() { @@ -123,26 +123,6 @@ opf_prepare_dvtws() opf_dvtws_anchor $1 | pfctl -qf - pfctl -qe } -mpf_tpws_anchor() -{ - # $1 - port - case "$IPV" in - 4) - echo "rdr pass on $LO_IFACE inet proto tcp from \!127.0.0.0/8 to any port $1 -> $LINKLOCAL port $TPPORT" - echo "pass out route-to ($LO_IFACE $LINKLOCAL) inet proto tcp from any to any port $1 user { >root }" - ;; - 6) - echo "rdr pass on $LO_IFACE inet6 proto tcp from \!::1 to any port $1 -> $LINKLOCAL port $TPPORT" - echo "pass out route-to ($LO_IFACE $LINKLOCAL) inet6 proto tcp from any to any port $1 user { >root }" - ;; - esac -} -mpf_prepare_tpws() -{ - # $1 - port - mpf_tpws_anchor $1 | pfctl -qf - - pfctl -qe -} cleanup() { @@ -197,6 +177,13 @@ nft_has_nfq() return $res } +mdig_resolve() +{ + # $1 - ip version 4/6 + # $2 - hostname + echo "$2" | "$MDIG" --family=$1 | head -n 1 +} + check_system() { echo \* checking system @@ -234,10 +221,6 @@ check_system() PKTWS="$DVTWS" PKTWSD=dvtws FWTYPE=mpf - # will not redirect traffic for root - CURL="sudo -u nobody curl" - # /dev/pf requires root. hardcoded in kernel - TPWS_UID=0 LO_IFACE=lo0 ;; *) @@ -308,11 +291,6 @@ check_prerequisites() echo pf is not available exitp 6 } - # I dont know how to redirect traffic originating from the host itself - # even with route-to trick DIOCNATLOOK fails, thus making tpws unusable - # this trick works fine on MacOS but doesn't work on FreeBSD and OpenBSD - # socks version is also not a solution because I can't control ip version of the resolved domain - [ "$UNAME" = "OpenBSD" ] && SKIP_TPWS=1 # no divert sockets in MacOS [ "$UNAME" = "Darwin" ] && SKIP_PKTWS=1 pf_save @@ -393,6 +371,12 @@ curl_supports_tlsmax() [ $? != 2 ] } +curl_supports_connect_to() +{ + curl --connect-to 127.0.0.1:: -o /dev/null http://127.0.0.1:65535 2>/dev/null + [ "$?" != 2 ] +} + hdrfile_http_code() { # $1 - hdr file @@ -405,12 +389,34 @@ hdrfile_location() # some DPIs return CRLF line ending tr -d '\015' <"$1" | sed -nre 's/^[Ll][Oo][Cc][Aa][Tt][Ii][Oo][Nn]:[ ]*([^ ]*)[ ]*$/\1/p' } + +curl_connect_to() +{ + # $1 - ip version : 4/6 + # $2 - domain name + local ip=$(mdig_resolve $1 $2) + [ -n "$ip" ] && echo "--connect-to $2::[$ip]" +} +curl_with_dig() +{ + # $1 - ip version : 4/6 + # $2 - domain name + # $3+ - curl params + local connect_to=$(curl_connect_to $1 $2) + [ -n "$connect_to" ] || { + echo "could not resolve ipv$1 $2" + return 6 + } + shift ; shift + ALL_PROXY="$ALL_PROXY" curl $connect_to "$@" +} + curl_test_http() { # $1 - ip version : 4/6 # $2 - domain name local code loc - $CURL -${1}SsD "$HDRTEMP" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || { + curl_with_dig $1 $2 -SsD "$HDRTEMP" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || { code=$? rm -f "$HDRTEMP" return $code @@ -439,7 +445,7 @@ curl_test_https_tls12() # $2 - domain name # do not use tls 1.3 to make sure server certificate is not encrypted - $CURL -${1}ISs -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1 + curl_with_dig $1 $2 -${1}ISs -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1 } curl_test_https_tls13() { @@ -447,7 +453,7 @@ curl_test_https_tls13() # $2 - domain name # force TLS1.3 mode - $CURL -${1}ISs -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1 + curl_with_dig $1 $2 -${1}ISs -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1 } pktws_ipt_prepare() @@ -485,7 +491,7 @@ pktws_ipt_prepare() nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} tcp dport $1 mark and 0x40000000 != 0x40000000 queue num $QNUM" # for strategies with incoming packets involved (autottl) nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }" - nft "add rule inet $NFT_TABLE prenat meta nfproto ipv${IPV} tcp sport $1 ct original packets 1-1 queue num $QNUM" + nft "add rule inet $NFT_TABLE prenat meta nfproto ipv${IPV} tcp sport $1 ct original packets 1 queue num $QNUM" # enable everything generated by nfqws (works only in OUTPUT, not in FORWARD) nft "add chain inet $NFT_TABLE predefrag { type filter hook output priority -402; }" nft "add rule inet $NFT_TABLE predefrag meta nfproto ipv${IPV} mark and $DESYNC_MARK !=0 notrack" @@ -529,45 +535,6 @@ pktws_ipt_unprepare() ;; esac } -tpws_ipt_prepare() -{ - # $1 - port - case "$FWTYPE" in - iptables) - IPT OUTPUT -t nat -p tcp --dport $1 -m owner ! --uid-owner $TPWS_UID -j DNAT --to $LOCALHOST_IPT:$TPPORT - ;; - nftables) - nft add table inet $NFT_TABLE - # -101 = pre dstnat - nft "add chain inet $NFT_TABLE output { type nat hook output priority -102; }" - nft "add rule inet $NFT_TABLE output tcp dport $1 skuid != $TPWS_UID dnat ip${IPVV} to $LOCALHOST_IPT:$TPPORT" - ;; - ipfw) - IPFW_ADD fwd $LOCALHOST,$TPPORT tcp from me to any $1 proto ip${IPV} not uid $TPWS_UID - ;; - mpf) - mpf_prepare_tpws $1 - ;; - esac -} -tpws_ipt_unprepare() -{ - # $1 - port - case "$FWTYPE" in - iptables) - IPT_DEL OUTPUT -t nat -p tcp --dport $1 -m owner ! --uid-owner $TPWS_UID -j DNAT --to $LOCALHOST_IPT:$TPPORT - ;; - nftables) - nft delete table inet $NFT_TABLE 2>/dev/null - ;; - ipfw) - IPFW_DEL - ;; - mpf) - pf_restore - ;; - esac -} pktws_start() { case "$UNAME" in @@ -584,7 +551,7 @@ pktws_start() } tpws_start() { - "$TPWS" --uid $TPWS_UID:$TPWS_GID --bind-addr=$LINKLOCAL%$LO_IFACE --port=$TPPORT "$@" >/dev/null & + "$TPWS" --uid $TPWS_UID:$TPWS_GID --socks --bind-addr=127.0.0.1 --port=$SOCKS_PORT "$@" >/dev/null & PID=$! # give some time to initialize minsleep @@ -643,6 +610,7 @@ tpws_curl_test() # $2 - domain # $3,$4,$5, ... - tpws params echo - checking tpws $3 $4 $5 $6 $7 $8 $9 + local ALL_PROXY="socks5://127.0.0.1:$SOCKS_PORT" ws_curl_test tpws_start "$@" } pktws_curl_test() @@ -862,7 +830,6 @@ check_domain() # in case was interrupted before pktws_ipt_unprepare $2 - tpws_ipt_unprepare $2 ws_kill echo "- checking without DPI bypass" @@ -879,17 +846,8 @@ check_domain() done echo - if [ "$SUBSYS" = "pfSense" ] ; then - echo "tpws tests are not possible on pfSense" - report_append "ipv${IPV} $4 $1 : automated tpws tests are not possible on pfSense. check docs/bsd.txt" - elif [ "$SKIP_TPWS" != 1 ]; then - echo preparing tpws redirection - tpws_ipt_prepare $2 - + if [ "$SKIP_TPWS" != 1 ]; then tpws_check_domain_bypass $1 $3 $4 - - echo clearing tpws redirection - tpws_ipt_unprepare $2 fi echo @@ -925,16 +883,11 @@ configure_ip_version() if [ "$IPV" = 6 ]; then LOCALHOST=::1 LOCALHOST_IPT=[${LOCALHOST}] - LINKLOCAL=$LOCALHOST - [ "$UNAME" = Darwin ] && LINKLOCAL=fe80::1 - LINKLOCAL_IPT=[${LINKLOCAL}] IPVV=6 else IPTABLES=iptables LOCALHOST=127.0.0.1 LOCALHOST_IPT=$LOCALHOST - LINKLOCAL=$LOCALHOST - LINKLOCAL_IPT=$LINKLOCAL IPVV= fi IPTABLES=ip${IPVV}tables @@ -1007,6 +960,14 @@ ask_params() echo echo NOTE ! this test should be run with zapret or any other bypass software disabled, without VPN echo + + curl_supports_connect_to || { + echo "installed curl does not support --connect-to option. pls install at least curl 7.49" + echo "current curl version:" + curl --version + exitp 1 + } + echo "specify domain(s) to test. multiple domains are space separated." printf "domain(s) (default: $DOMAINS) : " @@ -1201,8 +1162,6 @@ unprepare_all() # make sure we are not in a middle state that impacts connectivity rm -f "$HDRTEMP" [ -n "$IPV" ] && { - tpws_ipt_unprepare 80 - tpws_ipt_unprepare 443 pktws_ipt_unprepare 80 pktws_ipt_unprepare 443 }