update 2026-09-12 02:55:35

This commit is contained in:
action committed 2026-09-12 02:55:35 +08:00
1 parent 8daa9142b3
commit 7a00e14e57
24 files changed
+220 -209

No files matched your search

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 319 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 640 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 547 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 659 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

+1 -1
View File
@@ -1,7 +1,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-mosdns PKG_NAME:=luci-app-mosdns
PKG_VERSION:=1.7.13 PKG_VERSION:=1.7.14
PKG_RELEASE:=1 PKG_RELEASE:=1
LUCI_TITLE:=LuCI Support for mosdns LUCI_TITLE:=LuCI Support for mosdns
+21 -1
View File
@@ -429,7 +429,11 @@ generate_config() {
json_add_string "exec" "\$modify_ddns_ttl" json_add_string "exec" "\$modify_ddns_ttl"
json_close_object json_close_object
json_add_object json_add_object
json_add_string "matches" "!qname \$ddnslist" json_add_array "matches"
json_add_string "" "!qname \$ddnslist"
json_add_string "" "!qname \$blocklist"
json_add_string "" "!qname \$adlist"
json_close_array
json_add_string "exec" "\$modify_ttl" json_add_string "exec" "\$modify_ttl"
json_close_object json_close_object
[ "$cloudflare" -eq 1 ] && { [ "$cloudflare" -eq 1 ] && {
@@ -571,6 +575,22 @@ generate_config() {
json_add_array "args" json_add_array "args"
json_add_object json_add_object
json_add_string "matches" "qname \$blocklist" json_add_string "matches" "qname \$blocklist"
json_add_string "exec" "black_hole 0.0.0.0 ::"
json_close_object
json_add_object
json_add_string "matches" "qname \$adlist"
json_add_string "exec" "black_hole 0.0.0.0 ::"
json_close_object
json_add_object
json_add_string "matches" "has_resp"
json_add_string "exec" "ttl 3600"
json_close_object
json_add_object
json_add_string "matches" "has_resp"
json_add_string "exec" "accept"
json_close_object
json_add_object
json_add_string "matches" "qname \$blocklist"
json_add_string "exec" "reject 3" json_add_string "exec" "reject 3"
json_close_object json_close_object
json_add_object json_add_object
@@ -1846,8 +1846,8 @@ get_local_dns() {
RESOLVFILE=/tmp/resolv.conf.d/resolv.conf.auto RESOLVFILE=/tmp/resolv.conf.d/resolv.conf.auto
[ -f "${RESOLVFILE}" ] && [ -s "${RESOLVFILE}" ] || RESOLVFILE=/tmp/resolv.conf.auto [ -f "${RESOLVFILE}" ] && [ -s "${RESOLVFILE}" ] || RESOLVFILE=/tmp/resolv.conf.auto
ISP_DNS=$(cat $RESOLVFILE 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | grep -v -E '^(0\.0\.0\.0|127\.0\.0\.1)$' | awk '!seen[$0]++') ISP_DNS=$(grep -Eo "$IPv4_REGEX" "$RESOLVFILE" 2>/dev/null | grep -Ev '^(0\.0\.0\.0|127\.0\.0\.1)$' | awk '!seen[$0]++')
ISP_DNS6=$(cat $RESOLVFILE 2>/dev/null | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | awk -F % '{print $1}' | awk -F " " '{print $2}' | grep -v -Fx ::1 | grep -v -Fx :: | awk '!seen[$0]++') ISP_DNS6=$(grep -Eo "$IPv6_REGEX" "$RESOLVFILE" 2>/dev/null | awk -F% '{print $1}' | grep -Ev '^::1$|^::$' | awk '!seen[$0]++')
DEFAULT_DNS=$(uci show dhcp.@dnsmasq[0] | grep "\.server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' '\n' | grep -v "\/" | sed ':label;N;s/\n/,/;b label') DEFAULT_DNS=$(uci show dhcp.@dnsmasq[0] | grep "\.server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' '\n' | grep -v "\/" | sed ':label;N;s/\n/,/;b label')
[ -z "${DEFAULT_DNS}" ] && [ "$(echo $ISP_DNS | tr ' ' '\n' | wc -l)" -ge 1 ] && DEFAULT_DNS=$(echo -n $ISP_DNS | tr ' ' '\n' | tr '\n' ',' | sed 's/,$//') [ -z "${DEFAULT_DNS}" ] && [ "$(echo $ISP_DNS | tr ' ' '\n' | wc -l)" -ge 1 ] && DEFAULT_DNS=$(echo -n $ISP_DNS | tr ' ' '\n' | tr '\n' ',' | sed 's/,$//')
@@ -391,16 +391,16 @@ load_acl() {
local shunt_id local shunt_id
for shunt_id in $shunt_ids; do for shunt_id in $shunt_ids; do
[ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue [ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue
config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $shunt_set_name &/g" -e "s/$/ timeout 0/g" | ipset -! -R config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv4_REGEX" | sed -e "s/^/add $shunt_set_name &/g" -e "s/$/ timeout 0/g" | ipset -! -R
config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $shunt6_set_name &/g" -e "s/$/ timeout 0/g" | ipset -! -R config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv6_REGEX" | sed -e "s/^/add $shunt6_set_name &/g" -e "s/$/ timeout 0/g" | ipset -! -R
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
[ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code" [ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code"
} }
done done
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $shunt_set_name &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv4 | sed -e "s/^/add $shunt_set_name &/g" -e "s/$/ timeout 0/g" | ipset -! -R
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $shunt6_set_name &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv6 | sed -e "s/^/add $shunt6_set_name &/g" -e "s/$/ timeout 0/g" | ipset -! -R
fi fi
} }
} }
@@ -763,12 +763,12 @@ filter_haproxy() {
filter_vpsip() { filter_vpsip() {
local vps_addrs=$(uci show $CONFIG | grep -E "(\.address=|\.download_address=|\.domain_resolver_dns=|\.domain_resolver_dns_https=)" | cut -d "'" -f 2 | grep -Ev "$EXCLUDE_VPSIP") local vps_addrs=$(uci show $CONFIG | grep -E "(\.address=|\.download_address=|\.domain_resolver_dns=|\.domain_resolver_dns_https=)" | cut -d "'" -f 2 | grep -Ev "$EXCLUDE_VPSIP")
local ipv4_addrs=$(echo "$vps_addrs" | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}") local ipv4_addrs=$(echo "$vps_addrs" | grep -Eo "$IPv4_REGEX")
[ -n "$ipv4_addrs" ] && { [ -n "$ipv4_addrs" ] && {
echo "$ipv4_addrs" | sed "s/^/add $IPSET_VPS /" | awk '1; END{print "COMMIT"}' | ipset -! -R echo "$ipv4_addrs" | sed "s/^/add $IPSET_VPS /" | awk '1; END{print "COMMIT"}' | ipset -! -R
echolog " - [$?]加入所有IPv4节点服务器IP到ipset[$IPSET_VPS]直连完成" echolog " - [$?]加入所有IPv4节点服务器IP到ipset[$IPSET_VPS]直连完成"
} }
local ipv6_addrs=$(echo "$vps_addrs" | grep -Eo "\[?[A-Fa-f0-9:]*:[A-Fa-f0-9:]+\]?") local ipv6_addrs=$(echo "$vps_addrs" | grep -Eo "$IPv6_REGEX")
[ -n "$ipv6_addrs" ] && { [ -n "$ipv6_addrs" ] && {
echo "$ipv6_addrs" | sed "s/^/add $IPSET_VPS6 /" | awk '1; END{print "COMMIT"}' | ipset -! -R echo "$ipv6_addrs" | sed "s/^/add $IPSET_VPS6 /" | awk '1; END{print "COMMIT"}' | ipset -! -R
echolog " - [$?]加入所有IPv6节点服务器IP到ipset[$IPSET_VPS6]直连完成" echolog " - [$?]加入所有IPv6节点服务器IP到ipset[$IPSET_VPS6]直连完成"
@@ -776,8 +776,8 @@ filter_vpsip() {
#订阅方式为直连时 #订阅方式为直连时
local subscribe_host=$(get_subscribe_host | grep -Ev "$EXCLUDE_VPSIP") local subscribe_host=$(get_subscribe_host | grep -Ev "$EXCLUDE_VPSIP")
[ -n "$subscribe_host" ] && { [ -n "$subscribe_host" ] && {
echo "$subscribe_host" | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}" | sed "s/^/add $IPSET_VPS /" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R echo "$subscribe_host" | grep -Eo "$IPv4_REGEX" | sed "s/^/add $IPSET_VPS /" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R
echo "$subscribe_host" | grep -Eo "\[?[A-Fa-f0-9:]*:[A-Fa-f0-9:]+\]?" | sed "s/^/add $IPSET_VPS6 /" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R echo "$subscribe_host" | grep -Eo "$IPv6_REGEX" | sed "s/^/add $IPSET_VPS6 /" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R
} }
} }
@@ -929,13 +929,13 @@ add_firewall_rule() {
#直连列表 #直连列表
[ "$USE_DIRECT_LIST_ALL" = "1" ] && { [ "$USE_DIRECT_LIST_ALL" = "1" ] && {
cat $RULES_PATH/direct_ip | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $IPSET_WHITE &/g" -e "s/$/ timeout 0/g" | ipset -! -R cat $RULES_PATH/direct_ip | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv4_REGEX" | sed -e "s/^/add $IPSET_WHITE &/g" -e "s/$/ timeout 0/g" | ipset -! -R
cat $RULES_PATH/direct_ip | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $IPSET_WHITE6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R cat $RULES_PATH/direct_ip | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv6_REGEX" | sed -e "s/^/add $IPSET_WHITE6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local GEOIP_CODE=$(cat $RULES_PATH/direct_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local GEOIP_CODE=$(cat $RULES_PATH/direct_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $IPSET_WHITE &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv4 | sed -e "s/^/add $IPSET_WHITE &/g" -e "s/$/ timeout 0/g" | ipset -! -R
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $IPSET_WHITE6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv6 | sed -e "s/^/add $IPSET_WHITE6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R
echolog " - [$?]解析并加入[直连列表] GeoIP 到 IPSET 完成" echolog " - [$?]解析并加入[直连列表] GeoIP 到 IPSET 完成"
fi fi
} }
@@ -943,13 +943,13 @@ add_firewall_rule() {
#代理列表 #代理列表
[ "$USE_PROXY_LIST_ALL" = "1" ] && { [ "$USE_PROXY_LIST_ALL" = "1" ] && {
cat $RULES_PATH/proxy_ip | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $IPSET_BLACK &/g" -e "s/$/ timeout 0/g" | ipset -! -R cat $RULES_PATH/proxy_ip | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv4_REGEX" | sed -e "s/^/add $IPSET_BLACK &/g" -e "s/$/ timeout 0/g" | ipset -! -R
cat $RULES_PATH/proxy_ip | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $IPSET_BLACK6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R cat $RULES_PATH/proxy_ip | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv6_REGEX" | sed -e "s/^/add $IPSET_BLACK6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local GEOIP_CODE=$(cat $RULES_PATH/proxy_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local GEOIP_CODE=$(cat $RULES_PATH/proxy_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $IPSET_BLACK &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv4 | sed -e "s/^/add $IPSET_BLACK &/g" -e "s/$/ timeout 0/g" | ipset -! -R
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $IPSET_BLACK6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv6 | sed -e "s/^/add $IPSET_BLACK6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R
echolog " - [$?]解析并加入[代理列表] GeoIP 到 IPSET 完成" echolog " - [$?]解析并加入[代理列表] GeoIP 到 IPSET 完成"
fi fi
} }
@@ -957,13 +957,13 @@ add_firewall_rule() {
#屏蔽列表 #屏蔽列表
[ "$USE_BLOCK_LIST_ALL" = "1" ] && { [ "$USE_BLOCK_LIST_ALL" = "1" ] && {
cat $RULES_PATH/block_ip | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $IPSET_BLOCK &/g" -e "s/$/ timeout 0/g" | ipset -! -R cat $RULES_PATH/block_ip | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv4_REGEX" | sed -e "s/^/add $IPSET_BLOCK &/g" -e "s/$/ timeout 0/g" | ipset -! -R
cat $RULES_PATH/block_ip | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $IPSET_BLOCK6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R cat $RULES_PATH/block_ip | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv6_REGEX" | sed -e "s/^/add $IPSET_BLOCK6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local GEOIP_CODE=$(cat $RULES_PATH/block_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local GEOIP_CODE=$(cat $RULES_PATH/block_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $IPSET_BLOCK &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv4 | sed -e "s/^/add $IPSET_BLOCK &/g" -e "s/$/ timeout 0/g" | ipset -! -R
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $IPSET_BLOCK6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv6 | sed -e "s/^/add $IPSET_BLOCK6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R
echolog " - [$?]解析并加入[屏蔽列表] GeoIP 到 IPSET 完成" echolog " - [$?]解析并加入[屏蔽列表] GeoIP 到 IPSET 完成"
fi fi
} }
@@ -977,16 +977,16 @@ add_firewall_rule() {
local shunt_id local shunt_id
for shunt_id in $shunt_ids; do for shunt_id in $shunt_ids; do
[ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue [ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue
config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $IPSET_SHUNT &/g" -e "s/$/ timeout 0/g" | ipset -! -R config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv4_REGEX" | sed -e "s/^/add $IPSET_SHUNT &/g" -e "s/$/ timeout 0/g" | ipset -! -R
config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | grep -v "^#" | sed -e "/^$/d" | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $IPSET_SHUNT6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed 's/#.*//' | grep -E "$IPv6_REGEX" | sed -e "s/^/add $IPSET_SHUNT6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
[ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code" [ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code"
} }
done done
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | sed -e "s/^/add $IPSET_SHUNT &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv4 | sed -e "s/^/add $IPSET_SHUNT &/g" -e "s/$/ timeout 0/g" | ipset -! -R
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "s/^/add $IPSET_SHUNT6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R get_geoip $GEOIP_CODE ipv6 | sed -e "s/^/add $IPSET_SHUNT6 &/g" -e "s/$/ timeout 0/g" | ipset -! -R
echolog " - [$?]解析并加入[分流节点] GeoIP 到 IPSET 完成" echolog " - [$?]解析并加入[分流节点] GeoIP 到 IPSET 完成"
fi fi
} }
@@ -452,16 +452,16 @@ load_acl() {
local shunt_id local shunt_id
for shunt_id in $shunt_ids; do for shunt_id in $shunt_ids; do
[ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue [ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue
config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $shunt_set_name_static config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "$IPv4_REGEX" | insert_nftset $shunt_set_name_static
config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $shunt6_set_name_static config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "$IPv6_REGEX" | insert_nftset $shunt6_set_name_static
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
[ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code" [ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code"
} }
done done
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $shunt_set_name_static get_geoip $GEOIP_CODE ipv4 | insert_nftset $shunt_set_name_static
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $shunt6_set_name_static get_geoip $GEOIP_CODE ipv6 | insert_nftset $shunt6_set_name_static
fi fi
} }
} }
@@ -835,12 +835,12 @@ filter_vps_addr() {
filter_vpsip() { filter_vpsip() {
local vps_addrs=$(uci show $CONFIG | grep -E "(\.address=|\.download_address=|\.domain_resolver_dns=|\.domain_resolver_dns_https=)" | cut -d "'" -f 2 | grep -Ev "$EXCLUDE_VPSIP") local vps_addrs=$(uci show $CONFIG | grep -E "(\.address=|\.download_address=|\.domain_resolver_dns=|\.domain_resolver_dns_https=)" | cut -d "'" -f 2 | grep -Ev "$EXCLUDE_VPSIP")
local ipv4_addrs=$(echo "$vps_addrs" | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}") local ipv4_addrs=$(echo "$vps_addrs" | grep -Eo "$IPv4_REGEX")
[ -n "$ipv4_addrs" ] && { [ -n "$ipv4_addrs" ] && {
echo "$ipv4_addrs" | insert_nftset $NFTSET_VPS echo "$ipv4_addrs" | insert_nftset $NFTSET_VPS
echolog " - [$?]加入所有IPv4节点服务器IP到nftset[$NFTSET_VPS]直连完成" echolog " - [$?]加入所有IPv4节点服务器IP到nftset[$NFTSET_VPS]直连完成"
} }
local ipv6_addrs=$(echo "$vps_addrs" | grep -Eo "\[?[A-Fa-f0-9:]*:[A-Fa-f0-9:]+\]?") local ipv6_addrs=$(echo "$vps_addrs" | grep -Eo "$IPv6_REGEX")
[ -n "$ipv6_addrs" ] && { [ -n "$ipv6_addrs" ] && {
echo "$ipv6_addrs" | insert_nftset $NFTSET_VPS6 echo "$ipv6_addrs" | insert_nftset $NFTSET_VPS6
echolog " - [$?]加入所有IPv6节点服务器IP到nftset[$NFTSET_VPS6]直连完成" echolog " - [$?]加入所有IPv6节点服务器IP到nftset[$NFTSET_VPS6]直连完成"
@@ -848,8 +848,8 @@ filter_vpsip() {
#订阅方式为直连时 #订阅方式为直连时
local subscribe_host=$(get_subscribe_host | grep -Ev "$EXCLUDE_VPSIP") local subscribe_host=$(get_subscribe_host | grep -Ev "$EXCLUDE_VPSIP")
[ -n "$subscribe_host" ] && { [ -n "$subscribe_host" ] && {
echo "$subscribe_host" | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -Ev "$EXCLUDE_VPSIP" | insert_nftset $NFTSET_VPS echo "$subscribe_host" | grep -Eo "$IPv4_REGEX" | grep -Ev "$EXCLUDE_VPSIP" | insert_nftset $NFTSET_VPS
echo "$subscribe_host" | grep -Eo "\[?[A-Fa-f0-9:]*:[A-Fa-f0-9:]+\]?" | insert_nftset $NFTSET_VPS6 echo "$subscribe_host" | grep -Eo "$IPv6_REGEX" | insert_nftset $NFTSET_VPS6
} }
} }
@@ -1038,13 +1038,13 @@ add_firewall_rule() {
#直连列表 #直连列表
[ "$USE_DIRECT_LIST_ALL" = "1" ] && { [ "$USE_DIRECT_LIST_ALL" = "1" ] && {
cat $RULES_PATH/direct_ip | sed 's/#.*//' | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_WHITE_STATIC cat $RULES_PATH/direct_ip | sed 's/#.*//' | grep -E "$IPv4_REGEX" | insert_nftset $NFTSET_WHITE_STATIC
cat $RULES_PATH/direct_ip | sed 's/#.*//' | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_WHITE6_STATIC cat $RULES_PATH/direct_ip | sed 's/#.*//' | grep -E "$IPv6_REGEX" | insert_nftset $NFTSET_WHITE6_STATIC
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local GEOIP_CODE=$(cat $RULES_PATH/direct_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local GEOIP_CODE=$(cat $RULES_PATH/direct_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_WHITE_STATIC get_geoip $GEOIP_CODE ipv4 | insert_nftset $NFTSET_WHITE_STATIC
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_WHITE6_STATIC get_geoip $GEOIP_CODE ipv6 | insert_nftset $NFTSET_WHITE6_STATIC
echolog " - [$?]解析并加入[直连列表] GeoIP 到 NFTSET 完成" echolog " - [$?]解析并加入[直连列表] GeoIP 到 NFTSET 完成"
fi fi
} }
@@ -1052,13 +1052,13 @@ add_firewall_rule() {
#代理列表 #代理列表
[ "$USE_PROXY_LIST_ALL" = "1" ] && { [ "$USE_PROXY_LIST_ALL" = "1" ] && {
cat $RULES_PATH/proxy_ip | sed 's/#.*//' | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_BLACK_STATIC cat $RULES_PATH/proxy_ip | sed 's/#.*//' | grep -E "$IPv4_REGEX" | insert_nftset $NFTSET_BLACK_STATIC
cat $RULES_PATH/proxy_ip | sed 's/#.*//' | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_BLACK6_STATIC cat $RULES_PATH/proxy_ip | sed 's/#.*//' | grep -E "$IPv6_REGEX" | insert_nftset $NFTSET_BLACK6_STATIC
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local GEOIP_CODE=$(cat $RULES_PATH/proxy_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local GEOIP_CODE=$(cat $RULES_PATH/proxy_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_BLACK_STATIC get_geoip $GEOIP_CODE ipv4 | insert_nftset $NFTSET_BLACK_STATIC
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_BLACK6_STATIC get_geoip $GEOIP_CODE ipv6 | insert_nftset $NFTSET_BLACK6_STATIC
echolog " - [$?]解析并加入[代理列表] GeoIP 到 NFTSET 完成" echolog " - [$?]解析并加入[代理列表] GeoIP 到 NFTSET 完成"
fi fi
} }
@@ -1066,13 +1066,13 @@ add_firewall_rule() {
#屏蔽列表 #屏蔽列表
[ "$USE_BLOCK_LIST_ALL" = "1" ] && { [ "$USE_BLOCK_LIST_ALL" = "1" ] && {
cat $RULES_PATH/block_ip | sed 's/#.*//' | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_BLOCK_STATIC cat $RULES_PATH/block_ip | sed 's/#.*//' | grep -E "$IPv4_REGEX" | insert_nftset $NFTSET_BLOCK_STATIC
cat $RULES_PATH/block_ip | sed 's/#.*//' | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_BLOCK6_STATIC cat $RULES_PATH/block_ip | sed 's/#.*//' | grep -E "$IPv6_REGEX" | insert_nftset $NFTSET_BLOCK6_STATIC
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local GEOIP_CODE=$(cat $RULES_PATH/block_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local GEOIP_CODE=$(cat $RULES_PATH/block_ip | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_BLOCK_STATIC get_geoip $GEOIP_CODE ipv4 | insert_nftset $NFTSET_BLOCK_STATIC
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_BLOCK6_STATIC get_geoip $GEOIP_CODE ipv6 | insert_nftset $NFTSET_BLOCK6_STATIC
echolog " - [$?]解析并加入[屏蔽列表] GeoIP 到 NFTSET 完成" echolog " - [$?]解析并加入[屏蔽列表] GeoIP 到 NFTSET 完成"
fi fi
} }
@@ -1086,16 +1086,16 @@ add_firewall_rule() {
local shunt_id local shunt_id
for shunt_id in $shunt_ids; do for shunt_id in $shunt_ids; do
[ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue [ "${shunt_group}" != "$(config_n_get ${shunt_id} group)" ] && continue
config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_SHUNT_STATIC config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "$IPv4_REGEX" | insert_nftset $NFTSET_SHUNT_STATIC
config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_SHUNT6_STATIC config_n_get $shunt_id ip_list | sed 's/#.*//' | grep -E "$IPv6_REGEX" | insert_nftset $NFTSET_SHUNT6_STATIC
[ "$USE_GEOVIEW" = "1" ] && { [ "$USE_GEOVIEW" = "1" ] && {
local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g') local geoip_code=$(config_n_get $shunt_id ip_list | tr -s "\r\n" "\n" | sed -e "/^$/d" | grep -E "^geoip:" | grep -v "^geoip:private" | sed -E 's/^geoip:(.*)/\1/' | sed ':a;N;$!ba;s/\n/,/g')
[ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code" [ -n "$geoip_code" ] && GEOIP_CODE="${GEOIP_CODE:+$GEOIP_CODE,}$geoip_code"
} }
done done
if [ -n "$GEOIP_CODE" ]; then if [ -n "$GEOIP_CODE" ]; then
get_geoip $GEOIP_CODE ipv4 | grep -E "(\.((2(5[0-5]|[0-4][0-9]))|[0-1]?[0-9]{1,2})){3}" | insert_nftset $NFTSET_SHUNT_STATIC get_geoip $GEOIP_CODE ipv4 | insert_nftset $NFTSET_SHUNT_STATIC
get_geoip $GEOIP_CODE ipv6 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | insert_nftset $NFTSET_SHUNT6_STATIC get_geoip $GEOIP_CODE ipv6 | insert_nftset $NFTSET_SHUNT6_STATIC
echolog " - [$?]解析并加入[分流节点] GeoIP 到 NFTSET 完成" echolog " - [$?]解析并加入[分流节点] GeoIP 到 NFTSET 完成"
fi fi
} }
@@ -15,6 +15,20 @@ TMP_ROUTE_PATH=${TMP_PATH}/route
TMP_SCRIPT_FUNC_PATH=${TMP_PATH}/script_func TMP_SCRIPT_FUNC_PATH=${TMP_PATH}/script_func
RULES_PATH=/usr/share/${CONFIG}/rules RULES_PATH=/usr/share/${CONFIG}/rules
IPv6_REGEX="([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,7}:|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|"
IPv6_REGEX="${IPv6_REGEX}[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|"
IPv6_REGEX="${IPv6_REGEX}:((:[0-9a-fA-F]{1,4}){1,7}|:)|"
IPv6_REGEX="${IPv6_REGEX}fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|"
IPv6_REGEX="${IPv6_REGEX}::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
IPv4_REGEX="((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
. /lib/functions/network.sh . /lib/functions/network.sh
echolog() { echolog() {
@@ -85,12 +99,12 @@ get_host_ip() {
local isip="" local isip=""
local ip="" local ip=""
if [ "$1" = "ipv6" ]; then if [ "$1" = "ipv6" ]; then
isip=$(echo $host | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}") isip=$(echo $host | grep -Eo "$IPv6_REGEX")
if [ -n "$isip" ]; then if [ -n "$isip" ]; then
ip=$(echo "$host" | tr -d '[]') ip=$(echo "$host" | tr -d '[]')
fi fi
else else
isip=$(echo $host | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}") isip=$(echo $host | grep -Eo "$IPv4_REGEX")
[ -n "$isip" ] && ip=$isip [ -n "$isip" ] && ip=$isip
fi fi
[ -z "$isip" ] && { [ -z "$isip" ] && {
@@ -61,14 +61,11 @@ function getOption(config, section, opt) {
const id = `cbid.${config}.${section}.${opt}`; const id = `cbid.${config}.${section}.${opt}`;
obj = document.getElementsByName(id)[0] || document.getElementById(id); obj = document.getElementsByName(id)[0] || document.getElementById(id);
if (obj) { if (obj) {
//lua luci combobox
const combobox = document.getElementById('cbi.combobox.' + id); const combobox = document.getElementById('cbi.combobox.' + id);
if (combobox) { if (combobox) {
obj.combobox = combobox; obj.combobox = combobox;
} }
const div = document.getElementById(id);
if (div && div.getElementsByTagName("li").length > 0) {
obj = div;
}
return obj; return obj;
} else { } else {
return null; return null;
@@ -65,13 +65,13 @@ window.dl_dropdown_data["<%=cbid%>"] = <%=json.stringify(dropdown_data)%>;
</script> </script>
<div id="<%=cbid%>.main" class="dl-dropdown-container"> <div id="<%=cbid%>.main" class="dl-dropdown-container">
<select id="<%=cbid%>.ref" class="cbi-input-select" style="display:none !important;"> <div style="display:none !important;">
<option value>placeholder</option> <select id="<%=cbid%>.ref" class="cbi-input-select" style="display:none !important;">
</select> <option value>placeholder</option>
</select>
</div>
<!-- 已选节点显示区 --> <!-- 已选节点显示区 -->
<div id="<%=cbid%>.selected" class="dl-selected-list"></div> <div id="<%=cbid%>.selected" class="dl-selected-list"></div>
<!-- 模拟 listvalue 控件外观 --> <!-- 模拟 listvalue 控件外观 -->
<div class="cbi-input-value cbi-input-select dl-dropdown-display" id="<%=cbid%>.display" tabindex="0"> <div class="cbi-input-value cbi-input-select dl-dropdown-display" id="<%=cbid%>.display" tabindex="0">
<span id="<%=cbid%>.label" class="dl-dropdown-label"> <span id="<%=cbid%>.label" class="dl-dropdown-label">
@@ -90,9 +90,11 @@ window.lv_dropdown_data["<%=cbid%>"] = <%=json.stringify(dropdown_data)%>;
<div id="<%=cbid%>.main" class="lv-dropdown-container"> <div id="<%=cbid%>.main" class="lv-dropdown-container">
<!-- 隐藏 select(保存实际配置值) --> <!-- 隐藏 select(保存实际配置值) -->
<select id="<%=cbid%>" name="<%=cbid%>" class="cbi-input-select" data-update="change" style="display:none !important;"> <div style="display:none !important;">
<option value="<%=current_key%>" selected="selected">placeholder</option> <select id="<%=cbid%>" name="<%=cbid%>" class="cbi-input-select" data-update="change" style="display:none !important;">
</select> <option value="<%=current_key%>" selected="selected">placeholder</option>
</select>
</div>
<!-- 模拟 ListValue 控件外观 --> <!-- 模拟 ListValue 控件外观 -->
<div class="cbi-input-value cbi-input-select lv-dropdown-display" id="<%=cbid%>.display" tabindex="0"> <div class="cbi-input-value cbi-input-select lv-dropdown-display" id="<%=cbid%>.display" tabindex="0">
<span id="<%=cbid%>.label" class="lv-dropdown-label" title="<%=pcdata(current_label)%>"> <span id="<%=cbid%>.label" class="lv-dropdown-label" title="<%=pcdata(current_label)%>">
@@ -64,9 +64,11 @@ end
%> %>
<div id="<%=cbid%>" class="cbi-input-select" style="display:inline-block;"> <div id="<%=cbid%>" class="cbi-input-select" style="display:inline-block;">
<select id="<%=cbid%>.ref" class="cbi-input-select" style="display:none !important;"> <div style="display:none !important;">
<option value>placeholder</option> <select id="<%=cbid%>.ref" class="cbi-input-select" style="display:none !important;">
</select> <option value>placeholder</option>
</select>
</div>
<!-- 搜索框 --> <!-- 搜索框 -->
<input type="text" id="<%=cbid%>.search" <input type="text" id="<%=cbid%>.search"
class="mv_search_input cbi-input-text" class="mv_search_input cbi-input-text"
@@ -97,9 +97,11 @@ window.v_dropdown_data["<%=cbid%>"] = <%=json.stringify(dropdown_data)%>;
</script> </script>
<div id="<%=cbid%>.v-main" class="v-dropdown-container"> <div id="<%=cbid%>.v-main" class="v-dropdown-container">
<select id="<%=cbid%>.ref" class="cbi-input-select" style="display:none !important;"> <div style="display:none !important;">
<option value>placeholder</option> <select id="<%=cbid%>.ref" class="cbi-input-select" style="display:none !important;">
</select> <option value>placeholder</option>
</select>
</div>
<!-- 隐藏 input(保存实际配置值) --> <!-- 隐藏 input(保存实际配置值) -->
<input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" /> <input type="text" id="<%=cbid%>" name="<%=cbid%>" value="<%=current_key%>" data-update="change" style="display:none !important;" />
<!-- 模拟 ListValue 控件外观 --> <!-- 模拟 ListValue 控件外观 -->
@@ -26,12 +26,18 @@ local config = map.config
update_config(node_id, { update_config(node_id, {
remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value, remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value,
group: getOption("<%=config%>", "<%=sid%>", "group").value, group: getOption("<%=config%>", "<%=sid%>", "group").value,
type: getOption("<%=config%>", "<%=sid%>", "type").value, type: el.value,
protocol: '' protocol: ''
}, node_config_url); }, node_config_url);
} }
} }
}); });
const fromUrlCache = JSON.parse(sessionStorage.getItem("fromUrl"));
if (fromUrlCache && fromUrlCache.savetime && (Date.now() - fromUrlCache.timestamp) < fromUrlCache.savetime) {
fromUrl(fromUrlCache.link, true)
} else {
sessionStorage.removeItem("fromUrl");
}
}); });
waitForElement('select[name*="<%=config%>"][name*="protocol"]', function(el) { waitForElement('select[name*="<%=config%>"][name*="protocol"]', function(el) {
let o_val = el.value; let o_val = el.value;
@@ -56,7 +62,7 @@ local config = map.config
update_config(node_id, { update_config(node_id, {
remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value, remarks: getOption("<%=config%>", "<%=sid%>", "remarks").value,
group: getOption("<%=config%>", "<%=sid%>", "group").value, group: getOption("<%=config%>", "<%=sid%>", "group").value,
protocol: getOption("<%=config%>", "<%=sid%>", name).value, protocol: el.value,
}, node_config_url); }, node_config_url);
*/ */
} }
@@ -1,8 +1,8 @@
<%+cbi/valueheader%> <%+cbi/valueheader%>
<% <%
local api = require "luci.passwall2.api"
local appname = api.appname
local map = self.map local map = self.map
local api = map.api
local config = map.config
local has_ss_rust = api.is_finded("sslocal") local has_ss_rust = api.is_finded("sslocal")
local has_singbox = api.finded_com("sing-box") local has_singbox = api.finded_com("sing-box")
@@ -16,7 +16,7 @@ local hysteria2_type = api.get_core("hysteria2_type", {{has_singbox,"sing-box"},
local current_node = map:get(section) local current_node = map:get(section)
-%> -%>
<script src="<%=resource%>/view/<%=appname%>/qrcode.min.js"></script> <script src="<%=resource%>/view/<%=api.appname%>/qrcode.min.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
let has_singbox = "<%=has_singbox%>" let has_singbox = "<%=has_singbox%>"
let has_xray = "<%=has_xray%>" let has_xray = "<%=has_xray%>"
@@ -110,8 +110,7 @@ local current_node = map:get(section)
function buildUrl(btn, urlname, sid) { function buildUrl(btn, urlname, sid) {
var opt = { var opt = {
base: "cbid.<%=appname%>", base: "cbid.<%=config%>",
client: true,
get: function (opt) { get: function (opt) {
var id = this.base + "." + opt; var id = this.base + "." + opt;
var obj = document.getElementsByName(id)[0] || document.getElementsByClassName(id)[0] || document.getElementById(id) var obj = document.getElementsByName(id)[0] || document.getElementsByClassName(id)[0] || document.getElementById(id)
@@ -156,7 +155,6 @@ local current_node = map:get(section)
} }
} }
opt.base = "cbid." + urlname + "." + sid; opt.base = "cbid." + urlname + "." + sid;
opt.client = urlname.indexOf("server") === -1;
var v_type = opt.get("type").value; var v_type = opt.get("type").value;
var v_alias = opt.get("remarks"); var v_alias = opt.get("remarks");
@@ -733,35 +731,42 @@ local current_node = map:get(section)
if (!server) return ''; if (!server) return '';
return server.replace(/^\[/, '').replace(/\]$/, ''); return server.replace(/^\[/, '').replace(/\]$/, '');
} }
function tofromUrl(btn) {
let link = prompt('<%:Paste Share URL Here%>', '');
if (link === null || link === "") {
return false;
}
return fromUrl(link);
}
function fromUrl(btn, urlname, sid, cacheData) { function fromUrl(link, from_cache) {
var opt = { if (!link) {
base: 'cbid.<%=appname%>', return false;
client: true, }
const s = document.getElementById("<%=self.option%>-status");
if (!s) {
alert("Never");
return false;
}
s.innerHTML = "";
const current_type = '<%=current_node.type or ""%>';
let switch_type = null;
const opt = {
base: "cbid.<%=self.option%>.<%=self.value%>",
get: function (opt) { get: function (opt) {
var obj; return getOption("<%=config%>", "<%=self.value%>", opt);
var id = this.base + '.' + opt;
obj = document.getElementsByName(id)[0] || document.getElementById(id);
if (obj) {
var combobox = document.getElementById('cbi.combobox.' + id);
if (combobox) {
obj.combobox = combobox;
}
var div = document.getElementById(id);
if (div && div.getElementsByTagName("li").length > 0) {
obj = div;
}
return obj;
} else {
return null;
}
}, },
set: function (opt, val) { set: function (opt, val) {
if (!switch_type && opt == "type" && current_type != val) {
switch_type = val;
return;
}
var obj; var obj;
obj = this.get(opt); obj = this.get(opt);
if (obj) { if (obj) {
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
if (obj.type === 'checkbox') { if (obj.type === 'checkbox') {
obj.checked = val; obj.checked = val;
} else { } else {
@@ -795,7 +800,7 @@ local current_node = map:get(section)
} }
} }
try { try {
obj.dispatchEvent(event); obj.dispatchEvent(new Event("change", { bubbles: true, cancelable: true }));
} catch (err) {} } catch (err) {}
} else { } else {
//alert('<%:Faltal on set option, please help in debug: %>' + opt + ' = ' + val); //alert('<%:Faltal on set option, please help in debug: %>' + opt + ' = ' + val);
@@ -819,58 +824,20 @@ local current_node = map:get(section)
} }
} }
} }
},
setlist: function (opt, vlist) {
var id = this.base + "." + opt;
var objs = document.getElementsByName(id) || document.getElementsByClassName(id);
if (objs) {
var values = "";
for (var i = 0; i < vlist.length; i++) {
values += vlist[i] + ", ";
}
alert("Manually input the option:\n" + opt + "s:\n[" + values + "]");
} else {
//alert("<%:Faltal on set option, please help in debug: %>" + opt);
}
} }
} }
var s = document.getElementById(urlname + '-status'); link = link.split(/\r\n|\r|\n/, 1)[0];
if (!s) { link = link.replace(/&amp;/gi, '&').replace(/\s*#\s*/, '#').trim(); // Some odd links use "&" as "&", and include spaces before and after "#".
alert("Never"); const link_split = link.split('://');
return false; const link_type = link_split[0];
}
opt.base = "cbid." + urlname + "." + sid;
opt.client = urlname.indexOf("server") === -1;
var ssrurl = null;
if (cacheData) {
ssrurl = cacheData.ssrurl
} else {
ssrurl = prompt('<%:Paste Share URL Here%>', '');
if (ssrurl === null || ssrurl === "") {
return false;
}
sessionStorage.setItem("fromUrl", JSON.stringify({
timestamp: Date.now(),
savetime: 60 * 1000,
urlname: urlname,
sid: sid,
ssrurl: ssrurl
}));
}
ssrurl = ssrurl.split(/\r\n|\r|\n/, 1)[0];
ssrurl = ssrurl.replace(/&amp;/gi, '&').replace(/\s*#\s*/, '#').trim(); // Some odd links use "&" as "&", and include spaces before and after "#".
s.innerHTML = "";
var ssu = ssrurl.split('://');
var event = document.createEvent("HTMLEvents");
event.initEvent("change", true, true);
var dom_prefix = null let dom_prefix = null;
if (ssu[0] === "ssr") { if (link_type === "ssr") {
dom_prefix = "ssr_" dom_prefix = "ssr_"
//var b64c = ssu[1].match(/([A-Za-z0-9_-]+)/); //var b64c = link_split[1].match(/([A-Za-z0-9_-]+)/);
var sstr = b64decsafe((ssu[1] || "").replace(/#.*/, "").trim()); var sstr = b64decsafe((link_split[1] || "").replace(/#.*/, "").trim());
var ploc = sstr.indexOf("/?"); var ploc = sstr.indexOf("/?");
var url0 = "", param = ""; var url0 = "", param = "";
if (ploc > 0) { if (ploc > 0) {
@@ -905,8 +872,8 @@ local current_node = map:get(section)
if (typeof (rem) !== 'undefined' && rem !== '' && rem.length > 0) if (typeof (rem) !== 'undefined' && rem !== '' && rem.length > 0)
opt.set('remarks', b64decutf8safe(rem)); opt.set('remarks', b64decutf8safe(rem));
} }
if (ssu[0] === "ss") { if (link_type === "ss") {
var url0 = ssu[1] || ""; var url0 = link_split[1] || "";
param = ""; param = "";
var ploc = url0.indexOf("#"); var ploc = url0.indexOf("#");
@@ -981,15 +948,15 @@ local current_node = map:get(section)
queryParam.type && queryParam.type !== "tcp" && queryParam.type && queryParam.type !== "tcp" &&
queryParam.headerType && queryParam.headerType !== "none"; queryParam.headerType && queryParam.headerType !== "none";
if (has_xray && (ss_type == "xray" || needUpgrade || queryParam.type === "xhttp")) { if (has_xray && (ss_type == "xray" || needUpgrade || queryParam.type === "xhttp")) {
dom_prefix = "xray_" dom_prefix = "xray_";
opt.set('type', "Xray"); opt.set('type', "Xray");
opt.set(dom_prefix + 'protocol', "shadowsocks"); opt.set(dom_prefix + 'protocol', "shadowsocks");
} else if (has_singbox && (ss_type == "sing-box" || needUpgrade)) { } else if (has_singbox && (ss_type == "sing-box" || needUpgrade)) {
dom_prefix = "singbox_" dom_prefix = "singbox_";
opt.set('type', "sing-box"); opt.set('type', "sing-box");
opt.set(dom_prefix + 'protocol', "shadowsocks"); opt.set(dom_prefix + 'protocol', "shadowsocks");
} else if (ss_type == "shadowsocks-rust") { } else if (ss_type == "shadowsocks-rust") {
dom_prefix = "ssrust_" dom_prefix = "ssrust_";
opt.set('type', "SS-Rust"); opt.set('type', "SS-Rust");
} }
@@ -1189,17 +1156,17 @@ local current_node = map:get(section)
} }
} }
} }
if (ssu[0] === "trojan") { if (link_type === "trojan") {
if (trojan_type == "sing-box" && has_singbox) { if (trojan_type == "sing-box" && has_singbox) {
dom_prefix = "singbox_" dom_prefix = "singbox_";
opt.set('type', "sing-box"); opt.set('type', "sing-box");
opt.set(dom_prefix + 'protocol', "trojan"); opt.set(dom_prefix + 'protocol', "trojan");
} else { } else {
dom_prefix = "xray_" dom_prefix = "xray_";
opt.set('type', "Xray"); opt.set('type', "Xray");
opt.set(dom_prefix + 'protocol', "trojan"); opt.set(dom_prefix + 'protocol', "trojan");
} }
var m = parseNodeUrl(ssrurl); var m = parseNodeUrl(link);
var password = m.passwd; var password = m.passwd;
if (password === "") { if (password === "") {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>"; s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
@@ -1328,16 +1295,16 @@ local current_node = map:get(section)
opt.set('remarks', decodeURIComponent(m.hash.substr(1))); opt.set('remarks', decodeURIComponent(m.hash.substr(1)));
} }
} }
if (ssu[0] === "vmess") { if (link_type === "vmess") {
if (vmess_type == "sing-box" && has_singbox) { if (vmess_type == "sing-box" && has_singbox) {
dom_prefix = "singbox_" dom_prefix = "singbox_";
opt.set('type', "sing-box"); opt.set('type', "sing-box");
} else { } else {
dom_prefix = "xray_" dom_prefix = "xray_";
opt.set('type', "Xray"); opt.set('type', "Xray");
} }
opt.set(dom_prefix + 'protocol', "vmess"); opt.set(dom_prefix + 'protocol', "vmess");
var sstr = b64DecodeUnicode((ssu[1] || "").replace(/#.*/, "").trim()); var sstr = b64DecodeUnicode((link_split[1] || "").replace(/#.*/, "").trim());
var ploc = sstr.indexOf("/?"); var ploc = sstr.indexOf("/?");
var url0, param = ""; var url0, param = "";
if (ploc > 0) { if (ploc > 0) {
@@ -1429,14 +1396,14 @@ local current_node = map:get(section)
opt.set(dom_prefix + 'use_finalmask', !!ssm.fm); opt.set(dom_prefix + 'use_finalmask', !!ssm.fm);
opt.set(dom_prefix + 'finalmask', ssm.fm || ""); opt.set(dom_prefix + 'finalmask', ssm.fm || "");
} }
if (ssu[0] === "vless") { if (link_type === "vless") {
if (vless_type == "sing-box" && has_singbox) { if (vless_type == "sing-box" && has_singbox) {
dom_prefix = "singbox_"; dom_prefix = "singbox_";
} else { } else {
dom_prefix = "xray_"; dom_prefix = "xray_";
} }
var m = parseNodeUrl(ssrurl); var m = parseNodeUrl(link);
var password = m.passwd; var password = m.passwd;
if (password === "") { if (password === "") {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>"; s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
@@ -1458,7 +1425,7 @@ local current_node = map:get(section)
if (["xhttp", "kcp", "mkcp"].includes(queryParam.type) && vless_type !== "xray" && has_xray) { if (["xhttp", "kcp", "mkcp"].includes(queryParam.type) && vless_type !== "xray" && has_xray) {
dom_prefix = "xray_"; dom_prefix = "xray_";
} }
opt.set("type", dom_prefix === "singbox_" ? "sing-box" : "Xray"); opt.set('type', dom_prefix == "singbox_" ? "sing-box" : "Xray");
opt.set(dom_prefix + 'protocol', "vless"); opt.set(dom_prefix + 'protocol', "vless");
opt.set(dom_prefix + 'uuid', password); opt.set(dom_prefix + 'uuid', password);
@@ -1588,8 +1555,8 @@ local current_node = map:get(section)
opt.set('remarks', decodeURIComponent(m.hash.substr(1))); opt.set('remarks', decodeURIComponent(m.hash.substr(1)));
} }
} }
if (ssu[0] === "hysteria2" || ssu[0] === "hy2") { if (link_type === "hysteria2" || link_type === "hy2") {
var m = parseNodeUrl(ssrurl); var m = parseNodeUrl(link);
var password = m.passwd; var password = m.passwd;
if (password === "") { if (password === "") {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>"; s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
@@ -1639,13 +1606,13 @@ local current_node = map:get(section)
opt.set('remarks', decodeURIComponent(m.hash.substr(1))); opt.set('remarks', decodeURIComponent(m.hash.substr(1)));
} }
} }
if (ssu[0] === "tuic") { if (link_type === "tuic") {
if (has_singbox) { if (has_singbox) {
dom_prefix = "singbox_" dom_prefix = "singbox_";
opt.set('type', "sing-box"); opt.set('type', "sing-box");
} }
opt.set(dom_prefix + 'protocol', "tuic"); opt.set(dom_prefix + 'protocol', "tuic");
var _parsedUrl = new URL("http://" + ssu[1]); var _parsedUrl = new URL("http://" + link_split[1]);
var username = _parsedUrl.username; var username = _parsedUrl.username;
var password = _parsedUrl.password; var password = _parsedUrl.password;
var hostname = _parsedUrl.hostname; var hostname = _parsedUrl.hostname;
@@ -1688,13 +1655,13 @@ local current_node = map:get(section)
opt.set('remarks', decodeURIComponent(hash.substr(1))); opt.set('remarks', decodeURIComponent(hash.substr(1)));
} }
} }
if (ssu[0] === "anytls") { if (link_type === "anytls") {
if (has_singbox) { if (has_singbox) {
dom_prefix = "singbox_" dom_prefix = "singbox_";
opt.set('type', "sing-box"); opt.set('type', "sing-box");
} }
opt.set(dom_prefix + 'protocol', "anytls"); opt.set(dom_prefix + 'protocol', "anytls");
var m = parseNodeUrl(ssrurl); var m = parseNodeUrl(link);
var password = m.passwd; var password = m.passwd;
if (password === "") { if (password === "") {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>"; s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
@@ -1744,13 +1711,13 @@ local current_node = map:get(section)
opt.set('remarks', decodeURIComponent(m.hash.substr(1))); opt.set('remarks', decodeURIComponent(m.hash.substr(1)));
} }
} }
if (ssu[0] === "naive+https" || ssu[0] === "naive+quic") { if (link_type === "naive+https" || link_type === "naive+quic") {
if (has_singbox) { if (has_singbox) {
dom_prefix = "singbox_" dom_prefix = "singbox_";
opt.set('type', "sing-box"); opt.set('type', "sing-box");
} }
opt.set(dom_prefix + 'protocol', "naive"); opt.set(dom_prefix + 'protocol', "naive");
var _parsedUrl = new URL("http://" + ssu[1]); var _parsedUrl = new URL("http://" + link_split[1]);
var username = _parsedUrl.username; var username = _parsedUrl.username;
var password = _parsedUrl.password; var password = _parsedUrl.password;
var hostname = _parsedUrl.hostname; var hostname = _parsedUrl.hostname;
@@ -1785,7 +1752,7 @@ local current_node = map:get(section)
opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || '');
opt.set(dom_prefix + 'ech', !!queryParam.ech); opt.set(dom_prefix + 'ech', !!queryParam.ech);
opt.set(dom_prefix + 'ech_config', queryParam.ech || ''); opt.set(dom_prefix + 'ech_config', queryParam.ech || '');
if (ssu[0] === "naive+quic") { if (link_type === "naive+quic") {
opt.set(dom_prefix + 'naive_quic', true); opt.set(dom_prefix + 'naive_quic', true);
opt.set(dom_prefix + 'naive_congestion_control', queryParam.congestion_control || 'bbr'); opt.set(dom_prefix + 'naive_congestion_control', queryParam.congestion_control || 'bbr');
} }
@@ -1793,20 +1760,25 @@ local current_node = map:get(section)
opt.set('remarks', decodeURIComponent(hash.substr(1))); opt.set('remarks', decodeURIComponent(hash.substr(1)));
} }
} }
if (dom_prefix && dom_prefix != null) {
const port = opt.get(dom_prefix + 'port'); if (switch_type) {
if (!port) { sessionStorage.setItem("fromUrl", JSON.stringify({
return false; timestamp: Date.now(),
} savetime: 60 * 1000,
if (port.value) { link: link
port.focus(); }));
port.blur(); opt.set("type", switch_type);
} return
} else { }
if (!dom_prefix) {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>"; s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
sessionStorage.removeItem("fromUrl"); sessionStorage.removeItem("fromUrl");
return false; return false;
} }
if (opt.get(dom_prefix + 'port')) {
opt.get(dom_prefix + 'port').focus();
opt.get(dom_prefix + 'port').blur();
}
s.innerHTML = "<font color='green'><%:Import Finished %></font>"; s.innerHTML = "<font color='green'><%:Import Finished %></font>";
sessionStorage.removeItem("fromUrl"); sessionStorage.removeItem("fromUrl");
return true; return true;
@@ -1816,17 +1788,6 @@ local current_node = map:get(section)
window.open('<%=api.url("gen_client_config")%>?id=' + sid, "_blank") window.open('<%=api.url("gen_client_config")%>?id=' + sid, "_blank")
} }
document.addEventListener("DOMContentLoaded", function () {
setTimeout(function () {
const fromUrlCache = JSON.parse(sessionStorage.getItem("fromUrl"));
if (fromUrlCache && fromUrlCache.savetime && (Date.now() - fromUrlCache.timestamp) < fromUrlCache.savetime) {
fromUrl(null, fromUrlCache.urlname, fromUrlCache.sid, fromUrlCache)
} else {
sessionStorage.removeItem("fromUrl");
}
}, 500);
})
//]]></script> //]]></script>
<style> <style>
.share-toolbar { .share-toolbar {
@@ -1859,7 +1820,7 @@ local current_node = map:get(section)
<div class="share-toolbar"> <div class="share-toolbar">
<div class="toolbar-buttons"> <div class="toolbar-buttons">
<% if not current_node.protocol or not current_node.protocol:find("^_") then -%> <% if not current_node.protocol or not current_node.protocol:find("^_") then -%>
<input id="fromUrlBtn" type="button" class="btn cbi-button cbi-button-apply" value='<%:From Share URL%>' onclick="return fromUrl(this, '<%=self.option%>', '<%=self.value%>')" /> <input id="fromUrlBtn" type="button" class="btn cbi-button cbi-button-apply" value='<%:From Share URL%>' onclick="return tofromUrl()" />
<input id="exportUrlBtn" type="button" class="btn cbi-button cbi-button-apply" value='<%:Build Share URL%>' onclick="return exportUrl(this, '<%=self.option%>', '<%=self.value%>')" /> <input id="exportUrlBtn" type="button" class="btn cbi-button cbi-button-apply" value='<%:Build Share URL%>' onclick="return exportUrl(this, '<%=self.option%>', '<%=self.value%>')" />
<input id="genQrcodeBtn" type="button" class="btn cbi-button cbi-button-apply" value='<%:Generate QRCode%>' onclick="return genQrcode(this, '<%=self.option%>', '<%=self.value%>')" /> <input id="genQrcodeBtn" type="button" class="btn cbi-button cbi-button-apply" value='<%:Generate QRCode%>' onclick="return genQrcode(this, '<%=self.option%>', '<%=self.value%>')" />
<% end -%> <% end -%>
@@ -3,20 +3,21 @@ local map = self.map
local api = map.api local api = map.api
local appname = map.config local appname = map.config
local default_node_type = ""
local shunt_rule_list = {} local shunt_rule_list = {}
local node = map:get("@global[0]", "node") local node = map:get("@global[0]", "node")
if node then if node then
local node_type = map:get(node, "type")
local node_protocol = map:get(node, "protocol") local node_protocol = map:get(node, "protocol")
if (node_type == "Xray" or node_type == "sing-box") and node_protocol == "_shunt" then if node_protocol == "_shunt" then
default_node_type = node_protocol
local node_shunt_group = map:get(node, "shunt_group") local node_shunt_group = map:get(node, "shunt_group")
map:foreach("shunt_rules", function(e) map:foreach("shunt_rules", function(e)
if e[".name"] and e.remarks and e.group == node_shunt_group then if e[".name"] and e.remarks and e.group == node_shunt_group then
shunt_rule_list[#shunt_rule_list + 1] = e shunt_rule_list[#shunt_rule_list + 1] = e
end end
end) end)
shunt_rule_list[#shunt_rule_list + 1] = {
[".name"] = "default_node",
remarks = translate("Default")
}
end end
end end
-%> -%>
@@ -1664,7 +1665,7 @@ table td, .table .td {
<div style="position:absolute; right:0.5em; top: 0.5em;"><input class="btn cbi-button" type="button" onclick="set_node_div.close()" value="X" /></div> <div style="position:absolute; right:0.5em; top: 0.5em;"><input class="btn cbi-button" type="button" onclick="set_node_div.close()" value="X" /></div>
</div> </div>
<div class="cbi-value" style="justify-content: center; gap: 8px; margin: 1em 0;"> <div class="cbi-value" style="justify-content: center; gap: 8px; margin: 1em 0;">
<%- if default_node_type == "_shunt" then <%- if #shunt_rule_list > 0 then
for i, v in ipairs(shunt_rule_list) do for i, v in ipairs(shunt_rule_list) do
-%> -%>
<input class="btn cbi-button" type="button" onclick="set_node_div.set('<%=node%>', '<%=v[".name"]%>')" value="<%=v.remarks%>" /> <input class="btn cbi-button" type="button" onclick="set_node_div.set('<%=node%>', '<%=v[".name"]%>')" value="<%=v.remarks%>" />
@@ -671,16 +671,22 @@ add_script_mwan3() {
} }
} }
MWAN3_RULE_ARGS="-m connmark --mark ${FWMARK}/0xffffffff -j RETURN"
mwan3_stop() { mwan3_stop() {
nft list chain ip mangle mwan3_hook >/dev/null 2>&1 || return 0
local handles=$(nft -a list chain ip mangle mwan3_hook 2>/dev/null | grep "${FWMARK}" | awk -F '# handle ' '{print$2}') local handles=$(nft -a list chain ip mangle mwan3_hook 2>/dev/null | grep "${FWMARK}" | awk -F '# handle ' '{print$2}')
for handle in $handles; do for handle in $handles; do
nft delete rule ip mangle mwan3_hook handle ${handle} 2>/dev/null nft delete rule ip mangle mwan3_hook handle ${handle} 2>/dev/null
done done
while iptables -w 5 -t mangle -D mwan3_hook ${MWAN3_RULE_ARGS} >/dev/null 2>&1; do :; done
} }
mwan3_start() { mwan3_start() {
nft list chain ip mangle mwan3_hook >/dev/null 2>&1 || return 0
mwan3_stop mwan3_stop
nft list chain ip mangle mwan3_hook >/dev/null 2>&1 && nft insert rule ip mangle mwan3_hook ct mark ${FWMARK} counter return >/dev/null 2>&1 iptables -w 5 -t mangle -I mwan3_hook 1 ${MWAN3_RULE_ARGS} >/dev/null 2>&1 || \
logger -t passwall2 "mwan3: failed to add ${FWMARK} exemption rule to mangle/mwan3_hook"
} }
update_wan_sets() { update_wan_sets() {
@@ -39,10 +39,11 @@ do
mkdir -p $TMP_SUB_PATH mkdir -p $TMP_SUB_PATH
for item in $(uci show ${CONFIG} | grep "=subscribe_list" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do for item in $(uci show ${CONFIG} | grep "=subscribe_list" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
sub_update_week_mode=$(config_n_get $item update_week_mode) sub_update_week_mode=$(config_n_get $item update_week_mode)
if [ -n "$sub_update_week_mode" ]; then if [ -n "$sub_update_week_mode" ] && [ "$sub_update_week_mode" = "8" ]; then
remark=$(config_n_get $item remark)
sub_update_interval_mode=$(config_n_get $item update_interval_mode) sub_update_interval_mode=$(config_n_get $item update_interval_mode)
echo "$item" >> $TMP_SUB_PATH/${sub_update_week_mode}_${sub_update_interval_mode} [ -n "$sub_update_interval_mode" ] && {
echo "$item" >> $TMP_SUB_PATH/${sub_update_week_mode}_${sub_update_interval_mode}
}
fi fi
done done
@@ -55,7 +56,6 @@ do
[ "$sub_update_week_mode" = "8" ] && { [ "$sub_update_week_mode" = "8" ] && {
[ "$(expr "$CFG_UPDATE_INT" % "$sub_update_interval_mode")" -eq 0 ] && { lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 & } [ "$(expr "$CFG_UPDATE_INT" % "$sub_update_interval_mode")" -eq 0 ] && { lua $APP_PATH/subscribe.lua start $cfgids cron > /dev/null 2>&1 & }
} }
done done
rm -rf $TMP_SUB_PATH rm -rf $TMP_SUB_PATH
} }