From 1030588943fa594d2aca2553323d1d5c76d9089e Mon Sep 17 00:00:00 2001 From: bol-van Date: Fri, 15 Mar 2024 14:49:59 +0300 Subject: [PATCH] blockcheck: optimize fw scheme, enable udp ipfrag tests --- blockcheck.sh | 204 ++++++++++++++++++++++++++------------------------ 1 file changed, 106 insertions(+), 98 deletions(-) diff --git a/blockcheck.sh b/blockcheck.sh index f0c2a0c..3dbdd7e 100755 --- a/blockcheck.sh +++ b/blockcheck.sh @@ -143,6 +143,10 @@ IPT_DEL() { $IPTABLES -C "$@" >/dev/null 2>/dev/null && $IPTABLES -D "$@" } +IPT_ADD_DEL() +{ + on_off_function IPT IPT_DEL "$@" +} IPFW_ADD() { ipfw -qf add $IPFW_RULE_NUM "$@" @@ -199,7 +203,6 @@ 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 @@ -210,20 +213,17 @@ check_system() PKTWS="$DVTWS" PKTWSD=dvtws FWTYPE=ipfw - LO_IFACE=lo0 [ -f /etc/platform ] && read SUBSYS &1 } -pktws_ipt_prepare_tcp() +ipt_scheme() { - # $1 - port + # $1 - 1 - add , 0 - del + # $2 - tcp/udp + # $3 - port + + IPT_ADD_DEL $1 OUTPUT -t mangle -p $2 --dport $3 -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK -j NFQUEUE --queue-num $QNUM + # to avoid possible INVALID state drop + [ "$2" = tcp ] && IPT_ADD_DEL $1 INPUT -p $2 --sport $3 ! --syn -j ACCEPT + # for strategies with incoming packets involved (autottl) + IPT_ADD_DEL $1 OUTPUT -p $2 --dport $3 -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 + IPT_ADD_DEL $1 OUTPUT -t raw -p $2 -m frag -j CT --notrack + elif [ "$IPV" = 4 ]; then + # enable fragments + IPT_ADD_DEL $1 OUTPUT -f -j ACCEPT + fi + # enable everything generated by nfqws (works only in OUTPUT, not in FORWARD) + # raw table may not be present + IPT_ADD_DEL $1 OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CT --notrack +} +nft_scheme() +{ + # $1 - tcp/udp + # $2 - port + nft add table inet $NFT_TABLE + nft "add chain inet $NFT_TABLE postnat { type filter hook output priority 102; }" + nft "add rule inet $NFT_TABLE postnat meta nfproto ipv${IPV} $1 dport $2 mark and $DESYNC_MARK != $DESYNC_MARK queue num $QNUM" + # for strategies with incoming packets involved (autottl) + nft "add chain inet $NFT_TABLE prenat { type filter hook prerouting priority -102; }" + # 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" +} + +pktws_ipt_prepare() +{ + # $1 - tcp/udp + # $2 - port case "$FWTYPE" in iptables) - # 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 - IPT OUTPUT -t raw -p tcp -m frag -j CT --notrack - elif [ "$IPV" = 4 ]; then - # enable fragments - IPT OUTPUT -f -j ACCEPT - fi - 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 + ipt_scheme 1 $1 $2 ;; nftables) - nft add table inet $NFT_TABLE -# 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 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" + nft_scheme $1 $2 ;; ipfw) # disable PF to avoid interferences pf_is_avail && pfctl -qd - - 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 not diverted not sockarg + IPFW_ADD divert $IPFW_DIVERT_PORT $1 from me to any $2 proto ip${IPV} out not diverted not sockarg ;; opf) - opf_prepare_dvtws tcp $1 + opf_prepare_dvtws $1 $2 + ;; + esac +} +pktws_ipt_unprepare() +{ + # $1 - tcp/udp + # $2 - port + case "$FWTYPE" in + iptables) + ipt_scheme 0 $1 $2 + ;; + nftables) + nft delete table inet $NFT_TABLE 2>/dev/null + ;; + ipfw) + IPFW_DEL + pf_is_avail && pf_restore + ;; + opf) + pf_restore + ;; + esac +} + +pktws_ipt_prepare_tcp() +{ + # $1 - port + + pktws_ipt_prepare tcp $1 + + case "$FWTYPE" in + iptables) + # for autottl + IPT INPUT -t mangle -p tcp --sport $1 -m connbytes --connbytes-dir=original --connbytes-mode=packets --connbytes 1:1 -j NFQUEUE --queue-num $QNUM + ;; + nftables) + # for autottl + nft "add rule inet $NFT_TABLE prenat meta nfproto ipv${IPV} tcp sport $1 ct original packets 1 queue num $QNUM" + ;; + ipfw) + # for autottl mode + IPFW_ADD divert $IPFW_DIVERT_PORT tcp from any $1 to me proto ip${IPV} tcpflags syn,ack in not diverted not sockarg ;; esac } pktws_ipt_unprepare_tcp() { # $1 - port + + pktws_ipt_unprepare tcp $1 + case "$FWTYPE" in iptables) - 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 - - 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 - IPT_DEL OUTPUT -t raw -p tcp -m frag -j CT --notrack - elif [ "$IPV" = 4 ]; then - IPT_DEL OUTPUT -f -j ACCEPT - fi - # raw table may not be present - IPT_DEL OUTPUT -t raw -m mark --mark $DESYNC_MARK/$DESYNC_MARK -j CT --notrack - ;; - nftables) - nft delete table inet $NFT_TABLE 2>/dev/null - ;; - ipfw) - IPFW_DEL - pf_is_avail && pf_restore - ;; - opf) - pf_restore ;; esac } pktws_ipt_prepare_udp() { # $1 - port - case "$FWTYPE" in - iptables) - IPT OUTPUT -t mangle -p udp --dport $1 -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK -j NFQUEUE --queue-num $QNUM - ;; - nftables) - nft add table inet $NFT_TABLE - nft "add chain inet $NFT_TABLE premangle { type filter hook output priority -152; }" - nft "add rule inet $NFT_TABLE premangle meta nfproto ipv${IPV} udp dport $1 mark and 0x40000000 != 0x40000000 queue num $QNUM" - ;; - ipfw) - # disable PF to avoid interferences - pf_is_avail && pfctl -qd - IPFW_ADD divert $IPFW_DIVERT_PORT udp from me to any $1 proto ip${IPV} out not diverted not sockarg - ;; - opf) - opf_prepare_dvtws udp $1 - ;; - esac + pktws_ipt_prepare udp $1 } pktws_ipt_unprepare_udp() { # $1 - port - case "$FWTYPE" in - iptables) - IPT_DEL OUTPUT -t mangle -p udp --dport $1 -m mark ! --mark $DESYNC_MARK/$DESYNC_MARK -j NFQUEUE --queue-num $QNUM - ;; - nftables) - nft delete table inet $NFT_TABLE 2>/dev/null - ;; - ipfw) - IPFW_DEL - pf_is_avail && pf_restore - ;; - opf) - pf_restore - ;; - esac + + pktws_ipt_unprepare udp $1 } pktws_start() @@ -882,13 +880,23 @@ pktws_check_domain_http3_bypass() local f desync frag tests pktws_curl_test_update $1 $2 --dpi-desync=fake - + [ "$IPV" = 6 ] && { f="hopbyhop destopt" + [ -n "$IP6_DEFRAG_DISABLE" ] && f="$f ipfrag1" for desync in $f; do pktws_curl_test_update $1 $2 --dpi-desync=$desync done } + [ "$IPV" = 4 -o -n "$IP6_DEFRAG_DISABLE" ] && { + for frag in 8 16 24 32 40 64; do + tests="ipfrag2" + [ "$IPV" = 6 ] && tests="$tests hopbyhop,ipfrag2 destopt,ipfrag2" + for desync in $tests; do + pktws_curl_test_update $1 $2 --dpi-desync=$desync --dpi-desync-ipfrag-pos-udp=$frag + done + done + } report_strategy $1 $2 $PKTWSD }