blockcheck: use socks mode for tpws tests

This commit is contained in:
bol-van 2024-03-14 16:44:08 +03:00
parent 2f9c69b33f
commit 44f9878655

View File

@ -12,7 +12,7 @@ ZAPRET_BASE="$EXEDIR"
. "$ZAPRET_BASE/common/virt.sh" . "$ZAPRET_BASE/common/virt.sh"
[ -n "$QNUM" ] || QNUM=59780 [ -n "$QNUM" ] || QNUM=59780
[ -n "$TPPORT" ] || TPPORT=993 [ -n "$SOCKS_PORT" ] || SOCKS_PORT=1993
[ -n "$TPWS_UID" ] || TPWS_UID=1 [ -n "$TPWS_UID" ] || TPWS_UID=1
[ -n "$TPWS_GID" ] || TPWS_GID=3003 [ -n "$TPWS_GID" ] || TPWS_GID=3003
[ -n "$NFQWS" ] || NFQWS="$ZAPRET_BASE/nfq/nfqws" [ -n "$NFQWS" ] || NFQWS="$ZAPRET_BASE/nfq/nfqws"
@ -41,7 +41,7 @@ DNSCHECK_DIGS=/tmp/digs.txt
unset PF_STATUS unset PF_STATUS
PF_RULES_SAVE=/tmp/pf-zapret-save.conf PF_RULES_SAVE=/tmp/pf-zapret-save.conf
CURL=curl unset ALL_PROXY
killwait() killwait()
{ {
@ -123,26 +123,6 @@ opf_prepare_dvtws()
opf_dvtws_anchor $1 | pfctl -qf - opf_dvtws_anchor $1 | pfctl -qf -
pfctl -qe 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() cleanup()
{ {
@ -197,6 +177,13 @@ nft_has_nfq()
return $res return $res
} }
mdig_resolve()
{
# $1 - ip version 4/6
# $2 - hostname
echo "$2" | "$MDIG" --family=$1 | head -n 1
}
check_system() check_system()
{ {
echo \* checking system echo \* checking system
@ -234,10 +221,6 @@ check_system()
PKTWS="$DVTWS" PKTWS="$DVTWS"
PKTWSD=dvtws PKTWSD=dvtws
FWTYPE=mpf 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 LO_IFACE=lo0
;; ;;
*) *)
@ -308,11 +291,6 @@ check_prerequisites()
echo pf is not available echo pf is not available
exitp 6 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 # no divert sockets in MacOS
[ "$UNAME" = "Darwin" ] && SKIP_PKTWS=1 [ "$UNAME" = "Darwin" ] && SKIP_PKTWS=1
pf_save pf_save
@ -393,6 +371,12 @@ curl_supports_tlsmax()
[ $? != 2 ] [ $? != 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() hdrfile_http_code()
{ {
# $1 - hdr file # $1 - hdr file
@ -405,12 +389,34 @@ hdrfile_location()
# some DPIs return CRLF line ending # some DPIs return CRLF line ending
tr -d '\015' <"$1" | sed -nre 's/^[Ll][Oo][Cc][Aa][Tt][Ii][Oo][Nn]:[ ]*([^ ]*)[ ]*$/\1/p' 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() curl_test_http()
{ {
# $1 - ip version : 4/6 # $1 - ip version : 4/6
# $2 - domain name # $2 - domain name
local code loc 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=$? code=$?
rm -f "$HDRTEMP" rm -f "$HDRTEMP"
return $code return $code
@ -439,7 +445,7 @@ curl_test_https_tls12()
# $2 - domain name # $2 - domain name
# do not use tls 1.3 to make sure server certificate is not encrypted # 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() curl_test_https_tls13()
{ {
@ -447,7 +453,7 @@ curl_test_https_tls13()
# $2 - domain name # $2 - domain name
# force TLS1.3 mode # 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() 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" 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) # for strategies with incoming packets involved (autottl)
nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }" 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) # 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 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" 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 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() pktws_start()
{ {
case "$UNAME" in case "$UNAME" in
@ -584,7 +551,7 @@ pktws_start()
} }
tpws_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=$! PID=$!
# give some time to initialize # give some time to initialize
minsleep minsleep
@ -643,6 +610,7 @@ tpws_curl_test()
# $2 - domain # $2 - domain
# $3,$4,$5, ... - tpws params # $3,$4,$5, ... - tpws params
echo - checking tpws $3 $4 $5 $6 $7 $8 $9 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 "$@" ws_curl_test tpws_start "$@"
} }
pktws_curl_test() pktws_curl_test()
@ -862,7 +830,6 @@ check_domain()
# in case was interrupted before # in case was interrupted before
pktws_ipt_unprepare $2 pktws_ipt_unprepare $2
tpws_ipt_unprepare $2
ws_kill ws_kill
echo "- checking without DPI bypass" echo "- checking without DPI bypass"
@ -879,17 +846,8 @@ check_domain()
done done
echo echo
if [ "$SUBSYS" = "pfSense" ] ; then if [ "$SKIP_TPWS" != 1 ]; 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
tpws_check_domain_bypass $1 $3 $4 tpws_check_domain_bypass $1 $3 $4
echo clearing tpws redirection
tpws_ipt_unprepare $2
fi fi
echo echo
@ -925,16 +883,11 @@ configure_ip_version()
if [ "$IPV" = 6 ]; then if [ "$IPV" = 6 ]; then
LOCALHOST=::1 LOCALHOST=::1
LOCALHOST_IPT=[${LOCALHOST}] LOCALHOST_IPT=[${LOCALHOST}]
LINKLOCAL=$LOCALHOST
[ "$UNAME" = Darwin ] && LINKLOCAL=fe80::1
LINKLOCAL_IPT=[${LINKLOCAL}]
IPVV=6 IPVV=6
else else
IPTABLES=iptables IPTABLES=iptables
LOCALHOST=127.0.0.1 LOCALHOST=127.0.0.1
LOCALHOST_IPT=$LOCALHOST LOCALHOST_IPT=$LOCALHOST
LINKLOCAL=$LOCALHOST
LINKLOCAL_IPT=$LINKLOCAL
IPVV= IPVV=
fi fi
IPTABLES=ip${IPVV}tables IPTABLES=ip${IPVV}tables
@ -1008,6 +961,14 @@ ask_params()
echo NOTE ! this test should be run with zapret or any other bypass software disabled, without VPN echo NOTE ! this test should be run with zapret or any other bypass software disabled, without VPN
echo 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." echo "specify domain(s) to test. multiple domains are space separated."
printf "domain(s) (default: $DOMAINS) : " printf "domain(s) (default: $DOMAINS) : "
local dom local dom
@ -1201,8 +1162,6 @@ unprepare_all()
# make sure we are not in a middle state that impacts connectivity # make sure we are not in a middle state that impacts connectivity
rm -f "$HDRTEMP" rm -f "$HDRTEMP"
[ -n "$IPV" ] && { [ -n "$IPV" ] && {
tpws_ipt_unprepare 80
tpws_ipt_unprepare 443
pktws_ipt_unprepare 80 pktws_ipt_unprepare 80
pktws_ipt_unprepare 443 pktws_ipt_unprepare 443
} }