openwrt_helloworld/luci-app-openclash/root/etc/init.d/openclash
2025-03-05 22:00:26 +08:00

3164 lines
159 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. 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) 2019-2024 vernesong
START=99
STOP=15
USE_PROCD=1
. $IPKG_INSTROOT/usr/share/openclash/openclash_ps.sh
. $IPKG_INSTROOT/usr/share/openclash/ruby.sh
. $IPKG_INSTROOT/usr/share/openclash/log.sh
[ -f /etc/openwrt_release ] && {
RAW_CONFIG_FILE=$(uci -q get openclash.config.config_path)
BACKUP_FILE="/etc/openclash/backup/$(uci -q get openclash.config.config_path |awk -F '/' '{print $5}' 2>/dev/null)"
CONFIG_FILE="/etc/openclash/$(uci -q get openclash.config.config_path |awk -F '/' '{print $5}' 2>/dev/null)"
TMP_CONFIG_FILE="/tmp/yaml_config_tmp_$(uci -q get openclash.config.config_path |awk -F '/' '{print $5}' 2>/dev/null)"
FW4=$(command -v fw4)
# 获取默认的 DNSMASQ 配置 ID
DEFAULT_DNSMASQ_CFGID="$(uci -q show "dhcp.@dnsmasq[0]" | awk 'NR==1 {split($0, conf, /[.=]/); print conf[2]}')"
# 从 conf-dir 行中提取配置目录路径
if [ -f "/tmp/etc/dnsmasq.conf.$DEFAULT_DNSMASQ_CFGID" ]; then
DNSMASQ_CONF_DIR="$(awk -F '=' '/^conf-dir=/ {print $2}' "/tmp/etc/dnsmasq.conf.$DEFAULT_DNSMASQ_CFGID")"
else
DNSMASQ_CONF_DIR="/tmp/dnsmasq.d"
fi
# 设置 DNSMASQ_CONF_DIR并去除路径末尾的斜杠
DNSMASQ_CONF_DIR=${DNSMASQ_CONF_DIR%*/}
}
CLASH="/etc/openclash/clash"
CLASH_CONFIG="/etc/openclash"
CRON_FILE="/etc/crontabs/root"
CACHE_PATH_OLD="/etc/openclash/.cache"
CACHE_PATH="/etc/openclash/cache.db"
LOG_FILE="/tmp/openclash.log"
START_LOG="/tmp/openclash_start.log"
PROXY_FWMARK="0x162"
PROXY_ROUTE_TABLE="0x162"
add_cron()
{
[ "$(tail -n1 /etc/crontabs/root | wc -l)" -eq 0 ] && [ -n "$(cat /etc/crontabs/root 2>/dev/null)" ] && echo >> /etc/crontabs/root
[ -z "$(grep "openclash.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci -q get openclash.config.auto_update)" -eq 1 ] && [ "$(uci -q get openclash.config.config_auto_update_mode)" -ne 1 ] && echo "0 $(uci -q get openclash.config.auto_update_time) * * $(uci -q get openclash.config.config_update_week_time) /usr/share/openclash/openclash.sh" >> $CRON_FILE
}
[ -z "$(grep "openclash_rule.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci -q get openclash.config.other_rule_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.other_rule_update_day_time) * * $(uci -q get openclash.config.other_rule_update_week_time) /usr/share/openclash/openclash_rule.sh" >> $CRON_FILE
}
[ -z "$(grep "openclash_ipdb.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci -q get openclash.config.geo_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.geo_update_day_time) * * $(uci -q get openclash.config.geo_update_week_time) /usr/share/openclash/openclash_ipdb.sh" >> $CRON_FILE
}
[ -z "$(grep "openclash_geosite.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci -q get openclash.config.geosite_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.geosite_update_day_time) * * $(uci -q get openclash.config.geosite_update_week_time) /usr/share/openclash/openclash_geosite.sh" >> $CRON_FILE
}
[ -z "$(grep "openclash_geoip.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci -q get openclash.config.geoip_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.geoip_update_day_time) * * $(uci -q get openclash.config.geoip_update_week_time) /usr/share/openclash/openclash_geoip.sh" >> $CRON_FILE
}
[ -z "$(grep "openclash_chnroute.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci -q get openclash.config.chnr_auto_update)" -eq 1 ] && echo "0 $(uci -q get openclash.config.chnr_update_day_time) * * $(uci -q get openclash.config.chnr_update_week_time) /usr/share/openclash/openclash_chnroute.sh" >> $CRON_FILE
}
[ -z "$(grep "/etc/init.d/openclash" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci -q get openclash.config.auto_restart)" -eq 1 ] && echo "0 $(uci -q get openclash.config.auto_restart_day_time) * * $(uci -q get openclash.config.auto_restart_week_time) /etc/init.d/openclash restart 2>/dev/null" >> $CRON_FILE
}
crontab $CRON_FILE
start_watchdog
}
del_cron()
{
sed -i '/openclash.sh/d' $CRON_FILE 2>/dev/null
sed -i '/openclash_rule.sh/d' $CRON_FILE 2>/dev/null
sed -i '/openclash_ipdb.sh/d' $CRON_FILE 2>/dev/null
sed -i '/openclash_geoip.sh/d' $CRON_FILE 2>/dev/null
sed -i '/openclash_geosite.sh/d' $CRON_FILE 2>/dev/null
sed -i '/openclash_chnroute.sh/d' $CRON_FILE 2>/dev/null
sed -i '/\/etc\/init.d\/openclash/d' $CRON_FILE 2>/dev/null
/etc/init.d/cron restart
}
save_dnsmasq_server() {
if [ -z "$1" ] || [ "$1" == "127.0.0.1#${dns_port}" ]; then
return
fi
uci -q add_list openclash.config.dnsmasq_server="$1"
}
set_dnsmasq_server() {
if [ -z "$1" ] || [ "$1" == "127.0.0.1#${dns_port}" ]; then
return
fi
uci -q add_list dhcp.@dnsmasq[0].server="$1"
}
change_dns() {
local settype nftflag
if dnsmasq --version | grep -q 'Compile time options:.* nftset'; then
settype="nftset"
nftflag="inet#fw4#"
else
settype="ipset"
[ -n "$FW4" ] && LOG_OUT "Warning: Dnsmasq not Support nftset, Use ipset..."
fi
if [ -n "$FW4" ]; then
if [ "$china_ip_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
if [ "$enable_redirect_dns" != "2" ]; then
mkdir -p ${DNSMASQ_CONF_DIR}
awk '!/^$/&&!/^#/&&!/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("'${settype}'=/%s/'${nftflag}'china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf 2>/dev/null
fi
fi
if [ "$ipv6_enable" -eq 1 ]; then
if [ "$china_ip6_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
if [ "$enable_redirect_dns" != "2" ]; then
mkdir -p ${DNSMASQ_CONF_DIR}
awk '!/^$/&&!/^#/&&/([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/{printf("'${settype}'=/%s/'${nftflag}'china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf 2>/dev/null
#Prevent domain repeat
for i in `grep -wf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf`
do
if [ -n "$nftflag" ]; then
sed -i "s:${i}:${i},6#${nftflag}china_ip6_route_pass:g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
else
sed -i "s:${i}:${i},china_ip6_route_pass:g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
fi
sed -i 's:'$i':EXCLUSIVE:;/EXCLUSIVE/d' ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
done
if [ -n "$nftflag" ]; then
sed -i "s/\/${nftflag}/\/4#${nftflag}/g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
sed -i "s/${nftflag}china_ip_route_pass/6#${nftflag}china_ip6_route_pass/g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
else
sed -i "s/china_ip_route_pass/china_ip6_route_pass/g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
fi
fi
fi
fi
else
if [ "$china_ip_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
if [ "$enable_redirect_dns" != "2" ]; then
mkdir -p ${DNSMASQ_CONF_DIR}
awk '!/^$/&&!/^#/&&!/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("ipset=/%s/china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf 2>/dev/null
fi
fi
if [ "$ipv6_enable" -eq 1 ]; then
if [ "$china_ip6_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
if [ "$enable_redirect_dns" != "2" ]; then
mkdir -p ${DNSMASQ_CONF_DIR}
awk '!/^$/&&!/^#/&&/([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/{printf("ipset=/%s/china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
#Prevent domain repeat
for i in `grep -wf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf`
do
sed -i "s:${i}:${i},china_ip6_route_pass:g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
sed -i 's:'$i':EXCLUSIVE:;/EXCLUSIVE/d' ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
done
sed -i "s/china_ip_route_pass/china_ip6_route_pass/g" ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
fi
fi
fi
fi
/usr/share/openclash/openclash_custom_domain_dns.sh >/dev/null 2>&1
if [ "$1" -eq 1 ]; then
uci -q del openclash.config.dnsmasq_server
config_load "dhcp"
config_list_foreach "$(uci -q show dhcp.@dnsmasq[0].server |awk -F '.' '{print $2}')" "server" save_dnsmasq_server
uci -q del dhcp.@dnsmasq[-1].server
uci -q add_list dhcp.@dnsmasq[0].server=127.0.0.1#"$dns_port"
uci -q set openclash.config.dnsmasq_noresolv="$(uci -q get dhcp.@dnsmasq[0].noresolv)"
uci -q set openclash.config.dnsmasq_resolvfile="$(uci -q get dhcp.@dnsmasq[0].resolvfile)"
uci -q delete dhcp.@dnsmasq[0].resolvfile
uci -q set dhcp.@dnsmasq[0].noresolv=1
uci -q set dhcp.@dnsmasq[0].localuse=1
uci -q set openclash.config.redirect_dns=1
uci -q set openclash.config.dnsmasq_cachesize="$(uci -q get dhcp.@dnsmasq[0].cachesize)"
uci -q set dhcp.@dnsmasq[0].cachesize=0
uci -q set openclash.config.cachesize_dns=1
else
uci -q set openclash.config.redirect_dns=0
uci -q set openclash.config.cachesize_dns=0
fi
if [ "$1" -eq 1 ] && [ "$ipv6_dns" -eq 1 ] && [ -n "$(ip6tables -t mangle -L 2>&1 | grep -o 'Chain')" ]; then
#dnsmasq answer ipv6
uci -q set openclash.config.dnsmasq_filter_aaaa="$(uci -q get dhcp.@dnsmasq[0].filter_aaaa)"
uci -q set dhcp.@dnsmasq[0].filter_aaaa=0
uci -q set openclash.config.filter_aaaa_dns=1
else
uci -q set openclash.config.filter_aaaa_dns=0
fi
uci -q commit dhcp
uci -q commit openclash
/etc/init.d/dnsmasq restart >/dev/null 2>&1
}
revert_dns() {
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_custom_domain.conf >/dev/null 2>&1
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf >/dev/null 2>&1
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf >/dev/null 2>&1
[ "$1" -eq 1 ] && {
uci -q del dhcp.@dnsmasq[-1].server
[ -n "${10}" ] && {
config_load "openclash"
config_list_foreach "config" "dnsmasq_server" set_dnsmasq_server
}
if [ "$4" == "0" ] || [ -z "$4" ] || [ -z "$(uci -q show dhcp.@dnsmasq[0].server)" ]; then
uci -q set dhcp.@dnsmasq[0].noresolv=0
if [ -n "$5" ] && [ -n "$(grep nameserver $5)" ]; then
uci -q set dhcp.@dnsmasq[0].resolvfile="$5"
elif [ -n "$3" ] && [ -n "$(grep nameserver $3)" ]; then
uci -q set dhcp.@dnsmasq[0].resolvfile="$3"
elif [ -s "/tmp/resolv.conf.d/resolv.conf.auto" ] && [ -n "$(grep "nameserver" /tmp/resolv.conf.d/resolv.conf.auto)" ]; then
uci -q set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
uci -q set openclash.config.default_resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
elif [ -s "/tmp/resolv.conf.auto" ] && [ -n "$(grep "nameserver" /tmp/resolv.conf.auto)" ]; then
uci -q set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.auto
uci -q set openclash.config.default_resolvfile=/tmp/resolv.conf.auto
else
uci -q set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
uci -q set openclash.config.default_resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
fi
uci -q set dhcp.@dnsmasq[0].localuse=1
uci -q commit dhcp
/etc/init.d/dnsmasq restart >/dev/null 2>&1
masq_port=$(uci -q get dhcp.@dnsmasq[0].port)
if [ "$(nslookup www.apple.com 127.0.0.1:${masq_port} >/dev/null 2>&1 || echo $?)" = "1" ]; then
uci -q set openclash.config.default_resolvfile="/tmp/resolv.conf.d/resolv.conf.auto"
mkdir -p /tmp/resolv.conf.d
rm -rf /tmp/resolv.conf.d/resolv.conf.auto
touch /tmp/resolv.conf.d/resolv.conf.auto 2>/dev/null
cat >> "/tmp/resolv.conf.d/resolv.conf.auto" <<-EOF
# Interface lan
nameserver 119.29.29.29
nameserver 8.8.8.8
EOF
uci -q set dhcp.@dnsmasq[0].resolvfile="/tmp/resolv.conf.d/resolv.conf.auto"
fi
fi
}
[ "$6" -eq 1 ] && {
uci -q set dhcp.@dnsmasq[0].cachesize="$7"
uci -q set openclash.config.cachesize_dns=0
uci -q delete openclash.config.dnsmasq_cachesize
}
[ "$8" -eq 1 ] && {
uci -q set dhcp.@dnsmasq[0].filter_aaaa="$9"
uci -q set openclash.config.filter_aaaa_dns=0
uci -q delete openclash.config.dnsmasq_filter_aaaa
}
[ "$1" -eq 1 ] && {
uci -q set openclash.config.redirect_dns=0
uci -q del openclash.config.dnsmasq_server
}
uci -q commit dhcp
uci -q commit openclash
}
kill_clash()
{
check_time=1
while ( [ "$check_time" -le 10 ] && [ -n "$(pidof clash)" ] )
do
clash_pids=$(pidof clash |sed 's/$//g')
for clash_pid in $clash_pids; do
kill -9 "$clash_pid" 2>/dev/null
done
sleep 1
let check_time++
done >/dev/null 2>&1
}
start_fail()
{
kill_clash
stop
exit 0
}
#获取订阅配置
sub_info_get()
{
local section="$1" address enabled name
config_get_bool "enabled" "$section" "enabled" "1"
config_get "address" "$section" "address" ""
config_get "name" "$section" "name" ""
if [ "$subscribe_enable" = "1" ]; then
return
fi
if [ "$enabled" -eq 0 ]; then
return
fi
if [ -z "$address" ]; then
return
fi
if [ -z "$name" ]; then
SUB_CONFIG_FILE="/etc/openclash/config/config.yaml"
else
SUB_CONFIG_FILE="/etc/openclash/config/$name.yaml"
fi
if [ "$SUB_CONFIG_FILE" != "$2" ]; then
return
fi
subscribe_enable=1
}
#配置文件选择
config_choose()
{
if [ ! -f "$RAW_CONFIG_FILE" ]; then
config_load "openclash"
config_foreach sub_info_get "config_subscribe" "$RAW_CONFIG_FILE"
if [ "$subscribe_enable" = "1" ]; then
LOG_OUT "$RAW_CONFIG_FILE】Config File Does Not Exist, You Have Set Subscription Information, Ready To Download..."
/usr/share/openclash/openclash.sh "$RAW_CONFIG_FILE" &
exit 0
fi
fi
if [ -z "$RAW_CONFIG_FILE" ] || [ ! -f "$RAW_CONFIG_FILE" ]; then
for file_name in /etc/openclash/config/*
do
if [ -f "$file_name" ]; then
CONFIG_NAME=$(echo "$file_name" |awk -F '/' '{print $5}' 2>/dev/null)
uci -q set openclash.config.config_path="/etc/openclash/config/$CONFIG_NAME"
uci -q commit openclash
RAW_CONFIG_FILE="/etc/openclash/config/$CONFIG_NAME"
CONFIG_FILE="/etc/openclash/$CONFIG_NAME"
TMP_CONFIG_FILE="/tmp/yaml_config_tmp_$CONFIG_NAME"
LOG_OUT "Error: Config Not Found, Switch Config File to【$RAW_CONFIG_FILE"
break
fi
done
fi 2>/dev/null
if [ ! -f "$RAW_CONFIG_FILE" ]; then
LOG_OUT "Error: Config Not Found"
exit 0
fi
CONFIG_NAME=$(echo "$RAW_CONFIG_FILE" |awk -F '/' '{print $5}' 2>/dev/null)
HISTORY_PATH_OLD="/etc/openclash/history/${CONFIG_NAME%.*}"
HISTORY_PATH="/etc/openclash/history/${CONFIG_NAME%.*}.db"
}
config_check()
{
#创建启动配置
#rm -rf "/etc/openclash/*.y*" 2>/dev/null
cp "$RAW_CONFIG_FILE" "$TMP_CONFIG_FILE"
ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
begin
YAML.load_file('$RAW_CONFIG_FILE');
rescue Exception => e
YAML.LOG('Error: Unable To Parse Config File,【' + e.message + '】');
system 'rm -rf ${TMP_CONFIG_FILE}';
end
" 2>/dev/null >> $LOG_FILE
if [ $? -ne 0 ]; then
LOG_OUT "Error: Ruby Works Abnormally, Please Check The Ruby Library Depends!"
start_fail
elif [ ! -f "$TMP_CONFIG_FILE" ] || [ ! -s "$TMP_CONFIG_FILE" ]; then
LOG_OUT "Error: Config File Format Validation Failed..."
start_fail
fi
}
check_run_quick()
{
quick_start=true
check_file="$(cat /tmp/openclash.change 2>/dev/null |awk '{print $1}')"
if [ -z "$check_file" ] || [ ! -f "$CONFIG_FILE" ] || [ ! -f "/tmp/openclash_config.tmp" ]; then
quick_start=false
return
fi
cmp -s "/etc/config/openclash" "/tmp/openclash_config.tmp"
if [ "$?" -ne "0" ]; then
LOG_OUT "Tip: Because of the file【 /etc/config/openclash 】modificated, Pause quick start..."
quick_start=false
else
if [ -s "/tmp/openclash.change" ]; then
for i in $check_file; do
if [ -z "$(grep "$i $(date -r "$i")$" "/tmp/openclash.change")" ]; then
LOG_OUT "Tip: Because of the file【 $i 】modificated, Pause quick start..."
quick_start=false
break
fi
done 2>/dev/null
fi
fi
}
write_run_quick()
{
check_file="$(echo $RAW_CONFIG_FILE | tr " " "?") $(ls -d /etc/openclash/custom/*) /usr/share/openclash/res/lhie1.yaml"
cmp -s "/etc/config/openclash" "/tmp/openclash_config.tmp"
if [ "$?" -ne "0" ]; then
cp "/etc/config/openclash" "/tmp/openclash_config.tmp"
fi
if ! $quick_start; then
: > "/tmp/openclash.change"
for i in $check_file; do
echo "$i $(date -r "$i")" >> "/tmp/openclash.change"
done 2>/dev/null
fi
}
#运行模式处理
do_run_mode()
{
en_mode=$(uci -q get openclash.config.en_mode)
if [ "$en_mode" = "fake-ip-tun" ]; then
en_mode_tun="1"
en_mode="fake-ip"
fi
if [ "$en_mode" = "redir-host-tun" ]; then
en_mode_tun="1"
en_mode="redir-host"
fi
if [ "$en_mode" = "redir-host-mix" ]; then
en_mode_tun="2"
en_mode="redir-host"
fi
if [ "$en_mode" = "fake-ip-mix" ]; then
en_mode_tun="2"
en_mode="fake-ip"
fi
}
do_run_file()
{
#Some MIPS devices file system cound not use db
source "/etc/openwrt_release"
[ "$small_flash_memory" == "1" ] || [ -n "$(echo $core_version |grep mips)" ] || [ -n "$(echo $DISTRIB_ARCH |grep mips)" ] || [ -n "$(opkg status libc 2>/dev/null |grep 'Architecture' |awk -F ': ' '{print $2}' |grep mips)" ] || [ -n "$(apk list libc 2>/dev/null |grep mips)" ] && mkdir -p /tmp/etc/openclash && CACHE_PATH="/tmp/etc/openclash/cache.db"
[ -f "/etc/openclash/geosite.dat" ] && {
mv "/etc/openclash/geosite.dat" "/etc/openclash/GeoSite.dat" 2>/dev/null
}
[ -f "/etc/openclash/geoip.dat" ] && {
mv "/etc/openclash/geoip.dat" "/etc/openclash/GeoIP.dat" 2>/dev/null
}
if [ "$small_flash_memory" != "1" ]; then
meta_core_path="/etc/openclash/core/clash_meta"
ipdb_path="/etc/openclash/Country.mmdb"
chnr_path="/etc/openclash/china_ip_route.ipset"
chnr6_path="/etc/openclash/china_ip6_route.ipset"
geosite_path="/etc/openclash/GeoSite.dat"
geoip_path="/etc/openclash/GeoIP.dat"
mv "/tmp/etc/openclash/Country.mmdb" "$ipdb_path" 2>/dev/null
mv "/tmp/etc/openclash/china_ip_route.ipset" "$chnr_path" 2>/dev/null
mv "/tmp/etc/openclash/china_ip6_route.ipset" "$chnr6_path" 2>/dev/null
mv "/tmp/etc/openclash/GeoSite.dat" "$geosite_path" 2>/dev/null
mv "/tmp/etc/openclash/GeoIP.dat" "$geoip_path" 2>/dev/null
mv "/tmp/etc/openclash/core/" "/etc/openclash" 2>/dev/null
if [ "$CACHE_PATH" != "/tmp/etc/openclash/cache.db" ]; then
rm -rf "/tmp/etc/openclash" 2>/dev/null
fi
else
meta_core_path="/tmp/etc/openclash/core/clash_meta"
ipdb_path="/tmp/etc/openclash/Country.mmdb"
chnr_path="/tmp/etc/openclash/china_ip_route.ipset"
chnr6_path="/tmp/etc/openclash/china_ip6_route.ipset"
geosite_path="/tmp/etc/openclash/GeoSite.dat"
geoip_path="/tmp/etc/openclash/GeoIP.dat"
[ ! -h "/etc/openclash/Country.mmdb" ] && mv "/etc/openclash/Country.mmdb" "$ipdb_path" 2>/dev/null
[ ! -h "/etc/openclash/china_ip_route.ipset" ] && mv "/etc/openclash/china_ip_route.ipset" "$chnr_path" 2>/dev/null
[ ! -h "/etc/openclash/china_ip6_route.ipset" ] && mv "/etc/openclash/china_ip6_route.ipset" "$chnr6_path" 2>/dev/null
[ ! -h "/etc/openclash/GeoSite.dat" ] && mv "/etc/openclash/GeoSite.dat" "$geosite_path" 2>/dev/null
[ ! -h "/etc/openclash/GeoIP.dat" ] && mv "/etc/openclash/GeoIP.dat" "$geoip_path" 2>/dev/null
mv "/etc/openclash/core/" "/tmp/etc/openclash" 2>/dev/null
fi
rm -rf "/etc/openclash/cache.db" 2>/dev/null
rm -rf "/etc/openclash/clash" 2>/dev/null
ln -s "$meta_core_path" /etc/openclash/clash 2>/dev/null
core_type="Meta"
[ ! -f "$CLASH" ] && {
LOG_OUT "Tip: Detected that the Core is not Installed, Ready to Download..."
rm -rf "/tmp/clash_last_version"
/usr/share/openclash/openclash_core.sh "$core_type"
if [ ! -f "$meta_core_path" ]; then
start_fail
fi
}
[ ! -f "$ipdb_path" ] && {
LOG_OUT "Tip: Detected that the GEOIP Database is not Installed, Ready to Download..."
/usr/share/openclash/openclash_ipdb.sh
if [ ! -f "$ipdb_path" ]; then
start_fail
fi
}
[ ! -f "$geosite_path" ] && {
LOG_OUT "Tip: Detected that the GEOSITE Database is not Installed, Ready to Download..."
/usr/share/openclash/openclash_geosite.sh
if [ ! -f "$geosite_path" ]; then
start_fail
fi
}
[ ! -f "$geoip_path" ] && [ "$enable_geoip_dat" == "1" ] && {
LOG_OUT "Tip: Detected that the GEOIP Dat is not Installed, Ready to Download..."
/usr/share/openclash/openclash_geoip.sh
if [ "$enable_geoip_dat" == "1" ] && [ ! -f "$geoip_path" ]; then
start_fail
fi
}
if [ "$china_ip_route" != "0" ] || [ "$china_ip6_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
if [ ! -f "$chnr_path" ] || [ ! -f "$chnr6_path" ]; then
LOG_OUT "Tip: Detected that the Chnroute Cidr is not Installed, Ready to Download..."
/usr/share/openclash/openclash_chnroute.sh
fi
if [ -n "$FW4" ]; then
if [ -z "$(cat "$chnr_path" |grep "define china_ip_route")" ] || [ -z "$(cat "$chnr6_path" |grep "define china_ip6_route")" ]; then
LOG_OUT "Tip: Detected that the Chnroute Cidr List Format is wrong, Ready to Reformat..."
/usr/share/openclash/openclash_chnroute.sh
if [ -z "$(cat "$chnr_path" |grep "define china_ip_route")" ] || [ -z "$(cat "$chnr6_path" |grep "define china_ip6_route")" ]; then
start_fail
fi
fi
else
if [ -n "$(cat "$chnr_path" |grep "define china_ip_route")" ] || [ -n "$(cat "$chnr6_path" |grep "define china_ip6_route")" ]; then
LOG_OUT "Tip: Detected that the Chnroute Cidr List Format is wrong, Ready to Reformat..."
/usr/share/openclash/openclash_chnroute.sh
if [ -n "$(cat "$chnr_path" |grep "define china_ip_route")" ] || [ -n "$(cat "$chnr6_path" |grep "define china_ip6_route")" ]; then
start_fail
fi
fi
fi
if [ ! -f "$chnr_path" ] || [ ! -f "$chnr6_path" ]; then
start_fail
fi
fi
[ ! -x "$meta_core_path" ] && chmod 4755 "$meta_core_path" 2>/dev/null
[ -f "$ipdb_path" ] && [ "$small_flash_memory" = "1" ] && {
ln -s "$ipdb_path" /etc/openclash/Country.mmdb 2>/dev/null
}
[ -f "$geosite_path" ] && [ "$small_flash_memory" = "1" ] && {
ln -s "$geosite_path" /etc/openclash/GeoSite.dat 2>/dev/null
}
[ -f "$geoip_path" ] && [ "$small_flash_memory" = "1" ] && {
ln -s "$geoip_path" /etc/openclash/GeoIP.dat 2>/dev/null
}
[ -f "$chnr_path" ] && [ "$small_flash_memory" = "1" ] && {
ln -s "$chnr_path" /etc/openclash/china_ip_route.ipset 2>/dev/null
}
[ -f "$chnr6_path" ] && [ "$small_flash_memory" = "1" ] && {
ln -s "$chnr6_path" /etc/openclash/china_ip6_route.ipset 2>/dev/null
}
#Restore history cache
if [ -f "$HISTORY_PATH" ] && [ -f "$HISTORY_PATH_OLD" ]; then
if [ "$(date -r $HISTORY_PATH +%s)" -ge "$(date -r $HISTORY_PATH_OLD +%s)" ]; then
cmp -s "$CACHE_PATH" "$HISTORY_PATH"
if [ "$?" -ne "0" ]; then
if [ "$CACHE_PATH" != "/tmp/etc/openclash/cache.db" ]; then
ln -s "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
else
cp "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
fi
fi
else
cmp -s "$CACHE_PATH_OLD" "$HISTORY_PATH_OLD"
if [ "$?" -ne "0" ]; then
cp "$HISTORY_PATH_OLD" "$CACHE_PATH_OLD" 2>/dev/null
fi
fi
else
if [ -f "$HISTORY_PATH" ]; then
cmp -s "$CACHE_PATH" "$HISTORY_PATH"
if [ "$?" -ne "0" ]; then
if [ "$CACHE_PATH" != "/tmp/etc/openclash/cache.db" ]; then
ln -s "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
else
cp "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
fi
fi
fi
if [ -f "$HISTORY_PATH_OLD" ]; then
cmp -s "$CACHE_PATH_OLD" "$HISTORY_PATH_OLD"
if [ "$?" -ne "0" ]; then
cp "$HISTORY_PATH_OLD" "$CACHE_PATH_OLD" 2>/dev/null
fi
fi
fi
if [ "$CACHE_PATH" == "/tmp/etc/openclash/cache.db" ]; then
[ ! -f "$CACHE_PATH" ] && touch "$CACHE_PATH"
ln -s "$CACHE_PATH" /etc/openclash/cache.db 2>/dev/null
else
[ ! -f "$CACHE_PATH" ] && touch "$HISTORY_PATH"
ln -s "$HISTORY_PATH" "$CACHE_PATH" 2>/dev/null
fi
#创建原始备份
if [ ! -f "$2" ]; then
cp "$1" "$2"
fi
#保存启动内核类型
uci -q set openclash.config.core_type="$core_type"
uci -q commit openclash
}
start_run_core()
{
ulimit -SHn 1000000 2>/dev/null
ulimit -v unlimited 2>/dev/null
ulimit -u unlimited 2>/dev/null
modprobe tun >/dev/null 2>&1
if ! $quick_start; then
mv "$TMP_CONFIG_FILE" "$CONFIG_FILE" 2>/dev/null
rm -rf "$TMP_CONFIG_FILE" 2>/dev/null
fi
chown root:root /etc/openclash/core/* 2>/dev/null
kill_clash
procd_open_instance "openclash"
procd_set_param command /bin/sh -c "$CLASH -d $CLASH_CONFIG -f \"$CONFIG_FILE\" >> $LOG_FILE 2>&1"
procd_set_param user "root"
procd_set_param group "nogroup"
procd_set_param limits nproc="unlimited" as="unlimited" memlock="unlimited" nofile="1000000 1000000"
procd_set_param respawn 3600 3 10
procd_set_param stderr 1
procd_set_param no_new_privs 1
procd_close_instance
}
#防火墙设置部分
nft_ac_add()
{
if [ -z "$1" ]; then
return
fi
nft add element inet fw4 "$2" { "$1" } 2>/dev/null
[ -n "$3" ] && nft add element inet fw4 "$3" { "$1" } 2>/dev/null
}
ac_add()
{
if [ -z "$1" ]; then
return
fi
ipset add "$2" "$1" 2>/dev/null
[ -n "$3" ] && ipset add "$3" "$1" 2>/dev/null
}
wan_name_add()
{
if [ -z "$1" ]; then
return
fi
if [ -n "$wan_ints" ]; then
wan_ints="$wan_ints $1"
else
wan_ints="$1"
fi
}
wan6_name_add()
{
if [ -z "$1" ]; then
return
fi
if [ -n "$wan6_ints" ]; then
wan6_ints="$wan6_ints $1"
else
wan6_ints="$1"
fi
}
upnp_exclude()
{
if [ -s "$upnp_lease_file" ]; then
cat "$upnp_lease_file" |while read -r line
do
if [ -n "$line" ]; then
upnp_ip=$(echo "$line" |awk -F ':' '{print $3}')
upnp_dp=$(echo "$line" |awk -F ':' '{print $4}')
upnp_type=$(echo "$line" |awk -F ':' '{print $1}' |tr '[A-Z]' '[a-z]')
if [ -n "$upnp_ip" ] && [ -n "$upnp_dp" ] && [ -n "$upnp_type" ]; then
if [ -n "$FW4" ]; then
if [ -z "$(nft list chain inet fw4 openclash_upnp |grep "$upnp_ip" |grep "$upnp_dp" |grep "$upnp_type")" ]; then
nft add rule inet fw4 openclash_upnp ip saddr { "$upnp_ip" } "$upnp_type" sport "$upnp_dp" counter return 2>/dev/null
fi
else
if [ -z "$(iptables -t mangle -nL openclash_upnp |grep "$upnp_ip" |grep "$upnp_dp" |grep "$upnp_type")" ]; then
iptables -t mangle -A openclash_upnp -p "$upnp_type" -s "$upnp_ip" --sport "$upnp_dp" -j RETURN 2>/dev/null
fi
fi
fi
fi
done >/dev/null 2>&1
fi
}
check_core_status()
{
TUN_WAIT=0
TUN_RESTART=1
CORE_HTTP_CODE=0
if [ -z "$(pidof clash)" ]; then
sleep 5
fi
if [ -n "$en_mode_tun" ] || [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
if [ -n "$en_mode_tun" ]; then
ip_="ip"
else
ip_="ip -6"
fi
#wait 120s most for tun interface start
while ( [ -n "$(pidof clash)" ] && [ -z "$($ip_ route list |grep utun)" ] && [ "$TUN_WAIT" -le 120 ] )
do
$ip_ link set utun up
let TUN_WAIT++
sleep 1
done >/dev/null 2>&1
if [ -n "$(pidof clash)" ] && [ -z "$($ip_ route list |grep utun)" ] && [ "$TUN_WAIT" -gt 120 ]; then
while ( [ -n "$(pidof clash)" ] && [ -z "$($ip_ route list |grep utun)" ] && [ "$TUN_RESTART" -le 3 ] )
do
LOG_OUT "Warning: TUN Interface Start Failed, Try to Restart Again..."
kill_clash
start_run_core
sleep 120
let TUN_RESTART++
done >/dev/null 2>&1
if [ -n "$(pidof clash)" ] && [ -z "$($ip_ route list |grep utun)" ] && [ "$TUN_RESTART" -gt 3 ]; then
LOG_OUT "Warning: TUN Interface Start Failed, Please Check The Dependence or Try to Restart Again!"
start_fail
fi
fi
if [ -n "$(pidof clash)" ]; then
if [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
ip -6 rule del oif utun table 2022 >/dev/null 2>&1
ip -6 route del default dev utun table 2022 >/dev/null 2>&1
ip -6 route add default dev utun table "$PROXY_ROUTE_TABLE"
ip -6 rule add fwmark "$PROXY_FWMARK" ipproto icmp table main pref 1888
ip -6 rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" pref 1889
fi
ip route add default dev utun table "$PROXY_ROUTE_TABLE"
ip rule add fwmark "$PROXY_FWMARK" ipproto icmp table main pref 1888
ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" pref 1889
fi
else
reg4='^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$'
while ( [ -n "$(pidof clash)" ] && [ "$CORE_HTTP_CODE" != "200" ] && [ "$TUN_WAIT" -le 120 ] && [ -n "$(echo ${lan_ip} | grep -Eo ${reg4})" ] )
do
CORE_HTTP_CODE=$(curl -m 5 -o /dev/null -s -w '%{http_code}' -H 'Content-Type: application/json' -H "Authorization: Bearer ${da_password}" -XGET http://${lan_ip}:${cn_port}/group)
let TUN_WAIT++
sleep 1
done >/dev/null 2>&1
if [ -z "$(echo ${lan_ip} | grep -Eo ${reg4})" ]; then
LOG_OUT "Error: LAN IP Address Get Error, Please Check The LAN Interface Setting or Choose the Correct Interface in the Setting!"
sleep 10
fi
if [ "$CORE_HTTP_CODE" != "200" ]; then
LOG_OUT "Error: Core Status Abnormal, Please Check The Log Infos!"
start_fail
fi
fi
if [ -z "$(pidof clash)" ]; then
LOG_OUT "Error: Core Start Failed, Please Check The Log Infos!"
start_fail
fi
}
firewall_lan_ac_traffic()
{
local src_port src_ip proto target enabled family comment
config_get "src_port" "$section" "src_port" ""
config_get "src_ip" "$section" "src_ip" "localnetwork"
config_get "proto" "$section" "proto" "both"
config_get "target" "$section" "target" "return"
config_get "enabled" "$section" "enabled" "0"
config_get "family" "$section" "family" "both"
config_get "comment" "$section" "comment" "lan_ac_traffic"
if [ "$enabled" == "0" ] || [ -z "$src_port" ] || [ -z "$src_ip" ]; then
return
fi
local e_udp=false
local e_tcp=false
if [ $proto == "tcp" ]; then e_tcp=true; fi
if [ $proto == "udp" ]; then e_udp=true; fi
if [ $proto == "both" ]; then e_tcp=true; e_udp=true; fi
if [ -n "$FW4" ]; then
if [ "$src_ip" == "localnetwork" ]; then
src_ip="@localnetwork"
src_ip_v6="@localnetwork6"
else
src_ip="{ $src_ip }"
src_ip_v6="{ $src_ip }"
fi
if [ "$family" == "both" ] || [ "$family" == "ipv4" ]; then
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
if $e_tcp ; then
nft insert rule inet fw4 openclash_output position 0 meta nfproto {ipv4} ip daddr != { "$fakeip_range" } ip saddr "$src_ip" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash position 0 ip daddr != { "$fakeip_range" } ip saddr "$src_ip" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
fi
if $e_udp ; then
nft insert rule inet fw4 openclash_mangle_output position 0 meta nfproto {ipv4} ip daddr != { "$fakeip_range" } ip saddr "$src_ip" udp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash_mangle position 0 ip daddr != { "$fakeip_range" } ip saddr "$src_ip" udp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
fi
elif [ "$en_mode_tun" -eq 1 ]; then
if $e_tcp ; then
nft insert rule inet fw4 openclash_mangle_output position 0 meta nfproto {ipv4} ip daddr != { "$fakeip_range" } ip saddr "$src_ip" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash_mangle position 0 ip daddr != { "$fakeip_range" } ip saddr "$src_ip" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
fi
if $e_udp ; then
nft insert rule inet fw4 openclash_mangle_output position 0 meta nfproto {ipv4} ip daddr != { "$fakeip_range" } ip saddr "$src_ip" udp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash_mangle position 0 ip daddr != { "$fakeip_range" } ip saddr "$src_ip" udp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
fi
fi
if $e_tcp ; then
nft insert rule inet fw4 openclash_post position 0 ip daddr != { "$fakeip_range" } ip saddr "$src_ip" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
fi
if $e_udp ; then
nft insert rule inet fw4 openclash_post position 0 ip daddr != { "$fakeip_range" } ip saddr "$src_ip" udp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
fi
fi
if [ "$ipv6_enable" -eq 1 ]; then
if [ "$family" == "both" ] || [ "$family" == "ipv6" ]; then
if $e_tcp ; then
nft insert rule inet fw4 openclash_v6 position 0 ip6 saddr "$src_ip_v6" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash_output_v6 position 0 ip6 saddr "$src_ip_v6" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr "$src_ip_v6" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash_mangle_output_v6 position 0 meta nfproto {ipv6} ip6 saddr "$src_ip_v6" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash_post_v6 position 0 ip6 saddr "$src_ip_v6" tcp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
fi
if $e_udp ; then
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr "$src_ip_v6" udp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash_mangle_output_v6 position 0 meta nfproto {ipv6} ip6 saddr "$src_ip_v6" udp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
nft insert rule inet fw4 openclash_post_v6 position 0 ip6 saddr "$src_ip_v6" udp sport "$src_port" counter $target comment "\"$comment\"" >/dev/null 2>&1
fi
fi
fi
else
if [ "$src_ip" == "localnetwork" ]; then
src_ip="-m set --match-set localnetwork src"
src_ip_v6="-m set --match-set localnetwork6 src"
else
src_ip="-s ${src_ip}"
src_ip_v6="-s ${src_ip}"
fi
src_port=$(echo $src_port |sed "s/-/:/g" 2>/dev/null)
if [ $target == "accept" ]; then target="ACCEPT"; fi
if [ $target == "return" ]; then target="RETURN"; fi
if [ $target == "drop" ]; then target="DROP"; fi
if [ "$family" == "both" ] || [ "$family" == "ipv4" ]; then
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
if $e_tcp ; then
iptables -t nat -I openclash_output -p tcp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
iptables -t nat -I openclash -p tcp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
fi
if $e_udp ; then
iptables -t mangle -I openclash_output -p udp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
iptables -t mangle -I openclash -p udp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
fi
elif [ "$en_mode_tun" -eq 1 ]; then
if $e_tcp ; then
iptables -t mangle -I openclash_output -p tcp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
iptables -t mangle -I openclash -p tcp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
fi
if $e_udp ; then
iptables -t mangle -I openclash_output -p udp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
iptables -t mangle -I openclash -p udp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
fi
fi
if $e_tcp ; then
iptables -t nat -I openclash_post -p tcp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
fi
if $e_udp ; then
iptables -t nat -I openclash_post -p udp ! -d "$fakeip_range" "$src_ip" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
fi
fi
if [ "$ipv6_enable" -eq 1 ]; then
if [ "$family" == "both" ] || [ "$family" == "ipv6" ]; then
if $e_tcp ; then
ip6tables -t nat -I openclash "$src_ip_v6" -p tcp --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
ip6tables -t nat -A openclash_output "$src_ip_v6" -p tcp --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
ip6tables -t mangle -I openclash "$src_ip_v6" -p tcp --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
ip6tables -t mangle -I openclash_output -p tcp "$src_ip_v6" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
ip6tables -t nat -I openclash_post -p tcp "$src_ip_v6" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
fi
if $e_udp ; then
ip6tables -t mangle -I openclash -p udp "$src_ip_v6" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
ip6tables -t mangle -I openclash_output -p udp "$src_ip_v6" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
ip6tables -t nat -I openclash_post -p udp "$src_ip_v6" --sport "$src_port" -j $target -m comment --comment "$comment" >/dev/null 2>&1
fi
fi
fi
fi
}
firewall_rule_exclude()
{
local section="$1"
local name src dest dest_port dest_ip proto target enabled family
config_get "name" "$section" "name" ""
config_get "src" "$section" "src" ""
config_get "dest" "$section" "dest" ""
config_get "dest_port" "$section" "dest_port" ""
config_get "dest_ip" "$section" "dest_ip" ""
config_get "proto" "$section" "proto" ""
config_get "target" "$section" "target" ""
config_get "enabled" "$section" "enabled" ""
config_get "family" "$section" "family" ""
ipv6_suffix_to_nft_format() {
local ipv6_with_prefix="$1"
if [[ "$ipv6_with_prefix" =~ / ]] || [ -n "$(echo ${ipv6_with_prefix} | grep '/')" ]; then
local suffix="${ipv6_with_prefix%%/*}"
local prefix="${ipv6_with_prefix##*/}"
echo "& $prefix == $suffix"
else
echo "$ipv6_with_prefix"
fi
}
nft_ipv6=$(ipv6_suffix_to_nft_format "$dest_ip")
if [ a"$target" != aACCEPT ] || [ a"$enabled" == a0 ]; then
return
fi
local e_udp=false
local e_tcp=false
for p in $proto; do
if [ $p == tcp ]; then e_tcp=true; fi
if [ $p == udp ]; then e_udp=true; fi
if [ $p == all ]; then e_tcp=true; e_udp=true; fi
done
if [ -z "$proto" ]; then e_tcp=true; e_udp=true; fi
if ! $e_udp && ! $e_tcp ; then
return
fi
if [ -n "$(echo $dest_port |grep -E '\-|\:' 2>/dev/null)" ]; then
LOG_OUT "Warning: Because there is a port range【$dest_port】in the firewall rule settings【$name】auto bypassing may cause the normal connection of the client not to reach the core, if necessary, please add your own in the access control!"
return
fi
if [ -n "$FW4" ]; then
dest_ip=$(echo $dest_ip |sed "s/ /,/g" 2>/dev/null)
if [ -z "$family" ] || [ "$family" == "ipv4" ]; then
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
for i in $dest_port; do
if $e_tcp ; then
nft insert rule inet fw4 openclash_output position 0 meta nfproto {ipv4} tcp sport "$i" counter return >/dev/null 2>&1
if [ -z "$dest_ip" ]; then
nft insert rule inet fw4 openclash position 0 meta nfproto {ipv4} tcp sport "$i" counter return >/dev/null 2>&1
else
nft insert rule inet fw4 openclash position 0 ip saddr { "$dest_ip" } tcp sport "$i" counter return >/dev/null 2>&1
fi
fi
if $e_udp ; then
nft insert rule inet fw4 openclash_mangle_output position 0 meta nfproto {ipv4} udp sport "$i" counter return >/dev/null 2>&1
if [ -z "$dest_ip" ]; then
nft insert rule inet fw4 openclash_mangle position 0 meta nfproto {ipv4} udp sport "$i" counter return >/dev/null 2>&1
else
nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp sport "$i" counter return >/dev/null 2>&1
fi
fi
done
elif [ "$en_mode_tun" -eq 1 ]; then
for i in $dest_port; do
if $e_tcp ; then
nft insert rule inet fw4 openclash_mangle_output position 0 meta nfproto {ipv4} tcp sport "$i" counter return >/dev/null 2>&1
if [ -z "$dest_ip" ]; then
nft insert rule inet fw4 openclash_mangle position 0 meta nfproto {ipv4} tcp sport "$i" counter return >/dev/null 2>&1
else
nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } tcp sport "$i" counter return >/dev/null 2>&1
fi
fi
if $e_udp ; then
nft insert rule inet fw4 openclash_mangle_output position 0 meta nfproto {ipv4} udp sport "$i" counter return >/dev/null 2>&1
if [ -z "$dest_ip" ]; then
nft insert rule inet fw4 openclash_mangle position 0 meta nfproto {ipv4} udp sport "$i" counter return >/dev/null 2>&1
else
nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp sport "$i" counter return >/dev/null 2>&1
fi
fi
done
fi
fi
if [ "$ipv6_enable" -eq 1 ]; then
if [ -z "$family" ] || [ "$family" == "ipv6" ]; then
for i in $dest_port; do
if $e_tcp ; then
if [ -z "$dest_ip" ]; then
nft insert rule inet fw4 openclash_mangle_v6 position 0 meta nfproto {ipv6} tcp sport "$i" counter return >/dev/null 2>&1
nft insert rule inet fw4 openclash_v6 position 0 meta nfproto {ipv6} tcp sport "$i" counter return >/dev/null 2>&1
else
if [[ "$dest_ip" =~ , ]] || [ -n "$(echo ${dest_ip} | grep ',')" ]; then
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$i" counter return >/dev/null 2>&1
nft insert rule inet fw4 openclash_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$i" counter return >/dev/null 2>&1
else
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr "$nft_ipv6" tcp sport "$i" counter return >/dev/null 2>&1
nft insert rule inet fw4 openclash_v6 position 0 ip6 saddr "$nft_ipv6" tcp sport "$i" counter return >/dev/null 2>&1
fi
fi
nft insert rule inet fw4 openclash_mangle_output_v6 position 0 meta nfproto {ipv6} tcp sport "$i" counter return >/dev/null 2>&1
nft insert rule inet fw4 openclash_output_v6 position 0 meta nfproto {ipv6} tcp sport "$i" counter return >/dev/null 2>&1
fi
if $e_udp ; then
if [ -z "$dest_ip" ]; then
nft insert rule inet fw4 openclash_mangle_v6 position 0 meta nfproto {ipv6} udp sport "$i" counter return >/dev/null 2>&1
else
if [[ "$dest_ip" =~ , ]] || [ -n "$(echo ${dest_ip} | grep ',')" ]; then
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } udp sport "$i" counter return >/dev/null 2>&1
else
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr "$nft_ipv6" udp sport "$i" counter return >/dev/null 2>&1
fi
fi
nft insert rule inet fw4 openclash_mangle_output_v6 position 0 meta nfproto {ipv6} udp sport "$i" counter return >/dev/null 2>&1
fi
done
fi
fi
else
dest_port=$(echo $dest_port |sed "s/-/:/g" 2>/dev/null)
dest_ip=$(echo $dest_ip |sed "s/ /,/g" 2>/dev/null)
if [ -z "$family" ] || [ "$family" == "ipv4" ]; then
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
for i in $dest_port; do
if $e_tcp ; then
iptables -t nat -I openclash_output -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
if [ -z "$dest_ip" ]; then
iptables -t nat -I openclash -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
else
iptables -t nat -I openclash -p tcp -s "$dest_ip" --sport "$i" -j RETURN >/dev/null 2>&1
fi
fi
if $e_udp ; then
iptables -t mangle -I openclash_output -p udp --sport "$i" -j RETURN >/dev/null 2>&1
if [ -z "$dest_ip" ]; then
iptables -t mangle -I openclash -p udp --sport "$i" -j RETURN >/dev/null 2>&1
else
iptables -t mangle -I openclash -p udp -s "$dest_ip" --sport "$i" -j RETURN >/dev/null 2>&1
fi
fi
done
elif [ "$en_mode_tun" -eq 1 ]; then
for i in $dest_port; do
if $e_tcp ; then
iptables -t mangle -I openclash_output -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
if [ -z "$dest_ip" ]; then
iptables -t mangle -I openclash -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
else
iptables -t mangle -I openclash -p tcp -s "$dest_ip" --sport "$i" -j RETURN >/dev/null 2>&1
fi
fi
if $e_udp ; then
iptables -t mangle -I openclash_output -p udp --sport "$i" -j RETURN >/dev/null 2>&1
if [ -z "$dest_ip" ]; then
iptables -t mangle -I openclash -p udp --sport "$i" -j RETURN >/dev/null 2>&1
else
iptables -t mangle -I openclash -p udp -s "$dest_ip" --sport "$i" -j RETURN >/dev/null 2>&1
fi
fi
done
fi
fi
if [ "$ipv6_enable" -eq 1 ]; then
if [ -z "$family" ] || [ "$family" == "ipv6" ]; then
for i in $dest_port; do
if $e_tcp ; then
if [ -z "$dest_ip" ]; then
ip6tables -t mangle -I openclash -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
ip6tables -t nat -I openclash -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
else
ip6tables -t mangle -I openclash -s "$dest_ip" -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
ip6tables -t nat -I openclash -s "$dest_ip" -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
fi
ip6tables -t mangle -I openclash_output -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
ip6tables -t nat -I openclash_output -p tcp --sport "$i" -j RETURN >/dev/null 2>&1
fi
if $e_udp ; then
if [ -z "$dest_ip" ]; then
ip6tables -t mangle -I openclash -p udp --sport "$i" -j RETURN >/dev/null 2>&1
else
ip6tables -t mangle -I openclash -s "$dest_ip" -p udp --sport "$i" -j RETURN >/dev/null 2>&1
fi
ip6tables -t mangle -I openclash_output -p udp --sport "$i" -j RETURN >/dev/null 2>&1
fi
done
fi
fi
fi
}
firewall_redirect_exclude()
{
local section="$1"
local name src_dport dest_port dest_ip proto enabled
config_get "name" "$section" "name" ""
config_get "src_dport" "$section" "src_dport" ""
config_get "dest_port" "$section" "dest_port" ""
config_get "dest_ip" "$section" "dest_ip" ""
config_get "proto" "$section" "proto" ""
config_get "enabled" "$section" "enabled" ""
if [ -z "$src_dport" ] || [ a"$enabled" == a0 ]; then
return
fi
if [ -n "$(echo $dest_port |grep -E '\-|\:' 2>/dev/null)" ]; then
LOG_OUT "Warning: Because there is a port range【$dest_port】in the firewall rule settings【$name】auto bypassing may cause the normal connection of the client not to reach the core, if necessary, please add your own in the access control!"
return
fi
local e_udp=false
local e_tcp=false
for p in $proto; do
if [ $p == tcp ]; then e_tcp=true; fi
if [ $p == udp ]; then e_udp=true; fi
if [ $p == all ]; then e_tcp=true; e_udp=true; fi
done
if [ -z "$proto" ]; then e_tcp=true; e_udp=true; fi
if ! $e_udp && ! $e_tcp ; then
return
fi
if [ -n "$FW4" ]; then
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
if $e_tcp ; then
nft insert rule inet fw4 openclash_output position 0 ip saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
fi
if $e_udp ; then
nft insert rule inet fw4 openclash_mangle_output position 0 ip saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
if [ -n "$dest_ip" ]; then
nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
fi
fi
elif [ "$en_mode_tun" -eq 1 ]; then
if $e_tcp ; then
nft insert rule inet fw4 openclash_mangle_output position 0 ip saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
if [ -n "$dest_ip" ]; then
nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
fi
fi
if $e_udp ; then
nft insert rule inet fw4 openclash_mangle_output position 0 ip saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
if [ -n "$dest_ip" ]; then
nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
fi
fi
fi
if [ "$ipv6_enable" -eq 1 ]; then
if $e_tcp ; then
if [ -n "$dest_ip" ]; then
if [ "$ipv6_mode" -eq 1 ] || [ "$ipv6_mode" -eq 3 ]; then
nft insert rule inet fw4 openclash_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
nft insert rule inet fw4 openclash_output_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
else
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
nft insert rule inet fw4 openclash_mangle_output_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$dest_port" counter return >/dev/null 2>&1
fi
fi
fi
if $e_udp ; then
if [ -n "$dest_ip" ]; then
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
nft insert rule inet fw4 openclash_mangle_output_v6 position 0 ip6 saddr { "$dest_ip" } udp sport "$dest_port" counter return >/dev/null 2>&1
fi
fi
fi
else
dest_port=$(echo $dest_port |sed "s/-/:/g" 2>/dev/null)
dest_ip=$(echo $dest_ip |sed "s/ /,/g" 2>/dev/null)
[ -n "$dest_ip" ] && dest_ip="-s ${dest_ip}"
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
if $e_tcp ; then
iptables -t nat -I openclash_output "$dest_ip" -p tcp --sport "$dest_port" -j RETURN >/dev/null 2>&1
fi
if $e_udp ; then
iptables -t mangle -I openclash_output "$dest_ip" -p udp --sport "$dest_port" -j RETURN >/dev/null 2>&1
if [ -n "$dest_ip" ]; then
iptables -t mangle -I openclash "$dest_ip" -p udp --sport "$dest_port" -j RETURN >/dev/null 2>&1
fi
fi
elif [ "$en_mode_tun" -eq 1 ]; then
if $e_tcp ; then
iptables -t mangle -I openclash_output -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
if [ -n "$dest_ip" ]; then
iptables -t mangle -I openclash -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
fi
fi
if $e_udp ; then
iptables -t mangle -I openclash_output -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
if [ -n "$dest_ip" ]; then
iptables -t mangle -I openclash -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
fi
fi
fi
if [ "$ipv6_enable" -eq 1 ] && [ -n "$(ip6tables -t mangle -L 2>&1 | grep -o 'Chain')" ]; then
if $e_tcp ; then
if [ -n "$dest_ip" ]; then
if [ "$ipv6_mode" -eq 1 ] || [ "$ipv6_mode" -eq 3 ]; then
ip6tables -t nat -I openclash -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
ip6tables -t nat -I openclash_output -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
else
ip6tables -t mangle -I openclash -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
ip6tables -t mangle -I openclash_output -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
fi
fi
fi
if $e_udp ; then
if [ -n "$dest_ip" ]; then
ip6tables -t mangle -I openclash -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
ip6tables -t mangle -I openclash_output -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
fi
fi
fi
fi
}
set_firewall()
{
if [ -z "$(uci -q get firewall.openclash)" ] || [ -z "$(uci -q get ucitrack.@openclash[-1].init)" ]; then
uci -q delete ucitrack.@openclash[-1]
uci -q add ucitrack openclash
uci -q set ucitrack.@openclash[-1].init=openclash
uci -q commit ucitrack
uci -q delete firewall.openclash
uci -q set firewall.openclash=include
uci -q set firewall.openclash.type=script
uci -q set firewall.openclash.path=/var/etc/openclash.include
[ -n "$FW4" ] || uci -q set firewall.openclash.reload=1
uci -q commit firewall
fi
mkdir -p /var/etc
cat > "/var/etc/openclash.include" <<-EOF
/etc/init.d/openclash reload "firewall" >/dev/null 2>&1
EOF
#common ports
if [ -n "$common_ports" ] && [ "$common_ports" != "0" ]; then
if [ "$common_ports" = "1" ]; then
common_port="21 22 23 53 80 123 143 194 443 465 587 853 993 995 998 2052 2053 2082 2083 2086 2095 2096 5222 5228 5229 5230 8080 8443 8880 8888 8889"
else
common_port=$common_ports
fi
fi
case $enable_redirect_dns in
"1")
LOG_OUT "Tip: DNS Hijacking Mode is Dnsmasq Redirect..."
;;
"2")
LOG_OUT "Tip: DNS Hijacking Mode is Firewall Redirect..."
;;
*)
LOG_OUT "Tip: DNS Hijacking is Disabled..."
esac
if [ "$ipv6_enable" -eq 1 ]; then
case $ipv6_mode in
"1")
LOG_OUT "Tip: IPv6 Proxy Mode is Redirect..."
;;
"2")
LOG_OUT "Tip: IPv6 Proxy Mode is TUN..."
;;
"3")
LOG_OUT "Tip: IPv6 Proxy Mode is Mix..."
;;
*)
LOG_OUT "Tip: IPv6 Proxy Mode is TProxy..."
esac
fi
#NFTABLES
if [ -n "$FW4" ]; then
LOG_OUT "Tip: Firewall4 was Detected, Use NFTABLE Rules..."
#china ip route
if [ "$china_ip_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
nft 'flush set inet fw4 china_ip_route'
nft -f '/etc/openclash/china_ip_route.ipset'
CHNROUTE_WAIT=0
while ( [ -z "$(nft list sets |grep "set china_ip_route {")" ] && [ "$CHNROUTE_WAIT" -le 3 ] )
do
nft -f '/etc/openclash/china_ip_route.ipset'
let CHNROUTE_WAIT++
done
if [ "$enable_redirect_dns" != "2" ]; then
echo "add set inet fw4 china_ip_route_pass { type ipv4_addr; flags interval; auto-merge; }" >/tmp/openclash_china_ip_route_pass.list
[ -z `(awk '!/^$/&&!/^#/&&!/([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/{printf(" %s\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list)` ] || {
echo "define china_ip_route_pass = {" >>/tmp/openclash_china_ip_route_pass.list
awk '!/^$/&&!/^#/&&!/([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/{printf(" %s,\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list |sed '$ s/.$//' >>/tmp/openclash_china_ip_route_pass.list 2>/dev/null
echo "}" >>/tmp/openclash_china_ip_route_pass.list
echo 'add element inet fw4 china_ip_route_pass $china_ip_route_pass' >>/tmp/openclash_china_ip_route_pass.list
}
nft 'flush set inet fw4 china_ip_route_pass'
nft -f '/tmp/openclash_china_ip_route_pass.list'
rm -rf /tmp/openclash_china_ip_route_pass.list
fi
fi
#lan_ac
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
nft 'add set inet fw4 lan_ac_black_ips { type ipv4_addr; flags interval; auto-merge; }'
nft 'add set inet fw4 lan_ac_black_ipv6s { type ipv6_addr; flags interval; auto-merge; }'
config_load "openclash"
config_list_foreach "config" "lan_ac_black_ips" nft_ac_add "lan_ac_black_ips" "lan_ac_black_ipv6s"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
nft 'add set inet fw4 lan_ac_black_macs { type ether_addr; }'
config_load "openclash"
config_list_foreach "config" "lan_ac_black_macs" nft_ac_add "lan_ac_black_macs"
fi
elif [ "$lan_ac_mode" = "1" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ]; then
nft 'add set inet fw4 lan_ac_white_ips { type ipv4_addr; flags interval; auto-merge; }'
nft 'add set inet fw4 lan_ac_white_ipv6s { type ipv6_addr; flags interval; auto-merge; }'
config_load "openclash"
config_list_foreach "config" "lan_ac_white_ips" nft_ac_add "lan_ac_white_ips" "lan_ac_white_ipv6s"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
nft 'add set inet fw4 lan_ac_white_macs { type ether_addr; }'
config_load "openclash"
config_list_foreach "config" "lan_ac_white_macs" nft_ac_add "lan_ac_white_macs"
fi
fi
#wan ac
if [ -n "$(uci -q get openclash.config.wan_ac_black_ips)" ]; then
nft 'add set inet fw4 wan_ac_black_ips { type ipv4_addr; flags interval; auto-merge; }'
nft 'add set inet fw4 wan_ac_black_ipv6s { type ipv6_addr; flags interval; auto-merge; }'
config_load "openclash"
config_list_foreach "config" "wan_ac_black_ips" nft_ac_add "wan_ac_black_ips" "wan_ac_black_ipv6s"
fi
#local
nft 'add set inet fw4 localnetwork { type ipv4_addr; flags interval; auto-merge; }'
#nft 'delete set inet fw4 localnetwork'
if [ -f "/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list" ]; then
for line in `cat "/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list"`
do
nft add element inet fw4 localnetwork { "$line" }
done
else
nft 'add element inet fw4 localnetwork { 0.0.0.0/8, 127.0.0.0/8, 10.0.0.0/8, 169.254.0.0/16, 192.168.0.0/16, 224.0.0.0/4, 240.0.0.0/4, 172.16.0.0/12, 100.64.0.0/10}'
fi
if [ -n "$wan_ip4s" ]; then
for wan_ip4 in $wan_ip4s; do
nft add element inet fw4 localnetwork { "$wan_ip4" }
done
fi
#common ports
if [ -n "$common_ports" ] && [ "$common_ports" != "0" ]; then
nft 'add set inet fw4 common_ports { type inet_service; flags interval; }'
for i in $common_port; do
nft add element inet fw4 common_ports { "$i" }
done
fi
#bypass gateway compatible
if [ "$bypass_gateway_compatible" -eq 1 ]; then
#nft 'delete chain inet fw4 openclash_post'
nft 'add chain inet fw4 openclash_post'
nft 'flush chain inet fw4 openclash_post'
nft 'add rule inet fw4 openclash_post skgid == 65534 counter return'
nft add rule inet fw4 openclash_post mark "$PROXY_FWMARK" counter accept
nft 'add rule inet fw4 openclash_post ip daddr @localnetwork counter return'
nft 'add rule inet fw4 openclash_post ct direction reply counter return'
nft 'add rule inet fw4 openclash_post fib saddr type != { local } counter masquerade'
nft add rule inet fw4 srcnat meta nfproto {ipv4} counter jump openclash_post comment \"OpenClash Bypass Gateway Compatible\"
fi
#intranet allowed
if [ "$intranet_allowed" -eq 1 ]; then
if [ -n "$intranet_allowed_wan_name" ] && [ "$intranet_allowed_wan_name" != "0" ]; then
config_load "openclash"
config_list_foreach "config" "intranet_allowed_wan_name" wan_name_add
else
wan_ints=$(nft list chain inet fw4 input |grep -e "jump input_wan" 2>/dev/null |awk '{for (i=1;i<=NF;i++){if ($i ~ /iifname/ && $(i+1) != "{") {print $(i+1)} if ($i ~ /iifname/ && $(i+1) == "{"){for (j=i+1;j<=NF;j++){if ($j~ /}/) {out="";for (k=i+1;k<=j;k++){out=out" "$k};print out}}}}}' 2>/dev/null |sed 's/"//g'|sed 's/{//g'|sed 's/}//g'|sed 's/,//g')
fi
if [ -n "$wan_ints" ]; then
nft 'add chain inet fw4 openclash_wan_input'
nft 'flush chain inet fw4 openclash_wan_input'
for wan_int in $wan_ints; do
#nft delete rule inet fw4 input $(nft -a list chain inet fw4 input |grep "@localnetwork" |awk -F '# ' '{print$2}')
nft insert rule inet fw4 input position 0 iifname "$wan_int" ip saddr != @localnetwork counter jump openclash_wan_input
done
nft add rule inet fw4 openclash_wan_input th dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject
else
LOG_OUT "Warning: Can't Settting Only Intranet Allowed Function, Get IPv4 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
fi
fi
DNSPORT=$(uci -q get dhcp.@dnsmasq[0].port)
if [ -z "$DNSPORT" ]; then
DNSPORT=$(netstat -nlp |grep -E '127.0.0.1:.*dnsmasq' |awk -F '127.0.0.1:' '{print $2}' |awk '{print $1}' |head -1 || echo 53)
fi
if [ "$enable_redirect_dns" -eq 1 ]; then
if [ -z "$(nft list chain inet fw4 dstnat |grep 'OpenClash DNS Hijack')" ]; then
if [ "$lan_ac_mode" != "1" ]; then
ACBLACKDNSFILTER=""
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
ACBLACKDNSFILTER="ip saddr != @lan_ac_black_ips"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
fi
fi
nft insert rule inet fw4 dstnat position 0 meta l4proto {tcp,udp} th dport 53 ${ACBLACKDNSFILTER} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
else
nft insert rule inet fw4 dstnat position 0 meta l4proto {tcp,udp} th dport 53 ip saddr @lan_ac_white_ips counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
nft insert rule inet fw4 dstnat position 0 meta l4proto {tcp,udp} th dport 53 ether saddr @lan_ac_white_macs counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
fi
fi
if [ "$router_self_proxy" = 1 ]; then
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
nft insert rule inet fw4 nat_output position 0 skgid != 65534 meta l4proto {tcp,udp} th dport 53 ip daddr {127.0.0.1} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
fi
elif [ "$enable_redirect_dns" -eq 2 ]; then
nft 'add chain inet fw4 openclash_dns_redirect'
if [ "$lan_ac_mode" != "1" ]; then
ACBLACKDNSFILTER=""
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
ACBLACKDNSFILTER="ip saddr != @lan_ac_black_ips"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
fi
fi
nft add rule inet fw4 openclash_dns_redirect meta l4proto {tcp,udp} th dport 53 ${ACBLACKDNSFILTER} counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
else
nft add rule inet fw4 openclash_dns_redirect meta l4proto {tcp,udp} th dport 53 ip saddr @lan_ac_white_ips counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
nft add rule inet fw4 openclash_dns_redirect meta l4proto {tcp,udp} th dport 53 ether saddr @lan_ac_white_macs counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
fi
nft 'insert rule inet fw4 dstnat position 0 meta l4proto {tcp,udp} th dport 53 counter jump openclash_dns_redirect'
if [ "$router_self_proxy" = 1 ]; then
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
nft insert rule inet fw4 nat_output position 0 meta l4proto {tcp,udp} th dport 53 ip daddr {127.0.0.1} meta skgid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
fi
fi
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
#tcp
nft 'add chain inet fw4 openclash'
nft 'flush chain inet fw4 openclash'
nft 'add rule inet fw4 openclash ip daddr @localnetwork counter return'
nft 'add rule inet fw4 openclash ct direction reply counter return'
if [ -z "$en_mode_tun" ] && [ "$en_mode" = "fake-ip" ]; then
nft add rule inet fw4 openclash ip protocol tcp ip daddr { "$fakeip_range" } counter redirect to "$proxy_port"
fi
nft 'add rule inet fw4 openclash ip daddr @wan_ac_black_ips counter return'
nft 'add rule inet fw4 openclash ip saddr @lan_ac_black_ips counter return'
nft 'add rule inet fw4 openclash ether saddr @lan_ac_black_macs counter return'
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
nft 'add rule inet fw4 openclash ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
else
nft 'add rule inet fw4 openclash ether saddr != @lan_ac_white_macs counter return'
nft 'add rule inet fw4 openclash ip saddr != @lan_ac_white_ips counter return'
fi
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash th dport != @common_ports counter return'
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="ip daddr @china_ip_route"
elif [ "$china_ip_route" = "2" ]; then
rule="ip daddr != @china_ip_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip daddr != @china_ip_route_pass"
nft "add rule inet fw4 openclash $rule counter return"
fi
nft add rule inet fw4 openclash ip protocol tcp counter redirect to "$proxy_port"
nft 'add rule inet fw4 dstnat meta nfproto {ipv4} ip protocol tcp counter jump openclash'
if [ -z "$en_mode_tun" ]; then
#udp
if [ "$enable_udp_proxy" -eq 1 ]; then
modprobe nft_tproxy >/dev/null 2>&1
ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
ip route add local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE"
nft 'add chain inet fw4 openclash_mangle'
nft 'flush chain inet fw4 openclash_mangle'
nft 'add chain inet fw4 openclash_upnp'
nft 'flush chain inet fw4 openclash_upnp'
upnp_exclude
nft 'add rule inet fw4 openclash_mangle ip daddr @localnetwork counter return'
nft 'add rule inet fw4 openclash_mangle ct direction reply counter return'
if [ "$en_mode" = "fake-ip" ]; then
nft add rule inet fw4 openclash_mangle meta l4proto { udp } ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" tproxy ip to 127.0.0.1:"$tproxy_port" counter accept
fi
nft 'add rule inet fw4 openclash_mangle ip daddr @wan_ac_black_ips counter return'
nft 'add rule inet fw4 openclash_mangle ip saddr @lan_ac_black_ips counter return'
nft 'add rule inet fw4 openclash_mangle ether saddr @lan_ac_black_macs counter return'
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
else
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs counter return'
nft 'add rule inet fw4 openclash_mangle ip saddr != @lan_ac_white_ips counter return'
fi
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash_mangle th dport != @common_ports counter return'
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="ip daddr @china_ip_route"
elif [ "$china_ip_route" = "2" ]; then
rule="ip daddr != @china_ip_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip daddr != @china_ip_route_pass"
nft "add rule inet fw4 openclash_mangle $rule counter return"
fi
nft 'add rule inet fw4 openclash_mangle ip protocol udp counter jump openclash_upnp'
nft add rule inet fw4 openclash_mangle meta l4proto { udp } mark set "$PROXY_FWMARK" tproxy ip to 127.0.0.1:"$tproxy_port" counter accept
nft 'add rule inet fw4 mangle_prerouting meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle'
fi
if [ "$enable_udp_proxy" -ne 1 ] && [ "$en_mode" = "fake-ip" ]; then
modprobe nft_tproxy >/dev/null 2>&1
ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
ip route add local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE"
nft 'add chain inet fw4 openclash_mangle'
nft 'flush chain inet fw4 openclash_mangle'
nft add rule inet fw4 openclash_mangle meta l4proto { udp } ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" tproxy ip to 127.0.0.1:"$tproxy_port" counter accept 2>/dev/null
nft 'add rule inet fw4 mangle_prerouting meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle'
fi
#router self proxy udp
if ([ "$router_self_proxy" = "1" ] && [ "$enable_udp_proxy" -eq 1 ]) || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
nft 'add chain inet fw4 openclash_mangle_output'
nft 'flush chain inet fw4 openclash_mangle_output'
nft 'add rule inet fw4 openclash_mangle_output skgid == 65534 counter return'
nft 'add rule inet fw4 openclash_mangle_output ip daddr @localnetwork counter return'
nft 'add rule inet fw4 openclash_mangle_output ct direction reply counter return'
nft 'add rule inet fw4 openclash_mangle_output ip daddr @wan_ac_black_ips counter return'
if [ "$en_mode" = "redir-host" ]; then
nft add rule inet fw4 openclash_mangle_output th dport != @common_ports counter return
fi
if [ "$en_mode" = "fake-ip" ]; then
nft add rule inet fw4 openclash_mangle_output meta l4proto { udp } ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" counter accept
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="ip daddr @china_ip_route"
elif [ "$china_ip_route" = "2" ]; then
rule="ip daddr != @china_ip_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip daddr != @china_ip_route_pass"
nft "add rule inet fw4 openclash_mangle_output $rule counter return"
fi
if [ "$router_self_proxy" = "1" ] && [ "$enable_udp_proxy" -eq 1 ]; then
nft add rule inet fw4 openclash_mangle_output mark set "$PROXY_FWMARK" counter accept
fi
nft 'add rule inet fw4 mangle_output meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle_output'
fi
#quic
if [ "$disable_udp_quic" -eq 1 ]; then
if [ "$china_ip_route" = "2" ]; then
nft insert rule inet fw4 input position 0 udp dport 443 ip daddr @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
else
nft insert rule inet fw4 input position 0 udp dport 443 ip daddr != @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
fi
fi
fi
#router self proxy tcp
if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
nft 'add chain inet fw4 openclash_output'
nft 'flush chain inet fw4 openclash_output'
nft 'add rule inet fw4 openclash_output skgid == 65534 counter return'
nft 'add rule inet fw4 openclash_output ip daddr @localnetwork counter return'
nft 'add rule inet fw4 openclash_output ct direction reply counter return'
if [ "$en_mode" = "fake-ip" ] && [ "$en_mode_tun" != "1" ]; then
nft add rule inet fw4 openclash_output ip protocol tcp ip daddr { "$fakeip_range" } counter redirect to "$proxy_port"
fi
if [ "$router_self_proxy" = "1" ]; then
nft 'add rule inet fw4 openclash_output ip daddr @wan_ac_black_ips counter return'
if [ "$en_mode" = "redir-host" ]; then
nft add rule inet fw4 openclash_output th dport != @common_ports counter return
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="ip daddr @china_ip_route"
elif [ "$china_ip_route" = "2" ]; then
rule="ip daddr != @china_ip_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip daddr != @china_ip_route_pass"
nft "add rule inet fw4 openclash_output $rule counter return"
fi
nft add rule inet fw4 openclash_output ip protocol tcp counter redirect to "$proxy_port"
fi
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
nft 'add rule inet fw4 nat_output meta nfproto {ipv4} ip protocol tcp counter jump openclash_output'
fi
fi
if [ -n "$en_mode_tun" ]; then
#TUN模式
#设置防火墙
#router self proxy
if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
nft 'add chain inet fw4 openclash_mangle_output'
nft 'flush chain inet fw4 openclash_mangle_output'
nft 'add rule inet fw4 openclash_mangle_output skgid == 65534 counter return'
nft 'add rule inet fw4 openclash_mangle_output ip daddr @localnetwork counter return'
nft 'add rule inet fw4 openclash_mangle_output ct direction reply counter return'
nft add rule inet fw4 openclash_mangle_output meta l4proto {tcp,udp} ip daddr { "$fakeip_range" } mark set "$PROXY_FWMARK" counter
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash_mangle_output th dport != @common_ports counter return'
fi
if [ "$router_self_proxy" = "1" ]; then
nft 'add rule inet fw4 openclash_mangle_output ip daddr @wan_ac_black_ips counter return'
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="ip daddr @china_ip_route"
elif [ "$china_ip_route" = "2" ]; then
rule="ip daddr != @china_ip_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip daddr != @china_ip_route_pass"
nft "add rule inet fw4 openclash_mangle_output $rule counter return"
fi
if [ "$en_mode_tun" -eq 1 ]; then
nft add rule inet fw4 openclash_mangle_output meta l4proto {tcp,udp} meta mark set "$PROXY_FWMARK" counter
else
nft add rule inet fw4 openclash_mangle_output meta l4proto { udp } meta mark set "$PROXY_FWMARK" counter
fi
fi
nft 'add rule inet fw4 mangle_output meta nfproto {ipv4} meta l4proto {tcp,udp} counter jump openclash_mangle_output'
fi
nft 'add chain inet fw4 openclash_mangle'
nft 'flush chain inet fw4 openclash_mangle'
nft 'add chain inet fw4 openclash_upnp'
nft 'flush chain inet fw4 openclash_upnp'
upnp_exclude
#其他流量
nft 'add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} iifname utun counter return'
nft 'add rule inet fw4 openclash_mangle ip daddr @localnetwork counter return'
nft 'add rule inet fw4 openclash_mangle ct direction reply counter return'
nft 'add rule inet fw4 openclash_mangle ip daddr @wan_ac_black_ips counter return'
nft 'add rule inet fw4 openclash_mangle ip saddr @lan_ac_black_ips counter return'
nft 'add rule inet fw4 openclash_mangle ether saddr @lan_ac_black_macs counter return'
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs ip saddr != @lan_ac_white_ips counter return'
else
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs counter return'
nft 'add rule inet fw4 openclash_mangle ip saddr != @lan_ac_white_ips counter return'
fi
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash_mangle th dport != @common_ports counter return'
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="ip daddr @china_ip_route"
elif [ "$china_ip_route" = "2" ]; then
rule="ip daddr != @china_ip_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip daddr != @china_ip_route_pass"
nft "add rule inet fw4 openclash_mangle $rule counter return"
fi
nft 'add rule inet fw4 openclash_mangle ip protocol udp counter jump openclash_upnp'
nft add rule inet fw4 openclash_mangle mark set "$PROXY_FWMARK" counter
if [ "$en_mode_tun" -eq 1 ]; then
nft 'add rule inet fw4 mangle_prerouting meta nfproto {ipv4} meta l4proto {tcp,udp} counter jump openclash_mangle'
else
nft 'add rule inet fw4 mangle_prerouting meta nfproto {ipv4} ip protocol udp counter jump openclash_mangle'
fi
#TUN FORWORD
nft insert rule inet fw4 forward position 0 meta l4proto {tcp,udp} oifname utun counter accept comment \"OpenClash TUN Forward\"
nft insert rule inet fw4 forward position 0 meta l4proto {tcp,udp} iifname utun counter accept comment \"OpenClash TUN Forward\"
nft insert rule inet fw4 input position 0 meta l4proto {tcp,udp} iifname utun counter accept comment \"OpenClash TUN Input\"
nft insert rule inet fw4 srcnat position 0 meta nfproto {ipv4} oifname utun counter return comment \"OpenClash TUN Postrouting\"
#quic
if [ "$disable_udp_quic" -eq 1 ]; then
if [ "$china_ip_route" = "2" ]; then
nft insert rule inet fw4 forward position 0 oifname utun udp dport 443 ip daddr @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
else
nft insert rule inet fw4 forward position 0 oifname utun udp dport 443 ip daddr != @china_ip_route counter reject comment \"OpenClash QUIC REJECT\"
fi
fi
fi
#ipv6
if [ "$ipv6_enable" -eq 1 ]; then
#china ip route
if [ "$china_ip6_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
nft 'flush set inet fw4 china_ip6_route'
nft -f '/etc/openclash/china_ip6_route.ipset'
CHNROUTE_WAIT=0
while ( [ -z "$(nft list sets |grep "set china_ip6_route {")" ] && [ "$CHNROUTE_WAIT" -le 3 ] )
do
nft -f '/etc/openclash/china_ip6_route.ipset'
let CHNROUTE_WAIT++
done
if [ "$enable_redirect_dns" != "2" ]; then
echo "add set inet fw4 china_ip6_route_pass { type ipv6_addr; flags interval; auto-merge; }" >/tmp/openclash_china_ip6_route_pass.list
[ -z `(awk '!/^$/&&!/^#/&&!/([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/{printf(" %s,\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list)` ] || {
echo "define china_ip6_route_pass = {" >>/tmp/openclash_china_ip6_route_pass.list
awk '!/^$/&&!/^#/&&!/([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/{printf(" %s,\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list |sed '$ s/.$//' >>/tmp/openclash_china_ip6_route_pass.list 2>/dev/null
echo "}" >>/tmp/openclash_china_ip6_route_pass.list
echo 'add element inet fw4 china_ip6_route_pass $china_ip6_route_pass' >>/tmp/openclash_china_ip6_route_pass.list
}
nft 'flush set inet fw4 china_ip6_route_pass'
nft -f '/tmp/openclash_china_ip6_route_pass.list'
rm -rf /tmp/openclash_china_ip6_route_pass.list
fi
fi
if [ -z "$(nft list chain inet fw4 dstnat |grep 'OpenClash DNS Hijack')" ]; then
if [ "$enable_redirect_dns" -eq 1 ]; then
if [ "$lan_ac_mode" != "1" ]; then
ACBLACKDNSFILTER=""
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
ACBLACKDNSFILTER="ip6 saddr != @lan_ac_black_ipv6s"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
fi
fi
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} ip6 nexthdr {tcp,udp} th dport 53 ${ACBLACKDNSFILTER} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
else
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} ip6 nexthdr {tcp,udp} th dport 53 ip6 saddr @lan_ac_white_ipv6s counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} ip6 nexthdr {tcp,udp} th dport 53 ether saddr @lan_ac_white_macs counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
fi
if [ "$router_self_proxy" = 1 ]; then
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
nft insert rule inet fw4 nat_output position 0 skgid != 65534 meta nfproto {ipv6} ip6 nexthdr {tcp,udp} th dport 53 ip6 daddr {::/0} counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\"
fi
elif [ "$enable_redirect_dns" -eq 2 ]; then
if [ "$lan_ac_mode" != "1" ]; then
ACBLACKDNSFILTER=""
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
ACBLACKDNSFILTER="ip6 saddr != @lan_ac_black_ipv6s"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
ACBLACKDNSFILTER="$ACBLACKDNSFILTER ether saddr != @lan_ac_black_macs"
fi
fi
nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv6} ip6 nexthdr {tcp,udp} th dport 53 ${ACBLACKDNSFILTER} counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
else
nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv6} ip6 nexthdr {tcp,udp} th dport 53 ip6 saddr @lan_ac_white_ipv6s counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
nft add rule inet fw4 openclash_dns_redirect meta nfproto {ipv6} ip6 nexthdr {tcp,udp} th dport 53 ether saddr @lan_ac_white_macs counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
fi
nft 'insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} ip6 nexthdr {tcp,udp} th dport 53 counter jump openclash_dns_redirect'
if [ "$router_self_proxy" = 1 ]; then
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
nft insert rule inet fw4 nat_output position 0 meta nfproto {ipv6} ip6 nexthdr {tcp,udp} th dport 53 ip6 daddr {::/0} meta skgid != 65534 counter redirect to "$dns_port" comment \"OpenClash DNS Hijack\"
fi
fi
fi
#local
nft 'add set inet fw4 localnetwork6 { type ipv6_addr; flags interval; auto-merge; }'
#nft 'delete set inet fw4 localnetwork6'
if [ -f "/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list" ]; then
for line in `cat "/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list"`
do
nft add element inet fw4 localnetwork6 { "$line" }
done
else
nft 'add element inet fw4 localnetwork6 { ::/128, ::1/128, ::ffff:0:0/96, ::ffff:0:0:0/96, 64:ff9b::/96, 100::/64, 2001::/32, 2001:20::/28, 2001:db8::/32, 2002::/16, fc00::/7, fe80::/10, ff00::/8}'
fi
if [ -n "$wan_ip6s" ]; then
for wan_ip6 in $wan_ip6s; do
nft add element inet fw4 localnetwork6 { "$wan_ip6" }
done
fi
if [ "$ipv6_mode" -eq 1 ] || [ "$ipv6_mode" -eq 3 ]; then
#tcp
nft 'add chain inet fw4 openclash_v6'
nft 'flush chain inet fw4 openclash_v6'
nft 'add rule inet fw4 openclash_v6 ip6 daddr @localnetwork6 counter return'
nft 'add rule inet fw4 openclash_v6 ct direction reply counter return'
nft 'add rule inet fw4 openclash_v6 ip6 daddr @wan_ac_black_ipv6s counter return'
nft 'add rule inet fw4 openclash_v6 ip6 saddr @lan_ac_black_ipv6s counter return'
nft 'add rule inet fw4 openclash_v6 ether saddr @lan_ac_black_macs counter return'
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
nft 'add rule inet fw4 openclash_v6 ether saddr != @lan_ac_white_macs ip6 saddr != @lan_ac_white_ipv6s counter return'
else
nft 'add rule inet fw4 openclash_v6 ether saddr != @lan_ac_white_macs counter return'
nft 'add rule inet fw4 openclash_v6 ip6 saddr != @lan_ac_white_ipv6s counter return'
fi
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash_v6 th dport != @common_ports counter return'
fi
if [ "$china_ip6_route" != "0" ]; then
if [ "$china_ip6_route" = "1" ]; then
rule="ip6 daddr @china_ip6_route"
elif [ "$china_ip6_route" = "2" ]; then
rule="ip6 daddr != @china_ip6_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip6 daddr != @china_ip6_route_pass"
nft "add rule inet fw4 openclash_v6 $rule counter return"
fi
nft add rule inet fw4 openclash_v6 ip6 nexthdr {tcp} counter redirect to "$proxy_port"
nft 'add rule inet fw4 dstnat ip6 nexthdr {tcp} counter jump openclash_v6'
fi
#TProxy & TUN & Redirect udp
if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -ne 1 ]; then
nft 'add chain inet fw4 openclash_mangle_v6'
nft 'flush chain inet fw4 openclash_mangle_v6'
nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @localnetwork6 counter return'
nft 'add rule inet fw4 openclash_mangle_v6 ct direction reply counter return'
nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @wan_ac_black_ipv6s counter return'
if [ "$en_mode" == "redir-host" ]; then
nft 'add rule inet fw4 openclash_mangle_v6 th dport != @common_ports counter return'
fi
nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr @lan_ac_black_ipv6s counter return'
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr @lan_ac_black_macs counter return'
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr != @lan_ac_white_macs ip6 saddr != @lan_ac_white_ipv6s counter return'
else
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr != @lan_ac_white_macs counter return'
nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr != @lan_ac_white_ipv6s counter return'
fi
if [ "$china_ip6_route" != "0" ]; then
if [ "$china_ip6_route" = "1" ]; then
rule="ip6 daddr @china_ip6_route"
elif [ "$china_ip6_route" = "2" ]; then
rule="ip6 daddr != @china_ip6_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip6 daddr != @china_ip6_route_pass"
nft "add rule inet fw4 openclash_mangle_v6 $rule counter return"
fi
fi
#tcp Tproxy && TUN
if [ "$ipv6_mode" -ne 1 ] && [ "$ipv6_mode" -ne 3 ]; then
if [ "$ipv6_mode" -eq 0 ]; then
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {tcp} mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash TCP Tproxy\"
else
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {tcp} mark set "$PROXY_FWMARK" counter
fi
fi
#udp
if [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {udp} mark set "$PROXY_FWMARK" counter
else
if [ "$enable_v6_udp_proxy" -eq 1 ]; then
nft add rule inet fw4 openclash_mangle_v6 ip6 nexthdr {udp} mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash UDP Tproxy\"
fi
fi
nft 'add rule inet fw4 mangle_prerouting meta nfproto {ipv6} counter jump openclash_mangle_v6'
#router self proxy
if [ "$router_self_proxy" = "1" ]; then
if [ "$ipv6_mode" -eq 1 ] || [ "$ipv6_mode" -eq 3 ]; then
#tcp Redirect Mode
nft 'add chain inet fw4 openclash_output_v6'
nft 'flush chain inet fw4 openclash_output_v6'
nft 'add rule inet fw4 openclash_output_v6 skgid == 65534 counter return'
nft 'add rule inet fw4 openclash_output_v6 ip6 daddr @localnetwork6 counter return'
nft 'add rule inet fw4 openclash_output_v6 ct direction reply counter return'
nft 'add rule inet fw4 openclash_output_v6 ip6 daddr @wan_ac_black_ipv6s counter return'
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash_output_v6 th dport != @common_ports counter return'
fi
if [ "$china_ip6_route" != "0" ]; then
if [ "$china_ip6_route" = "1" ]; then
rule="ip6 daddr @china_ip6_route"
elif [ "$china_ip6_route" = "2" ]; then
rule="ip6 daddr != @china_ip6_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip6 daddr != @china_ip6_route_pass"
nft "add rule inet fw4 openclash_output_v6 $rule counter return"
fi
nft add rule inet fw4 openclash_output_v6 ip6 nexthdr {tcp} counter redirect to "$proxy_port"
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
nft 'add rule inet fw4 nat_output meta nfproto {ipv6} counter jump openclash_output_v6'
fi
#other mode and Redirect Mode udp
nft 'add chain inet fw4 openclash_mangle_output_v6'
nft 'flush chain inet fw4 openclash_mangle_output_v6'
nft 'add rule inet fw4 openclash_mangle_output_v6 skgid == 65534 counter return'
nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 daddr @localnetwork6 counter return'
nft 'add rule inet fw4 openclash_mangle_output_v6 ct direction reply counter return'
nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 daddr @wan_ac_black_ipv6s counter return'
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash_mangle_output_v6 th dport != @common_ports counter return'
fi
if [ "$china_ip6_route" != "0" ]; then
if [ "$china_ip6_route" = "1" ]; then
rule="ip6 daddr @china_ip6_route"
elif [ "$china_ip6_route" = "2" ]; then
rule="ip6 daddr != @china_ip6_route"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule ip6 daddr != @china_ip6_route_pass"
nft 'add rule inet fw4 openclash_mangle_output_v6 $rule counter return'
fi
if ([ "$ipv6_mode" -eq 1 ] && [ "$enable_v6_udp_proxy" -eq 1 ]) || [ "$ipv6_mode" -eq 3 ]; then
nft add rule inet fw4 openclash_mangle_output_v6 ip6 nexthdr {udp} mark set "$PROXY_FWMARK" counter
fi
if ([ "$ipv6_mode" -eq 0 ] && [ "$enable_v6_udp_proxy" -eq 1 ]) || [ "$ipv6_mode" -eq 2 ]; then
nft add rule inet fw4 openclash_mangle_output_v6 ip6 nexthdr {tcp,udp} mark set "$PROXY_FWMARK" counter
fi
if [ "$ipv6_mode" -eq 0 ] && [ "$enable_v6_udp_proxy" -ne 1 ]; then
nft add rule inet fw4 openclash_mangle_output_v6 ip6 nexthdr {tcp} mark set "$PROXY_FWMARK" counter
fi
nft 'add rule inet fw4 mangle_output meta nfproto {ipv6} counter jump openclash_mangle_output_v6'
fi
#route
if [ "$ipv6_mode" -ne 2 ] && [ "$ipv6_mode" -ne 3 ]; then
if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -eq 0 ]; then
modprobe nft_tproxy >/dev/null 2>&1
ip -6 rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
ip -6 route add local ::/0 dev lo table "$PROXY_ROUTE_TABLE"
fi
fi
#TUN FORWORD
if [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
nft insert rule inet fw4 forward position 0 meta nfproto {ipv6} oifname utun counter accept comment \"OpenClash TUN Forward\"
nft insert rule inet fw4 forward position 0 meta nfproto {ipv6} iifname utun counter accept comment \"OpenClash TUN Forward\"
nft insert rule inet fw4 input position 0 meta nfproto {ipv6} iifname utun counter accept comment \"OpenClash TUN Input\"
nft insert rule inet fw4 srcnat position 0 meta nfproto {ipv6} oifname utun counter return comment \"OpenClash TUN Postrouting\"
fi
#quic
if [ "$disable_udp_quic" -eq 1 ]; then
if [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
chain="forward"
else
chain="input"
fi
if [ "$china_ip6_route" = "2" ]; then
rule="ip6 daddr @china_ip6_route"
else
rule="ip6 daddr != @china_ip6_route"
fi
nft insert rule inet fw4 $chain position 0 udp dport 443 $rule counter reject comment \"OpenClash QUIC REJECT\"
fi
#bypass gateway compatible
if [ "$bypass_gateway_compatible" -eq 1 ]; then
#nft 'delete chain inet fw4 openclash_post_v6'
nft 'add chain inet fw4 openclash_post_v6'
nft 'flush chain inet fw4 openclash_post_v6'
nft 'add rule inet fw4 openclash_post_v6 skgid == 65534 counter return'
nft add rule inet fw4 openclash_post_v6 mark "$PROXY_FWMARK" counter accept
nft 'add rule inet fw4 openclash_post_v6 ip6 daddr @localnetwork6 counter return'
nft 'add rule inet fw4 openclash_post_v6 ct direction reply counter return'
nft 'add rule inet fw4 openclash_post_v6 fib saddr type != { local } counter masquerade'
nft add rule inet fw4 srcnat meta nfproto {ipv6} counter jump openclash_post_v6 comment \"OpenClash Bypass Gateway Compatible\"
fi
#intranet allowed
if [ "$intranet_allowed" -eq 1 ]; then
if [ -n "$intranet_allowed_wan_name" ] && [ "$intranet_allowed_wan_name" != "0" ]; then
config_load "openclash"
config_list_foreach "config" "intranet_allowed_wan_name" wan6_name_add
else
wan6_ints=$(nft list chain inet fw4 input |grep -e "jump input_wan" 2>/dev/null |awk '{for (i=1;i<=NF;i++){if ($i ~ /iifname/ && $(i+1) != "{") {print $(i+1)} if ($i ~ /iifname/ && $(i+1) == "{"){for (j=i+1;j<=NF;j++){if ($j~ /}/) {out="";for (k=i+1;k<=j;k++){out=out" "$k};print out}}}}}' 2>/dev/null |sed 's/"//g'|sed 's/{//g'|sed 's/}//g'|sed 's/,//g')
fi
if [ -n "$wan6_ints" ]; then
nft 'add chain inet fw4 openclash_wan6_input'
nft 'flush chain inet fw4 openclash_wan6_input'
for wan6_int in $wan6_ints; do
#nft delete rule inet fw4 input $(nft -a list chain inet fw4 input |grep "@localnetwork6" |awk -F '# ' '{print$2}')
nft insert rule inet fw4 input position 0 iifname "$wan6_int" ip6 saddr != @localnetwork6 counter jump openclash_wan6_input
done
nft add rule inet fw4 openclash_wan6_input ip6 nexthdr {tcp,udp} th dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject
else
LOG_OUT "Warning: Can't Settting Only Intranet Allowed Function, Get IPv6 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
fi
fi
fi
fi 2>/dev/null
#IPTABLES
if [ -z "$FW4" ]; then
#iptables owner module
if [ "$iptables_compat" -eq 0 ]; then
owner="-m mark --mark 0x1a0a"
noowner="-m mark ! --mark 0x1a0a"
addr_local="! -i lo"
else
owner="-m owner --gid-owner 65534"
noowner="-m owner ! --gid-owner 65534"
addr_local="-m addrtype ! --src-type LOCAL"
fi
#china ip route
if [ "$china_ip_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
ipset -! flush china_ip_route
ipset -! restore </etc/openclash/china_ip_route.ipset
if [ "$enable_redirect_dns" != "2" ]; then
echo "create china_ip_route_pass hash:net family inet hashsize 1024 maxelem 1000000" >/tmp/openclash_china_ip_route_pass.list
awk '!/^$/&&!/^#/&&/(^([1-9]|1[0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[1-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-5][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("add china_ip_route_pass %s'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>/tmp/openclash_china_ip_route_pass.list 2>/dev/null
ipset -! flush china_ip_route_pass
ipset -! restore </tmp/openclash_china_ip_route_pass.list
rm -rf /tmp/openclash_china_ip_route_pass.list
fi
fi
#lan_ac
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
ipset create lan_ac_black_ips hash:net
ipset create lan_ac_black_ipv6s hash:net family inet6
config_load "openclash"
config_list_foreach "config" "lan_ac_black_ips" ac_add "lan_ac_black_ips" "lan_ac_black_ipv6s"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
ipset create lan_ac_black_macs hash:mac
config_load "openclash"
config_list_foreach "config" "lan_ac_black_macs" ac_add "lan_ac_black_macs"
fi
elif [ "$lan_ac_mode" = "1" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ]; then
ipset create lan_ac_white_ips hash:net
ipset create lan_ac_white_ipv6s hash:net family inet6
config_load "openclash"
config_list_foreach "config" "lan_ac_white_ips" ac_add "lan_ac_white_ips" "lan_ac_white_ipv6s"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
ipset create lan_ac_white_macs hash:mac
config_load "openclash"
config_list_foreach "config" "lan_ac_white_macs" ac_add "lan_ac_white_macs"
fi
fi
#wan ac
if [ -n "$(uci -q get openclash.config.wan_ac_black_ips)" ]; then
ipset create wan_ac_black_ips hash:net
ipset create wan_ac_black_ipv6s hash:net family inet6
config_load "openclash"
config_list_foreach "config" "wan_ac_black_ips" ac_add "wan_ac_black_ips" "wan_ac_black_ipv6s"
fi
#local
ipset create localnetwork hash:net
if [ -f "/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list" ]; then
for line in `cat "/etc/openclash/custom/openclash_custom_localnetwork_ipv4.list"`
do
ipset add localnetwork "$line"
done
else
ipset add localnetwork 0.0.0.0/8
ipset add localnetwork 127.0.0.0/8
ipset add localnetwork 10.0.0.0/8
ipset add localnetwork 169.254.0.0/16
ipset add localnetwork 192.168.0.0/16
ipset add localnetwork 224.0.0.0/4
ipset add localnetwork 240.0.0.0/4
ipset add localnetwork 172.16.0.0/12
ipset add localnetwork 100.64.0.0/10
fi
if [ -n "$wan_ip4s" ]; then
for wan_ip4 in $wan_ip4s; do
ipset add localnetwork "$wan_ip4"
done
fi
#common ports
if [ -n "$common_ports" ] && [ "$common_ports" != "0" ]; then
ipset create common_ports bitmap:port range 0-65535
for i in $common_port; do
ipset add common_ports $i
done
fi
#bypass gateway compatible
if [ "$bypass_gateway_compatible" -eq 1 ]; then
iptables -t nat -N openclash_post
iptables -t nat -F openclash_post
iptables -t nat -A openclash_post $owner -j RETURN
iptables -t nat -A openclash_post -m mark --mark "$PROXY_FWMARK" -j ACCEPT
iptables -t nat -A openclash_post -m set --match-set localnetwork dst -j RETURN
iptables -t nat -A openclash_post -m conntrack --ctdir REPLY -j RETURN
iptables -t nat -A openclash_post $addr_local -j MASQUERADE
iptables -t nat -A POSTROUTING -m comment --comment "OpenClash Bypass Gateway Compatible" -j openclash_post
fi
#intranet allowed
if [ "$intranet_allowed" -eq 1 ]; then
if [ -n "$intranet_allowed_wan_name" ] && [ "$intranet_allowed_wan_name" != "0" ]; then
config_load "openclash"
config_list_foreach "config" "intranet_allowed_wan_name" wan_name_add
else
wan_ints=$(iptables-save -t filter |grep -e "-j zone_wan_input" 2>/dev/null |awk '{for (i=1;i<=NF;i++) {if ($i ~ /-i/) {print $(i+1)}}}' 2>/dev/null)
fi
if [ -n "$wan_ints" ]; then
iptables -t filter -N openclash_wan_input
iptables -t filter -F openclash_wan_input
for wan_int in $wan_ints; do
iptables -t filter -I INPUT -i "$wan_int" -m set ! --match-set localnetwork src -j openclash_wan_input
done
iptables -t filter -A openclash_wan_input -p udp -m multiport --dport "$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port" -j REJECT >/dev/null 2>&1
iptables -t filter -A openclash_wan_input -p tcp -m multiport --dport "$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port" -j REJECT >/dev/null 2>&1
else
LOG_OUT "Warning: Can't Settting Only Intranet Allowed Function, Get IPv4 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
fi
fi
DNSPORT=$(uci -q get dhcp.@dnsmasq[0].port)
if [ -z "$DNSPORT" ]; then
DNSPORT=$(netstat -nlp |grep -E '127.0.0.1:.*dnsmasq' |awk -F '127.0.0.1:' '{print $2}' |awk '{print $1}' |head -1 || echo 53)
fi
if [ "$enable_redirect_dns" -eq 1 ]; then
if [ -z "$(iptables -t nat -nL PREROUTING --line-number |grep 'OpenClash DNS Hijack')" ]; then
if [ "$lan_ac_mode" != "1" ]; then
ACBLACKDNSFILTER=""
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
ACBLACKDNSFILTER="-m set ! --match-set lan_ac_black_ips src"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
ACBLACKDNSFILTER="$ACBLACKDNSFILTER -m set ! --match-set lan_ac_black_macs src"
fi
fi
iptables -t nat -I PREROUTING -p udp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -I PREROUTING -p tcp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
else
iptables -t nat -I PREROUTING -p udp --dport 53 -m set --match-set lan_ac_white_ips src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -I PREROUTING -p tcp --dport 53 -m set --match-set lan_ac_white_ips src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -I PREROUTING -p udp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -I PREROUTING -p tcp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
fi
fi
if [ "$router_self_proxy" = 1 ]; then
iptables -t nat -I OUTPUT $noowner -m comment --comment "OpenClash DNS Hijack" -p tcp --dport 53 -d 127.0.0.1 -j REDIRECT --to-ports "$DNSPORT"
iptables -t nat -I OUTPUT $noowner -m comment --comment "OpenClash DNS Hijack" -p udp --dport 53 -d 127.0.0.1 -j REDIRECT --to-ports "$DNSPORT"
fi
elif [ "$enable_redirect_dns" -eq 2 ]; then
iptables -t nat -N openclash_dns_redirect
iptables -t nat -F openclash_dns_redirect
if [ "$lan_ac_mode" != "1" ]; then
ACBLACKDNSFILTER=""
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
ACBLACKDNSFILTER="-m set ! --match-set lan_ac_black_ips src"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
ACBLACKDNSFILTER="$ACBLACKDNSFILTER -m set ! --match-set lan_ac_black_macs src"
fi
fi
iptables -t nat -A openclash_dns_redirect -p udp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -A openclash_dns_redirect -p tcp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
else
iptables -t nat -A openclash_dns_redirect -p udp --dport 53 -m set --match-set lan_ac_white_ips src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -A openclash_dns_redirect -p tcp --dport 53 -m set --match-set lan_ac_white_ips src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -A openclash_dns_redirect -p udp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -A openclash_dns_redirect -p tcp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
fi
iptables -t nat -I PREROUTING -p udp --dport 53 -j openclash_dns_redirect
iptables -t nat -I PREROUTING -p tcp --dport 53 -j openclash_dns_redirect
if [ "$router_self_proxy" = 1 ]; then
iptables -t nat -I OUTPUT -p udp --dport 53 -d 127.0.0.1 $noowner -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -I OUTPUT -p tcp --dport 53 -d 127.0.0.1 $noowner -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
fi
fi
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
#tcp
iptables -t nat -N openclash
iptables -t nat -F openclash
iptables -t nat -A openclash -m set --match-set localnetwork dst -j RETURN
iptables -t nat -A openclash -m conntrack --ctdir REPLY -j RETURN
if [ -z "$en_mode_tun" ] && [ "$en_mode" = "fake-ip" ]; then
iptables -t nat -A openclash -p tcp -d "$fakeip_range" -j REDIRECT --to-ports "$proxy_port"
fi
iptables -t nat -A openclash -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
iptables -t nat -A openclash -m set --match-set lan_ac_black_ips src -j RETURN >/dev/null 2>&1
iptables -t nat -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
iptables -t nat -A openclash -m set ! --match-set lan_ac_white_ips src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
else
iptables -t nat -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
iptables -t nat -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
fi
if [ "$en_mode" = "redir-host" ]; then
iptables -t nat -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="-m set --match-set china_ip_route dst"
elif [ "$china_ip_route" = "2" ]; then
rule="-m set ! --match-set china_ip_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip_route_pass dst"
iptables -t nat -A openclash $rule -j RETURN >/dev/null 2>&1
fi
iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
iptables -t nat -A PREROUTING -p tcp -j openclash
if [ -z "$en_mode_tun" ]; then
#udp
if [ "$enable_udp_proxy" -eq 1 ]; then
modprobe xt_TPROXY >/dev/null 2>&1
ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
ip route add local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE"
iptables -t mangle -N openclash
iptables -t mangle -F openclash
iptables -t mangle -N openclash_upnp
iptables -t mangle -F openclash_upnp
upnp_exclude
iptables -t mangle -A openclash -m set --match-set localnetwork dst -j RETURN
iptables -t mangle -A openclash -m conntrack --ctdir REPLY -j RETURN
if [ "$en_mode" = "fake-ip" ]; then
iptables -t mangle -A openclash -p udp -d "$fakeip_range" -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
fi
iptables -t mangle -A openclash -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set --match-set lan_ac_black_ips src -j RETURN >/dev/null 2>&1
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
else
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
fi
if [ "$en_mode" = "redir-host" ]; then
iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="-m set --match-set china_ip_route dst"
elif [ "$china_ip_route" = "2" ]; then
rule="-m set ! --match-set china_ip_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip_route_pass dst"
iptables -t mangle -A openclash $rule -j RETURN >/dev/null 2>&1
fi
iptables -t mangle -A openclash -p udp -j openclash_upnp >/dev/null 2>&1
iptables -t mangle -A openclash -p udp -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
iptables -t mangle -A PREROUTING -p udp -j openclash
fi
if [ "$enable_udp_proxy" -ne 1 ] && [ "$en_mode" = "fake-ip" ]; then
modprobe xt_TPROXY >/dev/null 2>&1
ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
ip route add local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE"
iptables -t mangle -N openclash
iptables -t mangle -F openclash
iptables -t mangle -A openclash -p udp -d "$fakeip_range" -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
iptables -t mangle -A PREROUTING -p udp -j openclash
fi
#router self proxy udp
if ([ "$router_self_proxy" = "1" ] && [ "$enable_udp_proxy" -eq 1 ]) || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
iptables -t mangle -N openclash_output
iptables -t mangle -F openclash_output
iptables -t mangle -A openclash_output $owner -j RETURN
iptables -t mangle -A openclash_output -m set --match-set localnetwork dst -j RETURN
iptables -t mangle -A openclash_output -m conntrack --ctdir REPLY -j RETURN
iptables -t mangle -A openclash_output -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "fake-ip" ]; then
iptables -t mangle -A openclash_output -p udp -d "$fakeip_range" -j MARK --set-mark "$PROXY_FWMARK"
fi
if [ "$en_mode" = "redir-host" ]; then
iptables -t mangle -A openclash_output -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="-m set --match-set china_ip_route dst"
elif [ "$china_ip_route" = "2" ]; then
rule="-m set ! --match-set china_ip_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip_route_pass dst"
iptables -t mangle -A openclash_output $rule -j RETURN >/dev/null 2>&1
fi
if [ "$router_self_proxy" = "1" ] && [ "$enable_udp_proxy" -eq 1 ]; then
iptables -t mangle -A openclash_output -p udp -j MARK --set-mark "$PROXY_FWMARK"
fi
iptables -t mangle -A OUTPUT -p udp -j openclash_output
fi
#quic
if [ "$disable_udp_quic" -eq 1 ]; then
if [ "$china_ip_route" = "2" ]; then
iptables -I INPUT -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set --match-set china_ip_route dst -j REJECT >/dev/null 2>&1
else
iptables -I INPUT -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip_route dst -j REJECT >/dev/null 2>&1
fi
fi
fi
#router self proxy tcp
if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
iptables -t nat -N openclash_output
iptables -t nat -F openclash_output
iptables -t nat -A openclash_output $owner -j RETURN
if [ "$en_mode" = "fake-ip" ] && [ "$en_mode_tun" != "1" ]; then
iptables -t nat -A openclash_output -p tcp -d "$fakeip_range" -j REDIRECT --to-ports "$proxy_port"
fi
if [ "$router_self_proxy" = "1" ]; then
iptables -t nat -A openclash_output -m set --match-set localnetwork dst -j RETURN
iptables -t nat -A openclash_output -m conntrack --ctdir REPLY -j RETURN
iptables -t nat -A openclash_output -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "redir-host" ]; then
iptables -t nat -A openclash_output -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="-m set --match-set china_ip_route dst"
elif [ "$china_ip_route" = "2" ]; then
rule="-m set ! --match-set china_ip_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip_route_pass dst"
iptables -t nat -A openclash_output $rule -j RETURN >/dev/null 2>&1
fi
iptables -t nat -A openclash_output -p tcp -j REDIRECT --to-ports "$proxy_port"
fi
iptables -t nat -A OUTPUT -j openclash_output >/dev/null 2>&1
fi
fi
if [ -n "$en_mode_tun" ]; then
#TUN模式
#设置防火墙
#router self proxy
if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
iptables -t mangle -N openclash_output
iptables -t mangle -F openclash_output
iptables -t mangle -A openclash_output $owner -j RETURN
iptables -t mangle -A openclash_output -m set --match-set localnetwork dst -j RETURN
iptables -t mangle -A openclash_output -m conntrack --ctdir REPLY -j RETURN
iptables -t mangle -A openclash_output -d "$fakeip_range" -j MARK --set-mark "$PROXY_FWMARK"
if [ "$en_mode" = "redir-host" ]; then
iptables -t mangle -A openclash_output -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$router_self_proxy" = "1" ]; then
iptables -t mangle -A openclash_output -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="-m set --match-set china_ip_route dst"
elif [ "$china_ip_route" = "2" ]; then
rule="-m set ! --match-set china_ip_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip_route_pass dst"
iptables -t mangle -A openclash_output $rule -j RETURN >/dev/null 2>&1
fi
if [ "$en_mode_tun" -eq 1 ]; then
iptables -t mangle -A openclash_output -j MARK --set-mark "$PROXY_FWMARK"
else
iptables -t mangle -A openclash_output -p udp -j MARK --set-mark "$PROXY_FWMARK"
fi
fi
iptables -t mangle -A OUTPUT -j openclash_output
fi
iptables -t mangle -N openclash
iptables -t mangle -F openclash
iptables -t mangle -N openclash_upnp
iptables -t mangle -F openclash_upnp
upnp_exclude
#其他流量
iptables -t mangle -A openclash -i utun -j RETURN
iptables -t mangle -A openclash -m set --match-set localnetwork dst -j RETURN
iptables -t mangle -A openclash -m conntrack --ctdir REPLY -j RETURN
iptables -t mangle -A openclash -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set --match-set lan_ac_black_ips src -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
else
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
fi
if [ "$en_mode" = "redir-host" ]; then
iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip_route" != "0" ]; then
if [ "$china_ip_route" = "1" ]; then
rule="-m set --match-set china_ip_route dst"
elif [ "$china_ip_route" = "2" ]; then
rule="-m set ! --match-set china_ip_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip_route_pass dst"
iptables -t mangle -A openclash $rule -j RETURN >/dev/null 2>&1
fi
iptables -t mangle -A openclash -p udp -j openclash_upnp >/dev/null 2>&1
iptables -t mangle -A openclash -j MARK --set-mark "$PROXY_FWMARK"
if [ "$en_mode_tun" -eq 1 ]; then
iptables -t mangle -A PREROUTING -j openclash
else
iptables -t mangle -A PREROUTING -p udp -j openclash
fi
#TUN FORWORD
iptables -I FORWARD -m comment --comment "OpenClash TUN Forward" -o utun -j ACCEPT >/dev/null 2>&1
iptables -I FORWARD -m comment --comment "OpenClash TUN Forward" -i utun -j ACCEPT >/dev/null 2>&1
iptables -I INPUT -m comment --comment "OpenClash TUN Input" -i utun -j ACCEPT >/dev/null 2>&1
iptables -t nat -I POSTROUTING -m comment --comment "OpenClash TUN Postrouting" -o utun -j RETURN >/dev/null 2>&1
#quic
if [ "$disable_udp_quic" -eq 1 ]; then
if [ "$china_ip_route" = "2" ]; then
iptables -I FORWARD -p udp --dport 443 -o utun -m comment --comment "OpenClash QUIC REJECT" -m set --match-set china_ip_route dst -j REJECT >/dev/null 2>&1
else
iptables -I FORWARD -p udp --dport 443 -o utun -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip_route dst -j REJECT >/dev/null 2>&1
fi
fi
fi
#ipv6
if [ "$ipv6_enable" -eq 1 ] && [ -n "$(ip6tables -t mangle -L 2>&1 | grep -o 'Chain')" ]; then
#china ip route
if [ "$china_ip6_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
ipset -! flush china_ip6_route
ipset -! restore </etc/openclash/china_ip6_route.ipset
if [ "$enable_redirect_dns" != "2" ]; then
echo "create china_ip6_route_pass hash:net family inet6 hashsize 1024 maxelem 1000000" >/tmp/openclash_china_ip6_route_pass.list
awk '!/^$/&&!/^#/&&!/([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/{printf("add china_ip6_route_pass %s'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>/tmp/openclash_china_ip6_route_pass.list
ipset -! flush china_ip6_route_pass
ipset -! restore </tmp/openclash_china_ip6_route_pass.list
rm -rf /tmp/openclash_china_ip6_route_pass.list
fi
fi
if [ -z "$(ip6tables -t nat -nL PREROUTING --line-number |grep 'DNS Hijack')" ]; then
if [ "$enable_redirect_dns" -eq 1 ]; then
if [ "$lan_ac_mode" != "1" ]; then
ACBLACKDNSFILTER=""
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
ACBLACKDNSFILTER="-m set ! --match-set lan_ac_black_ipv6s src"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
ACBLACKDNSFILTER="$ACBLACKDNSFILTER -m set ! --match-set lan_ac_black_macs src"
fi
fi
ip6tables -t nat -I PREROUTING -p udp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -I PREROUTING -p tcp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
else
ip6tables -t nat -I PREROUTING -p udp --dport 53 -m set --match-set lan_ac_white_ipv6s src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -I PREROUTING -p tcp --dport 53 -m set --match-set lan_ac_white_ipv6s src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -I PREROUTING -p udp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -I PREROUTING -p tcp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
fi
if [ "$router_self_proxy" = 1 ]; then
ip6tables -t nat -I OUTPUT -p tcp --dport 53 -d ::/0 $noowner -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -I OUTPUT -p udp --dport 53 -d ::/0 $noowner -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
fi
elif [ "$enable_redirect_dns" -eq 2 ]; then
ip6tables -t nat -N openclash_dns_redirect
ip6tables -t nat -F openclash_dns_redirect
if [ "$lan_ac_mode" != "1" ]; then
ACBLACKDNSFILTER=""
if [ "$lan_ac_mode" = "0" ]; then
if [ -n "$(uci -q get openclash.config.lan_ac_black_ips)" ]; then
ACBLACKDNSFILTER="-m set ! --match-set lan_ac_black_ipv6s src"
fi
if [ -n "$(uci -q get openclash.config.lan_ac_black_macs)" ]; then
ACBLACKDNSFILTER="$ACBLACKDNSFILTER -m set ! --match-set lan_ac_black_macs src"
fi
fi
ip6tables -t nat -A openclash_dns_redirect -p udp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -A openclash_dns_redirect -p tcp --dport 53 ${ACBLACKDNSFILTER} -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
else
ip6tables -t nat -A openclash_dns_redirect -p udp --dport 53 -m set --match-set lan_ac_white_ipv6s src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -A openclash_dns_redirect -p tcp --dport 53 -m set --match-set lan_ac_white_ipv6s src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -A openclash_dns_redirect -p udp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -A openclash_dns_redirect -p tcp --dport 53 -m set --match-set lan_ac_white_macs src -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
fi
ip6tables -t nat -I PREROUTING -p udp --dport 53 -j openclash_dns_redirect
ip6tables -t nat -I PREROUTING -p tcp --dport 53 -j openclash_dns_redirect
if [ "$router_self_proxy" = 1 ]; then
ip6tables -t nat -I OUTPUT -p udp --dport 53 -d ::/0 $noowner -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -I OUTPUT -p tcp --dport 53 -d ::/0 $noowner -j REDIRECT --to-ports "$dns_port" -m comment --comment "OpenClash DNS Hijack"
fi
fi
fi
#local
ipset create localnetwork6 hash:net family inet6
if [ -f "/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list" ]; then
for line in `cat "/etc/openclash/custom/openclash_custom_localnetwork_ipv6.list"`
do
ipset add localnetwork6 "$line"
done
else
ipset add localnetwork6 ::/128
ipset add localnetwork6 ::1/128
ipset add localnetwork6 ::ffff:0:0/96
ipset add localnetwork6 ::ffff:0:0:0/96
ipset add localnetwork6 64:ff9b::/96
ipset add localnetwork6 100::/64
ipset add localnetwork6 2001::/32
ipset add localnetwork6 2001:20::/28
ipset add localnetwork6 2001:db8::/32
ipset add localnetwork6 2002::/16
ipset add localnetwork6 fc00::/7
ipset add localnetwork6 fe80::/10
ipset add localnetwork6 ff00::/8
fi
if [ -n "$wan_ip6s" ]; then
for wan_ip6 in $wan_ip6s; do
ipset add localnetwork6 "$wan_ip6"
done
fi
if [ "$ipv6_mode" -eq 1 ] || [ "$ipv6_mode" -eq 3 ]; then
#tcp
ip6tables -t nat -N openclash
ip6tables -t nat -F openclash
ip6tables -t nat -A openclash -m set --match-set localnetwork6 dst -j RETURN
ip6tables -t nat -A openclash -m conntrack --ctdir REPLY -j RETURN
ip6tables -t nat -A openclash -m set --match-set wan_ac_black_ipv6s dst -j RETURN >/dev/null 2>&1
ip6tables -t nat -A openclash -m set --match-set lan_ac_black_ipv6s src -j RETURN >/dev/null 2>&1
ip6tables -t nat -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
ip6tables -t nat -A openclash -m set ! --match-set lan_ac_white_ipv6s src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
else
ip6tables -t nat -A openclash -m set ! --match-set lan_ac_white_ipv6s src -j RETURN >/dev/null 2>&1
ip6tables -t nat -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
fi
if [ "$en_mode" = "redir-host" ]; then
ip6tables -t nat -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip6_route" != "0" ]; then
if [ "$china_ip6_route" = "1" ]; then
rule="-m set --match-set china_ip6_route dst"
elif [ "$china_ip6_route" = "2" ]; then
rule="-m set ! --match-set china_ip6_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip6_route_pass dst"
ip6tables -t nat -A openclash $rule -j RETURN >/dev/null 2>&1
fi
ip6tables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
ip6tables -t nat -A PREROUTING -p tcp -j openclash
fi
#TProxy & TUN & Redirect udp
if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -ne 1 ]; then
ip6tables -t mangle -N openclash
ip6tables -t mangle -F openclash
ip6tables -t mangle -A openclash -m set --match-set localnetwork6 dst -j RETURN
ip6tables -t mangle -A openclash -m conntrack --ctdir REPLY -j RETURN
ip6tables -t mangle -A openclash -m set --match-set wan_ac_black_ipv6s dst -j RETURN >/dev/null 2>&1
ip6tables -t mangle -A openclash -m set --match-set lan_ac_black_macs src -j RETURN >/dev/null 2>&1
ip6tables -t mangle -A openclash -m set --match-set lan_ac_black_ipv6s src -j RETURN >/dev/null 2>&1
if [ "$lan_ac_mode" = "1" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_ips)" ] && [ -n "$(uci -q get openclash.config.lan_ac_white_macs)" ]; then
ip6tables -t mangle -A openclash -m set ! --match-set lan_ac_white_ipv6s src -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
else
ip6tables -t mangle -A openclash -m set ! --match-set lan_ac_white_ipv6s src -j RETURN >/dev/null 2>&1
ip6tables -t mangle -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
fi
if [ "$en_mode" == "redir-host" ]; then
ip6tables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip6_route" != "0" ]; then
if [ "$china_ip6_route" = "1" ]; then
rule="-m set --match-set china_ip6_route dst"
elif [ "$china_ip6_route" = "2" ]; then
rule="-m set ! --match-set china_ip6_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip6_route_pass dst"
ip6tables -t mangle -A openclash $rule -j RETURN >/dev/null 2>&1
fi
fi
#tcp Tproxy && TUN
if [ "$ipv6_mode" -ne 1 ] && [ "$ipv6_mode" -ne 3 ]; then
if [ "$ipv6_mode" -eq 0 ]; then
ip6tables -t mangle -A openclash -p tcp -m comment --comment "OpenClash TCP Tproxy" -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
else
ip6tables -t mangle -A openclash -p tcp -j MARK --set-mark "$PROXY_FWMARK"
fi
fi
#udp
if [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
ip6tables -t mangle -A openclash -p udp -m comment --comment "OpenClash UDP TUN" -j MARK --set-xmark "$PROXY_FWMARK"
else
if [ "$enable_v6_udp_proxy" -eq 1 ]; then
ip6tables -t mangle -A openclash -p udp -m comment --comment "OpenClash UDP Tproxy" -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
fi
fi
ip6tables -t mangle -A PREROUTING -j openclash
#router self proxy
if [ "$router_self_proxy" = "1" ]; then
if [ "$ipv6_mode" -eq 1 ] || [ "$ipv6_mode" -eq 3 ]; then
#tcp Redirect Mode
ip6tables -t nat -N openclash_output
ip6tables -t nat -F openclash_output
ip6tables -t nat -A openclash_output $owner -j RETURN
ip6tables -t nat -A openclash_output -m set --match-set localnetwork6 dst -j RETURN
ip6tables -t nat -A openclash_output -m conntrack --ctdir REPLY -j RETURN
ip6tables -t nat -A openclash_output -m set --match-set wan_ac_black_ipv6s dst -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "redir-host" ]; then
ip6tables -t nat -A openclash_output -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip6_route" != "0" ]; then
if [ "$china_ip6_route" = "1" ]; then
rule="-m set --match-set china_ip6_route dst"
elif [ "$china_ip6_route" = "2" ]; then
rule="-m set ! --match-set china_ip6_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip6_route_pass dst"
ip6tables -t nat -A openclash_output $rule -j RETURN >/dev/null 2>&1
fi
ip6tables -t nat -A openclash_output -p tcp -j REDIRECT --to-ports "$proxy_port"
ip6tables -t nat -A OUTPUT -j openclash_output >/dev/null 2>&1
fi
#other mode and Redirect Mode udp
ip6tables -t mangle -N openclash_output
ip6tables -t mangle -F openclash_output
ip6tables -t mangle -A openclash_output $owner -j RETURN
ip6tables -t mangle -A openclash_output -m set --match-set localnetwork6 dst -j RETURN
ip6tables -t mangle -A openclash_output -m conntrack --ctdir REPLY -j RETURN
ip6tables -t mangle -A openclash_output -m set --match-set wan_ac_black_ipv6s dst -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "redir-host" ]; then
ip6tables -t mangle -A openclash_output -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip6_route" != "0" ]; then
if [ "$china_ip6_route" = "1" ]; then
rule="-m set --match-set china_ip6_route dst"
elif [ "$china_ip6_route" = "2" ]; then
rule="-m set ! --match-set china_ip6_route dst"
fi
[ "$enable_redirect_dns" != "2" ] && rule="$rule -m set ! --match-set china_ip6_route_pass dst"
ip6tables -t mangle -A openclash_output $rule -j RETURN >/dev/null 2>&1
fi
if ([ "$ipv6_mode" -eq 1 ] && [ "$enable_v6_udp_proxy" -eq 1 ]) || [ "$ipv6_mode" -eq 3 ]; then
ip6tables -t mangle -A openclash_output -p udp -j MARK --set-xmark "$PROXY_FWMARK"
fi
if ([ "$ipv6_mode" -eq 0 ] && [ "$enable_v6_udp_proxy" -eq 1 ]) || [ "$ipv6_mode" -eq 2 ]; then
ip6tables -t mangle -A openclash_output -j MARK --set-xmark "$PROXY_FWMARK"
fi
if [ "$ipv6_mode" -eq 0 ] && [ "$enable_v6_udp_proxy" -ne 1 ]; then
ip6tables -t mangle -A openclash_output -p tcp -j MARK --set-xmark "$PROXY_FWMARK"
fi
ip6tables -t mangle -A OUTPUT -j openclash_output
fi
#route
if [ "$ipv6_mode" -ne 2 ] && [ "$ipv6_mode" -ne 3 ]; then
if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -eq 0 ]; then
modprobe xt_TPROXY >/dev/null 2>&1
ip -6 rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
ip -6 route add local ::/0 dev lo table "$PROXY_ROUTE_TABLE"
fi
fi
#TUN FORWORD
if [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
ip6tables -I FORWARD -m comment --comment "OpenClash TUN Forward" -o utun -j ACCEPT >/dev/null 2>&1
ip6tables -I FORWARD -m comment --comment "OpenClash TUN Forward" -i utun -j ACCEPT >/dev/null 2>&1
ip6tables -I INPUT -m comment --comment "OpenClash TUN Input" -i utun -j ACCEPT >/dev/null 2>&1
ip6tables -t nat -I POSTROUTING -m comment --comment "OpenClash TUN Postrouting" -o utun -j RETURN >/dev/null 2>&1
fi
#quic
if [ "$disable_udp_quic" -eq 1 ]; then
if [ "$ipv6_mode" -eq 2 ] || [ "$ipv6_mode" -eq 3 ]; then
chain="FORWARD -o utun"
else
chain="INPUT"
fi
if [ "$china_ip6_route" = "2" ]; then
rule="-m set --match-set china_ip6_route dst"
else
rule="-m set ! --match-set china_ip6_route dst"
fi
ip6tables -I $chain -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" $rule -j REJECT >/dev/null 2>&1
fi
#bypass gateway compatible
if [ "$bypass_gateway_compatible" -eq 1 ]; then
ip6tables -t nat -N openclash_post
ip6tables -t nat -F openclash_post
ip6tables -t nat -A openclash_post $owner -j RETURN
ip6tables -t nat -A openclash_post -m mark --mark "$PROXY_FWMARK" -j ACCEPT
ip6tables -t nat -A openclash_post -m set --match-set localnetwork6 dst -j RETURN
ip6tables -t nat -A openclash_post -m conntrack --ctdir REPLY -j RETURN
ip6tables -t nat -A openclash_post $addr_local -j MASQUERADE
ip6tables -t nat -A POSTROUTING -m comment --comment "OpenClash Bypass Gateway Compatible" -j openclash_post
fi
#intranet allowed
if [ "$intranet_allowed" -eq 1 ]; then
if [ -n "$intranet_allowed_wan_name" ] && [ "$intranet_allowed_wan_name" != "0" ]; then
config_load "openclash"
config_list_foreach "config" "intranet_allowed_wan_name" wan6_name_add
else
wan6_ints=$(ip6tables-save -t filter |grep -e "-j zone_wan_input" 2>/dev/null |awk '{for (i=1;i<=NF;i++) {if ($i ~ /-i/) {print $(i+1)}}}' 2>/dev/null)
fi
if [ -n "$wan6_ints" ]; then
ip6tables -t filter -N openclash_wan_input
ip6tables -t filter -F openclash_wan_input
for wan6_int in $wan6_ints; do
ip6tables -t filter -I INPUT -i "$wan6_int" -m set ! --match-set localnetwork6 src -j openclash_wan_input
done
ip6tables -t filter -A openclash_wan_input -p udp -m multiport --dport "$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port" -j REJECT >/dev/null 2>&1
ip6tables -t filter -A openclash_wan_input -p tcp -m multiport --dport "$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port" -j REJECT >/dev/null 2>&1
else
LOG_OUT "Warning: Can't Settting Only Intranet Allowed Function, Get IPv6 WAN Interfaces error, Please Verify The Firewall's WAN Zone Name is wan, Ignore This IF The Device Does not Have a WAN Interfaces..."
fi
fi
fi
fi 2>/dev/null
#端口转发
LOG_OUT "Tip: Start Add Port Bypassing Rules For Firewall Redirect and Firewall Rules..."
config_load "firewall"
config_foreach firewall_redirect_exclude "redirect"
config_foreach firewall_rule_exclude "rule"
config_load "openclash"
config_foreach firewall_lan_ac_traffic "lan_ac_traffic"
#Custom
if [ -f "/etc/openclash/custom/openclash_custom_firewall_rules.sh" ]; then
chmod +x /etc/openclash/custom/openclash_custom_firewall_rules.sh >/dev/null 2>&1
/etc/openclash/custom/openclash_custom_firewall_rules.sh >/dev/null 2>&1
fi
}
revert_firewall()
{
rm -rf /var/etc/openclash.include >/dev/null 2>&1
ip rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
ip route del local 0.0.0.0/0 dev lo table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
ip -6 rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
ip -6 route del local ::/0 dev lo table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
#TUN
ip rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
ip rule del fwmark "$PROXY_FWMARK" ipproto icmp table main >/dev/null 2>&1
ip route del default dev utun table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
ip -6 rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
ip -6 rule del fwmark "$PROXY_FWMARK" ipproto icmp table main >/dev/null 2>&1
ip -6 route del default dev utun table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
if [ -n "$FW4" ]; then
for nft in "input" "forward" "dstnat" "srcnat" "nat_output" "mangle_prerouting" "mangle_output"; do
local handles=$(nft -a list chain inet fw4 ${nft} |grep -E "openclash|OpenClash" |awk -F '# handle ' '{print$2}')
for handle in $handles; do
nft delete rule inet fw4 ${nft} handle ${handle}
done
done >/dev/null 2>&1
for handle in $(nft -a list chains |grep -E "chain openclash|OpenClash" |awk -F '# handle ' '{print$2}'); do
nft delete chain inet fw4 handle ${handle}
done >/dev/null 2>&1
for handle in $(nft -a list sets |grep -E "set localnetwork|china_ip|lan_ac_|wan_ac_black_|_google_dns_|common_ports" |awk -F '# handle ' '{print$2}'); do
nft delete set inet fw4 handle ${handle}
done >/dev/null 2>&1
else
for ipt in "iptables -nvL INPUT" "iptables -nvL FORWARD" "iptables -nvL POSTROUTING -t nat" "iptables -nvL OUTPUT -t nat" "iptables -nvL OUTPUT -t mangle" "iptables -nvL PREROUTING -t nat" "iptables -nvL PREROUTING -t mangle" "ip6tables -nvL PREROUTING -t mangle" "ip6tables -nvL OUTPUT -t mangle" "ip6tables -nvL PREROUTING -t nat" "ip6tables -nvL INPUT" "ip6tables -nvL POSTROUTING -t nat" "ip6tables -nvL FORWARD" "ip6tables -nvL OUTPUT -t nat"; do
for comment in "openclash" "OpenClash"; do
local lines=$($ipt |sed 1,2d |sed -n "/${comment}/=" 2>/dev/null |sort -rn)
if [ -n "$lines" ]; then
for line in $lines; do
$(echo "$ipt" |awk -v OFS=" " '{print $1,$4,$5}' |sed 's/[ ]*$//g') -D $(echo "$ipt" |awk '{print $3}') $line
done
fi
done
done >/dev/null 2>&1
for chain in "openclash" "openclash_output" "openclash_post" "openclash_wan_input" "openclash_dns_redirect" "openclash_upnp"; do
iptables -t nat -F $chain
iptables -t nat -X $chain
iptables -t mangle -F $chain
iptables -t mangle -X $chain
iptables -t filter -F $chain
iptables -t filter -X $chain
ip6tables -t nat -F $chain
ip6tables -t nat -X $chain
ip6tables -t mangle -F $chain
ip6tables -t mangle -X $chain
ip6tables -t filter -F $chain
ip6tables -t filter -X $chain
done >/dev/null 2>&1
ipset destroy localnetwork6 >/dev/null 2>&1
ipset destroy china_ip6_route >/dev/null 2>&1
ipset destroy china_ip6_route_pass >/dev/null 2>&1
ipset destroy lan_ac_white_ipv6s >/dev/null 2>&1
ipset destroy lan_ac_black_ipv6s >/dev/null 2>&1
ipset destroy wan_ac_black_ipv6s >/dev/null 2>&1
ipset destroy localnetwork >/dev/null 2>&1
ipset destroy china_ip_route >/dev/null 2>&1
ipset destroy china_ip_route_pass >/dev/null 2>&1
ipset destroy lan_ac_white_ips >/dev/null 2>&1
ipset destroy lan_ac_black_ips >/dev/null 2>&1
ipset destroy lan_ac_white_macs >/dev/null 2>&1
ipset destroy lan_ac_black_macs >/dev/null 2>&1
ipset destroy wan_ac_black_ips >/dev/null 2>&1
ipset destroy common_ports >/dev/null 2>&1
fi
}
get_config()
{
enable=$(uci -q get openclash.config.enable)
rule_source=$(uci -q get openclash.config.rule_source)
enable_custom_clash_rules=$(uci -q get openclash.config.enable_custom_clash_rules)
da_password=$(uci -q get openclash.config.dashboard_password)
cn_port=$(uci -q get openclash.config.cn_port)
proxy_port=$(uci -q get openclash.config.proxy_port)
tproxy_port=$(uci -q get openclash.config.tproxy_port || echo 7895)
proxy_mode=$(uci -q get openclash.config.proxy_mode)
ipv6_enable=$(uci -q get openclash.config.ipv6_enable)
ipv6_dns=$(uci -q get openclash.config.ipv6_dns || echo 0)
ipv6_mode=$(uci -q get openclash.config.ipv6_mode || echo 0)
enable_v6_udp_proxy=$(uci -q get openclash.config.enable_v6_udp_proxy || echo 0)
http_port=$(uci -q get openclash.config.http_port)
socks_port=$(uci -q get openclash.config.socks_port)
enable_redirect_dns=$(uci -q get openclash.config.enable_redirect_dns || echo 1)
if [ "$(uci -q get openclash.config.fakeip_range)" == "0" ]; then
fakeip_range=$(ruby_read "$CONFIG_FILE" "['dns']['fake-ip-range']")
else
fakeip_range=$(uci -q get openclash.config.fakeip_range)
fi
[ -z "$fakeip_range" ] && fakeip_range="198.18.0.1/16"
lan_interface_name=$(uci -q get openclash.config.lan_interface_name || echo 0)
if [ "$lan_interface_name" = "0" ]; then
lan_ip=$(uci -q get network.lan.ipaddr 2>/dev/null | awk -F '/' '{print $1}' 2>/dev/null | tr -d '\n' || ip address show $(uci -q -p /tmp/state get network.lan.ifname || uci -q -p /tmp/state get network.lan.device) | grep -w "inet" 2>/dev/null |grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -1 | tr -d '\n' || ip addr show 2>/dev/null | grep -w 'inet' | grep 'global' | grep 'brd' | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -n 1 | tr -d '\n')
else
lan_ip=$(ip address show $lan_interface_name 2>/dev/null | grep -w "inet" 2>/dev/null | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -1 | tr -d '\n')
fi
wan_ip4s=$(/usr/share/openclash/openclash_get_network.lua "wanip" 2>/dev/null)
wan_ip6s=$(ifconfig | grep 'inet6 addr' | awk '{print $3}' 2>/dev/null)
log_level=$(uci -q get openclash.config.log_level)
intranet_allowed=$(uci -q get openclash.config.intranet_allowed)
enable_udp_proxy=$(uci -q get openclash.config.enable_udp_proxy || echo 1)
disable_udp_quic=$(uci -q get openclash.config.disable_udp_quic)
operation_mode=$(uci -q get openclash.config.operation_mode)
lan_ac_mode=$(uci -q get openclash.config.lan_ac_mode)
enable_rule_proxy=$(uci -q get openclash.config.enable_rule_proxy)
stack_type=$(uci -q get openclash.config.stack_type)
stack_type_v6=$(uci -q get openclash.config.stack_type_v6 || echo "system")
china_ip_route=$(uci -q get openclash.config.china_ip_route); [[ "$china_ip_route" != "0" && "$china_ip_route" != "1" && "$china_ip_route" != "2" ]] && china_ip_route=0
china_ip6_route=$(uci -q get openclash.config.china_ip6_route); [[ "$china_ip6_route" != "0" && "$china_ip6_route" != "1" && "$china_ip6_route" != "2" ]] && china_ip6_route=0
small_flash_memory=$(uci -q get openclash.config.small_flash_memory)
mixed_port=$(uci -q get openclash.config.mixed_port)
interface_name=$(uci -q get openclash.config.interface_name || echo 0)
common_ports=$(uci -q get openclash.config.common_ports)
dns_port=$(uci -q get openclash.config.dns_port)
store_fakeip=$(uci -q get openclash.config.store_fakeip || echo 0)
bypass_gateway_compatible=$(uci -q get openclash.config.bypass_gateway_compatible || echo 0)
core_version=$(uci -q get openclash.config.core_version || echo 0)
router_self_proxy=$(uci -q get openclash.config.router_self_proxy || echo 1)
enable_meta_sniffer=$(uci -q get openclash.config.enable_meta_sniffer || echo 0)
enable_meta_sniffer_custom=$(uci -q get openclash.config.enable_meta_sniffer_custom || echo 0)
geodata_loader=$(uci -q get openclash.config.geodata_loader || echo 0)
enable_geoip_dat=$(uci -q get openclash.config.enable_geoip_dat || echo 0)
enable_tcp_concurrent=$(uci -q get openclash.config.enable_tcp_concurrent || echo 0)
append_default_dns=$(uci -q get openclash.config.append_default_dns || echo 0)
enable_meta_sniffer_pure_ip=$(uci -q get openclash.config.enable_meta_sniffer_pure_ip || echo 0)
find_process_mode=$(uci -q get openclash.config.find_process_mode || echo 0)
upnp_lease_file=$(uci -q get upnpd.config.upnp_lease_file)
global_client_fingerprint=$(uci -q get openclash.config.global_client_fingerprint || echo 0)
enable_unified_delay=$(uci -q get openclash.config.enable_unified_delay || echo 0)
enable_respect_rules=$(uci -q get openclash.config.enable_respect_rules || echo 0)
intranet_allowed_wan_name=$(uci -q get openclash.config.intranet_allowed_wan_name || echo 0)
custom_fakeip_filter_mode=$(uci -q get openclash.config.custom_fakeip_filter_mode || echo "blacklist")
iptables_compat=$(iptables -m owner -h 2>/dev/null | grep "owner match options" || command -v fw4 || echo 0)
disable_quic_go_gso=$(uci -q get openclash.config.disable_quic_go_gso || echo 0)
[ -z "$dns_port" ] && dns_port=7874 && uci -q set openclash.config.dns_port=7874
uci -q commit openclash
}
start_service()
{
enable=$(uci -q get openclash.config.enable)
[ "$enable" != "1" ] && LOG_OUT "Warning: OpenClash Now Disabled, Need Start From Luci Page, Exit..." && SLOG_CLEAN && exit 0
LOG_OUT "OpenClash Start Running..."
config_choose
do_run_mode
LOG_OUT "Step 1: Get The Configuration..."
get_config
LOG_OUT "Step 2: Check The Components..."
#检查文件是否存在
do_run_file "$RAW_CONFIG_FILE" "$BACKUP_FILE"
if ! $quick_start; then
LOG_OUT "Step 3: Modify The Config File..."
config_check
/usr/share/openclash/yml_change.sh 2>/dev/null "$en_mode" "$da_password" "$cn_port" "$proxy_port" "$TMP_CONFIG_FILE" "$ipv6_enable" "$http_port" "$socks_port" "$log_level" "$proxy_mode" "$en_mode_tun" "$stack_type" "$dns_port" "$mixed_port" "$tproxy_port" "$ipv6_dns" "$store_fakeip" "$enable_meta_sniffer" "$enable_geoip_dat" "$geodata_loader" "$enable_meta_sniffer_custom" "$interface_name" "$enable_tcp_concurrent" "$core_type" "$append_default_dns" "$enable_meta_sniffer_pure_ip" "$find_process_mode" "$fakeip_range" "$global_client_fingerprint" "$ipv6_mode" "$stack_type_v6" "$enable_unified_delay" "$enable_respect_rules" "$custom_fakeip_filter_mode" "$iptables_compat" "$disable_quic_go_gso"
/usr/share/openclash/yml_rules_change.sh 2>/dev/null "$rule_source" "$enable_custom_clash_rules" "$TMP_CONFIG_FILE" "$enable_rule_proxy" "$CONFIG_NAME" "$router_self_proxy" "$lan_ip" "$enable_redirect_dns" "$en_mode"
#Custom overwrite
if [ -f "/etc/openclash/custom/openclash_custom_overwrite.sh" ]; then
chmod +x /etc/openclash/custom/openclash_custom_overwrite.sh >/dev/null 2>&1
/etc/openclash/custom/openclash_custom_overwrite.sh 2>/dev/null "$TMP_CONFIG_FILE"
fi
else
LOG_OUT "Step 3: Quick Start Mode, Skip Modify The Config File..."
fi
LOG_OUT "Step 4: Start Running The Clash Core..."
start_run_core
LOG_OUT "Step 5: Set Dnsmasq..."
change_dns "$enable_redirect_dns"
LOG_OUT "Step 6: Set Firewall Rules..."
set_firewall
check_core_status &
LOG_OUT "Step 7: Add Cron Rules, Start Daemons..."
add_cron
if [ -z "$(uci -q get dhcp.lan.dhcpv6)" ] || [ "$(uci -q get dhcp.lan.dhcpv6)" == "disabled" ]; then
LOG_OUT "OpenClash Start Successful!"
elif [ "$ipv6_enable" -eq 0 ]; then
LOG_OUT "Warning: OpenClash Start Successful, Please Note That Network May Abnormal With IPv6's DHCP Server"
else
LOG_OUT "OpenClash Start Successful!"
fi
echo "OpenClash Already Start!"
write_run_quick
SLOG_CLEAN
rm -rf /tmp/yaml_*
}
stop_service()
{
enable=$(uci -q get openclash.config.enable)
LOG_OUT "OpenClash Stoping..."
LOG_OUT "Step 1: Backup The Current Groups State..."
/usr/share/openclash/openclash_history_get.sh 2>/dev/null
LOG_OUT "Step 2: Delete OpenClash Firewall Rules..."
revert_firewall
LOG_OUT "Step 3: Close The OpenClash Daemons..."
watchdog_pids=$(unify_ps_pids "openclash_watchdog.sh")
for watchdog_pid in $watchdog_pids; do
kill -9 "$watchdog_pid" >/dev/null 2>&1
done >/dev/null 2>&1
streaming_unlock_pids=$(unify_ps_pids "openclash_streaming_unlock.lua")
for streaming_unlock_pid in $streaming_unlock_pids; do
kill -9 "$streaming_unlock_pid" >/dev/null 2>&1
done >/dev/null 2>&1
LOG_OUT "Step 4: Close The Clash Core Process..."
if [ "$enable" != "1" ]; then
kill_clash
fi
LOG_OUT "Step 5: Restart Dnsmasq..."
revert_dnsmasq
LOG_OUT "Step 6: Delete OpenClash Residue File..."
if [ "$enable" != "1" ]; then
rm -rf /tmp/clash_last_version >/dev/null 2>&1
rm -rf /tmp/Proxy_Group >/dev/null 2>&1
rm -rf /tmp/rules_name >/dev/null 2>&1
rm -rf /tmp/rule_providers_name >/dev/null 2>&1
rm -rf /tmp/openclash_last_version >/dev/null 2>&1
rm -rf /tmp/openclash_config.tmp >/dev/null 2>&1
rm -rf /tmp/openclash.change >/dev/null 2>&1
rm -rf /tmp/openclash_debug.log >/dev/null 2>&1
rm -rf /tmp/openclash_edit_file_name >/dev/null 2>&1
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf >/dev/null 2>&1
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf >/dev/null 2>&1
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_custom_domain.conf >/dev/null 2>&1
LOG_OUT "OpenClash Already Stop!"
else
LOG_OUT "OpenClash Already Stop!"
fi
del_cron
rm -rf /tmp/yaml_* >/dev/null 2>&1
rm -rf $START_LOG >/dev/null 2>&1
echo "OpenClash Already Stop!"
}
revert_dnsmasq()
{
get_config
redirect_dns=$(uci -q get openclash.config.redirect_dns)
dnsmasq_server=$(uci -q get openclash.config.dnsmasq_server)
dnsmasq_noresolv=$(uci -q get openclash.config.dnsmasq_noresolv)
dnsmasq_resolvfile=$(uci -q get openclash.config.dnsmasq_resolvfile)
cachesize_dns=$(uci -q get openclash.config.cachesize_dns)
dnsmasq_cachesize=$(uci -q get openclash.config.dnsmasq_cachesize)
filter_aaaa_dns=$(uci -q get openclash.config.filter_aaaa_dns)
dnsmasq_filter_aaaa=$(uci -q get openclash.config.dnsmasq_filter_aaaa)
default_resolvfile=$(uci -q get openclash.config.default_resolvfile)
revert_dns "$redirect_dns" "$enable" "$default_resolvfile" "$dnsmasq_noresolv" "$dnsmasq_resolvfile" "$cachesize_dns" "$dnsmasq_cachesize" "$filter_aaaa_dns" "$dnsmasq_filter_aaaa" "$dnsmasq_server"
/etc/init.d/dnsmasq restart >/dev/null 2>&1
}
restart()
{
echo "OpenClash Restart..."
LOG_OUT "OpenClash Restart..."
#快速启动判断
check_run_quick
stop
start
}
start_watchdog()
{
procd_open_instance "openclash-watchdog"
procd_set_param command "/usr/share/openclash/openclash_watchdog.sh"
procd_close_instance
}
reload_service()
{
enable=$(uci -q get openclash.config.enable)
if pidof clash >/dev/null && [ "$enable" == "1" ] && [ "$1" == "firewall" ]; then
LOG_OUT "Reload OpenClash Firewall Rules..."
revert_firewall 2>/dev/null
do_run_mode 2>/dev/null
get_config 2>/dev/null
set_firewall 2>/dev/null
check_core_status & 2>/dev/null
SLOG_CLEAN
fi
if pidof clash >/dev/null && [ "$enable" == "1" ] && [ "$1" == "revert" ]; then
revert_firewall 2>/dev/null
revert_dnsmasq 2>/dev/null
SLOG_CLEAN
fi
if pidof clash >/dev/null && [ "$enable" == "1" ] && [ "$1" == "restore" ]; then
do_run_mode 2>/dev/null
get_config 2>/dev/null
change_dns "$enable_redirect_dns"
set_firewall 2>/dev/null
check_core_status & 2>/dev/null
SLOG_CLEAN
fi
if [ "$enable" == "1" ] && [ "$1" == "core" ]; then
check_run_quick 2>/dev/null
do_run_mode 2>/dev/null
get_config 2>/dev/null
start_run_core 2>/dev/null
check_core_status 2>/dev/null
write_run_quick 2>/dev/null
SLOG_CLEAN
fi
}
boot()
{
delay_start=$(uci -q get openclash.config.delay_start || echo 0)
enable=$(uci -q get openclash.config.enable)
if [ "$delay_start" -gt 0 ] && [ "$enable" == "1" ]; then
LOG_OUT "Enable Delay Start, OpenClash Will Start After【$delay_start】Seconds..."
sleep "$delay_start"
fi
restart
}