zapret/blockcheck.sh

1264 lines
31 KiB
Bash
Raw Normal View History

2021-12-08 12:20:44 +00:00
#!/bin/sh
EXEDIR="$(dirname "$0")"
EXEDIR="$(cd "$EXEDIR"; pwd)"
ZAPRET_BASE="$EXEDIR"
2022-02-15 14:15:36 +00:00
[ -f "$ZAPRET_BASE/config" ] && . "$ZAPRET_BASE/config"
. "$ZAPRET_BASE/common/base.sh"
. "$ZAPRET_BASE/common/dialog.sh"
. "$ZAPRET_BASE/common/elevate.sh"
. "$ZAPRET_BASE/common/fwtype.sh"
. "$ZAPRET_BASE/common/virt.sh"
2022-02-15 14:15:36 +00:00
2021-12-08 12:20:44 +00:00
[ -n "$QNUM" ] || QNUM=59780
[ -n "$TPPORT" ] || TPPORT=993
[ -n "$TPWS_UID" ] || TPWS_UID=1
[ -n "$TPWS_GID" ] || TPWS_GID=3003
2021-12-08 12:20:44 +00:00
[ -n "$NFQWS" ] || NFQWS="$ZAPRET_BASE/nfq/nfqws"
2021-12-12 13:03:07 +00:00
[ -n "$DVTWS" ] || DVTWS="$ZAPRET_BASE/nfq/dvtws"
[ -n "$TPWS" ] || TPWS="$ZAPRET_BASE/tpws/tpws"
2021-12-08 12:20:44 +00:00
[ -n "$MDIG" ] || MDIG="$ZAPRET_BASE/mdig/mdig"
2024-03-10 18:22:16 +00:00
DESYNC_MARK=0x10000000
[ -n "$IPFW_RULE_NUM" ] || IPFW_RULE_NUM=1
[ -n "$IPFW_DIVERT_PORT" ] || IPFW_DIVERT_PORT=59780
[ -n "$DOMAINS" ] || DOMAINS=rutracker.org
2023-11-02 07:40:54 +00:00
[ -n "$CURL_MAX_TIME" ] || CURL_MAX_TIME=3
[ -n "$MIN_TTL" ] || MIN_TTL=1
[ -n "$MAX_TTL" ] || MAX_TTL=12
2022-03-12 11:08:14 +00:00
[ -n "$USER_AGENT" ] || USER_AGENT="Mozilla"
2021-12-08 12:20:44 +00:00
HDRTEMP=/tmp/zapret-hdr.txt
2022-02-10 19:30:50 +00:00
NFT_TABLE=blockcheck
[ -n "$DNSCHECK_DNS" ] || DNSCHECK_DNS="8.8.8.8 1.1.1.1 77.88.8.1"
2023-10-31 08:47:35 +00:00
[ -n "$DNSCHECK_DOM" ] || DNSCHECK_DOM="pornhub.com putinhuylo.com rutracker.org www.torproject.org bbc.com"
2021-12-08 12:20:44 +00:00
DNSCHECK_DIG1=/tmp/dig1.txt
DNSCHECK_DIG2=/tmp/dig2.txt
DNSCHECK_DIGS=/tmp/digs.txt
2024-03-11 16:00:22 +00:00
unset PF_STATUS
PF_RULES_SAVE=/tmp/pf-zapret-save.conf
2021-12-08 12:20:44 +00:00
2024-03-11 17:49:11 +00:00
CURL=curl
2021-12-08 12:20:44 +00:00
killwait()
{
# $1 - signal (-9, -2, ...)
# $2 - pid
kill $1 $2
# suppress job kill message
wait $2 2>/dev/null
}
exitp()
{
local A
echo
echo press enter to continue
read A
exit $1
}
2024-03-11 16:00:22 +00:00
pf_is_avail()
{
[ -c /dev/pf ]
}
pf_status()
{
pfctl -qsi | sed -nre "s/^Status: ([^ ]+).*$/\1/p"
}
pf_is_enabled()
{
[ "$(pf_status)" = Enabled ]
}
pf_save()
{
PF_STATUS=0
pf_is_enabled && PF_STATUS=1
2024-03-11 17:49:11 +00:00
[ "$UNAME" = "OpenBSD" ] && pfctl -sr >"$PF_RULES_SAVE"
2024-03-11 16:00:22 +00:00
}
pf_restore()
{
[ -n "$PF_STATUS" ] || return
2024-03-11 17:49:11 +00:00
case "$UNAME" in
OpenBSD)
if [ -f "$PF_RULES_SAVE" ]; then
pfctl -qf "$PF_RULES_SAVE"
else
echo | pfctl -qf -
fi
;;
Darwin)
# it's not possible to save all rules in the right order. hard to reorder. if not ordered pf will refuse to load conf.
pfctl -qf /etc/pf.conf
;;
esac
2024-03-11 16:00:22 +00:00
if [ "$PF_STATUS" = 1 ]; then
pfctl -qe
else
pfctl -qd
fi
}
pf_clean()
{
rm -f "$PF_RULES_SAVE"
}
opf_dvtws_anchor()
{
2024-03-11 17:49:11 +00:00
# $1 - port
local family=inet
[ "$IPV" = 6 ] && family=inet6
2024-03-11 16:00:22 +00:00
echo "set reassemble no"
2024-03-11 17:49:11 +00:00
echo "pass in quick $family proto tcp from port $1 flags SA/SA divert-packet port $IPFW_DIVERT_PORT no state"
echo "pass in quick $family proto tcp from port $1 no state"
echo "pass out quick $family proto tcp to port $1 divert-packet port $IPFW_DIVERT_PORT no state"
2024-03-11 16:00:22 +00:00
echo "pass"
}
opf_prepare_dvtws()
{
2024-03-11 17:49:11 +00:00
# $1 - port
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 }"
2024-03-11 17:49:11 +00:00
;;
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 }"
2024-03-11 17:49:11 +00:00
;;
esac
}
mpf_prepare_tpws()
{
# $1 - port
mpf_tpws_anchor $1 | pfctl -qf -
2024-03-11 16:00:22 +00:00
pfctl -qe
}
cleanup()
{
case "$UNAME" in
OpenBSD)
pf_clean
;;
esac
}
2021-12-08 12:20:44 +00:00
IPT()
{
$IPTABLES -C "$@" >/dev/null 2>/dev/null || $IPTABLES -I "$@"
}
IPT_DEL()
{
$IPTABLES -C "$@" >/dev/null 2>/dev/null && $IPTABLES -D "$@"
}
2021-12-12 13:03:07 +00:00
IPFW_ADD()
{
ipfw -qf add $IPFW_RULE_NUM "$@"
}
IPFW_DEL()
{
ipfw -qf delete $IPFW_RULE_NUM 2>/dev/null
2021-12-12 13:03:07 +00:00
}
ipt6_has_raw()
{
ip6tables -nL -t raw >/dev/null 2>/dev/null
}
ipt6_has_frag()
{
ip6tables -A OUTPUT -m frag 2>/dev/null || return 1
ip6tables -D OUTPUT -m frag 2>/dev/null
}
ipt_has_nfq()
{
# cannot just check /proc/net/ip_tables_targets because of iptables-nft or modules not loaded yet
iptables -A OUTPUT -t mangle -p 255 -j NFQUEUE --queue-num $QNUM --queue-bypass 2>/dev/null || return 1
iptables -D OUTPUT -t mangle -p 255 -j NFQUEUE --queue-num $QNUM --queue-bypass 2>/dev/null
return 0
}
2022-02-10 19:30:50 +00:00
nft_has_nfq()
{
local res=1
nft delete table ${NFT_TABLE}_test 2>/dev/null
nft add table ${NFT_TABLE}_test 2>/dev/null && {
nft add chain ${NFT_TABLE}_test test
nft add rule ${NFT_TABLE}_test test queue num $QNUM bypass 2>/dev/null && res=0
nft delete table ${NFT_TABLE}_test
}
return $res
}
2021-12-08 12:20:44 +00:00
check_system()
{
echo \* checking system
2021-12-12 13:03:07 +00:00
UNAME=$(uname)
SUBSYS=
local s
2022-02-11 07:24:35 +00:00
# can be passed FWTYPE=iptables to override default nftables preference
2021-12-12 13:03:07 +00:00
case "$UNAME" in
Linux)
PKTWS="$NFQWS"
PKTWSD=nfqws
2024-03-11 17:49:11 +00:00
LO_IFACE=lo
2022-02-15 14:15:36 +00:00
linux_fwtype
[ "$FWTYPE" = iptables -o "$FWTYPE" = nftables ] || {
echo firewall type $FWTYPE not supported in $UNAME
exitp 5
}
2021-12-12 13:03:07 +00:00
;;
FreeBSD)
PKTWS="$DVTWS"
PKTWSD=dvtws
2022-02-10 19:30:50 +00:00
FWTYPE=ipfw
2024-03-11 17:49:11 +00:00
LO_IFACE=lo0
[ -f /etc/platform ] && read SUBSYS </etc/platform
2021-12-12 13:03:07 +00:00
;;
2024-03-11 16:00:22 +00:00
OpenBSD)
PKTWS="$DVTWS"
PKTWSD=dvtws
FWTYPE=opf
2024-03-11 17:49:11 +00:00
LO_IFACE=lo0
;;
Darwin)
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
2024-03-11 16:00:22 +00:00
;;
2021-12-12 13:03:07 +00:00
*)
echo $UNAME not supported
exitp 5
esac
echo $UNAME${SUBSYS:+/$SUBSYS} detected
2022-02-10 19:30:50 +00:00
echo firewall type is $FWTYPE
2021-12-12 13:03:07 +00:00
}
freebsd_module_loaded()
{
# $1 - module name
2022-01-12 19:41:25 +00:00
kldstat -qm "${1}"
2021-12-12 13:03:07 +00:00
}
freebsd_modules_loaded()
{
# $1,$2,$3, ... - module names
while [ -n "$1" ]; do
freebsd_module_loaded $1 || return 1
shift
done
return 0
2021-12-08 12:20:44 +00:00
}
check_prerequisites()
{
echo \* checking prerequisites
2021-12-12 13:03:07 +00:00
2024-03-11 17:49:11 +00:00
[ "$UNAME" = Darwin -o -x "$PKTWS" ] && [ -x "$TPWS" ] && [ -x "$MDIG" ] || {
2021-12-12 20:34:04 +00:00
echo $PKTWS or $TPWS or $MDIG is not available. run \"$ZAPRET_BASE/install_bin.sh\" or make -C \"$ZAPRET_BASE\"
2021-12-08 12:20:44 +00:00
exitp 6
}
2022-01-10 21:46:32 +00:00
local prog progs='curl'
2021-12-12 13:03:07 +00:00
case "$UNAME" in
Linux)
2022-02-10 19:30:50 +00:00
case "$FWTYPE" in
iptables)
progs="$progs iptables ip6tables"
ipt_has_nfq || {
echo NFQUEUE iptables or ip6tables target is missing. pls install modules.
exitp 6
}
;;
nftables)
nft_has_nfq || {
echo nftables queue support is not available. pls install modules.
exitp 6
}
;;
esac
2021-12-12 13:03:07 +00:00
;;
FreeBSD)
progs="$progs ipfw"
freebsd_modules_loaded ipfw ipdivert || {
echo ipfw or ipdivert kernel module not loaded
exitp 6
}
2021-12-12 20:34:04 +00:00
[ "$(sysctl -qn net.inet.ip.fw.enable)" = 0 -o "$(sysctl -qn net.inet6.ip6.fw.enable)" = 0 ] && {
echo ipfw is disabled. use : ipfw enable firewall
exitp 6
}
2021-12-12 13:03:07 +00:00
;;
2024-03-11 17:49:11 +00:00
OpenBSD|Darwin)
2024-03-11 16:00:22 +00:00
progs="$progs pfctl"
pf_is_avail || {
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
2024-03-11 17:49:11 +00:00
[ "$UNAME" = "OpenBSD" ] && SKIP_TPWS=1
# no divert sockets in MacOS
[ "$UNAME" = "Darwin" ] && SKIP_PKTWS=1
2024-03-11 16:00:22 +00:00
pf_save
;;
2021-12-12 13:03:07 +00:00
esac
for prog in $progs; do
2021-12-08 12:20:44 +00:00
exists $prog || {
echo $prog does not exist. please install
exitp 6
}
done
2021-12-12 13:03:07 +00:00
if exists nslookup; then
LOOKUP=nslookup
elif exists host; then
LOOKUP=host
else
echo nslookup or host does not exist. please install
exitp 6
fi
2021-12-08 12:20:44 +00:00
}
2021-12-25 09:22:47 +00:00
curl_translate_code()
{
# $1 - code
2022-02-15 17:51:45 +00:00
printf $1
2021-12-25 09:22:47 +00:00
case $1 in
2022-02-15 17:51:45 +00:00
0) printf ": ok"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
1) printf ": unsupported protocol"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
2) printf ": early initialization code failed"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
3) printf ": the URL was not properly formatted"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
4) printf ": feature not supported by libcurl"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
5) printf ": could not resolve proxy"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
6) printf ": could not resolve host"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
7) printf ": could not connect"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
8) printf ": invalid server reply"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
9) printf ": remote access denied"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
27) printf ": out of memory"
2021-12-25 09:22:47 +00:00
;;
2022-02-15 17:51:45 +00:00
28) printf ": operation timed out"
;;
2022-02-15 17:51:45 +00:00
35) printf ": SSL connect error"
;;
2021-12-25 09:22:47 +00:00
esac
}
2021-12-10 08:18:25 +00:00
curl_supports_tls13()
{
local r
curl --tlsv1.3 -Is -o /dev/null http://127.0.0.1:65535 2>/dev/null
2021-12-10 08:18:25 +00:00
# return code 2 = init failed. likely bad command line options
[ $? = 2 ] && return 1
# curl can have tlsv1.3 key present but ssl library without TLS 1.3 support
# this is online test because there's no other way to trigger library incompatibility case
curl --tlsv1.3 --max-time $CURL_MAX_TIME -Is -o /dev/null https://w3.org 2>/dev/null
r=$?
[ $r != 4 -a $r != 35 ]
2021-12-10 08:18:25 +00:00
}
2021-12-08 12:20:44 +00:00
2023-03-26 09:52:30 +00:00
curl_supports_tlsmax()
{
# supported only in OpenSSL and LibreSSL
curl --version | grep -Fq -e OpenSSL -e LibreSSL -e GnuTLS || return 1
# supported since curl 7.54
curl --tls-max 1.2 -Is -o /dev/null http://127.0.0.1:65535 2>/dev/null
2023-03-26 09:52:30 +00:00
# return code 2 = init failed. likely bad command line options
[ $? != 2 ]
}
2021-12-08 12:20:44 +00:00
hdrfile_http_code()
{
# $1 - hdr file
sed -nre '1,1 s/^HTTP\/1\.[0,1] ([0-9]+) .*$/\1/p' "$1"
}
hdrfile_location()
{
# $1 - hdr file
# some DPIs return CRLF line ending
2022-01-22 15:08:05 +00:00
tr -d '\015' <"$1" | sed -nre 's/^[Ll][Oo][Cc][Aa][Tt][Ii][Oo][Nn]:[ ]*([^ ]*)[ ]*$/\1/p'
2021-12-08 12:20:44 +00:00
}
curl_test_http()
{
# $1 - ip version : 4/6
# $2 - domain name
local code loc
2024-03-11 17:49:11 +00:00
$CURL -${1}SsD "$HDRTEMP" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || {
2021-12-08 12:20:44 +00:00
code=$?
rm -f "$HDRTEMP"
return $code
}
code=$(hdrfile_http_code "$HDRTEMP")
[ "$code" = 301 -o "$code" = 302 -o "$code" = 307 -o "$code" = 308 ] && {
loc=$(hdrfile_location "$HDRTEMP")
echo "$loc" | grep -qE "^https?://.*$2(/|$)" ||
echo "$loc" | grep -vqE '^https?://' || {
echo suspicious redirection $code to : $loc
2021-12-08 12:20:44 +00:00
rm -f "$HDRTEMP"
return 254
}
}
rm -f "$HDRTEMP"
2023-11-02 07:40:54 +00:00
[ "$code" = 400 ] && {
# this can often happen if the server receives fake packets it should not receive
echo http code $code. likely the server receives fakes.
return 254
}
2021-12-08 12:20:44 +00:00
return 0
}
2021-12-10 08:18:25 +00:00
curl_test_https_tls12()
2021-12-08 12:20:44 +00:00
{
# $1 - ip version : 4/6
# $2 - domain name
2021-12-10 08:18:25 +00:00
# do not use tls 1.3 to make sure server certificate is not encrypted
2024-03-11 17:49:11 +00:00
$CURL -${1}ISs -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.2 $TLSMAX12 "https://$2" -o /dev/null 2>&1
2021-12-10 08:18:25 +00:00
}
curl_test_https_tls13()
{
# $1 - ip version : 4/6
# $2 - domain name
# force TLS1.3 mode
2024-03-11 17:49:11 +00:00
$CURL -${1}ISs -A "$USER_AGENT" --max-time $CURL_MAX_TIME $CURL_OPT --tlsv1.3 $TLSMAX13 "https://$2" -o /dev/null 2>&1
2021-12-08 12:20:44 +00:00
}
2021-12-12 13:03:07 +00:00
pktws_ipt_prepare()
2021-12-08 12:20:44 +00:00
{
# $1 - port
2022-02-10 19:30:50 +00:00
case "$FWTYPE" in
iptables)
2022-01-04 09:59:12 +00:00
# to avoid possible INVALID state drop
IPT INPUT -p tcp --sport $1 ! --syn -j ACCEPT
IPT OUTPUT -p tcp --dport $1 -m conntrack --ctstate INVALID -j ACCEPT
if [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ]; then
# the only way to reliable disable ipv6 defrag. works only in 4.16+ kernels
2022-02-05 14:58:56 +00:00
IPT OUTPUT -t raw -p tcp -m frag -j CT --notrack
2022-01-04 09:59:12 +00:00
elif [ "$IPV" = 4 ]; then
# enable fragments
IPT OUTPUT -f -j ACCEPT
fi
2024-03-02 14:53:37 +00:00
IPT OUTPUT -t mangle -p tcp --dport $1 -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK -j NFQUEUE --queue-num $QNUM
IPT INPUT -t mangle -p tcp --sport $1 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:1 -j NFQUEUE --queue-num $QNUM
# enable everything generated by nfqws (works only in OUTPUT, not in FORWARD)
# raw table may not be present
IPT OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CT --notrack
2021-12-12 13:03:07 +00:00
;;
2022-02-10 19:30:50 +00:00
nftables)
nft add table inet $NFT_TABLE
2024-03-02 14:53:37 +00:00
# prenat
# [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ] && {
# nft "add chain inet $NFT_TABLE predefrag { type filter hook output priority -402; }"
# nft "add rule inet $NFT_TABLE predefrag meta nfproto ipv${IPV} exthdr frag exists notrack"
# }
# nft "add chain inet $NFT_TABLE premangle { type filter hook output priority -152; }"
# nft "add rule inet $NFT_TABLE premangle meta nfproto ipv${IPV} tcp dport $1 mark and 0x40000000 != 0x40000000 queue num $QNUM"
# postnat. this is good because we need only output traffic
nft "add chain inet $NFT_TABLE postnat { type filter hook output priority 102; }"
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"
# 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"
2022-02-10 19:30:50 +00:00
;;
ipfw)
IPFW_ADD divert $IPFW_DIVERT_PORT tcp from me to any $1 proto ip${IPV} out not diverted not sockarg
# for autottl mode
IPFW_ADD divert $IPFW_DIVERT_PORT tcp from any $1 to me proto ip${IPV} tcpflags syn,ack in
2021-12-12 13:03:07 +00:00
;;
2024-03-11 16:00:22 +00:00
opf)
2024-03-11 17:49:11 +00:00
opf_prepare_dvtws $1
2024-03-11 16:00:22 +00:00
;;
2021-12-12 13:03:07 +00:00
esac
2021-12-08 12:20:44 +00:00
}
2021-12-12 13:03:07 +00:00
pktws_ipt_unprepare()
2021-12-08 12:20:44 +00:00
{
# $1 - port
2022-02-10 19:30:50 +00:00
case "$FWTYPE" in
iptables)
2024-03-02 14:53:37 +00:00
IPT_DEL OUTPUT -t mangle -p tcp --dport $1 -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK -j NFQUEUE --queue-num $QNUM
IPT_DEL INPUT -t mangle -p tcp --sport $1 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:1 -j NFQUEUE --queue-num $QNUM
2022-01-04 09:59:12 +00:00
IPT_DEL INPUT -p tcp --sport $1 ! --syn -j ACCEPT
IPT_DEL OUTPUT -p tcp --dport $1 -m conntrack --ctstate INVALID -j ACCEPT
if [ "$IPV" = 6 -a -n "$IP6_DEFRAG_DISABLE" ]; then
2022-02-05 14:58:56 +00:00
IPT_DEL OUTPUT -t raw -p tcp -m frag -j CT --notrack
2022-01-04 09:59:12 +00:00
elif [ "$IPV" = 4 ]; then
IPT_DEL OUTPUT -f -j ACCEPT
fi
2024-03-02 14:53:37 +00:00
# raw table may not be present
IPT_DEL OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CT --notrack
2021-12-12 13:03:07 +00:00
;;
2022-02-10 19:30:50 +00:00
nftables)
nft delete table inet $NFT_TABLE 2>/dev/null
;;
ipfw)
2021-12-12 13:03:07 +00:00
IPFW_DEL
;;
2024-03-11 16:00:22 +00:00
opf)
pf_restore
;;
2021-12-12 13:03:07 +00:00
esac
2021-12-08 12:20:44 +00:00
}
tpws_ipt_prepare()
{
# $1 - port
2022-02-10 19:30:50 +00:00
case "$FWTYPE" in
iptables)
2021-12-12 13:03:07 +00:00
IPT OUTPUT -t nat -p tcp --dport $1 -m owner ! --uid-owner $TPWS_UID -j DNAT --to $LOCALHOST_IPT:$TPPORT
;;
2022-02-10 19:30:50 +00:00
nftables)
nft add table inet $NFT_TABLE
# -101 = pre dstnat
2022-02-15 14:15:36 +00:00
nft "add chain inet $NFT_TABLE output { type nat hook output priority -102; }"
2022-02-10 19:30:50 +00:00
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
2021-12-12 13:03:07 +00:00
;;
2024-03-11 17:49:11 +00:00
mpf)
mpf_prepare_tpws $1
;;
2021-12-12 13:03:07 +00:00
esac
}
tpws_ipt_unprepare()
{
# $1 - port
2022-02-10 19:30:50 +00:00
case "$FWTYPE" in
iptables)
2021-12-12 13:03:07 +00:00
IPT_DEL OUTPUT -t nat -p tcp --dport $1 -m owner ! --uid-owner $TPWS_UID -j DNAT --to $LOCALHOST_IPT:$TPPORT
;;
2022-02-10 19:30:50 +00:00
nftables)
nft delete table inet $NFT_TABLE 2>/dev/null
;;
ipfw)
2021-12-12 13:03:07 +00:00
IPFW_DEL
;;
2024-03-11 17:49:11 +00:00
mpf)
pf_restore
;;
2021-12-12 13:03:07 +00:00
esac
}
pktws_start()
{
case "$UNAME" in
Linux)
"$NFQWS" --uid $TPWS_UID:$TPWS_GID --dpi-desync-fwmark=$DESYNC_MARK --qnum=$QNUM "$@" >/dev/null &
2021-12-12 13:03:07 +00:00
;;
2024-03-11 16:00:22 +00:00
FreeBSD|OpenBSD)
2021-12-12 13:03:07 +00:00
"$DVTWS" --port=$IPFW_DIVERT_PORT "$@" >/dev/null &
;;
esac
2021-12-09 17:13:38 +00:00
PID=$!
# give some time to initialize
minsleep
2021-12-08 12:20:44 +00:00
}
tpws_start()
{
"$TPWS" --uid $TPWS_UID:$TPWS_GID --bind-addr=$LINKLOCAL%$LO_IFACE --port=$TPPORT "$@" >/dev/null &
2021-12-09 17:13:38 +00:00
PID=$!
# give some time to initialize
2023-10-31 08:47:35 +00:00
minsleep
}
2021-12-10 08:18:25 +00:00
ws_kill()
{
[ -z "$PID" ] || {
killwait -9 $PID 2>/dev/null
PID=
}
}
2021-12-08 12:20:44 +00:00
curl_test()
{
# $1 - test function
# $2 - domain
2021-12-22 09:31:45 +00:00
local code=0 n=0
while [ $n -lt $REPEATS ]; do
n=$(($n+1))
2022-02-15 17:51:45 +00:00
[ $REPEATS -gt 1 ] && printf "[attempt $n] "
2022-01-04 09:59:12 +00:00
$1 "$IPV" $2 && {
2021-12-22 09:31:45 +00:00
[ $REPEATS -gt 1 ] && echo 'AVAILABLE'
continue
}
code=$?
done
2021-12-08 12:20:44 +00:00
if [ $code = 254 ]; then
2021-12-22 09:31:45 +00:00
echo "UNAVAILABLE"
elif [ $code = 0 ]; then
echo '!!!!! AVAILABLE !!!!!'
2021-12-08 12:20:44 +00:00
else
2021-12-22 09:31:45 +00:00
echo "UNAVAILABLE code=$code"
2021-12-08 12:20:44 +00:00
fi
return $code
}
ws_curl_test()
2021-12-08 12:20:44 +00:00
{
# $1 - ws start function
# $2 - test function
# $3 - domain
# $4,$5,$6, ... - ws params
2021-12-09 17:13:38 +00:00
local code ws_start=$1 testf=$2 dom=$3
shift
2021-12-08 12:20:44 +00:00
shift
shift
$ws_start "$@"
2021-12-08 12:20:44 +00:00
curl_test $testf $dom
code=$?
2021-12-10 08:18:25 +00:00
ws_kill
2021-12-08 12:20:44 +00:00
return $code
}
tpws_curl_test()
{
# $1 - test function
# $2 - domain
# $3,$4,$5, ... - tpws params
echo - checking tpws $3 $4 $5 $6 $7 $8 $9
ws_curl_test tpws_start "$@"
}
2021-12-12 13:03:07 +00:00
pktws_curl_test()
{
# $1 - test function
# $2 - domain
2021-12-12 13:03:07 +00:00
# $3,$4,$5, ... - nfqws/dvtws params
echo - checking $PKTWSD $3 $4 $5 $6 $7 $8 $9
ws_curl_test pktws_start "$@"
}
2021-12-23 16:12:09 +00:00
xxxws_curl_test_update()
{
# $1 - xxx_curl_test function
# $2 - test function
# $3 - domain
# $4,$5,$6, ... - nfqws/dvtws params
local code xxxf=$1 testf=$2 dom=$3
shift
shift
shift
$xxxf $testf $dom "$@"
code=$?
[ $code = 0 ] && strategy="${strategy:-$@}"
return $code
}
pktws_curl_test_update()
{
xxxws_curl_test_update pktws_curl_test "$@"
}
tpws_curl_test_update()
{
xxxws_curl_test_update tpws_curl_test "$@"
}
2021-12-25 09:22:47 +00:00
report_append()
{
NREPORT=${NREPORT:-0}
eval REPORT_${NREPORT}=\"$@\"
NREPORT=$(($NREPORT+1))
}
report_print()
{
local n=0 s
NREPORT=${NREPORT:-0}
while [ $n -lt $NREPORT ]; do
eval s=\"\${REPORT_$n}\"
echo $s
n=$(($n+1))
done
}
2021-12-24 16:24:01 +00:00
report_strategy()
{
2021-12-25 09:22:47 +00:00
# $1 - test function
# $2 - domain
# $3 - daemon
2021-12-24 16:24:01 +00:00
echo
if [ -n "$strategy" ]; then
2021-12-25 09:22:47 +00:00
echo "!!!!! $1: working strategy found for ipv${IPV} $2 : $3 $strategy !!!!!"
2021-12-24 16:24:01 +00:00
echo
2021-12-25 09:22:47 +00:00
report_append "ipv${IPV} $2 $1 : $3 $strategy"
2021-12-24 16:24:01 +00:00
return 0
else
2021-12-25 09:22:47 +00:00
echo "$1: $3 strategy for ipv${IPV} $2 not found"
2021-12-24 16:24:01 +00:00
echo
2021-12-25 09:22:47 +00:00
report_append "ipv${IPV} $2 $1 : $3 not working"
2021-12-24 16:24:01 +00:00
return 1
fi
}
test_has_split()
{
contains "$1" split || contains "$1" disorder
}
2024-03-02 14:53:37 +00:00
warn_fool()
{
2024-03-02 14:53:37 +00:00
case "$1" in
md5sig) echo 'WARNING ! although md5sig fooling worked it will not work on all sites. it typically works only on linux servers.' ;;
datanoack) echo 'WARNING ! although datanoack fooling worked it may break NAT and may only work with external IP. Additionally it may require nftables to work correctly.' ;;
2024-03-02 14:53:37 +00:00
esac
}
2021-12-12 13:03:07 +00:00
pktws_check_domain_bypass()
2021-12-08 12:20:44 +00:00
{
# $1 - test function
2021-12-09 13:38:02 +00:00
# $2 - encrypted test : 1/0
# $3 - domain
2024-03-02 19:31:02 +00:00
local strategy tests='fake' ret ok ttls s f e desync pos fooling frag sec="$2" delta
2021-12-08 12:20:44 +00:00
2021-12-09 13:38:02 +00:00
[ "$sec" = 0 ] && {
for s in '--hostcase' '--hostspell=hoSt' '--hostnospace' '--domcase'; do
2021-12-23 16:12:09 +00:00
pktws_curl_test_update $1 $3 $s
2021-12-09 13:54:12 +00:00
done
2021-12-09 13:38:02 +00:00
}
2021-12-08 12:20:44 +00:00
2021-12-09 13:38:02 +00:00
s="--dpi-desync=split2"
ok=0
2022-02-09 07:16:28 +00:00
pktws_curl_test_update $1 $3 $s
ret=$?
[ "$ret" = 0 ] && ok=1
[ "$ret" != 0 -o "$FORCE" = 1 ] && {
2021-12-23 16:12:09 +00:00
[ "$sec" = 0 ] && pktws_curl_test_update $1 $3 $s --hostcase
for pos in 1 3 4 5 10 50 100; do
s="--dpi-desync=split2 --dpi-desync-split-pos=$pos"
2021-12-23 16:12:09 +00:00
if pktws_curl_test_update $1 $3 $s; then
ok=1
break
2021-12-13 19:41:12 +00:00
elif [ "$sec" = 0 ]; then
2021-12-23 16:12:09 +00:00
pktws_curl_test_update $1 $3 $s --hostcase
fi
done
2021-12-23 16:12:09 +00:00
}
[ "$ok" = 1 -a "$FORCE" != 1 ] || tests="$tests split fake,split2 fake,split"
2021-12-09 13:38:02 +00:00
2022-02-09 07:06:01 +00:00
pktws_curl_test_update $1 $3 --dpi-desync=disorder2
ret=$?
[ "$ret" != 0 -o "$FORCE" = 1 ] && {
pktws_curl_test_update $1 $3 --dpi-desync=disorder2 --dpi-desync-split-pos=1
ret=$?
}
[ "$ret" != 0 -o "$FORCE" = 1 ] && tests="$tests disorder fake,disorder2 fake,disorder"
2021-12-08 12:20:44 +00:00
2021-12-08 13:30:21 +00:00
ttls=$(seq -s ' ' $MIN_TTL $MAX_TTL)
2021-12-13 14:01:50 +00:00
for e in '' '--wssize 1:6'; do
[ -n "$e" ] && {
2021-12-23 16:12:09 +00:00
pktws_curl_test_update $1 $3 $e
2021-12-13 14:01:50 +00:00
for desync in split2 disorder2; do
2021-12-23 16:12:09 +00:00
pktws_curl_test_update $1 $3 --dpi-desync=$desync $e
2021-12-13 14:01:50 +00:00
done
}
for desync in $tests; do
2021-12-23 16:12:09 +00:00
s="--dpi-desync=$desync"
2021-12-09 13:38:02 +00:00
for ttl in $ttls; do
2021-12-23 16:12:09 +00:00
pktws_curl_test_update $1 $3 $s --dpi-desync-ttl=$ttl $e && break
test_has_split $desync && pktws_curl_test_update $1 $3 $s --dpi-desync-split-pos=1 --dpi-desync-ttl=$ttl $e && break
2021-12-09 13:38:02 +00:00
done
for delta in 1 2 3 4 5; do
pktws_curl_test_update $1 $3 $s --dpi-desync-ttl=1 --dpi-desync-autottl=$delta $e || {
test_has_split $desync && pktws_curl_test_update $1 $3 $s --dpi-desync-split-pos=1 --dpi-desync-ttl=1 --dpi-desync-autottl=$delta $e
}
done
2024-03-11 16:00:22 +00:00
f=
[ "$UNAME" = "OpenBSD" ] || f="badsum"
f="$f badseq md5sig datanoack"
[ "$IPV" = 6 ] && f="$f hopbyhop hopbyhop2"
for fooling in $f; do
2024-03-02 14:53:37 +00:00
pktws_curl_test_update $1 $3 $s --dpi-desync-fooling=$fooling $e && warn_fool $fooling
test_has_split $desync && pktws_curl_test_update $1 $3 $s --dpi-desync-split-pos=1 --dpi-desync-fooling=$fooling $e && warn_fool $fooling
2021-12-13 14:01:50 +00:00
done
2021-12-09 13:50:31 +00:00
done
[ "$IPV" = 6 ] && {
f="hopbyhop hopbyhop,split2 hopbyhop,disorder2 destopt destopt,split2 destopt,disorder2"
[ -n "$IP6_DEFRAG_DISABLE" ] && f="$f ipfrag1 ipfrag1,split2 ipfrag1,disorder2"
for desync in $f; do
pktws_curl_test_update $1 $3 --dpi-desync=$desync $e
test_has_split $desync && pktws_curl_test_update $1 $3 --dpi-desync-split-pos=1 --dpi-desync=$desync $e
done
}
2021-12-13 14:01:50 +00:00
# do not do wssize test for http. it's useless
[ "$sec" = 1 ] || break
2021-12-08 12:20:44 +00:00
done
2022-01-03 19:17:39 +00:00
2024-03-11 16:00:22 +00:00
# OpenBSD has checksum issues with fragmented packets
if [ "$UNAME" != "OpenBSD" ]; then
[ "$IPV" = 4 -o -n "$IP6_DEFRAG_DISABLE" ] && {
for frag in 24 32 40 64 80 104; do
tests="ipfrag2"
[ "$IPV" = 6 ] && tests="$tests hopbyhop,ipfrag2 destopt,ipfrag2"
for desync in $tests; do
pktws_curl_test_update $1 $3 --dpi-desync=$desync --dpi-desync-ipfrag-pos-tcp=$frag
done
done
2024-03-11 16:00:22 +00:00
}
fi
2022-01-03 19:17:39 +00:00
2021-12-25 09:22:47 +00:00
report_strategy $1 $3 $PKTWSD
2021-12-08 12:20:44 +00:00
}
tpws_check_domain_bypass()
{
# $1 - test function
# $2 - encrypted test : 1/0
# $3 - domain
2023-07-03 12:28:42 +00:00
local s s2 pos strategy sec="$2"
if [ "$sec" = 0 ]; then
2023-07-03 12:28:42 +00:00
for s in '--hostcase' '--hostspell=hoSt' '--hostdot' '--hosttab' '--hostnospace' '--methodspace' '--methodeol' '--unixeol' \
'--hostpad=1024' '--hostpad=2048' '--hostpad=4096' '--hostpad=8192' '--hostpad=16384' ; do
2021-12-23 16:12:09 +00:00
tpws_curl_test_update $1 $3 $s
done
2024-03-02 14:53:37 +00:00
for s2 in '' '--disorder' '--oob'; do
2023-07-03 12:28:42 +00:00
for s in '--split-http-req=method' '--split-http-req=method --hostcase' '--split-http-req=host' '--split-http-req=host --hostcase' ; do
tpws_curl_test_update $1 $3 $s $s2
done
done
else
2024-03-02 14:53:37 +00:00
for s2 in '' '--disorder' '--oob'; do
2023-07-03 12:28:42 +00:00
for pos in 1 2 3 4 5 10 50 100; do
s="--split-pos=$pos"
tpws_curl_test_update $1 $3 $s $s2 && break
done
done
2024-03-02 14:53:37 +00:00
for s2 in '--tlsrec=sni' '--tlsrec=sni --split-pos=10' '--tlsrec=sni --split-pos=10 --disorder' '--tlsrec=sni --split-pos=10 --oob'; do
2023-10-12 09:35:06 +00:00
tpws_curl_test_update $1 $3 $s2 && [ "$FORCE" != 1 ] && break
done
fi
2021-12-25 09:22:47 +00:00
report_strategy $1 $3 tpws
}
2021-12-08 12:20:44 +00:00
check_domain()
{
# $1 - test function
# $2 - port
2021-12-09 13:38:02 +00:00
# $3 - encrypted test : 1/0
# $4 - domain
2021-12-08 12:20:44 +00:00
2022-01-10 21:46:32 +00:00
local code c
2021-12-08 18:23:06 +00:00
2021-12-08 12:20:44 +00:00
echo
echo \* $1 ipv$IPV $4
2021-12-08 12:20:44 +00:00
# in case was interrupted before
2021-12-12 13:03:07 +00:00
pktws_ipt_unprepare $2
tpws_ipt_unprepare $2
2021-12-10 08:18:25 +00:00
ws_kill
2021-12-08 12:20:44 +00:00
echo "- checking without DPI bypass"
2021-12-25 09:22:47 +00:00
curl_test $1 $4 && {
report_append "ipv${IPV} $4 $1 : working without bypass"
2022-02-09 07:06:01 +00:00
[ "$FORCE" = 1 ] || return
2021-12-25 09:22:47 +00:00
}
2021-12-08 18:23:06 +00:00
code=$?
for c in 1 2 3 4 6 27 ; do
2021-12-25 09:22:47 +00:00
[ $code = $c ] && {
report_append "ipv${IPV} $4 $1 : test aborted, no reason to continue. curl code $(curl_translate_code $code)"
return
}
2021-12-08 18:23:06 +00:00
done
2021-12-08 12:20:44 +00:00
2022-04-06 07:57:14 +00:00
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
tpws_check_domain_bypass $1 $3 $4
echo clearing tpws redirection
tpws_ipt_unprepare $2
fi
echo
2024-03-11 17:49:11 +00:00
[ "$SKIP_PKTWS" = 1 ] || {
echo preparing $PKTWSD redirection
pktws_ipt_prepare $2
2021-12-08 12:20:44 +00:00
2024-03-11 17:49:11 +00:00
pktws_check_domain_bypass $1 $3 $4
2021-12-08 12:20:44 +00:00
2024-03-11 17:49:11 +00:00
echo clearing $PKTWSD redirection
pktws_ipt_unprepare $2
}
2021-12-08 12:20:44 +00:00
}
check_domain_http()
{
# $1 - domain
2021-12-09 13:38:02 +00:00
check_domain curl_test_http 80 0 $1
2021-12-08 12:20:44 +00:00
}
2021-12-10 08:18:25 +00:00
check_domain_https_tls12()
{
# $1 - domain
check_domain curl_test_https_tls12 443 1 $1
}
check_domain_https_tls13()
2021-12-08 12:20:44 +00:00
{
# $1 - domain
2021-12-10 08:18:25 +00:00
check_domain curl_test_https_tls13 443 1 $1
2021-12-08 12:20:44 +00:00
}
configure_ip_version()
{
if [ "$IPV" = 6 ]; then
2021-12-09 17:24:41 +00:00
LOCALHOST=::1
2022-02-10 19:30:50 +00:00
LOCALHOST_IPT=[${LOCALHOST}]
LINKLOCAL=$LOCALHOST
[ "$UNAME" = Darwin ] && LINKLOCAL=fe80::1
LINKLOCAL_IPT=[${LINKLOCAL}]
2022-02-10 19:30:50 +00:00
IPVV=6
else
IPTABLES=iptables
LOCALHOST=127.0.0.1
2022-02-10 19:30:50 +00:00
LOCALHOST_IPT=$LOCALHOST
LINKLOCAL=$LOCALHOST
LINKLOCAL_IPT=$LINKLOCAL
2022-02-10 19:30:50 +00:00
IPVV=
fi
2022-02-10 19:30:50 +00:00
IPTABLES=ip${IPVV}tables
}
configure_curl_opt()
{
2023-03-26 09:52:30 +00:00
# wolfssl : --tlsv1.x mandates exact ssl version, tls-max not supported
# openssl : --tlsv1.x means "version equal or greater", tls-max supported
TLSMAX12=
TLSMAX13=
curl_supports_tlsmax && {
TLSMAX12="--tls-max 1.2"
TLSMAX13="--tls-max 1.3"
}
TLS13=
curl_supports_tls13 && TLS13=1
}
2022-02-10 19:30:50 +00:00
linux_ipv6_defrag_can_be_disabled()
{
2022-02-15 14:15:36 +00:00
linux_min_version 4 16
2022-02-10 19:30:50 +00:00
}
2022-02-09 07:43:18 +00:00
configure_defrag()
2022-02-09 07:06:01 +00:00
{
2022-02-10 19:30:50 +00:00
IP6_DEFRAG_DISABLE=
[ "$IPVS" = 4 ] && return
[ "$UNAME" = "Linux" ] && {
linux_ipv6_defrag_can_be_disabled || {
echo "WARNING ! ipv6 defrag can only be effectively disabled in linux kernel 4.16+"
echo "WARNING ! ipv6 ipfrag tests are disabled"
echo
return
}
}
case "$FWTYPE" in
iptables)
if ipt6_has_raw ; then
if ipt6_has_frag; then
IP6_DEFRAG_DISABLE=1
2022-02-09 07:06:01 +00:00
else
2022-02-10 19:30:50 +00:00
echo "WARNING ! ip6tables does not have '-m frag' module, ipv6 ipfrag tests are disabled"
2022-02-09 07:06:01 +00:00
echo
fi
2022-02-10 19:30:50 +00:00
else
echo "WARNING ! ip6tables raw table is not available, ipv6 ipfrag tests are disabled"
echo
fi
[ -n "$IP6_DEFRAG_DISABLE" ] && {
local ipexe="$(readlink -f $(whichq ip6tables))"
2022-02-15 14:15:36 +00:00
if contains "$ipexe" nft; then
2022-02-10 19:30:50 +00:00
echo "WARNING ! ipv6 ipfrag tests may have no effect if ip6tables-nft is used. current ip6tables point to : $ipexe"
else
echo "WARNING ! ipv6 ipfrag tests may have no effect if ip6table_raw kernel module is not loaded with parameter : raw_before_defrag=1"
fi
echo
2022-02-09 07:06:01 +00:00
}
;;
*)
IP6_DEFRAG_DISABLE=1
;;
esac
}
2021-12-08 12:20:44 +00:00
ask_params()
{
echo
echo NOTE ! this test should be run with zapret or any other bypass software disabled, without VPN
echo
2021-12-08 12:20:44 +00:00
echo "specify domain(s) to test. multiple domains are space separated."
2022-02-15 17:51:45 +00:00
printf "domain(s) (default: $DOMAINS) : "
2021-12-08 12:20:44 +00:00
local dom
read dom
[ -n "$dom" ] && DOMAINS="$dom"
2021-12-08 12:20:44 +00:00
2022-02-15 17:51:45 +00:00
printf "ip protocol version(s) - 4, 6 or 46 for both (default: 4) : "
read IPVS
[ -n "$IPVS" ] || IPVS=4
[ "$IPVS" = 4 -o "$IPVS" = 6 -o "$IPVS" = 46 ] || {
echo 'invalid ip version(s). should be 4, 6 or 46.'
2021-12-08 12:20:44 +00:00
exitp 1
}
[ "$IPVS" = 46 ] && IPVS="4 6"
configure_curl_opt
2021-12-08 12:20:44 +00:00
ENABLE_HTTP=1
ask_yes_no_var ENABLE_HTTP "check http"
2021-12-10 08:18:25 +00:00
ENABLE_HTTPS_TLS12=1
ask_yes_no_var ENABLE_HTTPS_TLS12 "check https tls 1.2"
ENABLE_HTTPS_TLS13=0
echo
if [ -n "$TLS13" ]; then
2021-12-10 08:18:25 +00:00
echo "TLS 1.3 is the new standard for encrypted communications over TCP"
2021-12-10 12:16:02 +00:00
echo "its the most important feature for DPI bypass is encrypted TLS ServerHello"
2021-12-10 08:18:25 +00:00
echo "more and more sites enable TLS 1.3 but still there're many sites with only TLS 1.2 support"
2021-12-10 08:22:42 +00:00
echo "with TLS 1.3 more DPI bypass strategies can work but they may not apply to all sites"
2021-12-10 08:18:25 +00:00
echo "if a strategy works with TLS 1.2 it will also work with TLS 1.3"
echo "if nothing works with TLS 1.2 this test may find TLS1.3 only strategies"
echo "make sure that $DOMAINS support TLS 1.3 otherwise all test will return an error"
2021-12-10 08:18:25 +00:00
ask_yes_no_var ENABLE_HTTPS_TLS13 "check https tls 1.3"
else
echo "installed curl version does not support TLS 1.3 . tests disabled."
fi
2021-12-08 12:20:44 +00:00
IGNORE_CA=0
CURL_OPT=
2021-12-10 08:18:25 +00:00
[ $ENABLE_HTTPS_TLS13 = 1 -o $ENABLE_HTTPS_TLS12 = 1 ] && {
echo
2021-12-22 09:31:45 +00:00
echo "on limited systems like openwrt CA certificates might not be installed to preserve space"
echo "in such a case curl cannot verify server certificate and you should either install ca-bundle or disable verification"
echo "however disabling verification will break https check if ISP does MitM attack and substitutes server certificate"
2021-12-08 12:20:44 +00:00
ask_yes_no_var IGNORE_CA "do not verify server certificate"
[ "$IGNORE_CA" = 1 ] && CURL_OPT=-k
}
2021-12-22 09:31:45 +00:00
echo
echo "sometimes ISPs use multiple DPIs or load balancing. bypass strategies may work unstable."
2022-02-15 17:51:45 +00:00
printf "how many times to repeat each test (default: 1) : "
2021-12-22 09:31:45 +00:00
read REPEATS
REPEATS=$((0+${REPEATS:-1}))
[ "$REPEATS" = 0 ] && {
echo invalid repeat count
exitp 1
}
2021-12-13 14:01:50 +00:00
echo
2022-02-09 07:06:01 +00:00
FORCE=0
ask_yes_no_var FORCE "do all tests despite of result ?"
2022-02-09 07:06:01 +00:00
echo
2022-02-09 07:43:18 +00:00
configure_defrag
2021-12-08 12:20:44 +00:00
}
pingtest()
{
2024-03-11 16:00:22 +00:00
case "$UNAME" in
OpenBSD)
ping -c 1 -w 1 $1 >/dev/null
;;
*)
ping -c 1 -W 1 $1 >/dev/null
;;
esac
2021-12-08 12:20:44 +00:00
}
dnstest()
{
# $1 - dns server. empty for system resolver
2021-12-12 13:03:07 +00:00
"$LOOKUP" w3.org $1 >/dev/null 2>/dev/null
2021-12-08 12:20:44 +00:00
}
find_working_public_dns()
{
2022-01-10 21:46:32 +00:00
local dns
2021-12-08 12:20:44 +00:00
for dns in $DNSCHECK_DNS; do
pingtest $dns && dnstest $dns && {
PUBDNS=$dns
return 0
}
done
return 1
}
2021-12-12 13:03:07 +00:00
lookup4()
{
# $1 - domain
# $2 - DNS
case "$LOOKUP" in
nslookup)
nslookup $1 $2 | sed -n '/Name:/,$p' | grep ^Address | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}'
;;
host)
host -t A $1 $2 | grep "has address" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}'
;;
esac
}
2021-12-08 12:20:44 +00:00
check_dns_spoof()
{
# $1 - domain
# $2 - public DNS
2021-12-12 13:03:07 +00:00
echo $1 | "$MDIG" --family=4 >"$DNSCHECK_DIG1"
lookup4 $1 $2 >"$DNSCHECK_DIG2"
2021-12-08 12:20:44 +00:00
# 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()
{
2022-01-10 21:46:32 +00:00
local C1 C2 dom
2021-12-08 12:20:44 +00:00
echo \* checking DNS
[ -f "$DNSCHECK_DIGS" ] && rm -f "$DNSCHECK_DIGS"
dnstest || {
echo -- DNS is not working. It's either misconfigured or blocked or you don't have inet access.
return 1
}
echo system DNS is working
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.
2021-12-12 13:03:07 +00:00
for dom in $DNSCHECK_DOM; do echo $dom; done | "$MDIG" --threads=10 --family=4 >"$DNSCHECK_DIGS"
2021-12-08 12:20:44 +00:00
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
}
unprepare_all()
2021-12-08 12:20:44 +00:00
{
2021-12-24 10:21:08 +00:00
# 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
2021-12-12 13:03:07 +00:00
pktws_ipt_unprepare 80
pktws_ipt_unprepare 443
}
2021-12-10 08:18:25 +00:00
ws_kill
2024-03-11 16:00:22 +00:00
cleanup
}
sigint()
{
echo
echo terminating...
unprepare_all
exitp 1
2021-12-08 12:20:44 +00:00
}
2024-03-11 16:00:22 +00:00
sigint_cleanup()
{
cleanup
exit 1
}
sigpipe()
{
# must not write anything here to stdout
unprepare_all
exit 1
}
2021-12-08 12:20:44 +00:00
2023-10-31 08:47:35 +00:00
fsleep_setup
fix_sbin_path
2021-12-08 12:20:44 +00:00
check_system
require_root
check_prerequisites
2024-03-11 16:00:22 +00:00
trap sigint_cleanup INT
2021-12-08 12:20:44 +00:00
check_dns
check_virt
2021-12-08 12:20:44 +00:00
ask_params
2024-03-11 16:00:22 +00:00
trap - INT
2021-12-08 12:20:44 +00:00
2021-12-10 08:18:25 +00:00
PID=
2021-12-25 09:22:47 +00:00
NREPORT=
trap sigint INT
trap sigpipe PIPE
for dom in $DOMAINS; do
for IPV in $IPVS; do
configure_ip_version
[ "$ENABLE_HTTP" = 1 ] && check_domain_http $dom
[ "$ENABLE_HTTPS_TLS12" = 1 ] && check_domain_https_tls12 $dom
[ "$ENABLE_HTTPS_TLS13" = 1 ] && check_domain_https_tls13 $dom
done
done
trap - PIPE
trap - INT
2021-12-08 18:12:41 +00:00
2024-03-11 16:00:22 +00:00
cleanup
2021-12-25 09:22:47 +00:00
echo
echo \* SUMMARY
report_print
2021-12-08 18:12:41 +00:00
exitp 0