From 703fe46dd124e237f993cbc6416b49332a630f3c Mon Sep 17 00:00:00 2001 From: "Ycarus (Yannick Chabanois)" Date: Wed, 10 Jan 2024 17:33:00 +0100 Subject: [PATCH] Add nftables support to omr-bypass --- omr-bypass/Makefile | 22 +- omr-bypass/files/etc/init.d/omr-bypass | 751 +++++++---------- omr-bypass/files/etc/init.d/omr-bypass-nft | 926 +++++++++++++++++++++ 3 files changed, 1255 insertions(+), 444 deletions(-) create mode 100755 omr-bypass/files/etc/init.d/omr-bypass-nft diff --git a/omr-bypass/Makefile b/omr-bypass/Makefile index b75dcf46e..59de108fb 100644 --- a/omr-bypass/Makefile +++ b/omr-bypass/Makefile @@ -20,15 +20,33 @@ DEPENDS:=+curl +dnsmasq-full +sqlite3-cli +iptables +iptables-mod-extra +ipset TITLE:=OMR-ByPass endef +define Package/$(PKG_NAME)-nft +SECTION:=net +CATEGORY:=Network +DEPENDS:=+curl +dnsmasq-full +sqlite3-cli +firewall4 +TITLE:=OMR-ByPass NFT +endef + define Package/$(PKG_NAME)/description OMR-ByPass endef +define Package/$(PKG_NAME)/description +OMR-ByPass nft support +endef + define Build/Compile endef define Package/$(PKG_NAME)/install - $(CP) ./files/* $(1)/ + $(CP) ./files/* $(1)/ + rm -f $(1)/etc/init.d/omr-bypass-nft endef -$(eval $(call BuildPackage,$(PKG_NAME))) \ No newline at end of file +define Package/$(PKG_NAME)-nft/install + $(CP) ./files/* $(1)/ + mv $(1)/etc/init.d/omr-bypass-nft $(1)/etc/init.d/omr-bypass +endef + +$(eval $(call BuildPackage,$(PKG_NAME))) +$(eval $(call BuildPackage,$(PKG_NAME)-nft)) \ No newline at end of file diff --git a/omr-bypass/files/etc/init.d/omr-bypass b/omr-bypass/files/etc/init.d/omr-bypass index 1d292c55a..8d2ef20c6 100755 --- a/omr-bypass/files/etc/init.d/omr-bypass +++ b/omr-bypass/files/etc/init.d/omr-bypass @@ -1,5 +1,5 @@ #!/bin/sh /etc/rc.common -# Copyright (C) 2018-2020 Ycarus (Yannick Chabanois) +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter START=98 STOP=10 @@ -8,13 +8,14 @@ EXTRA_COMMANDS="reload_rules bypass_asn" . /usr/lib/unbound/iptools.sh -if [ -f /usr/sbin/iptables-legacy ]; then - IPTABLES="/usr/sbin/iptables-legacy" - IPTABLESRESTORE="/usr/sbin/iptables-legacy-restore" - IPTABLESSAVE="/usr/sbin/iptables-legacy-save" - IP6TABLES="/usr/sbin/ip6tables-legacy" - IP6TABLESRESTORE="/usr/sbin/ip6tables-legacy-restore" - IP6TABLESSAVE="/usr/sbin/ip6tables-legacy-save" +# Still used by ndpi +if [ -e /usr/sbin/iptables-nft ]; then + IPTABLES="/usr/sbin/iptables-nft" + IPTABLESRESTORE="/usr/sbin/iptables-nft-restore" + IPTABLESSAVE="/usr/sbin/iptables-nft-save" + IP6TABLES="/usr/sbin/ip6tables-nft" + IP6TABLESRESTORE="/usr/sbin/ip6tables-nft-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-nft-save" else IPTABLES="/usr/sbin/iptables" IPTABLESRESTORE="/usr/sbin/iptables-restore" @@ -58,9 +59,13 @@ _bypass_ip() { valid_ip4=$( valid_subnet4 $ip) valid_ip6=$( valid_subnet6 $ip) if [ "$valid_ip4" = "ok" ]; then - ipset -q add omr_dst_bypass_$type $ip + uci -q add_list firewall.omr_dst_bypass_${type}_4.entry=$ip + uci -q set firewall.omr_dst_bypass_${type}_4.enabled='1' + uci -q set firewall.omr_dst_bypass_${type}_dstip_4.enabled='1' elif [ "$valid_ip6" = "ok" ]; then - ipset -q add omr6_dst_bypass_$type $ip + uci -q add_list firewall.omr_dst_bypass_${type}_6.entry=$ip + uci -q set firewall.omr_dst_bypass_${type}_6.enabled='1' + uci -q set firewall.omr_dst_bypass_${type}_dstip_6.enabled='1' fi } @@ -76,6 +81,7 @@ _bypass_domains() { [ -z "$intf" ] && intf="all" config_get vpn $1 vpn [ "$vpn" = "1" ] && intf="srv_vpn1" + #echo "bypass $domain $enabled $family $intf $vpn" [ "$enabled" = "0" ] && return [ -z "$domain" ] && return [ -z "$family" ] && family="ipv4ipv6" @@ -107,6 +113,7 @@ _bypass_domains() { _bypass_domain $validdomain $intf $family $noipv6 done else + #echo "_bypass_domain $domain $intf $family $noipv6" _bypass_domain $domain $intf $family $noipv6 fi } @@ -117,7 +124,6 @@ _bypass_domain() { local family=$3 local noipv6=$4 intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return [ -z "$intf" ] && intf="all" if [ -n "$domain" ]; then domain=$(echo $domain | sed 's:^\.::') @@ -134,35 +140,13 @@ _bypass_domain() { done fi fi - if [ "$(uci -q get dhcp.@dnsmasq[0].ipset | grep /$domain/)" = "" ]; then - if [ "$family" = "ipv4ipv6" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf,omr6_dst_bypass_$intf" - elif [ "$family" = "ipv4" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr_dst_bypass_$intf" - elif [ "$family" = "ipv6" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="/$domain/omr6_dst_bypass_$intf" - fi + if [ "$(uci -q get dhcp.omr_dst_bypass_$intf | grep /$domain/)" = "" ]; then + uci -q add_list dhcp.omr_dst_bypass_$intf.domain=$domain add_domains="true" - else - dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g') - for dnsipset in $dnsmasqipset; do - if [ "$(echo $dnsipset | cut -d/ -f2)" = "$domain" ]; then - uci -q del_list dhcp.@dnsmasq[0].ipset=$dnsipset - if [ "$family" = "ipv4ipv6" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf,omr6_dst_bypass_$intf" - elif [ "$family" = "ipv4" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr_dst_bypass_$intf" - elif [ "$family" = "ipv6" ]; then - uci -q add_list dhcp.@dnsmasq[0].ipset="$dnsipset,omr6_dst_bypass_$intf" - fi - add_domains="true" - fi - done fi if [ "$(uci -q get dhcp.@dnsmasq[0].noipv6 | grep /$domain/)" = "" ] && [ "$noipv6" = "1" ]; then uci -q add_list dhcp.@dnsmasq[0].noipv6="$domain" fi - #logger -t "omr-bypass" "Get IPs of $domain... Done" fi } @@ -176,38 +160,13 @@ _bypass_mac() { config_get enabled $1 enabled [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$mac" ] && return - if [ "$intf" = "all" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -m mac --mac-source $mac -j MARK --set-mark 0x539 - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -m mac --mac-source $mac -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - else - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -m mac --mac-source $mac -j MARK --set-mark 0x539$intfid - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -m mac --mac-source $mac -j MARK --set-mark 0x6539$intfid - COMMIT - EOF - fi - fi + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_$intf_mac.src_mac="$mac" + EOF } _bypass_lan_ip() { @@ -226,44 +185,16 @@ _bypass_lan_ip() { [ -z "$ip" ] && return valid_ip4=$(valid_subnet4 $ip) valid_ip6=$(valid_subnet6 $ip) - if [ "$intf" = "all" ]; then - if [ "$valid_ip4" = "ok" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -s $ip -j MARK --set-mark 0x539 - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local -s $ip -j MARK --set-mark 0x539 - COMMIT - EOF - elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -s $ip -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - else - if [ "$valid_ip4" = "ok" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -s $ip -j MARK --set-mark 0x539$intfid - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local -s $ip -j MARK --set-mark 0x539$intfid - COMMIT - EOF - elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -s $ip -j MARK --set-mark 0x6539$intfid - COMMIT - EOF - fi + if [ "$valid_ip4" = "ok" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcip_4.src_ip="$ip" + set firewall.omr_dst_bypass_${intf}_srcip_4.enabled='1' + EOF + elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcip_6.src_ip="$ip" + set firewall.omr_dst_bypass_${intf}_srcip_6.enabled='1' + EOF fi } @@ -278,49 +209,24 @@ _bypass_dest_port() { config_get enabled $1 enabled [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$dport" ] && return dport="$(echo $dport | sed 's/-/:/')" [ -z "$proto" ] && return - if [ "$intf" = "all" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass --protocol $proto --destination-port $dport -j MARK --set-mark 0x539 - COMMIT + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.dst_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local --protocol $proto --destination-port $dport -j MARK --set-mark 0x539 - COMMIT + fi + if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_udp.dst_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 --protocol $proto --destination-port $dport -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - else - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass --protocol $proto --destination-port $dport -j MARK --set-mark 0x539$intfid - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local --protocol $proto --destination-port $dport -j MARK --set-mark 0x539$intfid - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 --protocol $proto --destination-port $dport -j MARK --set-mark 0x6539$intfid - COMMIT - EOF - fi fi } @@ -335,49 +241,24 @@ _bypass_src_port() { config_get enabled $1 enabled [ "$enabled" = "0" ] && return intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" [ -z "$sport" ] && return sport="$(echo $sport | sed 's/-/:/')" [ -z "$proto" ] && return - if [ "$intf" = "all" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass --protocol $proto --source-port $sport -j MARK --set-mark 0x539 - COMMIT + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.dst_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local --protocol $proto --source-port $sport -j MARK --set-mark 0x539 - COMMIT + fi + if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_udp.dst_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 --protocol $proto --source-port $sport -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - else - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass --protocol $proto --source-port $sport -j MARK --set-mark 0x539$intfid - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local --protocol $proto --source-port $sport -j MARK --set-mark 0x539$intfid - COMMIT - EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 --protocol $proto --source-port $sport -j MARK --set-mark 0x6539$intfid - COMMIT - EOF - fi fi } @@ -398,7 +279,7 @@ _bypass_proto() { [ -z "$noipv6" ] && noipv6="0" [ -z "$family" ] && family="ipv4ipv6" intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" @@ -408,8 +289,8 @@ _bypass_proto() { if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539 - -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539 + -A omr-bypass-dpi -m mark --mark 0x4539 -j RETURN COMMIT EOF fi @@ -425,8 +306,8 @@ _bypass_proto() { if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle - -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x539$intfid - -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539$intfid + -A omr-bypass-dpi -m mark --mark 0x4539$intfid -j RETURN COMMIT EOF fi @@ -497,74 +378,84 @@ _bypass_proto_without_ndpi() { [ -z "$noipv6" ] && noipv6="0" [ -z "$family" ] && family="ipv4ipv6" intf=$(echo $intf | sed -e 's/\./_/') - [ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return local intfid="$(uci -q get omr-bypass.$intf.id)" [ -z "$intf" ] && intf="all" + [ "$intf" = "all" ] && intfid="" [ -z "$proto" ] && return if [ "$(uci -q get openmptcprouter.settings.ndpi)" == "0" ] || [ "$ndpi" == "0" ] || [ "$vpn" = "1" ]; then ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto=\"$proto\";" ".exit") if [ -n "$ALLIPS" ]; then if [ "$vpn" != "1" ]; then - ipset -q flush bypass_$proto > /dev/null 2>&1 - ipset -q flush bypass6_$proto > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create bypass_$proto hash:net hashsize 64 - create bypass6_$proto hash:net family inet6 hashsize 64 + uci -q batch <<-EOF >/dev/null + set firewall.bypass_$proto=ipset + set firewall.bypass_$proto.name="bypass_$proto" + set firewall.bypass_$proto.match='dest_ip' + set firewall.bypass_$proto_rule=rule + set firewall.bypass_$proto_rule.name="bypass_$proto" + set firewall.bypass_$proto_rule.src='lan' + set firewall.bypass_$proto_rule.dest='*' + set firewall.bypass_$proto_rule.target='MARK' + set firewall.bypass_$proto_rule.set_xmark="4539${intfid}" + commit firewall EOF + uci -q batch <<-EOF >/dev/null + set firewall.bypass6_$proto=ipset + set firewall.bypass6_$proto.name="bypas6s_$proto" + set firewall.bypass6_$proto.match='dest_ip' + set firewall.bypass6_$proto_rule=rule + set firewall.bypass6_$proto_rule.name="bypass6_$proto" + set firewall.bypass6_$proto_rule.src='lan' + set firewall.bypass6_$proto_rule.dest='*' + set firewall.bypass6_$proto_rule.target='MARK' + set firewall.bypass6_$proto_rule.set_xmark="6539${intfid}" + commit firewall + EOF + #if [ "$intfid" != "" ]; then + # uci -q batch <<-EOF >/dev/null + # delete network.${1}_fw_rule=rule + # set network.${1}_fw_rule=rule + # set network.${1}_fw_rule.priority=1 + # set network.${1}_fw_rule.mark=0x539${intfid} + # set network.${1}_fw_rule.lookup=${intfid} + # delete network.${1}_fw_rule6=rule6 + # set network.${1}_fw_rule6=rule6 + # set network.${1}_fw_rule6.priority=1 + # set network.${1}_fw_rule6.mark=0x6539${intfid} + # set network.${1}_fw_rule6.lookup=${intfid} + # commit network + # EOF + #fi + + #ipset -q flush bypass_$proto > /dev/null 2>&1 + #ipset -q flush bypass6_$proto > /dev/null 2>&1 + #ipset -q --exist restore <<-EOF + #create bypass_$proto hash:net hashsize 64 + #create bypass6_$proto hash:net family inet6 hashsize 64 + #EOF fi for ip in $ALLIPS; do valid_ip4=$( valid_subnet4 $ip) valid_ip6=$( valid_subnet6 $ip) if [ "$valid_ip4" = "ok" ]; then if [ "$vpn" != "1" ]; then - ipset -q add bypass_$proto $ip + #ipset -q add bypass_$proto $ip + uci -q add_list firewall.bypass_$proto.entry=$ip else - ipset -q add omr_dst_bypass_$intf $ip + #ipset -q add omr_dst_bypass_$intf $ip + uci -q add_list firewall.omr_dst_bypass_$intf_4.entry=$ip fi elif [ "$valid_ip6" = "ok" ]; then if [ "$vpn" != "1" ]; then - ipset -q add bypass6_$proto $ip + #ipset -q add bypass6_$proto $ip + uci -q add_list firewall.bypass6_$proto.entry=$ip else - ipset -q add omr6_dst_bypass_$intf $ip + #ipset -q add omr6_dst_bypass_$intf $ip + uci -q add_list firewall.omr6_dst_bypass_$intf_4.entry=$ip fi fi done - if [ "$intf" = "all" ]; then - if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539 - -A omr-bypass-dpi -m mark --mark 0x539 -j RETURN - COMMIT - EOF - fi - if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6-dpi -m set --match-set bypass6_$proto dst -j MARK --set-mark 0x6539 - -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN - COMMIT - EOF - fi - elif [ "$vpn" != "1" ]; then - if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-dpi -m set --match-set bypass_$proto dst -j MARK --set-mark 0x539$intfid - -A omr-bypass-dpi -m mark --mark 0x539$intfid -j RETURN - COMMIT - EOF - fi - if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6-dpi -m set --match-set bypass6_$proto dst -j MARK --set-mark 0x6539$intfid - -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN - COMMIT - EOF - fi - fi fi fi # Use dnsmasq ipset to bypass domains of the proto @@ -609,52 +500,15 @@ _bypass_proto_without_ndpi() { } _intf_rule_ss_rules() { - rule_name=$1 - [ "$rule_name" = "ss_rules" ] && rule_name="def" - if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_dst)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_dst | grep omr_dst_bypass_$intf)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I ssr_${rule_name}_dst 2 -m mark --mark 0x539$count -j RETURN - COMMIT - EOF - fi - if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_local_out)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_local_out | grep omr_dst_bypass_$intf)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I ssr_${rule_name}_local_out 2 -m mark --mark 0x539$count -j RETURN - COMMIT - EOF - fi - if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$($IPTABLESSAVE 2>/dev/null | grep ssr_${rule_name}_pre_src | grep omr_dst_bypass_$intf)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I ssr_${rule_name}_pre_src 2 -m mark --mark 0x539$count -j RETURN - COMMIT - EOF - fi + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + EOF if [ "$disableipv6" = "0" ]; then - if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep omr6_dst_bypass_$intf)" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -I omr-bypass6 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count - COMMIT - EOF - fi - if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLESSAVE 2>/dev/null | grep ssr6 | grep omr6_dst_bypass_$intf)" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count - -I ssr6_${rule_name}_dst 2 -m mark --mark 0x6539$count -j RETURN - -I ssr6_${rule_name}_local_out 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count - -I ssr6_${rule_name}_local_out 2 -m mark --mark 0x6539$count -j RETURN - -I ssr6_${rule_name}_pre_src 1 -m set --match-set omr6_dst_bypass_$intf dst -j MARK --set-mark 0x6539$count - -I ssr6_${rule_name}_pre_src 2 -m mark --mark 0x6539$count -j RETURN - COMMIT - EOF - fi + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + EOF fi } @@ -766,56 +620,133 @@ _intf_rule_xray_rules() { _intf_rule() { local intf - intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ "$1" = "all" ] && intf="all" + [ -z "$intf" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') [ -z "$intf" ] && config_get intf $1 device [ -n "$(echo $intf | grep '/')" ] && return #count=$((count+1)) - config_get count $1 metric + [ "$intf" != "all" ] && config_get count $1 metric + [ "$intf" = "all" ] && count="" local mode #config_get mode $1 multipath "off" #[ "$mode" = "off" ] && return - [ -z "$count" ] && return + [ "$intf" != "all" ] && [ -z "$count" ] && return [ -z "$intf" ] && return intf=$(echo $intf | sed -e 's/\./_/') + intf=$(echo $intf | sed -e 's/-/_/') [ "$(echo $1 | grep _dev)" != "" ] && return - [ -z "$RELOAD" ] || [ "$(ipset --list | grep omr_dst_bypass_$intf)" = "" ] && { - unset RELOAD - ipset -q flush omr_dst_bypass_$intf > /dev/null 2>&1 - ipset -q flush omr6_dst_bypass_$intf > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create omr_dst_bypass_$intf hash:net hashsize 64 - create omr6_dst_bypass_$intf hash:net family inet6 hashsize 64 + [ "$intf" = "lo" ] && return + [ -z "$intf" ] && return +# [ -z "$RELOAD" ] || [ "$(uci show firewall.omr_dst_bypass_$intf_4)" = "" ] && { + #unset RELOAD + #echo "$intf ip set dhcp" + uci batch <<-EOF + set dhcp.omr_dst_bypass_$intf=ipset + set dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_4,omr_dst_bypass_${intf}_6" + commit dhcp EOF - if [ "$(uci -q get openmptcprouter.settings.uci_rules)" = "1" ]; then + #echo "firewall omr_dst_bypass ipset" + uci -q batch <<-EOF + set firewall.omr_dst_bypass_${intf}_4=ipset + set firewall.omr_dst_bypass_${intf}_4.name="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_4.match='dest_ip' + EOF + #echo "firewall omr_dst_bypass rules" + if [ "$disableipv6" = "0" ]; then + protocol="4 6" + else + protocol="4" + fi + for ipv46 in $protocol; do + echo "ipv46: $ipv46 for $intf" + uci batch <<-EOF + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.name="omr_dst_bypass_${intf}_rule" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.name="omr_dst_bypass_${intf}_srcip" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.name='omr_dst_bypass_${intf}_mac' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.proto='tcp' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.proto='udp' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + commit firewall + EOF + done + if [ "$intf" = "all" ]; then uci -q batch <<-EOF >/dev/null - delete network.${1}_fw_rule=rule - set network.${1}_fw_rule=rule - set network.${1}_fw_rule.priority=1 - set network.${1}_fw_rule.mark=0x539${count} - set network.${1}_fw_rule.lookup=${count} - delete network.${1}_fw_rule6=rule6 - set network.${1}_fw_rule6=rule6 - set network.${1}_fw_rule6.priority=1 - set network.${1}_fw_rule6.mark=0x6539${count} - set network.${1}_fw_rule6.lookup=${count} + delete network.${intf}_fw_rule=rule + set network.${intf}_fw_rule=rule + set network.${intf}_fw_rule.priority=1 + set network.${intf}_fw_rule.mark=0x4539 + set network.${intf}_fw_rule.lookup=991337 + delete network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6.priority=1 + set network.${intf}_fw_rule6.mark=0x6539 + set network.${intf}_fw_rule6.lookup=6991337 commit network EOF else - ip rule add prio 1 fwmark 0x539$count lookup $count pref 1 > /dev/null 2>&1 - ip -6 rule add prio 1 fwmark 0x6539$count lookup 6$count pref 1 > /dev/null 2>&1 + uci -q batch <<-EOF >/dev/null + delete network.${intf}_fw_rule=rule + set network.${intf}_fw_rule=rule + set network.${intf}_fw_rule.priority=1 + set network.${intf}_fw_rule.mark=0x4539${count} + set network.${intf}_fw_rule.lookup=${count} + delete network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6.priority=1 + set network.${intf}_fw_rule6.mark=0x6539${count} + set network.${intf}_fw_rule6.lookup=${count} + commit network + EOF fi - } - if [ "$($IPTABLESSAVE 2>/dev/null | grep omr-bypass | grep omr_dst_bypass_$intf)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -I omr-bypass 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I omr-bypass 2 -m mark --mark 0x539$count -j RETURN - -I omr-bypass-local 1 -m set --match-set omr_dst_bypass_$intf dst -j MARK --set-mark 0x539$count - -I omr-bypass-local 2 -m mark --mark 0x539$count -j RETURN - COMMIT - EOF - fi + if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then config_load shadowsocks-libev config_foreach _intf_rule_ss_rules ss_rules @@ -856,7 +787,6 @@ _bypass_asn() { for ip in $asnips; do _bypass_ip $ip $interface done - } bypass_asn() { @@ -872,40 +802,15 @@ _bypass_omr_server() { _ss_rules_config() { - rule_name=$1 - [ "$rule_name" = "ss_rules" ] && rule_name="def" - if [ "$($IPTABLES --wait=40 -t nat -L -n | grep ssr_${rule_name}_pre_src)" != "" ] && [ "$($IPTABLES --wait=40 -t nat -L -n | grep omr_dst_bypass_all)" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr_${rule_name}_dst 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -I ssr_${rule_name}_dst 2 -m mark --mark 0x539 -j RETURN - -I ssr_${rule_name}_local_out 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -I ssr_${rule_name}_local_out 2 -m mark --mark 0x539 -j RETURN - -I ssr_${rule_name}_pre_src 1 -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -I ssr_${rule_name}_pre_src 2 -m mark --mark 0x539 -j RETURN - COMMIT - EOF - fi + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + EOF if [ "$disableipv6" = "0" ]; then - if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 - COMMIT - EOF - fi - if [ "$($IP6TABLES --wait=40 -t nat -L -n | grep ssr6_${rule_name}_pre_src)" != "" ] && [ "$($IP6TABLES --wait=40 -t nat -L -n | grep omr6_dst_bypass_all)" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *nat - -I ssr6_${rule_name}_dst 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 - -I ssr6_${rule_name}_dst 1 -m mark --mark 0x6539 -j RETURN - -I ssr6_${rule_name}_local_out 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 - -I ssr6_${rule_name}_local_out 2 -m mark --mark 0x6539 -j RETURN - -I ssr6_${rule_name}_pre_src 1 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x6539 - -I ssr6_${rule_name}_pre_src 2 -m mark --mark 0x6539 -j RETURN - COMMIT - EOF - fi + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + EOF fi } @@ -987,6 +892,18 @@ _xray_rules_config() { fi } +_delete_dhcp_ipset() { + [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { + uci -q delete dhcp.$1 + } +} + +_delete_firewall_rules() { + [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { + uci -q delete firewall.$1 + } +} + boot() { BOOT=1 start "$@" @@ -995,6 +912,16 @@ boot() { start_service() { #local count logger -t "omr-bypass" "Starting OMR-ByPass..." + + config_load dhcp + config_foreach _delete_dhcp_ipset ipset + #uci -q commit dhcp + config_load firewall + config_foreach _delete_firewall_rules rule + config_foreach _delete_firewall_rules ipset + #uci -q commit firewall + + add_domains="false" [ -d /proc/net/xt_ndpi ] && { config_load omr-bypass @@ -1003,128 +930,58 @@ start_service() { disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" #noipv6="$(uci -q get omr-bypass.global.noipv6)" - [ -n "$RELOAD" ] && [ "$(ipset --list | grep omr_dst_bypass_all)" = "" ] && { - unset RELOAD - } - [ -z "$RELOAD" ] && { - ipset -q flush omr_dst_bypass_all > /dev/null 2>&1 - ipset -q flush omr6_dst_bypass_all > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create omr_dst_bypass_all hash:net hashsize 64 - create omr6_dst_bypass_all hash:net family inet6 hashsize 64 - EOF - ipset -q flush omr_dst_bypass_srv_vpn1 > /dev/null 2>&1 - ipset -q flush omr6_dst_bypass_srv_vpn1 > /dev/null 2>&1 - ipset -q --exist restore <<-EOF - create omr_dst_bypass_srv_vpn1 hash:net hashsize 64 - create omr6_dst_bypass_srv_vpn1 hash:net family inet6 hashsize 64 - EOF - } - $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - :omr-bypass - - -A PREROUTING -j omr-bypass - COMMIT + cat > /etc/firewall.omr-bypass <<-EOF + #!/bin/sh + #nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all accept + #nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all accept EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - :omr-bypass-local - - -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass-local - COMMIT + uci batch <<-EOF + set firewall.omr_bypass=include + set firewall.omr_bypass.enabled='1' + set firewall.omr_bypass.type='script' + set firewall.omr_bypass.path='/etc/firewall.omr-bypass' + set firewall.omr_bypass.fw4_compatible='1' + commit firewall EOF - if [ "$disableipv6" = "0" ]; then - $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - :omr-bypass6 - - -A PREROUTING -j omr-bypass6 - COMMIT - EOF - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - :omr-bypass6-local - - -A OUTPUT -m addrtype ! --dst-type LOCAL -j omr-bypass6-local - COMMIT - EOF - fi - + echo "intf_rule" config_load network config_foreach _intf_rule interface + _intf_rule all local ndpi_rules="" + echo "bypass server" if [ "$(uci -q get openmptcprouter.settings.bypass_servers)" = "1" ]; then config_load openmptcprouter config_foreach _bypass_omr_server server fi config_load omr-bypass + echo "bypass ip" config_foreach _bypass_ip_set ips + echo "bypass mac" config_foreach _bypass_mac macs + echo "bypass lan ip" config_foreach _bypass_lan_ip lan_ip + echo "bypass dest port" config_foreach _bypass_dest_port dest_port + echo "bypass src port" config_foreach _bypass_src_port src_port + echo "bypass asn" config_foreach _bypass_asn asns - dnsmasqipset=$(uci -q get dhcp.@dnsmasq[0].ipset | sed 's/ /\n/g' | grep -v dst_bypass) - uci -q delete dhcp.@dnsmasq[0].ipset - uci -q delete dhcp.@dnsmasq[0].noipv6 - if [ -n "$dnsmasqipset" ]; then - for dnsipset in $dnsmasqipset; do - ipsets="" - allipsets=$(echo $dnsipset | cut -d/ -f3 | sed 's/,/\n/g') - for ipset in $allipsets; do - [ "$(echo $ipset | grep -v dst_bypass)" != "" ] && { - [ "$ipsets" != "" ] && ipsets="$ipsets,$ipset" - [ "$ipsets" = "" ] && ipsets="$ipset" - } - done - if [ "$ipsets" != "" ]; then - resultipset="/$(echo $dnsipset | cut -d/ -f2)/$ipsets" - [ -n "$resultipset" ] && uci -q add_list dhcp.@dnsmasq[0].ipset=$resultipset - fi - done - fi + echo "bypass domains" config_foreach _bypass_domains domains uci -q commit dhcp - ip rule add prio 1 fwmark 0x539 lookup 991337 > /dev/null 2>&1 - ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 +# ip rule add prio 1 fwmark 0x4539 lookup 991337 > /dev/null 2>&1 +# ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 - if [ "$($IPTABLES --wait=40 -t mangle -L -n | grep 'match-set omr_dst_bypass_all dst MARK set')" = "" ]; then - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -A omr-bypass -m mark --mark 0x539 -j RETURN - COMMIT - EOF - $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass-local -m set --match-set omr_dst_bypass_all dst -j MARK --set-mark 0x539 - -A omr-bypass-local -m mark --mark 0x539 -j RETURN - COMMIT - EOF - fi - if [ "$disableipv6" = "0" ]; then - if [ "$($IP6TABLES --wait=40 -t mangle -L -n | grep 'match-set omr6_dst_bypass_all dst MARK set')" = "" ]; then - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6 -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x539 - -A omr-bypass6 -m mark --mark 0x539 -j RETURN - COMMIT - EOF - $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF - *mangle - -A omr-bypass6-local -m set --match-set omr6_dst_bypass_all dst -j MARK --set-mark 0x539 - -A omr-bypass6-local -m mark --mark 0x539 -j RETURN - COMMIT - EOF - fi - fi - config_load shadowsocks-libev - config_foreach _ss_rules_config - config_load shadowsocks-rust - config_foreach _ss_rules_config + #config_load shadowsocks-libev + #config_foreach _ss_rules_config ss_rules + ([ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] || [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]) && _ss_rules_config + #config_load shadowsocks-rust + #config_foreach _ss_rules_config ss_rules _v2ray_rules_config _xray_rules_config + # NDPI Netfilter is not available for nftables $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass-dpi | $IPTABLESRESTORE -w --counters 2>/dev/null $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF *mangle @@ -1156,7 +1013,7 @@ start_service() { logger -t "omr-bypass" "Reload dnsmasq..." /etc/init.d/dnsmasq reload } - + fw4 restart # Create a protocol list for UI from a sqlite DB when NDPI is not available sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst config_load omr-bypass @@ -1168,15 +1025,25 @@ start_service() { stop_service() { $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null - $IPTABLESSAVE --counters 2>/dev/null | grep -v omr_dst | $IPTABLESRESTORE -w --counters 2>/dev/null +# $IPTABLESSAVE --counters 2>/dev/null | grep -v omr_dst | $IPTABLESRESTORE -w --counters 2>/dev/null $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null - $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr6_dst | $IP6TABLESRESTORE -w --counters 2>/dev/null - for setname in $(ipset -n list | grep "omr_"); do - ipset -q destroy "$setname" 2>/dev/null || true - done - for setname in $(ipset list | awk '/Name: bypass_/ {print $2}'); do - ipset -q destroy "$setname" 2>/dev/null || true - done +# $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr6_dst | $IP6TABLESRESTORE -w --counters 2>/dev/null + #for setname in $(ipset -n list | grep "omr_"); do + # ipset -q destroy "$setname" 2>/dev/null || true + #done + #for setname in $(ipset list | awk '/Name: bypass_/ {print $2}'); do + # ipset -q destroy "$setname" 2>/dev/null || true + #done + # disable all rules ? + uci -q set firewall.omr-bypass.enabled='0' + config_load dhcp + config_foreach _delete_dhcp_ipset ipset + uci -q commit dhcp + config_load firewall + config_foreach _delete_firewall_rules rule + config_foreach _delete_firewall_rules ipset + uci -q commit firewall + exit 0 } service_triggers() { diff --git a/omr-bypass/files/etc/init.d/omr-bypass-nft b/omr-bypass/files/etc/init.d/omr-bypass-nft new file mode 100755 index 000000000..3bb187e8c --- /dev/null +++ b/omr-bypass/files/etc/init.d/omr-bypass-nft @@ -0,0 +1,926 @@ +#!/bin/sh /etc/rc.common +# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) for OpenMPTCProuter + +START=98 +STOP=10 +USE_PROCD=1 +EXTRA_COMMANDS="reload_rules bypass_asn" + +. /usr/lib/unbound/iptools.sh + +# Still used by ndpi +if [ -e /usr/sbin/iptables-nft ]; then + IPTABLES="/usr/sbin/iptables-nft" + IPTABLESRESTORE="/usr/sbin/iptables-nft-restore" + IPTABLESSAVE="/usr/sbin/iptables-nft-save" + IP6TABLES="/usr/sbin/ip6tables-nft" + IP6TABLESRESTORE="/usr/sbin/ip6tables-nft-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-nft-save" +else + IPTABLES="/usr/sbin/iptables" + IPTABLESRESTORE="/usr/sbin/iptables-restore" + IPTABLESSAVE="/usr/sbin/iptables-save" + IP6TABLES="/usr/sbin/ip6tables" + IP6TABLESRESTORE="/usr/sbin/ip6tables-restore" + IP6TABLESSAVE="/usr/sbin/ip6tables-save" +fi + +_add_proto() { + protoname=$1 + [ -z "$protoname" ] && return + if [ "$(dd if=/proc/net/xt_ndpi/proto bs=4096 2> /dev/null | grep $protoname)" = "" ]; then + echo "add_custom $protoname" >/proc/net/xt_ndpi/proto + fi + allurls="$(dd if=/proc/net/xt_ndpi/host_proto bs=4096 2> /dev/null)" + hosts="$( uci -q get omr-bypass.$protoname.url )" + for url in $hosts; do + if [ "$(echo "$allurls" | grep -i ^${protoname}: | grep $url)" = "" ]; then + echo "$protoname:$url" >/proc/net/xt_ndpi/host_proto + fi + done + ip="$( uci -q get omr-bypass.$protoname.ip )" + for ip in $ips; do + if [ "$(echo "$allurls" | grep -i ^${protoname}: | grep $ip)" = "" ]; then + echo "$protoname:$ip" >/proc/net/xt_ndpi/ip_proto + fi + done +} + +_add_proto_without_ndpi() { + protoname=$1 + [ -z "$protoname" ] && return + echo "$protoname" >> /usr/share/omr-bypass/omr-bypass-proto.lst +} + +_bypass_ip() { + local ip=$1 + local type=$2 + [ -z "$type" ] && type="all" + valid_ip4=$( valid_subnet4 $ip) + valid_ip6=$( valid_subnet6 $ip) + if [ "$valid_ip4" = "ok" ]; then + uci -q add_list firewall.omr_dst_bypass_${type}_4.entry=$ip + uci -q set firewall.omr_dst_bypass_${type}_4.enabled='1' + uci -q set firewall.omr_dst_bypass_${type}_dstip_4.enabled='1' + elif [ "$valid_ip6" = "ok" ]; then + uci -q add_list firewall.omr_dst_bypass_${type}_6.entry=$ip + uci -q set firewall.omr_dst_bypass_${type}_6.enabled='1' + uci -q set firewall.omr_dst_bypass_${type}_dstip_6.enabled='1' + fi +} + +_bypass_domains() { + local domain + local intf + local enabled + config_get domain $1 name + config_get intf $1 interface + config_get enabled $1 enabled + config_get noipv6 $1 noipv6 + config_get family $1 family + [ -z "$intf" ] && intf="all" + config_get vpn $1 vpn + [ "$vpn" = "1" ] && intf="srv_vpn1" + #echo "bypass $domain $enabled $family $intf $vpn" + [ "$enabled" = "0" ] && return + [ -z "$domain" ] && return + [ -z "$family" ] && family="ipv4ipv6" + [ -z "$noipv6" ] && noipv6="0" + if [ "$(echo $domain | grep '\.$')" != "" ] || [ "$(echo $domain | grep '\.\*$')" != "" ]; then + tlds=`curl --max-time 4 -s -k https://data.iana.org/TLD/tlds-alpha-by-domain.txt` + domain="$(echo '"$domain"' | sed 's:*::')" + domainlist="" + # construct list of domains to query + i=0 + for tld in $tlds; do + i=$((i+1)) + # trim off header + if [ "$i" -lt "12" ] || [ "$i" -gt "50" ]; then + continue + fi + # add to command + domainlist="${domainlist} ${domain}${tld}" + done + domainlist="$(echo $domainlist `# Get the list of valid domains, pass it to awk` \ + | awk '{print tolower($0)}' `# awk lowercases the whole string and passes it to ` \ + | xargs -n8 -P12 `# xargs sends 8 arguments at a time to` \ + dig a +timeout=1 +tries=1 +retry=1 +nocmd +noall +answer `# dig, which passes results (if any) to` \ + | awk '{print $1}' `# awk, which outputs queried domain to` \ + | sed -e 's/.$//' `# sed, which trims off the trailing dot (google.com. -> google.com)` to \ + | grep $domain `# grep, only keep wanted domain` \ + | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate + for validdomain in $domainlist; do + _bypass_domain $validdomain $intf $family $noipv6 + done + else + #echo "_bypass_domain $domain $intf $family $noipv6" + _bypass_domain $domain $intf $family $noipv6 + fi +} + +_bypass_domain() { + local domain=$1 + local intf=$2 + local family=$3 + local noipv6=$4 + intf=$(echo $intf | sed -e 's/\./_/') + [ -z "$intf" ] && intf="all" + if [ -n "$domain" ]; then + domain=$(echo $domain | sed 's:^\.::') + #logger -t "omr-bypass" "Get IPs of $domain..." + if [ -z $RELOAD ]; then + resolve=$(dig a +timeout=1 +tries=1 +nocmd +noall +answer $domain | grep -v CNAME | awk '{print $5}') + for ip in $resolve; do + _bypass_ip $ip $intf + done + if [ "$disableipv6" = "0" ]; then + resolve=$(dig aaaa +timeout=1 +tries=1 +nocmd +noall +answer $domain | grep AAAA | awk '{print $5}') + for ip in $resolve; do + _bypass_ip $ip $intf + done + fi + fi + if [ "$(uci -q get dhcp.omr_dst_bypass_$intf | grep /$domain/)" = "" ]; then + uci -q add_list dhcp.omr_dst_bypass_$intf.domain=$domain + add_domains="true" + fi + if [ "$(uci -q get dhcp.@dnsmasq[0].noipv6 | grep /$domain/)" = "" ] && [ "$noipv6" = "1" ]; then + uci -q add_list dhcp.@dnsmasq[0].noipv6="$domain" + fi + #logger -t "omr-bypass" "Get IPs of $domain... Done" + fi +} + +_bypass_mac() { + local mac + local intf + local enabled + config_get mac $1 mac + config_get intf $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$mac" ] && return + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_$intf_mac.src_mac="$mac" + EOF +} + +_bypass_lan_ip() { + local ip + local intf + local enabled + config_get ip $1 ip + config_get intf $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$ip" ] && return + valid_ip4=$(valid_subnet4 $ip) + valid_ip6=$(valid_subnet6 $ip) + if [ "$valid_ip4" = "ok" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcip_4.src_ip="$ip" + set firewall.omr_dst_bypass_${intf}_srcip_4.enabled='1' + EOF + elif [ "$valid_ip6" = "ok" ] && [ "$disableipv6" = "0" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_srcip_6.src_ip="$ip" + set firewall.omr_dst_bypass_${intf}_srcip_6.enabled='1' + EOF + fi +} + +_bypass_dest_port() { + local intf + local enabled + local dport + local proto + config_get dport $1 dport + config_get proto $1 proto + config_get intf $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$dport" ] && return + dport="$(echo $dport | sed 's/:/-/')" + [ -z "$proto" ] && return + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.dest_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' + EOF + fi + if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_udp.dest_port="$dport" + set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' + EOF + fi +} + +_bypass_src_port() { + local intf + local enabled + local sport + local proto + config_get sport $1 sport + config_get proto $1 proto + config_get intf $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$sport" ] && return + sport="$(echo $sport | sed 's/:/-/')" + [ -z "$proto" ] && return + if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_tcp.src_port="$sport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp.enabled='1' + EOF + fi + if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then + uci -q batch <<-EOF + add_list firewall.omr_dst_bypass_${intf}_dstport_udp.src_port="$sport" + set firewall.omr_dst_bypass_${intf}_dstport_udp.enabled='1' + EOF + fi +} + +_bypass_proto() { + local proto + local intf + local enabled + config_get proto $1 proto + config_get intf $1 interface + config_get enabled $1 enabled + config_get ndpi $1 ndpi + config_get noipv6 $1 noipv6 + config_get family $1 family + config_get vpn $1 vpn + [ "$vpn" = "1" ] && intf="srv_vpn1" + + [ "$enabled" = "0" ] && return + [ -z "$noipv6" ] && noipv6="0" + [ -z "$family" ] && family="ipv4ipv6" + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ -z "$proto" ] && return + if [ "$(uci -q get openmptcprouter.settings.ndpi)" != "0" ] && [ "$ndpi" != "0" ] && [ "$vpn" != "1" ]; then + if [ "$intf" = "all" ]; then + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539 + -A omr-bypass-dpi -m mark --mark 0x4539 -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539 + -A omr-bypass6-dpi -m mark --mark 0x6539 -j RETURN + COMMIT + EOF + fi + else + if [ "$family" = "ipv4" ] || [ "$family" = "ipv4ipv6" ]; then + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass-dpi -m ndpi --proto $proto -j MARK --set-mark 0x4539$intfid + -A omr-bypass-dpi -m mark --mark 0x4539$intfid -j RETURN + COMMIT + EOF + fi + if [ "$disableipv6" = "0" ] && ([ "$family" = "ipv6" ] || [ "$family" = "ipv4ipv6" ]); then + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + -A omr-bypass6-dpi -m ndpi --proto $proto -j MARK --set-mark 0x6539$intfid + -A omr-bypass6-dpi -m mark --mark 0x6539$intfid -j RETURN + COMMIT + EOF + fi + fi + fi + # Use dnsmasq ipset to bypass domains of the proto + local domains + domains="$(cat /proc/net/xt_ndpi/host_proto | grep -i $proto: | sed -e "s/$proto://i" -e 's/*//' -e 's/,/ /g')" + if [ -n "$domains" ]; then + tlds=`curl --max-time 4 -s -k https://data.iana.org/TLD/tlds-alpha-by-domain.txt` + for domain in $domains; do + if [ -n "$domain" ]; then + domain="$(echo $domain | sed 's/^\.//')" + if [ "$(echo $domain | grep '\.$')" != "" ]; then + domainlist="" + # construct list of domains to query + i=0 + for tld in $tlds; do + i=$((i+1)) + # trim off header + if [ "$i" -lt "12" ] || [ "$i" -gt "50" ]; then + continue + fi + # add to command + domainlist="${domainlist} ${domain}${tld}" + done + domainlist="$(echo $domainlist `# Get the list of valid domains, pass it to awk` \ + | awk '{print tolower($0)}' `# awk lowercases the whole string and passes it to ` \ + | xargs -n8 -P12 `# xargs sends 8 arguments at a time to` \ + dig a +timeout=1 +tries=1 +retry=1 +nocmd +noall +answer `# dig, which passes results (if any) to` \ + | awk '{print $1}' `# awk, which outputs queried domain to` \ + | sed -e 's/.$//' `# sed, which trims off the trailing dot (google.com. -> google.com)` to \ + | grep $domain `# grep, only keep wanted domain` \ + | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate + for validdomain in $domainlist; do + _bypass_domain $validdomain $intf $family $noipv6 + done + else + _bypass_domain $domain $intf $family $noipv6 + fi + fi + done + fi +} + +_bypass_proto_without_ndpi() { + local proto + local intf + local enabled + config_get proto $1 proto + config_get intf $1 interface + config_get enabled $1 enabled + config_get ndpi $1 ndpi "0" + config_get noipv6 $1 noipv6 + config_get family $1 family + config_get vpn $1 vpn + [ "$vpn" = "1" ] && intf="srv_vpn1" + + [ "$enabled" = "0" ] && return + [ -z "$noipv6" ] && noipv6="0" + [ -z "$family" ] && family="ipv4ipv6" + intf=$(echo $intf | sed -e 's/\./_/') + #[ -n "$intf" ] && [ -z "$(ipset --list | grep omr_dst_bypass_$intf)" ] && return + local intfid="$(uci -q get omr-bypass.$intf.id)" + + [ -z "$intf" ] && intf="all" + [ "$intf" = "all" ] && intfid="" + [ -z "$proto" ] && return + if [ "$(uci -q get openmptcprouter.settings.ndpi)" == "0" ] || [ "$ndpi" == "0" ] || [ "$vpn" = "1" ]; then + ALLIPS=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select ip from ipproto where proto=\"$proto\";" ".exit") + if [ -n "$ALLIPS" ]; then + if [ "$vpn" != "1" ]; then + uci -q batch <<-EOF >/dev/null + set firewall.bypass_$proto=ipset + set firewall.bypass_$proto.name="bypass_$proto" + set firewall.bypass_$proto.match='dest_ip' + set firewall.bypass_$proto_rule=rule + set firewall.bypass_$proto_rule.name="bypass_$proto" + set firewall.bypass_$proto_rule.src='lan' + set firewall.bypass_$proto_rule.dest='*' + set firewall.bypass_$proto_rule.target='MARK' + set firewall.bypass_$proto_rule.set_xmark="4539${intfid}" + commit firewall + EOF + uci -q batch <<-EOF >/dev/null + set firewall.bypass6_$proto=ipset + set firewall.bypass6_$proto.name="bypas6s_$proto" + set firewall.bypass6_$proto.match='dest_ip' + set firewall.bypass6_$proto_rule=rule + set firewall.bypass6_$proto_rule.name="bypass6_$proto" + set firewall.bypass6_$proto_rule.src='lan' + set firewall.bypass6_$proto_rule.dest='*' + set firewall.bypass6_$proto_rule.target='MARK' + set firewall.bypass6_$proto_rule.set_xmark="6539${intfid}" + commit firewall + EOF + #if [ "$intfid" != "" ]; then + # uci -q batch <<-EOF >/dev/null + # delete network.${1}_fw_rule=rule + # set network.${1}_fw_rule=rule + # set network.${1}_fw_rule.priority=1 + # set network.${1}_fw_rule.mark=0x539${intfid} + # set network.${1}_fw_rule.lookup=${intfid} + # delete network.${1}_fw_rule6=rule6 + # set network.${1}_fw_rule6=rule6 + # set network.${1}_fw_rule6.priority=1 + # set network.${1}_fw_rule6.mark=0x6539${intfid} + # set network.${1}_fw_rule6.lookup=${intfid} + # commit network + # EOF + #fi + + #ipset -q flush bypass_$proto > /dev/null 2>&1 + #ipset -q flush bypass6_$proto > /dev/null 2>&1 + #ipset -q --exist restore <<-EOF + #create bypass_$proto hash:net hashsize 64 + #create bypass6_$proto hash:net family inet6 hashsize 64 + #EOF + fi + for ip in $ALLIPS; do + valid_ip4=$( valid_subnet4 $ip) + valid_ip6=$( valid_subnet6 $ip) + if [ "$valid_ip4" = "ok" ]; then + if [ "$vpn" != "1" ]; then + #ipset -q add bypass_$proto $ip + uci -q add_list firewall.bypass_$proto.entry=$ip + else + #ipset -q add omr_dst_bypass_$intf $ip + uci -q add_list firewall.omr_dst_bypass_$intf_4.entry=$ip + fi + elif [ "$valid_ip6" = "ok" ]; then + if [ "$vpn" != "1" ]; then + #ipset -q add bypass6_$proto $ip + uci -q add_list firewall.bypass6_$proto.entry=$ip + else + #ipset -q add omr6_dst_bypass_$intf $ip + uci -q add_list firewall.omr6_dst_bypass_$intf_4.entry=$ip + fi + fi + done + fi + fi + # Use dnsmasq ipset to bypass domains of the proto + local domains + #domains="$(cat /proc/net/xt_ndpi/host_proto | grep -i $proto: | sed -e "s/$proto://i" -e 's/*//' -e 's/,/ /g')" + domains=$(sqlite3 /usr/share/omr-bypass/omr-bypass.db "select host from hostproto where proto='"$proto"';" ".exit") + if [ -n "$domains" ]; then + tlds=`curl --max-time 4 -s -k https://data.iana.org/TLD/tlds-alpha-by-domain.txt` + for domain in $domains; do + if [ -n "$domain" ]; then + domain="$(echo $domain | sed 's/^\.//')" + if [ "$(echo $domain | grep '\.$')" != "" ]; then + domainlist="" + # construct list of domains to query + i=0 + for tld in $tlds; do + i=$((i+1)) + # trim off header + if [ "$i" -lt "2" ] || [ "${#tld}" -gt "3" ]; then + continue + fi + # add to command + domainlist="${domainlist} ${domain}${tld}" + done + domainlist="$(echo $domainlist `# Get the list of valid domains, pass it to awk` \ + | awk '{print tolower($0)}' `# awk lowercases the whole string and passes it to ` \ + | xargs -n8 -P12 `# xargs sends 8 arguments at a time to` \ + dig a +timeout=1 +tries=1 +retry=1 +nocmd +noall +answer `# dig, which passes results (if any) to` \ + | awk '{print $1}' `# awk, which outputs queried domain to` \ + | sed 's/.$//' `# sed, which trims off the trailing dot (google.com. -> google.com) to` \ + | grep $domain `# grep, only keep wanted domain` \ + | awk '{for (i=1;i<=NF;i++) if (!a[$i]++) printf("%s%s",$i,FS)}{printf("\n")}')" # deduplicate + for validdomain in $domainlist; do + _bypass_domain $validdomain $intf $family $noipv6 + done + else + _bypass_domain $domain $intf $family $noipv6 + fi + fi + done + fi +} + +_intf_rule_ss_rules() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + EOF + fi +} + +_intf_rule_v2ray_rules() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 v2r_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 v2r_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 v2r_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 v2r_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + EOF + fi +} + +_intf_rule_xray_rules() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 xr_rules_dst_tcp ip daddr @omr_dst_bypass_${intf}_4 accept + nft insert rule inet fw4 xr_rules_local_out ip daddr @omr_dst_bypass_${intf}_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 xr_rules_dst_tcp ip6 daddr @omr_dst_bypass_${intf}_6 accept + nft insert rule inet fw4 xr_rules_local_out ip6 daddr @omr_dst_bypass_${intf}_6 accept + EOF + fi +} + +_intf_rule() { + local intf + [ "$1" = "all" ] && intf="all" + [ -z "$intf" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["l3_device"]') + [ -n "$(echo $intf | grep '@')" ] && intf=$(ifstatus "$1" | jsonfilter -q -e '@["device"]') + [ -z "$intf" ] && config_get intf $1 device + [ -n "$(echo $intf | grep '/')" ] && return + #count=$((count+1)) + [ "$intf" != "all" ] && config_get count $1 metric + [ "$intf" = "all" ] && count="" + local mode + #config_get mode $1 multipath "off" + #[ "$mode" = "off" ] && return + [ "$intf" != "all" ] && [ -z "$count" ] && return + [ -z "$intf" ] && return + intf=$(echo $intf | sed -e 's/\./_/') + intf=$(echo $intf | sed -e 's/-/_/') + [ "$(echo $1 | grep _dev)" != "" ] && return + [ "$intf" = "lo" ] && return + [ -z "$intf" ] && return +# [ -z "$RELOAD" ] || [ "$(uci show firewall.omr_dst_bypass_$intf_4)" = "" ] && { + #unset RELOAD + #echo "$intf ip set dhcp" + uci batch <<-EOF + set dhcp.omr_dst_bypass_$intf=ipset + add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_4" + add_list dhcp.omr_dst_bypass_$intf.name="omr_dst_bypass_${intf}_6" + commit dhcp + EOF + #echo "firewall omr_dst_bypass ipset" + uci -q batch <<-EOF + set firewall.omr_dst_bypass_${intf}_4=ipset + set firewall.omr_dst_bypass_${intf}_4.name="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_4.match='dest_ip' + EOF + #echo "firewall omr_dst_bypass rules" + if [ "$disableipv6" = "0" ]; then + protocol="4 6" + else + protocol="4" + fi + for ipv46 in $protocol; do + echo "ipv46: $ipv46 for $intf" + uci batch <<-EOF + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.name="omr_dst_bypass_${intf}_rule" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.name="omr_dst_bypass_${intf}_srcip" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.ipset="omr_dst_bypass_${intf}_4" + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcip_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.name='omr_dst_bypass_${intf}_mac' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.proto='tcp' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.name="omr_dst_bypass_${intf}_srcport" + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.proto='udp' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.set_xmark="${ipv46}539${count}" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}=rule + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.name="omr_dst_bypass_${intf}_dstport" + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.src='lan' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.dest='*' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.target='MARK' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.enabled='0' + set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.set_xmark="${ipv46}539${count}" + commit firewall + EOF + done + if [ "$intf" = "all" ]; then + uci -q batch <<-EOF >/dev/null + delete network.${intf}_fw_rule=rule + set network.${intf}_fw_rule=rule + set network.${intf}_fw_rule.priority=1 + set network.${intf}_fw_rule.mark=0x4539 + set network.${intf}_fw_rule.lookup=991337 + delete network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6.priority=1 + set network.${intf}_fw_rule6.mark=0x6539 + set network.${intf}_fw_rule6.lookup=6991337 + commit network + EOF + else + uci -q batch <<-EOF >/dev/null + delete network.${intf}_fw_rule=rule + set network.${intf}_fw_rule=rule + set network.${intf}_fw_rule.priority=1 + set network.${intf}_fw_rule.mark=0x4539${count} + set network.${intf}_fw_rule.lookup=${count} + delete network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6=rule6 + set network.${intf}_fw_rule6.priority=1 + set network.${intf}_fw_rule6.mark=0x6539${count} + set network.${intf}_fw_rule6.lookup=${count} + commit network + EOF + fi + + if [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks" ]; then + config_load shadowsocks-libev + config_foreach _intf_rule_ss_rules ss_rules + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "shadowsocks-rust" ]; then + config_load shadowsocks-rust + config_foreach _intf_rule_ss_rules ss_rules + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "v2ray" ]; then + _intf_rule_v2ray_rules + elif [ "$(uci -q get openmptcprouter.settings.proxy)" = "xray" ]; then + _intf_rule_xray_rules + fi + + uci -q set omr-bypass.$intf=interface + uci -q set omr-bypass.$intf.id=$count +} + +_bypass_ip_set() { + local ip + local interface + local enabled + config_get ip $1 ip + config_get interface $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + _bypass_ip $ip $interface +} + +_bypass_asn() { + local asn + local interface + local enabled + config_get asn $1 asn + config_get interface $1 interface + config_get enabled $1 enabled + [ "$enabled" = "0" ] && return + local asnips + asnips=`curl --max-time 4 -s -k https://stat.ripe.net/data/announced-prefixes/data.json?resource=${asn} | jsonfilter -q -e '@.data.prefixes.*.prefix'` + for ip in $asnips; do + _bypass_ip $ip $interface + done +} + +bypass_asn() { + config_load omr-bypass + config_foreach _bypass_asn asns +} + +_bypass_omr_server() { + local ip + config_get ip $1 ip + _bypass_ip $ip +} + + +_ss_rules_config() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 ss_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + nft insert rule inet fw4 ss_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + EOF + fi +} + +_v2ray_rules_config() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 v2r_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + nft insert rule inet fw4 v2r_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 v2r_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + nft insert rule inet fw4 v2r_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + EOF + fi +} + +_xray_rules_config() { + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 xr_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 accept + nft insert rule inet fw4 xr_rules_local_out ip daddr @omr_dst_bypass_all_4 accept + EOF + if [ "$disableipv6" = "0" ]; then + cat >> /etc/firewall.omr-bypass <<-EOF + nft insert rule inet fw4 xr_rules_dst_tcp ip6 daddr @omr_dst_bypass_all_6 accept + nft insert rule inet fw4 xr_rules_local_out ip6 daddr @omr_dst_bypass_all_6 accept + EOF + fi +} + +_delete_dhcp_ipset() { + [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { + uci -q delete dhcp.$1 + } +} + +_delete_firewall_rules() { + [ -n "$(echo $1 | grep omr_dst_bypass)" ] && { + uci -q delete firewall.$1 + } +} + +boot() { + BOOT=1 + start "$@" +} + +start_service() { + #local count + logger -t "omr-bypass" "Starting OMR-ByPass..." + + config_load dhcp + config_foreach _delete_dhcp_ipset ipset + #uci -q commit dhcp + config_load firewall + config_foreach _delete_firewall_rules rule + config_foreach _delete_firewall_rules ipset + #uci -q commit firewall + + + add_domains="false" + [ -d /proc/net/xt_ndpi ] && { + config_load omr-bypass + config_foreach _add_proto proto + } + disableipv6="$(uci -q get openmptcprouter.settings.disable_ipv6)" + #noipv6="$(uci -q get omr-bypass.global.noipv6)" + + cat > /etc/firewall.omr-bypass <<-EOF + #!/bin/sh + #nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all accept + #nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all accept + EOF + uci batch <<-EOF + set firewall.omr_bypass=include + set firewall.omr_bypass.enabled='1' + set firewall.omr_bypass.type='script' + set firewall.omr_bypass.path='/etc/firewall.omr-bypass' + set firewall.omr_bypass.fw4_compatible='1' + commit firewall + EOF + echo "intf_rule" + config_load network + config_foreach _intf_rule interface + _intf_rule all + _intf_rule vpn1 + local ndpi_rules="" + echo "bypass server" + if [ "$(uci -q get openmptcprouter.settings.bypass_servers)" = "1" ]; then + config_load openmptcprouter + config_foreach _bypass_omr_server server + fi + config_load omr-bypass + echo "bypass ip" + config_foreach _bypass_ip_set ips + echo "bypass mac" + config_foreach _bypass_mac macs + echo "bypass lan ip" + config_foreach _bypass_lan_ip lan_ip + echo "bypass dest port" + config_foreach _bypass_dest_port dest_port + echo "bypass src port" + config_foreach _bypass_src_port src_port + echo "bypass asn" + config_foreach _bypass_asn asns + echo "bypass domains" + config_foreach _bypass_domains domains + uci -q commit dhcp + +# ip rule add prio 1 fwmark 0x4539 lookup 991337 > /dev/null 2>&1 +# ip -6 rule add prio 1 fwmark 0x6539 lookup 6991337 > /dev/null 2>&1 + + #config_load shadowsocks-libev + #config_foreach _ss_rules_config ss_rules + ([ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] || [ "$(uci -q get shadowsocks-rust.sss0.disabled)" != "1" ]) && _ss_rules_config + #config_load shadowsocks-rust + #config_foreach _ss_rules_config ss_rules + [ "$(uci -q get v2ray.main.enabled)" = "1" ] && _v2ray_rules_config + [ "$(uci -q get xray.main.enabled)" = "1" ] && _xray_rules_config + + # NDPI Netfilter is not available for nftables + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass-dpi | $IPTABLESRESTORE -w --counters 2>/dev/null + $IPTABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + :omr-bypass-dpi - + -A INPUT -j omr-bypass-dpi + -A FORWARD -j omr-bypass-dpi + COMMIT + EOF + if [ "$disableipv6" = "0" ]; then + $IP6TABLESSAVE --counters | grep -v omr-bypass6-dpi | $IP6TABLESRESTORE -w --counters 2>/dev/null + $IP6TABLESRESTORE -w --wait=60 --noflush <<-EOF + *mangle + :omr-bypass6-dpi - + -A INPUT -j omr-bypass6-dpi + -A FORWARD -j omr-bypass6-dpi + COMMIT + EOF + fi + config_load omr-bypass + [ -d /proc/net/xt_ndpi/proto ] && config_foreach _bypass_proto dpis + config_foreach _bypass_proto_without_ndpi dpis + uci -q commit omr-bypass + + [ -z "$RELOAD" ] && [ "$add_domains" = "true" ] && { + logger -t "omr-bypass" "Restart dnsmasq..." + /etc/init.d/dnsmasq restart + } + [ -n "$RELOAD" ] && [ "$add_domains" = "true" ] && { + logger -t "omr-bypass" "Reload dnsmasq..." + /etc/init.d/dnsmasq reload + } + fw4 restart + # Create a protocol list for UI from a sqlite DB when NDPI is not available + sqlite3 /usr/share/omr-bypass/omr-bypass.db "select distinct(proto) from (select proto from hostproto union all select proto from ipproto) a order by proto;" ".exit" > /usr/share/omr-bypass/omr-bypass-proto.lst + config_load omr-bypass + config_foreach _add_proto_without_ndpi proto + sort < /usr/share/omr-bypass/omr-bypass-proto.lst > /usr/share/omr-bypass/omr-bypass-proto.lst.new + mv /usr/share/omr-bypass/omr-bypass-proto.lst.new /usr/share/omr-bypass/omr-bypass-proto.lst + logger -t "omr-bypass" "OMR-ByPass is running" +} + +stop_service() { + # Rules for ndpi + $IPTABLESSAVE --counters 2>/dev/null | grep -v omr-bypass | $IPTABLESRESTORE -w --counters 2>/dev/null + $IP6TABLESSAVE --counters 2>/dev/null | grep -v omr-bypass6 | $IP6TABLESRESTORE -w --counters 2>/dev/null + # disable all rules + uci -q set firewall.omr_bypass.enabled='0' + config_load dhcp + config_foreach _delete_dhcp_ipset ipset + uci -q commit dhcp + config_load firewall + config_foreach _delete_firewall_rules rule + config_foreach _delete_firewall_rules ipset + uci -q commit firewall + fw4 restart + exit 0 +} + +service_triggers() { + procd_add_reload_trigger omr-bypass network firewall +} + +reload_service() { + RELOAD=1 + start +} + +reload_rules() { + #[ "$( ipset -n list | grep omr_ )" = "" ] && return 0 + RELOAD=1 + start +}