1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-02-13 19:11:51 +00:00
openmptcprouter-feeds/omr-bypass/files/etc/init.d/omr-bypass-nft

986 lines
35 KiB
Bash
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh /etc/rc.common
# Copyright (C) 2018-2023 Ycarus (Yannick Chabanois) <ycarus@zugaina.org> 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
if [ "$disableipv6" = "0" ]; then
protocol="4 6"
else
protocol="4"
fi
for ipv46 in $protocol; do
uci -q batch <<-EOF
add_list firewall.omr_dst_bypass_${intf}_mac_${ipv46}.src_mac="$mac"
set firewall.omr_dst_bypass_${intf}_mac_${ipv46}.enabled='1'
EOF
done
}
_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 [ "$disableipv6" = "0" ]; then
protocol="4 6"
else
protocol="4"
fi
if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then
for ipv46 in $protocol; do
uci -q batch <<-EOF
add_list firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.dest_port="$dport"
set firewall.omr_dst_bypass_${intf}_dstport_tcp_${ipv46}.enabled='1'
EOF
done
fi
if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then
for ipv46 in $protocol; do
uci -q batch <<-EOF
add_list firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.dest_port="$dport"
set firewall.omr_dst_bypass_${intf}_dstport_udp_${ipv46}.enabled='1'
EOF
done
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 [ "$disableipv6" = "0" ]; then
protocol="4 6"
else
protocol="4"
fi
if [ "$proto" = "tcp" ] || [ "$proto" = "tcp udp" ]; then
for ipv46 in $protocol; do
uci -q batch <<-EOF
add_list firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.src_port="$sport"
set firewall.omr_dst_bypass_${intf}_srcport_tcp_${ipv46}.enabled='1'
EOF
done
fi
if [ "$proto" = "udp" ] || [ "$proto" = "tcp udp" ]; then
for ipv46 in $protocol; do
uci -q batch <<-EOF
add_list firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.src_port="$sport"
set firewall.omr_dst_bypass_${intf}_srcport_udp_${ipv46}.enabled='1'
EOF
done
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.family='ipv4'
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="0x4539${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.family='ipv6'
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="0x6539${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.omr_dst_bypass_${intf}_6.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_pre_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_pre_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_pre_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_pre_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_pre_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_pre_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 "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'
set firewall.omr_dst_bypass_${intf}_4.family='ipv4'
set firewall.omr_dst_bypass_${intf}_4.enabled='1'
set firewall.omr_dst_bypass_${intf}_6=ipset
set firewall.omr_dst_bypass_${intf}_6.name="omr_dst_bypass_${intf}_6"
set firewall.omr_dst_bypass_${intf}_6.match='dest_ip'
set firewall.omr_dst_bypass_${intf}_6.family='ipv6'
set firewall.omr_dst_bypass_${intf}_6.enabled='1'
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}_${ipv46}"
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.target='MARK'
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}.family="ipv${ipv46}"
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.enabled='0'
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}.set_mark="0x${ipv46}539${count}"
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept=rule
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.name="omr_dst_bypass_${intf}_rule_accept"
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.target='ACCEPT'
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.dest='*'
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.family="ipv${ipv46}"
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.enabled='0'
set firewall.omr_dst_bypass_${intf}_dstip_${ipv46}_accept.mark="0x${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}_${ipv46}"
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}.family="ipv${ipv46}"
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="0x${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="0x${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="0x${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="0x${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="0x${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="0x${ipv46}539${count}"
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
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}
EOF
fi
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"
EOF
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
if [ "$intf" != "all" ]; then
uci -q set omr-bypass.$intf=interface
uci -q set omr-bypass.$intf.id=$count
fi
}
_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
[ -z "\$(nft list ruleset | grep ss_rules)" ] && exit 0
#nft insert rule inet fw4 ss_rules_dst_tcp ip daddr @omr_dst_bypass_all_4 meta mark set 0x00004539 accept
#nft insert rule inet fw4 ss_rules_local_out ip daddr @omr_dst_bypass_all_4 meta mark set 0x00004539 accept
#nft add chain inet fw4 bypass_prerouting '{ type nat hook prerouting priority filter - 5; policy accept; }'
#nft add chain inet fw4 bypass_local '{ type nat hook output priority filter - 5; policy 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
[ -z "\$(nft list ruleset | grep v2r_rules)" ] && exit 0
#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
[ -z "\$(nft list ruleset | grep xr_rules)" ] && exit 0
#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)" ] || [ -n "$(echo $1 | grep omr6_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)"
rm -f /etc/firewall.omr-bypass
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
#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
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'
EOF
#echo "intf_rule"
config_load network
config_foreach _intf_rule interface
_intf_rule all
_intf_rule srv_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
# 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
# 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
[ -n "$(uci change network)" ] && {
uci -q commit network
/etc/init.d/network reload
}
uci -q commit omr-bypass
uci -q commit dhcp
uci -q commit firewall
fw4 -q restart
[ -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
}
# 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 -q restart
exit 0
}
service_triggers() {
procd_add_reload_trigger omr-bypass network firewall
}
reload_service() {
RELOAD=1
stop
start
}
restart_service() {
RELOAD=1
stop
start
}
reload_rules() {
#[ "$( ipset -n list | grep omr_ )" = "" ] && return 0
RELOAD=1
stop
start
}