feat: Insert rules when the network changes a8a85e1dad

This commit is contained in:
twnesss
2024-08-09 22:09:32 +07:00
parent 365bd27a94
commit 7fb8f69ff7
4 changed files with 144 additions and 43 deletions

View File

@@ -14,8 +14,8 @@ fake_ip_range=""
iptables_version=$(iptables --version | busybox awk '/^iptables/ {print $2}')
required_version="v1.6.1"
if [ "$(printf '%s\n' "$required_version" "$iptables_version" | sort -V | head -n1)" = "$required_version" ]; then
IPV="iptables -w 32"
IP6V="ip6tables -w 32"
IPV="iptables -w 64"
IP6V="ip6tables -w 64"
else
IPV="iptables"
IP6V="ip6tables"
@@ -36,10 +36,12 @@ case "${bin_name}" in
"sing-box")
if [[ "${network_mode}" == @(mixed|tun) ]]; then
tun_device=$(find "${box_dir}/sing-box/" -maxdepth 1 -type f -name "*.json" -exec busybox grep -oE '"interface_name": "[^"]*' {} + | busybox awk -F'"' '{print $4}' 2>/dev/null | head -n 1)
if [ -z "$tun_device" ]; then
tun_device="tun0"
fi
fi
fake_ip_range=$(find ${box_dir}/sing-box/ -maxdepth 1 -type f -name "*.json" -exec busybox awk -F'"' '/inet4_range/ {print $4}' {} +)
fake_ip6_range=$(find ${box_dir}/sing-box/ -maxdepth 1 -type f -name "*.json" -exec busybox awk -F'"' '/inet6_range/ {print $4}' {} +)
;;
@@ -212,9 +214,9 @@ ipv4_rules=(
ipv6_rules=(
"iif lo goto 6000 pref 5000"
"iif ${tun_device} lookup main suppress_prefixlength 0 pref 5010"
# "from 10.0.0.0/8 lookup ${tun_table_index} pref 5030"
# "from 172.16.0.0/12 lookup ${tun_table_index} pref 5040"
# "from 192.168.0.0/16 lookup ${tun_table_index} pref 5050"
# "from 2001:db8::/32 lookup ${tun_table_index} pref 5030"
# "from fc00::/7 lookup ${tun_table_index} pref 5040"
# "from fd00::/8 lookup ${tun_table_index} pref 5050"
"iif ${tun_device} goto 6000 pref 5020"
"nop pref 6000"
)
@@ -232,9 +234,9 @@ ipv6_rules=(
# Function to delete IP rules for the tun device
tun_forward_ip_rules_del() {
for pref in 5000 5010 5020 5030 5040 5050 6000; do
ip -4 rule del pref $pref
ip -6 rule del pref $pref
for preff in 5000 5010 5020 5030 5040 5050 6000; do
ip -4 rule del pref $preff
ip -6 rule del pref $preff
done
}
@@ -249,6 +251,7 @@ sing_tun_ip_rules() {
# Function to modify the FORWARD chain for the specified tun device using iptables
forward() {
local action=$1
${iptables} "${action}" FORWARD -i "${tun_device}" -j ACCEPT
${iptables} "${action}" FORWARD -o "${tun_device}" -j ACCEPT
@@ -257,26 +260,25 @@ forward() {
sysctl -w net.ipv4.conf.all.rp_filter=2
probe_tun_index
if [ "${tun_forward}" = "enable" ] ; then
if [ "${tun_forward}" = "enable" ]; then
if probe_tun_device; then
tun_forward_ip_rules_del
tun_forward_ip_rules "${action}"
if [ "${action}" = "-I" ]; then
tun_forward_ip_rules_del
tun_forward_ip_rules "${action}"
sing_tun_ip_rules "add">> /dev/null 2>&1
sing_tun_ip_rules "add"
else
tun_forward_ip_rules_del
tun_forward_ip_rules "${action}"
sing_tun_ip_rules "del" >> /dev/null 2>&1
sing_tun_ip_rules "del"
fi
return 0
else
tun_forward_ip_rules_del
tun_forward_ip_rules -D
sing_tun_ip_rules "del" >> /dev/null 2>&1
sing_tun_ip_rules "del"
log Error "tun device not found"
return 1
fi
fi
return 0
} >> /dev/null 2>&1
start_redirect() {
@@ -299,9 +301,11 @@ start_redirect() {
# Fix ICMP (ping)
# This does not guarantee that the ping result is valid
# Just that it returns a result
if [ -n "${fake_ip_range}" ]; then
${iptables} -t nat -A BOX_EXTERNAL -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1
${iptables} -t nat -A BOX_LOCAL -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1
if [[ "${bin_name}" == @(clash|sing-box) ]]; then
if [ -n "${fake_ip_range}" ]; then
${iptables} -t nat -A BOX_EXTERNAL -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1
${iptables} -t nat -A BOX_LOCAL -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1
fi
fi
# Allow access to intranet subnets
@@ -324,7 +328,7 @@ start_redirect() {
if [ "${ignore_out_list}" != "" ]; then
for ignore in "${ignore_out_list[@]}"; do
${iptables} -t nat -I BOX_LOCAL -o "${ignore}" -j RETURN
${iptables} -t nat -A BOX_LOCAL -o "${ignore}" -j RETURN
done
[ ${network_mode} = "enhance" ] || log Info "${ignore_out_list[*]} ignore transparent proxy."
fi
@@ -345,7 +349,7 @@ start_redirect() {
# loop through the UID list
while read -r appid; do
# add iptables rules for returning packets
${iptables} -t nat -I BOX_LOCAL -m owner --uid-owner "${appid}" -j RETURN
${iptables} -t nat -A BOX_LOCAL -m owner --uid-owner "${appid}" -j RETURN
done < "${uid_list[@]}"
# Allow !app
${iptables} -t nat -A BOX_LOCAL -p tcp -j REDIRECT --to-ports "${redir_port}"
@@ -354,9 +358,11 @@ start_redirect() {
if [ "${gid_list}" != "" ] ; then
# Bypass gids
for gid in ${gid_list[@]} ; do
${iptables} -t nat -I BOX_LOCAL -m owner --gid-owner ${gid} -j RETURN
${iptables} -t nat -A BOX_LOCAL -m owner --gid-owner ${gid} -j RETURN
done
[ ${network_mode} = "enhance" ] || [ "${iptables}" = "$IPV" ] && log Info "proxy mode: ${proxy_mode}, GID ${gid_list[*]} no transparent proxy."
[ ${network_mode} = "enhance" ] || {
[ "${iptables}" = "$IPV" ] && log Info "proxy mode: ${proxy_mode}, GID ${gid_list[*]} no transparent proxy."
}
fi
;;
whitelist)
@@ -641,9 +647,11 @@ fi
fi
# Fix ICMP (ping), this does not guarantee that the ping result is valid (proxies such as clash do not support forwarding ICMP),
# just that it returns a result, "--to-destination" can be set to a reachable address.
if [ -n "${fake_ip_range}" ]; then
${iptables} -t nat -I OUTPUT -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1
${iptables} -t nat -I PREROUTING -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1
if [[ "${bin_name}" == @(clash|sing-box) ]]; then
if [ -n "${fake_ip_range}" ]; then
${iptables} -t nat -I OUTPUT -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1
${iptables} -t nat -I PREROUTING -d "${fake_ip_range}" -p icmp -j DNAT --to-destination 127.0.0.1
fi
fi
fi
}

View File

@@ -77,6 +77,7 @@ xclash() {
fi
fi
log Info "xclash [ $xclash_option ] setup completed"
return 0
}
box_ownership() {

95
box/scripts/net.inotify Normal file
View File

@@ -0,0 +1,95 @@
#!/system/bin/sh
events=$1
# monitor_dir=$2
# monitor_file=$3
export PATH="/data/adb/magisk:/data/adb/ksu/bin:/data/adb/ap/bin:$PATH:/system/bin"
iptables_version=$(iptables --version | busybox awk '/^iptables/ {print $2}')
required_version="v1.6.1"
if [ "$(printf '%s\n' "$required_version" "$iptables_version" | sort -V | head -n1)" = "$required_version" ]; then
IPV="iptables -w 64"
IP6V="ip6tables -w 64"
else
IPV="iptables"
IP6V="ip6tables"
fi
iptables=$IPV
ip6tables=$IP6V
rules_add() {
# Retrieve all local IPv4 addresses except loopback (127.0.0.1)
ip -4 a | busybox awk '/inet/ {print $2}' | grep -vE "^127.0.0.1" | while read -r local_ipv4 ; do
echo "Checking IPv4 address: $local_ipv4" >> /data/adb/box/run/net.inotify.log
# Check if a rule for the local IPv4 address already exists in the mangle table
if ! iptables -t mangle -nL BOX_LOCAL | grep -q $local_ipv4 > /dev/null 2>&1 ; then
echo "Adding IPv4 address $local_ipv4 to mangle tables." >> /data/adb/box/run/net.inotify.log
# If not, add a rule to prevent traffic to the local IPv4 address from going external
${iptables} -t mangle -I BOX_EXTERNAL 3 -d $local_ipv4 -j RETURN
${iptables} -t mangle -I BOX_LOCAL 4 -d $local_ipv4 -j RETURN
fi
# Check if a rule for the local IPv4 address already exists in the nat table
if ! iptables -t nat -nL BOX_LOCAL | grep -q $local_ipv4 > /dev/null 2>&1 ; then
echo "Adding IPv4 address $local_ipv4 to nat tables." >> /data/adb/box/run/net.inotify.log
# If not, add a rule to prevent NAT on the local IPv4 address
${iptables} -t nat -I BOX_EXTERNAL 3 -d $local_ipv4 -j RETURN
${iptables} -t nat -I BOX_LOCAL 4 -d $local_ipv4 -j RETURN
fi
done
# Retrieve all local IPv6 addresses except link-local (fe80::) and loopback (::1)
ip -6 a | busybox awk '/inet6/ {print $2}' | grep -vE "^fe80|^::1" | while read -r local_ipv6 ; do
echo "Checking IPv6 address: $local_ipv6" >> /data/adb/box/run/net.inotify.log
# Check if a rule for the local IPv6 address already exists in the mangle table
if ! ip6tables -t mangle -nL BOX_LOCAL | grep -q $local_ipv6 > /dev/null 2>&1 ; then
echo "Adding IPv6 address $local_ipv6 to mangle tables." >> /data/adb/box/run/net.inotify.log
# If not, add a rule to prevent traffic to the local IPv6 address from going external
${ip6tables} -t mangle -I BOX_EXTERNAL 3 -d $local_ipv6 -j RETURN
${ip6tables} -t mangle -I BOX_LOCAL 4 -d $local_ipv6 -j RETURN
fi
done
}
rules_delete() {
# Retrieve all local IPv4 addresses except loopback (127.0.0.1)
ip -4 a | busybox awk '/inet/ {print $2}' | grep -vE "^127.0.0.1" | while read -r local_ipv4 ; do
echo "Checking IPv4 address for deletion: $local_ipv4" >> /data/adb/box/run/net.inotify.log
# Check if a rule for the local IPv4 address exists in the mangle table
if iptables -t mangle -nL BOX_LOCAL | grep -q $local_ipv4 > /dev/null 2>&1 ; then
echo "Deleting IPv4 address $local_ipv4 from mangle tables." >> /data/adb/box/run/net.inotify.log
# If exists, delete the rule
${iptables} -t mangle -D BOX_EXTERNAL -d $local_ipv4 -j RETURN
${iptables} -t mangle -D BOX_LOCAL -d $local_ipv4 -j RETURN
fi
# Check if a rule for the local IPv4 address exists in the nat table
if iptables -t nat -nL BOX_LOCAL | grep -q $local_ipv4 > /dev/null 2>&1 ; then
echo "Deleting IPv4 address $local_ipv4 from nat tables." >> /data/adb/box/run/net.inotify.log
# If exists, delete the rule
${iptables} -t nat -D BOX_EXTERNAL -d $local_ipv4 -j RETURN
${iptables} -t nat -D BOX_LOCAL -d $local_ipv4 -j RETURN
fi
done
# Retrieve all local IPv6 addresses except link-local (fe80::) and loopback (::1)
ip -6 a | busybox awk '/inet6/ {print $2}' | grep -vE "^fe80|^::1" | while read -r local_ipv6 ; do
echo "Checking IPv6 address for deletion: $local_ipv6" >> /data/adb/box/run/net.inotify.log
# Check if a rule for the local IPv6 address exists in the mangle table
if ip6tables -t mangle -nL BOX_LOCAL | grep -q $local_ipv6 > /dev/null 2>&1 ; then
echo "Deleting IPv6 address $local_ipv6 from mangle tables." >> /data/adb/box/run/net.inotify.log
# If exists, delete the rule
${ip6tables} -t mangle -D BOX_EXTERNAL -d $local_ipv6 -j RETURN
${ip6tables} -t mangle -D BOX_LOCAL -d $local_ipv6 -j RETURN
fi
done
}
if [ "$events" = "w" ]; then
date > /data/adb/box/run/net.inotify.log
if [ -f /data/adb/box/run/box.pid ] ; then
rules_add
rm -f /data/adb/box/run/net
elif [ ! -f /data/adb/box/run/net ]; then
rules_delete
touch /data/adb/box/run/net
fi
fi

View File

@@ -2,23 +2,12 @@
scripts_dir="${0%/*}"
file_settings="/data/adb/box/settings.ini"
moddir="/data/adb/modules/box_for_root"
if [ -n "$(magisk -v | grep lite &> /dev/null )" ]; then
moddir="/data/adb/lite_modules/box_for_root"
fi
if [ -f "/data/adb/ksu/bin/busybox" ]; then
# busybox KSU
busybox="/data/adb/ksu/bin/busybox"
elif [ -f "/data/adb/ap/bin/busybox" ]; then
# busybox APatch
busybox="/data/adb/ap/bin/busybox"
else
# busybox Magisk
busybox="/data/adb/magisk/busybox"
fi
# busybox Magisk/KSU/Apatch
busybox="/data/adb/magisk/busybox"
[ -f "/data/adb/ksu/bin/busybox" ] && busybox="/data/adb/ksu/bin/busybox"
[ -f "/data/adb/ap/bin/busybox" ] && busybox="/data/adb/ap/bin/busybox"
refresh_box() {
if [ -f "/data/adb/box/run/box.pid" ]; then
@@ -54,7 +43,15 @@ start_inotifyd() {
kill -9 "$PID"
fi
done
inotifyd "${scripts_dir}/box.inotify" "${moddir}" >> "/dev/null" 2>&1 &
inotifyd "${scripts_dir}/box.inotify" "${moddir}" > "/dev/null" 2>&1 &
while [ ! -f /data/misc/net/rt_tables ] ; do
sleep 3
done
net_dir="/data/misc/net"
# Use inotifyd to monitor write events in the /data/misc/net directory for network changes, perhaps we have a better choice of files to monitor (the /proc filesystem is unsupported) and cyclic polling is a bad solution
inotifyd "${scripts_dir}/net.inotify" "${net_dir}" > "/dev/null" 2>&1 &
}
mkdir -p /data/adb/box/run/