From 19a44706dde7554f21c9d0503cdcfc399914067f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 15 Nov 2026 13:27:49 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9B=85=20Sync=202026-11-15=2013:27:49?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clashoo/Makefile | 4 +- .../share/clashoo/update/update_china_ip.sh | 49 +++++++++++++--- geo2txt/Makefile | 4 +- honk/Makefile | 6 +- libopenssl-gost/Makefile | 4 +- luci-app-fchomo/root/etc/init.d/fchomo | 2 +- luci-app-open-box/Makefile | 4 +- luci-app-passwall/Makefile | 2 +- .../root/usr/share/passwall/test.sh | 17 ++++-- luci-app-passwall2/Makefile | 2 +- .../root/usr/share/passwall2/test.sh | 29 +++++++--- .../root/usr/share/passwall2/utils.sh | 58 +++++++++---------- 12 files changed, 116 insertions(+), 65 deletions(-) diff --git a/clashoo/Makefile b/clashoo/Makefile index 597b43d69..b9352ff02 100644 --- a/clashoo/Makefile +++ b/clashoo/Makefile @@ -6,13 +6,13 @@ PKG_UPSTREAM_TAG:=v$(PKG_UPSTREAM_VERSION) PKG_SHORT_SHA:=0455d0d PKG_VERSION:=2026.11.12.$(PKG_UPSTREAM_VERSION) -PKG_RELEASE:=31 +PKG_RELEASE:=32 PKG_SOURCE:=$(PKG_NAME)-stable-$(PKG_UPSTREAM_TAG)-$(PKG_SHORT_SHA).tar.gz PKG_SOURCE_SUBDIR:=$(PKG_NAME)-stable-$(PKG_UPSTREAM_TAG)-$(PKG_SHORT_SHA) PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR) PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-clashoo/releases/download/mihomo-src -PKG_SOURCE_VERSION:=699f86a8fa8f94912881aa45be209f11ac9a691c +PKG_SOURCE_VERSION:=7c8892a626aadd6a7d7a6849210c95102800a066 PKG_HASH:=skip PKG_BUILD_VERSION:=$(PKG_UPSTREAM_TAG) diff --git a/clashoo/files/usr/share/clashoo/update/update_china_ip.sh b/clashoo/files/usr/share/clashoo/update/update_china_ip.sh index 8d31b73db..08990e6a2 100755 --- a/clashoo/files/usr/share/clashoo/update/update_china_ip.sh +++ b/clashoo/files/usr/share/clashoo/update/update_china_ip.sh @@ -14,6 +14,10 @@ TMP_V4="$TMP_ROOT/china_ip.txt" TMP_V6="$TMP_ROOT/china_ipv6.txt" OUT_V4="$TMP_ROOT/geoip_cn.nft" OUT_V6="$TMP_ROOT/geoip6_cn.nft" +# 失败现场放到固定路径:TMP_ROOT 会被 trap 清掉,事后才能回溯。 +KEEP_FAILED="${KEEP_FAILED:-/tmp/clashoo_china_ip_failed.txt}" +render_failure="" +render_detail="" log() { printf ' %s - %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$1" >> "$LOG_FILE" @@ -60,17 +64,23 @@ render_nft_set() { local output_file="$2" local set_name="$3" local set_type="$4" + local awk_log="$output_file.awk-error" + local nft_log="$output_file.nft-error" + + render_failure="" + render_detail="" awk -v set_name="$set_name" -v set_type="$set_type" ' function valid_cidr(value, parts, octets, i, prefix) { - if (split(value, parts, "/") != 2 || parts[2] !~ /^[0-9]+$/) + if (split(value, parts, "/") != 2 || parts[2] !~ /^[0-9]+$/ || parts[2] ~ /^0[0-9]/) return 0 prefix = parts[2] + 0 if (set_type == "ipv4_addr") { if (prefix > 32 || split(parts[1], octets, ".") != 4) return 0 + # nft 不认前导零(010.1.2.0/24),不在这里拦就只能等 nft 报错,看不出是哪一行 for (i = 1; i <= 4; i++) - if (octets[i] !~ /^[0-9]+$/ || length(octets[i]) > 3 || octets[i] + 0 > 255) + if (octets[i] !~ /^[0-9]+$/ || octets[i] ~ /^0[0-9]/ || length(octets[i]) > 3 || octets[i] + 0 > 255) return 0 return 1 } @@ -108,10 +118,35 @@ render_nft_set() { if (invalid || first) exit 1 } - ' "$source_file" > "$output_file" || return 1 + ' "$source_file" > "$output_file" 2>"$awk_log" || { + render_failure="格式校验失败" + render_detail=$(head -n 1 "$awk_log" 2>/dev/null) + return 1 + } # nft catches malformed IPv6 forms and invalid network prefixes before replacement. - { printf 'table inet clashoo_validate {\n'; cat "$output_file"; printf '\n}\n'; } | - nft -c -f - >/dev/null 2>&1 + if { printf 'table inet clashoo_validate {\n'; cat "$output_file"; printf '\n}\n'; } | + nft -c -f - >/dev/null 2>"$nft_log"; then + return 0 + fi + render_failure="nft 校验失败" + render_detail=$(head -n 1 "$nft_log" 2>/dev/null) + return 1 +} + +# 失败时保留现场:报错内容加下载到的原始文件,事后才能定位到行。 +report_render_failure() { + local label="$1" + local source_file="$2" + local lines + lines=$(grep -c '[^[:space:]]' "$source_file" 2>/dev/null || true) + [ -n "$render_detail" ] || render_detail="报错为空" + if cp -f "$source_file" "$KEEP_FAILED" 2>/dev/null; then + chmod 644 "$KEEP_FAILED" >/dev/null 2>&1 || true + log "${label}校验失败(${render_failure:-未知}),条目 ${lines:-?},$(nft --version 2>/dev/null | head -n 1),保留原文件;原始文件已存到 $KEEP_FAILED" + else + log "${label}校验失败(${render_failure:-未知}),条目 ${lines:-?},$(nft --version 2>/dev/null | head -n 1),保留原文件" + fi + log "${label}报错:$render_detail" } url4="$(uci -q get clashoo.config.china_ip_url 2>/dev/null || true)" @@ -135,7 +170,7 @@ download_with_fallback "$url4" "$TMP_V4" changed=0 if ! render_nft_set "$TMP_V4" "$OUT_V4" clashoo_china ipv4_addr; then - log '大陆 IPv4 白名单包含无效 CIDR,保留原文件' + report_render_failure '大陆 IPv4 白名单' "$TMP_V4" exit 1 fi if cmp -s "$OUT_V4" "$TARGET_V4"; then @@ -150,7 +185,7 @@ fi if download_with_fallback "$url6" "$TMP_V6"; then if [ -s "$TMP_V6" ]; then if ! render_nft_set "$TMP_V6" "$OUT_V6" clashoo_china6 ipv6_addr; then - log '大陆 IPv6 白名单包含无效 CIDR,保留原文件' + report_render_failure '大陆 IPv6 白名单' "$TMP_V6" exit 1 fi if cmp -s "$OUT_V6" "$TARGET_V6"; then diff --git a/geo2txt/Makefile b/geo2txt/Makefile index 09a7b2b2b..6bdb7c9bc 100644 --- a/geo2txt/Makefile +++ b/geo2txt/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=geo2txt -PKG_VERSION:=1.0.0 -PKG_RELEASE:=1 +PKG_VERSION:=1.0.1 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/sbwml/geo2txt/tar.gz/$(PKG_VERSION)? diff --git a/honk/Makefile b/honk/Makefile index 260487b4b..1fadc5f72 100644 --- a/honk/Makefile +++ b/honk/Makefile @@ -5,11 +5,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=honk -PKG_VERSION:=2026.11.13~d9d401e -PKG_RELEASE:=37 +PKG_VERSION:=2026.11.14~06eb039 +PKG_RELEASE:=38 HONK_SRC_URL:=https://github.com/daeuniverse/honk.git -HONK_SRC_VERSION:=d9d401e8dd4cfcbed84cff147b29fb8b2bb0c9b4 +HONK_SRC_VERSION:=06eb039792d20bff0eef526058483d1903be9e62 PKG_LICENSE:=AGPL-3.0-only PKG_LICENSE_FILES:=LICENSE diff --git a/libopenssl-gost/Makefile b/libopenssl-gost/Makefile index 458679b89..ffcdc1b56 100644 --- a/libopenssl-gost/Makefile +++ b/libopenssl-gost/Makefile @@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libopenssl-gost PKG_VERSION:=3.0.5 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/gost-engine/engine.git @@ -60,7 +60,7 @@ endef define Package/gost-utils SECTION:=utils CATEGORY:=Utilities - DEPENDS:=+libopenssl-gost-engine + DEPENDS:=+libopenssl TITLE+= GOST utilities endef diff --git a/luci-app-fchomo/root/etc/init.d/fchomo b/luci-app-fchomo/root/etc/init.d/fchomo index 1a9c2bf16..dc84ec4be 100755 --- a/luci-app-fchomo/root/etc/init.d/fchomo +++ b/luci-app-fchomo/root/etc/init.d/fchomo @@ -132,7 +132,7 @@ log() { start_service() { local client_enabled server_enabled - config_get client_enabled "routing" "client_enabled" "0" + config_get_bool client_enabled "routing" "client_enabled" "0" config_get_bool server_enabled "routing" "server_enabled" "0" if [ "$client_enabled" = "0" -a "$server_enabled" = "0" ]; then diff --git a/luci-app-open-box/Makefile b/luci-app-open-box/Makefile index 26b1b70d5..22742ff04 100644 --- a/luci-app-open-box/Makefile +++ b/luci-app-open-box/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-open-box -PKG_VERSION:=0.1.433 -PKG_RELEASE:=77 +PKG_VERSION:=0.1.437 +PKG_RELEASE:=78 PKG_MAINTAINER:=liandu2024 PKG_LICENSE:=GPL-3.0-or-later diff --git a/luci-app-passwall/Makefile b/luci-app-passwall/Makefile index c92f8589e..e976a315a 100644 --- a/luci-app-passwall/Makefile +++ b/luci-app-passwall/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=26.11.11 -PKG_RELEASE:=377 +PKG_RELEASE:=378 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall/root/usr/share/passwall/test.sh b/luci-app-passwall/root/usr/share/passwall/test.sh index a2bfbfcae..1579582cb 100755 --- a/luci-app-passwall/root/usr/share/passwall/test.sh +++ b/luci-app-passwall/root/usr/share/passwall/test.sh @@ -44,7 +44,7 @@ test_proxy() { echo $result } -url_test_node() { +url_test_node() ( local result=0 local node_id=$1 local test_flag="url_test_${node_id}_$$" @@ -67,11 +67,20 @@ url_test_node() { _password=$(config_n_get "$node_id" password) [ -n "${_username}" ] && [ -n "${_password}" ] && set -- --proxy-user "${_username}:${_password}" else + # 与其他临时节点测试互斥分配端口和启动代理,避免端口尚未监听时被重复选中。 + exec 8>"${LOCK_PATH}/${CONFIG}_socks_auto_switch_test.lock" + flock -x 8 || { echo 0; return 1; } _tmp_port=$(get_new_port $((48900 + $$ % 201)) tcp,udp) || { echo 0; return 1; } - NO_REC_PROCESS=1 /usr/share/${CONFIG}/app.sh run_socks flag="$test_flag" node="$node_id" bind=127.0.0.1 socks_port="$_tmp_port" config_file="${test_flag}.json" + NO_REC_PROCESS=1 /usr/share/${CONFIG}/app.sh run_socks flag="$test_flag" node="$node_id" bind=127.0.0.1 socks_port="$_tmp_port" config_file="${test_flag}.json" 8>&- curlx="socks5h://127.0.0.1:${_tmp_port}" fi - sleep 2s + sleep 2s 8>&- + # 监听就绪后释放启动锁,后续测试会通过端口占用检查避开当前端口。 + # 尚未监听或启动失败时,持锁到本次测试清理结束。 + if [ "$_type" != "socks" ] && [ "$(check_port_exists "$_tmp_port" tcp)" -gt 0 ]; then + flock -u 8 + exec 8>&- + fi probeUrl=$(config_n_get @global_other[0] url_test_url https://www.google.com/generate_204) # 预热代理链路,减轻首次请求的冷启动影响,提高部分节点的测试成功率和延迟稳定性 curl --connect-timeout 3 --max-time 5 -o /dev/null -I -sk "$@" -x "$curlx" "$probeUrl" >/dev/null 2>&1 @@ -85,7 +94,7 @@ url_test_node() { fi } printf '%s' "$result" -} +) arg1=$1 shift diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile index 12f359e49..6b46b9fa0 100644 --- a/luci-app-passwall2/Makefile +++ b/luci-app-passwall2/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 PKG_VERSION:=26.11.11 -PKG_RELEASE:=178 +PKG_RELEASE:=179 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall2/root/usr/share/passwall2/test.sh b/luci-app-passwall2/root/usr/share/passwall2/test.sh index 28f0a9309..aa2a1ddf2 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/test.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/test.sh @@ -41,27 +41,38 @@ test_proxy() { echo $result } -url_test_node() { - result=0 +url_test_node() ( + local result=0 local node_id=$1 + local test_flag="url_test_${node_id}_$$" + local _tmp_port local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z') [ -n "${_type}" ] && { - local _tmp_port=$(get_new_port 48900 tcp,udp) - NO_REC_PROCESS=1 /usr/share/${CONFIG}/app.sh run_socks flag="url_test_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=url_test_${node_id}.json + # Serialize port selection and startup with other temporary node tests. + exec 8>"${LOCK_PATH}/${CONFIG}_socks_auto_switch_test.lock" + flock -x 8 || { echo 0; return 1; } + _tmp_port=$(get_new_port 48900 tcp,udp) || { echo 0; return 1; } + NO_REC_PROCESS=1 /usr/share/${CONFIG}/app.sh run_socks flag="$test_flag" node="$node_id" bind=127.0.0.1 socks_port="$_tmp_port" config_file="${test_flag}.json" 8>&- local curlx="socks5h://127.0.0.1:${_tmp_port}" - sleep 2s + sleep 2s 8>&- + # Once listening, the socket itself prevents the next test from reusing the port. + # Keep the lock through cleanup if startup is still pending or has failed. + if [ "$(check_port_exists "$_tmp_port" tcp)" -gt 0 ]; then + flock -u 8 + exec 8>&- + fi local probeUrl=$(config_n_get @global_other[0] url_test_url https://www.google.com/generate_204) # Warm up the proxy connection to reduce cold-start effects on latency tests. curl --connect-timeout 3 --max-time 5 -o /dev/null -I -sk -x "$curlx" "$probeUrl" >/dev/null 2>&1 result=$(curl --connect-timeout 3 --max-time 5 -o /dev/null -I -skL -w "%{http_code}:%{time_pretransfer}" -x ${curlx} "${probeUrl}") # End the SS plugin process - local pid_file="${TMP_PATH}/url_test_${node_id}_plugin.pid" + local pid_file="${TMP_PATH}/${test_flag}_plugin.pid" [ -s "$pid_file" ] && kill -9 "$(head -n 1 "$pid_file")" >/dev/null 2>&1 - busybox pgrep -af "url_test_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1 - rm -rf ${TMP_PATH}/*url_test_${node_id}*.* + busybox pgrep -af "${TMP_PATH}/${test_flag}[._]" | awk '! /test\.sh/{print $1}' | xargs -r kill -9 >/dev/null 2>&1 + rm -f "$TMP_PATH/${test_flag}"*.* } echo $result -} +) arg1=$1 shift diff --git a/luci-app-passwall2/root/usr/share/passwall2/utils.sh b/luci-app-passwall2/root/usr/share/passwall2/utils.sh index d159826d4..76c84a949 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/utils.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/utils.sh @@ -282,45 +282,41 @@ get_new_port() { local default_start_port=2001 local min_port=1025 local max_port=49151 - local port=$1 #Required parameter; please pass "auto" if you want it to be automatic. - local last_get_new_port_auto - if [ "$1" == "auto" ]; then - last_get_new_port_auto=$(get_cache_var "last_get_new_port_auto") + local port="$1" # Required parameter; please pass "auto" if you want it to be automatic. + local protocol=$(echo "$2" | tr 'A-Z' 'a-z') + local is_auto + if [ "$port" = "auto" ]; then + is_auto=1 + local last_get_new_port_auto=$(get_cache_var "last_get_new_port_auto") if [ -n "$last_get_new_port_auto" ]; then - port=$last_get_new_port_auto - port=$(expr $port + 1) + port=$(expr "$last_get_new_port_auto" + 1) else port=$default_start_port fi fi - [ "$port" -lt $min_port -o "$port" -gt $max_port ] && port=$default_start_port - local protocol=$(echo $2 | tr 'A-Z' 'a-z') - local result=$(check_port_exists $port $protocol) - [ -n "$(get_cache_var "get_port_${port}")" ] && { - # exist, continue get. - # Make the following result logic true. - result=1 - } - if [ "$result" != 0 ]; then - local temp= - if [ "$port" -lt $max_port ]; then - # If the port is smaller than the maximum port, then increment by 1 and continue. - temp=$(expr $port + 1) - elif [ "$port" -gt $min_port ]; then - # If the port is greater than the minimum port, then decrement by 1 and continue. - temp=$(expr $port - 1) - else - # Otherwise, reassign the default starting port. - temp=$default_start_port + ([ "$port" -lt "$min_port" ] || [ "$port" -gt "$max_port" ]) && port=$default_start_port + local start_port=$port + while :; do + local result=$(check_port_exists "$port" "$protocol") + if [ "$is_auto" = "1" ] && [ -n "$(get_cache_var "get_port_${port}")" ]; then + # The port has already been allocated, continue to the next port. + result=1 fi - # Recursion, until it obtains an unused port. - get_new_port $temp $protocol - else - # Set cache, mark this port as already obtained, so it should not be obtained again. + [ "$result" = "0" ] && break + if [ "$port" -lt "$max_port" ]; then + # If the port is smaller than the maximum port, increment by 1 and continue. + port=$(expr "$port" + 1) + else + port=$min_port + fi + [ "$port" -eq "$start_port" ] && return 1 + done + if [ "$is_auto" = "1" ]; then + # Set cache to prevent the port from being allocated again. set_cache_var "get_port_${port}" "1" - [ "$1" == "auto" ] && set_cache_var "last_get_new_port_auto" "$port" - echo $port + set_cache_var "last_get_new_port_auto" "$port" fi + echo "$port" } has_1_65535() {