Merge pull request #11 from VizzleTF/main

feat: Add diagnostic checks
This commit is contained in:
itdoginfo
2024-12-14 14:53:31 +03:00
committed by GitHub
5 changed files with 454 additions and 44 deletions

View File

@@ -7,6 +7,8 @@ DOWNLOAD_DIR="/tmp/podkop"
mkdir -p "$DOWNLOAD_DIR" mkdir -p "$DOWNLOAD_DIR"
main() { main() {
check_system
wget -qO- "$REPO" | grep -o 'https://[^"]*\.ipk' | while read -r url; do wget -qO- "$REPO" | grep -o 'https://[^"]*\.ipk' | while read -r url; do
filename=$(basename "$url") filename=$(basename "$url")
echo "Download $filename..." echo "Download $filename..."
@@ -384,4 +386,24 @@ wg_awg_setup() {
handler_network_restart handler_network_restart
} }
check_system() {
# Get router model
MODEL=$(cat /tmp/sysinfo/model)
echo "Router model: $MODEL"
# Check available space
AVAILABLE_SPACE=$(df /tmp | awk 'NR==2 {print $4}')
REQUIRED_SPACE=20480 # 20MB in KB
echo "Available space: $((AVAILABLE_SPACE/1024))MB"
echo "Required space: $((REQUIRED_SPACE/1024))MB"
if [ "$AVAILABLE_SPACE" -lt "$REQUIRED_SPACE" ]; then
echo "Error: Insufficient space in /tmp"
echo "Available: $((AVAILABLE_SPACE/1024))MB"
echo "Required: $((REQUIRED_SPACE/1024))MB"
exit 1
fi
}
main main

View File

@@ -3,6 +3,7 @@
'require form'; 'require form';
'require ui'; 'require ui';
'require network'; 'require network';
'require fs';
return view.extend({ return view.extend({
async render() { async render() {
@@ -626,6 +627,163 @@ return view.extend({
return true; return true;
}; };
o = s.tab('diagnostics', _('Diagnostics'));
function formatDiagnosticOutput(output) {
if (!output) return '';
return output
.replace(/\x1B\[[0-9;]*[mK]/g, '')
.replace(/\[[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\] /g, '')
.replace(/\n{3,}/g, '\n\n')
.replace(/===\s+(.*?)\s+===/g, (_, title) => `\n${title}\n${'─'.repeat(title.length)}`)
.replace(/^Checking\s+(.+)\.{3}/gm, '► Checking $1...')
.replace(/:\s+(available|not found)$/gm, (_, status) =>
`: ${status === 'available' ? '✓' : '✗'}`);
}
// Check All - полная диагностика
o = s.taboption('diagnostics', form.Button, '_check_all');
o.title = _('Main Check');
o.description = _('Run a comprehensive diagnostic check of all components');
o.inputtitle = _('Run Check');
o.inputstyle = 'apply';
o.onclick = function () {
return fs.exec('/etc/init.d/podkop', ['check_three'])
.then(function (res) {
const formattedOutput = formatDiagnosticOutput(res.stdout || _('No output'));
const modalElement = ui.showModal(_('Full Diagnostic Results'), [
E('div', {
style:
'max-height: 70vh;' +
'overflow-y: auto;' +
'margin: 1em 0;' +
'padding: 1.5em;' +
'background: #f8f9fa;' +
'border: 1px solid #e9ecef;' +
'border-radius: 4px;' +
'font-family: monospace;' +
'white-space: pre-wrap;' +
'word-wrap: break-word;' +
'line-height: 1.5;' +
'font-size: 14px;'
}, [
E('pre', { style: 'margin: 0;' }, formattedOutput)
]),
E('div', {
style: 'display: flex; justify-content: space-between; margin-top: 1em;'
}, [
E('button', {
'class': 'btn',
'click': function () {
const textarea = document.createElement('textarea');
textarea.value = '```txt\n' + formattedOutput + '\n```';
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
} catch (err) {
ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message));
}
document.body.removeChild(textarea);
}
}, _('Copy to Clipboard')),
E('button', {
'class': 'btn',
'click': ui.hideModal
}, _('Close'))
])
], 'large');
if (modalElement && modalElement.parentElement) {
modalElement.parentElement.style.width = '90%';
modalElement.parentElement.style.maxWidth = '1200px';
modalElement.parentElement.style.margin = '2rem auto';
}
});
};
o = s.taboption('diagnostics', form.Button, '_check_logs');
o.title = _('System Logs');
o.description = _('View recent system logs related to Podkop');
o.inputtitle = _('View Logs');
o.inputstyle = 'apply';
o.onclick = function () {
return fs.exec('/etc/init.d/podkop', ['check_logs'])
.then(function (res) {
const formattedOutput = formatDiagnosticOutput(res.stdout || _('No output'));
const modalElement = ui.showModal(_('System Logs'), [
E('div', {
style:
'max-height: 70vh;' +
'overflow-y: auto;' +
'margin: 1em 0;' +
'padding: 1.5em;' +
'background: #f8f9fa;' +
'border: 1px solid #e9ecef;' +
'border-radius: 4px;' +
'font-family: monospace;' +
'white-space: pre-wrap;' +
'word-wrap: break-word;' +
'line-height: 1.5;' +
'font-size: 14px;'
}, [
E('pre', { style: 'margin: 0;' }, formattedOutput)
]),
E('div', {
style: 'display: flex; justify-content: space-between; margin-top: 1em;'
}, [
E('button', {
'class': 'btn',
'click': function () {
const textarea = document.createElement('textarea');
textarea.value = '```txt\n' + formattedOutput + '\n```';
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
} catch (err) {
ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message));
}
document.body.removeChild(textarea);
}
}, _('Copy to Clipboard')),
E('button', {
'class': 'btn',
'click': ui.hideModal
}, _('Close'))
])
], 'large');
if (modalElement && modalElement.parentElement) {
modalElement.parentElement.style.width = '90%';
modalElement.parentElement.style.maxWidth = '1200px';
modalElement.parentElement.style.margin = '2rem auto';
}
});
};
o = s.taboption('diagnostics', form.Button, '_list_update');
o.title = _('Update lists');
o.description = _('Update all lists in config');
o.inputtitle = _('Update lists');
o.inputstyle = 'apply';
o.onclick = function () {
fs.exec('/etc/init.d/podkop', ['list_update']);
ui.showModal(_('List Update'), [
E('p', {}, _('Lists will be updated in background. You can check the progress in system logs.')),
E('div', { class: 'right' }, [
E('button', {
'class': 'btn',
'click': ui.hideModal
}, _('Close'))
])
]);
};
return m.render(); return m.render();
} }
}); });

