mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-06 11:36:50 +03:00
22
install.sh
22
install.sh
@@ -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
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -290,4 +290,43 @@ msgid "JSON must contain at least type, server and server_port fields"
|
|||||||
msgstr "JSON должен содержать как минимум поля type, server и server_port"
|
msgstr "JSON должен содержать как минимум поля type, server и server_port"
|
||||||
|
|
||||||
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 "Ошибка копирования логов: "
|
||||||
@@ -290,4 +290,43 @@ msgid "JSON must contain at least type, server and server_port fields"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Invalid JSON format"
|
msgid "Invalid JSON format"
|
||||||
|
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 ""
|
msgstr ""
|
||||||
@@ -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
|
||||||
sed -i 's/fw4#vpn_domains/PodkopTable#podkop_domains/g' /tmp/dnsmasq.d/podkop-domains.lst
|
if [ $? -eq 0 ]; then
|
||||||
return 0
|
sed -i 's/fw4#vpn_domains/PodkopTable#podkop_domains/g' /tmp/dnsmasq.d/podkop-domains.lst
|
||||||
|
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
|
||||||
delist_downloaded_domains
|
if [ $? -eq 0 ]; then
|
||||||
sed -i 's/.*/nftset=\/&\/4#inet#PodkopTable#podkop2_domains/g' /tmp/dnsmasq.d/podkop2-domains.lst
|
delist_downloaded_domains
|
||||||
return 0
|
sed -i 's/.*/nftset=\/&\/4#inet#PodkopTable#podkop2_domains/g' /tmp/dnsmasq.d/podkop2-domains.lst
|
||||||
|
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"
|
||||||
|
|||||||
Reference in New Issue
Block a user