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"
[ -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
@ -1008,6 +961,14 @@ ask_params()
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) : "
local dom
@ -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
}