View File

@@ -291,3 +291,42 @@ msgstr "JSON должен содержать как минимум поля type
msgid "Invalid JSON format" msgid "Invalid JSON format"
msgstr "Неверный формат JSON" msgstr "Неверный формат JSON"
msgid "Diagnostics"
msgstr "Диагностика"
msgid "Main Check"
msgstr "Основная проверка"
msgid "Run a comprehensive diagnostic check of all components"
msgstr "Запустить комплексную диагностическую проверку всех компонентов"
msgid "Run Check"
msgstr "Запустить проверку"
msgid "Full Diagnostic Results"
msgstr "Полные результаты диагностики"
msgid "Failed to copy: "
msgstr "Ошибка копирования: "
msgid "Copy to Clipboard"
msgstr "Скопировать в буфер"
msgid "Close"
msgstr "Закрыть"
msgid "No output"
msgstr "Нет данных"
msgid "System Logs"
msgstr "Системные логи"
msgid "View recent system logs related to Podkop"
msgstr "Просмотр недавних системных логов, связанных с Podkop"
msgid "View Logs"
msgstr "Просмотр логов"
msgid "Failed to copy logs: "
msgstr "Ошибка копирования логов: "

View File

@@ -291,3 +291,42 @@ msgstr ""
msgid "Invalid JSON format" msgid "Invalid JSON format"
msgstr "" msgstr ""
msgid "Diagnostics"
msgstr ""
msgid "Main Check"
msgstr ""
msgid "Run a comprehensive diagnostic check of all components"
msgstr ""
msgid "Run Check"
msgstr ""
msgid "Full Diagnostic Results"
msgstr ""
msgid "Failed to copy: "
msgstr ""
msgid "Copy to Clipboard"
msgstr ""
msgid "Close"
msgstr ""
msgid "No output"
msgstr ""
msgid "System Logs"
msgstr ""
msgid "View recent system logs related to Podkop"
msgstr ""
msgid "View Logs"
msgstr ""
msgid "Failed to copy logs: "
msgstr ""

