mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-05 01:44:16 +08:00
⛄ Sync 2026-06-30 01:11:33
This commit is contained in:
1 parent
fb3826f4ad
commit
a09508c01e
157 files changed
+78873
-73698
No files matched your search
@@ -56,6 +56,7 @@ config openclash 'config'
|
||||
option yacd_type 'Meta'
|
||||
option append_default_dns '0'
|
||||
option enable_respect_rules '0'
|
||||
option default_dashboard 'metacubexd'
|
||||
option geo_custom_url 'https://testingcf.jsdelivr.net/gh/alecthw/mmdb_china_ip_list@release/lite/Country.mmdb'
|
||||
option geosite_custom_url 'https://testingcf.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geosite.dat'
|
||||
option geoip_custom_url 'https://testingcf.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/geoip.dat'
|
||||
|
||||
@@ -102,6 +102,11 @@ load_ip_route_pass() {
|
||||
if [ "$china_ip_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
|
||||
if [ "$enable_redirect_dns" != "2" ]; then
|
||||
mkdir -p ${DNSMASQ_CONF_DIR}
|
||||
if [ "$settype" = "nftset" ]; then
|
||||
nft add set inet fw4 china_ip_route_pass '{ type ipv4_addr; flags interval; auto-merge; }'
|
||||
else
|
||||
ipset -! create china_ip_route_pass hash:net family inet hashsize 1024 maxelem 1000000
|
||||
fi
|
||||
awk '!/^$/&&!/^#/&&!/(^([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("'${settype}'=/%s/'${nftflag}'china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
|
||||
for ip in $(uci_get_config "china_ip_route_pass"); do
|
||||
[ -z "$ip" ] && continue
|
||||
@@ -114,6 +119,11 @@ load_ip_route_pass() {
|
||||
if [ "$china_ip6_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
|
||||
if [ "$enable_redirect_dns" != "2" ]; then
|
||||
mkdir -p ${DNSMASQ_CONF_DIR}
|
||||
if [ "$settype" = "nftset" ]; then
|
||||
nft add set inet fw4 china_ip6_route_pass '{ type ipv6_addr; flags interval; auto-merge; }'
|
||||
else
|
||||
ipset -! create china_ip6_route_pass hash:net family inet6 hashsize 1024 maxelem 1000000
|
||||
fi
|
||||
awk '!/^$/&&!/^#/&&/([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/{printf("'${settype}'=/%s/'${nftflag}'china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
|
||||
for ip in $(uci_get_config "china_ip6_route_pass"); do
|
||||
[ -z "$ip" ] && continue
|
||||
@@ -142,6 +152,7 @@ load_ip_route_pass() {
|
||||
if [ "$china_ip_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
|
||||
if [ "$enable_redirect_dns" != "2" ]; then
|
||||
mkdir -p ${DNSMASQ_CONF_DIR}
|
||||
ipset -! create china_ip_route_pass hash:net family inet hashsize 1024 maxelem 1000000
|
||||
awk '!/^$/&&!/^#/&&!/(^([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)(([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){2}([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4])((\/[0-9][0-9])?)$/{printf("ipset=/%s/china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
|
||||
for ip in $(uci_get_config "china_ip_route_pass"); do
|
||||
[ -z "$ip" ] && continue
|
||||
@@ -154,6 +165,7 @@ load_ip_route_pass() {
|
||||
if [ "$china_ip6_route" != "0" ] || [ "$disable_udp_quic" = "1" ]; then
|
||||
if [ "$enable_redirect_dns" != "2" ]; then
|
||||
mkdir -p ${DNSMASQ_CONF_DIR}
|
||||
ipset -! create china_ip6_route_pass hash:net family inet6 hashsize 1024 maxelem 1000000
|
||||
awk '!/^$/&&!/^#/&&/([0-9a-zA-Z-]{1,}\.)+([a-zA-Z]{2,})/{printf("ipset=/%s/china_ip_route_pass'" "'\n",$0)}' /etc/openclash/custom/openclash_custom_chnroute6_pass.list >>${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
|
||||
for ip in $(uci_get_config "china_ip6_route_pass"); do
|
||||
[ -z "$ip" ] && continue
|
||||
@@ -172,7 +184,7 @@ load_ip_route_pass() {
|
||||
fi
|
||||
}
|
||||
|
||||
change_dns() {
|
||||
change_dnsmasq() {
|
||||
if ! /etc/init.d/dnsmasq enabled; then
|
||||
return
|
||||
fi
|
||||
@@ -184,13 +196,15 @@ change_dns() {
|
||||
/usr/share/openclash/openclash_custom_domain_dns.sh
|
||||
|
||||
if [ "$1" -eq 1 ]; then
|
||||
uci -q del openclash.config.dnsmasq_server
|
||||
config_load "dhcp"
|
||||
config_list_foreach "$(uci -q show dhcp.@dnsmasq[0].server |awk -F '.' '{print $2}')" "server" save_dnsmasq_server
|
||||
if [ "$(uci_get_config "redirect_dns")" != "1" ]; then
|
||||
uci -q del openclash.config.dnsmasq_server
|
||||
config_load "dhcp"
|
||||
config_list_foreach "$(uci -q show dhcp.@dnsmasq[0].server |awk -F '.' '{print $2}')" "server" save_dnsmasq_server
|
||||
uci -q 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)"
|
||||
fi
|
||||
uci -q del dhcp.@dnsmasq[-1].server
|
||||
uci -q add_list dhcp.@dnsmasq[0].server=127.0.0.1#"$dns_port"
|
||||
uci -q set openclash.config.dnsmasq_noresolv="$(uci -q get dhcp.@dnsmasq[0].noresolv)"
|
||||
uci -q set openclash.config.dnsmasq_resolvfile="$(uci -q get dhcp.@dnsmasq[0].resolvfile)"
|
||||
uci -q delete dhcp.@dnsmasq[0].resolvfile
|
||||
uci -q set dhcp.@dnsmasq[0].noresolv=1
|
||||
uci -q set dhcp.@dnsmasq[0].localuse=1
|
||||
@@ -212,33 +226,44 @@ change_dns() {
|
||||
uci -q set openclash.config.filter_aaaa_dns=0
|
||||
fi
|
||||
|
||||
uci -q commit dhcp
|
||||
uci -q commit openclash
|
||||
uci -q commit dhcp
|
||||
/etc/init.d/dnsmasq restart
|
||||
} >/dev/null 2>&1
|
||||
|
||||
revert_dns() {
|
||||
revert_dnsmasq()
|
||||
{
|
||||
if ! /etc/init.d/dnsmasq enabled; then
|
||||
return
|
||||
fi
|
||||
|
||||
redirect_dns=$(uci_get_config "redirect_dns")
|
||||
dnsmasq_server=$(uci_get_config "dnsmasq_server")
|
||||
dnsmasq_noresolv=$(uci_get_config "dnsmasq_noresolv")
|
||||
dnsmasq_resolvfile=$(uci_get_config "dnsmasq_resolvfile")
|
||||
cachesize_dns=$(uci_get_config "cachesize_dns")
|
||||
dnsmasq_cachesize=$(uci_get_config "dnsmasq_cachesize")
|
||||
filter_aaaa_dns=$(uci_get_config "filter_aaaa_dns")
|
||||
dnsmasq_filter_aaaa=$(uci_get_config "dnsmasq_filter_aaaa")
|
||||
default_resolvfile=$(uci_get_config "default_resolvfile")
|
||||
|
||||
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_custom_domain.conf
|
||||
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute_pass.conf
|
||||
rm -rf ${DNSMASQ_CONF_DIR}/dnsmasq_openclash_chnroute6_pass.conf
|
||||
|
||||
[ "$1" -eq 1 ] && {
|
||||
[ "$redirect_dns" -eq 1 ] && {
|
||||
uci -q del dhcp.@dnsmasq[-1].server
|
||||
[ -n "${10}" ] && {
|
||||
[ -n "$dnsmasq_server" ] && {
|
||||
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
|
||||
if [ "$dnsmasq_noresolv" == "0" ] || [ -z "$dnsmasq_noresolv" ] || [ -z "$(uci -q show dhcp.@dnsmasq[0].server)" ]; then
|
||||
uci -q set dhcp.@dnsmasq[0].noresolv=0
|
||||
if [ -n "$5" ] && [ -n "$(grep nameserver $5)" ]; then
|
||||
uci -q set dhcp.@dnsmasq[0].resolvfile="$5"
|
||||
elif [ -n "$3" ] && [ -n "$(grep nameserver $3)" ]; then
|
||||
uci -q set dhcp.@dnsmasq[0].resolvfile="$3"
|
||||
if [ -n "$dnsmasq_resolvfile" ] && [ -n "$(grep nameserver $dnsmasq_resolvfile)" ]; then
|
||||
uci -q set dhcp.@dnsmasq[0].resolvfile="$dnsmasq_resolvfile"
|
||||
elif [ -n "$default_resolvfile" ] && [ -n "$(grep nameserver $default_resolvfile)" ]; then
|
||||
uci -q set dhcp.@dnsmasq[0].resolvfile="$default_resolvfile"
|
||||
elif [ -s "/tmp/resolv.conf.d/resolv.conf.auto" ] && [ -n "$(grep "nameserver" /tmp/resolv.conf.d/resolv.conf.auto)" ]; then
|
||||
uci -q set dhcp.@dnsmasq[0].resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
|
||||
uci -q set openclash.config.default_resolvfile=/tmp/resolv.conf.d/resolv.conf.auto
|
||||
@@ -253,19 +278,19 @@ revert_dns() {
|
||||
fi
|
||||
}
|
||||
|
||||
[ "$6" -eq 1 ] && {
|
||||
uci -q set dhcp.@dnsmasq[0].cachesize="$7"
|
||||
[ "$cachesize_dns" -eq 1 ] && {
|
||||
uci -q set dhcp.@dnsmasq[0].cachesize="$dnsmasq_cachesize"
|
||||
uci -q set openclash.config.cachesize_dns=0
|
||||
uci -q delete openclash.config.dnsmasq_cachesize
|
||||
}
|
||||
|
||||
[ "$8" -eq 1 ] && {
|
||||
uci -q set dhcp.@dnsmasq[0].filter_aaaa="$9"
|
||||
[ "$filter_aaaa_dns" -eq 1 ] && {
|
||||
uci -q set dhcp.@dnsmasq[0].filter_aaaa="$dnsmasq_filter_aaaa"
|
||||
uci -q set openclash.config.filter_aaaa_dns=0
|
||||
uci -q delete openclash.config.dnsmasq_filter_aaaa
|
||||
}
|
||||
|
||||
[ "$1" -eq 1 ] && {
|
||||
[ "$redirect_dns" -eq 1 ] && {
|
||||
uci -q set openclash.config.redirect_dns=0
|
||||
uci -q del openclash.config.dnsmasq_server
|
||||
}
|
||||
@@ -273,8 +298,6 @@ revert_dns() {
|
||||
uci -q commit dhcp
|
||||
uci -q commit openclash
|
||||
|
||||
/etc/init.d/dnsmasq restart
|
||||
|
||||
masq_port=$(uci -q get dhcp.@dnsmasq[0].port)
|
||||
if [ "$(nslookup www.apple.com 127.0.0.1:${masq_port} >/dev/null 2>&1 || echo $?)" = "1" ]; then
|
||||
resolv_file=$(uci -q get dhcp.@dnsmasq[0].resolvfile)
|
||||
@@ -302,9 +325,10 @@ nameserver 119.29.29.29
|
||||
nameserver 8.8.8.8
|
||||
EOF
|
||||
fi
|
||||
/etc/init.d/dnsmasq restart
|
||||
fi
|
||||
|
||||
/etc/init.d/dnsmasq restart
|
||||
|
||||
} >/dev/null 2>&1
|
||||
|
||||
start_fail()
|
||||
@@ -389,7 +413,7 @@ if [ -z "$RAW_CONFIG_FILE" ] || [ ! -f "$RAW_CONFIG_FILE" ]; then
|
||||
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"
|
||||
TMP_CONFIG_FILE="/tmp/$CONFIG_NAME"
|
||||
LOG_ERROR "Config Not Found, Switch Config File to【$RAW_CONFIG_FILE】"
|
||||
break
|
||||
fi
|
||||
@@ -512,12 +536,14 @@ do_run_file()
|
||||
chnr6_path="/etc/openclash/china_ip6_route.ipset"
|
||||
geosite_path="/etc/openclash/GeoSite.dat"
|
||||
geoip_path="/etc/openclash/GeoIP.dat"
|
||||
asn_path="/etc/openclash/ASN.mmdb"
|
||||
lgbm_path="/etc/openclash/Model.bin"
|
||||
mv "/tmp/etc/openclash/Country.mmdb" "$ipdb_path"
|
||||
mv "/tmp/etc/openclash/china_ip_route.ipset" "$chnr_path"
|
||||
mv "/tmp/etc/openclash/china_ip6_route.ipset" "$chnr6_path"
|
||||
mv "/tmp/etc/openclash/GeoSite.dat" "$geosite_path"
|
||||
mv "/tmp/etc/openclash/GeoIP.dat" "$geoip_path"
|
||||
mv "/tmp/etc/openclash/ASN.mmdb" "$asn_path"
|
||||
mv "/tmp/etc/openclash/Model.bin" "$lgbm_path"
|
||||
mv "/tmp/etc/openclash/core/" "/etc/openclash"
|
||||
if [ "$CACHE_PATH" != "/tmp/etc/openclash/cache.db" ]; then
|
||||
@@ -530,12 +556,14 @@ do_run_file()
|
||||
chnr6_path="/tmp/etc/openclash/china_ip6_route.ipset"
|
||||
geosite_path="/tmp/etc/openclash/GeoSite.dat"
|
||||
geoip_path="/tmp/etc/openclash/GeoIP.dat"
|
||||
asn_path="/tmp/etc/openclash/ASN.mmdb"
|
||||
lgbm_path="/tmp/etc/openclash/Model.bin"
|
||||
[ ! -h "/etc/openclash/Country.mmdb" ] && mv "/etc/openclash/Country.mmdb" "$ipdb_path"
|
||||
[ ! -h "/etc/openclash/china_ip_route.ipset" ] && mv "/etc/openclash/china_ip_route.ipset" "$chnr_path"
|
||||
[ ! -h "/etc/openclash/china_ip6_route.ipset" ] && mv "/etc/openclash/china_ip6_route.ipset" "$chnr6_path"
|
||||
[ ! -h "/etc/openclash/GeoSite.dat" ] && mv "/etc/openclash/GeoSite.dat" "$geosite_path"
|
||||
[ ! -h "/etc/openclash/GeoIP.dat" ] && mv "/etc/openclash/GeoIP.dat" "$geoip_path"
|
||||
[ ! -h "/etc/openclash/ASN.mmdb" ] && mv "/etc/openclash/ASN.mmdb" "$asn_path"
|
||||
[ ! -h "/etc/openclash/Model.bin" ] && mv "/etc/openclash/Model.bin" "$lgbm_path"
|
||||
mv "/etc/openclash/core/" "/tmp/etc/openclash"
|
||||
fi
|
||||
@@ -545,7 +573,9 @@ do_run_file()
|
||||
|
||||
ln -s "$meta_core_path" /etc/openclash/clash
|
||||
|
||||
if [ "$smart_enable" -eq 1 ] || [ "$core_type" == "Smart" ]; then
|
||||
if [ -n "$OIX_TOKEN" ]; then
|
||||
core_type="Oix"
|
||||
elif [ "$smart_enable" -eq 1 ] || [ "$core_type" == "Smart" ]; then
|
||||
core_type="Smart"
|
||||
else
|
||||
core_type="Meta"
|
||||
@@ -556,8 +586,8 @@ do_run_file()
|
||||
chown root:root "$CLASH"
|
||||
fi
|
||||
|
||||
[ ! -f "$CLASH" ] || { [ "$core_type" = "Smart" ] && [ -z "$($CLASH -v | grep 'smart')" ]; } && {
|
||||
LOG_TIP "Detected that the Core is not Installed, Ready to Download..."
|
||||
[ ! -f "$CLASH" ] || { [ "$core_type" = "Smart" ] && [ -z "$($CLASH -v | grep 'smart')" ]; } || { [ "$core_type" = "Oix" ] && [ -z "$($CLASH -v | grep 'oix')" ]; } && {
|
||||
LOG_TIP "【$core_type】Core is not Detected installed, Ready to Download..."
|
||||
rm -rf "/tmp/clash_last_version"
|
||||
/usr/share/openclash/openclash_core.sh "$core_type"
|
||||
if [ ! -f "$meta_core_path" ]; then
|
||||
@@ -618,6 +648,10 @@ do_run_file()
|
||||
ln -s "$chnr6_path" /etc/openclash/china_ip6_route.ipset
|
||||
}
|
||||
|
||||
[ -f "$asn_path" ] && [ "$small_flash_memory" = "1" ] && {
|
||||
ln -s "$asn_path" /etc/openclash/ASN.mmdb
|
||||
}
|
||||
|
||||
#Restore history cache
|
||||
if [ -f "$HISTORY_PATH" ]; then
|
||||
cmp -s "$CACHE_PATH" "$HISTORY_PATH"
|
||||
@@ -762,7 +796,7 @@ check_core_status()
|
||||
|
||||
# redirect dns setting after core started, prevent core dns lookup failure
|
||||
if [ "$1" == "start" ]; then
|
||||
change_dns "$enable_redirect_dns"
|
||||
change_dnsmasq "$enable_redirect_dns"
|
||||
set_firewall
|
||||
LOG_TIP "OpenClash Start Successful!"
|
||||
else
|
||||
@@ -787,6 +821,8 @@ start_run_core()
|
||||
chown root:root "$CLASH"
|
||||
procd_open_instance "openclash"
|
||||
procd_set_param env SAFE_PATHS=/usr/share/openclash:/etc/ssl
|
||||
procd_append_param env CLASH_AGE_SECRET_KEY="$SECRET_KEY"
|
||||
procd_append_param env OIX_TOKEN="$OIX_TOKEN"
|
||||
procd_set_param command /bin/sh -c "$CLASH -d $CLASH_CONFIG -f \"$CONFIG_FILE\" >> $LOG_FILE 2>&1"
|
||||
procd_set_param user "root"
|
||||
procd_set_param group "nogroup"
|
||||
@@ -1370,6 +1406,11 @@ if [ -n "$FW4" ]; then
|
||||
nft add rule inet fw4 openclash ip protocol tcp counter redirect to "$proxy_port"
|
||||
nft 'add rule inet fw4 dstnat meta nfproto {ipv4} ip protocol tcp counter jump openclash'
|
||||
|
||||
# Accept redirected traffic in input chain (needed when zone input policy is REJECT without DNAT rules)
|
||||
if [ -z "$(nft list chain inet fw4 input 2>/dev/null | grep 'ct status dnat accept')" ]; then
|
||||
nft insert rule inet fw4 input position 0 ct status dnat accept comment \"OpenClash Redirect Accept\"
|
||||
fi
|
||||
|
||||
if [ -z "$en_mode_tun" ]; then
|
||||
#udp
|
||||
if [ "$enable_udp_proxy" -eq 1 ]; then
|
||||
@@ -1464,6 +1505,11 @@ if [ -n "$FW4" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Accept TPROXY traffic in input chain (needed when zone input policy is REJECT)
|
||||
if [ -z "$(nft list chain inet fw4 input 2>/dev/null | grep 'OpenClash TPROXY Accept')" ]; then
|
||||
nft insert rule inet fw4 input position 0 meta mark "$PROXY_FWMARK" accept comment \"OpenClash TPROXY Accept\"
|
||||
fi
|
||||
|
||||
#router self proxy tcp
|
||||
if [ "$router_self_proxy" = "1" ] || ([ "$enable_redirect_dns" != "2" ] && [ "$en_mode" = "fake-ip" ]); then
|
||||
nft 'add chain inet fw4 openclash_output'
|
||||
@@ -2219,6 +2265,11 @@ if [ -z "$FW4" ]; then
|
||||
iptables -t nat -A openclash -p tcp -j REDIRECT --to-ports "$proxy_port"
|
||||
iptables -t nat -A PREROUTING -p tcp -j openclash
|
||||
|
||||
# Accept redirected traffic in input chain (needed when zone input policy is REJECT without DNAT rules)
|
||||
if [ -z "$(iptables-save -t filter 2>/dev/null | grep 'OpenClash Redirect Accept')" ]; then
|
||||
iptables -I INPUT -m conntrack --ctstate DNAT -j ACCEPT -m comment --comment "OpenClash Redirect Accept"
|
||||
fi
|
||||
|
||||
if [ -z "$en_mode_tun" ]; then
|
||||
#udp
|
||||
if [ "$enable_udp_proxy" -eq 1 ]; then
|
||||
@@ -2302,6 +2353,14 @@ if [ -z "$FW4" ]; then
|
||||
iptables -t mangle -A OUTPUT -p udp -j openclash_output
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# Accept TPROXY traffic in input chain (needed when zone input policy is REJECT)
|
||||
if [ -z "$(iptables -nL INPUT 2>/dev/null | grep 'OpenClash TPROXY Accept')" ]; then
|
||||
iptables -I INPUT -m mark --mark "$PROXY_FWMARK" -j ACCEPT -m comment --comment "OpenClash TPROXY Accept"
|
||||
fi
|
||||
|
||||
if [ -z "$en_mode_tun" ]; then
|
||||
#quic
|
||||
if [ "$disable_udp_quic" -eq 1 ]; then
|
||||
if [ "$china_ip_route" = "2" ]; then
|
||||
@@ -2584,6 +2643,11 @@ if [ -z "$FW4" ]; then
|
||||
ip6tables -t nat -A PREROUTING -p tcp -j openclash
|
||||
fi
|
||||
|
||||
# Accept redirected IPv6 traffic in input chain (needed when zone input policy is REJECT without DNAT rules)
|
||||
if [ -z "$(ip6tables-save -t filter 2>/dev/null | grep 'OpenClash Redirect Accept')" ]; then
|
||||
ip6tables -I INPUT -m conntrack --ctstate DNAT -j ACCEPT -m comment --comment "OpenClash Redirect Accept"
|
||||
fi
|
||||
|
||||
#TProxy & TUN & Redirect udp
|
||||
if [ "$enable_v6_udp_proxy" -eq 1 ] || [ "$ipv6_mode" -ne 1 ]; then
|
||||
ip6tables -t mangle -N openclash
|
||||
@@ -2655,6 +2719,11 @@ if [ -z "$FW4" ]; then
|
||||
|
||||
ip6tables -t mangle -A PREROUTING -j openclash
|
||||
|
||||
# Accept TPROXY IPv6 traffic in input chain (needed when zone input policy is REJECT)
|
||||
if [ -z "$(ip6tables-save -t filter 2>/dev/null | grep 'OpenClash TPROXY Accept')" ]; then
|
||||
ip6tables -I INPUT -m mark --mark "$PROXY_FWMARK" -j ACCEPT -m comment --comment "OpenClash TPROXY Accept"
|
||||
fi
|
||||
|
||||
#router self proxy
|
||||
if [ "$router_self_proxy" = "1" ]; then
|
||||
if [ "$ipv6_mode" -eq 1 ] || [ "$ipv6_mode" -eq 3 ]; then
|
||||
@@ -2987,6 +3056,8 @@ overwrite_file()
|
||||
EOF
|
||||
|
||||
allowed_keys_types="\
|
||||
AGE_SECRET_KEY:string \
|
||||
AGE_PUBLIC_KEY:string \
|
||||
APPEND_DEFAULT_DNS:int_bool \
|
||||
APPEND_WAN_DNS:int_bool \
|
||||
AUTO_SMART_SWITCH:int_bool \
|
||||
@@ -3118,6 +3189,11 @@ EOF
|
||||
echo "# --- overwrite source: ${name} (sid=${sid}) ---" >> "$overwrite_script"
|
||||
echo "export OPENCLASH_OVERWRITE_SID='${sid}'" >> "$overwrite_script"
|
||||
|
||||
cfg_name=$(basename "$(uci_get_config "config_path")" 2>/dev/null)
|
||||
age_config_name="${cfg_name%.*}"
|
||||
age_secret_key=""
|
||||
age_public_key=""
|
||||
|
||||
param=$(uci -q get openclash."$sid".param 2>/dev/null || echo '')
|
||||
if [ -n "$param" ]; then
|
||||
OLD_IFS="$IFS"
|
||||
@@ -3251,8 +3327,9 @@ EOF
|
||||
uci -q set openclash.@overwrite[0].config_path="$RAW_CONFIG_FILE"
|
||||
cfg_name=$(basename "$RAW_CONFIG_FILE" 2>/dev/null)
|
||||
if [ -n "$cfg_name" ]; then
|
||||
age_config_name="${cfg_name%.*}"
|
||||
CONFIG_FILE="/etc/openclash/${cfg_name}"
|
||||
TMP_CONFIG_FILE="/tmp/yaml_config_tmp_${cfg_name}"
|
||||
TMP_CONFIG_FILE="/tmp/${cfg_name}"
|
||||
fi
|
||||
elif printf "%s" "$key_u" | grep -q "^SUB_INFO_URL$"; then
|
||||
val_clean=$(printf "%s" "$val" | sed "s/^[[:space:]]*['\"]//;s/['\"][[:space:]]*$//")
|
||||
@@ -3265,6 +3342,16 @@ EOF
|
||||
uci -q set openclash.@subscribe_info[-1].name="${cfg_name%.*}"
|
||||
uci -q add_list openclash.@subscribe_info[-1].url="$url_key"
|
||||
fi
|
||||
elif printf "%s" "$key_u" | grep -q "^AGE_SECRET_KEY$"; then
|
||||
val_clean=$(printf "%s" "$val" | sed "s/^[[:space:]]*['\"]//;s/['\"][[:space:]]*$//")
|
||||
val_key=$(eval "echo \"$val_clean\"")
|
||||
[ -z "$val_key" ] && continue
|
||||
age_secret_key="$val_key"
|
||||
elif printf "%s" "$key_u" | grep -q "^AGE_PUBLIC_KEY$"; then
|
||||
val_clean=$(printf "%s" "$val" | sed "s/^[[:space:]]*['\"]//;s/['\"][[:space:]]*$//")
|
||||
val_key=$(eval "echo \"$val_clean\"")
|
||||
[ -z "$val_key" ] && continue
|
||||
age_public_key="$val_key"
|
||||
elif printf "%s" "$key_u" | grep -q "^RESTART$"; then
|
||||
val_clean=$(printf "%s" "$val" | sed "s/^[[:space:]]*['\"]//;s/['\"][[:space:]]*$//")
|
||||
val_key=$(eval "echo \"$val_clean\"")
|
||||
@@ -3295,6 +3382,10 @@ EOF
|
||||
fi
|
||||
done < "$file"
|
||||
|
||||
if [ -n "$age_config_name" ] && { [ -n "$age_secret_key" ] || [ -n "$age_public_key" ]; }; then
|
||||
uci_set_age_keys_by_name "$age_config_name" "$age_secret_key" "$age_public_key"
|
||||
fi
|
||||
|
||||
if [ -n "$yaml_content" ]; then
|
||||
LOG_TIP "Load YAML Override Block【YAML Block => $name】"
|
||||
|
||||
@@ -3377,7 +3468,10 @@ get_config()
|
||||
RAW_CONFIG_FILE=$(uci_get_config "config_path")
|
||||
CFG_NAME=$(basename "$RAW_CONFIG_FILE" 2>/dev/null)
|
||||
CONFIG_FILE="/etc/openclash/${CFG_NAME}"
|
||||
TMP_CONFIG_FILE="/tmp/yaml_config_tmp_${CFG_NAME}"
|
||||
TMP_CONFIG_FILE="/tmp/${CFG_NAME}"
|
||||
CFG_NO_EXT_NAME="${CFG_NAME%.*}"
|
||||
SECRET_KEY=$(uci_get_age_secret_keys "$CFG_NO_EXT_NAME")
|
||||
OIX_TOKEN=$(uci_get_config "oix_token")
|
||||
enable=$(uci_get_config "enable")
|
||||
enable_custom_clash_rules=$(uci_get_config "enable_custom_clash_rules")
|
||||
da_password=$(uci_get_config "dashboard_password")
|
||||
@@ -3662,20 +3756,6 @@ stop_service()
|
||||
echo "OpenClash Already Stop!"
|
||||
}
|
||||
|
||||
revert_dnsmasq()
|
||||
{
|
||||
redirect_dns=$(uci_get_config "redirect_dns")
|
||||
dnsmasq_server=$(uci_get_config "dnsmasq_server")
|
||||
dnsmasq_noresolv=$(uci_get_config "dnsmasq_noresolv")
|
||||
dnsmasq_resolvfile=$(uci_get_config "dnsmasq_resolvfile")
|
||||
cachesize_dns=$(uci_get_config "cachesize_dns")
|
||||
dnsmasq_cachesize=$(uci_get_config "dnsmasq_cachesize")
|
||||
filter_aaaa_dns=$(uci_get_config "filter_aaaa_dns")
|
||||
dnsmasq_filter_aaaa=$(uci_get_config "dnsmasq_filter_aaaa")
|
||||
default_resolvfile=$(uci_get_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"
|
||||
} >/dev/null 2>&1
|
||||
|
||||
restart()
|
||||
{
|
||||
echo "OpenClash Restart..."
|
||||
|
||||
+66108
-65849
File diff suppressed because it is too large.
Load diff
@@ -123,6 +123,8 @@
|
||||
# SKIP_PROXY_ADDRESS (跳过代理地址, 0: 禁用, 1: 启用)
|
||||
# SUB_INFO_URL (订阅信息 URL)
|
||||
# DOWNLOAD_FILE (下载外部文件到指定路径, need URL and path)
|
||||
# AGE_PUBLIC_KEY (指定配置文件的 AGE 公钥)
|
||||
# AGE_SECRET_KEY (指定配置文件的 AGE 私钥)
|
||||
# RESTART (模块更新后重启插件, true: 启用, false: 禁用)
|
||||
# =========================
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ uci -q commit firewall
|
||||
|
||||
mkdir -p /etc/openclash/config
|
||||
mkdir -p /etc/openclash/proxy_provider
|
||||
mkdir -p /etc/openclash/rule_provider
|
||||
mkdir -p /etc/openclash/core
|
||||
mkdir -p /etc/openclash/history
|
||||
mkdir -p /usr/share/openclash/backup/overwrite
|
||||
@@ -151,6 +152,7 @@ cp -f "/etc/openclash/custom/openclash_custom_overwrite.sh" "/usr/share/openclas
|
||||
cp -f "/etc/openclash/china_ip_route.ipset" "/usr/share/openclash/backup/china_ip_route.ipset" >/dev/null 2>&1
|
||||
cp -f "/etc/openclash/china_ip6_route.ipset" "/usr/share/openclash/backup/china_ip6_route.ipset" >/dev/null 2>&1
|
||||
cp -f "/etc/openclash/overwrite/default" "/usr/share/openclash/backup/overwrite/default" >/dev/null 2>&1
|
||||
cp -f "/etc/openclash/rule_provider/oc-cn-domain.mrs" "/usr/share/openclash/backup/oc-cn-domain.mrs" >/dev/null 2>&1
|
||||
|
||||
#Restore
|
||||
if [ -f "/tmp/openclash.bak" ]; then
|
||||
@@ -186,6 +188,10 @@ if [ -f "/tmp/openclash.bak" ]; then
|
||||
cp -rf "/tmp/pac/." "/www/luci-static/resources/openclash/pac/" >/dev/null 2>&1
|
||||
rm -rf "/tmp/pac/" >/dev/null 2>&1
|
||||
fi
|
||||
#oc-domain
|
||||
if [ -f "/etc/openclash/rule_provider/oc-cn-domain.mrs" ]; then
|
||||
cp -f "/usr/share/openclash/backup/oc-cn-domain.mrs" "/etc/openclash/rule_provider/oc-cn-domain.mrs" >/dev/null 2>&1
|
||||
fi
|
||||
rm -rf "/etc/openclash/openclash" >/dev/null 2>&1
|
||||
rm -rf "/tmp/openclash" >/dev/null 2>&1
|
||||
rm -rf "/tmp/openclash.bak" >/dev/null 2>&1
|
||||
|
||||
@@ -22,9 +22,47 @@ module YAML
|
||||
end
|
||||
|
||||
def self.load_file(filename, *args, **kwargs)
|
||||
yaml_content = File.read(filename)
|
||||
processed_content = fix_short_id_quotes(yaml_content)
|
||||
yaml_content = File.read(filename, mode: "r:bom|utf-8")
|
||||
|
||||
secret = nil
|
||||
if kwargs.key?(:secret)
|
||||
secret = kwargs.delete(:secret)
|
||||
end
|
||||
|
||||
if secret && secret.to_s.strip != "" && yaml_content.include?("BEGIN AGE ENCRYPTED FILE")
|
||||
begin
|
||||
decrypted = decrypt_content_with_secret(secret.to_s, yaml_content)
|
||||
if decrypted && !decrypted.empty? && !decrypted.include?("BEGIN AGE ENCRYPTED FILE")
|
||||
processed = fix_short_id_quotes(decrypted)
|
||||
return load(processed, *args, **kwargs)
|
||||
else
|
||||
LOG_WARN("【%s】Decrypted content empty or still encrypted" % [filename])
|
||||
end
|
||||
rescue => e
|
||||
LOG_WARN("Decrypt attempt failed:【%s】" % [e.message])
|
||||
end
|
||||
end
|
||||
|
||||
if (secret.nil? || secret.to_s.strip == "") && yaml_content.include?("BEGIN AGE ENCRYPTED FILE")
|
||||
keys = find_age_keys_for_filename(filename)
|
||||
(keys[:secrets] || []).each do |sec|
|
||||
begin
|
||||
decrypted = decrypt_content_with_secret(sec, yaml_content)
|
||||
if decrypted && !decrypted.empty? && !decrypted.include?("BEGIN AGE ENCRYPTED FILE")
|
||||
processed = fix_short_id_quotes(decrypted)
|
||||
return load(processed, *args, **kwargs)
|
||||
end
|
||||
rescue => e
|
||||
LOG_WARN("Decrypt attempt failed for a found secret:【%s】" % [e.message])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if yaml_content.include?("BEGIN AGE ENCRYPTED FILE")
|
||||
raise "Encrypted file: decryption failed for %s" % [filename]
|
||||
end
|
||||
|
||||
processed_content = fix_short_id_quotes(yaml_content)
|
||||
load(processed_content, *args, **kwargs)
|
||||
end
|
||||
|
||||
@@ -32,6 +70,45 @@ module YAML
|
||||
begin
|
||||
yaml_content = original_dump(obj, **options)
|
||||
processed = fix_short_id_quotes(yaml_content)
|
||||
public_key = nil
|
||||
fname = nil
|
||||
if options.key?(:public)
|
||||
public_key = options.delete(:public)
|
||||
end
|
||||
|
||||
if (!public_key || public_key.to_s.strip == "")
|
||||
if options.key?(:filename)
|
||||
fname = options.delete(:filename)
|
||||
elsif io && io.respond_to?(:path)
|
||||
fname = io.path
|
||||
elsif io && io.respond_to?(:to_path)
|
||||
fname = io.to_path
|
||||
end
|
||||
|
||||
if fname && fname.to_s.strip != ""
|
||||
keys = find_age_keys_for_filename(fname)
|
||||
public_key = keys[:publics].first if keys[:publics] && !keys[:publics].empty?
|
||||
end
|
||||
end
|
||||
|
||||
if public_key && public_key.to_s.strip != ""
|
||||
begin
|
||||
encrypted = encrypt_content_with_public(public_key.to_s, processed)
|
||||
if encrypted && !encrypted.empty?
|
||||
if io.nil?
|
||||
return encrypted
|
||||
elsif io.respond_to?(:write)
|
||||
io.write(encrypted)
|
||||
return io
|
||||
else
|
||||
return encrypted
|
||||
end
|
||||
end
|
||||
rescue => e
|
||||
LOG_WARN("Encrypt attempt failed:【%s】" % [e.message])
|
||||
end
|
||||
end
|
||||
|
||||
if io.nil?
|
||||
processed
|
||||
elsif io.respond_to?(:write)
|
||||
@@ -46,6 +123,77 @@ module YAML
|
||||
end
|
||||
end
|
||||
|
||||
def self.popen_stream(cmd, input, chunk_size: 64 * 1024)
|
||||
output = String.new
|
||||
IO.popen(cmd, 'r+', err: [:child, :out]) do |io|
|
||||
io.binmode
|
||||
writer = Thread.new do
|
||||
begin
|
||||
input.bytesize.times do |i|
|
||||
chunk = input.byteslice(i * chunk_size, chunk_size)
|
||||
break if chunk.nil?
|
||||
io.write(chunk)
|
||||
end
|
||||
io.close_write
|
||||
rescue Errno::EPIPE
|
||||
end
|
||||
end
|
||||
|
||||
while chunk = io.read(chunk_size)
|
||||
output << chunk
|
||||
end
|
||||
writer.join
|
||||
end
|
||||
[output, $?]
|
||||
end
|
||||
|
||||
def self.decode64(input)
|
||||
out, status = popen_stream(["base64", "-d"], input)
|
||||
status.success? ? out : input
|
||||
rescue Errno::ENOENT
|
||||
input
|
||||
end
|
||||
|
||||
def self.find_age_keys_for_filename(filename)
|
||||
begin
|
||||
basename = File.basename(filename)
|
||||
basename_no_ext = File.basename(filename, File.extname(filename))
|
||||
publics = []
|
||||
secrets = []
|
||||
|
||||
[basename, basename_no_ext].uniq.each do |n|
|
||||
cmd_public = ["/bin/sh", "-c", ". /usr/share/openclash/uci.sh; uci_get_age_public_keys \"$1\"", "sh", n]
|
||||
IO.popen(cmd_public, "r") do |io|
|
||||
io.each_line { |l| publics << l.strip unless l.nil? || l.strip == "" }
|
||||
end
|
||||
|
||||
cmd_secret = ["/bin/sh", "-c", ". /usr/share/openclash/uci.sh; uci_get_age_secret_keys \"$1\"", "sh", n]
|
||||
IO.popen(cmd_secret, "r") do |io|
|
||||
io.each_line { |l| secrets << l.strip unless l.nil? || l.strip == "" }
|
||||
end
|
||||
end
|
||||
{ publics: publics, secrets: secrets }
|
||||
rescue => e
|
||||
{ publics: [], secrets: [] }
|
||||
end
|
||||
end
|
||||
|
||||
def self.decrypt_content_with_secret(secret, content)
|
||||
cmd = ['/etc/openclash/core/clash_meta', 'age', 'decrypt', secret, '-', '-']
|
||||
out, status = popen_stream(cmd, content)
|
||||
status.success? ? out : nil
|
||||
rescue => e
|
||||
nil
|
||||
end
|
||||
|
||||
def self.encrypt_content_with_public(public, content)
|
||||
cmd = ['/etc/openclash/core/clash_meta', 'age', 'encrypt', public, '-', '-']
|
||||
out, status = popen_stream(cmd, content)
|
||||
status.success? ? out : nil
|
||||
rescue => e
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# fix_short_id_quotes:
|
||||
@@ -65,6 +213,8 @@ module YAML
|
||||
# Input: short-id: null -> Output: short-id: ""
|
||||
|
||||
def self.fix_short_id_quotes(yaml_content)
|
||||
yaml_content = decode64(yaml_content)
|
||||
|
||||
return yaml_content unless yaml_content.include?('short-id:')
|
||||
|
||||
begin
|
||||
|
||||
@@ -17,18 +17,30 @@ set_lock
|
||||
DOWNLOAD_FILE="/tmp/clash_last_version"
|
||||
RELEASE_BRANCH=$(uci_get_config "release_branch" || echo "master")
|
||||
github_address_mod=$(uci_get_config "github_address_mod" || echo 0)
|
||||
CORE_TYPE=$(uci_get_config "core_type")
|
||||
OIX_TOKEN=$(uci_get_config "oix_token")
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
github_address_mod="$1"
|
||||
fi
|
||||
|
||||
if [ "$github_address_mod" != "0" ]; then
|
||||
if [ "$github_address_mod" == "https://cdn.jsdelivr.net/" ] || [ "$github_address_mod" == "https://fastly.jsdelivr.net/" ] || [ "$github_address_mod" == "https://testingcf.jsdelivr.net/" ]; then
|
||||
DOWNLOAD_URL="${github_address_mod}gh/vernesong/OpenClash@core/${RELEASE_BRANCH}/core_version"
|
||||
if [ "$CORE_TYPE" = "Oix" ] || [ -n "$OIX_TOKEN" ]; then
|
||||
OIX_VERSION_URL="https://github.com/vernesong/mihomo-oix/releases/download/Pre-Alpha/version.txt"
|
||||
if [ "$github_address_mod" != "0" ] && [ "$github_address_mod" != "https://cdn.jsdelivr.net/" ] && [ "$github_address_mod" != "https://fastly.jsdelivr.net/" ] && [ "$github_address_mod" != "https://testingcf.jsdelivr.net/" ]; then
|
||||
DOWNLOAD_URL="${github_address_mod}${OIX_VERSION_URL}"
|
||||
else
|
||||
DOWNLOAD_URL="${github_address_mod}https://raw.githubusercontent.com/vernesong/OpenClash/core/${RELEASE_BRANCH}/core_version"
|
||||
DOWNLOAD_URL="$OIX_VERSION_URL"
|
||||
fi
|
||||
else
|
||||
DOWNLOAD_URL="https://raw.githubusercontent.com/vernesong/OpenClash/core/${RELEASE_BRANCH}/core_version"
|
||||
if [ "$github_address_mod" != "0" ]; then
|
||||
if [ "$github_address_mod" == "https://cdn.jsdelivr.net/" ] || [ "$github_address_mod" == "https://fastly.jsdelivr.net/" ] || [ "$github_address_mod" == "https://testingcf.jsdelivr.net/" ]; then
|
||||
DOWNLOAD_URL="${github_address_mod}gh/vernesong/OpenClash@core/${RELEASE_BRANCH}/core_version"
|
||||
else
|
||||
DOWNLOAD_URL="${github_address_mod}https://raw.githubusercontent.com/vernesong/OpenClash/core/${RELEASE_BRANCH}/core_version"
|
||||
fi
|
||||
else
|
||||
DOWNLOAD_URL="https://raw.githubusercontent.com/vernesong/OpenClash/core/${RELEASE_BRANCH}/core_version"
|
||||
fi
|
||||
fi
|
||||
|
||||
DOWNLOAD_FILE_CURL "$DOWNLOAD_URL" "$DOWNLOAD_FILE" "$DOWNLOAD_FILE"
|
||||
|
||||
@@ -49,7 +49,7 @@ config_test()
|
||||
{
|
||||
if [ -f "$CLASH" ]; then
|
||||
LOG_OUT "Config File Download Successful, Test If There is Any Errors..."
|
||||
test_info=$($CLASH -t -d $CLASH_CONFIG -f "$CFG_FILE")
|
||||
test_info=$($CLASH -t -d $CLASH_CONFIG -f "$CFG_FILE" -age-secret-key "$SECRET_KEY")
|
||||
local IFS=$'\n'
|
||||
for i in $test_info; do
|
||||
if [ -n "$(echo "$i" |grep "configuration file")" ]; then
|
||||
@@ -72,15 +72,14 @@ config_download()
|
||||
LOG_TIP "Config File【$name】Downloading User-Agent【$sub_ua】..."
|
||||
if [ -n "$subscribe_url_param" ] && [ -n "$c_address" ]; then
|
||||
LOG_INFO "Config File【$name】Downloading URL【$c_address$subscribe_url_param】..."
|
||||
local DOWNLOAD_URL="${c_address}${subscribe_url_param}"
|
||||
local DOWNLOAD_PARAM="$sub_ua"
|
||||
DOWNLOAD_URL="${c_address}${subscribe_url_param}"
|
||||
fi
|
||||
if [ -z "$DOWNLOAD_URL" ]; then
|
||||
LOG_INFO "Config File【$name】Downloading URL【$subscribe_url】..."
|
||||
local DOWNLOAD_URL="${subscribe_url}"
|
||||
local DOWNLOAD_PARAM="$sub_ua"
|
||||
DOWNLOAD_URL="${subscribe_url}"
|
||||
fi
|
||||
DOWNLOAD_FILE_CURL "$DOWNLOAD_URL" "$CFG_FILE" "$CONFIG_FILE" "$DOWNLOAD_PARAM"
|
||||
DOWNLOAD_PARAM="$sub_ua"
|
||||
DOWNLOAD_FILE_CURL "$DOWNLOAD_URL" "$CFG_FILE" "$CONFIG_FILE" "$DOWNLOAD_PARAM" "$SECRET_KEY"
|
||||
DOWNLOAD_RESULT=$?
|
||||
}
|
||||
|
||||
@@ -317,7 +316,7 @@ convert_custom_param()
|
||||
|
||||
sub_info_get()
|
||||
{
|
||||
local section="$1" subscribe_url template_path subscribe_url_param template_path_encode key_match_param key_ex_match_param c_address de_ex_keyword sub_ua append_custom_params
|
||||
local section="$1" subscribe_url template_path subscribe_url_param template_path_encode key_match_param key_ex_match_param c_address de_ex_keyword sub_ua append_custom_params SECRET_KEY DOWNLOAD_URL DOWNLOAD_PARAM
|
||||
config_get_bool "enabled" "$section" "enabled" "1"
|
||||
config_get "name" "$section" "name" "config"
|
||||
config_get "sub_convert" "$section" "sub_convert" ""
|
||||
@@ -335,6 +334,7 @@ sub_info_get()
|
||||
config_get "custom_template_url" "$section" "custom_template_url" ""
|
||||
config_get "de_ex_keyword" "$section" "de_ex_keyword" ""
|
||||
config_get "sub_ua" "$section" "sub_ua" "clash-verge/v2.4.5"
|
||||
SECRET_KEY=$(uci_get_age_secret_keys "$name")
|
||||
|
||||
CONFIG_FILE="/etc/openclash/config/$name.yaml"
|
||||
CFG_FILE="/tmp/$name.yaml"
|
||||
|
||||
@@ -44,8 +44,8 @@ if [ -z "$CHNR_CUSTOM_URL" ]; then
|
||||
else
|
||||
DOWNLOAD_FILE_CURL "$CHNR_CUSTOM_URL" "/tmp/china_ip_route.txt" "$chnr_path"
|
||||
fi
|
||||
|
||||
if [ "$?" -eq 0 ]; then
|
||||
DOWNLOAD_RESULT=$?
|
||||
if [ "$DOWNLOAD_RESULT" -eq 0 ]; then
|
||||
LOG_OUT "Chnroute Cidr List Download Success, Check Updated..."
|
||||
#预处理
|
||||
if [ -n "$FW4" ]; then
|
||||
@@ -69,7 +69,7 @@ if [ "$?" -eq 0 ]; then
|
||||
else
|
||||
LOG_OUT "Updated Chnroute Cidr List No Change, Do Nothing..."
|
||||
fi
|
||||
elif [ "$?" -eq 2 ]; then
|
||||
elif [ "$DOWNLOAD_RESULT" -eq 2 ]; then
|
||||
LOG_OUT "Updated Chnroute Cidr List No Change, Do Nothing..."
|
||||
else
|
||||
LOG_OUT "Chnroute Cidr List Update Error, Please Try Again Later..."
|
||||
|
||||
@@ -35,7 +35,9 @@ fi
|
||||
CORE_TYPE="$1"
|
||||
C_CORE_TYPE=$(uci_get_config "core_type")
|
||||
SMART_ENABLE=$(uci_get_config "smart_enable" || echo 0)
|
||||
OIX_TOKEN=$(uci_get_config "oix_token")
|
||||
[ "$SMART_ENABLE" -eq 1 ] && CORE_TYPE="Smart"
|
||||
[ "$CORE_TYPE" = "Oix" ] || [ -n "$OIX_TOKEN" ] && CORE_TYPE="Oix"
|
||||
[ -z "$CORE_TYPE" ] && CORE_TYPE="Meta"
|
||||
small_flash_memory=$(uci_get_config "small_flash_memory")
|
||||
CPU_MODEL=$(uci_get_config "core_version")
|
||||
@@ -62,31 +64,45 @@ else
|
||||
fi
|
||||
|
||||
CORE_CV=$($meta_core_path -v 2>/dev/null |awk -F ' ' '{print $3}' |head -1)
|
||||
DOWNLOAD_FILE="/tmp/clash_meta.tar.gz"
|
||||
TMP_FILE="/tmp/clash_meta"
|
||||
TARGET_CORE_PATH="$meta_core_path"
|
||||
|
||||
if [ "$CORE_TYPE" = "Smart" ]; then
|
||||
if [ "$CORE_TYPE" = "Oix" ]; then
|
||||
CORE_URL_PATH=""
|
||||
DOWNLOAD_FILE="/tmp/clash_meta.gz"
|
||||
CORE_LV=$(sed -n 1p /tmp/clash_last_version 2>/dev/null)
|
||||
elif [ "$CORE_TYPE" = "Smart" ]; then
|
||||
CORE_URL_PATH="$RELEASE_BRANCH/smart"
|
||||
DOWNLOAD_FILE="/tmp/clash_meta.tar.gz"
|
||||
CORE_LV=$(sed -n 2p /tmp/clash_last_version 2>/dev/null)
|
||||
else
|
||||
CORE_URL_PATH="$RELEASE_BRANCH/meta"
|
||||
DOWNLOAD_FILE="/tmp/clash_meta.tar.gz"
|
||||
CORE_LV=$(sed -n 1p /tmp/clash_last_version 2>/dev/null)
|
||||
fi
|
||||
|
||||
[ "$C_CORE_TYPE" = "$CORE_TYPE" ] || [ -z "$C_CORE_TYPE" ] && restart=1
|
||||
[ "$C_CORE_TYPE" != "$CORE_TYPE" ] || [ -z "$C_CORE_TYPE" ] && restart=1
|
||||
|
||||
if [ "$CORE_CV" != "$CORE_LV" ] || [ -z "$CORE_CV" ]; then
|
||||
if [ "$CPU_MODEL" != 0 ]; then
|
||||
LOG_TIP "【$CORE_TYPE】Core Downloading, Please Try to Download and Upload Manually If Fails"
|
||||
if [ "$github_address_mod" != "0" ]; then
|
||||
if [ "$github_address_mod" == "https://cdn.jsdelivr.net/" ] || [ "$github_address_mod" == "https://fastly.jsdelivr.net/" ] || [ "$github_address_mod" == "https://testingcf.jsdelivr.net/" ]; then
|
||||
DOWNLOAD_URL="${github_address_mod}gh/vernesong/OpenClash@core/${CORE_URL_PATH}/clash-${CPU_MODEL}.tar.gz"
|
||||
if [ "$CORE_TYPE" = "Oix" ]; then
|
||||
OIX_CORE_URL="https://github.com/vernesong/mihomo-oix/releases/download/Pre-Alpha/mihomo-${CPU_MODEL}-${CORE_LV}.gz"
|
||||
if [ "$github_address_mod" != "0" ] && [ "$github_address_mod" != "https://cdn.jsdelivr.net/" ] && [ "$github_address_mod" != "https://fastly.jsdelivr.net/" ] && [ "$github_address_mod" != "https://testingcf.jsdelivr.net/" ]; then
|
||||
DOWNLOAD_URL="${github_address_mod}${OIX_CORE_URL}"
|
||||
else
|
||||
DOWNLOAD_URL="${github_address_mod}https://raw.githubusercontent.com/vernesong/OpenClash/core/${CORE_URL_PATH}/clash-${CPU_MODEL}.tar.gz"
|
||||
DOWNLOAD_URL="$OIX_CORE_URL"
|
||||
fi
|
||||
else
|
||||
DOWNLOAD_URL="https://raw.githubusercontent.com/vernesong/OpenClash/core/${CORE_URL_PATH}/clash-${CPU_MODEL}.tar.gz"
|
||||
if [ "$github_address_mod" != "0" ]; then
|
||||
if [ "$github_address_mod" == "https://cdn.jsdelivr.net/" ] || [ "$github_address_mod" == "https://fastly.jsdelivr.net/" ] || [ "$github_address_mod" == "https://testingcf.jsdelivr.net/" ]; then
|
||||
DOWNLOAD_URL="${github_address_mod}gh/vernesong/OpenClash@core/${CORE_URL_PATH}/clash-${CPU_MODEL}.tar.gz"
|
||||
else
|
||||
DOWNLOAD_URL="${github_address_mod}https://raw.githubusercontent.com/vernesong/OpenClash/core/${CORE_URL_PATH}/clash-${CPU_MODEL}.tar.gz"
|
||||
fi
|
||||
else
|
||||
DOWNLOAD_URL="https://raw.githubusercontent.com/vernesong/OpenClash/core/${CORE_URL_PATH}/clash-${CPU_MODEL}.tar.gz"
|
||||
fi
|
||||
fi
|
||||
|
||||
retry_count=0
|
||||
@@ -107,8 +123,12 @@ if [ "$CORE_CV" != "$CORE_LV" ] || [ -z "$CORE_CV" ]; then
|
||||
LOG_TIP "【"$CORE_TYPE"】Core Download Successful, Start Update..."
|
||||
extract_success=true
|
||||
[ -s "$DOWNLOAD_FILE" ] && {
|
||||
tar zxvfo "$DOWNLOAD_FILE" -C /tmp >/dev/null 2>&1 || extract_success=false
|
||||
mv /tmp/clash "$TMP_FILE" >/dev/null 2>&1 || extract_success=false
|
||||
if [ "$CORE_TYPE" = "Oix" ]; then
|
||||
gzip -dc "$DOWNLOAD_FILE" > "$TMP_FILE" 2>/dev/null || extract_success=false
|
||||
else
|
||||
tar zxvfo "$DOWNLOAD_FILE" -C /tmp >/dev/null 2>&1 || extract_success=false
|
||||
mv /tmp/clash "$TMP_FILE" >/dev/null 2>&1 || extract_success=false
|
||||
fi
|
||||
rm -rf "$DOWNLOAD_FILE" >/dev/null 2>&1
|
||||
chmod 4755 "$TMP_FILE" >/dev/null 2>&1 || extract_success=false
|
||||
"$TMP_FILE" -v >/dev/null 2>&1 || extract_success=false
|
||||
|
||||
@@ -8,28 +8,54 @@ DOWNLOAD_FILE_CURL() {
|
||||
DOWNLOAD_PATH=$2
|
||||
FILE_PATH=$3
|
||||
DOWNLOAD_UA=$4
|
||||
SECRET_KEY=$5
|
||||
[ -z "$DOWNLOAD_UA" ] && DOWNLOAD_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
|
||||
|
||||
CURL_OUTPUT=$(curl -sLI --connect-timeout 5 -m 10 --speed-time 5 --speed-limit 1 --retry 2 \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" "$DOWNLOAD_URL" 2>&1)
|
||||
|
||||
NEW_ETAG=$(echo "$CURL_OUTPUT" | grep -i "^etag:" | cut -d' ' -f2- | tr -d '\r\n' | sed 's/^"//;s/"$//')
|
||||
HTTP_CODE=$(echo "$CURL_OUTPUT" | grep -i "^HTTP" | tail -1 | cut -d' ' -f2)
|
||||
HEADER_TMP="/tmp/openclash_curl_header_$$"
|
||||
DOWNLOAD_TMP="${DOWNLOAD_PATH}.download.$$"
|
||||
CACHED_ETAG=$(GET_ETAG_BY_PATH "$FILE_PATH")
|
||||
ETAG_HEADER=""
|
||||
|
||||
if [ "$HTTP_CODE" = "200" ] && [ -n "$NEW_ETAG" ] && [ "$NEW_ETAG" = "$CACHED_ETAG" ] && [ -e "$FILE_PATH" ]; then
|
||||
return 2
|
||||
if [ -n "$CACHED_ETAG" ] && [ -e "$FILE_PATH" ]; then
|
||||
FILE_MTIME=$(date -r "$FILE_PATH" '+%Y-%m-%d %H:%M:%S' 2>/dev/null)
|
||||
LAST_UPDATE=$(GET_ETAG_TIMESTAMP_BY_PATH "$FILE_PATH")
|
||||
if [ -n "$LAST_UPDATE" ] && [ -n "$FILE_MTIME" ] && [ "$LAST_UPDATE" = "$FILE_MTIME" ]; then
|
||||
ETAG_HEADER="If-None-Match: \"${CACHED_ETAG}\""
|
||||
fi
|
||||
fi
|
||||
|
||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||
|
||||
if [ "$SHOW_DOWNLOAD_PROGRESS" = "1" ] || [ "$SHOW_DOWNLOAD_PROGRESS" = "true" ]; then
|
||||
TEMP_LOG="/tmp/curl_log_$$"
|
||||
|
||||
LOG_OUT "Downloading:【$(basename "$DOWNLOAD_PATH") - 0%】"
|
||||
|
||||
(
|
||||
curl -# -L --connect-timeout 10 -m 60 --speed-time 20 --speed-limit 1 --retry 2 \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_PATH" 2>"$TEMP_LOG"
|
||||
if [ -n "$SECRET_KEY" ] && [ -n "$ETAG_HEADER" ]; then
|
||||
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||
-D "$HEADER_TMP" \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
||||
-H "$ETAG_HEADER" \
|
||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
||||
elif [ -n "$SECRET_KEY" ]; then
|
||||
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||
-D "$HEADER_TMP" \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
||||
elif [ -n "$ETAG_HEADER" ]; then
|
||||
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||
-D "$HEADER_TMP" \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||
-H "$ETAG_HEADER" \
|
||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
||||
else
|
||||
curl -# -L --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||
-D "$HEADER_TMP" \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>"$TEMP_LOG"
|
||||
fi
|
||||
echo $? > "${TEMP_LOG}.exit"
|
||||
) &
|
||||
|
||||
@@ -55,6 +81,7 @@ DOWNLOAD_FILE_CURL() {
|
||||
|
||||
wait $CURL_PID
|
||||
EXIR_CODE=$(cat "${TEMP_LOG}.exit" 2>/dev/null || echo "1")
|
||||
HTTP_CODE=$(grep -i "^HTTP" "$HEADER_TMP" 2>/dev/null | tail -1 | cut -d' ' -f2)
|
||||
|
||||
if [ "$EXIR_CODE" -eq 0 ] && [ "$LAST_PROGRESS" -ne 100 ]; then
|
||||
LOG_OUT "Downloading:【$(basename "$DOWNLOAD_PATH") - 100%】"
|
||||
@@ -66,29 +93,82 @@ DOWNLOAD_FILE_CURL() {
|
||||
|
||||
rm -f "$TEMP_LOG" "${TEMP_LOG}.exit"
|
||||
|
||||
if [ "$EXIR_CODE" -ne 0 ]; then
|
||||
if [ "$EXIR_CODE" -eq 0 ] && [ "$HTTP_CODE" = "304" ] && [ -e "$FILE_PATH" ]; then
|
||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||
return 2
|
||||
fi
|
||||
|
||||
if [ "$EXIR_CODE" -ne 0 ] || [ "$HTTP_CODE" != "200" ]; then
|
||||
LOG_OUT "【$DOWNLOAD_PATH】Download Failed:【$OUTPUT】"
|
||||
rm -rf $DOWNLOAD_PATH
|
||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||
SLOG_CLEAN
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 60 --speed-time 30 --speed-limit 1 --retry 2 -H "User-Agent: ${DOWNLOAD_UA}" "$DOWNLOAD_URL" -o "$DOWNLOAD_PATH" 2>&1)
|
||||
EXIR_CODE=$?
|
||||
HTTP_CODE=$(echo "$CURL_OUTPUT" | tail -n1)
|
||||
DOWNLOAD_TRY=0
|
||||
MAX_DOWNLOAD_RETRIES=3
|
||||
while [ "$DOWNLOAD_TRY" -lt "$MAX_DOWNLOAD_RETRIES" ]; do
|
||||
DOWNLOAD_TRY=$((DOWNLOAD_TRY + 1))
|
||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||
if [ -n "$SECRET_KEY" ] && [ -n "$ETAG_HEADER" ]; then
|
||||
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||
-D "$HEADER_TMP" \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
||||
-H "$ETAG_HEADER" \
|
||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
||||
elif [ -n "$SECRET_KEY" ]; then
|
||||
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||
-D "$HEADER_TMP" \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||
-H "X-Age-Public-Key: ${SECRET_KEY}" \
|
||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
||||
elif [ -n "$ETAG_HEADER" ]; then
|
||||
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||
-D "$HEADER_TMP" \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" \
|
||||
-H "$ETAG_HEADER" \
|
||||
"$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
||||
else
|
||||
CURL_OUTPUT=$(curl -w "\n%{http_code}" -SsL --connect-timeout 30 -m 180 --speed-time 30 --speed-limit 1 --retry 2 \
|
||||
-D "$HEADER_TMP" \
|
||||
-H "User-Agent: ${DOWNLOAD_UA}" "$DOWNLOAD_URL" -o "$DOWNLOAD_TMP" 2>&1)
|
||||
fi
|
||||
EXIR_CODE=$?
|
||||
HTTP_CODE=$(echo "$CURL_OUTPUT" | tail -n1)
|
||||
if { [ "$EXIR_CODE" -eq 0 ] && [ "$HTTP_CODE" = "200" ]; } || { [ "$EXIR_CODE" -eq 0 ] && [ "$HTTP_CODE" = "304" ] && [ -e "$FILE_PATH" ]; }; then
|
||||
break
|
||||
fi
|
||||
[ "$DOWNLOAD_TRY" -lt "$MAX_DOWNLOAD_RETRIES" ] && sleep 1
|
||||
done
|
||||
|
||||
if [ "$EXIR_CODE" -ne 0 ] || [ "$HTTP_CODE" -ne 200 ]; then
|
||||
if [ "$EXIR_CODE" -eq 0 ] && [ "$HTTP_CODE" = "304" ] && [ -e "$FILE_PATH" ]; then
|
||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||
return 2
|
||||
fi
|
||||
|
||||
if [ "$EXIR_CODE" -ne 0 ] || [ "$HTTP_CODE" != "200" ]; then
|
||||
OUTPUT=$(echo "$CURL_OUTPUT" | sed '$d' | grep -a 'curl:' | tail -n 1)
|
||||
LOG_OUT "【$DOWNLOAD_PATH】Download Failed:【$OUTPUT】"
|
||||
rm -rf $DOWNLOAD_PATH
|
||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||
SLOG_CLEAN
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! mv -f "$DOWNLOAD_TMP" "$DOWNLOAD_PATH"; then
|
||||
LOG_OUT "【$DOWNLOAD_PATH】Download Failed:【Unable to save download file】"
|
||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||
SLOG_CLEAN
|
||||
return 1
|
||||
fi
|
||||
NEW_ETAG=$(grep -i "^etag:" "$HEADER_TMP" 2>/dev/null | tail -1 | cut -d' ' -f2- | tr -d '\r\n' | sed 's/^"//;s/"$//')
|
||||
|
||||
if [ -n "$NEW_ETAG" ] && [ "$HTTP_CODE" = "200" ]; then
|
||||
SAVE_ETAG_TO_CACHE "$DOWNLOAD_URL" "$NEW_ETAG" "$FILE_PATH"
|
||||
fi
|
||||
|
||||
rm -f "$HEADER_TMP" "$DOWNLOAD_TMP"
|
||||
|
||||
return 0
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,9 @@ del_lock() {
|
||||
ipk_v()
|
||||
{
|
||||
if [ -x "/bin/opkg" ]; then
|
||||
echo $(opkg status "$1" 2>/dev/null |grep 'Version' |awk -F ': ' '{print $2}' 2>/dev/null)
|
||||
echo $(rm -f /var/lock/opkg.lock && opkg status "$1" 2>/dev/null |grep 'Version' |awk -F ': ' '{print $2}' 2>/dev/null)
|
||||
elif [ -x "/usr/bin/apk" ]; then
|
||||
echo $(apk list "$1" 2>/dev/null |grep 'installed' | grep -oE '\d+(\.\d+)*' | head -1)
|
||||
echo $(rm -f /lib/apk/db/lock && apk list "$1" 2>/dev/null |grep 'installed' | grep -oE '\d+(\.\d+)*' | head -1)
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -42,9 +42,9 @@ RAW_CONFIG_FILE=$(uci_get_config "config_path")
|
||||
CONFIG_FILE="/etc/openclash/$(uci_get_config "config_path" |awk -F '/' '{print $5}' 2>/dev/null)"
|
||||
core_model=$(uci_get_config "core_version")
|
||||
if [ -x "/bin/opkg" ]; then
|
||||
cpu_model=$(opkg status libc 2>/dev/null |grep 'Architecture' |awk -F ': ' '{print $2}' 2>/dev/null)
|
||||
cpu_model=$(rm -f /var/lock/opkg.lock && opkg status libc 2>/dev/null |grep 'Architecture' |awk -F ': ' '{print $2}' 2>/dev/null)
|
||||
elif [ -x "/usr/bin/apk" ]; then
|
||||
cpu_model=$(apk list libc 2>/dev/null|awk '{print $2}')
|
||||
cpu_model=$(rm -f /lib/apk/db/lock && apk list libc 2>/dev/null|awk '{print $2}')
|
||||
fi
|
||||
core_meta_version=$(/etc/openclash/core/clash_meta -v 2>/dev/null |awk -F ' ' '{print $3}' |head -1 2>/dev/null)
|
||||
op_version=$(ipk_v "luci-app-openclash")
|
||||
@@ -54,6 +54,19 @@ router_self_proxy=$(uci_get_config "router_self_proxy")
|
||||
core_type=$(uci_get_config "core_type" || echo "Dev")
|
||||
da_password=$(uci_get_config "dashboard_password")
|
||||
cn_port=$(uci_get_config "cn_port")
|
||||
stack_type=$(uci_get_config "stack_type")
|
||||
delay_start=$(uci_get_config "delay_start")
|
||||
log_size=$(uci_get_config "log_size")
|
||||
bypass_gateway_compatible=$(uci_get_config "bypass_gateway_compatible")
|
||||
disable_quic_go_gso=$(uci_get_config "disable_quic_go_gso")
|
||||
small_flash_memory=$(uci_get_config "small_flash_memory")
|
||||
enable_meta_sniffer=$(uci_get_config "enable_meta_sniffer")
|
||||
enable_respect_rules=$(uci_get_config "enable_respect_rules")
|
||||
skip_proxy_address=$(uci_get_config "skip_proxy_address")
|
||||
disable_udp_quic=$(uci_get_config "disable_udp_quic")
|
||||
lan_ac_mode=$(uci_get_config "lan_ac_mode")
|
||||
ipv6_mode=$(uci_get_config "ipv6_mode")
|
||||
china_ip6_route=$(uci_get_config "china_ip6_route")
|
||||
lan_interface_name=$(uci_get_config "lan_interface_name" || echo "0")
|
||||
if [ "$lan_interface_name" = "0" ]; then
|
||||
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.device || uci -q -p /tmp/state get network.lan.device) | grep -w "inet" 2>/dev/null |grep -Eo 'inet [0-9\.]+' | awk '{print $2}' |head -1 || ip addr show 2>/dev/null | grep -w 'inet' | grep 'global' | grep 'brd' | grep -Eo 'inet [0-9\.]+' | awk '{print $2}' | head -n 1)
|
||||
@@ -122,6 +135,12 @@ cat >> "$DEBUG_LOG" <<-EOF
|
||||
LuCI版本: $(ipk_v "luci")
|
||||
内核版本: $(uname -r 2>/dev/null)
|
||||
处理器架构: $cpu_model
|
||||
系统运行时间: $(uptime 2>/dev/null)
|
||||
|
||||
#磁盘与内存
|
||||
$(df -h / /tmp /etc/openclash 2>/dev/null)
|
||||
$(free -m 2>/dev/null)
|
||||
$(cat /proc/meminfo 2>/dev/null | grep -E '^(MemTotal|MemAvailable|SwapTotal|SwapFree)')
|
||||
|
||||
#此项有值时,如不使用IPv6,建议到网络-接口-lan的设置中禁用IPV6的DHCP
|
||||
IPV6-DHCP: $(uci -q get dhcp.lan.dhcpv6)
|
||||
@@ -129,6 +148,8 @@ IPV6-DHCP: $(uci -q get dhcp.lan.dhcpv6)
|
||||
DNS劫持: $(dns_re "$enable_redirect_dns")
|
||||
#DNS劫持为Dnsmasq时,此项结果应仅有配置文件的DNS监听地址
|
||||
Dnsmasq转发设置: $(uci -q get dhcp.@dnsmasq[0].server)
|
||||
Dnsmasq完整配置:
|
||||
$(uci show dhcp.@dnsmasq[0] 2>/dev/null)
|
||||
EOF
|
||||
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
@@ -147,6 +168,8 @@ ruby: $(ts_re "$(ipk_v "ruby")")
|
||||
ruby-yaml: $(ts_re "$(ipk_v "ruby-yaml")")
|
||||
ruby-psych: $(ts_re "$(ipk_v "ruby-psych")")
|
||||
ruby-pstore: $(ts_re "$(ipk_v "ruby-pstore")")
|
||||
ruby版本: $(ruby --version 2>/dev/null || echo "未安装")
|
||||
ruby功能测试: $(ruby -e "require 'yaml'; YAML.load('test: ok'); puts '正常'" 2>/dev/null || echo "异常")
|
||||
kmod-tun(TUN模式): $(ts_re "$(ipk_v "kmod-tun")")
|
||||
luci-compat(Luci >= 19.07): $(ts_re "$(ipk_v "luci-compat")")
|
||||
kmod-inet-diag(PROCESS-NAME): $(ts_re "$(ipk_v "kmod-inet-diag")")
|
||||
@@ -166,6 +189,12 @@ kmod-ipt-nat: $(ts_re "$(ipk_v "kmod-ipt-nat")")
|
||||
EOF
|
||||
fi
|
||||
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
#内核模块加载状态:
|
||||
$(lsmod | grep -E 'tun|tproxy|inet_diag' 2>/dev/null || echo "无相关模块")
|
||||
EOF
|
||||
|
||||
#core
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
@@ -219,6 +248,22 @@ fi
|
||||
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
#===================== GEO 数据文件 =====================#
|
||||
|
||||
$(ls -lh /etc/openclash/Country.mmdb /etc/openclash/GeoIP.dat /etc/openclash/GeoSite.dat /etc/openclash/ASN.mmdb 2>/dev/null)
|
||||
|
||||
#===================== 模型、缓存文件状态 =====================#
|
||||
|
||||
Model.bin: $(ls -lh /etc/openclash/Model.bin 2>/dev/null || echo "不存在")
|
||||
cache.db: $(ls -lh /etc/openclash/cache.db 2>/dev/null || echo "不存在")
|
||||
|
||||
#===================== 冲突插件检测 =====================#
|
||||
|
||||
$(ps | grep -E 'passwall|ssr-plus|bypass|helloworld' | grep -v grep 2>/dev/null || echo "未检测到冲突插件")
|
||||
EOF
|
||||
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
#===================== 插件设置 =====================#
|
||||
|
||||
当前配置文件: $RAW_CONFIG_FILE
|
||||
@@ -236,11 +281,31 @@ IPV6-DNS解析: $(ts_cf "$ipv6_dns")
|
||||
仅允许常用端口流量: $(ts_cf "$common_ports")
|
||||
绕过中国大陆IP: $(ts_cf "$china_ip_route")
|
||||
路由本机代理: $(ts_cf "$router_self_proxy")
|
||||
TUN堆栈类型: ${stack_type:-system}
|
||||
启动延迟: ${delay_start:-0}秒
|
||||
日志大小: ${log_size:-1024}KB
|
||||
旁路由兼容: $(ts_cf "$bypass_gateway_compatible")
|
||||
禁用quic-go GSO: $(ts_cf "$disable_quic_go_gso")
|
||||
小闪存模式: $(ts_cf "$small_flash_memory")
|
||||
域名嗅探: $(ts_cf "$enable_meta_sniffer")
|
||||
DNS代理: $(ts_cf "$enable_respect_rules")
|
||||
绕过服务器地址: $(ts_cf "$skip_proxy_address")
|
||||
禁用QUIC: $(ts_cf "$disable_udp_quic")
|
||||
访问控制模式: $([ "$lan_ac_mode" = "1" ] && echo "White" || echo "Black")
|
||||
IPv6模式: ${ipv6_mode:-0}
|
||||
绕过IPv6区域: $(ts_cf "$china_ip6_route")
|
||||
|
||||
EOF
|
||||
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
#===================== Cron 定时任务 =====================#
|
||||
|
||||
$(crontab -l 2>/dev/null | grep -i openclash || echo "无 OpenClash 相关 cron 任务")
|
||||
EOF
|
||||
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
#===================== 覆写模块设置 =====================#
|
||||
|
||||
$(uci -q show openclash.@overwrite[0])
|
||||
@@ -408,6 +473,14 @@ netstat -nlp |grep clash >> "$DEBUG_LOG" 2>/dev/null
|
||||
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
#===================== 网络接口状态 =====================#
|
||||
|
||||
EOF
|
||||
ip link show >> "$DEBUG_LOG" 2>/dev/null
|
||||
ip addr show | grep -E 'inet |utun' >> "$DEBUG_LOG" 2>/dev/null
|
||||
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
#===================== 测试本机DNS查询(www.baidu.com) =====================#
|
||||
|
||||
EOF
|
||||
@@ -462,6 +535,15 @@ else
|
||||
curl -SsIL -m 3 --retry 2 "$VERSION_URL" >> "$DEBUG_LOG" 2>/dev/null
|
||||
fi
|
||||
|
||||
if pidof clash >/dev/null; then
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
#===================== Mihomo API 健康检查 =====================#
|
||||
|
||||
EOF
|
||||
curl -Ss -m 3 http://127.0.0.1:${cn_port}/version >> "$DEBUG_LOG" 2>/dev/null
|
||||
fi
|
||||
|
||||
cat >> "$DEBUG_LOG" <<-EOF
|
||||
|
||||
#===================== 最近运行日志 (切换为Debug模式) =====================#
|
||||
|
||||
@@ -50,7 +50,7 @@ if [ -z "$CONFIG_FILE" ] || [ ! -f "$CONFIG_FILE" ]; then
|
||||
fi
|
||||
|
||||
if [ -n "$(pidof clash)" ] && [ -f "$CONFIG_FILE" ]; then
|
||||
if [ "$small_flash_memory" == "1" ] || [ -n "$(echo $core_version |grep mips)" ] || [ -n "$(echo $DISTRIB_ARCH |grep mips)" ] || [ -n "$(opkg status libc 2>/dev/null |grep 'Architecture' |awk -F ': ' '{print $2}' |grep mips)" ] || [ -n "$(apk list libc 2>/dev/null |grep mips)" ]; then
|
||||
if [ "$small_flash_memory" == "1" ] || [ -n "$(echo $core_version |grep mips)" ] || [ -n "$(echo $DISTRIB_ARCH |grep mips)" ] || [ -n "$(rm -f /var/lock/opkg.lock && opkg status libc 2>/dev/null |grep 'Architecture' |awk -F ': ' '{print $2}' |grep mips)" ] || [ -n "$(rm -f /lib/apk/db/lock && apk list libc 2>/dev/null |grep mips)" ]; then
|
||||
CACHE_PATH="/tmp/etc/openclash/cache.db"
|
||||
if [ -f "$CACHE_PATH" ]; then
|
||||
cmp -s "$CACHE_PATH" "$HISTORY_PATH"
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
require "nixio"
|
||||
require "luci.util"
|
||||
require "luci.sys"
|
||||
local uci = require("luci.model.uci").cursor()
|
||||
local fs = require "luci.openclash"
|
||||
local json = require "luci.jsonc"
|
||||
|
||||
local function oix_checkin()
|
||||
local info, path, checkin
|
||||
local token = fs.uci_get_config("config", "oix_token")
|
||||
local enable = fs.uci_get_config("config", "oix_checkin") or 0
|
||||
local interval = fs.uci_get_config("config", "oix_checkin_interval") or 1
|
||||
local multiple = fs.uci_get_config("config", "oix_checkin_multiple") or 1
|
||||
path = "/tmp/oix_checkin"
|
||||
if token and enable == "1" then
|
||||
checkin = string.format("curl -sL -H 'Content-Type: application/json' -H 'Authorization: Bearer %s' -d '{\"multiple\":\"%s\"}' -X POST https://oix-api.dler.io/api/v1/checkin -o %s", token, multiple, path)
|
||||
if fs.readfile(path) == "" or not fs.readfile(path) then
|
||||
luci.sys.exec(checkin)
|
||||
else
|
||||
if (os.time() - fs.mtime(path) > interval*3600+1) then
|
||||
fs.unlink(path)
|
||||
luci.sys.exec(checkin)
|
||||
else
|
||||
os.exit(0)
|
||||
end
|
||||
end
|
||||
if fs.readfile(path) == "" or not fs.readfile(path) then
|
||||
fs.writefile(path, " ")
|
||||
end
|
||||
info = fs.readfile(path)
|
||||
if info then
|
||||
info = json.parse(info)
|
||||
end
|
||||
if info and info.ret == 200 then
|
||||
luci.sys.exec(string.format('echo "%s [Info] oixCloud Checkin Successful, Result:【%s】" >> /tmp/openclash.log', os.date("%Y-%m-%d %H:%M:%S"), info.data.checkin))
|
||||
else
|
||||
if info and info.msg then
|
||||
luci.sys.exec(string.format('echo "%s [Info] oixCloud Checkin Failed, Result:【%s】" >> /tmp/openclash.log', os.date("%Y-%m-%d %H:%M:%S"), info.msg))
|
||||
else
|
||||
luci.sys.exec(string.format('echo "%s [Info] oixCloud Checkin Failed! Please Check And Try Again..." >> /tmp/openclash.log', os.date("%Y-%m-%d %H:%M:%S")))
|
||||
end
|
||||
end
|
||||
end
|
||||
os.exit(0)
|
||||
end
|
||||
|
||||
oix_checkin()
|
||||
@@ -709,7 +709,7 @@ function table_sort_by_cache(t)
|
||||
end
|
||||
end
|
||||
if #tab > 0 then
|
||||
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] "..type.." Group:".."【"..group_match_name.."】".."Cached Compliant Nodes Number:".."【"..#(tab).."】"..", Cached Non-compliant Nodes Number:".."【"..#(tab_b).."】"..", Prioritize Testing With Cached Compliant Nodes...")
|
||||
print(os.date("%Y-%m-%d %H:%M:%S").." [Info] 【"..group_match_name.."】".."Cached Compliant Nodes Number:".."【"..#(tab).."】"..", Cached Non-compliant Nodes Number:".."【"..#(tab_b).."】"..", Prioritize Testing With Cached Compliant Nodes...")
|
||||
end
|
||||
for k,v in pairs(tab_b) do table.insert(tab, v) end
|
||||
return tab
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
local nixio = require "nixio"
|
||||
local jsonc = require "luci.jsonc"
|
||||
local util = require "luci.util"
|
||||
local fs = require "luci.openclash"
|
||||
|
||||
if not nixio.fs.access("/usr/bin/base64") and not nixio.fs.access("/bin/base64") then
|
||||
os.exit(1)
|
||||
@@ -14,31 +15,8 @@ if not file_path or not nixio.fs.access(file_path) then
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
local function raw_base64_decode(str)
|
||||
if not str or str == "" then return nil end
|
||||
|
||||
str = str:gsub("-", "+"):gsub("_", "/")
|
||||
|
||||
local padding = #str % 4
|
||||
if padding > 0 then
|
||||
str = str .. string.rep("=", 4 - padding)
|
||||
end
|
||||
|
||||
local cmd = "printf '%s' '" .. str .. "' | base64 -d 2>/dev/null"
|
||||
local f = io.popen(cmd, "r")
|
||||
if not f then return nil end
|
||||
local result = f:read("*a")
|
||||
f:close()
|
||||
|
||||
if result and result ~= "" then
|
||||
return result
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function base64_decode_subscription(str)
|
||||
local result = raw_base64_decode(str)
|
||||
local result = fs.decode64(str)
|
||||
if result and result:find("://") then
|
||||
return result
|
||||
end
|
||||
@@ -126,7 +104,7 @@ local function get_server_from_url(line)
|
||||
original_body = original_body:match("([^#]+)") or original_body
|
||||
|
||||
-- base64
|
||||
local decoded = raw_base64_decode(original_body)
|
||||
local decoded = fs.decode64(original_body)
|
||||
if decoded then
|
||||
-- V2RayN JSON
|
||||
local ok, data = pcall(jsonc.parse, decoded)
|
||||
@@ -160,7 +138,7 @@ local function get_server_from_url(line)
|
||||
else
|
||||
-- ss://base64
|
||||
original_body = original_body:match("([^#]+)") or original_body
|
||||
local decoded = raw_base64_decode(original_body)
|
||||
local decoded = fs.decode64(original_body)
|
||||
if decoded then
|
||||
server = decoded:match("@([^:/]+)")
|
||||
else
|
||||
@@ -170,7 +148,7 @@ local function get_server_from_url(line)
|
||||
|
||||
elseif scheme == "ssr" then
|
||||
original_body = original_body:match("([^#]+)") or original_body
|
||||
local decoded = raw_base64_decode(original_body)
|
||||
local decoded = fs.decode64(original_body)
|
||||
if decoded then
|
||||
-- ssr://host:port:protocol:method:obfs:urlsafebase64pass/?params
|
||||
local before_query = decoded:match("^([^/?]+)")
|
||||
@@ -214,7 +192,7 @@ local function get_server_from_url(line)
|
||||
|
||||
-- fallback
|
||||
if not server then
|
||||
local body_to_parse = raw_base64_decode(original_body) or original_body
|
||||
local body_to_parse = fs.decode64(original_body) or original_body
|
||||
server = body_to_parse:match("@([^:/]+)") or -- user@host
|
||||
body_to_parse:match("([^:/]+)") or -- host
|
||||
body_to_parse:match("//([^:/]+)") -- //host
|
||||
|
||||
@@ -51,12 +51,31 @@ version_compare() {
|
||||
return 1
|
||||
}
|
||||
|
||||
run_with_timeout() {
|
||||
local timeout_sec="$1"
|
||||
shift
|
||||
"$@" &
|
||||
local _pid=$!
|
||||
(
|
||||
sleep "$timeout_sec"
|
||||
kill $_pid 2>/dev/null
|
||||
sleep 0.5
|
||||
kill -9 $_pid 2>/dev/null
|
||||
) &
|
||||
local _watchdog=$!
|
||||
wait $_pid 2>/dev/null
|
||||
local _ret=$?
|
||||
kill $_watchdog 2>/dev/null
|
||||
wait $_watchdog 2>/dev/null
|
||||
return $_ret
|
||||
}
|
||||
|
||||
LAST_OPVER="/tmp/openclash_last_version"
|
||||
LAST_VER=$(sed -n 1p "$LAST_OPVER" 2>/dev/null |sed "s/^v//g" |tr -d "\n")
|
||||
if [ -x "/bin/opkg" ]; then
|
||||
OP_CV=$(rm -f /var/lock/opkg.lock && opkg status luci-app-openclash 2>/dev/null |grep 'Version' |awk -F 'Version: ' '{print $2}' 2>/dev/null)
|
||||
elif [ -x "/usr/bin/apk" ]; then
|
||||
OP_CV=$(apk list luci-app-openclash 2>/dev/null|grep "installed" | grep -oE '[0-9]+(\.[0-9]+)*' | head -1 2>/dev/null)
|
||||
OP_CV=$(rm -f /lib/apk/db/lock && apk list luci-app-openclash 2>/dev/null|grep "installed" | grep -oE '[0-9]+(\.[0-9]+)*' | head -1 2>/dev/null)
|
||||
fi
|
||||
OP_LV=$(sed -n 1p "$LAST_OPVER" 2>/dev/null |sed "s/^v//g" |tr -d "\n")
|
||||
RELEASE_BRANCH=$(uci_get_config "release_branch" || echo "master")
|
||||
@@ -129,27 +148,48 @@ if [ -n "$OP_CV" ] && [ -n "$OP_LV" ] && version_compare "$OP_CV" "$OP_LV" && [
|
||||
LOG_TIP "【$retry_count/$max_retries】【OpenClash - v$LAST_VER】Download successful, start pre update test..."
|
||||
|
||||
pre_test_success=false
|
||||
pkg_update_success=true
|
||||
|
||||
if [ -x "/bin/opkg" ]; then
|
||||
opkg update >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
sleep 2
|
||||
pkg_update_success=false
|
||||
continue
|
||||
fi
|
||||
update_retry=0
|
||||
max_update_retry=2
|
||||
while [ $update_retry -lt $max_update_retry ]; do
|
||||
update_retry=$((update_retry + 1))
|
||||
run_with_timeout 30 opkg update >/dev/null 2>&1
|
||||
opkg_ret=$?
|
||||
rm -f /var/lock/opkg.lock
|
||||
if [ $opkg_ret -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
if [ $update_retry -lt $max_update_retry ]; then
|
||||
LOG_ERROR "【$update_retry/$max_update_retry】【OpenClash - v$LAST_VER】opkg update failed or timed out, retrying..."
|
||||
sleep 2
|
||||
else
|
||||
LOG_ERROR "【$update_retry/$max_update_retry】【OpenClash - v$LAST_VER】opkg update failed, trying pre update test..."
|
||||
fi
|
||||
done
|
||||
if [ -s "/tmp/openclash.ipk" ]; then
|
||||
if [ -n "$(opkg install /tmp/openclash.ipk --noaction 2>/dev/null |grep 'Upgrading luci-app-openclash on root' 2>/dev/null)" ]; then
|
||||
pre_test_success=true
|
||||
fi
|
||||
fi
|
||||
elif [ -x "/usr/bin/apk" ]; then
|
||||
apk update >/dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
sleep 2
|
||||
pkg_update_success=false
|
||||
continue
|
||||
fi
|
||||
update_retry=0
|
||||
max_update_retry=2
|
||||
while [ $update_retry -lt $max_update_retry ]; do
|
||||
update_retry=$((update_retry + 1))
|
||||
run_with_timeout 30 apk update >/dev/null 2>&1
|
||||
apk_ret=$?
|
||||
rm -f /lib/apk/db/lock /tmp/apk.lock
|
||||
if [ $apk_ret -eq 0 ]; then
|
||||
break
|
||||
fi
|
||||
if [ $update_retry -lt $max_update_retry ]; then
|
||||
LOG_ERROR "【$update_retry/$max_update_retry】【OpenClash - v$LAST_VER】apk update failed or timed out, retrying..."
|
||||
sleep 2
|
||||
else
|
||||
LOG_ERROR "【$update_retry/$max_update_retry】【OpenClash - v$LAST_VER】apk update failed, trying pre update test..."
|
||||
fi
|
||||
done
|
||||
if [ -s "/tmp/openclash.apk" ]; then
|
||||
apk add -s -q --force-overwrite --clean-protected --allow-untrusted /tmp/openclash.apk >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
|
||||
@@ -37,7 +37,7 @@ RELEASE_BRANCH=$(uci_get_config "release_branch" || echo "master")
|
||||
if [ -x "/bin/opkg" ]; then
|
||||
OP_CV=$(rm -f /var/lock/opkg.lock && opkg status luci-app-openclash 2>/dev/null |grep 'Version' |awk -F 'Version: ' '{print $2}' 2>/dev/null)
|
||||
elif [ -x "/usr/bin/apk" ]; then
|
||||
OP_CV=$(apk list luci-app-openclash 2>/dev/null|grep 'installed' | grep -oE '[0-9]+(\.[0-9]+)*' | head -1 2>/dev/null)
|
||||
OP_CV=$(rm -f /lib/apk/db/lock && apk list luci-app-openclash 2>/dev/null|grep 'installed' | grep -oE '[0-9]+(\.[0-9]+)*' | head -1 2>/dev/null)
|
||||
fi
|
||||
OP_LV=$(sed -n 1p "$DOWNLOAD_FILE" 2>/dev/null |sed "s/^v//g" |tr -d "\n")
|
||||
github_address_mod=$(uci_get_config "github_address_mod" || echo 0)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
. /usr/share/openclash/uci.sh
|
||||
|
||||
LOG_FILE="/tmp/openclash.log"
|
||||
CLASH="/etc/openclash/clash"
|
||||
CFG_UPDATE_INT=0
|
||||
SKIP_PROXY_ADDRESS=1
|
||||
SKIP_PROXY_ADDRESS_INTERVAL=30
|
||||
@@ -29,8 +30,6 @@ begin
|
||||
exit;
|
||||
end
|
||||
|
||||
require 'thread'
|
||||
|
||||
servers_to_process = Array.new
|
||||
|
||||
# Servers from proxies
|
||||
@@ -46,20 +45,41 @@ begin
|
||||
if provider.key?('path') and not provider['path'].empty?
|
||||
path = provider['path'].start_with?('./') ? '/etc/openclash/' + provider['path'][2..-1] : provider['path']
|
||||
if File.exist?(path)
|
||||
file_is_age_encrypted = File.read(path, 512).include?('BEGIN AGE ENCRYPTED FILE') rescue false
|
||||
begin
|
||||
provider_config = YAML.load_file(path)
|
||||
if provider.key?('age-secret-key') and not provider['age-secret-key'].to_s.empty?
|
||||
begin
|
||||
provider_config = YAML.load_file(path, secret: provider['age-secret-key']) rescue nil
|
||||
rescue Exception => e
|
||||
YAML.LOG_WARN('Set Proxies Address Skip Failed,【' + path + ': ' + e.message+'】')
|
||||
continue
|
||||
end
|
||||
else
|
||||
if file_is_age_encrypted
|
||||
YAML.LOG_WARN('Set Proxies Address Skip Failed,【' + path + ': File is AGE encrypted but no secret key provided】')
|
||||
next
|
||||
end
|
||||
provider_config = YAML.load_file(path)
|
||||
end
|
||||
|
||||
if provider_config.is_a?(Hash) and provider_config.key?('proxies') and not provider_config['proxies'].nil?
|
||||
provider_config['proxies'].each do |p|
|
||||
servers_to_process.push(p['server']) if p.key?('server')
|
||||
end
|
||||
end
|
||||
rescue Psych::SyntaxError, ArgumentError
|
||||
begin
|
||||
syscall = \"lua /usr/share/openclash/openclash_sub_parser.lua \\\"#{path}\\\"\"
|
||||
sub_servers = IO.popen(syscall).read.split(/\n+/)
|
||||
servers_to_process.concat(sub_servers) if sub_servers
|
||||
rescue Exception => e
|
||||
YAML.LOG_WARN('Failed to parse subscription file with Lua helper ' + path + ': ' + e.message)
|
||||
if not provider.key?('age-secret-key') or provider['age-secret-key'].to_s.empty?
|
||||
if file_is_age_encrypted
|
||||
YAML.LOG_WARN('Failed to parse config file with Lua helper【' + path + ': File is AGE encrypted, cannot parse with Lua】')
|
||||
next
|
||||
end
|
||||
begin
|
||||
syscall = \"lua /usr/share/openclash/openclash_sub_parser.lua \\\"#{path}\\\"\"
|
||||
sub_servers = IO.popen(syscall).read.split(/\n+/)
|
||||
servers_to_process.concat(sub_servers) if sub_servers
|
||||
rescue Exception => e
|
||||
YAML.LOG_WARN('Failed to parse config file with Lua helper【' + path + ': ' + e.message+'】')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -195,8 +215,8 @@ fi
|
||||
## Log File Size Manage:
|
||||
LOGSIZE=`ls -l /tmp/openclash.log |awk '{print int($5/1024)}'`
|
||||
if [ "$LOGSIZE" -gt "$log_size" ]; then
|
||||
: > /tmp/openclash.log
|
||||
LOG_WATCHDOG "Log Size Limit, Clean Up All Log Records..."
|
||||
: > /tmp/openclash.log
|
||||
LOG_WATCHDOG "Log Size Limit, Clean Up All Log Records..."
|
||||
fi
|
||||
|
||||
## 防火墙检查
|
||||
@@ -361,6 +381,9 @@ fi
|
||||
fi
|
||||
fi
|
||||
|
||||
##Dler Cloud Checkin
|
||||
/usr/share/openclash/openclash_oix_checkin.lua >/dev/null 2>&1
|
||||
|
||||
## 配置文件循环更新
|
||||
if [ "$cfg_update" -eq 1 ] && [ "$cfg_update_mode" -eq 1 ]; then
|
||||
if [ "$CFG_UPDATE_INT" -ne 0 ]; then
|
||||
@@ -374,59 +397,59 @@ fi
|
||||
if [ "$STREAM_AUTO_SELECT" -ne 0 ]; then
|
||||
if [ "$(expr "$STREAM_AUTO_SELECT" % "$stream_auto_select_interval")" -eq 0 ] || [ "$STREAM_AUTO_SELECT" -eq 1 ]; then
|
||||
if [ "$stream_auto_select_netflix" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【Netflix】..."
|
||||
LOG_TIP "【Netflix】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "Netflix" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_disney" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【Disney Plus】..."
|
||||
LOG_TIP "【Disney Plus】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "Disney Plus" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_google_not_cn" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【Google Not CN】..."
|
||||
LOG_TIP "【Google Not CN】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "Google" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_ytb" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【YouTube Premium】..."
|
||||
LOG_TIP "【YouTube Premium】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "YouTube Premium" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_prime_video" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【Amazon Prime Video】..."
|
||||
LOG_TIP "【Amazon Prime Video】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "Amazon Prime Video" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_hbo_max" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【HBO Max】..."
|
||||
LOG_TIP "【HBO Max】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "HBO Max" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_tvb_anywhere" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【TVB Anywhere+】..."
|
||||
LOG_TIP "【TVB Anywhere+】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "TVB Anywhere+" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_dazn" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【DAZN】..."
|
||||
LOG_TIP "【DAZN】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "DAZN" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_paramount_plus" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【Paramount Plus】..."
|
||||
LOG_TIP "【Paramount Plus】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "Paramount Plus" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_discovery_plus" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【Discovery Plus】..."
|
||||
LOG_TIP "【Discovery Plus】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "Discovery Plus" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_bilibili" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【Bilibili】..."
|
||||
LOG_TIP "【Bilibili】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "Bilibili" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_openai" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【OpenAI】..."
|
||||
LOG_TIP "【OpenAI】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "OpenAI" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_claude" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【Claude】..."
|
||||
LOG_TIP "【Claude】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "Claude" >> $LOG_FILE
|
||||
fi
|
||||
if [ "$stream_auto_select_gemini" -eq 1 ]; then
|
||||
LOG_TIP "Start Auto Select Unlock Proxy For【Gemini】..."
|
||||
LOG_TIP "【Gemini】Start Auto Select Unlock Proxy..."
|
||||
/usr/share/openclash/openclash_streaming_unlock.lua "Gemini" >> $LOG_FILE
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,6 +1,73 @@
|
||||
#!/bin/sh
|
||||
. /lib/functions.sh
|
||||
|
||||
uci_get_config() {
|
||||
local key="$1"
|
||||
uci -q get openclash.@overwrite[0]."$key" || uci -q get openclash.config."$key"
|
||||
}
|
||||
|
||||
uci_get_age_public_keys() {
|
||||
local name="$1"
|
||||
[ -n "$name" ] || return 0
|
||||
|
||||
_print_pub() {
|
||||
local section="$1"
|
||||
config_get cfg_name "$section" name
|
||||
if [ "$cfg_name" = "$name" ]; then
|
||||
config_get pub "$section" public
|
||||
[ -n "$pub" ] && printf '%s\n' "$pub"
|
||||
fi
|
||||
}
|
||||
|
||||
config_load openclash
|
||||
config_foreach _print_pub config_age_secret
|
||||
}
|
||||
|
||||
uci_get_age_secret_keys() {
|
||||
local name="$1"
|
||||
[ -n "$name" ] || return 0
|
||||
|
||||
_print_sec() {
|
||||
local section="$1"
|
||||
config_get cfg_name "$section" name
|
||||
if [ "$cfg_name" = "$name" ]; then
|
||||
config_get sec "$section" secret
|
||||
[ -n "$sec" ] && printf '%s\n' "$sec"
|
||||
fi
|
||||
}
|
||||
|
||||
config_load openclash
|
||||
config_foreach _print_sec config_age_secret
|
||||
}
|
||||
|
||||
uci_set_age_keys_by_name() {
|
||||
local name="$1"
|
||||
local secret="$2"
|
||||
local public="$3"
|
||||
local target_section=""
|
||||
|
||||
[ -n "$name" ] || return 1
|
||||
|
||||
_find_age_section() {
|
||||
local section="$1"
|
||||
local cfg_name
|
||||
config_get cfg_name "$section" name
|
||||
[ "$cfg_name" = "$name" ] && target_section="$section"
|
||||
}
|
||||
|
||||
config_load openclash
|
||||
config_foreach _find_age_section config_age_secret
|
||||
|
||||
if [ -z "$target_section" ]; then
|
||||
target_section=$(uci -q add openclash config_age_secret)
|
||||
fi
|
||||
|
||||
[ -n "$target_section" ] || return 1
|
||||
|
||||
uci -q set openclash."$target_section".name="$name"
|
||||
[ -n "$secret" ] && uci -q set openclash."$target_section".secret="$secret"
|
||||
[ -n "$public" ] && uci -q set openclash."$target_section".public="$public"
|
||||
uci -q commit openclash
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -427,9 +427,9 @@ begin
|
||||
Value['external-ui-url'] = 'https://codeload.github.com/MetaCubeX/Yacd-meta/zip/refs/heads/gh-pages'
|
||||
end
|
||||
when 'metacubexd'
|
||||
Value['external-ui-url'] = 'https://codeload.github.com/MetaCubeX/metacubexd/zip/refs/heads/gh-pages'
|
||||
Value['external-ui-url'] = 'https://codeload.github.com/MetaCubeX/metacubexd/zip/refs/heads/gh-pages'
|
||||
when 'zashboard'
|
||||
Value['external-ui-url'] = 'https://codeload.github.com/Zephyruso/zashboard/zip/refs/heads/gh-pages-cdn-fonts'
|
||||
Value['external-ui-url'] = 'https://codeload.github.com/Zephyruso/zashboard/zip/refs/heads/gh-pages-cdn-fonts'
|
||||
end
|
||||
if !Value.key?('keep-alive-interval') && !Value.key?('keep-alive-idle')
|
||||
Value['keep-alive-interval'] = 15
|
||||
@@ -456,7 +456,7 @@ begin
|
||||
end
|
||||
|
||||
if smart_collect
|
||||
(Value['profile'] ||= {})['smart-collector-size'] = smart_collect_size.to_f
|
||||
(Value['profile'] ||= {})['smart-collector-size'] = smart_collect_size.to_f
|
||||
end
|
||||
|
||||
Value['geox-url'] ||= {}
|
||||
|
||||
@@ -22,7 +22,7 @@ yml_other_set()
|
||||
begin
|
||||
thread_pool = [];
|
||||
# GEOIP replace
|
||||
geoip_pattern = /GEOIP,([A-Za-z]{2}),([^,]+)(,.*)?/;
|
||||
geoip_pattern = /^GEOIP,([A-Za-z]{2}),([^,]+)(,.*)?/;
|
||||
match_pattern = /(^MATCH.*|^FINAL.*)/;
|
||||
thread_pool << Thread.new{
|
||||
#BT/P2P DIRECT Rules
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* OpenClash Common JavaScript Utilities
|
||||
* Shared functions used across multiple view templates.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Detects if an element has a dark background by analyzing its computed CSS.
|
||||
* Used by CodeMirror log editor to set dark mode attribute.
|
||||
* @param {HTMLElement} element - The element to check
|
||||
* @returns {boolean} True if the background is dark
|
||||
*/
|
||||
function isDarkBackground(element) {
|
||||
var cachedTheme = localStorage.getItem('oc-theme');
|
||||
if (cachedTheme === 'dark') {
|
||||
return true;
|
||||
} else if (cachedTheme === 'light') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var style = window.getComputedStyle(element);
|
||||
var bgColor = style.backgroundColor;
|
||||
var r, g, b;
|
||||
if (/rgb\(/.test(bgColor)) {
|
||||
var rgb = bgColor.match(/\d+/g);
|
||||
r = parseInt(rgb[0]);
|
||||
g = parseInt(rgb[1]);
|
||||
b = parseInt(rgb[2]);
|
||||
} else if (/#/.test(bgColor)) {
|
||||
if (bgColor.length === 4) {
|
||||
r = parseInt(bgColor[1] + bgColor[1], 16);
|
||||
g = parseInt(bgColor[2] + bgColor[2], 16);
|
||||
b = parseInt(bgColor[3] + bgColor[3], 16);
|
||||
} else {
|
||||
r = parseInt(bgColor.slice(1, 3), 16);
|
||||
g = parseInt(bgColor.slice(3, 5), 16);
|
||||
b = parseInt(bgColor.slice(5, 7), 16);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
var luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||
return luminance < 128;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a URL in a new window. Used for external links (Wiki, GitHub, etc.).
|
||||
* @param {string} url - The URL to open
|
||||
* @returns {boolean} false to prevent default link behavior
|
||||
*/
|
||||
function winOpen(url) {
|
||||
var win = window.open(url);
|
||||
if (win == null || typeof(win) == 'undefined') {
|
||||
window.location.href = url;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in new issue
Block a user