small-package/luci-app-openclash/root/etc/init.d/openclash

2524 lines
126 KiB
Bash

#!/bin/sh /etc/rc.common
# Copyright (c) 2019 vernesong
START=99
STOP=15
. $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)"
}
LOGTIME=$(echo $(date "+%Y-%m-%d %H:%M:%S"))
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"
LOCK_FILE=/tmp/lock/openclash.lock
PROXY_FWMARK="0x162"
PROXY_ROUTE_TABLE="0x162"
FW4="$(command -v fw4)"
set_lock() {
exec 888>"$LOCK_FILE" 2>/dev/null
flock -x 888 2>/dev/null
}
del_lock() {
flock -u 888 2>/dev/null
rm -rf "$LOCK_FILE"
}
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
nohup /usr/share/openclash/openclash_watchdog.sh &
}
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() {
if [ "$1" -eq 1 ]; then
uci -q del openclash.config.dnsmasq_server
config_load "dhcp"
config_list_foreach "$(uci 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 openclash.config.redirect_dns=1
else
uci -q set openclash.config.redirect_dns=0
fi
if [ "$2" -eq 1 ]; then
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.cachesize_dns=0
fi
if [ "$ipv6_dns" == 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
}
revert_dns() {
[ "$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" ]; then
uci -q set dhcp.@dnsmasq[0].resolvfile="$5"
elif [ -n "$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
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
else
rm -rf /tmp/resolv.conf.auto
touch /tmp/resolv.conf.auto 2>/dev/null
cat >> "/tmp/resolv.conf.auto" <<-EOF
# Interface lan
nameserver 114.114.114.114
nameserver 119.29.29.29
EOF
uci -q set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.auto
fi
fi
}
[ "$6" -eq 1 ] && {
uci -q set dhcp.@dnsmasq[0].cachesize="$7"
}
[ "$8" -eq 1 ] && {
uci -q set dhcp.@dnsmasq[0].filter_aaaa="$9"
}
[ "$1" -eq 1 ] && [ "$2" -eq 0 ] && {
uci -q set openclash.config.redirect_dns=0
}
[ "$6" -eq 1 ] && [ "$2" -eq 0 ] && {
uci -q set openclash.config.cachesize_dns=0
}
[ "$8" -eq 1 ] && [ "$2" -eq 0 ] && {
uci -q set openclash.config.filter_aaaa_dns=0
}
uci -q commit dhcp
uci -q commit openclash
rm -rf /tmp/dnsmasq.d/dnsmasq_openclash.conf >/dev/null 2>&1
rm -rf /tmp/dnsmasq.d/dnsmasq_openclash_custom_domain.conf >/dev/null 2>&1
}
kill_clash()
{
clash_pids=$(pidof clash |sed 's/$//g')
for clash_pid in $clash_pids; do
kill -9 "$clash_pid" 2>/dev/null
done >/dev/null 2>&1
sleep 1
}
start_fail()
{
kill_clash
stop
del_lock
exit 0
}
#检查集文件防止启动失败
yml_provider_check()
{
provider_path_line=$(ruby_read "$1" ".key?('$2')")
local provider_path_check
if "$provider_path_line"; then
while :;
do
provider_path_check=$(ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
Value = YAML.load_file('$1');
Value['$2'].values.each{|x,v|
if not x['path'].empty? then
if x['path'].split('/')[0] == '.' then
v = '/etc/openclash/'+x['path'].split('./')[1]
else
v = x['path']
end
end;
if File::exist?(v) then
if not YAML.load_file(v).key?('$3') then
puts false
break
end
else
puts false
break
end
}
" 2>/dev/null)
if [ "$provider_path_check" == "false" ] && [ -n "$(pidof clash)" ]; then
sleep 2
else
break
fi
done
fi
if [ -z "$(pidof clash)" ] && [ "$provider_path_check" == "false" ]; then
if [ "$2" = "proxy-providers" ]; then
LOG_OUT "Error: Failed To Download Proxy-providers, Please Check The Log Page For Detailed error information!"
else
LOG_OUT "Error: Failed To Download Rule-providers, Please Check The Log Page For Detailed error information!"
fi
LOG_ALERT
start_fail
fi
}
#获取订阅配置
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
RAW_CONFIG_FILE="/etc/openclash/config/config.yaml"
else
RAW_CONFIG_FILE="/etc/openclash/config/$name.yaml"
fi
uci -q set openclash.config.config_path="$RAW_CONFIG_FILE"
uci -q commit openclash
subscribe_enable=1
}
#配置文件选择
config_choose()
{
if [ -z "$RAW_CONFIG_FILE" ] || [ ! -f "$RAW_CONFIG_FILE" ]; then
CONFIG_NAME=$(ls -lt /etc/openclash/config/ | grep -E '.yaml|.yml' | head -n 1 |awk '{print $9}')
if [ -n "$CONFIG_NAME" ]; then
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"
fi
fi 2>/dev/null
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"
if [ ! -f "$RAW_CONFIG_FILE" ]; then
config_load "openclash"
config_foreach sub_info_get "config_subscribe"
if [ "$subscribe_enable" = "1" ]; then
LOG_OUT "Config File Does Not Exist, You Have Set Subscription Information, Ready To Download..."
nohup /usr/share/openclash/openclash.sh &
del_lock
exit 0
else
LOG_OUT "Error: Config Not Found"
sleep 3
del_lock
exit 0
fi
fi
}
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
puts '${LOGTIME} 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!"
sleep 3
start_fail
elif [ ! -f "$TMP_CONFIG_FILE" ] || [ ! -s "$TMP_CONFIG_FILE" ]; then
LOG_OUT "Error: Config File Format Validation Failed..."
sleep 3
start_fail
fi
}
yml_other_rules_get()
{
local section="$1"
local enabled config
config_get_bool "enabled" "$section" "enabled" "1"
config_get "config" "$section" "config" ""
if [ "$enabled" = "0" ] || [ "$config" != "$2" ]; then
return
fi
if [ -n "$rule_name" ]; then
return
fi
config_get "rule_name" "$section" "rule_name" ""
}
check_run_quick()
{
quick_start=true
check_file="$(echo $RAW_CONFIG_FILE | tr " " "?") /etc/openclash/custom/openclash_custom_domain_dns.list /etc/openclash/custom/openclash_custom_domain_dns_policy.list /etc/openclash/custom/openclash_custom_fake_filter.list /etc/openclash/custom/openclash_custom_fallback_filter.yaml /etc/openclash/custom/openclash_custom_hosts.list /etc/openclash/custom/openclash_custom_rules.list /etc/openclash/custom/openclash_custom_rules_2.list $dev_core_path $tun_core_path $meta_core_path $ipdb_path $geosite_path $geoip_path $chnr_path $chnr6_path /usr/share/openclash/res/ConnersHua.yaml /usr/share/openclash/res/ConnersHua_return.yaml /usr/share/openclash/res/lhie1.yaml /etc/openclash/custom/openclash_force_sniffing_domain.yaml /etc/openclash/custom/openclash_sniffing_domain_filter.yaml /etc/openclash/custom/openclash_sniffing_port_filter.yaml /etc/openclash/custom/openclash_custom_localnetwork_ipv4.list /etc/openclash/custom/openclash_custom_localnetwork_ipv6.list /etc/openclash/custom/openclash_custom_chnroute_pass.list /etc/openclash/custom/openclash_custom_chnroute6_pass.list"
if [ ! -f "$CONFIG_FILE" ] || [ ! -f "/tmp/openclash_config.tmp" ] || [ ! -f "/tmp/openclash.change" ]; 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()
{
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
}
custom_rule_provider()
{
local section="$1"
local enabled config
config_get "config" "$section" "config" ""
config_get_bool "enabled" "$section" "enabled" "1"
if [ "$enabled" = "0" ]; then
return
fi
if [ "$config" = "all" ] || [ "$config" = "$CONFIG_NAME" ]; then
config_set_custom_rule_provider=1
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)" ] && 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
dev_core_path="/etc/openclash/core/clash"
tun_core_path="/etc/openclash/core/clash_tun"
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
dev_core_path="/tmp/etc/openclash/core/clash"
tun_core_path="/tmp/etc/openclash/core/clash_tun"
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
if [ "$enable_meta_core" != "1" ]; then
if [ -n "$en_mode_tun" ]; then
ln -s "$tun_core_path" /etc/openclash/clash 2>/dev/null
core_type="TUN"
core_start_log="Tip: Detected The Exclusive Function of The TUN Core, Use TUN Core to Start..."
fi
if [ "$rule_source" != "0" ]; then
config_load "openclash"
config_foreach yml_other_rules_get "other_rules" "$CONFIG_NAME"
fi
config_load "openclash"
config_set_custom_rule_provider=0
for i in "rule_provider_config" "rule_provider_config" "rule_providers" "game_config"; do
config_foreach custom_rule_provider "$i"
if [ "$config_set_custom_rule_provider" -eq 1 ]; then
break
fi
done 2>/dev/null
if [ "$proxy_mode" = "script" ] || [ "$config_set_custom_rule_provider" -eq 1 ] || [ "$rule_name" = "ConnersHua" ] || [ "$rule_name" = "lhie1" ] || [ -n "$(ruby_read "$RAW_CONFIG_FILE" "['rules'].grep(/(^RULE-SET,|^SCRIPT,)/)")" ] || [ -n "$(ruby_read "/etc/openclash/custom/openclash_custom_rules.list" "['rules'].grep(/(^RULE-SET,|^SCRIPT,)/)")" ] || [ -n "$(ruby_read "/etc/openclash/custom/openclash_custom_rules_2.list" "['rules'].grep(/(^RULE-SET,|^SCRIPT,)/)")" ]; then
if [ -z "$en_mode_tun" ]; then
ln -s "$tun_core_path" /etc/openclash/clash 2>/dev/null
core_type="TUN"
core_start_log="Tip: Detected The Exclusive Function of The TUN Core, Use TUN Core to Start..."
fi
fi
else
ln -s "$meta_core_path" /etc/openclash/clash 2>/dev/null
core_type="Meta"
core_start_log="Tip: Detected The Exclusive Function of The Meta Core, Use Meta Core to Start..."
fi
if [ ! -f "/etc/openclash/clash" ] && [ -f "$dev_core_path" ] && [ -z "$core_type" ]; then
ln -s "$dev_core_path" /etc/openclash/clash 2>/dev/null
core_start_log="Tip: No Special Configuration Detected, Use Dev Core to Start..."
fi
if [ ! -f "/etc/openclash/clash" ] && [ -f "$tun_core_path" ] && [ -z "$core_type" ]; then
ln -s "$tun_core_path" /etc/openclash/clash 2>/dev/null
core_type="TUN"
core_start_log="Tip: Detected that the Dev Core is not Installed, Use TUN Core to Start..."
fi
if [ ! -f "/etc/openclash/clash" ] && [ -f "$meta_core_path" ] && [ -z "$core_type" ]; then
ln -s "$meta_core_path" /etc/openclash/clash 2>/dev/null
core_type="Meta"
core_start_log="Tip: Detected that the Dev Core is not Installed, Use Meta Core to Start..."
fi
[ ! -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 [ "$core_type" == "TUN" ] && [ ! -f "$tun_core_path" ]; then
start_fail
elif [ "$core_type" == "Meta" ] && [ ! -f "$meta_core_path" ]; then
start_fail
elif [ -z "$core_type" ] && [ ! -f "$dev_core_path" ]; then
start_fail
else
del_lock
restart
exit 0
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" = "1" ] || [ "$china_ip6_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
if [ ! -f "$chnr_path" ] || [ ! -f "$chnr6_path" ]; then
LOG_OUT "Tip: Detected that the Chnroute Cidr List 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 "$tun_core_path" ] && chmod 4755 "$tun_core_path" 2>/dev/null
[ ! -x "$dev_core_path" ] && chmod 4755 "$dev_core_path" 2>/dev/null
[ ! -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 [ -z "$_koolshare" ]; then
if ! capsh --is-uid=0 >/dev/null || ! capsh --has-ambient >/dev/null; then
LOG_OUT "Error: Could Not Load The Capsh Library, Please Verify The Capsh Shell Library Work Well"
LOG_OUT "Tip: You Could Download And Re-Install The libcap & libcap-bin Library From The Address Give"
echo "" >> $LOG_FILE
echo "---------- https://mirrors.cloud.tencent.com/lede/snapshots/packages/ ----------" >> $LOG_FILE
echo "" >> $LOG_FILE
sleep 3
start_fail
fi
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()
{
LOG_OUT "$core_start_log"
ulimit -SHn 65535 2>/dev/null
ulimit -v 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
config_reload=$(uci -q get openclash.config.config_reload)
if [ -n "$(pidof clash)" ] && [ "$core_type" != "TUN" ] && [ "$core_type" != "Meta" ] && [ "$config_reload" != "0" ]; then
curl -s --connect-timeout 5 -m 5 -H 'Content-Type: application/json' -H "Authorization: Bearer ${da_password}" -XPUT http://"$lan_ip":"$cn_port"/configs -d "{\"path\": \"$CONFIG_FILE\"}" 2>/dev/null
else
kill_clash
if [ -z "$_koolshare" ]; then
#防止赋权失败
touch "/tmp/openclash.log" 2>/dev/null
chmod o+w /etc/openclash/proxy_provider/* 2>/dev/null
chmod o+w /etc/openclash/rule_provider/* 2>/dev/null
chmod o+w /etc/openclash/history/* 2>/dev/null
chmod o+w /etc/openclash/cache.db 2>/dev/null
chmod o+w /tmp/openclash.log 2>/dev/null
chown nobody:nogroup /etc/openclash/core/* 2>/dev/null
#使用nobody启动内核方便代理路由自身流量
capabilties="cap_sys_resource,cap_dac_override,cap_net_raw,cap_net_bind_service,cap_net_admin,cap_sys_ptrace"
capsh --caps="${capabilties}+eip" -- -c "capsh --user=nobody --addamb='${capabilties}' -- -c 'nohup $CLASH -d $CLASH_CONFIG -f \"$CONFIG_FILE\" >> $LOG_FILE 2>&1 &'" >> $LOG_FILE 2>&1
else
nohup $CLASH -d $CLASH_CONFIG -f "$CONFIG_FILE" >> $LOG_FILE 2>&1 &
fi
fi
uci -q set openclash.config.config_reload=1
uci -q commit openclash
}
check_core_status()
{
check_time=1
while ( [ "$check_time" -le 3 ] && [ -n "$(pidof clash)" ] )
do
sleep 1
let check_time++
done
if [ -z "$(pidof clash)" ]; then
LOG_ALERT
fi
}
#不修改配置文件启动
raw_config_start()
{
cp "$RAW_CONFIG_FILE" "$CONFIG_FILE"
dns_port=$(ruby_read "$CONFIG_FILE" "['dns']['listen'].split(':')[1]")
en_mode=$(ruby_read "$CONFIG_FILE" "['dns']['enhanced-mode']")
proxy_port=$(ruby_read "$CONFIG_FILE" "['redir-port']")
if [ -z "$dns_port" ] || [ -z "$en_mode" ] || [ -z "$proxy_port" ]; then
if [ -z "$dns_port" ]; then
LOG_OUT "Error: Get DNS 'listen' Option Error, OpenClash Can Not Start With Raw Config File"
sleep 2
fi
if [ -z "$en_mode" ]; then
LOG_OUT "Error: Get DNS 'enhanced-mode' Option Error, OpenClash Can Not Start With Raw Config File"
sleep 2
fi
if [ -z "$proxy_port" ]; then
LOG_OUT "Error: Get General 'redir-port' Option Error, OpenClash Can Not Start With Raw Config File"
sleep 2
fi
start_fail
fi
start_run_core
check_core_status
if ! pidof clash >/dev/null; then
LOG_OUT "Error: OpenClash Can Not Start, Please Check The Error Info And Try Again!"
sleep 3
start_fail
fi
if [ "$en_mode" = "redir-host" ]; then
case $en_mode_tun in
"1")
uci -q set openclash.config.en_mode=redir-host-tun
;;
"2")
uci -q set openclash.config.en_mode=redir-host-mix
;;
*)
uci -q set openclash.config.en_mode=redir-host
esac
elif [ "$en_mode" = "fake-ip" ]; then
case $en_mode_tun in
"1")
uci -q set openclash.config.en_mode=fake-ip-tun
;;
"2")
uci -q set openclash.config.en_mode=fake-ip-mix
;;
*)
uci -q set openclash.config.en_mode=fake-ip
esac
fi
dase=$(ruby_read "$CONFIG_FILE" "['secret']")
uci -q set openclash.config.dashboard_password="$dase"
cn_port=$(ruby_read "$CONFIG_FILE" "['external-controller'].split(':')[1]")
uci -q set openclash.config.cn_port="$cn_port"
uci -q set openclash.config.proxy_port="$proxy_port"
uci -q set openclash.config.restricted_mode=1
uci commit openclash
}
try_restore_start()
{
if [ -z "$(pidof clash)" ]; then
if [ "$rule_source" = 0 ] && [ "$enable_custom_clash_rules" = 0 ]; then
LOG_OUT "Error: OpenClash Can Not Start, Try Use Raw Config Restart Again..."
raw_config_start
else
LOG_OUT "Error: OpenClash Can Not Start, Try Use Backup Rules Start Again..."
ruby -ryaml -rYAML -I "/usr/share/openclash" -E UTF-8 -e "
begin
Value = YAML.load_file('$RAW_CONFIG_FILE');
Value_1 = YAML.load_file('$CONFIG_FILE');
if Value.has_key?('rule-providers') then
Value_1['rule-providers'] = Value.select {|x| 'rule-providers' == x}['rule-providers'];
end;
if Value.has_key?('script') then
Value_1['script'] = Value.select {|x| 'script' == x}['script'];
end;
if Value.has_key?('rules') then
Value_1['rules'] = Value.select {|x| 'rules' == x}['rules'];
end;
File.open('$CONFIG_FILE','w') {|f| YAML.dump(Value_1, f)};
rescue Exception => e
puts '${LOGTIME} Error: Restore Backup Rules Failed,【' + e.message + '】';
end
" 2>/dev/null >> $LOG_FILE
start_run_core
check_core_status
if ! pidof clash >/dev/null; then
LOG_OUT "Error: OpenClash Can Not Start, Try Use Raw Config Restart Again..."
raw_config_start
fi
fi
fi
}
#防火墙设置部分
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
}
firewall_rule_exclude()
{
local section="$1"
local name src src_port dest dest_port proto target enabled family
config_get "name" "$section" "name" ""
config_get "src" "$section" "src" ""
config_get "src_port" "$section" "src_port" ""
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" ""
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 "$FW4" ]; then
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
else
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } tcp sport "$i" counter return >/dev/null 2>&1
fi
nft insert rule inet fw4 openclash_mangle_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
nft insert rule inet fw4 openclash_mangle_v6 position 0 ip6 saddr { "$dest_ip" } udp sport "$i" counter return >/dev/null 2>&1
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 ] && [ -n "$(ip6tables -t mangle -L 2>&1 | grep -o 'Chain')" ]; 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
else
ip6tables -t mangle -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
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 src_dport dest_port dest_ip proto enabled
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
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
nft insert rule inet fw4 openclash_output position 0 ip saddr { "$dest_ip" } tcp dport "$src_dport" 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
nft insert rule inet fw4 openclash_mangle_output position 0 ip saddr { "$dest_ip" } udp dport "$src_dport" 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
nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp dport "$src_dport" 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
nft insert rule inet fw4 openclash_mangle_output position 0 ip saddr { "$dest_ip" } tcp dport "$src_dport" 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
nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } tcp dport "$src_dport" 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
nft insert rule inet fw4 openclash_mangle_output position 0 ip saddr { "$dest_ip" } udp dport "$src_dport" 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
nft insert rule inet fw4 openclash_mangle position 0 ip saddr { "$dest_ip" } udp dport "$src_dport" counter return >/dev/null 2>&1
fi
fi
fi
if [ "$ipv6_enable" -eq 1 ]; then
if $e_tcp ; then
if [ -n "$dest_ip" ]; then
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_v6 position 0 ip6 saddr { "$dest_ip" } tcp dport "$src_dport" counter return >/dev/null 2>&1
fi
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
nft insert rule inet fw4 openclash_mangle_output_v6 position 0 ip6 saddr { "$dest_ip" } tcp dport "$src_dport" counter return >/dev/null 2>&1
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_v6 position 0 ip6 saddr { "$dest_ip" } udp dport "$src_dport" counter return >/dev/null 2>&1
fi
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
nft insert rule inet fw4 openclash_mangle_output_v6 position 0 ip6 saddr { "$dest_ip" } udp dport "$src_dport" counter return >/dev/null 2>&1
fi
fi
else
dest_port=$(echo $dest_port |sed "s/-/:/g" 2>/dev/null)
src_dport=$(echo $src_dport |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
iptables -t nat -I openclash_output "$dest_ip" -p tcp --dport "$src_dport" -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
iptables -t mangle -I openclash_output "$dest_ip" -p udp --dport "$src_dport" -j RETURN >/dev/null 2>&1
if [ -n "$dest_ip" ]; then
iptables -t mangle -I openclash "$dest_ip" -p udp --dport "$src_dport" -j RETURN >/dev/null 2>&1
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
iptables -t mangle -I openclash_output -p tcp "$dest_ip" --dport "$src_dport" -j RETURN >/dev/null 2>&1
if [ -n "$dest_ip" ]; then
iptables -t mangle -I openclash -p tcp "$dest_ip" --dport "$src_dport" -j RETURN >/dev/null 2>&1
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
iptables -t mangle -I openclash_output -p udp "$dest_ip" --dport "$src_dport" -j RETURN >/dev/null 2>&1
if [ -n "$dest_ip" ]; then
iptables -t mangle -I openclash -p udp "$dest_ip" --dport "$src_dport" -j RETURN >/dev/null 2>&1
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
ip6tables -t mangle -I openclash -p tcp "$dest_ip" --dport "$src_dport" -j RETURN >/dev/null 2>&1
ip6tables -t mangle -I openclash -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
fi
ip6tables -t mangle -I openclash_output -p tcp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
ip6tables -t mangle -I openclash_output -p tcp "$dest_ip" --dport "$src_dport" -j RETURN >/dev/null 2>&1
fi
if $e_udp ; then
if [ -n "$dest_ip" ]; then
ip6tables -t mangle -I openclash -p udp "$dest_ip" --dport "$src_dport" -j RETURN >/dev/null 2>&1
ip6tables -t mangle -I openclash -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
fi
ip6tables -t mangle -I openclash_output -p udp "$dest_ip" --sport "$dest_port" -j RETURN >/dev/null 2>&1
ip6tables -t mangle -I openclash_output -p udp "$dest_ip" --dport "$src_dport" -j RETURN >/dev/null 2>&1
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
local settype nftflag
if dnsmasq --version | grep -q 'Compile time options:.* nftset'; then
settype="nftset"
nftflag="inet#fw4#"
else
settype="ipset"
fi
if [ -n "$FW4" ]; then
if [ "$china_ip_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
nft 'flush set inet fw4 china_ip_route'
nft -f '/etc/openclash/china_ip_route.ipset' 2>/dev/null
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' 2>/dev/null
done
mkdir -p /tmp/dnsmasq.d 2>/dev/null
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 '!/^$/&&!/^#/&&/(^([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(" %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 '!/^$/&&!/^#/&&/(^([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(" %s,'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>/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
}
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 >>/tmp/dnsmasq.d/dnsmasq_openclash_chnroute_pass.conf 2>/dev/null
nft 'flush set inet fw4 china_ip_route_pass' 2>/dev/null
nft -f '/tmp/openclash_china_ip_route_pass.list' 2>/dev/null
rm -rf /tmp/openclash_china_ip_route_pass.list 2>/dev/null
fi
if [ "$enable_redirect_dns" -eq 1 ] && [ -z "$(nft list chain inet fw4 dstnat |grep 'OpenClash DNS Hijack')"]; then
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 "$dns_port")
fi
nft insert rule inet fw4 dstnat position 0 tcp dport 53 redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\" 2>/dev/null
nft insert rule inet fw4 dstnat position 0 udp dport 53 redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\" 2>/dev/null
fi
#lan_google_dns_ac
if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ]; then
nft 'add set inet fw4 lan_block_google_dns_ips { type ipv4_addr; flags interval; auto-merge; }' 2>/dev/null
nft 'add set inet fw4 lan_block_google_dns_ipv6s { type ipv6_addr; flags interval; auto-merge; }' 2>/dev/null
config_load "openclash"
config_list_foreach "config" "lan_block_google_dns_ips" nft_ac_add "lan_block_google_dns_ips" "lan_block_google_dns_ipv6s"
fi
if [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
nft 'add set inet fw4 lan_block_google_dns_macs { type ether_addr; }' 2>/dev/null
config_load "openclash"
config_list_foreach "config" "lan_block_google_dns_macs" nft_ac_add "lan_block_google_dns_macs"
fi
#lan_ac
if [ "$operation_mode" = "redir-host" ] && [ "$en_mode" = "redir-host" ]; then
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; }' 2>/dev/null
nft 'add set inet fw4 lan_ac_black_ipv6s { type ipv6_addr; flags interval; auto-merge; }' 2>/dev/null
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; }' 2>/dev/null
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; }' 2>/dev/null
nft 'add set inet fw4 lan_ac_white_ipv6s { type ipv6_addr; flags interval; auto-merge; }' 2>/dev/null
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; }' 2>/dev/null
config_load "openclash"
config_list_foreach "config" "lan_ac_white_macs" nft_ac_add "lan_ac_white_macs"
fi
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; }' 2>/dev/null
nft 'add set inet fw4 wan_ac_black_ipv6s { type ipv6_addr; flags interval; auto-merge; }' 2>/dev/null
config_load "openclash"
config_list_foreach "config" "wan_ac_black_ips" nft_ac_add "wan_ac_black_ips" "wan_ac_black_ipv6s"
fi
#lan port ac
if [ -n "$(uci -q get openclash.config.lan_ac_black_ports)" ]; then
nft 'add set inet fw4 lan_ac_black_ports { type inet_service; }' 2>/dev/null
config_load "openclash"
config_list_foreach "config" "lan_ac_black_ports" nft_ac_add "lan_ac_black_ports"
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" } 2>/dev/null
done 2>/dev/null
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 "$lan_ip_cidrs" ]; then
for lan_ip_cidr in $lan_ip_cidrs; do
nft add element inet fw4 localnetwork { "$lan_ip_cidr" } 2>/dev/null
done
fi
if [ -n "$wan_ip4s" ]; then
for wan_ip4 in $wan_ip4s; do
nft add element inet fw4 localnetwork { "$wan_ip4" } 2>/dev/null
done
fi
#common ports
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"
nft 'add set inet fw4 common_ports { type inet_service; }'
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' 2>/dev/null
nft 'add chain inet fw4 openclash_post' 2>/dev/null
nft 'flush chain inet fw4 openclash_post' 2>/dev/null
nft add rule inet fw4 openclash_post meta mark "$PROXY_FWMARK" counter accept 2>/dev/null
nft 'add rule inet fw4 openclash_post ip daddr @localnetwork counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_post meta nfproto {ipv4} fib saddr type != { local } meta skuid != 65534 counter masquerade' 2>/dev/null
nft add rule inet fw4 srcnat meta nfproto {ipv4} counter jump openclash_post comment \"OpenClash Bypass Gateway Compatible\" 2>/dev/null
fi
#intranet allowed
if [ "$intranet_allowed" -eq 1 ]; then
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/) {print $(i+1)}}}' 2>/dev/null |sed 's/"//g')
if [ -n "$wan_ints" ]; then
nft 'add chain inet fw4 openclash_wan_input' 2>/dev/null
nft 'flush chain inet fw4 openclash_wan_input' 2>/dev/null
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 2>/dev/null
done
nft add rule inet fw4 openclash_wan_input udp dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject
nft add rule inet fw4 openclash_wan_input tcp dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject
fi
fi
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
#tcp
nft 'add chain inet fw4 openclash' 2>/dev/null
nft 'flush chain inet fw4 openclash' 2>/dev/null
nft 'add rule inet fw4 openclash ip daddr @localnetwork counter return' 2>/dev/null
if [ -z "$en_mode_tun" ] && [ "$en_mode" = "fake-ip" ]; then
nft add rule inet fw4 openclash ip protocol tcp ip daddr {198.18.0.0/16} counter redirect to "$proxy_port" 2>/dev/null
fi
nft 'add rule inet fw4 openclash ip saddr @localnetwork tcp sport @lan_ac_black_ports counter return' 2>/dev/null
nft 'add rule inet fw4 openclash ip daddr @wan_ac_black_ips counter return' 2>/dev/null
nft 'add rule inet fw4 openclash ip saddr @lan_ac_black_ips counter return' 2>/dev/null
nft 'add rule inet fw4 openclash ether saddr @lan_ac_black_macs counter return' 2>/dev/null
nft 'add rule inet fw4 openclash ether saddr != @lan_ac_white_macs counter return' 2>/dev/null
nft 'add rule inet fw4 openclash ip saddr != @lan_ac_white_ips counter return' 2>/dev/null
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash tcp dport != @common_ports counter return' 2>/dev/null
if [ "$china_ip_route" = "1" ]; then
nft 'add rule inet fw4 openclash ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return' 2>/dev/null
fi
fi
nft add rule inet fw4 openclash ip protocol tcp counter redirect to "$proxy_port" 2>/dev/null
nft 'add rule inet fw4 dstnat ip protocol tcp counter jump openclash' 2>/dev/null
if [ -z "$en_mode_tun" ]; then
#Google dns
nft insert rule inet fw4 dstnat position 0 ip daddr { 8.8.8.8, 8.8.4.4 } tcp dport 53 counter redirect to "$proxy_port" comment \"OpenClash Google DNS Hijack\" 2>/dev/null
#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' 2>/dev/null
nft 'flush chain inet fw4 openclash_mangle' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ip daddr @localnetwork counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle udp dport 53 counter return' 2>/dev/null
if [ "$en_mode" = "fake-ip" ]; then
nft add rule inet fw4 openclash_mangle meta l4proto { udp } ip daddr {198.18.0.0/16} mark set "$PROXY_FWMARK" tproxy ip to 127.0.0.1:"$tproxy_port" counter accept 2>/dev/null
fi
nft 'add rule inet fw4 openclash_mangle ip saddr @localnetwork udp sport @lan_ac_black_ports counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ip daddr @wan_ac_black_ips counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ip saddr @lan_ac_black_ips counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ether saddr @lan_ac_black_macs counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ip saddr != @lan_ac_white_ips counter return' 2>/dev/null
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash_mangle udp dport != @common_ports counter return' 2>/dev/null
if [ "$china_ip_route" = "1" ]; then
nft 'add rule inet fw4 openclash_mangle ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return' 2>/dev/null
fi
fi
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 2>/dev/null
nft 'add rule inet fw4 mangle_prerouting ip protocol udp counter jump openclash_mangle' 2>/dev/null
elif [ "$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' 2>/dev/null
nft 'flush chain inet fw4 openclash_mangle' 2>/dev/null
nft add rule inet fw4 openclash_mangle meta l4proto { udp } ip daddr {198.18.0.0/16} 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 ip protocol udp counter jump openclash_mangle' 2>/dev/null
nft 'add chain inet fw4 openclash_mangle_output' 2>/dev/null
nft 'flush chain inet fw4 openclash_mangle_output' 2>/dev/null
nft add rule inet fw4 openclash_mangle_output meta l4proto { udp } ip daddr {198.18.0.0/16} mark set "$PROXY_FWMARK" 2>/dev/null
nft 'add rule inet fw4 mangle_output ip protocol udp counter jump openclash_mangle_output' 2>/dev/null
fi
#quic
if [ "$disable_udp_quic" -eq 1 ]; then
nft insert rule inet fw4 input position 0 udp dport 443 ip daddr != @china_ip_route counter reject comment \"OpenClash QUIC REJECT\" 2>/dev/null
fi
fi
nft 'add chain inet fw4 openclash_output' 2>/dev/null
nft 'flush chain inet fw4 openclash_output' 2>/dev/null
nft 'add rule inet fw4 openclash_output ip daddr @localnetwork counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_output ip saddr @localnetwork tcp sport @lan_ac_black_ports counter return' 2>/dev/null
if [ "$en_mode" = "fake-ip" ]; then
nft add rule inet fw4 openclash_output ip protocol tcp ip daddr {198.18.0.0/16} skuid != 65534 counter redirect to "$proxy_port" 2>/dev/null
fi
nft add rule inet fw4 openclash_output tcp dport != @common_ports skuid != 65534 counter return 2>/dev/null
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash_output ip daddr @wan_ac_black_ips counter return' 2>/dev/null
if [ "$china_ip_route" = "1" ]; then
nft 'add rule inet fw4 openclash_output skuid != 65534 ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return' 2>/dev/null
fi
fi
nft add rule inet fw4 openclash_output ip protocol tcp skuid != 65534 counter redirect to "$proxy_port" 2>/dev/null
nft 'add chain inet fw4 nat_output { type nat hook output priority -1; }'
nft 'add rule inet fw4 nat_output ip protocol tcp counter jump openclash_output' 2>/dev/null
fi
if [ -n "$en_mode_tun" ]; then
#TUN模式
#启动TUN
TUN_WAIT=0
ip link set utun up
while ( [ -n "$(pidof clash)" ] && [ -z "$(ip route list |grep utun)" ] && [ "$TUN_WAIT" -le 3 ] )
do
ip link set utun up
let TUN_WAIT++
sleep 2
done
ip route replace default dev utun table "$PROXY_ROUTE_TABLE"
ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
#MTU UP TO 65535
ifconfig utun mtu 65535 >/dev/null 2>&1
#设置防火墙
nft 'add chain inet fw4 openclash_mangle_output' 2>/dev/null
nft 'flush chain inet fw4 openclash_mangle_output' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_output ip daddr @localnetwork counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_output ip saddr @localnetwork meta l4proto {tcp,udp} th sport @lan_ac_black_ports counter return' 2>/dev/null
if [ "$en_mode" = "fake-ip" ]; then
if [ "$en_mode_tun" -eq 1 ]; then
nft add rule inet fw4 openclash_mangle_output meta l4proto {tcp,udp} th dport { 0-65535 } ip daddr {198.18.0.0/16} mark set "$PROXY_FWMARK" 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_output meta l4proto {tcp,udp} th dport != @common_ports skuid != 65534 counter return' 2>/dev/null
nft add rule inet fw4 openclash_mangle_output tcp dport { 0-65535 } skuid != 65534 meta mark set "$PROXY_FWMARK" 2>/dev/null
else
nft add rule inet fw4 openclash_mangle_output skuid != 65534 udp dport { 0-65535 } ip daddr {198.18.0.0/16} meta mark set "$PROXY_FWMARK" 2>/dev/null
fi
elif [ "$en_mode" = "redir-host" ] && [ "$en_mode_tun" -eq 1 ]; then
nft 'add rule inet fw4 openclash_mangle_output ip daddr @wan_ac_black_ips counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_output meta l4proto {tcp,udp} th dport != @common_ports skuid != 65534 counter return' 2>/dev/null
if [ "$china_ip_route" = "1" ]; then
nft 'add rule inet fw4 openclash_mangle_output skuid != 65534 ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return' 2>/dev/null
fi
nft add rule inet fw4 openclash_mangle_output tcp dport { 0-65535 } skuid != 65534 meta mark set "$PROXY_FWMARK" 2>/dev/null
fi
nft 'add rule inet fw4 mangle_output meta l4proto {tcp,udp} counter jump openclash_mangle_output' 2>/dev/null
nft 'add chain inet fw4 openclash_mangle' 2>/dev/null
nft 'flush chain inet fw4 openclash_mangle' 2>/dev/null
nft 'add chain inet fw4 openclash_dns_hijack' 2>/dev/null
nft 'flush chain inet fw4 openclash_dns_hijack' 2>/dev/null
#其他流量
nft 'add rule inet fw4 openclash_mangle ip daddr @localnetwork counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ip saddr @localnetwork meta l4proto {tcp,udp} th sport @lan_ac_black_ports counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ip daddr @wan_ac_black_ips counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ip saddr @lan_ac_black_ips counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ether saddr @lan_ac_black_macs counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ether saddr != @lan_ac_white_macs counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle ip saddr != @lan_ac_white_ips counter return' 2>/dev/null
if [ "$en_mode" = "redir-host" ]; then
nft 'add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} th dport != @common_ports counter return' 2>/dev/null
if [ "$china_ip_route" = "1" ]; then
nft 'add rule inet fw4 openclash_mangle ip daddr @china_ip_route ip daddr != @china_ip_route_pass counter return' 2>/dev/null
fi
fi
nft add rule inet fw4 openclash_mangle meta l4proto {tcp,udp} th dport { 0-65535 } mark set "$PROXY_FWMARK" 2>/dev/null
if [ "$en_mode_tun" -eq 1 ]; then
nft 'insert rule inet fw4 mangle_prerouting position 0 meta l4proto {tcp,udp} counter jump openclash_mangle' 2>/dev/null
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv4} tcp dport 53 counter accept comment \"OpenClash TCP DNS Hijack\" 2>/dev/null
else
nft 'insert rule inet fw4 mangle_prerouting position 0 meta nfproto {ipv4} tcp dport 53 counter jump openclash_dns_hijack' 2>/dev/null
nft add rule inet fw4 openclash_dns_hijack meta nfproto {ipv4} tcp dport 53 mark set "$PROXY_FWMARK" comment \"OpenClash TCP DNS Hijack\" 2>/dev/null
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv4} tcp dport 53 counter accept comment \"OpenClash TCP DNS Hijack\" 2>/dev/null
nft 'insert rule inet fw4 mangle_prerouting position 0 ip protocol udp counter jump openclash_mangle' 2>/dev/null
fi
#TUN FORWORD
nft insert rule inet fw4 forward position 0 meta l4proto {tcp,udp} oifname utun counter accept comment \"OpenClash TUN Forward\" 2>/dev/null
#quic
if [ "$disable_udp_quic" -eq 1 ]; 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\" 2>/dev/null
fi
fi
#google_dns_block
if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ] || [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
nft 'add set inet fw4 openclash_google_dns_ips { type ipv4_addr; flags interval; auto-merge; }'
nft 'add element inet fw4 openclash_google_dns_ips { 8.8.8.8, 8.8.4.4 }'
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
nft insert rule inet fw4 dstnat position 0 ip saddr @lan_block_google_dns_ips ip daddr @openclash_google_dns_ips counter accept comment \"OpenClash Google DNS Block\" 2>/dev/null
nft insert rule inet fw4 dstnat position 0 ether saddr @lan_block_google_dns_macs ip daddr @openclash_google_dns_ips counter accept comment \"OpenClash Google DNS Block\" 2>/dev/null
fi
nft insert rule inet fw4 forward position 0 ip saddr @lan_block_google_dns_ips ip daddr @openclash_google_dns_ips counter reject comment \"OpenClash Google DNS Block\" 2>/dev/null
nft insert rule inet fw4 forward position 0 ether saddr @lan_block_google_dns_macs ip daddr @openclash_google_dns_ips counter reject comment \"OpenClash Google DNS Block\" 2>/dev/null
fi
#ipv6
if [ "$ipv6_enable" -eq 1 ]; then
if [ "$enable_redirect_dns" -eq 1 ] && [ -z "$(nft list chain inet fw4 dstnat |grep 'OpenClash DNS Hijack')"]; then
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} tcp dport 53 counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\" 2>/dev/null
nft insert rule inet fw4 dstnat position 0 meta nfproto {ipv6} udp dport 53 counter redirect to "$DNSPORT" comment \"OpenClash DNS Hijack\" 2>/dev/null
fi
if [ "$china_ip6_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
nft 'flush set inet fw4 china_ip6_route'
nft -f '/etc/openclash/china_ip6_route.ipset' 2>/dev/null
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' 2>/dev/null
done
mkdir -p /tmp/dnsmasq.d 2>/dev/null
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 '!/^$/&&!/^#/&&!/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{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 '!/^$/&&!/^#/&&!/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{printf(" %s,'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>/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
}
awk '!/^$/&&!/^#/&&/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{printf("'${settype}'=/%s/'${nftflag}'china_ip6_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>/tmp/dnsmasq.d/dnsmasq_openclash_chnroute6_pass.conf 2>/dev/null
nft 'flush set inet fw4 china_ip6_route_pass' 2>/dev/null
nft -f '/tmp/openclash_china_ip6_route_pass.list' 2>/dev/null
rm -rf /tmp/openclash_china_ip6_route_pass.list 2>/dev/null
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" } 2>/dev/null
done 2>/dev/null
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 "$lan_ip6_cidrs" ]; then
for lan_ip6_cidr in $lan_ip6_cidrs; do
nft add element inet fw4 localnetwork6 { "$lan_ip6_cidr" } 2>/dev/null
done
fi
if [ -n "$wan_ip6s" ]; then
for wan_ip6 in $wan_ip6s; do
nft add element inet fw4 localnetwork6 { "$wan_ip6" } 2>/dev/null
done
fi
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"
#Google dns
nft insert rule inet fw4 dstnat position 0 ip6 daddr { 2001:4860:4860::8888, 2001:4860:4860::8844 } tcp dport 53 counter accept comment \"OpenClash Google DNS Hijack\" 2>/dev/null
nft 'add chain inet fw4 openclash_mangle_v6' 2>/dev/null
nft 'flush chain inet fw4 openclash_mangle_v6' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @localnetwork6 counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} udp dport 53 counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr @localnetwork6 meta nfproto {ipv6} sport @lan_ac_black_ports counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @wan_ac_black_ipv6s counter return' 2>/dev/null
if [ "$en_mode" == "redir-host" ]; then
nft 'add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} th dport != @common_ports counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr @lan_ac_black_ipv6s counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr @lan_ac_black_macs counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_v6 ether saddr != @lan_ac_white_macs counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_v6 ip6 saddr != @lan_ac_white_ipv6s counter return' 2>/dev/null
fi
if [ "$china_ip6_route" = "1" ]; then
nft 'add rule inet fw4 openclash_mangle_v6 ip6 daddr @china_ip6_route ip6 daddr != @china_ip6_route_pass counter return' 2>/dev/null
fi
nft add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} tcp dport { 0-65535 } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash TCP Tproxy\" 2>/dev/null
nft 'add rule inet fw4 mangle_prerouting meta nfproto {ipv6} jump openclash_mangle_v6' 2>/dev/null
if [ -z "$_koolshare" ]; then
nft 'add chain inet fw4 openclash_mangle_output_v6' 2>/dev/null
nft 'flush chain inet fw4 openclash_mangle_output_v6' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 daddr @localnetwork6 counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 saddr @localnetwork6 meta nfproto {ipv6} sport @lan_ac_black_ports counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_output_v6 ip6 daddr @wan_ac_black_ipv6s counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_mangle_output_v6 meta nfproto {ipv6} th dport != @common_ports skuid != 65534 counter return' 2>/dev/null
if [ "$china_ip6_route" = "1" ]; then
nft 'add rule inet fw4 openclash_mangle_output_v6 skuid != 65534 ip6 daddr @china_ip6_route ip6 daddr != @china_ip6_route_pass counter return' 2>/dev/null
fi
nft add rule inet fw4 openclash_mangle_output_v6 meta nfproto {ipv6} skuid != 65534 tcp dport { 0-65535 } mark set "$PROXY_FWMARK" 2>/dev/null
nft 'add rule inet fw4 mangle_output meta nfproto {ipv6} counter jump openclash_mangle_output_v6' 2>/dev/null
fi
#udp
if [ "$enable_udp_proxy" -eq 1 ] || [ -n "$en_mode_tun" ]; then
nft add rule inet fw4 openclash_mangle_v6 meta nfproto {ipv6} udp dport { 0-65535 } mark set "$PROXY_FWMARK" tproxy ip6 to :"$tproxy_port" counter accept comment \"OpenClash UDP Tproxy\" 2>/dev/null
fi
#quic
if [ "$disable_udp_quic" -eq 1 ]; then
nft insert rule inet fw4 input position 0 udp dport 443 ip6 daddr != @china_ip6_route counter reject comment \"OpenClash QUIC REJECT\" 2>/dev/null
fi
#bypass gateway compatible
if [ "$bypass_gateway_compatible" -eq 1 ]; then
#nft 'delete chain inet fw4 openclash_post_v6' 2>/dev/null
nft 'add chain inet fw4 openclash_post_v6' 2>/dev/null
nft 'flush chain inet fw4 openclash_post_v6' 2>/dev/null
nft add rule inet fw4 openclash_post_v6 meta nfproto {ipv6} meta mark "$PROXY_FWMARK" counter accept 2>/dev/null
nft 'add rule inet fw4 openclash_post_v6 ip6 daddr @localnetwork6 counter return' 2>/dev/null
nft 'add rule inet fw4 openclash_post_v6 meta nfproto {ipv6} fib saddr type != { local } meta skuid != 65534 counter masquerade' 2>/dev/null
nft add rule inet fw4 srcnat meta nfproto {ipv6} counter jump openclash_post_v6 comment \"OpenClash Bypass Gateway Compatible\" 2>/dev/null
fi
#google_dns_block
if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ] || [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
nft 'add set inet fw4 openclash_google_dns_ipv6s { type ipv6_addr; flags interval; auto-merge; }'
nft 'add element inet fw4 openclash_google_dns_ipv6s { 2001:4860:4860::8888, 2001:4860:4860::8844, 2001:4860:4860::6464, 2001:4860:4860::64 }'
nft insert rule inet fw4 dstnat position 0 ip6 saddr @lan_block_google_dns_ipv6s ip6 daddr @openclash_google_dns_ipv6s counter accept comment \"OpenClash Google DNS Block\" 2>/dev/null
nft insert rule inet fw4 dstnat position 0 ether saddr @lan_block_google_dns_macs ip6 daddr @openclash_google_dns_ipv6s counter accept comment \"OpenClash Google DNS Block\" 2>/dev/null
nft insert rule inet fw4 forward position 0 ip6 saddr @lan_block_google_dns_ipv6s ip6 daddr @openclash_google_dns_ipv6s counter reject comment \"OpenClash Google DNS Block\" 2>/dev/null
nft insert rule inet fw4 forward position 0 ether saddr @lan_block_google_dns_macs ip6 daddr @openclash_google_dns_ipv6s counter reject comment \"OpenClash Google DNS Block\" 2>/dev/null
fi
#intranet allowed
if [ "$intranet_allowed" -eq 1 ]; then
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/) {print $(i+1)}}}' 2>/dev/null |sed 's/"//g')
if [ -n "$wan6_ints" ]; then
nft 'add chain inet fw4 openclash_wan6_input' 2>/dev/null
nft 'flush chain inet fw4 openclash_wan6_input' 2>/dev/null
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 2>/dev/null
done
nft add rule inet fw4 openclash_wan6_input udp dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject 2>/dev/null
nft add rule inet fw4 openclash_wan6_input tcp dport {$proxy_port,$tproxy_port,$cn_port,$http_port,$socks_port,$mixed_port,$dns_port} counter reject 2>/dev/null
fi
fi
fi 2>/dev/null
else
if [ "$china_ip_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
ipset -! flush china_ip_route 2>/dev/null
ipset -! restore </etc/openclash/china_ip_route.ipset 2>/dev/null
mkdir -p /tmp/dnsmasq.d 2>/dev/null
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
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 >>/tmp/dnsmasq.d/dnsmasq_openclash_chnroute_pass.conf 2>/dev/null
ipset -! flush china_ip_route_pass 2>/dev/null
ipset -! restore </tmp/openclash_china_ip_route_pass.list 2>/dev/null
rm -rf /tmp/openclash_china_ip_route_pass.list 2>/dev/null
fi
if [ "$enable_redirect_dns" -eq 1 ] && [ -z "$(iptables -t nat -nL PREROUTING --line-number |grep 'OpenClash DNS Hijack')"]; then
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 "$dns_port")
fi
iptables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
iptables -t nat -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
fi
#lan_google_dns_ac
if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ]; then
ipset create lan_block_google_dns_ips hash:net
ipset create lan_block_google_dns_ipv6s hash:net family inet6
config_load "openclash"
config_list_foreach "config" "lan_block_google_dns_ips" ac_add "lan_block_google_dns_ips" "lan_block_google_dns_ipv6s"
fi
if [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
ipset create lan_block_google_dns_macs hash:mac
config_load "openclash"
config_list_foreach "config" "lan_block_google_dns_macs" ac_add "lan_block_google_dns_macs"
fi
#lan_ac
if [ "$operation_mode" = "redir-host" ] && [ "$en_mode" = "redir-host" ]; then
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
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
#lan port ac
if [ -n "$(uci -q get openclash.config.lan_ac_black_ports)" ]; then
ipset create lan_ac_black_ports bitmap:port range 0-65535
config_load "openclash"
config_list_foreach "config" "lan_ac_black_ports" ac_add "lan_ac_black_ports"
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 2>/dev/null
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 "$lan_ip_cidrs" ]; then
for lan_ip_cidr in $lan_ip_cidrs; do
ipset add localnetwork "$lan_ip_cidr" 2>/dev/null
done
fi
if [ -n "$wan_ip4s" ]; then
for wan_ip4 in $wan_ip4s; do
ipset add localnetwork "$wan_ip4" 2>/dev/null
done
fi
#common ports
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"
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 -m mark --mark "$PROXY_FWMARK" -m comment --comment "OpenClash Bypass Gateway Compatible" -j ACCEPT
iptables -t nat -A openclash_post -m comment --comment "OpenClash Bypass Gateway Compatible" -m set --match-set localnetwork dst -j RETURN
iptables -t nat -A openclash_post -m addrtype ! --src-type LOCAL -m owner ! --uid-owner 65534 -m comment --comment "OpenClash Bypass Gateway Compatible" -j MASQUERADE
iptables -t nat -A POSTROUTING -j openclash_post
fi
#intranet allowed
if [ "$intranet_allowed" -eq 1 ]; then
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)
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
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
if [ -z "$en_mode_tun" ] && [ "$en_mode" = "fake-ip" ]; then
iptables -t nat -A openclash -p tcp -d 198.18.0.0/16 -j REDIRECT --to-ports "$proxy_port"
fi
iptables -t nat -A openclash -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN
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
iptables -t nat -A openclash -m set ! --match-set lan_ac_white_macs src -j RETURN >/dev/null 2>&1
iptables -t nat -A openclash -m set ! --match-set lan_ac_white_ips src -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "redir-host" ]; then
iptables -t nat -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
if [ "$china_ip_route" = "1" ]; then
iptables -t nat -A openclash -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
fi
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
#Google dns
iptables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Hijack" -p tcp -d 8.8.8.8 --dport 53 -j REDIRECT --to-ports "$proxy_port"
iptables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Hijack" -p tcp -d 8.8.4.4 --dport 53 -j REDIRECT --to-ports "$proxy_port"
#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 -A openclash -m set --match-set localnetwork dst -j RETURN
iptables -t mangle -A openclash -p udp --dport 53 -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "fake-ip" ]; then
iptables -t mangle -A openclash -p udp -d 198.18.0.0/16 -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
fi
iptables -t mangle -A openclash -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -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_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
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
if [ "$en_mode" = "redir-host" ]; then
iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
if [ "$china_ip_route" = "1" ]; then
iptables -t mangle -A openclash -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
fi
fi
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
elif [ "$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 198.18.0.0/16 -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
iptables -t mangle -A PREROUTING -p udp -j openclash
iptables -t mangle -N openclash_output
iptables -t mangle -F openclash_output
iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -p udp -d 198.18.0.0/16 -j MARK --set-mark "$PROXY_FWMARK"
iptables -t mangle -A OUTPUT -p udp -j openclash_output
fi
#quic
if [ "$disable_udp_quic" -eq 1 ]; 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
fi
fi
if [ -z "$_koolshare" ]; then
iptables -t nat -N openclash_output
iptables -t nat -F openclash_output
if [ "$en_mode" = "fake-ip" ] && [ -z "$en_mode_tun" ]; then
iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -p tcp -d 198.18.0.0/16 -j REDIRECT --to-ports "$proxy_port"
fi
iptables -t nat -A openclash_output -m set --match-set localnetwork dst -j RETURN
iptables -t nat -A openclash_output -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN
iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
if [ "$en_mode" = "redir-host" ]; then
iptables -t nat -A openclash_output -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
if [ "$china_ip_route" = "1" ]; then
iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
fi
fi
iptables -t nat -A openclash_output -m owner ! --uid-owner 65534 -p tcp -j REDIRECT --to-ports "$proxy_port"
else
if [ "$en_mode" = "fake-ip" ]; then
iptables -t nat -N openclash_output
iptables -t nat -F openclash_output
iptables -t nat -A openclash_output -m set --match-set localnetwork dst -j RETURN
iptables -t nat -A openclash_output -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN
iptables -t nat -A openclash_output -p tcp -d 198.18.0.0/16 -j REDIRECT --to-ports "$proxy_port"
fi
fi
iptables -t nat -A OUTPUT -j openclash_output >/dev/null 2>&1
fi
if [ -n "$en_mode_tun" ]; then
#TUN模式
#启动TUN
TUN_WAIT=0
ip link set utun up
while ( [ -n "$(pidof clash)" ] && [ -z "$(ip route list |grep utun)" ] && [ "$TUN_WAIT" -le 3 ] )
do
ip link set utun up
let TUN_WAIT++
sleep 2
done
ip route replace default dev utun table "$PROXY_ROUTE_TABLE"
ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
#MTU UP TO 65535
ifconfig utun mtu 65535 >/dev/null 2>&1
#设置防火墙
if [ "$en_mode" = "fake-ip" ]; then
iptables -t mangle -N openclash_output
iptables -t mangle -F openclash_output
iptables -t mangle -A openclash_output -m set --match-set localnetwork dst -j RETURN
iptables -t mangle -A openclash_output -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN
if [ "$en_mode_tun" -eq 1 ]; then
if [ -z "$_koolshare" ]; then
iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -d 198.18.0.0/16 -j MARK --set-mark "$PROXY_FWMARK"
iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -p tcp -j MARK --set-mark "$PROXY_FWMARK"
else
iptables -t mangle -A openclash_output -d 198.18.0.0/16 -j MARK --set-mark "$PROXY_FWMARK"
fi
elif [ -z "$_koolshare" ]; then
iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -p udp -d 198.18.0.0/16 -j MARK --set-mark "$PROXY_FWMARK"
fi
iptables -t mangle -A OUTPUT -j openclash_output
elif [ -z "$_koolshare" ] && [ "$en_mode" = "redir-host" ] && [ "$en_mode_tun" -eq 1 ]; then
iptables -t mangle -N openclash_output
iptables -t mangle -F openclash_output
iptables -t mangle -A openclash_output -m set --match-set localnetwork dst -j RETURN
iptables -t mangle -A openclash_output -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -j RETURN
iptables -t mangle -A openclash_output -m set --match-set wan_ac_black_ips dst -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
if [ "$china_ip_route" = "1" ]; then
iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
fi
iptables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -p tcp -j MARK --set-mark "$PROXY_FWMARK"
iptables -t mangle -A OUTPUT -j openclash_output
fi
iptables -t mangle -N openclash
iptables -t mangle -F openclash
iptables -t mangle -N openclash_dns_hijack
iptables -t mangle -F openclash_dns_hijack
#其他流量
iptables -t mangle -A openclash -m set --match-set localnetwork dst -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -m set --match-set localnetwork src -m set --match-set lan_ac_black_ports src -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
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
if [ "$en_mode" = "redir-host" ]; then
iptables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
if [ "$china_ip_route" = "1" ]; then
iptables -t mangle -A openclash -m set --match-set china_ip_route dst -m set ! --match-set china_ip_route_pass dst -j RETURN >/dev/null 2>&1
fi
fi
iptables -t mangle -A openclash -j MARK --set-mark "$PROXY_FWMARK"
if [ "$en_mode_tun" -eq 1 ]; then
iptables -t mangle -I PREROUTING -j openclash
iptables -t nat -I PREROUTING -m comment --comment "OpenClash TCP DNS Hijack" -p tcp --dport 53 -j ACCEPT
else
iptables -t mangle -I PREROUTING -p tcp --dport 53 -j openclash_dns_hijack
iptables -t mangle -A openclash_dns_hijack -m comment --comment "OpenClash TCP DNS Hijack" -p tcp --dport 53 -j MARK --set-mark "$PROXY_FWMARK"
iptables -t mangle -I PREROUTING -p udp -j openclash
iptables -t nat -I PREROUTING -m comment --comment "OpenClash TCP DNS Hijack" -p tcp --dport 53 -j ACCEPT
fi
#TUN FORWORD
iptables -I FORWARD -m comment --comment "OpenClash TUN Forward" -o utun -j ACCEPT
#quic
if [ "$disable_udp_quic" -eq 1 ]; 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
fi
fi
#google_dns_block
if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ] || [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
ipset create openclash_google_dns_ips hash:net
ipset add openclash_google_dns_ips 8.8.8.8
ipset add openclash_google_dns_ips 8.8.4.4
if [ -z "$en_mode_tun" ] || [ "$en_mode_tun" -eq 2 ]; then
iptables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Block" -m set --match-set lan_block_google_dns_ips src -m set --match-set openclash_google_dns_ips dst -j ACCEPT >/dev/null 2>&1
iptables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Block" -m set --match-set lan_block_google_dns_macs src -m set --match-set openclash_google_dns_ips dst -j ACCEPT >/dev/null 2>&1
fi
iptables -t filter -I FORWARD -m set --match-set lan_block_google_dns_ips src -m set --match-set openclash_google_dns_ips dst -j REJECT >/dev/null 2>&1
iptables -t filter -I FORWARD -m set --match-set lan_block_google_dns_macs src -m set --match-set openclash_google_dns_ips dst -j REJECT >/dev/null 2>&1
fi
#ipv6
if [ "$ipv6_enable" -eq 1 ] && [ -n "$(ip6tables -t mangle -L 2>&1 | grep -o 'Chain')" ]; then
if [ "$enable_redirect_dns" -eq 1 ] && [ -z "$(ip6tables -t nat -nL PREROUTING --line-number |grep 'DNS Hijack')"]; then
ip6tables -t nat -I PREROUTING -p udp --dport 53 -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
ip6tables -t nat -I PREROUTING -p tcp --dport 53 -j REDIRECT --to-ports "$DNSPORT" -m comment --comment "OpenClash DNS Hijack"
fi
if [ "$china_ip6_route" = "1" ] || [ "$disable_udp_quic" = "1" ]; then
ipset -! flush china_ip6_route 2>/dev/null
ipset -! restore </etc/openclash/china_ip6_route.ipset 2>/dev/null
mkdir -p /tmp/dnsmasq.d 2>/dev/null
echo "create china_ip6_route_pass hash:net family inet6 hashsize 1024 maxelem 1000000" >/tmp/openclash_china_ip6_route_pass.list
awk '!/^$/&&!/^#/&&!/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{printf("add china_ip6_route_pass %s'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>/tmp/openclash_china_ip6_route_pass.list 2>/dev/null
awk '!/^$/&&!/^#/&&/^(\*?\.?)*[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*$/{printf("ipset=/%s/china_ip6_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>/tmp/dnsmasq.d/dnsmasq_openclash_chnroute6_pass.conf 2>/dev/null
ipset -! flush china_ip6_route_pass 2>/dev/null
ipset -! restore </tmp/openclash_china_ip6_route_pass.list 2>/dev/null
rm -rf /tmp/openclash_china_ip6_route_pass.list 2>/dev/null
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 2>/dev/null
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 "$lan_ip6_cidrs" ]; then
for lan_ip6_cidr in $lan_ip6_cidrs; do
ipset add localnetwork6 "$lan_ip6_cidr" 2>/dev/null
done
fi
if [ -n "$wan_ip6s" ]; then
for wan_ip6 in $wan_ip6s; do
ipset add localnetwork6 "$wan_ip6"
done
fi
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"
#Google dns
ip6tables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Hijack" -p tcp -d 2001:4860:4860::8888 --dport 53 -j ACCEPT
ip6tables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Hijack" -p tcp -d 2001:4860:4860::8844 --dport 53 -j ACCEPT
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 -p udp --dport 53 -j RETURN >/dev/null 2>&1
ip6tables -t mangle -A openclash -m set --match-set localnetwork6 src -m set --match-set lan_ac_black_ports src -j RETURN
ip6tables -t mangle -A openclash -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 -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
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
ip6tables -t mangle -A openclash -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
fi
if [ "$china_ip6_route" = "1" ]; then
ip6tables -t mangle -A openclash -m set --match-set china_ip6_route dst -m set ! --match-set china_ip6_route_pass dst -j RETURN >/dev/null 2>&1
fi
ip6tables -t mangle -A openclash -p tcp -m comment --comment "OpenClash TCP Tproxy" -j TPROXY --on-port "$tproxy_port" --tproxy-mark "$PROXY_FWMARK"
ip6tables -t mangle -A PREROUTING -j openclash
if [ -z "$_koolshare" ]; then
ip6tables -t mangle -N openclash_output
ip6tables -t mangle -F openclash_output
ip6tables -t mangle -A openclash_output -m set --match-set localnetwork6 dst -j RETURN
ip6tables -t mangle -A openclash_output -m set --match-set localnetwork6 src -m set --match-set lan_ac_black_ports src -j RETURN
ip6tables -t mangle -A openclash_output -m set --match-set wan_ac_black_ipv6s dst -j RETURN >/dev/null 2>&1
ip6tables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set ! --match-set common_ports dst -j RETURN >/dev/null 2>&1
if [ "$china_ip6_route" = "1" ]; then
ip6tables -t mangle -A openclash_output -m owner ! --uid-owner 65534 -m set --match-set china_ip6_route dst -m set ! --match-set china_ip6_route_pass dst -j RETURN >/dev/null 2>&1
fi
ip6tables -t mangle -A openclash_output -p tcp -m owner ! --uid-owner 65534 -j MARK --set-xmark "$PROXY_FWMARK"
ip6tables -t mangle -A OUTPUT -j openclash_output
fi
#udp
if [ "$enable_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
#quic
if [ "$disable_udp_quic" -eq 1 ]; then
ip6tables -I INPUT -p udp --dport 443 -m comment --comment "OpenClash QUIC REJECT" -m set ! --match-set china_ip6_route dst -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 -m mark --mark "$PROXY_FWMARK" -m comment --comment "OpenClash Bypass Gateway Compatible" -j ACCEPT
ip6tables -t nat -A openclash_post -m comment --comment "OpenClash Bypass Gateway Compatible" -m set --match-set localnetwork6 dst -j RETURN
ip6tables -t nat -A openclash_post -m addrtype ! --src-type LOCAL -m owner ! --uid-owner 65534 -m comment --comment "OpenClash Bypass Gateway Compatible" -j MASQUERADE
ip6tables -t nat -A POSTROUTING -j openclash_post
fi
#google_dns_block
if [ -n "$(uci -q get openclash.config.lan_block_google_dns_ips)" ] || [ -n "$(uci -q get openclash.config.lan_block_google_dns_macs)" ]; then
ipset create openclash_google_dns_ipv6s hash:net family inet6
ipset add openclash_google_dns_ipv6s 2001:4860:4860::8888
ipset add openclash_google_dns_ipv6s 2001:4860:4860::8844
ipset add openclash_google_dns_ipv6s 2001:4860:4860::6464
ipset add openclash_google_dns_ipv6s 2001:4860:4860::64
ip6tables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Block" -m set --match-set lan_block_google_dns_ipv6s src -m set --match-set openclash_google_dns_ipv6s dst -j ACCEPT
ip6tables -t nat -I PREROUTING -m comment --comment "OpenClash Google DNS Block" -m set --match-set lan_block_google_dns_macs src -m set --match-set openclash_google_dns_ipv6s dst -j ACCEPT
ip6tables -t filter -I FORWARD -m set --match-set lan_block_google_dns_ipv6s src -m set --match-set openclash_google_dns_ipv6s dst -j REJECT >/dev/null 2>&1
ip6tables -t filter -I FORWARD -m set --match-set lan_block_google_dns_macs src -m set --match-set openclash_google_dns_ipv6s dst -j REJECT >/dev/null 2>&1
fi
#intranet allowed
if [ "$intranet_allowed" -eq 1 ]; then
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)
if [ -n "$wan_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 "$wan_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
fi
fi
fi 2>/dev/null
fi
#端口转发
config_load "firewall"
config_foreach firewall_redirect_exclude "redirect"
config_foreach firewall_rule_exclude "rule"
}
revert_firewall()
{
rm -rf /var/etc/openclash.include >/dev/null 2>&1
rm -rf /tmp/dnsmasq.d/dnsmasq_openclash_chnroute_pass.conf >/dev/null 2>&1
rm -rf /tmp/dnsmasq.d/dnsmasq_openclash_chnroute6_pass.conf >/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 route del default dev utun table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
ip rule del fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
route delete -net 198.18.0.0/16 dev utun >/dev/null 2>&1
ip link set dev utun down >/dev/null 2>&1
ip tuntap del utun mode tun >/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"; 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_dns_hijack" "openclash_wan_input"; 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 openclash_google_dns_ipv6s >/dev/null 2>&1
ipset destroy lan_block_google_dns_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
ipset destroy lan_block_google_dns_ips >/dev/null 2>&1
ipset destroy lan_block_google_dns_macs >/dev/null 2>&1
ipset destroy openclash_google_dns_ips >/dev/null 2>&1
fi
}
get_config()
{
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)
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)
lan_ip=$(uci -q get network.lan.ipaddr |awk -F '/' '{print $1}' 2>/dev/null || 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}' || ip addr show 2>/dev/null | grep -w 'inet' | grep 'global' | grep 'brd' | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -n 1)
lan_ip_cidrs=$(ip route | grep "/" | awk '{print $1}' | grep -vE "^198.18" 2>/dev/null)
lan_ip6_cidrs=$(ip -6 route | grep "/" | awk '{print $1}' | grep -vE "^unreachable" 2>/dev/null)
wan_ip4s=$(ifconfig | grep 'inet addr' | awk '{print $2}' | cut -d: -f2 | grep -vE "(^198.18|^192.168|^127.0)" 2>/dev/null)
wan_ip6s=$(ifconfig | grep 'inet6 addr' | awk '{print $3}' 2>/dev/null)
disable_masq_cache=$(uci -q get openclash.config.disable_masq_cache)
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)
china_ip_route=$(uci -q get openclash.config.china_ip_route)
china_ip6_route=$(uci -q get openclash.config.china_ip6_route)
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)
stream_domains_prefetch=$(uci -q get openclash.config.stream_domains_prefetch || echo 0)
store_fakeip=$(uci -q get openclash.config.store_fakeip || echo 1)
dns_remote=$(uci -q get openclash.config.dns_remote || 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_core=$(uci -q get openclash.config.enable_meta_core || echo 0)
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 "memconservative")
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 1)
_koolshare=$(cat /usr/lib/os-release 2>/dev/null |grep OPENWRT_RELEASE 2>/dev/null |grep -i koolshare 2>/dev/null)
[ -z "$dns_port" ] && dns_port=7874 && uci -q set openclash.config.dns_port=7874
uci -q set openclash.config.restricted_mode=0 && uci -q commit openclash
}
start()
{
enable=$(uci -q get openclash.config.enable)
[ "$enable" != "1" ] && LOG_OUT "Warning: OpenClash Now Disabled, Need Start From Luci Page, Exit..." && SLOG_CLEAN && del_lock && 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"
#快速启动判断
check_run_quick
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" "$stream_domains_prefetch" "$dns_remote" "$enable_meta_core" "$enable_meta_sniffer" "$enable_geoip_dat" "$geodata_loader" "$enable_meta_sniffer_custom" "$interface_name" "$enable_tcp_concurrent" "$core_type" "$append_default_dns"
/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" "$proxy_port" "$tproxy_port" "$enable_meta_core"
/usr/share/openclash/openclash_server_fake_filter.sh >/dev/null 2>&1
/usr/share/openclash/openclash_custom_domain_dns.sh >/dev/null 2>&1
fi
LOG_OUT "Step 4: Start Running The Clash Core..."
start_run_core
LOG_OUT "Step 5: Check The Core Status..."
check_core_status
#检测proxy_provider配置文件状态
LOG_OUT "Step 6: Wait For The File Downloading..."
if [ "$enable_meta_core" != "1" ]; then
yml_provider_check "$CONFIG_FILE" "proxy-providers" "proxies"
yml_provider_check "$CONFIG_FILE" "rule-providers" "payload"
fi
try_restore_start
LOG_OUT "Step 7: Set Firewall Rules..."
set_firewall
LOG_OUT "Step 8: Restart Dnsmasq..."
change_dns "$enable_redirect_dns" "$disable_masq_cache"
/etc/init.d/dnsmasq restart >/dev/null 2>&1
LOG_OUT "Step 9: Add Cron Rules, Start Daemons..."
add_cron
if [ "$(uci -q get openclash.config.restricted_mode)" != "1" ]; then
if [ -z "$(uci -q get dhcp.lan.dhcpv6)" ] || [ "$(uci -q get dhcp.lan.dhcpv6)" == "disabled" ]; then
LOG_OUT "OpenClash Start Successful!"
sleep 3
elif [ "$ipv6_enable" -eq 0 ]; then
LOG_OUT "Warning: OpenClash Start Successful, Please Note That Network May Abnormal With IPv6's DHCP Server"
sleep 3
else
LOG_OUT "OpenClash Start Successful!"
sleep 3
fi
else
LOG_OUT "Warning: OpenClash Start Successful With Raw Config File, Please Note That It's Restricted Mode Now"
sleep 3
fi
echo "OpenClash Already Start!"
write_run_quick
SLOG_CLEAN
rm -rf /tmp/yaml_*
}
stop()
{
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..."
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
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/dnsmasq.d/dnsmasq_openclash.conf >/dev/null 2>&1
rm -rf /tmp/dnsmasq.d/dnsmasq_openclash_custom_domain.conf >/dev/null 2>&1
rm -rf /tmp/dnsmasq.d/dnsmasq_openclash_chnroute_pass.conf >/dev/null 2>&1
rm -rf /tmp/dnsmasq.d/dnsmasq_openclash_chnroute6_pass.conf >/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/etc/openclash >/dev/null 2>&1
rm -rf /tmp/openclash_edit_file_name >/dev/null 2>&1
rm -rf /tmp/openclash_*_region>/dev/null 2>&1
del_lock
LOG_OUT "OpenClash Already Stop!"
sleep 3
rm -rf $LOG_FILE
fi
del_cron
rm -rf /tmp/yaml_* >/dev/null 2>&1
rm -rf $START_LOG >/dev/null 2>&1
echo "OpenClash Already Stop!"
}
restart()
{
[ -f "$LOCK_FILE" ] && LOG_OUT "Warning: Multiple Restart Scripts Running, Exit..." && SLOG_CLEAN && exit 0
mkdir -p /tmp/lock
touch $LOCK_FILE
set_lock
stop
start
del_lock
}
reload()
{
enable=$(uci -q get openclash.config.enable)
if pidof clash >/dev/null && [ "$enable" == "1" ] && [ "$1" == "firewall" ]; then
LOG_OUT "Reload OpenClash Firewall Rules..."
set_lock
revert_firewall 2>/dev/null
do_run_mode 2>/dev/null
get_config 2>/dev/null
set_firewall 2>/dev/null
/etc/init.d/dnsmasq restart >/dev/null 2>&1
SLOG_CLEAN
del_lock
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
}