diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js index 5fe0886..66af555 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js @@ -63,20 +63,20 @@ function getNetworkInterfaces(o, section_id, excludeInterfaces = []) { } function getNetworkNetworks(o, section_id, excludeInterfaces = []) { - return network.getNetworks().then(networks => { - o.keylist = []; - o.vallist = []; + return network.getNetworks().then(networks => { + o.keylist = []; + o.vallist = []; - networks.forEach(net => { - const name = net.getName(); - const ifname = net.getIfname(); - if (name && !excludeInterfaces.includes(name)) { - o.value(name, ifname ? `${name} (${ifname})` : name); - } - }); - }).catch(error => { - console.error('Failed to get networks:', error); - }); + networks.forEach(net => { + const name = net.getName(); + const ifname = net.getIfname(); + if (name && !excludeInterfaces.includes(name)) { + o.value(name, ifname ? `${name} (${ifname})` : name); + } + }); + }).catch(error => { + console.error('Failed to get networks:', error); + }); } function createConfigSection(section, map, network) { @@ -623,7 +623,32 @@ const createModalContent = (title, content) => { const showConfigModal = async (command, title) => { const res = await safeExec('/usr/bin/podkop', [command]); - const formattedOutput = formatDiagnosticOutput(res.stdout || _('No output')); + let formattedOutput = formatDiagnosticOutput(res.stdout || _('No output')); + + if (command === 'global_check') { + try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 10000); + + const response = await fetch('https://fakeip.tech-domain.club/check', { signal: controller.signal }); + const data = await response.json(); + clearTimeout(timeoutId); + + formattedOutput += '\n━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'; + formattedOutput += ' ➡️ ' + _('FAKEIP BROWSER TEST') + '\n'; + + if (data.fakeip === true) { + formattedOutput += '✅ ' + _('FakeIP is working in browser!') + '\n'; + } else { + formattedOutput += '❌ ' + _('FakeIP is not working in browser') + '\n'; + formattedOutput += _('Check DNS server on current device (PC, phone)') + '\n'; + formattedOutput += _('Its must be router!') + '\n'; + } + } catch (error) { + formattedOutput += '\n❌ ' + _('Check failed: ') + (error.name === 'AbortError' ? _('timeout') : error.message) + '\n'; + } + } + ui.showModal(_(title), createModalContent(_(title), formattedOutput)); }; @@ -672,11 +697,18 @@ const createStatusPanel = (title, status, buttons) => { E('strong', {}, _(title)), status && E('br'), status && E('span', { - 'style': `color: ${status.running ? STATUS_COLORS.SUCCESS : STATUS_COLORS.ERROR}` + 'style': `color: ${title === 'Sing-box Status' ? + (status.running && !status.enabled ? STATUS_COLORS.SUCCESS : STATUS_COLORS.ERROR) : + title === 'Podkop Status' ? + (status.enabled ? STATUS_COLORS.SUCCESS : STATUS_COLORS.ERROR) : + (status.running ? STATUS_COLORS.SUCCESS : STATUS_COLORS.ERROR) + }` }, [ - status.running ? '✔' : '✘', - ' ', - status.status + title === 'Sing-box Status' ? + (status.running && !status.enabled ? '✔ running' : '✘ ' + status.status) : + title === 'Podkop Status' ? + (status.enabled ? '✔ enabled' : '✘ disabled') : + (status.running ? '✔' : '✘') + ' ' + status.status ]) ].filter(Boolean); @@ -688,7 +720,80 @@ const createStatusPanel = (title, status, buttons) => { E('div', { 'class': 'panel-body', 'style': 'display: flex; flex-direction: column; gap: 8px;' - }, buttons) + }, title === 'Podkop Status' ? [ + ButtonFactory.createActionButton({ + label: 'Restart Podkop', + type: 'apply', + action: 'restart', + reload: true + }), + ButtonFactory.createInitActionButton({ + label: status.enabled ? 'Disable Podkop' : 'Enable Podkop', + type: status.enabled ? 'remove' : 'apply', + action: status.enabled ? 'disable' : 'enable', + reload: true + }), + ButtonFactory.createModalButton({ + label: _('Global check'), + command: 'global_check', + title: _('Click here for all the info') + }), + ButtonFactory.createModalButton({ + label: 'View Logs', + command: 'check_logs', + title: 'Podkop Logs' + }), + ButtonFactory.createModalButton({ + label: _('Update Lists'), + command: 'list_update', + title: _('Lists Update Results') + }) + ] : title === 'FakeIP Status' ? [ + E('div', { style: 'margin-bottom: 10px;' }, [ + E('div', { style: 'margin-bottom: 5px;' }, [ + E('span', { style: `color: ${fakeipStatus.color}` }, [ + fakeipStatus.state === 'working' ? '✔' : fakeipStatus.state === 'not_working' ? '✘' : '!', + ' ', + fakeipStatus.state === 'working' ? _('works in browser') : _('not works in browser') + ]) + ]), + E('div', {}, [ + E('span', { style: `color: ${fakeipCLIStatus.color}` }, [ + fakeipCLIStatus.state === 'working' ? '✔' : fakeipCLIStatus.state === 'not_working' ? '✘' : '!', + ' ', + fakeipCLIStatus.state === 'working' ? _('works on router') : _('not works on router') + ]) + ]) + ]), + E('div', { style: 'margin-bottom: 10px;' }, [ + E('div', { style: 'margin-bottom: 5px;' }, [ + E('strong', {}, _('DNS Status')), + E('br'), + E('span', { style: `color: ${dnsStatus.remote.color}` }, [ + dnsStatus.remote.state === 'available' ? '✔' : dnsStatus.remote.state === 'unavailable' ? '✘' : '!', + ' ', + dnsStatus.remote.message + ]), + E('br'), + E('span', { style: `color: ${dnsStatus.local.color}` }, [ + dnsStatus.local.state === 'available' ? '✔' : dnsStatus.local.state === 'unavailable' ? '✘' : '!', + ' ', + dnsStatus.local.message + ]) + ]) + ]), + E('div', { style: 'margin-bottom: 10px;' }, [ + E('div', { style: 'margin-bottom: 5px;' }, [ + E('strong', {}, configName), + E('br'), + E('span', { style: `color: ${bypassStatus.color}` }, [ + bypassStatus.state === 'working' ? '✔' : bypassStatus.state === 'not_working' ? '✘' : '!', + ' ', + bypassStatus.message + ]) + ]) + ]) + ] : buttons) ]); }; @@ -717,9 +822,9 @@ let createStatusSection = function (podkopStatus, singboxStatus, podkop, luci, s reload: true }), ButtonFactory.createModalButton({ - label: 'Show Config', - command: 'show_config', - title: 'Podkop Configuration' + label: _('Global check'), + command: 'global_check', + title: _('Click here for all the info') }), ButtonFactory.createModalButton({ label: 'View Logs', @@ -807,12 +912,7 @@ let createStatusSection = function (podkopStatus, singboxStatus, podkop, luci, s bypassStatus.message ]) ]) - ]), - ButtonFactory.createModalButton({ - label: _('Global check'), - command: 'global_check', - title: _('Click here for all the info') - }) + ]) ]), // Version Information Panel @@ -1350,32 +1450,67 @@ return view.extend({ async function updateDiagnostics() { try { - const [ - podkopStatus, - singboxStatus, - podkop, - luci, - singbox, - system, - fakeipStatus, - fakeipCLIStatus, - dnsStatus, - bypassStatus - ] = await Promise.all([ - safeExec('/usr/bin/podkop', ['get_status']), - safeExec('/usr/bin/podkop', ['get_sing_box_status']), - safeExec('/usr/bin/podkop', ['show_version']), - safeExec('/usr/bin/podkop', ['show_luci_version']), - safeExec('/usr/bin/podkop', ['show_sing_box_version']), - safeExec('/usr/bin/podkop', ['show_system_info']), - checkFakeIP(), - checkFakeIPCLI(), - checkDNSAvailability(), - checkBypass() - ]); + const results = { + podkopStatus: null, + singboxStatus: null, + podkop: null, + luci: null, + singbox: null, + system: null, + fakeipStatus: null, + fakeipCLIStatus: null, + dnsStatus: null, + bypassStatus: null + }; - const parsedPodkopStatus = JSON.parse(podkopStatus.stdout || '{"running":0,"enabled":0,"status":"unknown"}'); - const parsedSingboxStatus = JSON.parse(singboxStatus.stdout || '{"running":0,"enabled":0,"status":"unknown"}'); + // Выполняем все проверки независимо друг от друга + const checks = [ + safeExec('/usr/bin/podkop', ['get_status']) + .then(result => results.podkopStatus = result) + .catch(() => results.podkopStatus = { stdout: '{"enabled":0,"status":"error"}' }), + + safeExec('/usr/bin/podkop', ['get_sing_box_status']) + .then(result => results.singboxStatus = result) + .catch(() => results.singboxStatus = { stdout: '{"running":0,"enabled":0,"status":"error"}' }), + + safeExec('/usr/bin/podkop', ['show_version']) + .then(result => results.podkop = result) + .catch(() => results.podkop = { stdout: 'error' }), + + safeExec('/usr/bin/podkop', ['show_luci_version']) + .then(result => results.luci = result) + .catch(() => results.luci = { stdout: 'error' }), + + safeExec('/usr/bin/podkop', ['show_sing_box_version']) + .then(result => results.singbox = result) + .catch(() => results.singbox = { stdout: 'error' }), + + safeExec('/usr/bin/podkop', ['show_system_info']) + .then(result => results.system = result) + .catch(() => results.system = { stdout: 'error' }), + + checkFakeIP() + .then(result => results.fakeipStatus = result) + .catch(() => results.fakeipStatus = { state: 'error', message: 'check error', color: STATUS_COLORS.WARNING }), + + checkFakeIPCLI() + .then(result => results.fakeipCLIStatus = result) + .catch(() => results.fakeipCLIStatus = { state: 'error', message: 'check error', color: STATUS_COLORS.WARNING }), + + checkDNSAvailability() + .then(result => results.dnsStatus = result) + .catch(() => results.dnsStatus = { + remote: { state: 'error', message: 'check error', color: STATUS_COLORS.WARNING }, + local: { state: 'error', message: 'check error', color: STATUS_COLORS.WARNING } + }), + + checkBypass() + .then(result => results.bypassStatus = result) + .catch(() => results.bypassStatus = { state: 'error', message: 'check error', color: STATUS_COLORS.WARNING }) + ]; + + // Ждем завершения всех проверок + await Promise.allSettled(checks); const container = document.getElementById('diagnostics-status'); if (!container) return; @@ -1395,11 +1530,7 @@ return view.extend({ const label = activeConfig.split('#').pop(); if (label && label.trim()) { configName = _('Config: ') + decodeURIComponent(label); - } else { - configName = _('Main config'); } - } else { - configName = _('Main config'); } } } @@ -1407,42 +1538,62 @@ return view.extend({ console.error('Error getting config name from UCI:', e); } - // Create a modified statusSection function with the configName - const statusSection = createStatusSection(parsedPodkopStatus, parsedSingboxStatus, podkop, luci, singbox, system, fakeipStatus, fakeipCLIStatus, dnsStatus, bypassStatus, configName); + const parsedPodkopStatus = JSON.parse(results.podkopStatus.stdout || '{"enabled":0,"status":"error"}'); + const parsedSingboxStatus = JSON.parse(results.singboxStatus.stdout || '{"running":0,"enabled":0,"status":"error"}'); + + const statusSection = createStatusSection( + parsedPodkopStatus, + parsedSingboxStatus, + results.podkop, + results.luci, + results.singbox, + results.system, + results.fakeipStatus, + results.fakeipCLIStatus, + results.dnsStatus, + results.bypassStatus, + configName + ); + container.innerHTML = ''; container.appendChild(statusSection); - const fakeipElement = document.getElementById('fakeip-status'); - if (fakeipElement) { - fakeipElement.innerHTML = E('span', { 'style': `color: ${fakeipStatus.color}` }, [ - fakeipStatus.state === 'working' ? '✔ ' : fakeipStatus.state === 'not_working' ? '✘ ' : '! ', - fakeipStatus.message - ]).outerHTML; - } + // Обновляем отдельные элементы статуса + const updateStatusElement = (elementId, status, template) => { + const element = document.getElementById(elementId); + if (element) { + element.innerHTML = template(status); + } + }; - const fakeipCLIElement = document.getElementById('fakeip-cli-status'); - if (fakeipCLIElement) { - fakeipCLIElement.innerHTML = E('span', { 'style': `color: ${fakeipCLIStatus.color}` }, [ - fakeipCLIStatus.state === 'working' ? '✔ ' : fakeipCLIStatus.state === 'not_working' ? '✘ ' : '! ', - fakeipCLIStatus.message - ]).outerHTML; - } + updateStatusElement('fakeip-status', results.fakeipStatus, + status => E('span', { 'style': `color: ${status.color}` }, [ + status.state === 'working' ? '✔ ' : status.state === 'not_working' ? '✘ ' : '! ', + status.message + ]).outerHTML + ); - const dnsRemoteElement = document.getElementById('dns-remote-status'); - if (dnsRemoteElement) { - dnsRemoteElement.innerHTML = E('span', { 'style': `color: ${dnsStatus.remote.color}` }, [ - dnsStatus.remote.state === 'available' ? '✔ ' : dnsStatus.remote.state === 'unavailable' ? '✘ ' : '! ', - dnsStatus.remote.message - ]).outerHTML; - } + updateStatusElement('fakeip-cli-status', results.fakeipCLIStatus, + status => E('span', { 'style': `color: ${status.color}` }, [ + status.state === 'working' ? '✔ ' : status.state === 'not_working' ? '✘ ' : '! ', + status.message + ]).outerHTML + ); + + updateStatusElement('dns-remote-status', results.dnsStatus.remote, + status => E('span', { 'style': `color: ${status.color}` }, [ + status.state === 'available' ? '✔ ' : status.state === 'unavailable' ? '✘ ' : '! ', + status.message + ]).outerHTML + ); + + updateStatusElement('dns-local-status', results.dnsStatus.local, + status => E('span', { 'style': `color: ${status.color}` }, [ + status.state === 'available' ? '✔ ' : status.state === 'unavailable' ? '✘ ' : '! ', + status.message + ]).outerHTML + ); - const dnsLocalElement = document.getElementById('dns-local-status'); - if (dnsLocalElement) { - dnsLocalElement.innerHTML = E('span', { 'style': `color: ${dnsStatus.local.color}` }, [ - dnsStatus.local.state === 'available' ? '✔ ' : dnsStatus.local.state === 'unavailable' ? '✘ ' : '! ', - dnsStatus.local.message - ]).outerHTML; - } } catch (e) { const container = document.getElementById('diagnostics-status'); if (container) { diff --git a/luci-app-podkop/po/ru/podkop.po b/luci-app-podkop/po/ru/podkop.po index 6b1ff8e..b1ba065 100644 --- a/luci-app-podkop/po/ru/podkop.po +++ b/luci-app-podkop/po/ru/podkop.po @@ -819,3 +819,27 @@ msgstr "недоступен" msgid "Apply for SS2022" msgstr "Применить для SS2022" + +msgid "PODKOP CONFIGURATION" +msgstr "КОНФИГУРАЦИЯ PODKOP" + +msgid "FAKEIP ROUTER TEST" +msgstr "ПРОВЕРКА FAKEIP НА РОУТЕРЕ" + +msgid "FAKEIP BROWSER TEST" +msgstr "ПРОВЕРКА FAKEIP В БРАУЗЕРЕ" + +msgid "FakeIP is working correctly on router (198.18.x.x)" +msgstr "FakeIP работает корректно на роутере (198.18.x.x)" + +msgid "Click here for all the info" +msgstr "Нажмите для просмотра всей информации" + +msgid "Check DNS server on current device (PC, phone)" +msgstr "Проверьте DNS сервер на текущем устройстве (ПК, телефон)" + +msgid "Its must be router!" +msgstr "Это должен быть роутер!" + +msgid "Global check" +msgstr "Глобальная проверка" \ No newline at end of file diff --git a/luci-app-podkop/po/templates/podkop.pot b/luci-app-podkop/po/templates/podkop.pot index c017151..f668555 100644 --- a/luci-app-podkop/po/templates/podkop.pot +++ b/luci-app-podkop/po/templates/podkop.pot @@ -1169,4 +1169,28 @@ msgid "available" msgstr "" msgid "unavailable" +msgstr "" + +msgid "PODKOP CONFIGURATION" +msgstr "" + +msgid "FAKEIP ROUTER TEST" +msgstr "" + +msgid "FAKEIP BROWSER TEST" +msgstr "" + +msgid "FakeIP is working correctly on router (198.18.x.x)" +msgstr "" + +msgid "Click here for all the info" +msgstr "" + +msgid "Check DNS server on current device (PC, phone)" +msgstr "" + +msgid "Its must be router!" +msgstr "" + +msgid "Global check" msgstr "" \ No newline at end of file diff --git a/podkop/files/usr/bin/podkop b/podkop/files/usr/bin/podkop index 52f2779..7283c8f 100755 --- a/podkop/files/usr/bin/podkop +++ b/podkop/files/usr/bin/podkop @@ -24,6 +24,7 @@ TEST_DOMAIN="fakeip.tech-domain.club" INTERFACES_LIST="" SRC_INTERFACE="" RESOLV_CONF="/etc/resolv.conf" +CLOUDFLARE_OCTETS="103.21 103.22 103.31 104.16 104.17 104.18 104.19 104.20 104.21 104.22 104.23 104.24 104.25 104.26 104.27 104.28 108.162 131.0 141.101 162.158 162.159 172.64 172.65 172.66 172.67 172.68 172.69 172.70 172.71 173.245 188.114 190.93 197.234 198.41" log() { local message="$1" @@ -1953,9 +1954,7 @@ show_sing_box_config() { )' "$SING_BOX_CONFIG" } -show_config() { - nolog "📄 Current podkop configuration:" - +show_config() { if [ ! -f /etc/config/podkop ]; then nolog "Configuration file not found" return 1 @@ -2046,36 +2045,18 @@ get_sing_box_status() { } get_status() { - local running=0 local enabled=0 local status="" # Check if service is enabled if [ -x /etc/rc.d/S99podkop ]; then enabled=1 - fi - - # Check if service is running - if pgrep -f "sing-box" >/dev/null; then - running=1 - fi - - # Format status message - if [ $running -eq 1 ]; then - if [ $enabled -eq 1 ]; then - status="running & enabled" - else - status="running but disabled" - fi + status="enabled" else - if [ $enabled -eq 1 ]; then - status="stopped but enabled" - else - status="stopped & disabled" - fi + status="disabled" fi - echo "{\"running\":$running,\"enabled\":$enabled,\"status\":\"$status\"}" + echo "{\"enabled\":$enabled,\"status\":\"$status\"}" } check_dns_available() { @@ -2171,71 +2152,33 @@ sing_box_add_secure_dns_probe_domain() { log "DNS probe domain ${domain} configured with override to port ${override_port}" } +print_global() { + local message="$1" + echo "$message" +} + global_check() { - nolog "📡 Global check run!" + print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_global " ➡️ SYSTEM INFO" + print_global "📦 Podkop: $(opkg list-installed podkop | awk '{print $3}')" + print_global "📦 LuCI App: $(opkg list-installed luci-app-podkop | awk '{print $3}')" + print_global "📦 Sing-box: $(sing-box version | head -n 1 | awk '{print $3}')" + print_global "🔧 OpenWrt: $(grep OPENWRT_RELEASE /etc/os-release | cut -d'"' -f2)" + print_global "💻 Device: $(cat /tmp/sysinfo/model)" - nolog "Podkop $(opkg list-installed podkop | awk '{print $3}')" - nolog "LuCi App $(opkg list-installed luci-app-podkop | awk '{print $3}')" - nolog "Sing-box $(sing-box version | head -n 1 | awk '{print $3}')" - nolog "$(grep OPENWRT_RELEASE /etc/os-release | cut -d'"' -f2)" - nolog "Device: $(cat /tmp/sysinfo/model)" - - printf "\n" + print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_global " ➡️ CONFIGURATION" show_config - printf "\n" - nolog "Checking fakeip functionality..." - - nolog "➡️ DNS resolution: system DNS server" - nslookup -timeout=2 $TEST_DOMAIN - - local working_resolver=$(find_working_resolver) - if [ -z "$working_resolver" ]; then - nolog "❌ No working resolver found, skipping resolver check" - else - nolog "➡️ DNS resolution: external resolver ($working_resolver)" - nslookup -timeout=2 $TEST_DOMAIN $working_resolver - fi - - # Main FakeIP check - nolog "➡️ DNS resolution: sing-box DNS server (127.0.0.42)" - local result=$(nslookup -timeout=2 $TEST_DOMAIN 127.0.0.42 2>&1) - echo "$result" - - if echo "$result" | grep -q "198.18"; then - nolog "✅ FakeIP is working correctly! Domain resolved to FakeIP range (198.18.x.x)" - else - nolog "❌ FakeIP test failed. Domain did not resolve to FakeIP range" - nolog "Checking if sing-box is running..." - - if ! pgrep -f "sing-box" >/dev/null; then - nolog "sing-box is not running" - else - nolog "sing-box is running, but FakeIP might not be configured correctly" - nolog "Checking DNS configuration in sing-box..." - - if [ -f "$SING_BOX_CONFIG" ]; then - local fakeip_enabled=$(jq -r '.dns.fakeip.enabled' "$SING_BOX_CONFIG") - local fakeip_range=$(jq -r '.dns.fakeip.inet4_range' "$SING_BOX_CONFIG") - - nolog "FakeIP enabled: $fakeip_enabled" - nolog "FakeIP range: $fakeip_range" - - local dns_rules=$(jq -r '.dns.rules[] | select(.server == "fakeip-server") | .domain' "$SING_BOX_CONFIG") - nolog "FakeIP domain: $dns_rules" - else - nolog "sing-box config file not found" - fi - fi - fi - printf "\n" + print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_global " ➡️ SYSTEM CHECKS" 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 - nolog "❌ /etc/resolv.conf contains an external nameserver:" + print_global "❌ /etc/resolv.conf contains external nameserver:" cat /etc/resolv.conf echo "" else - nolog "✅ /etc/resolv.conf OK" + print_global "✅ /etc/resolv.conf - OK" fi cachesize="$(uci get dhcp.@dnsmasq[0].cachesize 2>/dev/null)" @@ -2243,29 +2186,31 @@ global_check() { server="$(uci get dhcp.@dnsmasq[0].server 2>/dev/null)" if [ "$cachesize" != "0" ] || [ "$noresolv" != "1" ] || [ "$server" != "127.0.0.42" ]; then - nolog "❌ The configuration differs from the template. 📄 DHCP config:" + print_global "❌ DHCP configuration differs from template:" awk '/^config /{p=($2=="dnsmasq")} p' /etc/config/dhcp elif [ "$(uci get podkop.main.dont_touch_dhcp 2>/dev/null)" = "1" ]; then - nolog "⚠️ Enable dont_touch_dhcp. 📄 DHCP config:" + print_global "⚠️ dont_touch_dhcp is enabled:" awk '/^config /{p=($2=="dnsmasq")} p' /etc/config/dhcp else - nolog "✅ /etc/config/dhcp" + print_global "✅ DHCP configuration - OK" fi if ! pgrep -f "sing-box" >/dev/null; then - nolog "❌ sing-box is not running" + print_global "❌ sing-box is not running" else - nolog "✅ sing-box is running" + print_global "✅ sing-box is running" fi - nolog "📄 NFT Table Podkop" + print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_global " ➡️ NFT RULES" if ! nft list table inet PodkopTable >/dev/null 2>&1; then - nolog "PodkopTable not found" + print_global "❌ PodkopTable not found" else nft list table inet PodkopTable fi - nolog "📄 WAN config" + print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_global " ➡️ WAN CONFIG" if uci show network.wan >/dev/null 2>&1; then awk ' /^config / { @@ -2286,26 +2231,65 @@ global_check() { } ' /etc/config/network else - nolog "WAN not exists" + print_global "❌ WAN configuration not found" fi - CLOUDFLARE_OCTETS="103.21 103.22 103.31 104.16 104.17 104.18 104.19 104.20 104.21 104.22 104.23 \ - 104.24 104.25 104.26 104.27 104.28 108.162 131.0 141.101 162.158 162.159 172.64 172.65 172.66 \ - 172.67 172.68 172.69 172.70 172.71 173.245 188.114 190.93 197.234 198.41" - 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 - nolog "⚠️ 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 - nolog "⚠️ WARP detected ($host)" + print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_global " ➡️ WARP DETECTION" + print_global "⚠️ WARP detected: $host" fi done fi + + print_global "━━━━━━━━━━━━━━━━━━━━━━━━━━━" + print_global " ➡️ FAKEIP ROUTER TEST" + + print_global "🔍 Testing system DNS resolver..." + nslookup -timeout=2 $TEST_DOMAIN + + local working_resolver=$(find_working_resolver) + if [ -z "$working_resolver" ]; then + print_global "❌ No working external resolver found" + else + print_global "🔍 Testing external resolver ($working_resolver)..." + nslookup -timeout=2 $TEST_DOMAIN $working_resolver + fi + + print_global "🔍 Testing sing-box DNS server (127.0.0.42)..." + local result=$(nslookup -timeout=2 $TEST_DOMAIN 127.0.0.42 2>&1) + echo "$result" + + if echo "$result" | grep -q "198.18"; then + print_global "✅ FakeIP is working correctly on router (198.18.x.x)" + else + print_global "❌ FakeIP test failed - domain did not resolve to FakeIP range" + if ! pgrep -f "sing-box" >/dev/null; then + print_global " └─ sing-box is not running" + else + print_global " └─ sing-box is running, checking configuration..." + + if [ -f "$SING_BOX_CONFIG" ]; then + local fakeip_enabled=$(jq -r '.dns.fakeip.enabled' "$SING_BOX_CONFIG") + local fakeip_range=$(jq -r '.dns.fakeip.inet4_range' "$SING_BOX_CONFIG") + local dns_rules=$(jq -r '.dns.rules[] | select(.server == "fakeip-server") | .domain' "$SING_BOX_CONFIG") + + print_global " ├─ FakeIP enabled: $fakeip_enabled" + print_global " ├─ FakeIP range: $fakeip_range" + print_global " └─ FakeIP domain: $dns_rules" + else + print_global " └─ sing-box config file not found" + fi + fi + fi } case "$1" in