From 353d34a42555fd28ae29926a60f9f5237a191bf7 Mon Sep 17 00:00:00 2001 From: bol-van Date: Mon, 11 Mar 2024 20:49:11 +0300 Subject: [PATCH] blockcheck: macos support --- blockcheck.sh | 104 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 23 deletions(-) diff --git a/blockcheck.sh b/blockcheck.sh index bda4eb8..cd60820 100755 --- a/blockcheck.sh +++ b/blockcheck.sh @@ -41,6 +41,8 @@ DNSCHECK_DIGS=/tmp/digs.txt unset PF_STATUS PF_RULES_SAVE=/tmp/pf-zapret-save.conf +CURL=curl + killwait() { # $1 - signal (-9, -2, ...) @@ -76,16 +78,24 @@ pf_save() { PF_STATUS=0 pf_is_enabled && PF_STATUS=1 - pfctl -sr >"$PF_RULES_SAVE" + [ "$UNAME" = "OpenBSD" ] && pfctl -sr >"$PF_RULES_SAVE" } pf_restore() { [ -n "$PF_STATUS" ] || return - if [ -f "$PF_RULES_SAVE" ]; then - pfctl -qf "$PF_RULES_SAVE" - else - echo | pfctl -qf - - fi + 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 if [ "$PF_STATUS" = 1 ]; then pfctl -qe else @@ -98,15 +108,39 @@ pf_clean() } opf_dvtws_anchor() { + # $1 - port + local family=inet + [ "$IPV" = 6 ] && family=inet6 echo "set reassemble no" - echo "pass in quick proto tcp from port {80,443} flags SA/SA divert-packet port $IPFW_DIVERT_PORT no state" - echo "pass in quick proto tcp from port {80,443} no state" - echo "pass out quick proto tcp to port {80,443} divert-packet port $IPFW_DIVERT_PORT no state" + 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" echo "pass" } opf_prepare_dvtws() { - opf_dvtws_anchor | pfctl -qf - + # $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 -> $LOCALHOST port $TPPORT" + echo "pass out route-to ($LO_IFACE $LOCALHOST) 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 -> $LOCALHOST port $TPPORT" + echo "pass out route-to ($LO_IFACE $LOCALHOST) 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 } @@ -176,6 +210,7 @@ check_system() Linux) PKTWS="$NFQWS" PKTWSD=nfqws + LO_IFACE=lo linux_fwtype [ "$FWTYPE" = iptables -o "$FWTYPE" = nftables ] || { echo firewall type $FWTYPE not supported in $UNAME @@ -186,12 +221,24 @@ check_system() PKTWS="$DVTWS" PKTWSD=dvtws FWTYPE=ipfw + LO_IFACE=lo0 [ -f /etc/platform ] && read SUBSYS &1 || { + $CURL -${1}SsD "$HDRTEMP" --max-time $CURL_MAX_TIME $CURL_OPT "http://$2" -o /dev/null 2>&1 || { code=$? rm -f "$HDRTEMP" return $code @@ -390,7 +439,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 -${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() { @@ -398,7 +447,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 -${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() @@ -447,7 +496,7 @@ pktws_ipt_prepare() IPFW_ADD divert $IPFW_DIVERT_PORT tcp from any $1 to me proto ip${IPV} tcpflags syn,ack in ;; opf) - opf_prepare_dvtws + opf_prepare_dvtws $1 ;; esac } @@ -496,6 +545,9 @@ tpws_ipt_prepare() 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() @@ -511,6 +563,9 @@ tpws_ipt_unprepare() ipfw) IPFW_DEL ;; + mpf) + pf_restore + ;; esac } pktws_start() @@ -529,7 +584,7 @@ pktws_start() } tpws_start() { - "$TPWS" --uid $TPWS_UID:$TPWS_GID --bind-addr=$LOCALHOST --port=$TPPORT "$@" >/dev/null & + "$TPWS" --uid $TPWS_UID:$TPWS_GID --bind-addr=$LOCALHOST%$LO_IFACE --port=$TPPORT "$@" >/dev/null & PID=$! # give some time to initialize minsleep @@ -839,13 +894,15 @@ check_domain() echo - echo preparing $PKTWSD redirection - pktws_ipt_prepare $2 + [ "$SKIP_PKTWS" = 1 ] || { + echo preparing $PKTWSD redirection + pktws_ipt_prepare $2 - pktws_check_domain_bypass $1 $3 $4 + pktws_check_domain_bypass $1 $3 $4 - echo clearing $PKTWSD redirection - pktws_ipt_unprepare $2 + echo clearing $PKTWSD redirection + pktws_ipt_unprepare $2 + } } check_domain_http() { @@ -867,6 +924,7 @@ configure_ip_version() { if [ "$IPV" = 6 ]; then LOCALHOST=::1 + [ "$UNAME" = Darwin ] && LOCALHOST=fe80::1 LOCALHOST_IPT=[${LOCALHOST}] IPVV=6 else