immortalwrt/package/ctcgfw/luci-app-openclash/files/etc/init.d/openclash
2020-07-18 22:04:13 +08:00

1566 lines
63 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh /etc/rc.common
# Copyright (c) 2019 vernesong
START=99
STOP=15
LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")
CLASH="/etc/openclash/clash"
CLASH_CONFIG="/etc/openclash"
CRON_FILE="/etc/crontabs/root"
CONFIG_FILE=$(uci get openclash.config.config_path 2>/dev/null)
LOG_FILE="/tmp/openclash.log"
START_LOG="/tmp/openclash_start.log"
BACKUP_FILE="/etc/openclash/backup/$(uci get openclash.config.config_path 2>/dev/null |awk -F '/' '{print $5}' 2>/dev/null)"
START_BACKUP="/tmp/config.sbak"
CHANGE_FILE="/tmp/yaml_change.yaml"
SCRIPT_FILE="/tmp/yaml_script.yaml"
RULE_PROVIDER_FILE="/tmp/yaml_rule_provider.yaml"
RULE_FILE="/tmp/yaml_rules.yaml"
DNS_FILE="/tmp/yaml_dns.yaml"
PROXY_FILE="/tmp/yaml_proxy.yaml"
PROXY_PROVIDER_FILE="/tmp/yaml_proxy_provider.yaml"
GROUP_FILE="/tmp/yaml_group.yaml"
GAME_RULE_FILE="/tmp/yaml_game_rule_group.yaml"
HOSTS_FILE="/etc/openclash/custom/openclash_custom_hosts.list"
PROXY_FWMARK="0x162"
PROXY_ROUTE_TABLE="0x162"
add_cron()
{
[ -z "$(grep "openclash.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci get openclash.config.auto_update 2>/dev/null)" -eq 1 ] && [ "$(uci get openclash.config.config_auto_update_mode 2>/dev/null)" -ne 1 ] && echo "0 $(uci get openclash.config.auto_update_time 2>/dev/null) * * $(uci get openclash.config.config_update_week_time 2>/dev/null) /usr/share/openclash/openclash.sh" >> $CRON_FILE
}
[ -z "$(grep "openclash_rule.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci get openclash.config.other_rule_auto_update 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.other_rule_update_day_time 2>/dev/null) * * $(uci get openclash.config.other_rule_update_week_time 2>/dev/null) /usr/share/openclash/openclash_rule.sh" >> $CRON_FILE
}
[ -z "$(grep "openclash_ipdb.sh" "$CRON_FILE" 2>/dev/null)" ] && {
[ "$(uci get openclash.config.geo_auto_update 2>/dev/null)" -eq 1 ] && echo "0 $(uci get openclash.config.geo_update_day_time 2>/dev/null) * * $(uci get openclash.config.geo_update_week_time 2>/dev/null) /usr/share/openclash/openclash_ipdb.sh" >> $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
/etc/init.d/cron restart
}
change_dns() {
if [ "$1" -eq "1" ]; then
uci del dhcp.@dnsmasq[-1].server >/dev/null 2>&1
uci add_list dhcp.@dnsmasq[0].server=127.0.0.1#"$dns_port"
uci delete dhcp.@dnsmasq[0].resolvfile 2>/dev/null
uci set dhcp.@dnsmasq[0].noresolv=1 2>/dev/null
uci set openclash.config.redirect_dns=1
else
uci delete openclash.config.redirect_dns 2>/dev/null
fi
if [ "$2" -eq "1" ]; then
uci set dhcp.@dnsmasq[0].cachesize=0 2>/dev/null
fi
uci commit dhcp
uci commit openclash
}
revert_dns() {
[ "$1" -eq "0" ] && {
if [ "$(uci get openclash.config.dns_revert 2>/dev/null)" != "1" ]; then
uci del_list dhcp.@dnsmasq[0].server=127.0.0.1#"$3" >/dev/null 2>&1
uci set openclash.config.dns_revert=1 2>/dev/null
fi
}
[ "$1" -eq "1" ] && {
uci del_list dhcp.@dnsmasq[0].server=127.0.0.1#"$3" >/dev/null 2>&1
uci set openclash.config.dns_revert=0 2>/dev/null
}
[ "$(uci get dhcp.@dnsmasq[0].cachesize 2>/dev/null)" = "0" ] && {
uci delete dhcp.@dnsmasq[0].cachesize >/dev/null 2>&1
}
if [ -s "/tmp/resolv.conf.d/resolv.conf.auto" ]; then
uci set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.d/resolv.conf.auto >/dev/null 2>&1
elif [ -s "/tmp/resolv.conf.auto" ]; then
uci set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.auto >/dev/null 2>&1
fi
uci set dhcp.@dnsmasq[0].noresolv=0 >/dev/null 2>&1
uci commit dhcp
uci commit openclash
rm -rf /tmp/dnsmasq.d/dnsmasq_openclash.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
sleep 1
}
field_cut()
{
local i lines end_len
proxy_len=$(sed -n '/^Proxy:/=' "$3" 2>/dev/null |sed -n 1p)
provider_len=$(sed -n '/^proxy-providers:/=' "$3" 2>/dev/null)
group_len=$(sed -n '/^proxy-groups:/=' "$3" 2>/dev/null)
rule_len=$(sed -n '/^rules:/=' "$3" 2>/dev/null)
rule_provider_len=$(sed -n '/^rule-providers:/=' "$3" 2>/dev/null)
script_len=$(sed -n '/^script:/=' "$3" 2>/dev/null)
lines="$proxy_len $provider_len $group_len $rule_len $rule_provider_len $script_len"
for i in $lines; do
if [ -z "$1" ]; then
break
fi
if [ "$1" -ge "$i" ]; then
continue
fi
if [ "$end_len" -gt "$i" ] || [ -z "$end_len" ]; then
end_len="$i"
fi
done 2>/dev/null
if [ -n "$1" ] && [ -z "$end_len" ]; then
end_len=$(sed -n '$=' "$3")
elif [ -n "$end_len" ]; then
end_len=$(expr "$end_len" - 1)
fi
sed -n "${1},${end_len}p" "$3" > "$2" 2>/dev/null
sed -i "${1},${end_len}d" "$3" 2>/dev/null
}
yml_check()
{
#格式替换
sed -i 's/\t/ /g' "$3" 2>/dev/null
sed -i "s/- \{2,\}/- /g" "$3" 2>/dev/null
#检查关键字避免后续操作出错
/usr/share/openclash/yml_field_name_ch.sh "$3" 2>/dev/null
#dns
[ -z "$(grep "^dns:" "$3")" ] && {
sed -i "s/^ \{1,\}dns:/dns:/g" "$3" 2>/dev/null
}
#创建启动备份
cp "$3" "$5"
#创建原始备份
if [ ! -f "$4" ]; then
cp "$3" "$4"
fi
#位置检查
proxy_len=$(sed -n '/^Proxy:/=' "$3" 2>/dev/null |sed -n 1p)
provider_len=$(sed -n '/^proxy-providers:/=' "$3" 2>/dev/null)
group_len=$(sed -n '/^proxy-groups:/=' "$3" 2>/dev/null)
dns_len=$(sed -n '/^dns:/=' "$3" 2>/dev/null)
rule_len=$(sed -n '/^rules:/=' "$3" 2>/dev/null)
if [ "$dns_len" -ge "$proxy_len" ] || [ "$dns_len" -ge "$rule_len" ] || [ "$dns_len" -ge "$group_len" ]; then
kill_clash
stop
echo "错误: 不支持的配置文件, General 设置部分应位于开头,请根据模板修改后重试!" > $START_LOG
echo "${LOGTIME} Unsupported Config, Please Check The General Setting's location And Try-again!" >> $LOG_FILE
mv "$START_BACKUP" "$CONFIG_FILE"
exit 0
fi 2>/dev/null
if [ "$proxy_len" -ge "$rule_len" ]; then
kill_clash
stop
echo "错误: 不支持的配置文件,服务器节点设置部分应位于规则之前,请根据模板修改后重试!" > $START_LOG
echo "${LOGTIME} Unsupported Config, Please Check The Proxy Setting's location And Try-again!" >> $LOG_FILE
mv "$START_BACKUP" "$CONFIG_FILE"
exit 0
fi 2>/dev/null
if [ "$group_len" -ge "$rule_len" ] || [ "$proxy_len" -ge "$group_len" ]; then
kill_clash
stop
echo "错误: 不支持的配置文件,策略组设置部分应位于规则之前、节点之后,请根据模板修改后重试!" > $START_LOG
echo "${LOGTIME} Unsupported Config, Please Check The Group Setting's location And Try-again!" >> $LOG_FILE
mv "$START_BACKUP" "$CONFIG_FILE"
exit 0
fi 2>/dev/null
#处理proxy_provider位置
if [ "$provider_len" -ge "$proxy_len" ] || [ "$provider_len" -ge "$group_len" ]; then
field_cut "$provider_len" "$PROXY_PROVIDER_FILE" "$3"
if [ -n "$proxy_len" ]; then
sed -i '/^Proxy:/i\proxy-provider-tag' "$3" 2>/dev/null
sed -i '/proxy-provider-tag/r/tmp/yaml_proxy_provider.yaml' "$3" 2>/dev/null
sed -i '/proxy-provider-tag/d' "$3" 2>/dev/null
elif [ -n "$group_len" ]; then
sed -i '/^proxy-groups:/i\proxy-provider-tag' "$3" 2>/dev/null
sed -i '/proxy-provider-tag/r/tmp/yaml_proxy_provider.yaml' "$3" 2>/dev/null
sed -i '/proxy-provider-tag/d' "$3" 2>/dev/null
fi
fi 2>/dev/null
#处理rule_provider位置
rule_provider_len=$(sed -n '/^rule-providers:/=' "$3" 2>/dev/null)
if [ -n "$rule_provider_len" ]; then
field_cut "$rule_provider_len" "$RULE_PROVIDER_FILE" "$3"
fi 2>/dev/null
#处理script位置
script_len=$(sed -n '/^script:/=' "$3" 2>/dev/null)
if [ -n "$script_len" ]; then
field_cut "$script_len" "$SCRIPT_FILE" "$3"
fi 2>/dev/null
if [ -n "$provider_len" ]; then
proxy_provider_mode=1
fi
#自定义DNS还原
if [ "$(grep -c '##Custom DNS##' "$3")" -gt 0 ] && [ "$2" = 0 ] && [ -f "$4" ]; then
if [ "$proxy_provider_mode" -eq 1 ]; then
awk '/^ {0,}nameserver:/,/proxy-providers:/{print}' "$4" | sed '/^proxy-providers:/d' >/tmp/backdns.config 2>/dev/null
else
awk '/^ {0,}nameserver:/,/Proxy:/{print}' "$4" | sed '/^Proxy:/d' >/tmp/backdns.config 2>/dev/null
fi
sed -i '/OpenClash-General-Settings/i\Custom DNS End' "$3" 2>/dev/null
sed -i '/^ \{0,\}nameserver:/,/^Custom DNS End$/d' "$3" 2>/dev/null
sed -i '/##Custom DNS##/r/tmp/bakdns.config' "$3" 2>/dev/null
rm -rf /tmp/backdns.config 2>/dev/null
fi 2>/dev/null
yml_dns_check
if [ -n "$(grep "^ \{1,\}port:" "$3")" ] || [ -n "$(grep "^ \{1,\}mode:" "$3")" ] || [ -n "$(grep "^ \{1,\}log-level:" "$3")" ]; then
cp "$3" /tmp/config.check 2>/dev/null
sed -i '/^dns:/,$d' /tmp/config.check 2>/dev/null
sed -i 's/^[ \t]*//' /tmp/config.check 2>/dev/null
sed -n '/^dns:/,$p' "$3" >> /tmp/config.check 2>/dev/null
mv /tmp/config.check "$3" 2>/dev/null
fi
#添加标识
sed -i '/OpenClash-General/d' "$3" 2>/dev/null
if [ "$proxy_provider_mode" -eq 1 ]; then
sed -i '/^proxy-providers:/i\#===================== OpenClash-General-Settings =====================#' "$3" 2>/dev/null
else
sed -i '/^Proxy:/i\#===================== OpenClash-General-Settings =====================#' "$3" 2>/dev/null
fi 2>/dev/null
}
#检查DNS设置
yml_dns_check()
{
if [ -z "$(grep '^dns:' "$CONFIG_FILE")" ]; then
if [ "$proxy_provider_mode" -eq 1 ]; then
sed -i '/^proxy-providers:/i\dns:' "$CONFIG_FILE" 2>/dev/null
else
sed -i '/^Proxy:/i\dns:' "$CONFIG_FILE" 2>/dev/null
fi 2>/dev/null
fi
if [ -z "$(grep '^ \{0,\}nameserver:' "$CONFIG_FILE")" ]; then
if [ "$proxy_provider_mode" -eq 1 ]; then
sed -i '/^proxy-providers:/i\ nameserver:' "$CONFIG_FILE" 2>/dev/null
else
sed -i '/^Proxy:/i\ nameserver:' "$CONFIG_FILE" 2>/dev/null
fi 2>/dev/null
sed -i "/^ \{0,\}nameserver:/a\ - tls://8.8.8.8:853" "$CONFIG_FILE" 2>/dev/null
sed -i "/^ \{0,\}nameserver:/a\ fallback:" "$CONFIG_FILE" 2>/dev/null
sed -i "/^ \{0,\}nameserver:/a\ - 114.114.114.114" "$CONFIG_FILE" 2>/dev/null
fi
dns_port=$(grep "^ \{0,\}listen:" "$CONFIG_FILE" |awk -F ':' '{print $3}' |awk -F '#' '{print $1}' |tr -cd "[0-9]" 2>/dev/null)
if [ -z "$dns_port" ] || [ "$dns_port" -eq 53 ]; then
dns_port=7874
fi
if [ -n "$(grep "^ \{0,\}listen:" "$CONFIG_FILE")" ]; then
if [ "$ipv6_enable" != "1" ]; then
sed -i "/^ \{0,\}listen:/c\ listen: 127.0.0.1:${dns_port}" "$CONFIG_FILE" 2>/dev/null
else
sed -i "/^ \{0,\}listen:/c\ listen: 0.0.0.0:${dns_port}" "$CONFIG_FILE" 2>/dev/null
fi
else
if [ "$ipv6_enable" != "1" ]; then
sed -i "/^dns:/a\ listen: 127.0.0.1:${dns_port}" "$CONFIG_FILE" 2>/dev/null
else
sed -i "/^dns:/a\ listen: 0.0.0.0:${dns_port}" "$CONFIG_FILE" 2>/dev/null
fi
fi 2>/dev/null
uci set openclash.config.dns_port="$dns_port" && uci commit openclash
}
#修改集路径
yml_provider_path()
{
provider_path_line=$(sed -n '/ \{0,\}path/=' "$1" 2>/dev/null)
if [ -n "$provider_path_line" ]; then
for n in $provider_path_line; do
if [ -n "$(sed -n "${n}p" "$1" |grep "^ \{0,\}#")" ]; then
continue
fi
provider_path=$(sed -n "${n}p" "$1" |sed "s/\'//g" |sed 's/\"//g' |awk -F 'path:' '{print $2}' 2>/dev/null |sed 's/,.*//' 2>/dev/null |sed 's/^ \{0,\}//g' 2>/dev/null |sed 's/ \{0,\}$//g' 2>/dev/null |sed 's/ \{0,\}\}\{0,\}$//g' 2>/dev/null)
if [ -z "$(echo "$provider_path" |grep "$2")" ]; then
provider_name=$(echo "$provider_path" |awk -F '/' '{print $NF}')
sed -i "s#path: ${provider_path}#path: ./${2}/${provider_name}#" "$1" 2>/dev/null
sed -i "s#\"${provider_path}#\"./${2}/${provider_name}#" "$1" 2>/dev/null
sed -i "s#\'${provider_path}#\'./${2}/${provider_name}#" "$1" 2>/dev/null
sed -i "s#\:${provider_path}#\:./${2}/${provider_name}#" "$1" 2>/dev/null
uci set openclash.config.config_reload=0 2>/dev/null
uci commit openclash
fi
done
fi 2>/dev/null
}
#检查集文件防止启动失败
yml_provider_check()
{
provider_path_line=$(sed -n '/ \{0,\}path/=' "$1" 2>/dev/null)
local provider_path_exist
if [ -n "$provider_path_line" ]; then
while ( [ -n "$(pidof clash)" ] && [ "$provider_path_exist" != 1 ] )
do
provider_path_exist=1
for n in $provider_path_line; do
if [ -n "$(sed -n "${n}p" "$1" |grep "^ \{0,\}#")" ]; then
continue
fi
provider_path=$(sed -n "${n}p" "$1" |sed "s/\'//g" |sed 's/\"//g' |awk -F 'path:' '{print $2}' 2>/dev/null |sed 's/,.*//' 2>/dev/null |sed 's/^ \{0,\}//g' 2>/dev/null |sed 's/ \{0,\}$//g' 2>/dev/null |sed 's/ \{0,\}\}\{0,\}$//g' 2>/dev/null)
if [ "$(echo "${provider_path:0:1}")" = "." ]; then
provider_path_check="/etc/openclash/$(echo ${provider_path:2})"
if [ -f "$provider_path_check" ] && [ "$2" = "proxy_provider" ]; then
if [ -z "$(grep "'proxies':" "$provider_path_check")" ] && [ -z "$(grep '"proxies":' "$provider_path_check")" ] && [ -z "$(grep 'proxies:' "$provider_path_check")" ]; then
provider_path_exist=0
fi
elif [ "$2" = "proxy_provider" ]; then
provider_path_exist=0
fi
if [ -f "$provider_path_check" ] && [ "$2" = "rule_provider" ]; then
if [ -z "$(grep "'payload':" "$provider_path_check")" ] && [ -z "$(grep '"payload":' "$provider_path_check")" ] && [ -z "$(grep 'payload:' "$provider_path_check")" ]; then
provider_path_exist=0
fi
elif [ "$2" = "rule_provider" ]; then
provider_path_exist=0
fi
elif [ "$(echo "${provider_path:0:1}")" = "/" ]; then
provider_path_check="$provider_path"
if [ -f "$provider_path_check" ] && [ "$2" = "proxy_provider" ]; then
if [ -z "$(grep "'proxies':" "$provider_path_check")" ] && [ -z "$(grep '"proxies":' "$provider_path_check")" ] && [ -z "$(grep 'proxies:' "$provider_path_check")" ]; then
provider_path_exist=0
fi
elif [ "$2" = "proxy_provider" ]; then
provider_path_exist=0
fi
if [ -f "$provider_path_check" ] && [ "$2" = "rule_provider" ]; then
if [ -z "$(grep "'payload':" "$provider_path_check")" ] && [ -z "$(grep '"payload":' "$provider_path_check")" ] && [ -z "$(grep 'payload:' "$provider_path_check")" ]; then
provider_path_exist=0
fi
elif [ "$2" = "rule_provider" ]; then
provider_path_exist=0
fi
fi
done
done
fi
if [ -z "$(pidof clash)" ] && [ "$provider_path_exist" = 0 ]; then
kill_clash
stop
if [ "$2" = "proxy_provider" ]; then
echo "错误: 代理集文件下载失败,请到日志页面查看详细错误信息!" >$START_LOG
echo "${LOGTIME} Faild to Download Proxy-Provider File, Please Check The Error Info And Try Again" >> $LOG_FILE
else
echo "错误: 规则集文件下载失败,请到日志页面查看详细错误信息!" >$START_LOG
echo "${LOGTIME} Faild to Download Rule-Provider File, Please Check The Error Info And Try Again" >> $LOG_FILE
fi
sleep 10
echo "" >$START_LOG
exit 0
fi
}
#切割配置文件以分开处理
yml_cut()
{
cp "$4" "$1"
sed -i '/^rules:/,$d' "$1" 2>/dev/null
sed -n '/^ \{0,\}nameserver:/,$p' "$1" >"$3" 2>/dev/null
if [ "$proxy_provider_mode" -eq 1 ]; then
sed -n '/^ \{0,\}proxy-groups:/,$p' "$3" >"$7" 2>/dev/null
sed -n '/^ \{0,\}Proxy:/,$p' "$3" >"$5" 2>/dev/null
sed -n '/^ \{0,\}proxy-providers:/,$p' "$3" >"$6" 2>/dev/null
sed -i '/^ \{0,\}proxy-groups:/,$d' "$5" 2>/dev/null
sed -i '/^ \{0,\}Proxy:/,$d' "$6" 2>/dev/null
sed -i '/^ \{0,\}proxy-groups:/,$d' "$6" 2>/dev/null
else
sed -n '/^ \{0,\}proxy-groups:/,$p' "$3" >"$7" 2>/dev/null
sed -n '/^ \{0,\}Proxy:/,$p' "$3" >"$5" 2>/dev/null
sed -i '/^ \{0,\}proxy-groups:/,$d' "$5" 2>/dev/null
fi 2>/dev/null
sed -i '/^ \{0,\}nameserver:/,$d' "$1" 2>/dev/null
if [ "$proxy_provider_mode" -eq 1 ]; then
sed -i '/^ \{0,\}proxy-providers:/,$d' "$3" 2>/dev/null
else
sed -i '/^ \{0,\}Proxy:/,$d' "$3" 2>/dev/null
fi 2>/dev/null
sed -n '/^rules:/,$p' "$4" >"$2" 2>/dev/null
}
#获取自定义DNS设置
yml_dns_get()
{
local section="$1"
local enabled port type ip group dns_type dns_address
config_get_bool "enabled" "$section" "enabled" "1"
config_get "port" "$section" "port" ""
config_get "type" "$section" "type" ""
config_get "ip" "$section" "ip" ""
config_get "group" "$section" "group" ""
if [ "$enabled" = "0" ]; then
return
fi
if [ -z "$ip" ]; then
return
fi
if [ "$type" = "tcp" ]; then
dns_type="- tcp://"
elif [ "$type" = "tls" ]; then
dns_type="- tls://"
elif [ "$type" = "udp" ]; then
dns_type="- "
elif [ "$type" = "https" ]; then
dns_type="- https://"
fi
if [ -n "$port" ] && [ -n "$ip" ]; then
dns_address="$ip:$port"
elif [ -z "$port" ] && [ -n "$ip" ]; then
dns_address="$ip"
else
return
fi
if [ -n "$group" ]; then
if [ "$group" = "nameserver" ]; then
echo " $dns_type$dns_address" >>/etc/openclash/config.namedns
else
if [ -z "$(grep "fallback:$" /etc/openclash/config.falldns 2>/dev/null)" ]; then
echo " fallback:" >/etc/openclash/config.falldns
fi
echo " $dns_type$dns_address" >>/etc/openclash/config.falldns
fi
else
return
fi
}
#添加自定义DNS设置
yml_dns_custom()
{
if [ "$1" = 1 ]; then
echo " nameserver:" >/etc/openclash/config.namedns
config_load "openclash"
config_foreach yml_dns_get "dns_servers"
sed -i '/^ \{0,\}nameserver:/i\##Custom DNS##' "$2" 2>/dev/null
sed -i '/OpenClash-General-Settings/i\Custom DNS End' "$2" 2>/dev/null
sed -i '/^ \{0,\}nameserver:/,/^Custom DNS End$/d' "$2" 2>/dev/null
sed -i '/##Custom DNS##/r/etc/openclash/config.falldns' "$2" 2>/dev/null
sed -i '/##Custom DNS##/r/etc/openclash/config.namedns' "$2" 2>/dev/null
rm -rf /etc/openclash/config.namedns 2>/dev/null
rm -rf /etc/openclash/config.falldns 2>/dev/null
else
sed -i "/^ \{0,\}nameserver:/c\ nameserver:" "$2" 2>/dev/null
sed -i "/^ \{0,\}fallback:/c\ fallback:" "$2" 2>/dev/null
fi
#fallback-filter
if [ -n "$(grep "^ \{0,\}fallback:" "$2")" ]; then
if [ -z "$(grep "^ \{0,\}fallback-filter:" "$2")" ]; then
awk '/^ {0,}fallback:/,/OpenClash-General-Settings/{print}' "$2" |sed '1d' |sed '$d' >/tmp/fallback.cache 2>/dev/null
sed -i '/cfw-bypass:/,$d' /tmp/fallback.cache 2>/dev/null
sed -i '/cfw-latency-timeout:/,$d' /tmp/fallback.cache 2>/dev/null
sed -i '/fallback:/,$d' "$2" 2>/dev/null
echo " fallback:" >>"$2"
sed -i '/ fallback:/a\ - 240.0.0.0/4' "$2" 2>/dev/null
sed -i '/ fallback:/a\ ipcidr:' "$2" 2>/dev/null
sed -i '/ fallback:/a\ geoip: true' "$2" 2>/dev/null
sed -i '/ fallback:/a\ fallback-filter:' "$2" 2>/dev/null
sed -i '/ fallback:/r/tmp/fallback.cache' "$2" 2>/dev/null
rm -rf /tmp/fallback.cache 2>/dev/null
echo "#===================== OpenClash-General-Settings =====================#" >>"$2"
else
if [ -z "$(grep "^ fallback-filter:" "$2")" ]; then
sed -i "/fallback-filter:/c\ fallback-filter:" "$2" 2>/dev/null
fi
if [ -z "$(grep "^ geoip: true" "$2")" ]; then
sed -i "/geoip: true/c\ geoip: true" "$2" 2>/dev/null
fi
if [ -z "$(grep "^ ipcidr:" "$2")" ]; then
sed -i "/ipcidr:/c\ ipcidr:" "$2" 2>/dev/null
fi
fi
if [ -z "$(grep "^ - " "$2")" ]; then
sed -i '/^ \{0,\}nameserver:/,/^ \{0,\}fallback-filter:/ {s/^ \{0,\}- / - /}' "$2" 2>/dev/null #修改参数空格
fi
if [ -z "$(grep "^ - " "$2")" ]; then
sed -i '/^ \{0,\}ipcidr:/,/OpenClash-General-Settings/ {s/^ \{0,\}- / - /}' "$2" 2>/dev/null #修改参数空格
fi
#删除fallback-filter
else
if [ -n "$(grep "^ \{0,\}fallback-filter:" "$2")" ]; then
sed -i '/fallback-filter:/,$d' "$2" 2>/dev/null
echo "#===================== OpenClash-General-Settings =====================#" >>"$2"
fi
if [ -n "$(grep "^ \{0,1\}- " "$2")" ]; then
#添加参数空格
sed -i "s/^ \{0,\}- / - /" "$2" 2>/dev/null
fi
fi
}
#获取认证信息
yml_auth_get()
{
local section="$1"
local enabled username password
config_get_bool "enabled" "$section" "enabled" "1"
config_get "username" "$section" "username" ""
config_get "password" "$section" "password" ""
if [ "$enabled" = "0" ]; then
return
fi
if [ -z "$username" ] || [ -z "$password" ]; then
return
else
echo " - $username:$password" >>/etc/openclash/config.auth
fi
}
#添加认证信息
yml_auth_custom()
{
if [ -n "$(grep "^authentication:" "$1")" ]; then
sed -i '/^dns:/i\#authentication' "$1" 2>/dev/null
sed -i '/^authentication:/,/^#authentication/d' "$1" 2>/dev/null
fi
if [ -f /etc/openclash/config.auth ]; then
sed -i '/^dns:/i\authentication:' "$1" 2>/dev/null
sed -i '/^authentication:/r/etc/openclash/config.auth' "$1" 2>/dev/null
mv /etc/openclash/config.auth /tmp/openclash.auth 2>/dev/null
else
rm -rf /tmp/openclash.auth 2>/dev/null
fi
}
get_rule_file()
{
if [ -z "$1" ]; then
return
fi
GAME_RULE_FILE_NAME=$(grep "^$1," /etc/openclash/game_rules.list |awk -F ',' '{print $3}' 2>/dev/null)
if [ -z "$GAME_RULE_FILE_NAME" ]; then
GAME_RULE_FILE_NAME=$(grep "^$1," /etc/openclash/game_rules.list |awk -F ',' '{print $2}' 2>/dev/null)
fi
GAME_RULE_PATH="/etc/openclash/game_rules/$GAME_RULE_FILE_NAME"
sed '/^#/d' "$GAME_RULE_PATH" 2>/dev/null |sed '/^ *$/d' |awk '{print "- IP-CIDR,"$0}' |awk -v tag="$2" '{print $0","'tag'""}' >> $GAME_RULE_FILE 2>/dev/null
set_rule_file=1
}
yml_game_rule_get()
{
local section="$1"
local enabled group config
config_get_bool "enabled" "$section" "enabled" "1"
config_get "group" "$section" "group" ""
config_get "config" "$section" "config" ""
if [ "$enabled" = "0" ]; then
return
fi
if [ -n "$config" ] && [ "$config" != "$CONFIG_NAME" ] && [ "$config" != "all" ]; then
return
fi
if [ -z "$group" ]; then
return
fi
config_list_foreach "$section" "rule_name" get_rule_file "$group"
}
yml_rule_group_get()
{
local section="$1"
local enabled group config
config_get_bool "enabled" "$section" "enabled" "1"
config_get "group" "$section" "group" ""
config_get "config" "$section" "config" ""
if [ "$enabled" = "0" ]; then
return
fi
if [ -n "$config" ] && [ "$config" != "$CONFIG_NAME" ] && [ "$config" != "all" ]; then
return
fi
if [ -z "$group" ]; then
return
fi
/usr/share/openclash/yml_groups_set.sh "$group"
}
yml_game_custom()
{
#处理游戏规则
rm -rf $GAME_RULE_FILE 2>/dev/null
config_load "openclash"
config_foreach yml_game_rule_get "game_config"
if [ -n "$(grep "OpenClash-Game-Rules" "$RULE_FILE")" ]; then
sed -i '/OpenClash-Game-Rules/,/OpenClash-Game-Rules-End/d' "$RULE_FILE" 2>/dev/null
fi
sed -i '/OpenClash-Game-Rules/d' "$RULE_FILE" 2>/dev/null
sed -i '/OpenClash-Game-Rules-End/d' "$RULE_FILE" 2>/dev/null
[ "$set_rule_file" = 1 ] && {
if [ -n "$(grep "##Custom Rules 2##" "$RULE_FILE")" ]; then
sed -i "/##Custom Rules 2##/i\#===================== OpenClash-Game-Rules =====================#" "$RULE_FILE" 2>/dev/null
elif [ -n "$(grep "^ \{0,\}- GEOIP" "$RULE_FILE")" ]; then
sed -i '1,/^ \{0,\}- GEOIP,/{/^ \{0,\}- GEOIP,/s/^ \{0,\}- GEOIP,/#===================== OpenClash-Game-Rules =====================#\n&/}' "$RULE_FILE" 2>/dev/null
elif [ -n "$(grep "^ \{0,\}- MATCH," "$RULE_FILE")" ]; then
sed -i '1,/^ \{0,\}- MATCH,/{/^ \{0,\}- MATCH,/s/^ \{0,\}- MATCH,/#===================== OpenClash-Game-Rules =====================#\n&/}' "$RULE_FILE" 2>/dev/null
elif [ -n "$(grep "^ \{0,\}- FINAL," "$RULE_FILE")" ]; then
sed -i '1,/^ \{0,\}- FINAL,/{/^ \{0,\}- FINAL,/s/^ \{0,\}- FINAL,/#===================== OpenClash-Game-Rules =====================#\n&/}' "$RULE_FILE" 2>/dev/null
else
echo "#===================== OpenClash-Game-Rules =====================#" >> "$RULE_FILE" 2>/dev/null
fi
echo "#===================== OpenClash-Game-Rules-End =====================#" >> $GAME_RULE_FILE
sed -i '/OpenClash-Game-Rules/r/tmp/yaml_game_rule_group.yaml' "$RULE_FILE" 2>/dev/null
}
#合并文件
cat "$CHANGE_FILE" "$DNS_FILE" "$PROXY_PROVIDER_FILE" "$PROXY_FILE" "$GROUP_FILE" "$RULE_PROVIDER_FILE" "$SCRIPT_FILE" "$RULE_FILE" > "$CONFIG_FILE" 2>/dev/null
#处理游戏节点与策略组
config_load "openclash"
config_foreach yml_rule_group_get "rule_provider_config"
config_foreach yml_rule_group_get "game_config"
sed -i '/^ \{0,\}proxy-groups:/r/tmp/yaml_groups.yaml' "$CONFIG_FILE" 2>/dev/null
sed -i '/^ \{0,\}Proxy:/d' /tmp/yaml_servers.yaml 2>/dev/null
sed -i '/^ \{0,\}proxy-providers:/d' /tmp/yaml_provider.yaml 2>/dev/null
if [ -z "$(grep "^ \{0,\}Proxy:" "$CONFIG_FILE" 2>/dev/null)" ] && [ -f "/tmp/yaml_servers.yaml" ]; then
sed -i '/^ \{0,\}proxy-groups:/i\Proxy:' "$CONFIG_FILE" 2>/dev/null
sed -i '/^ \{0,\}Proxy:/r/tmp/yaml_servers.yaml' "$CONFIG_FILE" 2>/dev/null
elif [ -f "/tmp/yaml_servers.yaml" ]; then
sed -i '/^ \{0,\}Proxy:/r/tmp/yaml_servers.yaml' "$CONFIG_FILE" 2>/dev/null
fi
if [ -z "$(grep "^ \{0,\}proxy-providers:" "$CONFIG_FILE" 2>/dev/null)" ] && [ -f "/tmp/yaml_provider.yaml" ]; then
sed -i '/OpenClash-General-Settings/a\proxy-providers:' "$CONFIG_FILE" 2>/dev/null
sed -i '/^ \{0,\}proxy-providers:/r/tmp/yaml_provider.yaml' "$CONFIG_FILE" 2>/dev/null
elif [ -f "/tmp/yaml_servers.yaml" ]; then
sed -i '/^ \{0,\}proxy-providers:r/tmp/yaml_provider.yaml' "$CONFIG_FILE" 2>/dev/null
fi
}
yml_rule_set_add()
{
if [ -z "$(grep "rules:" "$RULE_FILE" 2>/dev/null)" ]; then
echo "rules:" > "$RULE_FILE"
fi
if [ "$3" -eq 1 ]; then
if [ -z "$(grep "OpenClash-Rule-Set-Extended-End" "$RULE_FILE" 2>/dev/null)" ]; then
if [ -n "$(grep "##Custom Rules 2##" "$RULE_FILE")" ]; then
sed -i "/##Custom Rules 2##/i\#===================== OpenClash-Rule-Set-Extended-End =====================#" "$RULE_FILE" 2>/dev/null
sed -i "/OpenClash-Rule-Set-Extended-End/i\#===================== OpenClash-Rule-Set-Extended =====================#" "$RULE_FILE" 2>/dev/null
elif [ -n "$(grep "^ \{0,\}- GEOIP" "$RULE_FILE")" ]; then
sed -i '1,/^ \{0,\}- GEOIP,/{/^ \{0,\}- GEOIP,/s/^ \{0,\}- GEOIP,/#===================== OpenClash-Rule-Set-Extended-End =====================#\n&/}' "$RULE_FILE" 2>/dev/null
sed -i "/OpenClash-Rule-Set-Extended-End/i\#===================== OpenClash-Rule-Set-Extended =====================#" "$RULE_FILE" 2>/dev/null
elif [ -n "$(grep "^ \{0,\}- MATCH," "$RULE_FILE")" ]; then
sed -i '1,/^ \{0,\}- MATCH,/{/^ \{0,\}- MATCH,/s/^ \{0,\}- MATCH,/#===================== OpenClash-Rule-Set-Extended-End =====================#\n&/}' "$RULE_FILE" 2>/dev/null
sed -i "/OpenClash-Rule-Set-Extended-End/i\#===================== OpenClash-Rule-Set-Extended =====================#" "$RULE_FILE" 2>/dev/null
elif [ -n "$(grep "^ \{0,\}- FINAL," "$RULE_FILE")" ]; then
sed -i '1,/^ \{0,\}- FINAL,/{/^ \{0,\}- FINAL,/s/^ \{0,\}- FINAL,/#===================== OpenClash-Rule-Set-Extended-End =====================#\n&/}' "$RULE_FILE" 2>/dev/null
sed -i "/OpenClash-Rule-Set-Extended-End/i\#===================== OpenClash-Rule-Set-Extended =====================#" "$RULE_FILE" 2>/dev/null
else
echo "#===================== OpenClash-Rule-Set-Extended =====================#" >> "$RULE_FILE" 2>/dev/null
echo "#===================== OpenClash-Rule-Set-Extended-End =====================#" >> "$RULE_FILE" 2>/dev/null
fi
fi
sed -i "/OpenClash-Rule-Set-Extended-End/i\- RULE-SET,${1},${2}" "$RULE_FILE" 2>/dev/null
elif [ "$3" -eq 0 ]; then
if [ -z "$(grep "OpenClash-Rule-Set-Priority-End" "$RULE_FILE" 2>/dev/null)" ]; then
if [ -n "$(grep "##Custom Rules##" "$RULE_FILE" 2>/dev/null)" ]; then
sed -i "/##Custom Rules End##/a\#===================== OpenClash-Rule-Set-Priority-End =====================#" "$RULE_FILE" 2>/dev/null
sed -i "/##Custom Rules End##/a\#===================== OpenClash-Rule-Set-Priority =====================#" "$RULE_FILE" 2>/dev/null
else
sed -i "/^rules:/a\#===================== OpenClash-Rule-Set-Priority-End =====================#" "$RULE_FILE" 2>/dev/null
sed -i "/^rules:/a\#===================== OpenClash-Rule-Set-Priority =====================#" "$RULE_FILE" 2>/dev/null
fi
fi
sed -i "/OpenClash-Rule-Set-Priority-End/i\- RULE-SET,${1},${2}" "$RULE_FILE" 2>/dev/null
fi
}
yml_gen_rule_provider_file()
{
if [ -z "$1" ]; then
return
fi
RULE_PROVIDER_FILE_NAME=$(grep "^$1," /etc/openclash/rule_providers.list |awk -F ',' '{print $6}' 2>/dev/null)
if [ -z "$RULE_PROVIDER_FILE_NAME" ]; then
RULE_PROVIDER_FILE_NAME=$(grep "^$1," /etc/openclash/rule_providers.list |awk -F ',' '{print $5}' 2>/dev/null)
fi
RULE_PROVIDER_FILE_BEHAVIOR=$(grep -F "$RULE_PROVIDER_FILE_NAME" /etc/openclash/rule_providers.list |awk -F ',' '{print $3}' 2>/dev/null)
RULE_PROVIDER_FILE_PATH="/etc/openclash/rule_provider/$RULE_PROVIDER_FILE_NAME"
RULE_PROVIDER_FILE_URL="https://raw.githubusercontent.com/$(grep -F "$RULE_PROVIDER_FILE_NAME" /etc/openclash/rule_providers.list |awk -F ',' '{print $4$5}' 2>/dev/null)"
if [ -n "$(grep "$RULE_PROVIDER_FILE_URL" $RULE_PROVIDER_FILE)" ]; then
return
fi
if [ -z "$(grep "rule-providers:" $RULE_PROVIDER_FILE 2>/dev/null)" ]; then
echo "rule-providers:" > "$RULE_PROVIDER_FILE"
fi
if [ -z "$(grep "OpenClash-Rule-Providers-Set" $RULE_PROVIDER_FILE 2>/dev/null)" ]; then
echo "#===================== OpenClash-Rule-Providers-Set =====================#" >> "$RULE_PROVIDER_FILE"
fi
cat >> "$RULE_PROVIDER_FILE" <<-EOF
$1:
type: http
behavior: $RULE_PROVIDER_FILE_BEHAVIOR
path: $RULE_PROVIDER_FILE_PATH
url: $RULE_PROVIDER_FILE_URL
EOF
if [ -z "$3" ]; then
cat >> "$RULE_PROVIDER_FILE" <<-EOF
interval=86400
EOF
else
cat >> "$RULE_PROVIDER_FILE" <<-EOF
interval: $3
EOF
fi
yml_rule_set_add "$1" "$2" "$4"
}
yml_get_rule_provider()
{
local section="$1"
local enabled group config interval position
config_get_bool "enabled" "$section" "enabled" "1"
config_get "group" "$section" "group" ""
config_get "config" "$section" "config" ""
config_get "interval" "$section" "interval" ""
config_get "position" "$section" "position" ""
if [ "$enabled" = "0" ]; then
return
fi
if [ -n "$config" ] && [ "$config" != "$CONFIG_NAME" ] && [ "$config" != "all" ]; then
return
fi
if [ -z "$group" ]; then
return
fi
config_list_foreach "$section" "rule_name" yml_gen_rule_provider_file "$group" "$interval" "$position"
}
#处理自定义规则集
yml_set_custom_rule_provider()
{
local section="$1"
local enabled name config type behavior path url interval group position
config_get_bool "enabled" "$section" "enabled" "1"
config_get "name" "$section" "name" ""
config_get "config" "$section" "config" ""
config_get "type" "$section" "type" ""
config_get "behavior" "$section" "behavior" ""
config_get "path" "$section" "path" ""
config_get "url" "$section" "url" ""
config_get "interval" "$section" "interval" ""
config_get "group" "$section" "group" ""
config_get "position" "$section" "position" ""
if [ "$enabled" = "0" ]; then
return
fi
if [ -n "$(grep "$url" "$RULE_PROVIDER_FILE")" ] && [ -n "$url" ]; then
return
fi
if [ -n "$config" ] && [ "$config" != "$CONFIG_NAME" ] && [ "$config" != "all" ]; then
return
fi
if [ -z "$name" ] || [ -z "$type" ] || [ -z "$behavior" ]; then
return
fi
if [ "$type" = "http" ] && [ -z "$url" ]; then
return
fi
if [ "$path" != "./rule_provider/$name.yaml" ] && [ "$type" = "http" ]; then
path="./rule_provider/$name.yaml"
elif [ -z "$path" ]; then
return
fi
if [ -n "$(grep "$path" "$RULE_PROVIDER_FILE")" ]; then
return
fi
if [ -z "$interval" ] && [ "$type" = "http" ]; then
interval=86400
fi
if [ -z "$(grep "rule-providers:" "$RULE_PROVIDER_FILE" 2>/dev/null)" ]; then
echo "rule-providers:" > "$RULE_PROVIDER_FILE"
fi
if [ -z "$(grep "OpenClash-Rule-Providers-Set" "$RULE_PROVIDER_FILE" 2>/dev/null)" ]; then
echo "#===================== OpenClash-Rule-Providers-Set =====================#" >> "$RULE_PROVIDER_FILE"
fi
cat >> "$RULE_PROVIDER_FILE" <<-EOF
$name:
type: $type
behavior: $behavior
path: $path
EOF
if [ "$type" = "http" ]; then
cat >> "$RULE_PROVIDER_FILE" <<-EOF
url: $url
interval: $interval
EOF
fi
yml_rule_set_add "$name" "$group" "$position"
}
#处理规则集
yml_custom_rule_provider()
{
if [ -n "$(grep "OpenClash-Rule-Set-Extended-End" "$RULE_FILE")" ]; then
sed -i '/OpenClash-Rule-Set-Extended/,/OpenClash-Rule-Set-Extended-End/d' "$RULE_FILE" 2>/dev/null
fi
if [ -n "$(grep "OpenClash-Rule-Set-Priority-End" "$RULE_FILE")" ]; then
sed -i '/OpenClash-Rule-Set-Priority/,/OpenClash-Rule-Set-Priority-End/d' "$RULE_FILE" 2>/dev/null
fi
if [ -n "$(grep "OpenClash-Rule-Providers-Set" "$RULE_PROVIDER_FILE")" ]; then
sed -i '/OpenClash-Rule-Providers-Set/,/OpenClash-Rule-Providers-Set-End/d' "$RULE_PROVIDER_FILE" 2>/dev/null
fi
sed -i '/OpenClash-Rule-Set/d' "$RULE_FILE" 2>/dev/null
sed -i '/OpenClash-Rule-Providers/d' "$RULE_PROVIDER_FILE" 2>/dev/null
if [ -z "$(grep "^ type:" $RULE_PROVIDER_FILE 2>/dev/null)" ]; then
#处理缩进
sed -i '/^ *$/d' "$RULE_PROVIDER_FILE" 2>/dev/null
sed -i 's/\t/ /g' "$RULE_PROVIDER_FILE" 2>/dev/null
sed -i 's/^ \{1,\}/ /g' "$RULE_PROVIDER_FILE" 2>/dev/null
sed -i 's/^ \{1,\}type:/ type:/g' "$RULE_PROVIDER_FILE" 2>/dev/null
sed -i 's/^ \{1,\}behavior:/ behavior:/g' "$RULE_PROVIDER_FILE" 2>/dev/null
sed -i 's/^ \{1,\}path:/ path:/g' "$RULE_PROVIDER_FILE" 2>/dev/null
sed -i 's/^ \{1,\}url:/ url:/g' "$RULE_PROVIDER_FILE" 2>/dev/null
sed -i 's/^ \{1,\}interval:/ interval:/g' "$RULE_PROVIDER_FILE" 2>/dev/null
sed -i 's/^ \{1,\}rule-providers:/rule-providers:/g' "$RULE_PROVIDER_FILE" 2>/dev/null
fi
config_load "openclash"
config_foreach yml_get_rule_provider "rule_provider_config"
config_foreach yml_set_custom_rule_provider "rule_providers"
if [ -n "$(grep "OpenClash-Rule-Providers-Set" $RULE_PROVIDER_FILE 2>/dev/null)" ]; then
echo "#===================== OpenClash-Rule-Providers-Set-End =====================#" >> "$RULE_PROVIDER_FILE"
fi
}
lan_ac()
{
if [ -z "$1" ]; then
return
fi
ipset add "$2" "$1" 2>/dev/null
}
firewall_redirect_exclude()
{
local section="$1"
local src_dport
config_get "src_dport" "$section" "src_dport" ""
if [ -z "$src_dport" ]; then
return
fi
if [ -z "$en_mode_tun" ]; then
iptables -t mangle -A openclash -p udp --dport "$src_dport" -j RETURN >/dev/null 2>&1
else
iptables -t mangle -A openclash -p tcp --dport "$src_dport" -j RETURN >/dev/null 2>&1
iptables -t mangle -A openclash -p udp --dport "$src_dport" -j RETURN >/dev/null 2>&1
fi
}
#配置文件选择
config_choose()
{
if [ -z "$CONFIG_FILE" ] || [ ! -f "$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 set openclash.config.config_path="/etc/openclash/config/$CONFIG_NAME"
uci commit openclash
CONFIG_FILE="/etc/openclash/config/$CONFIG_NAME"
elif [ -f "/etc/openclash/config.yaml" ]; then
mv "/etc/openclash/config.yaml" "/etc/openclash/config/config.yaml"
uci set openclash.config.config_path="/etc/openclash/config/config.yaml"
uci commit openclash
CONFIG_FILE="/etc/openclash/config/config.yaml"
elif [ -f "/etc/openclash/config.yml" ]; then
mv "/etc/openclash/config.yml" "/etc/openclash/config/config.yaml"
uci set openclash.config.config_path="/etc/openclash/config/config.yaml"
uci commit openclash
CONFIG_FILE="/etc/openclash/config/config.yaml"
fi
else
if [ ! -f "$CONFIG_FILE" ] && [ -f "$BACKUP_FILE" ]; then
cp "$BACKUP_FILE" "$CONFIG_FILE"
fi
fi 2>/dev/null
CONFIG_NAME=$(echo "$CONFIG_FILE" |awk -F '/' '{print $5}' 2>/dev/null)
}
#运行模式处理
do_run_mode()
{
en_mode=$(uci get openclash.config.en_mode 2>/dev/null)
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-vpn" ]; then
en_mode_tun="2"
en_mode="redir-host"
fi
if [ "$en_mode" = "fake-ip-vpn" ]; then
en_mode_tun="2"
en_mode="fake-ip"
fi
}
do_run_core()
{
if [ ! -h "/etc/openclash/clash" ] && [ -s "/etc/openclash/clash" ] && [ ! -s "/etc/openclash/core/clash" ]; then
mv "/etc/openclash/clash" "/etc/openclash/core/clash" 2>/dev/null
fi
rm -rf "/etc/openclash/clash" 2>/dev/null
if [ "$en_mode_tun" = "1" ]; then
ln -s /etc/openclash/core/clash_tun /etc/openclash/clash 2>/dev/null
core_type="Tun"
fi
if [ "$en_mode_tun" = "1" ]; then
ln -s /etc/openclash/core/clash_tun /etc/openclash/clash 2>/dev/null
core_type="Tun"
fi
if [ "$en_mode_tun" = "2" ]; then
ln -s /etc/openclash/core/clash_game /etc/openclash/clash 2>/dev/null
core_type="Game"
fi
if [ "$en_mode_tun" = "2" ]; then
ln -s /etc/openclash/core/clash_game /etc/openclash/clash 2>/dev/null
core_type="Game"
fi
if [ "$proxy_mode" = "Script" ] || [ "$rule_source" = "ConnersHua" ]; then
ln -s /etc/openclash/core/clash_tun /etc/openclash/clash 2>/dev/null
core_type="Tun"
fi
if [ -n "$(grep "^ \{0,\}rule-providers:" "$RULE_PROVIDER_FILE" 2>/dev/null)" ] && [ -n "$(grep "^ \{0,\}behavior" "$RULE_PROVIDER_FILE" 2>/dev/null |grep -v "^ \{0,\}#")" ]; then
ln -s /etc/openclash/core/clash_tun /etc/openclash/clash 2>/dev/null
core_type="Tun"
fi
if [ ! -f "/etc/openclash/clash" ] && [ -f "/etc/openclash/core/clash" ] && [ -z "$core_type" ]; then
ln -s /etc/openclash/core/clash /etc/openclash/clash 2>/dev/null
fi
#权限检查
[ ! -x "/etc/openclash/core/clash_tun" ] && chmod 4755 /etc/openclash/core/clash_tun 2>/dev/null
[ ! -x "/etc/openclash/core/clash_game" ] && chmod 4755 /etc/openclash/core/clash_game 2>/dev/null
[ ! -x "/etc/openclash/core/clash" ] && chmod 4755 /etc/openclash/core/clash 2>/dev/null
}
set_firewall()
{
if [ "$(iptables -t nat -nL PREROUTING --line-number |grep "udp dpt:53" |grep "0.0.0.0/0 \{0,\}0.0.0.0/0" |wc -l)" -gt 1 ] && [ "$enable_redirect_dns" -eq "1" ]; then
echo "发现53端口被劫持清理防火墙规则..." >$START_LOG
pre_lines=$(iptables -nvL PREROUTING -t nat |sed 1,2d |sed -n '/0.0.0.0\/0 \{0,\}0.0.0.0\/0 \{0,\}udp dpt:53/=' 2>/dev/null |sort -rn)
for pre_line in $pre_lines; do
iptables -t nat -D PREROUTING "$pre_line" >/dev/null 2>&1
done
iptables -t nat -A PREROUTING -p udp --dport 53 -j REDIRECT --to-ports 53 >/dev/null 2>&1
sleep 2
fi
if [ -z "$(uci get firewall.openclash 2>/dev/null)" ] || [ -z "$(uci get ucitrack.@openclash[-1].init 2>/dev/null)" ]; then
uci delete ucitrack.@openclash[-1] >/dev/null 2>&1
uci add ucitrack openclash >/dev/null 2>&1
uci set ucitrack.@openclash[-1].init=openclash >/dev/null 2>&1
uci commit ucitrack >/dev/null 2>&1
uci delete firewall.openclash >/dev/null 2>&1
uci set firewall.openclash=include >/dev/null 2>&1
uci set firewall.openclash.type=script >/dev/null 2>&1
uci set firewall.openclash.path=/var/etc/openclash.include >/dev/null 2>&1
uci set firewall.openclash.reload=1 >/dev/null 2>&1
fi
if [ "$(uci get firewall.@defaults[0].forward)" != "ACCEPT" ]; then
uci set firewall.@defaults[0].forward=ACCEPT >/dev/null 2>&1
uci commit firewall >/dev/null 2>&1
/etc/init.d/firewall reload >/dev/null 2>&1
fi
mkdir -p /var/etc
cat > "/var/etc/openclash.include" <<-EOF
/etc/init.d/openclash reload >/dev/null 2>&1
EOF
#lan_ac
if [ "$operation_mode" = "redir-host" ] && [ "$en_mode" = "redir-host" ]; then
if [ "$lan_ac_mode" = "0" ] && [ -n "$(uci get openclash.config.lan_ac_black_ips 2>/dev/null)" ]; then
ipset create lan_ac_black_ips hash:net
config_load "openclash"
config_list_foreach "config" "lan_ac_black_ips" lan_ac "lan_ac_black_ips"
elif [ "$lan_ac_mode" = "1" ] && [ -n "$(uci get openclash.config.lan_ac_white_ips 2>/dev/null)" ]; then
ipset create lan_ac_white_ips hash:net
config_load "openclash"
config_list_foreach "config" "lan_ac_white_ips" lan_ac "lan_ac_white_ips"
fi
fi
#local
ipset create localnetwork hash:net
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
if [ -n "$wan_ip4" ]; then
for wan_ip4s in $wan_ip4; do
ipset add localnetwork "$wan_ip4s" 2>/dev/null
done
fi
if [ -z "$en_mode_tun" ]; then
#tcp
iptables -t nat -N openclash
iptables -t nat -F openclash
iptables -t nat -A openclash -m set --match-set localnetwork dst -j RETURN
iptables -t nat -A openclash -m 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_white_ips src -j RETURN >/dev/null 2>&1
iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
iptables -t nat -I PREROUTING -p tcp -d 8.8.8.8 -j REDIRECT --to-ports "$proxy_port"
iptables -t nat -I PREROUTING -p tcp -d 8.8.4.4 -j REDIRECT --to-ports "$proxy_port"
iptables -t nat -A PREROUTING -p tcp -j openclash
#udp
if [ "$enable_udp_proxy" -eq 1 ]; then
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 -A openclash -m set --match-set localnetwork dst -j RETURN
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 -p udp --dport 53 -j RETURN >/dev/null 2>&1
#端口转发
config_load "firewall"
config_foreach firewall_redirect_exclude "redirect"
iptables -t mangle -A openclash -p udp -j TPROXY --on-port "$proxy_port" --on-ip 0.0.0.0 --tproxy-mark "$PROXY_FWMARK"
iptables -t mangle -A PREROUTING -p udp -j openclash
fi
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 -p tcp -d 198.18.0.0/16 -j REDIRECT --to-ports "$proxy_port"
iptables -t nat -A OUTPUT -p tcp -j openclash_output
fi
if [ "$ipv6_enable" -eq 1 ]; then
#tcp
ip6tables -t nat -N openclash
if [ -n "$lan_ip6" ]; then
for lan_ip6s in $lan_ip6; do
ip6tables -t nat -A openclash -d "$lan_ip6s" -j RETURN 2>/dev/null
done
fi
ip6tables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
ip6tables -t nat -A PREROUTING -p tcp -j openclash
#udp
#if [ "$enable_udp_proxy" -eq 1 ]; then
# ip6tables -t mangle -N openclash
# if [ -n "$lan_ip6" ]; then
# for lan_ip6s in $lan_ip6; do
# if [ "$enable_udp_proxy" -eq 1 ]; then
# ip6tables -t mangle -A openclash -d "$lan_ip6s" -j RETURN 2>/dev/null
# fi
# done
# fi
# ip6tables -t mangle -A openclash -p udp -j TPROXY --on-port "$proxy_port" --tproxy-mark "$PROXY_FWMARK"
# ip6tables -t mangle -A PREROUTING -p udp -j openclash
#fi
fi 2>/dev/null
else
#TUN模式
#启动TUN
if [ "$en_mode_tun" = "2" ]; then
ip tuntap add user root mode tun clash0
ip link set clash0 up
ip route replace default dev clash0 table "$PROXY_ROUTE_TABLE"
elif [ "$en_mode_tun" = "1" ]; then
TUN_WAIT=0
while ( [ -n "$(pidof clash)" ] && [ -z "$(ip route list |grep utun)" ] && [ "$TUN_WAIT" -le 3 ] )
do
TUN_WAIT=$(expr "$TUN_WAIT" + 1)
sleep 2
done
ip route replace default dev utun table "$PROXY_ROUTE_TABLE"
fi
ip rule add fwmark "$PROXY_FWMARK" table "$PROXY_ROUTE_TABLE"
#设置防火墙
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
if [ "$en_mode" = "fake-ip" ]; then
iptables -t mangle -A openclash_output -d 198.18.0.0/16 -j MARK --set-mark "$PROXY_FWMARK"
fi
iptables -t mangle -I OUTPUT -j openclash_output
iptables -t mangle -N openclash
iptables -t mangle -F openclash
#端口转发
config_load "firewall"
config_foreach firewall_redirect_exclude "redirect"
#其他流量
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 localnetwork dst -j MARK --set-mark "$PROXY_FWMARK"
iptables -t mangle -I PREROUTING -j openclash
iptables -t nat -I PREROUTING -p tcp --dport 53 -j ACCEPT
#ipv6
# if [ "$ipv6_enable" -eq 1 ]; then
# ip6tables -t mangle -I PREROUTING -j MARK --set-mark "$PROXY_FWMARK"
# fi
fi
}
revert_firewall()
{
rm -rf /var/etc/openclash.include 2>/dev/null
#ipv4
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
iptables -t nat -D PREROUTING -p tcp --dport 53 -j ACCEPT >/dev/null 2>&1
out_lines=$(iptables -nvL OUTPUT -t nat |sed 1,2d |sed -n '/openclash/=' 2>/dev/null |sort -rn)
for out_line in $out_lines; do
iptables -t nat -D OUTPUT "$out_line" >/dev/null 2>&1
done >/dev/null 2>&1
iptables -t nat -D OUTPUT -p tcp -j openclash_output >/dev/null 2>&1
pre_lines=$(iptables -nvL PREROUTING -t nat |sed 1,2d |sed -n '/8\.8\./=' 2>/dev/null |sort -rn)
for pre_line in $pre_lines; do
iptables -t nat -D PREROUTING "$pre_line" >/dev/null 2>&1
done >/dev/null 2>&1
pre_lines=$(iptables -nvL PREROUTING -t mangle |sed 1,2d |sed -n '/openclash/=' 2>/dev/null |sort -rn)
for pre_line in $pre_lines; do
iptables -t mangle -D PREROUTING "$pre_line" >/dev/null 2>&1
done >/dev/null 2>&1
iptables -t mangle -D PREROUTING -p udp -j openclash >/dev/null 2>&1
pre_lines=$(iptables -nvL PREROUTING -t nat |sed 1,2d |sed -n '/openclash/=' 2>/dev/null |sort -rn)
for pre_line in $pre_lines; do
iptables -t nat -D PREROUTING "$pre_line" >/dev/null 2>&1
done >/dev/null 2>&1
iptables -t nat -D PREROUTING -p tcp -j openclash >/dev/null 2>&1
#ipv6
#ip6tables -t mangle -F openclash >/dev/null 2>&1
#ip6tables -t mangle -D PREROUTING -p udp -j openclash >/dev/null 2>&1
#ip6tables -t mangle -X openclash >/dev/null 2>&1
iptables -t nat -F openclash >/dev/null 2>&1
iptables -t nat -X openclash >/dev/null 2>&1
iptables -t nat -F openclash_output >/dev/null 2>&1
iptables -t nat -X openclash_output >/dev/null 2>&1
ip6tables -t nat -F openclash >/dev/null 2>&1
ip6tables -t nat -D PREROUTING -p tcp -j openclash >/dev/null 2>&1
ip6tables -t nat -X openclash >/dev/null 2>&1
#TUN
ip route del default dev clash0 table "$PROXY_ROUTE_TABLE" >/dev/null 2>&1
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
ip link set dev clash0 down >/dev/null 2>&1
ip tuntap del clash0 mode tun >/dev/null 2>&1
iptables -t mangle -D OUTPUT -j openclash_output >/dev/null 2>&1
iptables -t mangle -D PREROUTING -j openclash >/dev/null 2>&1
iptables -t mangle -F openclash >/dev/null 2>&1
iptables -t mangle -X openclash >/dev/null 2>&1
iptables -t mangle -F openclash_output >/dev/null 2>&1
iptables -t mangle -X openclash_output >/dev/null 2>&1
#ip6tables -t mangle -D PREROUTING -j MARK --set-mark "$PROXY_FWMARK" >/dev/null 2>&1
ipset destroy localnetwork >/dev/null 2>&1
ipset destroy lan_ac_white_ips >/dev/null 2>&1
ipset destroy lan_ac_black_ips >/dev/null 2>&1
}
get_config()
{
proxy_mode=$(uci get openclash.config.proxy_mode 2>/dev/null)
rule_source=$(uci get openclash.config.rule_source 2>/dev/null)
enable_custom_dns=$(uci get openclash.config.enable_custom_dns 2>/dev/null)
enable_custom_clash_rules=$(uci get openclash.config.enable_custom_clash_rules 2>/dev/null)
da_password=$(uci get openclash.config.dashboard_password 2>/dev/null)
cn_port=$(uci get openclash.config.cn_port 2>/dev/null)
proxy_port=$(uci get openclash.config.proxy_port 2>/dev/null)
ipv6_enable=$(uci get openclash.config.ipv6_enable 2>/dev/null)
http_port=$(uci get openclash.config.http_port 2>/dev/null)
socks_port=$(uci get openclash.config.socks_port 2>/dev/null)
enable_redirect_dns=$(uci get openclash.config.enable_redirect_dns 2>/dev/null)
lan_ip=$(uci get network.lan.ipaddr 2>/dev/null |awk -F '/' '{print $1}' 2>/dev/null)
wan_ip4=$(ifconfig | grep 'inet addr' | awk '{print $2}' | cut -d: -f2 2>/dev/null)
lan_ip6=$(ifconfig | grep 'inet6 addr' | awk '{print $3}' 2>/dev/null)
disable_masq_cache=$(uci get openclash.config.disable_masq_cache 2>/dev/null)
log_level=$(uci get openclash.config.log_level 2>/dev/null)
intranet_allowed=$(uci get openclash.config.intranet_allowed 2>/dev/null)
enable_udp_proxy=$(uci get openclash.config.enable_udp_proxy 2>/dev/null)
operation_mode=$(uci get openclash.config.operation_mode 2>/dev/null)
lan_ac_mode=$(uci get openclash.config.lan_ac_mode 2>/dev/null)
enable_rule_proxy=$(uci get openclash.config.enable_rule_proxy 2>/dev/null)
stack_type=$(uci get openclash.config.stack_type 2>/dev/null)
}
start()
{
#禁止多个实例
status=$(ps|grep -c /etc/init.d/openclash)
[ "$status" -gt "3" ] && exit 0
config_choose
enable=$(uci get openclash.config.enable 2>/dev/null)
if [ "$enable" -eq 1 ] && [ -f "$CONFIG_FILE" ]; then
do_run_mode
echo "OpenClash 开始启动..." >$START_LOG
echo "第一步: 获取配置..." >$START_LOG
get_config
echo "第二步: 配置文件检查..." >$START_LOG
yml_check "$en_mode" "$enable_custom_dns" "$CONFIG_FILE" "$BACKUP_FILE" "$START_BACKUP"
if [ -n "$(grep "^ \{0,\}proxy-groups:" "$CONFIG_FILE")" ]; then
if [ -z "$(grep "^ \{0,\}Proxy:" "$CONFIG_FILE" 2>/dev/null)" ] && [ -z "$(grep "^ \{0,\}proxy-providers:" "$CONFIG_FILE" 2>/dev/null)" ]; then
kill_clash
stop
echo "错误: 配置文件完整性检查不通过,已自动还原配置文件,请对照模板格式检查修改配置文件!" >$START_LOG
mv "$START_BACKUP" "$CONFIG_FILE"
sleep 5
echo "" >$START_LOG
elif [ -z "$(grep "^ \{0,\}rules:" "$CONFIG_FILE" 2>/dev/null)" ] && [ -z "$(grep "^ \{0,\}script:" "$CONFIG_FILE" 2>/dev/null)" ]; then
kill_clash
stop
echo "错误: 配置文件完整性检查不通过,已自动还原配置文件,请对照模板格式检查修改配置文件!" >$START_LOG
mv "$START_BACKUP" "$CONFIG_FILE"
sleep 5
echo "" >$START_LOG
else
echo "第三步: 修改配置文件..." >$START_LOG
config_load "openclash"
config_foreach yml_auth_get "authentication"
yml_auth_custom "$CONFIG_FILE"
yml_cut "$CHANGE_FILE" "$RULE_FILE" "$DNS_FILE" "$CONFIG_FILE" "$PROXY_FILE" "$PROXY_PROVIDER_FILE" "$GROUP_FILE"
yml_dns_custom "$enable_custom_dns" "$DNS_FILE"
/usr/share/openclash/yml_change.sh >/dev/null 2>&1 "$LOGTIME" "$en_mode" "$enable_custom_dns" "$da_password" "$cn_port" "$proxy_port" "$CHANGE_FILE" "$ipv6_enable" "$http_port" "$socks_port" "$lan_ip" "$log_level" "$proxy_mode" "$intranet_allowed" "$en_mode_tun" "$stack_type" &
/usr/share/openclash/yml_rules_change.sh >/dev/null 2>&1 "$LOGTIME" "$rule_source" "$enable_custom_clash_rules" "$RULE_FILE" "$set_rule_file" "$en_mode" "$enable_rule_proxy" "$BACKUP_FILE" "$RULE_PROVIDER_FILE" &
wait
yml_provider_path "$PROXY_PROVIDER_FILE" "proxy_provider"
yml_provider_path "$RULE_PROVIDER_FILE" "rule_provider"
yml_custom_rule_provider
yml_game_custom
echo "第四步: DNS设置检查..." >$START_LOG
if [ -n "$(sed -n '/^ \{0,\}nameserver:/{n;p}' "$CONFIG_FILE" |grep '^ \{0,\}fallback:')" ] || [ -n "$(sed -n '/^ \{0,\}nameserver:/{n;p}' "$CONFIG_FILE" |grep 'OpenClash-General')" ]; then
kill_clash
stop
echo "错误: 配置文件DNS选项下的Nameserver必须设置服务器已自动还原配置文件请重新设置" >$START_LOG
echo "${LOGTIME} Nameserver Must Be Set, Please Change Your Configrations In Config.yaml" >>$LOG_FILE
mv "$START_BACKUP" "$CONFIG_FILE"
sleep 10
echo "" >$START_LOG
else
echo "第五步: 启动主程序..." >$START_LOG
#检查是否存在核心文件
do_run_core
[ ! -f "$CLASH" ] && {
kill_clash
stop
echo "内核文件不存在,开始下载..." >$START_LOG
nohup /usr/share/openclash/openclash_core.sh "$core_type" &
exit 0
}
sed -i "s/^ \{0,\}Proxy:/proxies:/g" "$CONFIG_FILE" 2>/dev/null
ulimit -SHn 65535 2>/dev/null
config_reload=$(uci get openclash.config.config_reload 2>/dev/null)
if [ -n "$(pidof clash)" ] && [ "$core_type" != "Tun" ] && [ "$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
nohup "$CLASH" -d "$CLASH_CONFIG" -f "$CONFIG_FILE" >> $LOG_FILE 2>&1 &
fi
uci set openclash.config.config_reload=1 2>/dev/null
uci commit openclash
#检测proxy_provider配置文件状态
echo "第六步: 等待主程序下载外部文件..." >$START_LOG
yml_provider_check "$PROXY_PROVIDER_FILE" "proxy_provider"
yml_provider_check "$RULE_PROVIDER_FILE" "rule_provider"
echo "第七步: 设置控制面板..." >$START_LOG
ln -s /usr/share/openclash/yacd /www/luci-static/openclash 2>/dev/null
echo "第八步: 设置防火墙规则..." >$START_LOG
set_firewall
echo "第九步: 重启 Dnsmasq 程序..." >$START_LOG
change_dns "$enable_redirect_dns" "$disable_masq_cache"
/etc/init.d/dnsmasq restart >/dev/null 2>&1
if pidof clash >/dev/null; then
echo "第十步: 还原策略组节点状态..." >$START_LOG
/usr/share/openclash/openclash_history_set.sh
echo "第十一步: 添加计划任务,启动进程守护程序..." >$START_LOG
add_cron
if [ -z "$(uci get dhcp.lan.dhcpv6 2>/dev/null)" ]; then
echo "OpenClash 启动成功,请等待服务器上线!" >$START_LOG
echo "${LOGTIME} OpenClash Start Successful" >> $LOG_FILE
sleep 5
else
echo "OpenClash 启动成功检测到您启用了IPV6的DHCP服务可能会造成连接异常" >$START_LOG
echo "${LOGTIME} OpenClash Start Successful, Please Note That Network May Abnormal With IPV6's DHCP Server" >> $LOG_FILE
sleep 10
fi
echo "OpenClash Already Start"
echo "" >$START_LOG
else
if [ "$rule_source" != 0 ] || [ "$enable_custom_clash_rules" != 0 ]; then
echo "错误: OpenClash 启动失败,尝试还原第三方规则并重新启动 Clash 主程序..." >$START_LOG
echo "${LOGTIME} OpenClash Can Not Start, Try Use Backup Rules Start Again" >> $LOG_FILE
mv "$START_BACKUP" /tmp/configrules.bak
sed -i -n '/^rules:/,$p' /tmp/configrules.bak
sed -i '/^rules:/,$d' "$CONFIG_FILE" 2>/dev/null
sed -i '/##Other-rule-providers##/,/##Other-rule-providers-end##/d' "$CONFIG_FILE" 2>/dev/null
cat /tmp/configrules.bak >> "$CONFIG_FILE"
rm -rf /tmp/configrules.bak
nohup "$CLASH" -d "$CLASH_CONFIG" -f "$CONFIG_FILE" >> $LOG_FILE 2>&1 &
sleep 3
if pidof clash >/dev/null; then
/usr/share/openclash/openclash_history_set.sh
add_cron
if [ -z "$(uci get dhcp.lan.dhcpv6 2>/dev/null)" ]; then
echo "OpenClash 使用备份规则启动成功,请更新、检查变动的规则后重试!" >$START_LOG
echo "${LOGTIME} OpenClash Start Successful With Backup Rules Config, Please Check Or Update Other Rules And Retry" >> $LOG_FILE
sleep 10
else
echo "OpenClash 使用备份规则启动成功,请更新、检查变动的规则后重试!" >$START_LOG
echo "${LOGTIME} OpenClash Start Successful With Backup Rules Config, Please Check Or Update Other Rules And Retry" >> $LOG_FILE
sleep 5
echo "检测到您启用了IPV6的DHCP服务可能会造成连接异常" >$START_LOG
echo "${LOGTIME} OpenClash Start Successful, Please Note That Network May Abnormal With IPV6's DHCP Server" >> $LOG_FILE
sleep 10
fi
echo "OpenClash Already Start"
echo "" >$START_LOG
else
kill_clash
stop
echo "错误: OpenClash 启动失败,请到日志页面查看详细错误信息!" >$START_LOG
echo "${LOGTIME} OpenClash Can Not Start, Please Check The Error Info And Try Again" >> $LOG_FILE
sleep 10
echo "" >$START_LOG
fi
else
kill_clash
stop
echo "错误: OpenClash 启动失败,请到日志页面查看详细错误信息!" >$START_LOG
echo "${LOGTIME} OpenClash Can Not Start, Please Check The Error Info And Try Again" >> $LOG_FILE
sleep 10
echo "" >$START_LOG
fi
fi
fi
fi
else
nohup "$CLASH" -d "$CLASH_CONFIG" -f "$CONFIG_FILE" >> $LOG_FILE 2>&1 &
kill_clash
stop
echo "错误: 配置文件完整性检查不通过,已自动还原配置文件,请根据日志信息对照模板格式检查修改配置文件!" >$START_LOG
mv "$START_BACKUP" "$CONFIG_FILE"
sleep 5
echo "" >$START_LOG
fi
rm -rf $START_BACKUP 2>/dev/null
rm -rf /tmp/yaml_* 2>/dev/null
else
subscribe_info=$(uci get openclash.@config_subscribe[0].address 2>/dev/null)
if [ ! -f "$CONFIG_FILE" ] && [ -n "$subscribe_info" ]; then
kill_clash
stop
echo "OpenClash 配置文件不存在,开始下载..." >$START_LOG
nohup /usr/share/openclash/openclash.sh &
exit 0
elif [ ! -f "$CONFIG_FILE" ]; then
kill_clash
stop
echo "错误: OpenClash 缺少配置文件,请上传或更新配置文件!" >$START_LOG
echo "${LOGTIME} Config Not Found" >> $LOG_FILE
sleep 5
echo "" >$START_LOG
fi
fi
}
stop()
{
enable=$(uci get openclash.config.enable 2>/dev/null)
echo "OpenClash 开始关闭..." >$START_LOG
echo "第一步: 备份当前节点状态..." >$START_LOG
/usr/share/openclash/openclash_history_get.sh 2>/dev/null
echo "第二步: 删除 OpenClash 防火墙规则..." >$START_LOG
revert_firewall
echo "第三步: 关闭 OpenClash 守护程序..." >$START_LOG
watchdog_pids=$(ps |grep openclash_watchdog.sh |grep -v grep |awk '{print $1}' 2>/dev/null)
for watchdog_pid in $watchdog_pids; do
kill -9 "$watchdog_pid" >/dev/null 2>&1
done
echo "第四步: 关闭 Clash 主程序..." >$START_LOG
if [ "$enable" -eq 0 ]; then
kill_clash
fi
echo "第五步: 重启 Dnsmasq 程序..." >$START_LOG
dns_port=$(uci get openclash.config.dns_port 2>/dev/null)
redirect_dns=$(uci get openclash.config.redirect_dns 2>/dev/null)
masq_cache=$(uci get openclash.config.masq_cache 2>/dev/null)
revert_dns "$redirect_dns" "$masq_cache" "$dns_port"
/etc/init.d/dnsmasq restart >/dev/null 2>&1
echo "第六步:删除 OpenClash 残留文件..." >$START_LOG
if [ "$enable" -eq 0 ]; then
rm -rf $LOG_FILE 2>/dev/null
rm -rf /tmp/openclash_debug.log 2>/dev/null
rm -rf /www/luci-static/openclash 2>/dev/null
rm -rf /tmp/openclash_last_version 2>/dev/null
rm -rf /tmp/clash_last_version 2>/dev/null
rm -rf /tmp/Proxy_Group 2>/dev/null
rm -rf /tmp/rules_name 2>/dev/null
echo "OpenClash 关闭成功!" >$START_LOG
sleep 5
fi
rm -rf /tmp/yaml_* 2>/dev/null
rm -rf $START_LOG 2>/dev/null
del_cron
echo "OpenClash Already Stop"
}
restart()
{
stop
start
}
reload()
{
if pidof clash >/dev/null; then
revert_firewall 2>/dev/null
do_run_mode 2>/dev/null
get_config 2>/dev/null
set_firewall 2>/dev/null
echo "${LOGTIME} OpenClash Reload After Firewall Restart" >> $LOG_FILE
fi
}