Усилить отказоустойчивость загрузки подписок
This commit is contained in:
@@ -147,6 +147,213 @@ has_outbound_section() {
|
||||
return $section_exists
|
||||
}
|
||||
|
||||
get_subscription_json_path() {
|
||||
local section="$1"
|
||||
|
||||
echo "$TMP_SUBSCRIPTION_FOLDER/${section}.json"
|
||||
}
|
||||
|
||||
get_subscription_url_cache_path() {
|
||||
local section="$1"
|
||||
|
||||
echo "$TMP_SUBSCRIPTION_FOLDER/${section}.url"
|
||||
}
|
||||
|
||||
subscription_cache_is_usable() {
|
||||
local subscription_json_path="$1"
|
||||
|
||||
[ -s "$subscription_json_path" ] || return 1
|
||||
|
||||
validate_subscription_file "$subscription_json_path"
|
||||
}
|
||||
|
||||
wait_for_subscription_connectivity() {
|
||||
local section="$1"
|
||||
local subscription_url="$2"
|
||||
local service_proxy_address="$3"
|
||||
local attempts="${4:-12}"
|
||||
local wait="${5:-5}"
|
||||
local timeout="${6:-5}"
|
||||
local attempt
|
||||
|
||||
for attempt in $(seq 1 "$attempts"); do
|
||||
if check_subscription_connectivity "$subscription_url" "$service_proxy_address" 1 0 "$timeout"; then
|
||||
log "Subscription connectivity check passed for section '$section'" "info"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Subscription source is unavailable for section '$section' [$attempt/$attempts]" "warn"
|
||||
[ "$attempt" -lt "$attempts" ] && sleep "$wait"
|
||||
done
|
||||
|
||||
log "Subscription connectivity check failed for section '$section' after $attempts attempts" "error"
|
||||
return 1
|
||||
}
|
||||
|
||||
download_subscription_into_cache() {
|
||||
local section="$1"
|
||||
local subscription_url="$2"
|
||||
local subscription_json_path="$3"
|
||||
local subscription_url_cache_path="$4"
|
||||
local service_proxy_address="$5"
|
||||
local tmpfile
|
||||
|
||||
mkdir -p "$TMP_SUBSCRIPTION_FOLDER"
|
||||
tmpfile="$(mktemp "$TMP_SUBSCRIPTION_FOLDER/${section}.download.XXXXXX")" || return 1
|
||||
|
||||
if ! download_subscription "$subscription_url" "$tmpfile" "$service_proxy_address" 3 2 10; then
|
||||
rm -f "$tmpfile"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! validate_subscription_file "$tmpfile"; then
|
||||
log "Downloaded subscription for section '$section' is invalid" "error"
|
||||
rm -f "$tmpfile"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -f "$subscription_json_path" ] && cmp -s "$tmpfile" "$subscription_json_path"; then
|
||||
rm -f "$tmpfile"
|
||||
printf '%s' "$subscription_url" > "$subscription_url_cache_path"
|
||||
log "Subscription for section '$section' is unchanged" "info"
|
||||
return 2
|
||||
fi
|
||||
|
||||
mv "$tmpfile" "$subscription_json_path" || {
|
||||
rm -f "$tmpfile"
|
||||
return 1
|
||||
}
|
||||
|
||||
printf '%s' "$subscription_url" > "$subscription_url_cache_path"
|
||||
return 0
|
||||
}
|
||||
|
||||
prepare_subscription_cache_for_startup() {
|
||||
local section="$1"
|
||||
local connection_type proxy_config_type subscription_url subscription_json_path subscription_url_cache_path
|
||||
local cached_subscription_url service_proxy_address had_usable_cache cache_needs_refresh
|
||||
|
||||
config_get connection_type "$section" "connection_type"
|
||||
[ "$connection_type" = "proxy" ] || return 0
|
||||
|
||||
config_get proxy_config_type "$section" "proxy_config_type"
|
||||
[ "$proxy_config_type" = "subscription" ] || return 0
|
||||
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
if [ -z "$subscription_url" ]; then
|
||||
log "Subscription URL is not set for section '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
subscription_json_path="$(get_subscription_json_path "$section")"
|
||||
subscription_url_cache_path="$(get_subscription_url_cache_path "$section")"
|
||||
cached_subscription_url=""
|
||||
had_usable_cache=0
|
||||
cache_needs_refresh=0
|
||||
|
||||
if subscription_cache_is_usable "$subscription_json_path"; then
|
||||
had_usable_cache=1
|
||||
else
|
||||
rm -f "$subscription_json_path"
|
||||
fi
|
||||
|
||||
if [ -f "$subscription_url_cache_path" ]; then
|
||||
cached_subscription_url="$(cat "$subscription_url_cache_path" 2> /dev/null)"
|
||||
fi
|
||||
|
||||
if [ "$had_usable_cache" -eq 0 ] || [ "$cached_subscription_url" != "$subscription_url" ]; then
|
||||
cache_needs_refresh=1
|
||||
fi
|
||||
|
||||
if [ "$cache_needs_refresh" -eq 0 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
service_proxy_address="$(get_service_proxy_address 2>/dev/null || echo '')"
|
||||
|
||||
if wait_for_subscription_connectivity "$section" "$subscription_url" "$service_proxy_address"; then
|
||||
if download_subscription_into_cache \
|
||||
"$section" "$subscription_url" "$subscription_json_path" "$subscription_url_cache_path" "$service_proxy_address"; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$had_usable_cache" -eq 1 ]; then
|
||||
log "Keeping cached subscription for section '$section' until a fresh download succeeds" "warn"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "No usable subscription cache for section '$section'; podkop startup will wait for internet connectivity" "warn"
|
||||
subscription_startup_blocked=1
|
||||
return 1
|
||||
}
|
||||
|
||||
prepare_subscription_caches_for_startup() {
|
||||
subscription_startup_blocked=0
|
||||
config_foreach prepare_subscription_cache_for_startup "section"
|
||||
|
||||
[ "$subscription_startup_blocked" -eq 0 ]
|
||||
}
|
||||
|
||||
stop_subscription_startup_retry_worker() {
|
||||
local pidfile="/var/run/podkop_subscription_retry.pid"
|
||||
|
||||
if [ -f "$pidfile" ]; then
|
||||
pid="$(cat "$pidfile" 2> /dev/null)"
|
||||
if [ -n "$pid" ] && kill -0 "$pid" 2> /dev/null; then
|
||||
kill "$pid" 2> /dev/null
|
||||
log "Stopped deferred startup recovery worker"
|
||||
fi
|
||||
rm -f "$pidfile"
|
||||
fi
|
||||
}
|
||||
|
||||
start_subscription_startup_retry_worker() {
|
||||
local pidfile="/var/run/podkop_subscription_retry.pid"
|
||||
|
||||
if [ -f "$pidfile" ]; then
|
||||
pid="$(cat "$pidfile" 2> /dev/null)"
|
||||
if [ -n "$pid" ] && kill -0 "$pid" 2> /dev/null; then
|
||||
log "Deferred startup recovery worker is already running" "debug"
|
||||
return 0
|
||||
fi
|
||||
rm -f "$pidfile"
|
||||
fi
|
||||
|
||||
(
|
||||
trap 'rm -f "'"$pidfile"'"' EXIT INT TERM
|
||||
|
||||
while true; do
|
||||
config_load "$PODKOP_CONFIG"
|
||||
|
||||
if prepare_subscription_caches_for_startup; then
|
||||
log "Subscription cache is ready, resuming deferred podkop startup" "info"
|
||||
rm -f "$pidfile"
|
||||
start_main
|
||||
start_rc=$?
|
||||
|
||||
if [ "$start_rc" -eq 0 ]; then
|
||||
config_get_bool dont_touch_dhcp "settings" "dont_touch_dhcp" 0
|
||||
if [ "$dont_touch_dhcp" -eq 0 ]; then
|
||||
dnsmasq_configure
|
||||
fi
|
||||
|
||||
uci_set "podkop" "settings" "shutdown_correctly" 0
|
||||
uci commit "podkop" && config_load "$PODKOP_CONFIG"
|
||||
fi
|
||||
|
||||
exit "$start_rc"
|
||||
fi
|
||||
|
||||
log "Deferred podkop startup is still waiting for subscription connectivity" "warn"
|
||||
sleep 10
|
||||
done
|
||||
) &
|
||||
|
||||
echo $! > "$pidfile"
|
||||
log "Started deferred startup recovery worker with PID $!" "warn"
|
||||
}
|
||||
|
||||
start_main() {
|
||||
log "Starting podkop"
|
||||
|
||||
@@ -167,6 +374,14 @@ start_main() {
|
||||
mkdir -p "$TMP_RULESET_FOLDER"
|
||||
mkdir -p "$TMP_SUBSCRIPTION_FOLDER"
|
||||
|
||||
if ! prepare_subscription_caches_for_startup; then
|
||||
log "Podkop startup is deferred until the subscription source becomes reachable" "warn"
|
||||
start_subscription_startup_retry_worker
|
||||
return 2
|
||||
fi
|
||||
|
||||
stop_subscription_startup_retry_worker
|
||||
|
||||
# base
|
||||
route_table_rule_mark
|
||||
create_nft_rules
|
||||
@@ -186,6 +401,8 @@ start_main() {
|
||||
stop_main() {
|
||||
log "Stopping the podkop"
|
||||
|
||||
stop_subscription_startup_retry_worker
|
||||
|
||||
if [ -f /var/run/podkop_list_update.pid ]; then
|
||||
pid=$(cat /var/run/podkop_list_update.pid)
|
||||
if kill -0 "$pid" 2> /dev/null; then
|
||||
@@ -220,6 +437,15 @@ stop_main() {
|
||||
|
||||
start() {
|
||||
start_main
|
||||
start_rc=$?
|
||||
|
||||
if [ "$start_rc" -eq 2 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [ "$start_rc" -ne 0 ]; then
|
||||
return "$start_rc"
|
||||
fi
|
||||
|
||||
config_get_bool dont_touch_dhcp "settings" "dont_touch_dhcp" 0
|
||||
if [ "$dont_touch_dhcp" -eq 0 ]; then
|
||||
@@ -245,8 +471,8 @@ stop() {
|
||||
|
||||
reload() {
|
||||
log "Podkop reload"
|
||||
stop_main
|
||||
start_main
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
restart() {
|
||||
@@ -587,7 +813,7 @@ ensure_nft_ready_for_list_update() {
|
||||
|
||||
|
||||
list_update() {
|
||||
echolog "🔄 Starting lists update..."
|
||||
echolog "рџ”„ Starting lists update..."
|
||||
|
||||
local nslookup_timeout=3
|
||||
local nslookup_attempts=10
|
||||
@@ -600,7 +826,7 @@ list_update() {
|
||||
# DNS Check
|
||||
for i in $(seq 1 $nslookup_attempts); do
|
||||
if nslookup -timeout=$nslookup_timeout openwrt.org > /dev/null 2>&1; then
|
||||
echolog "✅ DNS check passed"
|
||||
echolog "вњ… DNS check passed"
|
||||
break
|
||||
fi
|
||||
echolog "DNS is unavailable [$i/$nslookup_attempts]"
|
||||
@@ -608,7 +834,7 @@ list_update() {
|
||||
done
|
||||
|
||||
if [ "$i" -eq $nslookup_attempts ]; then
|
||||
echolog "❌ DNS check failed after $nslookup_attempts attempts"
|
||||
echolog "вќЊ DNS check failed after $nslookup_attempts attempts"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -619,12 +845,12 @@ list_update() {
|
||||
|
||||
if [ -n "$service_proxy_address" ]; then
|
||||
if curl -s -x "http://$service_proxy_address" -m $curl_timeout https://github.com > /dev/null; then
|
||||
echolog "✅ GitHub connection check passed (via proxy)"
|
||||
echolog "вњ… GitHub connection check passed (via proxy)"
|
||||
break
|
||||
fi
|
||||
else
|
||||
if curl -s -m $curl_timeout https://github.com > /dev/null; then
|
||||
echolog "✅ GitHub connection check passed"
|
||||
echolog "вњ… GitHub connection check passed"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
@@ -637,16 +863,16 @@ list_update() {
|
||||
done
|
||||
|
||||
if [ "$i" -eq $curl_attempts ]; then
|
||||
echolog "❌ GitHub connection check failed after $curl_attempts attempts"
|
||||
echolog "вќЊ GitHub connection check failed after $curl_attempts attempts"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! ensure_nft_ready_for_list_update; then
|
||||
echolog "❌ NFT table is unavailable, cannot update lists"
|
||||
echolog "вќЊ NFT table is unavailable, cannot update lists"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echolog "📥 Downloading and processing lists..."
|
||||
echolog "рџ“Ґ Downloading and processing lists..."
|
||||
|
||||
local update_failed=0
|
||||
config_foreach import_community_subnet_lists "section" || update_failed=1
|
||||
@@ -654,17 +880,19 @@ list_update() {
|
||||
config_foreach import_subnets_from_remote_subnet_lists "section" || update_failed=1
|
||||
|
||||
if [ "$update_failed" -eq 0 ]; then
|
||||
echolog "✅ Lists update completed successfully"
|
||||
echolog "вњ… Lists update completed successfully"
|
||||
else
|
||||
echolog "❌ Lists update failed"
|
||||
echolog "вќЊ Lists update failed"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
subscription_update() {
|
||||
echolog "🔄 Starting subscription update..."
|
||||
echolog "рџ”„ Starting subscription update..."
|
||||
|
||||
local has_subscription=0
|
||||
local updated_sections=0
|
||||
local failed_sections=0
|
||||
|
||||
_check_subscription_section() {
|
||||
local section="$1"
|
||||
@@ -683,13 +911,14 @@ subscription_update() {
|
||||
config_foreach _check_subscription_section "section"
|
||||
|
||||
if [ "$has_subscription" -eq 0 ]; then
|
||||
echolog "ℹ️ No subscription sections found, nothing to update"
|
||||
echolog "в„№пёЏ No subscription sections found, nothing to update"
|
||||
return 0
|
||||
fi
|
||||
|
||||
_update_subscription_for_section() {
|
||||
local section="$1"
|
||||
local connection_type proxy_config_type subscription_url subscription_json_path
|
||||
local subscription_url_cache_path service_proxy_address update_result outbounds_count
|
||||
|
||||
config_get connection_type "$section" "connection_type"
|
||||
if [ "$connection_type" != "proxy" ]; then
|
||||
@@ -704,31 +933,44 @@ subscription_update() {
|
||||
|
||||
config_get subscription_url "$section" "subscription_url"
|
||||
if [ -z "$subscription_url" ]; then
|
||||
echolog "❌ Subscription URL not set for section '$section'"
|
||||
echolog "вќЊ Subscription URL not set for section '$section'"
|
||||
failed_sections=$((failed_sections + 1))
|
||||
return
|
||||
fi
|
||||
|
||||
mkdir -p "$TMP_SUBSCRIPTION_FOLDER"
|
||||
subscription_json_path="$TMP_SUBSCRIPTION_FOLDER/${section}.json"
|
||||
local subscription_url_cache_path
|
||||
subscription_url_cache_path="$TMP_SUBSCRIPTION_FOLDER/${section}.url"
|
||||
subscription_json_path="$(get_subscription_json_path "$section")"
|
||||
subscription_url_cache_path="$(get_subscription_url_cache_path "$section")"
|
||||
|
||||
echolog "📥 Updating subscription for section '$section'..."
|
||||
echolog "рџ“Ґ Updating subscription for section '$section'..."
|
||||
|
||||
local service_proxy_address
|
||||
service_proxy_address="$(get_service_proxy_address 2>/dev/null || echo '')"
|
||||
|
||||
# Remove old cached file to force re-download
|
||||
rm -f "$subscription_json_path"
|
||||
download_subscription "$subscription_url" "$subscription_json_path" "$service_proxy_address"
|
||||
|
||||
if [ ! -f "$subscription_json_path" ] || [ ! -s "$subscription_json_path" ]; then
|
||||
echolog "❌ Failed to download subscription for section '$section'"
|
||||
if ! wait_for_subscription_connectivity "$section" "$subscription_url" "$service_proxy_address" 6 5 5; then
|
||||
echolog "вќЊ Failed to download subscription for section '$section'"
|
||||
failed_sections=$((failed_sections + 1))
|
||||
return
|
||||
fi
|
||||
|
||||
printf '%s' "$subscription_url" > "$subscription_url_cache_path"
|
||||
local outbounds_count
|
||||
download_subscription_into_cache \
|
||||
"$section" "$subscription_url" "$subscription_json_path" "$subscription_url_cache_path" "$service_proxy_address"
|
||||
update_result=$?
|
||||
|
||||
case "$update_result" in
|
||||
0)
|
||||
updated_sections=$((updated_sections + 1))
|
||||
;;
|
||||
2)
|
||||
echolog "в„№пёЏ Subscription for section '$section' is unchanged"
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echolog "вќЊ Failed to download subscription for section '$section'"
|
||||
failed_sections=$((failed_sections + 1))
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
outbounds_count=$(jq -r '[.outbounds[] | select(
|
||||
.type != "selector" and
|
||||
.type != "urltest" and
|
||||
@@ -737,13 +979,33 @@ subscription_update() {
|
||||
.type != "block"
|
||||
)] | length' "$subscription_json_path" 2>/dev/null)
|
||||
|
||||
echolog "✅ Subscription updated for section '$section': $outbounds_count outbounds"
|
||||
echolog "вњ… Subscription updated for section '$section': $outbounds_count outbounds"
|
||||
}
|
||||
config_foreach _update_subscription_for_section "section"
|
||||
|
||||
echolog "🔄 Restarting podkop to apply updated subscriptions..."
|
||||
if [ "$updated_sections" -eq 0 ]; then
|
||||
if [ "$failed_sections" -gt 0 ]; then
|
||||
echolog "вќЊ Subscription update finished with errors; keeping the last working cache"
|
||||
return 1
|
||||
fi
|
||||
|
||||
echolog "в„№пёЏ Subscription update completed: no changes detected"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echolog "рџ”„ Restarting podkop to apply updated subscriptions..."
|
||||
restart
|
||||
echolog "✅ Subscription update completed"
|
||||
restart_rc=$?
|
||||
if [ "$restart_rc" -ne 0 ]; then
|
||||
echolog "вќЊ Subscription was downloaded, but podkop restart failed"
|
||||
return "$restart_rc"
|
||||
fi
|
||||
|
||||
if [ "$failed_sections" -gt 0 ]; then
|
||||
echolog "вњ… Subscription update applied for changed sections; failed sections kept their previous cache"
|
||||
else
|
||||
echolog "вњ… Subscription update completed"
|
||||
fi
|
||||
}
|
||||
|
||||
# sing-box funcs
|
||||
@@ -1002,12 +1264,16 @@ configure_outbound_handler() {
|
||||
fi
|
||||
|
||||
mkdir -p "$TMP_SUBSCRIPTION_FOLDER"
|
||||
subscription_json_path="$TMP_SUBSCRIPTION_FOLDER/${section}.json"
|
||||
local subscription_url_cache_path cached_subscription_url should_download
|
||||
subscription_url_cache_path="$TMP_SUBSCRIPTION_FOLDER/${section}.url"
|
||||
subscription_json_path="$(get_subscription_json_path "$section")"
|
||||
local subscription_url_cache_path cached_subscription_url should_download had_usable_cache
|
||||
subscription_url_cache_path="$(get_subscription_url_cache_path "$section")"
|
||||
should_download=0
|
||||
had_usable_cache=0
|
||||
|
||||
if [ ! -f "$subscription_json_path" ] || [ ! -s "$subscription_json_path" ]; then
|
||||
if subscription_cache_is_usable "$subscription_json_path"; then
|
||||
had_usable_cache=1
|
||||
else
|
||||
rm -f "$subscription_json_path"
|
||||
should_download=1
|
||||
fi
|
||||
|
||||
@@ -1019,24 +1285,30 @@ configure_outbound_handler() {
|
||||
|
||||
if [ "$cached_subscription_url" != "$subscription_url" ]; then
|
||||
if [ -n "$cached_subscription_url" ]; then
|
||||
log "Subscription URL changed for section '$section', refreshing cache" "debug"
|
||||
log "Subscription URL changed for section '$section'" "warn"
|
||||
fi
|
||||
if [ "$had_usable_cache" -eq 0 ]; then
|
||||
should_download=1
|
||||
else
|
||||
log "Using cached subscription for section '$section' until a fresh download succeeds" "warn"
|
||||
fi
|
||||
should_download=1
|
||||
rm -f "$subscription_json_path"
|
||||
fi
|
||||
|
||||
if [ "$should_download" -eq 1 ]; then
|
||||
log "Downloading subscription for section '$section'"
|
||||
local service_proxy_address
|
||||
service_proxy_address="$(get_service_proxy_address 2>/dev/null || echo '')"
|
||||
download_subscription "$subscription_url" "$subscription_json_path" "$service_proxy_address"
|
||||
|
||||
if [ ! -f "$subscription_json_path" ] || [ ! -s "$subscription_json_path" ]; then
|
||||
log "Failed to download subscription for section '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
if ! wait_for_subscription_connectivity "$section" "$subscription_url" "$service_proxy_address" 6 5 5 ||
|
||||
! download_subscription_into_cache \
|
||||
"$section" "$subscription_url" "$subscription_json_path" "$subscription_url_cache_path" "$service_proxy_address"; then
|
||||
if [ "$had_usable_cache" -eq 1 ]; then
|
||||
log "Failed to refresh subscription for section '$section', continuing with cached data" "warn"
|
||||
else
|
||||
log "Failed to download subscription for section '$section'. Aborted." "fatal"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
printf '%s' "$subscription_url" > "$subscription_url_cache_path"
|
||||
fi
|
||||
|
||||
# Parse subscription outbounds
|
||||
@@ -1169,10 +1441,10 @@ configure_outbound_handler() {
|
||||
config=$(sing_box_cm_add_interface_outbound "$config" "$outbound_tag" "$interface_name" "$domain_resolver_tag")
|
||||
;;
|
||||
block)
|
||||
log "Connection type 'block' detected for the $section section – no outbound will be created (handled via reject route rules)"
|
||||
log "Connection type 'block' detected for the $section section – no outbound will be created (handled via reject route rules)"
|
||||
;;
|
||||
exclusion)
|
||||
log "Connection type 'exclusion' detected for the $section section – no outbound will be created (handled via route rules)"
|
||||
log "Connection type 'exclusion' detected for the $section section – no outbound will be created (handled via route rules)"
|
||||
;;
|
||||
*)
|
||||
log "Unknown connection type '$connection_type' for the $section section. Aborted." "fatal"
|
||||
@@ -2133,7 +2405,7 @@ check_nft() {
|
||||
|
||||
# Check if table exists
|
||||
if ! nft list table inet "$NFT_TABLE_NAME" > /dev/null 2>&1; then
|
||||
nolog "❌ $NFT_TABLE_NAME not found"
|
||||
nolog "вќЊ $NFT_TABLE_NAME not found"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -2782,9 +3054,9 @@ global_check() {
|
||||
local PODKOP_LUCI_VERSION="Unknown"
|
||||
[ -n "$1" ] && PODKOP_LUCI_VERSION="$1"
|
||||
|
||||
print_global "📡 Global check run!"
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "🛠️ System info"
|
||||
print_global "рџ“Ў Global check run!"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "рџ› пёЏ System info"
|
||||
|
||||
local system_info_json
|
||||
system_info_json=$(get_system_info)
|
||||
@@ -2799,17 +3071,17 @@ global_check() {
|
||||
openwrt_version=$(echo "$system_info_json" | jq -r '.openwrt_version // "unknown"')
|
||||
device_model=$(echo "$system_info_json" | jq -r '.device_model // "unknown"')
|
||||
|
||||
print_global "🕳️ Podkop: $podkop_version (latest: $podkop_latest_version)"
|
||||
print_global "🕳️ LuCI App: $luci_app_version"
|
||||
print_global "📦 Sing-box: $sing_box_version"
|
||||
print_global "🛜 OpenWrt: $openwrt_version"
|
||||
print_global "🛜 Device: $device_model"
|
||||
print_global "рџ•іпёЏ Podkop: $podkop_version (latest: $podkop_latest_version)"
|
||||
print_global "рџ•іпёЏ LuCI App: $luci_app_version"
|
||||
print_global "📦 Sing-box: $sing_box_version"
|
||||
print_global "рџ›њ OpenWrt: $openwrt_version"
|
||||
print_global "рџ›њ Device: $device_model"
|
||||
else
|
||||
print_global "❌ Failed to get system info"
|
||||
print_global "вќЊ Failed to get system info"
|
||||
fi
|
||||
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "➡️ DNS status"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "вћЎпёЏ DNS status"
|
||||
|
||||
local dns_check_json
|
||||
dns_check_json=$(check_dns_available)
|
||||
@@ -2828,24 +3100,24 @@ global_check() {
|
||||
# Bootstrap DNS
|
||||
if [ -n "$bootstrap_dns_server" ]; then
|
||||
if [ "$bootstrap_dns_status" -eq 1 ]; then
|
||||
print_global "✅ Bootstrap DNS: $bootstrap_dns_server"
|
||||
print_global "вњ… Bootstrap DNS: $bootstrap_dns_server"
|
||||
else
|
||||
print_global "❌ Bootstrap DNS: $bootstrap_dns_server"
|
||||
print_global "вќЊ Bootstrap DNS: $bootstrap_dns_server"
|
||||
fi
|
||||
fi
|
||||
|
||||
# DNS server status
|
||||
if [ "$dns_status" -eq 1 ]; then
|
||||
print_global "✅ Main DNS: $dns_server [$dns_type]"
|
||||
print_global "вњ… Main DNS: $dns_server [$dns_type]"
|
||||
else
|
||||
print_global "❌ Main DNS: $dns_server [$dns_type]"
|
||||
print_global "вќЊ Main DNS: $dns_server [$dns_type]"
|
||||
fi
|
||||
|
||||
# DNS on router
|
||||
if [ "$dns_on_router" -eq 1 ]; then
|
||||
print_global "✅ DNS on router"
|
||||
print_global "вњ… DNS on router"
|
||||
else
|
||||
print_global "❌ DNS on router"
|
||||
print_global "вќЊ DNS on router"
|
||||
fi
|
||||
|
||||
# DHCP configuration check
|
||||
@@ -2853,20 +3125,20 @@ global_check() {
|
||||
config_get dont_touch_dhcp "settings" "dont_touch_dhcp"
|
||||
|
||||
if [ "$dont_touch_dhcp" = "1" ]; then
|
||||
print_global "⚠️ dont_touch_dhcp is enabled. 📄 DHCP config:"
|
||||
print_global "вљ пёЏ dont_touch_dhcp is enabled. рџ“„ DHCP config:"
|
||||
awk '/^config /{p=($2=="dnsmasq")} p' /etc/config/dhcp
|
||||
elif [ "$dhcp_config_status" -eq 0 ]; then
|
||||
print_global "❌ DHCP configuration differs from template. 📄 DHCP config:"
|
||||
print_global "вќЊ DHCP configuration differs from template. рџ“„ DHCP config:"
|
||||
awk '/^config /{p=($2=="dnsmasq")} p' /etc/config/dhcp
|
||||
else
|
||||
print_global "✅ /etc/config/dhcp"
|
||||
print_global "вњ… /etc/config/dhcp"
|
||||
fi
|
||||
else
|
||||
print_global "❌ Failed to get DNS info"
|
||||
print_global "вќЊ Failed to get DNS info"
|
||||
fi
|
||||
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "📦 Sing-box status"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "📦 Sing-box status"
|
||||
|
||||
local singbox_check_json
|
||||
singbox_check_json=$(check_sing_box)
|
||||
@@ -2882,46 +3154,46 @@ global_check() {
|
||||
sing_box_ports_listening=$(echo "$singbox_check_json" | jq -r '.sing_box_ports_listening // 0')
|
||||
|
||||
if [ "$sing_box_installed" -eq 1 ]; then
|
||||
print_global "✅ Sing-box installed"
|
||||
print_global "вњ… Sing-box installed"
|
||||
else
|
||||
print_global "❌ Sing-box installed"
|
||||
print_global "вќЊ Sing-box installed"
|
||||
fi
|
||||
|
||||
if [ "$sing_box_version_ok" -eq 1 ]; then
|
||||
print_global "✅ Sing-box version is compatible (newer than 1.12.4)"
|
||||
print_global "вњ… Sing-box version is compatible (newer than 1.12.4)"
|
||||
else
|
||||
print_global "❌ Sing-box version is not compatible (older than 1.12.4)"
|
||||
print_global "вќЊ Sing-box version is not compatible (older than 1.12.4)"
|
||||
fi
|
||||
|
||||
if [ "$sing_box_service_exist" -eq 1 ]; then
|
||||
print_global "✅ Sing-box service exist"
|
||||
print_global "вњ… Sing-box service exist"
|
||||
else
|
||||
print_global "❌ Sing-box service exist"
|
||||
print_global "вќЊ Sing-box service exist"
|
||||
fi
|
||||
|
||||
if [ "$sing_box_autostart_disabled" -eq 1 ]; then
|
||||
print_global "✅ Sing-box autostart disabled"
|
||||
print_global "вњ… Sing-box autostart disabled"
|
||||
else
|
||||
print_global "❌ Sing-box autostart disabled"
|
||||
print_global "вќЊ Sing-box autostart disabled"
|
||||
fi
|
||||
|
||||
if [ "$sing_box_process_running" -eq 1 ]; then
|
||||
print_global "✅ Sing-box process running"
|
||||
print_global "вњ… Sing-box process running"
|
||||
else
|
||||
print_global "❌ Sing-box process running"
|
||||
print_global "вќЊ Sing-box process running"
|
||||
fi
|
||||
|
||||
if [ "$sing_box_ports_listening" -eq 1 ]; then
|
||||
print_global "✅ Sing-box listening ports"
|
||||
print_global "вњ… Sing-box listening ports"
|
||||
else
|
||||
print_global "❌ Sing-box listening ports"
|
||||
print_global "вќЊ Sing-box listening ports"
|
||||
fi
|
||||
else
|
||||
print_global "❌ Failed to get sing-box info"
|
||||
print_global "вќЊ Failed to get sing-box info"
|
||||
fi
|
||||
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "🧱 NFT rules status"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "рџ§± NFT rules status"
|
||||
|
||||
local nft_check_json
|
||||
nft_check_json=$(check_nft_rules)
|
||||
@@ -2939,78 +3211,78 @@ global_check() {
|
||||
rules_other_mark_exist=$(echo "$nft_check_json" | jq -r '.rules_other_mark_exist // 0')
|
||||
|
||||
if [ "$table_exist" -eq 1 ]; then
|
||||
print_global "✅ Table exist"
|
||||
print_global "вњ… Table exist"
|
||||
else
|
||||
print_global "❌ Table exist"
|
||||
print_global "вќЊ Table exist"
|
||||
fi
|
||||
|
||||
if [ "$rules_mangle_exist" -eq 1 ]; then
|
||||
print_global "✅ Rules mangle exist"
|
||||
print_global "вњ… Rules mangle exist"
|
||||
else
|
||||
print_global "❌ Rules mangle exist"
|
||||
print_global "вќЊ Rules mangle exist"
|
||||
fi
|
||||
|
||||
if [ "$rules_mangle_counters" -eq 1 ]; then
|
||||
print_global "✅ Rules mangle counters"
|
||||
print_global "вњ… Rules mangle counters"
|
||||
else
|
||||
print_global "⚠️ Rules mangle counters"
|
||||
print_global "вљ пёЏ Rules mangle counters"
|
||||
fi
|
||||
|
||||
if [ "$rules_mangle_output_exist" -eq 1 ]; then
|
||||
print_global "✅ Rules mangle output exist"
|
||||
print_global "вњ… Rules mangle output exist"
|
||||
else
|
||||
print_global "❌ Rules mangle output exist"
|
||||
print_global "вќЊ Rules mangle output exist"
|
||||
fi
|
||||
|
||||
if [ "$rules_mangle_output_counters" -eq 1 ]; then
|
||||
print_global "✅ Rules mangle output counters"
|
||||
print_global "вњ… Rules mangle output counters"
|
||||
else
|
||||
print_global "⚠️ Rules mangle output counters"
|
||||
print_global "вљ пёЏ Rules mangle output counters"
|
||||
fi
|
||||
|
||||
if [ "$rules_proxy_exist" -eq 1 ]; then
|
||||
print_global "✅ Rules proxy exist"
|
||||
print_global "вњ… Rules proxy exist"
|
||||
else
|
||||
print_global "❌ Rules proxy exist"
|
||||
print_global "вќЊ Rules proxy exist"
|
||||
fi
|
||||
|
||||
if [ "$rules_proxy_counters" -eq 1 ]; then
|
||||
print_global "✅ Rules proxy counters"
|
||||
print_global "вњ… Rules proxy counters"
|
||||
else
|
||||
print_global "⚠️ Rules proxy counters"
|
||||
print_global "вљ пёЏ Rules proxy counters"
|
||||
fi
|
||||
|
||||
if [ "$rules_other_mark_exist" -eq 1 ]; then
|
||||
print_global "⚠️ Additional marking rules found:"
|
||||
print_global "вљ пёЏ Additional marking rules found:"
|
||||
nft list ruleset | awk '/table inet '"$NFT_TABLE_NAME"'/{flag=1; next} /^table/{flag=0} !flag' | grep -E "mark set|meta mark"
|
||||
else
|
||||
print_global "✅ Additional marking rules found"
|
||||
print_global "вњ… Additional marking rules found"
|
||||
fi
|
||||
else
|
||||
print_global "❌ Failed to get NFT rules info"
|
||||
print_global "вќЊ Failed to get NFT rules info"
|
||||
fi
|
||||
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "📄 Podkop config"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "рџ“„ Podkop config"
|
||||
show_config
|
||||
|
||||
# print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
# print_global "🔧 System check"
|
||||
# print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
# print_global "рџ”§ System check"
|
||||
|
||||
# if grep -E "^nameserver\s+([0-9]{1,3}\.){3}[0-9]{1,3}" "$RESOLV_CONF" | grep -vqE "127\.0\.0\.1|0\.0\.0\.0"; then
|
||||
# print_global "❌ /etc/resolv.conf contains external nameserver:"
|
||||
# print_global "вќЊ /etc/resolv.conf contains external nameserver:"
|
||||
# cat /etc/resolv.conf
|
||||
# echo ""
|
||||
# else
|
||||
# print_global "✅ /etc/resolv.conf"
|
||||
# print_global "вњ… /etc/resolv.conf"
|
||||
# fi
|
||||
|
||||
# print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
# print_global "🧱 NFT table"
|
||||
# print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
# print_global "рџ§± NFT table"
|
||||
# check_nft
|
||||
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "📄 WAN config"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "рџ“„ WAN config"
|
||||
if uci show network.wan > /dev/null 2>&1; then
|
||||
awk '
|
||||
/^config / {
|
||||
@@ -3031,20 +3303,20 @@ global_check() {
|
||||
}
|
||||
' /etc/config/network
|
||||
else
|
||||
print_global "❌ WAN configuration not found"
|
||||
print_global "вќЊ WAN configuration not found"
|
||||
fi
|
||||
|
||||
if uci show network | grep -q endpoint_host; then
|
||||
uci show network | grep endpoint_host | cut -d'=' -f2 | tr -d "'\" " | while read -r host; do
|
||||
if [ "$host" = "engage.cloudflareclient.com" ]; then
|
||||
print_global "⚠️ WARP detected: $host"
|
||||
print_global "вљ пёЏ WARP detected: $host"
|
||||
continue
|
||||
fi
|
||||
|
||||
ip_prefix=$(echo "$host" | cut -d'.' -f1,2)
|
||||
if echo "$CLOUDFLARE_OCTETS" | grep -wq "$ip_prefix"; then
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "⚠️ WARP detected: $host"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "вљ пёЏ WARP detected: $host"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
@@ -3055,19 +3327,19 @@ global_check() {
|
||||
allowed_ips=$(uci get "${peer_section}.allowed_ips" 2> /dev/null)
|
||||
|
||||
if [ "$allowed_ips" = "0.0.0.0/0" ]; then
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "⚠️ WG Route allowed IP enabled with 0.0.0.0/0"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "вљ пёЏ WG Route allowed IP enabled with 0.0.0.0/0"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -f "/etc/init.d/zapret" ]; then
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "⚠️ Zapret detected"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "вљ пёЏ Zapret detected"
|
||||
fi
|
||||
|
||||
print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
print_global "🥸 FakeIP status"
|
||||
print_global "в”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓв”Ѓ"
|
||||
print_global "🥸 FakeIP status"
|
||||
|
||||
local fakeip_check_json
|
||||
fakeip_check_json=$(check_fakeip)
|
||||
@@ -3078,21 +3350,21 @@ global_check() {
|
||||
fakeip_status=$(echo "$fakeip_check_json" | jq -r '.fakeip // false')
|
||||
|
||||
if [ "$fakeip_status" = "true" ]; then
|
||||
print_global "✅ Router DNS is routed through sing-box"
|
||||
print_global "вњ… Router DNS is routed through sing-box"
|
||||
else
|
||||
print_global "⚠️ Router DNS is NOT routed through sing-box"
|
||||
print_global "вљ пёЏ Router DNS is NOT routed through sing-box"
|
||||
fi
|
||||
else
|
||||
print_global "❌ Failed to get FakeIP info"
|
||||
print_global "вќЊ Failed to get FakeIP info"
|
||||
fi
|
||||
|
||||
local fakeip_address
|
||||
fakeip_address=$(dig +short @127.0.0.42 $FAKEIP_TEST_DOMAIN)
|
||||
|
||||
if echo "$fakeip_address" | grep -q "^198\.18\."; then
|
||||
print_global "✅ Sing-box works with FakeIP: $fakeip_address"
|
||||
print_global "вњ… Sing-box works with FakeIP: $fakeip_address"
|
||||
else
|
||||
print_global "❌ Sing-box does NOT work with FakeIP: $fakeip_address"
|
||||
print_global "вќЊ Sing-box does NOT work with FakeIP: $fakeip_address"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -417,6 +417,7 @@ download_subscription() {
|
||||
local http_proxy_address="$3"
|
||||
local retries="${4:-3}"
|
||||
local wait="${5:-2}"
|
||||
local timeout="${6:-10}"
|
||||
|
||||
local sb_version device_model kernel_version hwid
|
||||
sb_version="$(get_sing_box_version)"
|
||||
@@ -424,24 +425,100 @@ download_subscription() {
|
||||
kernel_version="$(get_kernel_version)"
|
||||
hwid="$(generate_hwid)"
|
||||
|
||||
local header_args=""
|
||||
header_args="--header='User-Agent: singbox/$sb_version'"
|
||||
header_args="$header_args --header='X-HWID: $hwid'"
|
||||
header_args="$header_args --header='X-Device-OS: OpenWrt Linux'"
|
||||
header_args="$header_args --header='X-Device-Model: $device_model'"
|
||||
header_args="$header_args --header='X-Ver-OS: $kernel_version'"
|
||||
header_args="$header_args --header='Accept-Language: ru-RU,en,*'"
|
||||
header_args="$header_args --header='X-Device-Locale: EN'"
|
||||
local tmpfile
|
||||
tmpfile="${filepath}.part.$$"
|
||||
rm -f "$tmpfile"
|
||||
|
||||
for attempt in $(seq 1 "$retries"); do
|
||||
if [ -n "$http_proxy_address" ]; then
|
||||
http_proxy="http://$http_proxy_address" https_proxy="http://$http_proxy_address" \
|
||||
eval wget -O "$filepath" $header_args "$url" && break
|
||||
wget -T "$timeout" -t 1 -O "$tmpfile" \
|
||||
--header "User-Agent: singbox/$sb_version" \
|
||||
--header "X-HWID: $hwid" \
|
||||
--header "X-Device-OS: OpenWrt Linux" \
|
||||
--header "X-Device-Model: $device_model" \
|
||||
--header "X-Ver-OS: $kernel_version" \
|
||||
--header "Accept-Language: ru-RU,en,*" \
|
||||
--header "X-Device-Locale: EN" \
|
||||
"$url"
|
||||
else
|
||||
eval wget -O "$filepath" $header_args "$url" && break
|
||||
wget -T "$timeout" -t 1 -O "$tmpfile" \
|
||||
--header "User-Agent: singbox/$sb_version" \
|
||||
--header "X-HWID: $hwid" \
|
||||
--header "X-Device-OS: OpenWrt Linux" \
|
||||
--header "X-Device-Model: $device_model" \
|
||||
--header "X-Ver-OS: $kernel_version" \
|
||||
--header "Accept-Language: ru-RU,en,*" \
|
||||
--header "X-Device-Locale: EN" \
|
||||
"$url"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ] && [ -s "$tmpfile" ]; then
|
||||
mv "$tmpfile" "$filepath"
|
||||
return 0
|
||||
fi
|
||||
|
||||
rm -f "$tmpfile"
|
||||
log "Attempt $attempt/$retries to download subscription from $url failed" "warn"
|
||||
sleep "$wait"
|
||||
done
|
||||
}
|
||||
|
||||
rm -f "$tmpfile"
|
||||
return 1
|
||||
}
|
||||
|
||||
check_subscription_connectivity() {
|
||||
local url="$1"
|
||||
local http_proxy_address="$2"
|
||||
local retries="${3:-3}"
|
||||
local wait="${4:-2}"
|
||||
local timeout="${5:-5}"
|
||||
|
||||
local sb_version device_model kernel_version hwid
|
||||
sb_version="$(get_sing_box_version)"
|
||||
device_model="$(get_device_model)"
|
||||
kernel_version="$(get_kernel_version)"
|
||||
hwid="$(generate_hwid)"
|
||||
|
||||
local attempt
|
||||
for attempt in $(seq 1 "$retries"); do
|
||||
if [ -n "$http_proxy_address" ]; then
|
||||
http_proxy="http://$http_proxy_address" https_proxy="http://$http_proxy_address" \
|
||||
wget -q -T "$timeout" -t 1 -O /dev/null \
|
||||
--header "User-Agent: singbox/$sb_version" \
|
||||
--header "X-HWID: $hwid" \
|
||||
--header "X-Device-OS: OpenWrt Linux" \
|
||||
--header "X-Device-Model: $device_model" \
|
||||
--header "X-Ver-OS: $kernel_version" \
|
||||
--header "Accept-Language: ru-RU,en,*" \
|
||||
--header "X-Device-Locale: EN" \
|
||||
"$url" && return 0
|
||||
else
|
||||
wget -q -T "$timeout" -t 1 -O /dev/null \
|
||||
--header "User-Agent: singbox/$sb_version" \
|
||||
--header "X-HWID: $hwid" \
|
||||
--header "X-Device-OS: OpenWrt Linux" \
|
||||
--header "X-Device-Model: $device_model" \
|
||||
--header "X-Ver-OS: $kernel_version" \
|
||||
--header "Accept-Language: ru-RU,en,*" \
|
||||
--header "X-Device-Locale: EN" \
|
||||
"$url" && return 0
|
||||
fi
|
||||
|
||||
[ "$attempt" -lt "$retries" ] && sleep "$wait"
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
validate_subscription_file() {
|
||||
local filepath="$1"
|
||||
|
||||
[ -s "$filepath" ] || return 1
|
||||
|
||||
jq -e '
|
||||
type == "object" and
|
||||
(.outbounds | type == "array") and
|
||||
((.outbounds | length) > 0)
|
||||
' "$filepath" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user