View File

@@ -7,10 +7,28 @@ script=$(readlink "$initscript")
NAME="$(basename ${script:-$initscript})" NAME="$(basename ${script:-$initscript})"
config_load "$NAME" config_load "$NAME"
EXTRA_COMMANDS="list_update add_route_interface" EXTRA_COMMANDS="list_update add_route_interface check_proxy check_nft check_github check_logs check_all check_three"
EXTRA_HELP=" list_update Updating domain and subnet lists EXTRA_HELP=" list_update Updating domain and subnet lists
add_route_interface Adding route for interface add_route_interface Adding route for interface
sing_box_config_vless For test vless string" sing_box_config_vless For test vless string
check_proxy Check if sing-box proxy works correctly
check_nft Show PodkopTable nftables rules
check_github Check GitHub connectivity and lists availability
check_logs Show podkop logs from system journal
check_all Run all checks
check_three Run check_proxy, check_nft and check_github"
[ ! -L /usr/sbin/podkop ] && ln -s /etc/init.d/podkop /usr/sbin/podkop
GITHUB_RAW_URL="https://raw.githubusercontent.com/itdoginfo/allow-domains/main"
DOMAINS_RU_INSIDE="${GITHUB_RAW_URL}/Russia/inside-dnsmasq-nfset.lst"
DOMAINS_RU_OUTSIDE="${GITHUB_RAW_URL}/Russia/outside-dnsmasq-nfset.lst"
DOMAINS_UA="${GITHUB_RAW_URL}/Ukraine/inside-dnsmasq-nfset.lst"
DOMAINS_YOUTUBE="${GITHUB_RAW_URL}/Services/youtube.lst"
SUBNETS_TWITTER="${GITHUB_RAW_URL}/Subnets/IPv4/Twitter.lst"
SUBNETS_META="${GITHUB_RAW_URL}/Subnets/IPv4/Meta.lst"
SUBNETS_DISCORD="${GITHUB_RAW_URL}/Subnets/IPv4/Discord.lst"
SING_BOX_CONFIG="/etc/sing-box/config.json"
config_get update_interval "main" "update_interval" "0 4 * * *" config_get update_interval "main" "update_interval" "0 4 * * *"
cron_job="${update_interval} /etc/init.d/podkop list_update" cron_job="${update_interval} /etc/init.d/podkop list_update"
@@ -108,10 +126,10 @@ start_service() {
config_get proxy_string main "proxy_string" config_get proxy_string main "proxy_string"
if [[ "$proxy_string" =~ ^ss:// ]]; then if [[ "$proxy_string" =~ ^ss:// ]]; then
sing_box_config_shadowsocks "$proxy_string" "1602" sing_box_config_shadowsocks "$proxy_string" "1602"
jq '.outbounds[0] + {tag: "main"} | {outbounds: [.]}' /etc/sing-box/config.json > "$outbound_main" jq '.outbounds[0] + {tag: "main"} | {outbounds: [.]}' $SING_BOX_CONFIG > "$outbound_main"
elif [[ "$proxy_string" =~ ^vless:// ]]; then elif [[ "$proxy_string" =~ ^vless:// ]]; then
sing_box_config_vless "$proxy_string" "1602" sing_box_config_vless "$proxy_string" "1602"
jq '.outbounds[0] + {tag: "main"} | {outbounds: [.]}' /etc/sing-box/config.json > "$outbound_main" jq '.outbounds[0] + {tag: "main"} | {outbounds: [.]}' $SING_BOX_CONFIG > "$outbound_main"
else else
log "Unsupported proxy type or missing configuration for main" log "Unsupported proxy type or missing configuration for main"
rm -f "$outbound_main" "$outbound_second" rm -f "$outbound_main" "$outbound_second"
@@ -136,10 +154,10 @@ start_service() {
config_get proxy_string "second" "second_proxy_string" config_get proxy_string "second" "second_proxy_string"
if [[ "$proxy_string" =~ ^ss:// ]]; then if [[ "$proxy_string" =~ ^ss:// ]]; then
sing_box_config_shadowsocks "$proxy_string" "1603" sing_box_config_shadowsocks "$proxy_string" "1603"
jq '.outbounds[0] + {tag: "second"} | {outbounds: [.]}' /etc/sing-box/config.json > "$outbound_second" jq '.outbounds[0] + {tag: "second"} | {outbounds: [.]}' $SING_BOX_CONFIG > "$outbound_second"
elif [[ "$proxy_string" =~ ^vless:// ]]; then elif [[ "$proxy_string" =~ ^vless:// ]]; then
sing_box_config_vless "$proxy_string" "1603" sing_box_config_vless "$proxy_string" "1603"
jq '.outbounds[0] + {tag: "second"} | {outbounds: [.]}' /etc/sing-box/config.json > "$outbound_second" jq '.outbounds[0] + {tag: "second"} | {outbounds: [.]}' $SING_BOX_CONFIG > "$outbound_second"
else else
log "Unsupported proxy type or missing configuration for second" log "Unsupported proxy type or missing configuration for second"
rm -f "$outbound_main" "$outbound_second" rm -f "$outbound_main" "$outbound_second"
@@ -179,7 +197,7 @@ start_service() {
], ],
"auto_detect_interface": true "auto_detect_interface": true
} }
}' "$outbound_main" "$outbound_second" > /etc/sing-box/config.json }' "$outbound_main" "$outbound_second" > $SING_BOX_CONFIG
rm -f "$outbound_main" "$outbound_second" rm -f "$outbound_main" "$outbound_second"
@@ -265,7 +283,7 @@ start_service() {
jq '.experimental.clash_api = { jq '.experimental.clash_api = {
"external_ui": "ui", "external_ui": "ui",
"external_controller": "0.0.0.0:9090" "external_controller": "0.0.0.0:9090"
}' /etc/sing-box/config.json >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json /etc/sing-box/config.json }' $SING_BOX_CONFIG >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json $SING_BOX_CONFIG
/etc/init.d/sing-box restart /etc/init.d/sing-box restart
fi fi
@@ -277,7 +295,7 @@ start_service() {
"listen": "0.0.0.0", "listen": "0.0.0.0",
"listen_port": 2080, "listen_port": 2080,
"set_system_proxy": false "set_system_proxy": false
}]' /etc/sing-box/config.json >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json /etc/sing-box/config.json }]' $SING_BOX_CONFIG >/tmp/sing-box-config-tmp.json && mv /tmp/sing-box-config-tmp.json $SING_BOX_CONFIG
/etc/init.d/sing-box restart /etc/init.d/sing-box restart
fi fi
@@ -352,6 +370,16 @@ log() {
logger -t "podkop" "$timestamp $message" logger -t "podkop" "$timestamp $message"
} }
nolog() {
local message="$1"
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
local CYAN="\033[0;36m"
local GREEN="\033[0;32m"
local RESET="\033[0m"
echo -e "${CYAN}[$timestamp]${RESET} ${GREEN}$message${RESET}"
}
add_cron_job() { add_cron_job() {
remove_cron_job remove_cron_job
crontab -l | { crontab -l | {
@@ -646,19 +674,15 @@ add_mark() {
lists_domains_download() { lists_domains_download() {
local URL="$1" local URL="$1"
RU_INSIDE_DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/inside-dnsmasq-nfset.lst
RU_OUTSIDE_DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Russia/outside-dnsmasq-nfset.lst
UA_DOMAINS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Ukraine/inside-dnsmasq-nfset.lst
case "$URL" in case "$URL" in
"ru_inside") "ru_inside")
URL=$RU_INSIDE_DOMAINS URL=$DOMAINS_RU_INSIDE
;; ;;
"ru_outside") "ru_outside")
URL=$RU_OUTSIDE_DOMAINS URL=$DOMAINS_RU_OUTSIDE
;; ;;
"ua") "ua")
URL=$UA_DOMAINS URL=$DOMAINS_UA
;; ;;
*) *)
log "Unidentified list of domains" log "Unidentified list of domains"
@@ -668,10 +692,12 @@ lists_domains_download() {
count=0 count=0
while true; do while true; do
if curl -m 3 github.com; then if ping -c 1 -W 3 github.com >/dev/null 2>&1; then
curl -f $URL --output /tmp/dnsmasq.d/podkop-domains.lst wget -q -O /tmp/dnsmasq.d/podkop-domains.lst $URL
if [ $? -eq 0 ]; then
sed -i 's/fw4#vpn_domains/PodkopTable#podkop_domains/g' /tmp/dnsmasq.d/podkop-domains.lst sed -i 's/fw4#vpn_domains/PodkopTable#podkop_domains/g' /tmp/dnsmasq.d/podkop-domains.lst
return 0 return 0
fi
else else
log "GitHub is not available. Check the internet availability [$count sec]" log "GitHub is not available. Check the internet availability [$count sec]"
count=$((count + 1)) count=$((count + 1))
@@ -694,11 +720,9 @@ lists_domains_download() {
lists_services_download() { lists_services_download() {
local URL="$1" local URL="$1"
YOUTUBE=https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Services/youtube.lst
case "$URL" in case "$URL" in
"youtube") "youtube")
URL=$YOUTUBE URL=$DOMAINS_YOUTUBE
;; ;;
*) *)
log "Unidentified list of domains" log "Unidentified list of domains"
@@ -708,11 +732,13 @@ lists_services_download() {
count=0 count=0
while true; do while true; do
if curl -m 3 github.com; then if ping -c 1 -W 3 github.com >/dev/null 2>&1; then
curl -f $URL --output /tmp/dnsmasq.d/podkop2-domains.lst wget -q -O /tmp/dnsmasq.d/podkop2-domains.lst $URL
if [ $? -eq 0 ]; then
delist_downloaded_domains delist_downloaded_domains
sed -i 's/.*/nftset=\/&\/4#inet#PodkopTable#podkop2_domains/g' /tmp/dnsmasq.d/podkop2-domains.lst sed -i 's/.*/nftset=\/&\/4#inet#PodkopTable#podkop2_domains/g' /tmp/dnsmasq.d/podkop2-domains.lst
return 0 return 0
fi
else else
log "GitHub is not available. Check the internet availability [$count sec]" log "GitHub is not available. Check the internet availability [$count sec]"
count=$((count + 1)) count=$((count + 1))
@@ -733,33 +759,31 @@ lists_services_download() {
} }
list_subnets_download() { list_subnets_download() {
TWITTER_SUBNETS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Subnets/IPv4/Twitter.lst
META_SUBNETS=https://raw.githubusercontent.com/itdoginfo/allow-domains/main/Subnets/IPv4/Meta.lst
DISCORD_SUBNETS=https://raw.githubusercontent.com/itdoginfo/allow-domains/refs/heads/main/Subnets/IPv4/Discord.lst
local URL="$1" local URL="$1"
case "$URL" in case "$URL" in
"twitter") "twitter")
URL=$TWITTER_SUBNETS URL=$SUBNETS_TWITTER
;; ;;
"meta") "meta")
URL=$META_SUBNETS URL=$SUBNETS_META
;; ;;
"discord") "discord")
URL=$DISCORD_SUBNETS URL=$SUBNETS_DISCORD
;; ;;
*) *)
log "Custom URL for subnet" log "Custom URL for subnet"
if curl --output /dev/null --silent --head --fail "$URL"; then if wget -q --spider "$URL"; then
log "URL is valid" log "URL is valid"
else else
log "URL $URL is not valid" log "URL $URL is not valid"
return
fi fi
;; ;;
esac esac
local filename=$(basename "$URL") local filename=$(basename "$URL")
curl -f "$URL" --output "/tmp/podkop/$filename" wget -q -O "/tmp/podkop/$filename" "$URL"
while IFS= read -r subnet; do while IFS= read -r subnet; do
nft add element inet PodkopTable podkop_subnets { $subnet } nft add element inet PodkopTable podkop_subnets { $subnet }
done <"/tmp/podkop/$filename" done <"/tmp/podkop/$filename"
@@ -778,7 +802,7 @@ list_custom_local_domains_create() {
local filename=$(basename "$local_file" | cut -d. -f1) local filename=$(basename "$local_file" | cut -d. -f1)
local config="/tmp/dnsmasq.d/${name}-${filename}.lst" local config="/tmp/dnsmasq.d/${name}-${filename}.lst"
rm -f $config rm -f "$config"
while IFS= read -r domain; do while IFS= read -r domain; do
echo "nftset=/$domain/4#inet#PodkopTable#${name}_domains" >>$config echo "nftset=/$domain/4#inet#PodkopTable#${name}_domains" >>$config
done <"$local_file" done <"$local_file"
@@ -791,8 +815,8 @@ list_custom_download_domains_create() {
local filename=$(basename "$URL") local filename=$(basename "$URL")
local config="/tmp/dnsmasq.d/${name}-${filename}.lst" local config="/tmp/dnsmasq.d/${name}-${filename}.lst"
rm -f $config rm -f "$config"
curl -f "$URL" --output "/tmp/podkop/${filename}" wget -q -O "/tmp/podkop/${filename}" "$URL"
while IFS= read -r domain; do while IFS= read -r domain; do
echo "nftset=/$domain/4#inet#PodkopTable#${name}_domains" >>$config echo "nftset=/$domain/4#inet#PodkopTable#${name}_domains" >>$config
done <"/tmp/podkop/$filename" done <"/tmp/podkop/$filename"
@@ -897,7 +921,7 @@ sing_box_config_outbound_json() {
} }
EOF EOF
jq --argjson outbound "$json_config" '.outbounds += [$outbound]' /tmp/base_config.json > /etc/sing-box/config.json jq --argjson outbound "$json_config" '.outbounds += [$outbound]' /tmp/base_config.json > $SING_BOX_CONFIG
rm -f /tmp/base_config.json rm -f /tmp/base_config.json
} }
@@ -972,7 +996,7 @@ sing_box_config_shadowsocks() {
} }
EOF EOF
mv /tmp/ss_config.json /etc/sing-box/config.json mv /tmp/ss_config.json $SING_BOX_CONFIG
} }
sing_box_config_vless() { sing_box_config_vless() {
@@ -1072,7 +1096,7 @@ sing_box_config_vless() {
"short_id": $sid "short_id": $sid
} }
else . end else . end
else . end' > /etc/sing-box/config.json else . end' > $SING_BOX_CONFIG
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "Config created successfully" echo "Config created successfully"
@@ -1083,12 +1107,140 @@ sing_box_config_vless() {
} }
sing_box_config_check() { sing_box_config_check() {
if ! sing-box -c /etc/sing-box/config.json check >/dev/null 2>&1; then if ! sing-box -c $SING_BOX_CONFIG check >/dev/null 2>&1; then
log "Sing-box configuration is invalid" log "Sing-box configuration is invalid"
return return
fi fi
} }
check_proxy() {
if ! command -v sing-box >/dev/null 2>&1; then
nolog "sing-box is not installed"
return 1
fi
if [ ! -f $SING_BOX_CONFIG ]; then
nolog "Configuration file not found"
return 1
fi
nolog "Checking sing-box configuration..."
if ! sing-box -c $SING_BOX_CONFIG check >/dev/null; then
nolog "Invalid configuration"
return 1
fi
jq '
walk(
if type == "object" then
with_entries(
if [.key] | inside(["uuid", "server", "server_name", "password", "public_key", "short_id"]) then
.value = "MASKED"
else . end
)
else . end
)' $SING_BOX_CONFIG
nolog "Checking proxy connection..."
for attempt in `seq 1 5`; do
response=$(sing-box tools fetch ifconfig.me -D /etc/sing-box 2>/dev/null)
if ! echo "$response" | grep -q "403 Forbidden"; then
nolog "Proxy check completed successfully"
echo "$response" | sed 's/\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)/XXX.\2.\3.\4/'
return 0
fi
done
nolog "Failed to get a non-403 response after 5 attempts"
return 1
}
check_nft() {
if ! command -v nft >/dev/null 2>&1; then
nolog "nft is not installed"
return 1
fi
nolog "Checking PodkopTable rules..."
# Список всех возможных сетов
local sets="podkop_domains podkop_subnets podkop2_domains podkop2_subnets localv4"
nolog "Sets statistics:"
for set_name in $sets; do
if nft list set inet PodkopTable $set_name >/dev/null 2>&1; then
local count=$(nft list set inet PodkopTable $set_name 2>/dev/null | grep -c ",")
nolog "- $set_name: $count elements"
else
nolog "- $set_name: not found"
fi
done
# Показываем правила с счетчиками
nolog "Current chains and rules:"
nft list table inet PodkopTable | grep "chain\|counter"
nolog "NFT check completed"
}
check_github() {
nolog "Checking GitHub connectivity..."
if ! ping -c 1 -W 3 github.com >/dev/null 2>&1; then
nolog "Error: Cannot connect to GitHub"
return 1
fi
nolog "GitHub is accessible"
nolog "Checking lists availability:"
for url in "$DOMAINS_RU_INSIDE" "$DOMAINS_RU_OUTSIDE" "$DOMAINS_UA" "$DOMAINS_YOUTUBE" \
"$SUBNETS_TWITTER" "$SUBNETS_META" "$SUBNETS_DISCORD"; do
local list_name=$(basename "$url")
wget -q -O /dev/null "$url"
if [ $? -eq 0 ]; then
nolog "- $list_name: available"
else
nolog "- $list_name: not available"
fi
done
}
check_logs() {
nolog "Showing podkop logs from system journal..."
if command -v logread >/dev/null 2>&1; then
# Попытка получить последние 50 записей
logread -e "podkop" | tail -n 50
else
nolog "Error: logread command not found"
return 1
fi
}
check_three() {
nolog "\n=== Checking GitHub connectivity ==="
check_github
nolog "\n=== Checking proxy settings ==="
check_proxy
nolog "\n=== Checking NFT rules ==="
check_nft
nolog "\nFull diagnostic check completed"
}
check_all() {
nolog "Starting full diagnostic check..."
nolog "\n=== Checking recent logs ==="
check_logs
check_three
}
process_domains_text() { process_domains_text() {
local text="$1" local text="$1"
local name="$2" local name="$2"