🐤 Sync 2026-06-24 03:33:40

This commit is contained in:
github-actions[bot] committed 2026-06-24 03:33:40 +08:00
1 parent c72c833af0
commit 34879cebcd
69 files changed
+3101 -8708

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=beszel-agent
PKG_VERSION:=0.18.7
PKG_RELEASE:=5
PKG_RELEASE:=6
ifeq ($(ARCH),aarch64)
PKG_ARCH:=arm64
+1
View File
@@ -4,4 +4,5 @@ config agent 'agent'
option public_key ''
option hub_url '' # optional, for outbound mode (websockets)
option token '' # optional, for outbound mode (websockets)
option extra_filesystems '' # optional, comma-separated, e.g. 'sda1__NAS'
+3 -1
View File
@@ -7,7 +7,7 @@ USE_PROCD=1
PROG=/usr/bin/beszel-agent
start_service() {
local enabled port key url token
local enabled port key url token extra_fs
config_load 'beszel-agent'
config_get_bool enabled 'agent' 'enabled' '0'
@@ -15,6 +15,7 @@ start_service() {
config_get key 'agent' 'public_key' ''
config_get url 'agent' 'hub_url' ''
config_get token 'agent' 'token' ''
config_get extra_fs 'agent' 'extra_filesystems' ''
[ "$enabled" -eq 0 ] && return 0
@@ -39,6 +40,7 @@ start_service() {
}
procd_set_param env DATA_DIR=/usr/share/beszel-agent
[ -n "$extra_fs" ] && procd_append_param env EXTRA_FILESYSTEMS="$extra_fs"
procd_set_param respawn 3600 5 5
procd_set_param stdout 1
procd_set_param stderr 1
+2 -2
View File
@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=BitSrunLoginGo
PKG_VERSION:=1.6.6
PKG_RELEASE:=4
PKG_VERSION:=1.6.7
PKG_RELEASE:=5
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/Mmx233/BitSrunLoginGo/tar.gz/v$(PKG_VERSION)?
+3 -1
View File
@@ -1,10 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2023 ImmortalWrt.org
include $(TOPDIR)/rules.mk
PKG_NAME:=dae
PKG_VERSION:=2026.06.14
PKG_RELEASE:=11
PKG_RELEASE:=12
PKG_SOURCE:=dae-src-2026.06.14-fa89ea7197a5.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/dae-src
+5 -2
View File
@@ -1,10 +1,12 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2023 ImmortalWrt.org
include $(TOPDIR)/rules.mk
PKG_NAME:=daed
PKG_VERSION:=2026.06.14
PKG_RELEASE:=12
PKG_RELEASE:=13
PKG_SOURCE:=daed-src-2026.06.14-4e215048068a.tar.gz
PKG_SOURCE_URL:=https://github.com/kenzok8/openwrt-daede/releases/download/daed-src
@@ -94,7 +96,8 @@ endef
define Build/Prepare
mkdir -p $(DAED_BUILD_DIR)
$(TAR) --strip-components=1 -C $(DAED_BUILD_DIR) -xzf $(DL_DIR)/$(PKG_SOURCE)
$(if $(wildcard $(PATCH_DIR)/*.patch),$(call PatchDir,$(PKG_BUILD_DIR),$(PATCH_DIR),))
$(if $(wildcard $(CURDIR)/patches/*.patch),$(call PatchDir,$(PKG_BUILD_DIR),$(CURDIR)/patches,))
$(if $(filter arm,$(ARCH)),$(if $(wildcard $(CURDIR)/patches_arm/*.patch),$(call PatchDir,$(PKG_BUILD_DIR),$(CURDIR)/patches_arm,)))
endef
DAE_CFLAGS:= \
@@ -0,0 +1,42 @@
From: kenzok8 <kenzok8@noreply>
Date: 2026-06-23
Subject: [PATCH] daed: detach BPF hooks when stopping from dashboard
The dashboard "stop" (GraphQL Run(dry:true)) is delivered to dae-wing as a
reload to EmptyConfig. The fast-reload path keeps the eBPF hooks attached via
EjectBpf() (it only skips bpf.Close(), the TC/clsact filters stay bound). On a
genuine stop this leaves the LAN/WAN clsact programs attached with no tproxy
behind them, so every TCP/UDP packet (including DNS:53) is steered into a dead
tproxy and black-holed; only `network restart`/reboot recovers. ICMP is not
hijacked, so the box still pings IPs ("internal works, external dead").
dae-core already has DetachBpfHooks() for exactly this, but upstream only calls
it from the standalone dae SIGTERM handler (dae-core/cmd/run.go), never on
dae-wing's stop path. Call it explicitly when reloading to EmptyConfig.
Reported: https://github.com/kenzok8/openwrt-daede/issues/13
---
--- a/dae/run.go
+++ b/dae/run.go
@@ -138,6 +138,21 @@
/* dae-wing start */
newConf := newReloadMsg.Config
/* dae-wing end */
+
+ // openwrt-daede patch: a "stop" from the dashboard is delivered as a
+ // reload to EmptyConfig. The fast-reload path keeps the eBPF hooks
+ // attached via EjectBpf (only bpf.Close() is skipped, the TC filters
+ // stay bound). On a real stop that leaves the LAN/WAN clsact programs
+ // attached with no tproxy behind them, black-holing all TCP/UDP
+ // (incl. DNS) until `network restart`/reboot. Upstream only calls
+ // DetachBpfHooks() from the standalone dae SIGTERM handler, never on
+ // dae-wing's stop path. Detach this generation's BPF hooks now so the
+ // datapath is fully removed when stopping.
+ if newConf == EmptyConfig {
+ if e := c.DetachBpfHooks(); e != nil {
+ log.Errorln("[Stop] DetachBpfHooks:", e)
+ }
+ }
// New logger.
oldLogOutput := log.Out
log = logrus.New()
+2 -2
View File
@@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:= deepbot
PKG_VERSION:= 0.0.2
PKG_RELEASE:=2
PKG_VERSION:= 0.0.3
PKG_RELEASE:=3
include $(INCLUDE_DIR)/package.mk
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -6,8 +6,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=dns2socks-rust
PKG_VERSION:=0.2.5
PKG_RELEASE:=3
PKG_VERSION:=0.2.6
PKG_RELEASE:=4
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/tun2proxy/dns2socks/tar.gz/v$(PKG_VERSION)?
+2 -2
View File
@@ -8,8 +8,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=go-ethereum
PKG_VERSION:=1.17.3
PKG_RELEASE:=6
PKG_VERSION:=1.17.4
PKG_RELEASE:=7
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/ethereum/go-ethereum/tar.gz/v${PKG_VERSION}?
+1 -1
View File
@@ -9,7 +9,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=glorytun
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=95fa5ead2154adb546bcdb454c56c876e9f60bb5
PKG_SOURCE:=glorytun-$(PKG_VERSION).tar.gz
+3 -3
View File
@@ -89,6 +89,9 @@ start_instance() {
}
[ "${enable}" = "1" ] || return 1
apply_sysctl_optimizations
[ "${proto}" = "tcp" ] || return 1
[ -n "${key}" ] || {
_err "Key empty"
@@ -163,9 +166,6 @@ start_instance() {
}
start_service() {
# Apply system optimizations before starting instances
apply_sysctl_optimizations
config_load glorytun
config_foreach start_instance glorytun
}
+2 -2
View File
@@ -16,8 +16,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-amlogic
PKG_VERSION:=3.1.318
PKG_RELEASE:=15
PKG_VERSION:=3.1.319
PKG_RELEASE:=16
PKG_LICENSE:=GPL-2.0 License
PKG_MAINTAINER:=ophub <https://github.com/ophub/luci-app-amlogic>
@@ -80,14 +80,12 @@ return view.extend({
maxF.rmempty = false;
});
// Wrap the default saveApply: after a successful UCI commit, trigger
// reload_cpu so the new governor and frequency limits take effect
// without the user manually restarting the service.
const origHandle = m.handleSaveApply;
m.handleSaveApply = function () {
return origHandle.apply(this, arguments)
.then(function (r) { callReloadCpu(); return r; });
};
// Reload CPU settings after the LuCI apply mechanism commits UCI to disk.
// The standard apply flow (apply_rollback → ucitrack → init.d restart)
// reads UCI before the new values are fully written, so we re-apply here.
document.addEventListener('uci-applied', function () {
callReloadCpu();
});
return m.render();
}
@@ -704,8 +704,10 @@ function m_save_backup_list(req) {
}
function m_reload_cpu() {
shcall('(sleep 1 && /etc/init.d/amlogic start) &');
return { code: 0 };
// Apply governor / freq settings synchronously so they take effect before
// the RPC response is sent back to the browser.
const rc = shcall('/etc/init.d/amlogic start');
return { code: rc };
}
// Sync menu_install and menu_armcpu UCI flags based on runtime platform detection.
+2 -2
View File
@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-daede
PKG_VERSION:=1.14.6
PKG_RELEASE:=21
PKG_VERSION:=1.14.7
PKG_RELEASE:=22
PKG_MAINTAINER:=kenzok8
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
@@ -33,7 +33,6 @@ const BACKENDS = {
log: '/var/log/dae/dae.log',
pkg: 'dae',
config: '/etc/dae/config.dae',
example: '/etc/dae/example.dae',
hasWebUI: false,
useNetns: false
}
@@ -11,84 +11,62 @@
/* dae 示例里的占位订阅特征 —— example.com、relative/path/to 或中文占位文本 */
const RE_PLACEHOLDER_URL = /(['"])(?:(?:https?|https-file|file):\/\/[^'"]*?(?:example\.com|relative\/path\/to)[^'"]*|你的订阅链接或者机场链接)\1/;
/* 常用块片段 —— 给文本模式用户一键插入官方推荐结构 */
const SNIPPETS = {
subscription:
'\nsubscription {\n' +
' # 把下面这行换成你的机场订阅链接\n' +
" my_sub: '你的订阅链接或者机场链接'\n" +
'}\n',
node:
'\nnode {\n' +
' # 单条节点链接(ss/vmess/trojan/vless 等 share link)\n' +
" # 'ss://...'\n" +
'}\n',
group:
'\ngroup {\n' +
' my_group {\n' +
' # 节点选择策略:min_moving_avg / min / random / fixed(0)\n' +
' policy: min_moving_avg\n' +
' }\n' +
'}\n',
routing:
'\nrouting {\n' +
' # 私网直连\n' +
' dip(geoip:private) -> direct\n' +
' # 国内直连\n' +
' dip(geoip:cn) -> direct\n' +
' domain(geosite:cn) -> direct\n' +
' # 兜底:走代理组\n' +
' fallback: my_group\n' +
'}\n',
dns:
'\ndns {\n' +
' upstream {\n' +
" alidns: 'udp://dns.alidns.com:53'\n" +
" googledns: 'tcp+udp://dns.google:53'\n" +
' }\n' +
' routing {\n' +
' request {\n' +
' qname(geosite:cn) -> alidns\n' +
' fallback: googledns\n' +
' }\n' +
' }\n' +
'}\n',
include:
'\ninclude {\n' +
' # 相对路径:相对于 dae -c 指定的入口配置目录\n' +
' config.d/*.dae\n' +
'}\n'
};
/* 把 example.dae 的 subscription 块瘦身成「只保留 1 行占位 + 中文引导注释」,
降低用户认知负担。其他块(global/node/group/routing/dns)原样保留。 */
function simplifySubscriptionBlock(text) {
if (!text) return text;
const lines = text.split('\n');
let start = -1, end = -1, depth = 0;
for (let i = 0; i < lines.length; i++) {
if (start < 0) {
if (/^\s*subscription\s*\{/.test(lines[i])) {
start = i;
depth = 1;
continue;
}
} else {
depth += (lines[i].match(/\{/g) || []).length;
depth -= (lines[i].match(/\}/g) || []).length;
if (depth <= 0) { end = i; break; }
}
}
if (start < 0 || end < 0) return text;
/* 整块替换:保留原有 block 缩进风格(4 空格) */
const replacement = [
'subscription {',
' # ⚠ 把下面这行的 URL 换成你机场的订阅链接,然后保存。',
" my_sub: '你的订阅链接或者机场链接'",
'}'
];
return lines.slice(0, start).concat(replacement).concat(lines.slice(end + 1)).join('\n');
}
/* Minimal ready-to-run default: gen-dae-config.sh defaults + a placeholder subscription to swap. */
const DEFAULT_TEMPLATE =
'# luci-app-daede 默认配置:把 subscription 里的占位链接换成你的机场订阅,保存即可运行。\n' +
'global {\n' +
' tproxy_port: 12345\n' +
' tproxy_port_protect: true\n' +
' log_level: info\n' +
' lan_interface: br-lan\n' +
' wan_interface: auto\n' +
' auto_config_kernel_parameter: true\n' +
' dial_mode: domain\n' +
" tcp_check_url: 'http://cp.cloudflare.com,1.1.1.1,2606:4700:4700::1111'\n" +
" udp_check_dns: 'dns.google:53,8.8.8.8,2001:4860:4860::8888'\n" +
' check_interval: 30s\n' +
' check_tolerance: 50ms\n' +
'}\n' +
'\n' +
'subscription {\n' +
' # ⚠ 把下面这行的 URL 换成你机场的订阅链接,然后保存。\n' +
" my_airport: 'https://example.com/sub'\n" +
'}\n' +
'\n' +
'dns {\n' +
' ipversion_prefer: 4\n' +
' upstream {\n' +
" cndns: 'udp://dns.alidns.com:53'\n" +
" fallbackdns: 'tcp+udp://dns.google:53'\n" +
' }\n' +
' routing {\n' +
' request {\n' +
' qname(geosite:cn) -> cndns\n' +
' fallback: fallbackdns\n' +
' }\n' +
' }\n' +
'}\n' +
'\n' +
'group {\n' +
' proxy {\n' +
' filter: subtag(my_airport)\n' +
' policy: min_moving_avg\n' +
' }\n' +
'}\n' +
'\n' +
'routing {\n' +
' pname(NetworkManager) -> direct\n' +
' dip(224.0.0.0/3) -> direct\n' +
' dip(255.255.255.255/32) -> direct\n' +
" dip('ff00::/8') -> direct\n" +
' dip(geoip:private) -> direct\n' +
' l4proto(udp) && dport(123) -> direct\n' +
' domain(connectivitycheck.gstatic.com) -> direct\n' +
' domain(msftconnecttest.com) -> direct\n' +
' dip(geoip:cn) -> direct\n' +
' domain(geosite:cn) -> direct\n' +
' fallback: proxy\n' +
'}\n';
function detectPlaceholders(text) {
if (!text) return [];
@@ -584,7 +562,7 @@ function renderDaeEditor() {
const textarea = E('textarea', {
'class': 'dd-editor dd-editor-hl',
'spellcheck': 'false',
'placeholder': _('dae config file is empty. Click "Initialize from example" to start, or paste your config here.')
'placeholder': _('dae config file is empty. Click "Load default config" to start, or paste your config here.')
}, '');
const hlCode = E('code', {});
const hlPre = E('pre', { 'class': 'dd-hl', 'aria-hidden': 'true' }, hlCode);
@@ -595,7 +573,7 @@ function renderDaeEditor() {
}
textarea.addEventListener('scroll', function() { hlPre.scrollTop = textarea.scrollTop; });
const save = E('button', { 'class': 'cbi-button cbi-button-positive' }, _('Save manual config'));
const init = E('button', { 'class': 'cbi-button cbi-button-action' }, _('Initialize from example'));
const init = E('button', { 'class': 'cbi-button cbi-button-action' }, _('Load default config'));
const status = E('span', { 'class': 'dd-editor-status' }, '');
const phWarn = E('div', { 'class': 'dd-ph-warn' }, [
@@ -605,40 +583,12 @@ function renderDaeEditor() {
E('ul', { 'class': 'dd-ph-list' })
]);
/* Insert Block 下拉:选完后自动复位到首项 */
const insertSelect = E('select', { 'class': 'dd-insert-select', 'title': _('Insert config block at cursor') }, [
E('option', { 'value': '' }, _('+ Insert Block…')),
E('option', { 'value': 'subscription' }, 'subscription'),
E('option', { 'value': 'node' }, 'node'),
E('option', { 'value': 'group' }, 'group'),
E('option', { 'value': 'routing' }, 'routing'),
E('option', { 'value': 'dns' }, 'dns'),
E('option', { 'value': 'include' }, 'include')
]);
/* Footer:dae version · 行数 · 占位剩余 */
const fbVer = E('span', { 'class': 'dd-fb-item' }, [ E('span', { 'class': 'dd-fb-key' }, 'dae'), E('span', {}, '—') ]);
const fbLine = E('span', { 'class': 'dd-fb-item' }, [ E('span', { 'class': 'dd-fb-key' }, _('lines')), E('span', {}, '0') ]);
const fbStat = E('span', { 'class': 'dd-fb-item dd-fb-ok' }, '✓ ready');
const footer = E('div', { 'class': 'dd-editor-footer' }, [ fbVer, fbLine, fbStat ]);
function insertAtCursor(text) {
const start = textarea.selectionStart;
const end = textarea.selectionEnd;
const v = textarea.value;
textarea.value = v.slice(0, start) + text + v.slice(end);
const pos = start + text.length;
textarea.focus();
textarea.setSelectionRange(pos, pos);
refreshPlaceholders();
}
insertSelect.addEventListener('change', function() {
const key = insertSelect.value;
insertSelect.value = '';
if (key && SNIPPETS[key]) insertAtCursor(SNIPPETS[key]);
});
let statusTimer = null;
function flashStatus(text, kind, holdMs) {
status.textContent = text;
@@ -762,16 +712,9 @@ function renderDaeEditor() {
ev.preventDefault();
if (textarea.value.trim() && !confirm(_('This will replace your current config. Continue?')))
return;
init.disabled = true;
flashStatus(_('Loading example…'));
fs.read_direct(backend.BACKENDS.dae.example, 'text')
.then(function(content) {
textarea.value = simplifySubscriptionBlock(content || '');
refreshPlaceholders();
flashStatus(_('Example loaded — save to apply'), 'ok');
})
.catch(function(e) { flashStatus(_('Init failed: %s').format(e.message || e), 'err'); })
.finally(function() { init.disabled = false; });
textarea.value = DEFAULT_TEMPLATE;
refreshPlaceholders();
flashStatus(_('Default config loaded — replace the subscription link, then save'), 'ok');
});
/* 一次性探测 dae --version;失败就显示 unknown,不影响主流程 */
@@ -797,12 +740,12 @@ function renderDaeEditor() {
E('div', { 'class': 'dd-editor-hint', style: 'margin:0 0 10px' }, [
E('b', {}, _('Text-only mode.')),
' ',
_('Edit the dae DSL directly. Initialize loads a template. Use daed for a GUI.')
_('Edit the dae DSL directly. "Load default config" gives a ready-to-run starting point. Use daed for a GUI.')
]),
phWarn,
editWrap,
footer,
E('div', { 'class': 'dd-editor-actions' }, [ save, init, insertSelect, status ])
E('div', { 'class': 'dd-editor-actions' }, [ save, init, status ])
])
]);
adv.firstChild.addEventListener('click', function() { adv.classList.toggle('dd-closed'); });
@@ -107,8 +107,10 @@ const CSS = [
'.dd-edit-wrap .dd-editor,.dd-edit-wrap .dd-hl{margin:0;padding:10px 12px;border-width:1px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono",monospace;font-size:12px;line-height:1.5;letter-spacing:0;tab-size:4;white-space:pre-wrap;word-break:break-word;box-sizing:border-box}',
'.dd-edit-wrap .dd-hl{position:absolute;inset:0;margin:0;overflow:hidden;border:1px solid transparent;border-radius:6px 6px 0 0;pointer-events:none;background:#f6f8fa;color:#3b4252;z-index:1}',
/* reset Argon's code{background:var(--lighter)} so the overlay inherits the
pre background uniformly — otherwise a dark pre shows as side bars */
'.dd-edit-wrap .dd-hl code{font:inherit;white-space:inherit;word-break:inherit;display:block;background:transparent !important}',
pre background uniformly — otherwise a dark pre shows as side bars.
color:inherit so plain text follows .dd-hl (light in dark mode) instead of
the theme's own code{color}, which is dark and vanishes on a dark pre */
'.dd-edit-wrap .dd-hl code{font:inherit;white-space:inherit;word-break:inherit;display:block;color:inherit !important;background:transparent !important}',
'.dd-edit-wrap .dd-editor-hl{position:relative;z-index:2;color:transparent !important;background:transparent !important;caret-color:#2f7288;border:1px solid rgba(128,128,128,.28)}',
'.dd-edit-wrap .dd-editor-hl::placeholder{color:rgba(128,128,128,.55)}',
/* keep selected text transparent too — else the browser force-colors it and
+8 -20
View File
@@ -140,23 +140,17 @@ msgstr "纯文本模式。"
msgid "dae has no built-in WebUI. Edit the config DSL below by hand (subscriptions, nodes, routing, DNS). \"Initialize from example\" loads the bundled template — replace the placeholder subscription URL with your own before saving. For point-and-click management, switch backend to daed."
msgstr "dae 没有内置 WebUI,下面的 DSL 配置需要手工编辑(订阅、节点、路由、DNS)。「从示例初始化」会载入官方模板——保存前请把占位的订阅链接换成你自己的。想图形化点选管理,请把后端切回 daed。"
msgid "dae config file is empty. Click \"Initialize from example\" to start, or paste your config here."
msgstr "dae 配置文件为空。点「从示例初始化」开始,或直接粘贴你的配置。"
msgid "dae config file is empty. Click \"Load default config\" to start, or paste your config here."
msgstr "dae 配置文件为空。点「初始化默认配置」开始,或直接粘贴你的配置。"
msgid "Edit the dae DSL directly. Initialize loads a template. Use daed for a GUI."
msgstr "直接编辑 dae DSL,「从示例初始化」载入模板。图形界面用 daed。"
msgid "Edit the dae DSL directly. \"Load default config\" gives a ready-to-run starting point. Use daed for a GUI."
msgstr "直接编辑 dae DSL,「初始化默认配置」给一份开箱即用的起点。图形界面用 daed。"
msgid "Save and Hot Reload"
msgstr "保存并热重载"
msgid "Initialize from example"
msgstr "从示例初始化"
msgid "+ Insert Block…"
msgstr "+ 插入块…"
msgid "Insert config block at cursor"
msgstr "在光标处插入配置块"
msgid "Load default config"
msgstr "初始化默认配置"
msgid "lines"
msgstr "行"
@@ -200,11 +194,8 @@ msgstr "已校验 · 已保存 · 已热重载"
msgid "Save failed: %s"
msgstr "保存失败:%s"
msgid "Loading example…"
msgstr "加载示例中…"
msgid "Example loaded"
msgstr "示例已加载"
msgid "Default config loaded — replace the subscription link, then save"
msgstr "已载入默认配置——把订阅链接换成你自己的,然后保存"
msgid "Init failed: %s"
msgstr "初始化失败:%s"
@@ -410,9 +401,6 @@ msgstr "失败"
msgid "This will replace your current config. Continue?"
msgstr "这将覆盖当前配置,继续?"
msgid "Example loaded — save to apply"
msgstr "示例已载入,保存后生效"
msgid "Saved OK (start dae to apply)"
msgstr "已保存(启动 dae 后生效)"
+8 -20
View File
@@ -140,23 +140,17 @@ msgstr "纯文本模式。"
msgid "dae has no built-in WebUI. Edit the config DSL below by hand (subscriptions, nodes, routing, DNS). \"Initialize from example\" loads the bundled template — replace the placeholder subscription URL with your own before saving. For point-and-click management, switch backend to daed."
msgstr "dae 没有内置 WebUI,下面的 DSL 配置需要手工编辑(订阅、节点、路由、DNS)。「从示例初始化」会载入官方模板——保存前请把占位的订阅链接换成你自己的。想图形化点选管理,请把后端切回 daed。"
msgid "dae config file is empty. Click \"Initialize from example\" to start, or paste your config here."
msgstr "dae 配置文件为空。点「从示例初始化」开始,或直接粘贴你的配置。"
msgid "dae config file is empty. Click \"Load default config\" to start, or paste your config here."
msgstr "dae 配置文件为空。点「初始化默认配置」开始,或直接粘贴你的配置。"
msgid "Edit the dae DSL directly. Initialize loads a template. Use daed for a GUI."
msgstr "直接编辑 dae DSL,「从示例初始化」载入模板。图形界面用 daed。"
msgid "Edit the dae DSL directly. \"Load default config\" gives a ready-to-run starting point. Use daed for a GUI."
msgstr "直接编辑 dae DSL,「初始化默认配置」给一份开箱即用的起点。图形界面用 daed。"
msgid "Save and Hot Reload"
msgstr "保存并热重载"
msgid "Initialize from example"
msgstr "从示例初始化"
msgid "+ Insert Block…"
msgstr "+ 插入块…"
msgid "Insert config block at cursor"
msgstr "在光标处插入配置块"
msgid "Load default config"
msgstr "初始化默认配置"
msgid "lines"
msgstr "行"
@@ -200,11 +194,8 @@ msgstr "已校验 · 已保存 · 已热重载"
msgid "Save failed: %s"
msgstr "保存失败:%s"
msgid "Loading example…"
msgstr "加载示例中…"
msgid "Example loaded"
msgstr "示例已加载"
msgid "Default config loaded — replace the subscription link, then save"
msgstr "已载入默认配置——把订阅链接换成你自己的,然后保存"
msgid "Init failed: %s"
msgstr "初始化失败:%s"
@@ -410,9 +401,6 @@ msgstr "失败"
msgid "This will replace your current config. Continue?"
msgstr "这将覆盖当前配置,继续?"
msgid "Example loaded — save to apply"
msgstr "示例已载入,保存后生效"
msgid "Saved OK (start dae to apply)"
msgstr "已保存(启动 dae 后生效)"
@@ -226,7 +226,7 @@ generate() {
fb_up="$(sanitize "$fb_up")"
{
echo "# Auto-generated by luci-app-daede form. Manual edits are overwritten on next save."
echo "# 本配置由 luci-app-daede 表单自动生成,再次保存表单会覆盖你的手动修改。"
echo "global {"
echo " tproxy_port: 12345"
echo " tproxy_port_protect: true"
@@ -68,8 +68,7 @@ return view.extend({
o = s.option(form.ListValue, 'fullcone', _('Enable FullCone NAT'));
o.value('0', _('Disable'));
o.value('1', _('FULLCONENAT'));
if (!fw4)
o.value('2', _('Boardcom Fullcone NAT1'));
o.value('2', _('Boardcom Fullcone NAT1'));
addTCPCCAOption();
if (fw4)
o = s.option(form.Flag, 'fullcone6', _('Enable FullCone NAT6'));
@@ -8,7 +8,6 @@
},
"depends": {
"acl": [ "luci-app-firewall" ],
"fs": { "/sbin/fw3": "executable" },
"uci": { "firewall": true }
}
},
+1 -1
View File
@@ -4,7 +4,7 @@ LUCI_TITLE:=Information dashboard for 3G/LTE dongle
LUCI_DEPENDS:=+modeminfo
PKG_LICENSE:=GPLv3
PKG_VERSION:=0.4.8
PKG_RELEASE:=9
PKG_RELEASE:=10
include $(TOPDIR)/feeds/luci/luci.mk
@@ -60,7 +60,7 @@ var qdesc = _('Select qmi port.');
var lacdec = _('Show LAC and CID in decimal.');
var mmdesc = _('Get device hardware name via mmcli utility if aviable.');
var qmidesc = _('Set qmi mode.');
var idesc = _('Show short info.<br />Overview: show info on main page \"Cellular Network\" section<br />MenuBar: show info on menubar all pages<br />NOTICE: Don\'t add too many modems in menubar, it may break the theme display.');
var idesc = _('Show short info.<br />Overview: show info on main page \"Cellular Network\" section<br />MenuBar: show info on menubar all pages<br />NOTICE: Do not add too many modems in menubar, it may break the theme display.');
var portplace = _('Please select a port');
return view.extend({
+1 -1
View File
@@ -135,7 +135,7 @@ msgstr "QMI через MBIM"
msgid "Short info"
msgstr "Краткая информация"
msgid "Show short info.<br />Overview: show info on main page \"Cellular Network\" section<br />MenuBar: show info on menubar all pages<br />NOTICE: Don\'t add too many modems in menubar, it may break the theme display."
msgid "Show short info.<br />Overview: show info on main page \"Cellular Network\" section<br />MenuBar: show info on menubar all pages<br />NOTICE: Do not add too many modems in menubar, it may break the theme display."
msgstr "Показвать краткую информацию<br />На главной: показывать главной странице раздел \"Сотовая сеть\"<br />Меню: показывать в строке меню на всех страницах<br />ВНИМАНИЕ: не добавляйте слишком много устройств в строку меню, это может сломать отображение."
msgid "overview"
+2 -2
View File
@@ -10,8 +10,8 @@ LUCI_TITLE:=Simple OTA Update for OpenWrt
#LUCI_DEPENDS:= +luci-app-firewall
PKG_LICENSE:=Apache-2.0
PKG_VERSION:=0.0.1
PKG_RELEASE:=1
PKG_VERSION:=0.0.2
PKG_RELEASE:=2
include $(TOPDIR)/feeds/luci/luci.mk
@@ -17,30 +17,44 @@ return view.extend({
var self = this;
this.verifyCheckResult().then(function(success) {
if (success) {
// If files already exist, disable Check button
self.checkButton.disabled = true;
// And show information about available update
self.statusDiv.innerHTML = '';
self.statusDiv.appendChild(E('div', {
'class': 'alert-message success'
}, [
E('h3', {}, _('Update Available')),
E('pre', {
'style': 'white-space: pre-wrap; background: #f5f5f5; padding: 10px; border-radius: 3px; color: black;'
}, self.changelog || '')
]));
// Activate Upgrade button
self.showUpdateAvailable();
self.upgradeButton.disabled = false;
}
}).catch(function(err) {
// No files, leave Check button active
});
}).catch(function() {});
},
showUpdateAvailable: function() {
var self = this;
self.statusDiv.innerHTML = '';
self.statusDiv.appendChild(E('div', { 'class': 'alert-message success' }, [
E('h3', {}, _('Update Available')),
E('button', {
'class': 'btn cbi-button cbi-button-neutral',
'style': 'margin-top: 6px;',
'click': function() { self.showChangelog(); }
}, _('Show Changelog'))
]));
},
showChangelog: function() {
ui.showModal(_('Changelog'), [
E('pre', {
'style': 'white-space: pre-wrap; max-height: 60vh; overflow-y: auto; ' +
'background: #f5f5f5; padding: 10px; border-radius: 3px; color: black;'
}, this.changelog || _('(empty)')),
E('div', { 'class': 'right' }, [
E('button', {
'class': 'btn cbi-button',
'click': ui.hideModal
}, _('Close'))
])
]);
},
render: function() {
var self = this;
// Create control elements
this.checkButton = E('button', {
'class': 'btn cbi-button cbi-button-positive important',
'click': ui.createHandlerFn(this, 'handleCheck')
@@ -53,11 +67,7 @@ return view.extend({
}, _('Upgrade'));
this.statusDiv = E('div', { 'class': 'cbi-section' });
this.progressBar = E('div', {
'style': 'display: none; margin: 10px 0;'
});
// Main layout
var container = E('div', { 'class': 'cbi-map' }, [
E('h2', {}, _('OTA System Update')),
E('div', { 'class': 'cbi-section' }, [
@@ -65,11 +75,9 @@ return view.extend({
' ',
this.upgradeButton
]),
this.progressBar,
this.statusDiv
]);
// Check initial state when page loads
this.checkInitialState();
return container;
@@ -77,14 +85,11 @@ return view.extend({
handleCheck: function() {
var self = this;
this.checkButton.disabled = true;
this.statusDiv.innerHTML = '';
this.statusDiv.appendChild(E('div', {
'class': 'spinner'
}, _('Checking for updates...')));
this.statusDiv.appendChild(E('div', { 'class': 'spinner' }, _('Checking for updates...')));
// Execute update check
return fs.exec('/usr/share/ota.sh', ['check'])
.then(function() {
return self.verifyCheckResult();
@@ -92,35 +97,25 @@ return view.extend({
.then(function(success) {
if (success) {
self.upgradeButton.disabled = false;
self.statusDiv.innerHTML = '';
self.statusDiv.appendChild(E('div', {
'class': 'alert-message success'
}, [
E('h3', {}, _('Update Available')),
E('pre', {
'style': 'white-space: pre-wrap; background: #f5f5f5; padding: 10px; border-radius: 3px; color: black;'
}, self.changelog || '')
]));
self.showUpdateAvailable();
} else {
self.statusDiv.innerHTML = '';
self.statusDiv.appendChild(E('div', {
'class': 'alert-message warning'
}, _('No updates available or check failed')));
self.statusDiv.appendChild(E('div', { 'class': 'alert-message warning' },
_('No updates available or check failed')));
}
self.checkButton.disabled = false;
})
.catch(function(err) {
self.statusDiv.innerHTML = '';
self.statusDiv.appendChild(E('div', {
'class': 'alert-message error'
}, _('Check failed: ') + (err.message || err)));
self.statusDiv.appendChild(E('div', { 'class': 'alert-message error' },
_('Check failed: ') + (err.message || err)));
self.checkButton.disabled = false;
});
},
verifyCheckResult: function() {
var self = this;
return Promise.all([
fs.stat('/tmp/profiles.json').catch(function() { return null; }),
fs.stat('/tmp/update.lock').catch(function() { return null; }),
@@ -131,125 +126,180 @@ return view.extend({
})
.catch(function() { return false; })
]).then(function(results) {
// Check that all files exist and changelog is not empty
return results[0] !== null &&
results[1] !== null &&
return results[0] !== null &&
results[1] !== null &&
results[2] === true;
});
},
// ----------------------------------------------------------------
// Upgrade modal
// ----------------------------------------------------------------
handleUpgrade: function() {
var self = this;
this.upgradeButton.disabled = true;
this.checkButton.disabled = true;
this.progressBar.style.display = 'block';
// Initialize progress bar once
this.progressBar.innerHTML = '';
// Create progress bar title
this.progressTitle = E('div', {
'class': 'cbi-progressbar-title'
}, _('Starting upgrade...'));
this.progressBar.appendChild(this.progressTitle);
// Create progress bar container
this.currentProgressBar = E('div', {
'class': 'cbi-progressbar',
'style': 'margin: 10px 0;'
}, E('div', { 'style': 'width: 0%' }));
this.progressBar.appendChild(this.currentProgressBar);
// First start progress simulation
this.simulateProgressBar();
// Remove stale progress file before starting
fs.remove('/tmp/ota_progress').catch(function() {});
self.openUpgradeModal();
// Then start update process
return fs.exec('/usr/share/ota.sh', ['upgrade'])
.then(function(result) {
// Wait for progress simulation to complete to 100%
return new Promise(function(resolve) {
var checkCompletion = function() {
if (self.progressInterval) {
setTimeout(checkCompletion, 100);
} else {
resolve(result);
}
};
checkCompletion();
});
})
.then(function(result) {
// Show final message
self.progressBar.style.display = 'none';
self.statusDiv.innerHTML = '';
self.statusDiv.appendChild(E('div', {
'class': 'alert-message warning'
}, _('Download completed successfully! Start upgrade.<br />DO NOT POWER OFF THIS DEVICE!<br />System will be upgrade completed after reboot!')));
self.upgradeButton.disabled = false;
self.checkButton.disabled = false;
.then(function() {
self.stopProgressPolling();
self.setModalProgress(100, _('Upgrade started. Device will reboot...'), 'done');
self.finalizeUpgradeModal(false);
})
.catch(function(err) {
// Stop progress simulation on error
if (self.progressInterval) {
clearInterval(self.progressInterval);
self.progressInterval = null;
}
// Check if error is XHR timeout
var errorMessage = err.message || err.toString();
if (errorMessage.includes('XHR request timed out')) {
// For timeout show success message
self.progressBar.style.display = 'none';
self.statusDiv.innerHTML = '';
self.statusDiv.appendChild(E('div', {
'class': 'alert-message warning'
}, _('Download completed successfully! Start upgrade.<br />DO NOT POWER OFF THIS DEVICE!<br />System will be upgrade completed after reboot!')));
var msg = err.message || err.toString();
self.stopProgressPolling();
// XHR timeout = sysupgrade already running, treat as success
if (msg.indexOf('timed out') !== -1) {
self.setModalProgress(100, _('Upgrade started. Device will reboot...'), 'done');
self.finalizeUpgradeModal(false);
} else {
// For other errors show error message
self.progressTitle.textContent = _('Upgrade failed: ') + errorMessage;
self.progressTitle.className = 'cbi-progressbar-title error';
self.setModalProgress(0, _('Error: ') + msg, 'error');
self.finalizeUpgradeModal(true);
}
self.upgradeButton.disabled = false;
self.checkButton.disabled = false;
});
},
simulateProgressBar: function() {
openUpgradeModal: function() {
var self = this;
if (this.progressInterval) {
clearInterval(this.progressInterval);
}
let progress = 0;
this.progressInterval = setInterval(function() {
progress += Math.random() * 10 + 5; // Slowed down simulation
if (progress >= 100) {
progress = 100;
clearInterval(self.progressInterval);
self.progressInterval = null;
self.updateProgressBar(progress, _('Download completed! Prepare upgrade...'));
} else {
self.updateProgressBar(progress, _('Downloading: ') + Math.round(progress) + '%');
// Progress bar element
self.modalProgressInner = E('div', { 'style': 'width: 0%; transition: width 0.4s ease;' });
self.modalProgressBar = E('div', { 'class': 'cbi-progressbar', 'style': 'margin: 10px 0;' },
self.modalProgressInner);
// Status label
self.modalStatus = E('div', {
'style': 'font-size: 0.9em; color: #666; margin-bottom: 8px;'
}, _('Starting upgrade...'));
// Log area
self.modalLog = E('pre', {
'style': 'white-space: pre-wrap; max-height: 200px; overflow-y: auto; ' +
'background: #f5f5f5; padding: 8px; border-radius: 3px; ' +
'color: black; font-size: 0.85em; margin-top: 10px;'
}, '');
// Close button (disabled until done)
self.modalCloseBtn = E('button', {
'class': 'btn cbi-button',
'disabled': true,
'click': function() {
self.stopProgressPolling();
ui.hideModal();
self.upgradeButton.disabled = false;
self.checkButton.disabled = false;
}
}, 800); // Increased interval
}, _('Close'));
ui.showModal(_('Upgrade Progress'), [
self.modalStatus,
self.modalProgressBar,
self.modalLog,
E('div', { 'class': 'right', 'style': 'margin-top: 10px;' }, [
self.modalCloseBtn
])
]);
// Start polling /tmp/ota_progress
self.startProgressPolling();
},
updateProgressBar: function(percent, text) {
if (!this.currentProgressBar || !this.progressTitle) return;
// Update only text and progress, without recreating elements
this.progressTitle.textContent = text;
// Update progress bar as in modem example
var percentValue = Math.min(100, Math.max(0, percent));
this.currentProgressBar.firstElementChild.style.width = percentValue + '%';
// Add animation as in example
this.currentProgressBar.firstElementChild.style.animationDirection = "reverse";
startProgressPolling: function() {
var self = this;
if (self.pollTimer) clearInterval(self.pollTimer);
self.lastLogLine = '';
self.pollTimer = setInterval(function() {
fs.read('/tmp/ota_progress').then(function(raw) {
if (!raw) return;
var line = raw.trim();
if (line === self.lastLogLine) return;
self.lastLogLine = line;
if (line.indexOf('downloading') === 0) {
var pct = parseInt(line.split(' ')[1], 10) || 0;
// downloading maps to 0..70% of bar
var barPct = Math.round(pct * 0.70);
self.setModalProgress(barPct,
_('Downloading firmware: ') + pct + '%', 'progress');
self.appendModalLog(_('Downloading: ') + pct + '%');
} else if (line === 'verifying') {
self.setModalProgress(75, _('Verifying SHA256 checksum...'), 'progress');
self.appendModalLog(_('Verifying SHA256...'));
} else if (line === 'testing') {
self.setModalProgress(85, _('Testing firmware image (sysupgrade -T)...'), 'progress');
self.appendModalLog(_('Testing firmware image...'));
} else if (line === 'flashing') {
self.setModalProgress(95, _('Flashing! DO NOT POWER OFF!'), 'progress');
self.appendModalLog(_('Flashing firmware...'));
} else if (line.indexOf('error') === 0) {
var reason = line.replace('error', '').trim();
self.setModalProgress(0, _('Error: ') + reason, 'error');
self.appendModalLog(_('FAILED: ') + reason);
self.stopProgressPolling();
}
}).catch(function() {
// file not yet created — ignore
});
}, 1500);
},
stopProgressPolling: function() {
if (this.pollTimer) {
clearInterval(this.pollTimer);
this.pollTimer = null;
}
},
setModalProgress: function(percent, text, state) {
if (!this.modalProgressInner || !this.modalStatus) return;
var pct = Math.min(100, Math.max(0, percent));
this.modalProgressInner.style.width = pct + '%';
this.modalStatus.textContent = text;
if (state === 'error') {
this.modalStatus.style.color = '#c00';
} else if (state === 'done') {
this.modalStatus.style.color = '#080';
} else {
this.modalStatus.style.color = '#666';
}
},
appendModalLog: function(line) {
if (!this.modalLog) return;
this.modalLog.textContent += line + '\n';
// Auto-scroll to bottom
this.modalLog.scrollTop = this.modalLog.scrollHeight;
},
finalizeUpgradeModal: function(isError) {
if (this.modalCloseBtn) {
this.modalCloseBtn.disabled = false;
}
if (!isError) {
// For successful flash — don't re-enable buttons,
// device is about to reboot
this.statusDiv.innerHTML = '';
this.statusDiv.appendChild(E('div', { 'class': 'alert-message warning' },
_('Upgrade started! DO NOT POWER OFF THIS DEVICE! System will reboot after upgrade.')));
} else {
this.upgradeButton.disabled = false;
this.checkButton.disabled = false;
}
},
handleSaveApply: null,
+43 -24
View File
@@ -33,6 +33,11 @@
. /lib/functions.sh
PROGRESS_FILE=/tmp/ota_progress
set_progress() {
echo "$1" > ${PROGRESS_FILE}
}
load_config(){
config_get url $1 url
@@ -47,7 +52,6 @@ if [ "x${URL_BASE}" = "x" ]; then
exit 0
fi
# Get OpenWrt Release info
[ -f /etc/openwrt_release ] && {
. /etc/openwrt_release
@@ -65,20 +69,16 @@ BOARD=$(jsonfilter -s "$(cat /etc/board.json)" -e '@["model"]["id"]')
# Remove update files
remove_files(){
for f in firmware.bin changelog.txt; do
[ -f /tmp/${f} ] && {
rm -rf /tmp/${f}
}
[ -f /tmp/${f} ] && rm -rf /tmp/${f}
done
}
case $1 in
check)
if [ ! -f /tmp/update.lock ]; then
echo -e "Check updates from ${URL_BASE}\n"
fi
# Get aviable profiles
! [ -f /tmp/profiles.json ] && {
wget ${URL_BASE}/targets/${DISTRIB_TARGET}/profiles.json -O /tmp/profiles.json > /dev/null 2>&1
}
@@ -88,7 +88,6 @@ case $1 in
exit 0
}
# Get changelog
[ -f /tmp/profiles.json ] && {
[ ! -f /tmp/changelog.txt ] && {
wget ${URL_BASE}/changelog.txt -O /tmp/changelog.txt > /dev/null 2>&1
@@ -105,12 +104,12 @@ esac
BASE_BOARD=$(jsonfilter -s "$(cat /tmp/profiles.json)" -e '@["profiles"][*]["supported_devices"].*')
# Get available board info
board_stuff(){
IMAGES=$(jsonfilter -s "$(cat /tmp/profiles.json)" -e "@['profiles']['$FW_BOARD']['images'][*]" | grep sysupgrade)
echo $IMAGES | jsonfilter \
-e FILE="$['name']" \
-e SHA256="$['sha256']"
-e SHA256="$['sha256']" \
-e FILESIZE="$['size']"
}
#sha256check(){
@@ -119,7 +118,6 @@ board_stuff(){
# stuff
for b in $BASE_BOARD; do
if [ "${b}" = "${BOARD}" ]; then
# modify board name for profiles.json
FW_BOARD=$(echo $BOARD | sed -e 's/\,/_/')
[ -f /tmp/profiles.json ] && {
eval $(board_stuff)
@@ -127,9 +125,7 @@ for b in $BASE_BOARD; do
echo "Failed! Abort update"
remove_files
}
# Get remote revision firmware
FW_REV_EXT=$(echo $FILE | awk -F [-] '{gsub("rev",""); gsub(/\./,"",$2); print $2$5$6}')
# Get local revision firmware
if [ -f /rom/etc/uci-defaults/fw_rev ]; then
. /rom/etc/uci-defaults/fw_rev
VER_LOCAL=$(echo $FW_REV | awk -F [-] '{gsub("rev",""); print $1$2}')
@@ -139,43 +135,66 @@ for b in $BASE_BOARD; do
echo "Failed! Abort update"
exit 0
fi
# Firmware upgrade
case $1 in
upgrade)
if [ -f /tmp/update.lock ]; then
echo "Download firmware $FILE"
echo "from $URL_BASE"
wget $URL_BASE/targets/${DISTRIB_TARGET}/$FILE -O /tmp/firmware.bin > /dev/null 2>&1
case $? in
0) echo "Download complete." ;;
*) echo "No updates for this board: $BOARD" && remove_files && exit 0 ;;
set_progress "downloading 0"
# Start wget in background
wget ${URL_BASE}/targets/${DISTRIB_TARGET}/$FILE -O /tmp/firmware.bin 2>/dev/null &
WGET_PID=$!
# Poll file size while wget runs
while kill -0 $WGET_PID 2>/dev/null; do
CURRENT=$(stat -c%s /tmp/firmware.bin 2>/dev/null || echo 0)
if [ -n "$FILESIZE" ] && [ "$FILESIZE" -gt 0 ]; then
PCT=$(( CURRENT * 100 / FILESIZE ))
[ $PCT -gt 99 ] && PCT=99
set_progress "downloading $PCT"
fi
sleep 1
done
wait $WGET_PID
DL_RC=$?
case $DL_RC in
0) echo "Download complete."
set_progress "downloading 100" ;;
*) echo "No updates for this board: $BOARD"
set_progress "error download"
remove_files && exit 0 ;;
esac
# Get local SHA256
set_progress "verifying"
SHA256_DL=$(sha256sum /tmp/firmware.bin | awk '{print $1}')
echo -n "Check sha256 sum: "
# Compare remote and download file SHA256
if [ "$SHA256" = "$SHA256_DL" ]; then
echo "OK"
echo "Update process start!"
echo "Device will be rebooted."
echo "DO NOT TURN OFF DEVICE!"
# Test firmware image before flashing
set_progress "testing"
sysupgrade -T /tmp/firmware.bin
case $? in
0) echo "Flashing firmware" ;;
*) echo "Failed! Abort update" && remove_files && exit 0 ;;
0) echo "Flashing firmware"
set_progress "flashing" ;;
*) echo "Failed! Abort update"
set_progress "error verify"
remove_files && exit 0 ;;
esac
rm -rf /tmp/update.lock /tmp/profiles.json /tmp/changelog.txt
# Updrade firmware
sleep 25 && sysupgrade /tmp/firmware.bin &
else
echo "Failed! Abort update."
set_progress "error sha256"
remove_files && rm -rf /tmp/update.lock /tmp/profiles.json
fi
fi
;;
check)
# Compare firmware versions
if [ $FW_REV_EXT -gt $FW_VER_LOCAL ]; then
echo "New firmware upgrade release!"
echo -e "*** $FILE ***\n"
+1 -1
View File
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=26.6.2
PKG_RELEASE:=164
PKG_RELEASE:=165
PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \
@@ -80,6 +80,7 @@ o:value("https://www.google.com/generate_204", "Google")
o:value("https://www.youtube.com/generate_204", "YouTube")
o:value("https://connect.rom.miui.com/generate_204", "MIUI (CN)")
o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud (CN)")
o:value("https://wifi.vivo.com.cn/generate_204", "VIVO (CN)")
o.default = o.keylist[3]
o.description = translate("The URL used to detect the connection status.")
o:depends("health_check_type", "passwall_logic")
@@ -25,6 +25,7 @@ o:value("https://www.google.com/generate_204", "Google")
o:value("https://www.youtube.com/generate_204", "YouTube")
o:value("https://connect.rom.miui.com/generate_204", "MIUI (CN)")
o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud (CN)")
o:value("https://wifi.vivo.com.cn/generate_204", "VIVO (CN)")
o.default = o.keylist[3]
-- [[ Add the node via the link ]]--
@@ -129,6 +129,7 @@ o:value("https://www.google.com/generate_204", "Google")
o:value("https://www.youtube.com/generate_204", "YouTube")
o:value("https://connect.rom.miui.com/generate_204", "MIUI (CN)")
o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud (CN)")
o:value("https://wifi.vivo.com.cn/generate_204", "VIVO (CN)")
o.default = o.keylist[3]
o:depends("enable_autoswitch", true)
@@ -245,6 +245,7 @@ if load_balancing_options then -- [[ Load balancing Start ]]
o:value("https://www.youtube.com/generate_204", "YouTube")
o:value("https://connect.rom.miui.com/generate_204", "MIUI (CN)")
o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud (CN)")
o:value("https://wifi.vivo.com.cn/generate_204", "VIVO (CN)")
o.default = o.keylist[3]
o.description = translate("The URL used to detect the connection status.")
@@ -163,6 +163,7 @@ if load_urltest_options then -- [[ URLTest Start ]]
o:value("https://www.youtube.com/generate_204", "YouTube")
o:value("https://connect.rom.miui.com/generate_204", "MIUI (CN)")
o:value("https://connectivitycheck.platform.hicloud.com/generate_204", "HiCloud (CN)")
o:value("https://wifi.vivo.com.cn/generate_204", "VIVO (CN)")
o.default = o.keylist[3]
o.description = translate("The URL used to detect the connection status.")
@@ -1610,10 +1610,14 @@ function parse_realm_uri(uri)
local scheme, token, server_url, realm_id, query = trim(uri):match("^(realm%+http|realm)://([^@]+)@([^/]+)/([^?]*)%??(.*)$")
if not scheme or not token or not server_url or not realm_id then return nil end
realm_id = realm_id:gsub("/+$", "")
local address, port = server_url:match("^%[?([^%]]+)%]?:?(%d*)$")
port = tonumber(port) or (scheme == "realm+http" and 80 or 443)
local realm = {
scheme = scheme,
token = token,
server_url = server_url,
address = address,
port = port,
realm_id = realm_id
}
-- 解析 query 中的 stun=
@@ -586,6 +586,8 @@ function gen_outbound(flag, node, tag, proxy_table)
realm.server_url = (realm.scheme == "realm+http" and "http://" or "https://") .. realm.server_url
realm.stun_servers = realm.stun_servers or node.hysteria2_realm_stun
realm.scheme = nil
realm.address = nil
realm.port = nil
return realm
end
return nil
@@ -933,6 +935,8 @@ function gen_config_server(node)
realm.server_url = (realm.scheme == "realm+http" and "http://" or "https://") .. realm.server_url
realm.stun_servers = realm.stun_servers or node.hysteria2_realm_stun
realm.scheme = nil
realm.address = nil
realm.port = nil
realm.stun_domain_resolver = "direct"
return realm
end
@@ -389,6 +389,14 @@ function gen_outbound(flag, node, tag, proxy_table)
}
}
if node.protocol == "hysteria" and node.hysteria2_realms then
local realm = api.parse_realm_uri(node.hysteria2_realm_url)
if realm then
result.settings.address = realm.address
result.settings.port = realm.port
end
end
if node.protocol == "wireguard" then
result.settings.noKernelTun = true
if node.finalmask and node.finalmask ~= "" then
File diff suppressed because it is too large. Load diff
@@ -202,12 +202,11 @@
103.125.236.0/22
103.126.1.0/24
103.126.124.0/22
103.13.12.0/24
103.13.244.0/22
103.130.160.0/23
103.131.138.0/23
103.131.152.0/22
103.131.168.0/22
103.131.168.0/23
103.132.212.0/23
103.132.22.0/23
103.133.128.0/23
@@ -239,7 +238,6 @@
103.149.244.0/22
103.15.4.0/22
103.15.96.0/22
103.150.10.0/23
103.150.164.0/23
103.150.24.0/23
103.151.148.0/23
@@ -265,7 +263,7 @@
103.162.10.0/23
103.163.180.0/24
103.163.46.0/23
103.164.32.0/23
103.164.32.0/24
103.165.110.0/23
103.169.50.0/23
103.169.62.0/23
@@ -307,7 +305,6 @@
103.197.0.0/22
103.197.228.0/22
103.198.124.0/22
103.198.180.0/23
103.198.216.0/21
103.198.224.0/20
103.198.244.0/22
@@ -324,6 +321,8 @@
103.200.220.0/22
103.200.224.0/24
103.201.192.0/24
103.201.196.0/24
103.201.200.0/24
103.202.0.0/19
103.202.112.0/22
103.202.120.0/21
@@ -362,8 +361,7 @@
103.213.144.0/23
103.213.148.0/22
103.213.160.0/19
103.213.48.0/21
103.213.60.0/22
103.213.48.0/20
103.213.64.0/19
103.213.96.0/22
103.214.48.0/22
@@ -382,8 +380,6 @@
103.219.184.0/22
103.219.24.0/21
103.219.32.0/21
103.219.85.0/24
103.219.86.0/23
103.219.92.0/24
103.22.188.0/22
103.22.252.0/22
@@ -406,7 +402,6 @@
103.224.220.0/22
103.224.232.0/22
103.226.57.0/24
103.226.59.0/24
103.227.120.0/22
103.227.136.0/22
103.227.228.0/22
@@ -433,7 +428,7 @@
103.232.144.0/22
103.232.166.0/23
103.233.128.0/22
103.233.136.0/23
103.233.136.0/24
103.233.138.0/24
103.233.162.0/23
103.233.4.0/22
@@ -454,8 +449,7 @@
103.236.52.0/22
103.236.56.0/21
103.236.64.0/19
103.236.96.0/23
103.236.98.0/24
103.236.96.0/22
103.237.176.0/20
103.237.192.0/19
103.237.224.0/20
@@ -465,6 +459,7 @@
103.237.8.0/22
103.238.0.0/21
103.238.132.0/22
103.238.140.0/22
103.238.144.0/22
103.238.16.0/22
103.238.160.0/22
@@ -521,6 +516,7 @@
103.25.36.0/22
103.25.64.0/23
103.250.104.0/22
103.250.124.0/22
103.250.192.0/22
103.250.216.0/22
103.250.248.0/21
@@ -647,11 +643,11 @@
103.48.235.0/24
103.49.108.0/22
103.49.12.0/22
103.49.176.0/24
103.5.192.0/23
103.5.194.0/24
103.5.52.0/24
103.52.100.0/22
103.52.104.0/23
103.52.172.0/22
103.52.176.0/22
103.52.196.0/22
@@ -672,7 +668,8 @@
103.57.139.0/24
103.59.112.0/21
103.59.124.0/22
103.59.148.0/22
103.59.148.0/23
103.59.151.0/24
103.59.168.0/23
103.6.220.0/22
103.60.164.0/22
@@ -725,7 +722,7 @@
103.78.228.0/22
103.78.60.0/22
103.79.200.0/22
103.79.228.0/24
103.79.228.0/23
103.79.24.0/22
103.8.220.0/22
103.8.32.0/22
@@ -773,6 +770,7 @@
103.96.8.0/22
103.97.112.0/23
103.97.144.0/22
103.97.175.0/24
103.97.60.0/24
103.98.125.0/24
103.98.127.0/24
@@ -786,6 +784,7 @@
103.99.104.0/22
104.192.108.0/23
104.192.110.0/24
104.234.102.0/24
106.0.4.0/22
106.108.0.0/14
106.11.0.0/16
@@ -806,8 +805,6 @@
106.2.112.0/21
106.2.124.0/22
106.2.128.0/19
106.2.224.0/24
106.2.232.0/21
106.2.37.0/24
106.2.40.0/23
106.2.42.0/24
@@ -853,6 +850,7 @@
106.80.0.0/13
106.88.0.0/14
106.92.0.0/16
107.158.37.0/24
108.165.168.0/24
108.165.240.0/24
109.244.0.0/16
@@ -862,8 +860,6 @@
110.115.128.0/17
110.116.0.0/16
110.120.0.0/16
110.124.0.0/16
110.125.128.0/17
110.152.0.0/14
110.156.0.0/15
110.16.0.0/14
@@ -911,10 +907,7 @@
111.120.0.0/14
111.124.0.0/16
111.126.0.0/15
111.128.0.0/16
111.132.0.0/16
111.142.0.0/15
111.144.0.0/14
111.148.0.0/16
111.149.0.0/24
111.160.0.0/13
@@ -1057,7 +1050,7 @@
114.113.223.0/24
114.113.224.0/20
114.113.63.0/24
114.113.64.0/20
114.113.64.0/22
114.113.80.0/22
114.113.84.0/24
114.113.88.0/21
@@ -1075,7 +1068,6 @@
114.135.0.0/16
114.138.0.0/15
114.141.128.0/18
114.142.142.0/23
114.196.0.0/15
114.212.0.0/14
114.216.0.0/13
@@ -1092,7 +1084,7 @@
114.66.240.0/20
114.66.64.0/24
114.66.72.0/21
114.66.80.0/23
114.66.81.0/24
114.67.128.0/17
114.67.16.0/21
114.67.48.0/24
@@ -1146,6 +1138,7 @@
115.32.64.0/19
115.33.0.0/19
115.33.128.0/20
115.33.64.0/18
115.44.0.0/15
115.46.0.0/16
115.48.0.0/12
@@ -1219,6 +1212,10 @@
116.214.132.0/23
116.214.134.0/24
116.214.32.0/19
116.218.0.0/18
116.218.128.0/20
116.218.144.0/21
116.218.64.0/19
116.224.0.0/12
116.242.0.0/16
116.246.0.0/15
@@ -1234,6 +1231,7 @@
116.66.123.0/24
116.66.36.0/24
116.66.48.0/23
116.66.50.0/24
116.66.53.0/24
116.66.54.0/23
116.66.98.0/24
@@ -1437,6 +1435,8 @@
119.148.160.0/20
119.15.136.0/23
119.15.140.0/23
119.16.0.0/17
119.16.128.0/18
119.161.120.0/22
119.161.124.0/24
119.161.183.0/24
@@ -1562,6 +1562,8 @@
119.91.0.0/16
119.96.0.0/13
120.0.0.0/12
120.130.0.0/18
120.130.64.0/19
120.131.0.0/19
120.131.124.0/22
120.131.88.0/21
@@ -1660,9 +1662,9 @@
121.69.0.0/16
121.70.0.0/17
121.76.0.0/15
121.79.128.0/20
121.79.144.0/22
121.79.148.0/24
121.79.131.0/24
121.79.132.0/24
121.79.134.0/23
121.8.0.0/13
121.89.0.0/16
121.91.104.0/21
@@ -1766,11 +1768,7 @@
122.72.3.0/24
122.72.38.0/24
122.72.57.0/24
122.77.240.0/24
122.84.0.0/16
122.9.0.0/16
122.90.0.0/16
122.91.0.0/17
122.94.0.0/16
122.96.0.0/15
123.101.0.0/16
@@ -1802,6 +1800,7 @@
123.244.0.0/14
123.249.0.0/17
123.253.224.0/23
123.253.226.0/24
123.254.96.0/21
123.4.0.0/14
123.49.192.0/23
@@ -1841,7 +1840,6 @@
123.66.0.0/16
123.77.0.0/16
123.8.0.0/13
123.82.0.0/17
123.83.128.0/17
123.88.0.0/15
123.90.0.0/16
@@ -1851,19 +1849,19 @@
124.126.0.0/15
124.128.0.0/13
124.14.1.0/24
124.14.10.0/24
124.14.12.0/22
124.14.16.0/21
124.14.2.0/23
124.14.224.0/19
124.14.5.0/24
124.14.64.0/18
124.14.7.0/24
124.14.8.0/21
124.14.8.0/24
124.151.0.0/16
124.152.0.0/16
124.16.0.0/15
124.160.0.0/13
124.172.0.0/15
124.174.0.0/16
124.172.0.0/14
124.192.0.0/15
124.196.12.0/23
124.196.25.0/24
@@ -1943,13 +1941,13 @@
125.98.122.0/23
125.98.128.0/17
128.108.0.0/16
128.14.116.0/24
129.204.0.0/16
129.211.0.0/16
129.28.0.0/16
132.232.0.0/16
132.237.134.0/24
134.175.0.0/16
136.0.59.0/24
138.252.72.0/23
139.129.0.0/16
139.148.0.0/16
@@ -2012,6 +2010,7 @@
140.250.0.0/16
140.255.0.0/16
140.75.0.0/16
141.11.219.0/24
143.20.246.0/24
143.64.0.0/16
144.0.0.0/16
@@ -2065,6 +2064,7 @@
150.242.80.0/22
150.242.96.0/22
150.255.0.0/16
151.246.165.0/24
151.247.148.0/23
152.104.128.0/17
152.136.0.0/16
@@ -2107,7 +2107,8 @@
155.102.20.0/24
155.102.201.0/24
155.102.202.0/24
155.102.204.0/22
155.102.205.0/24
155.102.206.0/23
155.102.208.0/21
155.102.216.0/22
155.102.22.0/23
@@ -2123,13 +2124,14 @@
155.102.43.0/24
155.102.44.0/22
155.102.48.0/20
155.102.65.0/24
155.102.64.0/23
155.102.67.0/24
155.102.68.0/23
155.102.70.0/24
155.102.74.0/23
155.102.76.0/22
155.102.72.0/21
155.102.8.0/21
155.102.91.0/24
155.102.92.0/22
155.102.98.0/23
155.126.176.0/23
156.107.160.0/23
@@ -2141,7 +2143,7 @@
156.59.108.0/24
157.0.0.0/16
157.10.112.0/23
157.10.34.0/23
157.10.35.0/24
157.119.172.0/22
157.119.252.0/22
157.119.28.0/22
@@ -2172,7 +2174,6 @@
160.22.188.0/24
160.22.244.0/23
160.25.194.0/23
160.250.102.0/23
160.250.14.0/23
160.250.84.0/23
160.30.230.0/23
@@ -2203,7 +2204,9 @@
163.181.131.0/24
163.181.132.0/23
163.181.135.0/24
163.181.136.0/21
163.181.136.0/22
163.181.140.0/24
163.181.142.0/23
163.181.144.0/20
163.181.15.0/24
163.181.16.0/22
@@ -2217,13 +2220,14 @@
163.181.190.0/23
163.181.192.0/23
163.181.196.0/22
163.181.2.0/24
163.181.200.0/21
163.181.209.0/24
163.181.210.0/23
163.181.212.0/22
163.181.216.0/21
163.181.216.0/24
163.181.218.0/23
163.181.22.0/23
163.181.220.0/22
163.181.224.0/23
163.181.228.0/22
163.181.232.0/23
@@ -2260,6 +2264,7 @@
163.181.97.0/24
163.181.99.0/24
163.204.0.0/16
163.223.173.0/24
163.223.178.0/23
163.227.40.0/23
163.228.0.0/16
@@ -2276,8 +2281,9 @@
163.61.178.0/23
163.61.202.0/23
163.61.214.0/23
164.163.236.0/22
165.101.208.0/23
165.101.70.0/24
165.101.70.0/23
166.111.0.0/16
167.139.0.0/16
167.189.0.0/16
@@ -2330,6 +2336,8 @@
175.44.0.0/16
175.46.0.0/15
178.219.5.0/24
178.219.7.0/24
178.248.72.0/24
180.129.128.0/17
180.130.0.0/16
180.136.0.0/13
@@ -2439,21 +2447,39 @@
183.91.61.0/24
183.91.63.0/24
183.92.0.0/14
185.116.90.0/24
185.39.51.0/24
185.75.173.0/24
185.75.174.0/24
188.131.128.0/17
188.221.99.0/24
189.12.48.0/24
189.73.18.0/24
189.75.185.0/24
189.75.186.0/24
191.217.175.0/24
191.219.18.0/24
191.222.242.0/24
191.222.244.0/24
191.222.43.0/24
191.44.18.0/24
192.140.160.0/19
192.140.208.0/21
192.144.128.0/17
192.163.11.0/24
192.232.97.0/24
193.112.0.0/16
193.168.185.0/24
193.233.49.0/24
193.8.114.0/24
194.127.229.0/24
194.138.202.0/23
194.138.245.0/24
194.179.146.0/24
194.231.140.0/24
195.162.246.0/24
195.40.157.0/24
195.40.158.0/24
198.208.112.0/23
198.208.17.0/24
198.208.19.0/24
@@ -2464,6 +2490,13 @@
198.23.195.0/24
199.182.239.0/24
199.244.144.0/24
2.26.167.0/24
200.102.180.0/24
200.102.183.0/24
200.181.87.0/24
201.11.233.0/24
201.14.219.0/24
201.24.195.0/24
202.104.0.0/14
202.108.0.0/15
202.110.0.0/16
@@ -2490,8 +2523,8 @@
202.127.12.0/22
202.127.144.0/20
202.127.16.0/20
202.127.192.0/24
202.127.200.0/21
202.127.216.0/21
202.127.224.0/19
202.127.40.0/21
202.127.48.0/23
@@ -2518,14 +2551,19 @@
202.149.224.0/19
202.150.16.0/20
202.153.48.0/20
202.153.7.0/24
202.158.160.0/19
202.158.242.0/24
202.160.140.0/22
202.164.0.0/20
202.168.160.0/19
202.170.128.0/19
202.170.216.0/21
202.171.232.0/24
202.172.7.0/24
202.173.14.0/23
202.173.224.0/19
202.173.6.0/24
202.173.8.0/22
202.179.240.0/20
202.181.120.0/21
@@ -2541,7 +2579,6 @@
202.38.132.0/23
202.38.134.0/24
202.38.140.0/23
202.38.146.0/23
202.38.152.0/23
202.38.164.0/22
202.38.184.0/21
@@ -2552,10 +2589,7 @@
202.4.128.0/19
202.4.252.0/22
202.41.152.0/21
202.41.241.0/24
202.41.242.0/23
202.41.244.0/22
202.41.248.0/21
202.41.240.0/20
202.46.224.0/22
202.46.228.0/23
202.46.232.0/23
@@ -2602,6 +2636,7 @@
202.96.0.0/13
203.0.104.0/21
203.100.192.0/20
203.100.60.0/24
203.100.92.0/22
203.104.32.0/20
203.107.1.0/24
@@ -2633,7 +2668,7 @@
203.119.26.0/23
203.119.28.0/22
203.119.33.0/24
203.119.80.0/23
203.119.80.0/24
203.119.83.0/24
203.12.91.0/24
203.12.93.0/24
@@ -2643,15 +2678,16 @@
203.130.40.0/21
203.132.32.0/19
203.135.96.0/19
203.142.219.0/24
203.148.0.0/18
203.148.64.0/20
203.148.86.0/23
203.15.0.0/20
203.152.64.0/19
203.156.192.0/18
203.16.63.0/24
203.160.129.0/24
203.160.192.0/19
203.161.192.0/19
203.166.160.0/22
203.166.165.0/24
203.166.166.0/24
@@ -2661,8 +2697,10 @@
203.166.188.0/23
203.166.191.0/24
203.168.0.0/19
203.17.249.0/24
203.170.58.0/23
203.174.4.0/24
203.174.6.0/24
203.174.96.0/19
203.175.128.0/19
203.176.168.0/24
@@ -2670,14 +2708,15 @@
203.176.92.0/22
203.187.160.0/19
203.189.0.0/23
203.189.113.0/24
203.189.115.0/24
203.189.192.0/19
203.189.240.0/22
203.189.6.0/23
203.19.1.0/24
203.190.100.0/23
203.191.0.0/23
203.191.144.0/21
203.191.2.0/24
203.191.7.0/24
203.192.1.0/24
203.192.16.0/24
203.192.2.0/23
@@ -2696,7 +2735,9 @@
203.2.112.0/21
203.2.160.0/21
203.2.64.0/21
203.201.181.0/24
203.202.236.0/23
203.205.88.0/24
203.207.104.0/22
203.207.112.0/20
203.207.128.0/18
@@ -3019,7 +3060,7 @@
211.145.64.0/20
211.146.0.0/16
211.147.0.0/18
211.147.128.0/18
211.147.128.0/19
211.147.208.0/20
211.147.224.0/19
211.147.64.0/19
@@ -3043,8 +3084,6 @@
211.154.0.0/19
211.154.128.0/17
211.154.64.0/19
211.155.108.0/22
211.155.112.0/20
211.155.128.0/19
211.155.16.0/20
211.155.160.0/20
@@ -3056,6 +3095,7 @@
211.155.240.0/20
211.155.32.0/19
211.155.80.0/20
211.155.96.0/19
211.156.0.0/19
211.156.128.0/19
211.156.176.0/20
@@ -3108,7 +3148,6 @@
211.161.32.0/20
211.161.60.0/23
211.161.62.0/24
211.161.97.0/24
211.162.0.0/21
211.162.119.0/24
211.162.120.0/21
@@ -3156,12 +3195,7 @@
211.95.0.0/17
211.95.128.0/19
211.95.192.0/18
211.96.0.0/16
211.97.0.0/17
211.97.128.0/19
211.97.160.0/21
211.97.176.0/20
211.97.192.0/18
211.96.0.0/15
211.98.0.0/16
211.99.128.0/18
211.99.16.0/23
@@ -3171,7 +3205,10 @@
211.99.64.0/18
211.99.8.0/21
212.129.128.0/17
212.134.159.0/24
212.189.97.0/24
212.64.0.0/17
213.210.55.0/24
218.0.0.0/11
218.100.88.0/21
218.104.0.0/15
@@ -3238,7 +3275,9 @@
218.98.111.0/24
218.98.112.0/20
218.98.160.0/24
218.98.176.0/21
218.98.176.0/22
218.98.180.0/23
218.98.182.0/24
218.98.192.0/24
218.98.96.0/21
219.128.0.0/12
@@ -3507,6 +3546,7 @@
27.8.0.0/13
27.98.224.0/19
31.56.124.0/24
31.77.184.0/22
36.1.0.0/16
36.112.0.0/15
36.114.0.0/16
@@ -3541,6 +3581,7 @@
38.134.58.0/23
38.247.24.0/22
38.247.32.0/23
38.247.35.0/24
38.247.36.0/22
38.84.220.0/24
38.95.118.0/23
@@ -3614,21 +3655,45 @@
43.102.128.0/21
43.102.136.0/22
43.102.144.0/20
43.109.0.0/22
43.109.0.0/23
43.109.10.0/24
43.109.100.0/23
43.109.102.0/24
43.109.105.0/24
43.109.107.0/24
43.109.111.0/24
43.109.108.0/22
43.109.112.0/24
43.109.114.0/23
43.109.116.0/23
43.109.118.0/24
43.109.12.0/22
43.109.133.0/24
43.109.134.0/23
43.109.136.0/22
43.109.143.0/24
43.109.144.0/23
43.109.146.0/24
43.109.148.0/24
43.109.156.0/24
43.109.16.0/22
43.109.160.0/22
43.109.164.0/24
43.109.167.0/24
43.109.169.0/24
43.109.170.0/24
43.109.172.0/22
43.109.184.0/23
43.109.191.0/24
43.109.192.0/21
43.109.2.0/24
43.109.200.0/23
43.109.202.0/24
43.109.206.0/24
43.109.208.0/24
43.109.21.0/24
43.109.22.0/24
43.109.223.0/24
43.109.224.0/24
43.109.24.0/23
43.109.26.0/24
43.109.28.0/24
@@ -3643,8 +3708,7 @@
43.109.46.0/24
43.109.48.0/23
43.109.51.0/24
43.109.53.0/24
43.109.54.0/23
43.109.52.0/22
43.109.57.0/24
43.109.58.0/23
43.109.60.0/22
@@ -3671,6 +3735,8 @@
43.194.0.0/20
43.194.16.0/24
43.195.0.0/20
43.195.16.0/22
43.195.20.0/23
43.196.0.0/16
43.224.12.0/22
43.224.24.0/22
@@ -3835,6 +3901,8 @@
43.255.84.0/22
43.255.96.0/22
44.30.120.0/24
44.30.130.0/23
44.30.152.0/24
44.31.216.0/24
44.31.28.0/24
44.31.43.0/24
@@ -3882,9 +3950,11 @@
45.126.120.0/22
45.127.129.0/24
45.127.144.0/21
45.132.80.0/24
45.137.97.0/24
45.146.82.0/24
45.248.108.0/22
45.248.108.0/23
45.248.110.0/24
45.248.204.0/22
45.248.8.0/22
45.249.212.0/22
@@ -3896,7 +3966,6 @@
45.250.32.0/21
45.250.40.0/22
45.251.120.0/22
45.251.2.0/23
45.251.20.0/22
45.251.8.0/22
45.251.88.0/21
@@ -3927,10 +3996,11 @@
45.65.24.0/22
45.82.239.0/24
45.86.73.0/24
45.9.11.0/24
46.37.112.0/24
47.112.0.0/13
47.120.0.0/14
47.246.0.0/23
47.246.0.0/22
47.246.12.0/23
47.246.15.0/24
47.246.20.0/24
@@ -3938,7 +4008,6 @@
47.246.24.0/24
47.246.26.0/24
47.246.28.0/22
47.246.3.0/24
47.246.36.0/22
47.246.4.0/24
47.246.41.0/24
@@ -3948,6 +4017,7 @@
47.246.48.0/23
47.246.50.0/24
47.246.57.0/24
47.246.58.0/24
47.246.6.0/23
47.246.60.0/22
47.246.64.0/24
@@ -4129,16 +4199,10 @@
61.128.0.0/10
61.232.0.0/14
61.236.112.0/21
61.236.248.0/24
61.236.251.0/24
61.236.80.0/20
61.236.96.0/20
61.237.0.0/16
61.240.0.0/16
61.241.0.0/17
61.241.128.0/18
61.241.192.0/19
61.242.0.0/15
61.240.0.0/14
61.28.108.0/24
61.28.112.0/20
61.28.20.0/24
@@ -4153,6 +4217,7 @@
62.72.171.0/24
63.140.0.0/24
63.140.3.0/24
65.86.192.0/24
66.102.240.0/21
66.102.248.0/22
66.102.252.0/24
@@ -4169,6 +4234,9 @@
71.132.0.0/18
71.136.64.0/18
71.137.0.0/18
78.105.147.0/24
78.105.182.0/23
78.154.108.0/24
79.133.176.0/24
8.128.32.0/19
8.128.4.0/22
@@ -4182,8 +4250,7 @@
8.148.0.0/19
8.148.128.0/17
8.148.36.0/22
8.148.41.0/24
8.148.43.0/24
8.148.40.0/22
8.148.64.0/18
8.149.0.0/16
8.150.0.0/20
@@ -4205,9 +4272,16 @@
81.173.20.0/22
81.173.28.0/24
81.68.0.0/14
82.108.198.0/23
82.109.96.0/23
82.110.234.0/23
82.110.98.0/24
82.156.0.0/15
82.22.30.0/23
82.38.7.0/24
82.38.92.0/24
86.38.235.0/24
87.76.221.0/24
87.76.222.0/24
93.95.117.0/24
87.83.2.0/24
94.191.0.0/17
@@ -5,7 +5,6 @@
2001:4510:400::/40
2001:4511:1480::/41
2001:678:53c::/48
2001:7fa:5::/48
2001:c68::/32
2001:cc0::/32
2001:da8::/32
@@ -16,12 +15,12 @@
2001:dc7::/32
2001:dd8:1::/48
2001:dd9::/48
2001:df5:4740::/48
2001:df6:40::/48
2400:1160::/32
2400:3200::/32
2400:5280:f803::/48
2400:5a00::/32
2400:5a60:100::/48
2400:5a60:2::/48
2400:6000::/32
2400:6600::/32
@@ -63,7 +62,6 @@
2400:9380:9001::/48
2400:9380:9009::/48
2400:9380:9020::/47
2400:9380:9040::/48
2400:9380:9050::/47
2400:9380:9060::/48
2400:9380:9071::/48
@@ -73,7 +71,6 @@
2400:9380:90b4::/46
2400:9380:9121::/48
2400:9380:9220::/47
2400:9380:9240::/48
2400:9380:9250::/47
2400:9380:9260::/48
2400:9380:9271::/48
@@ -108,6 +105,9 @@
2401:1200::/48
2401:1320::/32
2401:1d40::/32
2401:20:1330::/46
2401:20:2104::/46
2401:20::/40
2401:2780::/32
2401:2a00:f000::/43
2401:2e00::/32
@@ -135,7 +135,6 @@
2401:4a80::/32
2401:5560:1000::/48
2401:5c20:10::/48
2401:70e0::/32
2401:71c0::/48
2401:7660::/48
2401:7700::/32
@@ -145,7 +144,7 @@
2401:8be0::/48
2401:8d00:12::/48
2401:8d00:3::/48
2401:8d00:4::/48
2401:8d00:4::/47
2401:8d00:7::/48
2401:8d00:8::/47
2401:8d00::/47
@@ -182,20 +181,17 @@
2401:ec00::/32
2401:f860:100::/40
2401:f860:85::/48
2401:f860:87::/48
2401:f860:88::/47
2401:f860:90::/46
2401:f860:90::/48
2401:f860:92::/47
2401:f860:94::/48
2401:f860:96::/47
2401:fa00:40::/43
2401:f860:97::/48
2401:fa00:40::/48
2402:1440::/32
2402:18a0::/32
2402:2000::/32
2402:2620::/48
2402:2e60::/39
2402:34e0::/32
2402:36e0::/44
2402:3c00::/32
2402:3f80:1400::/40
2402:4440:9000::/39
2402:4440:9200::/48
@@ -217,7 +213,7 @@
2402:5e40::/32
2402:5ec0::/32
2402:6e80::/32
2402:6f40:2::/48
2402:6f40:2::/47
2402:6f40::/48
2402:6fc0::/48
2402:7040::/32
@@ -228,8 +224,6 @@
2402:840:e000::/46
2402:840:f000::/38
2402:8bc0::/32
2402:8cc0:200::/40
2402:8cc0::/40
2402:92c0::/48
2402:93c0:100::/48
2402:93c0:20::/48
@@ -291,129 +285,31 @@
2403:f4c0::/48
2403:ffc0:1100::/40
2403:ffc0:1200::/39
2404:1c40:503::/48
2404:1c80::/32
2404:2280:105::/48
2404:2280:106::/47
2404:2280:109::/48
2404:2280:10a::/47
2404:2280:10b::/48
2404:2280:10d::/48
2404:2280:10f::/48
2404:2280:112::/47
2404:2280:112::/48
2404:2280:115::/48
2404:2280:116::/47
2404:2280:11a::/47
2404:2280:11c::/46
2404:2280:11c::/48
2404:2280:123::/48
2404:2280:125::/48
2404:2280:126::/47
2404:2280:128::/46
2404:2280:127::/48
2404:2280:12b::/48
2404:2280:12e::/48
2404:2280:130::/48
2404:2280:134::/48
2404:2280:136::/47
2404:2280:138::/48
2404:2280:13b::/48
2404:2280:13c::/47
2404:2280:142::/48
2404:2280:147::/48
2404:2280:14f::/48
2404:2280:150::/48
2404:2280:154::/46
2404:2280:159::/48
2404:2280:15d::/48
2404:2280:15e::/47
2404:2280:160::/48
2404:2280:170::/48
2404:2280:177::/48
2404:2280:17a::/47
2404:2280:17c::/46
2404:2280:156::/47
2404:2280:17b::/48
2404:2280:180::/47
2404:2280:183::/48
2404:2280:187::/48
2404:2280:18a::/47
2404:2280:18c::/46
2404:2280:190::/48
2404:2280:193::/48
2404:2280:18a::/48
2404:2280:18d::/48
2404:2280:18e::/47
2404:2280:196::/48
2404:2280:198::/45
2404:2280:1a4::/46
2404:2280:1a8::/47
2404:2280:1b0::/48
2404:2280:1b2::/48
2404:2280:1b4::/46
2404:2280:1b8::/47
2404:2280:1ba::/48
2404:2280:1bf::/48
2404:2280:1c1::/48
2404:2280:1c2::/47
2404:2280:1c4::/46
2404:2280:1c8::/48
2404:2280:1cb::/48
2404:2280:1cc::/48
2404:2280:1cf::/48
2404:2280:1d0::/47
2404:2280:1d3::/48
2404:2280:1d4::/48
2404:2280:1d6::/47
2404:2280:1d8::/45
2404:2280:1e0::/45
2404:2280:1e8::/46
2404:2280:1ec::/47
2404:2280:1ee::/48
2404:2280:1f0::/45
2404:2280:1f8::/46
2404:2280:201::/48
2404:2280:202::/47
2404:2280:204::/46
2404:2280:208::/46
2404:2280:20c::/47
2404:2280:20e::/48
2404:2280:210::/46
2404:2280:214::/48
2404:2280:217::/48
2404:2280:218::/46
2404:2280:21d::/48
2404:2280:21e::/48
2404:2280:221::/48
2404:2280:259::/48
2404:2280:25a::/47
2404:2280:25c::/48
2404:2280:265::/48
2404:2280:266::/47
2404:2280:268::/45
2404:2280:270::/45
2404:2280:278::/47
2404:2280:27b::/48
2404:2280:27c::/46
2404:2280:282::/47
2404:2280:284::/47
2404:2280:288::/46
2404:2280:28c::/48
2404:2280:291::/48
2404:2280:292::/48
2404:2280:296::/47
2404:2280:298::/46
2404:2280:29c::/47
2404:2280:2a0::/47
2404:2280:2a4::/46
2404:2280:2a9::/48
2404:2280:2aa::/48
2404:2280:2ad::/48
2404:2280:2ae::/47
2404:2280:2b1::/48
2404:2280:2b2::/47
2404:2280:2b5::/48
2404:2280:2b6::/47
2404:2280:2b8::/47
2404:2280:2ba::/48
2404:2280:2bc::/46
2404:2280:2c2::/47
2404:2280:2c5::/48
2404:2280:2c9::/48
2404:2280:2ca::/47
2404:2280:2cd::/48
2404:2280:2cf::/48
2404:2280:19a::/47
2404:2280:19c::/48
2404:2280:277::/48
2404:3700::/48
2404:4dc0::/32
2404:6380:1000::/48
@@ -436,8 +332,6 @@
2404:7240::/33
2404:7600::/32
2404:7940::/32
2404:8d02:28c8::/48
2404:8d02:4881::/48
2404:bc0:1::/48
2404:bc0:4000::/43
2404:bc0:4100::/43
@@ -445,7 +339,6 @@
2404:bc0:4300::/44
2404:bc0:4400::/43
2404:bc0:4500::/43
2404:bc0:4620::/44
2404:bc0:4f00::/43
2404:c2c0:240::/44
2404:c2c0:280::/44
@@ -466,10 +359,10 @@
2405:1480:1000::/48
2405:1480:2000::/48
2405:1480:3000::/47
2405:1640:6::/48
2405:3140:11::/48
2405:3140:21::/48
2405:3140:31::/48
2405:3140:3a::/48
2405:68c0:21::/48
2405:6940::/48
2405:6c0:2::/48
@@ -480,6 +373,8 @@
2405:6f00:c602::/48
2405:7040:6000::/47
2405:78c0:6e00::/43
2405:80:10::/48
2405:80:13::/48
2405:8280::/32
2405:8a40::/32
2405:a900:ffee::/48
@@ -488,6 +383,7 @@
2405:b7c0::/32
2405:d900::/32
2405:e000::/32
2405:e600:2::/48
2405:f940::/32
2406:1080::/48
2406:1e40:f012::/47
@@ -507,25 +403,21 @@
2406:840:10::/45
2406:840:110::/48
2406:840:1800::/48
2406:840:180::/48
2406:840:1::/48
2406:840:20::/48
2406:840:2380::/48
2406:840:2600::/48
2406:840:2800::/48
2406:840:2880::/47
2406:840:2::/48
2406:840:2e0::/48
2406:840:3800::/48
2406:840:380::/48
2406:840:3c1::/48
2406:840:3c2::/48
2406:840:3e0::/48
2406:840:4100::/47
2406:840:410::/47
2406:840:412::/48
2406:840:420::/48
2406:840:42::/48
2406:840:43c0::/47
2406:840:43e0::/47
2406:840:44::/48
2406:840:46::/48
@@ -538,23 +430,19 @@
2406:840:5860::/47
2406:840:5880::/47
2406:840:5c00::/47
2406:840:600::/48
2406:840:680::/48
2406:840:6c1::/48
2406:840:710::/48
2406:840:78::/47
2406:840:7::/48
2406:840:800::/46
2406:840:805::/48
2406:840:806::/48
2406:840:80::/47
2406:840:8100::/40
2406:840:840::/47
2406:840:842::/48
2406:840:860::/48
2406:840:880::/47
2406:840:882::/48
2406:840:880::/46
2406:840:90::/48
2406:840:9178::/48
2406:840:9200::/40
2406:840:9680::/44
2406:840:9700::/40
@@ -565,37 +453,41 @@
2406:840:9966::/48
2406:840:996c::/48
2406:840:9970::/44
2406:840:a10::/48
2406:840:a31::/48
2406:840:c02::/48
2406:840:c60::/48
2406:840:cb8::/48
2406:840:cc2::/48
2406:840:e072::/48
2406:840:e080::/44
2406:840:e0cf::/48
2406:840:e0e0::/46
2406:840:e0e4::/47
2406:840:e0e8::/48
2406:840:e10f::/48
2406:840:e14f::/48
2406:840:e260::/48
2406:840:e280::/44
2406:840:e301::/48
2406:840:e302::/48
2406:840:e304::/48
2406:840:e306::/48
2406:840:e330::/44
2406:840:e57e::/48
2406:840:e600::/44
2406:840:e620::/47
2406:840:e80f::/48
2406:840:eb00::/46
2406:840:eb01::/48
2406:840:eb02::/47
2406:840:eb04::/47
2406:840:eb07::/48
2406:840:eb08::/48
2406:840:eb0b::/48
2406:840:eb0f::/48
2406:840:eb80::/42
2406:840:ee40::/47
2406:840:ee44::/48
2406:840:ee4b::/48
2406:840:ee4d::/48
2406:840:eee5::/48
2406:840:f0a1::/48
2406:840:f0aa::/48
2406:840:f380::/44
@@ -603,26 +495,60 @@
2406:840:f402::/48
2406:840:f44f::/48
2406:840:f680::/44
2406:840:f860::/46
2406:840:f868::/47
2406:840:f86c::/48
2406:840:f889::/48
2406:840:fa01::/48
2406:840:fa40::/48
2406:840:fa60::/44
2406:840:fc10::/44
2406:840:fc20::/43
2406:840:fc40::/42
2406:840:fc90::/44
2406:840:fca0::/43
2406:840:fc10::/47
2406:840:fc12::/48
2406:840:fc20::/47
2406:840:fc22::/48
2406:840:fc30::/47
2406:840:fc32::/48
2406:840:fc40::/47
2406:840:fc42::/48
2406:840:fc50::/47
2406:840:fc52::/48
2406:840:fc60::/47
2406:840:fc62::/48
2406:840:fc70::/47
2406:840:fc72::/48
2406:840:fc90::/47
2406:840:fc92::/48
2406:840:fca0::/47
2406:840:fca2::/48
2406:840:fcb0::/47
2406:840:fcb2::/48
2406:840:fcd0::/48
2406:840:fd40::/43
2406:840:fcf0::/46
2406:840:fcf4::/47
2406:840:fd30::/44
2406:840:fd40::/48
2406:840:fd46::/47
2406:840:fd48::/48
2406:840:fd50::/48
2406:840:fd56::/47
2406:840:fd58::/48
2406:840:fd60::/48
2406:840:fd67::/48
2406:840:fd66::/47
2406:840:fd68::/48
2406:840:fd70::/48
2406:840:fd77::/48
2406:840:fd76::/47
2406:840:fd78::/48
2406:840:fd80::/48
2406:840:fd87::/48
2406:840:fd90::/44
2406:840:fda0::/43
2406:840:fdc0::/44
2406:840:fd86::/47
2406:840:fd88::/48
2406:840:fd90::/47
2406:840:fd92::/48
2406:840:fd9f::/48
2406:840:fda0::/48
2406:840:fda7::/48
2406:840:fdb0::/48
2406:840:fdb7::/48
2406:840:fdc0::/48
2406:840:fdc7::/48
2406:840:fe50::/47
2406:840:fe73::/48
2406:840:fe90::/46
@@ -631,6 +557,7 @@
2406:840:fe98::/46
2406:840:fe9d::/48
2406:840:fe9e::/48
2406:840:fea1::/48
2406:840:fea2::/47
2406:840:fea4::/46
2406:840:fea8::/48
@@ -646,7 +573,7 @@
2406:840:fed4::/48
2406:840:fed8::/48
2406:840:fedb::/48
2406:840:fedc::/48
2406:840:fedc::/47
2406:840:feed::/48
2406:840:fef2::/47
2406:840:fef4::/46
@@ -674,6 +601,7 @@
2407:6c40:1210::/48
2407:6c40:1500::/48
2407:6c40:1600::/40
2407:7d00:1::/48
2407:8f40:2::/48
2407:9f00::/32
2407:ad80::/32
@@ -694,29 +622,19 @@
2408:8000:8000::/33
2408:8000::/48
2408:8001::/32
2408:8020::/30
2408:8024::/31
2408:8024:8000::/33
2408:8025::/32
2408:8026::/32
2408:802a:8000::/33
2408:802c::/32
2408:803e::/32
2408:8056::/32
2408:805c::/30
2408:8060::/33
2408:80c2::/33
2408:80c5::/33
2408:80ca:8000::/34
2408:80ca::/33
2408:80da:8000::/34
2408:80da::/33
2408:80e0:4000::/34
2408:80e0:8000::/33
2408:80e0:4000::/36
2408:80e2::/33
2408:80e9:4000::/34
2408:80ea:4000::/34
2408:80ea:8000::/33
2408:80f0:4000::/34
2408:80f0:8000::/33
2408:80f0:4000::/36
2408:80f1:100::/43
2408:80f1:120::/44
2408:80f1:160::/43
@@ -731,8 +649,6 @@
2408:80f1::/42
2408:80f5:4000::/34
2408:80f9:4000::/34
2408:80fa:4000::/34
2408:80fa:8000::/33
2408:8120:1::/48
2408:8120:2::/48
2408:8120:7000::/36
@@ -809,50 +725,34 @@
2408:837a::/32
2408:8406:100::/41
2408:8406:180::/42
2408:8406:18c0::/42
2408:8406:1900::/41
2408:8406:1980::/42
2408:8406:24c0::/42
2408:8406:2500::/41
2408:8406:2580::/42
2408:8406:30c0::/42
2408:8406:3100::/41
2408:8406:3180::/42
2408:8406:3cc0::/42
2408:8406:3d00::/41
2408:8406:3d80::/42
2408:8406:48c0::/42
2408:8406:4900::/41
2408:8406:4980::/42
2408:8406:54c0::/42
2408:8406:5500::/41
2408:8406:5580::/42
2408:8406:60c0::/42
2408:8406:6100::/41
2408:8406:6180::/42
2408:8406:6cc0::/42
2408:8406:6d00::/41
2408:8406:6d80::/42
2408:8406:78c0::/42
2408:8406:7900::/41
2408:8406:7980::/42
2408:8406:84c0::/42
2408:8406:8500::/41
2408:8406:8580::/42
2408:8406:90c0::/42
2408:8406:9100::/41
2408:8406:9180::/42
2408:8406:9cc0::/42
2408:8406:9d00::/41
2408:8406:9d80::/42
2408:8406:a8c0::/42
2408:8406:a900::/41
2408:8406:a980::/42
2408:8406:b4c0::/42
2408:8406:b500::/41
2408:8406:b580::/42
2408:8406:c0::/42
2408:8406:cc0::/42
2408:8406:d00::/41
2408:8406:d80::/42
2408:8407:500::/42
@@ -974,82 +874,99 @@
2408:840d:1140::/43
2408:840d:1300::/42
2408:840d:1a00::/42
2408:840d:1a40::/43
2408:840d:1c00::/42
2408:840d:1e00::/42
2408:840d:1e40::/43
2408:840d:2000::/42
2408:840d:200::/42
2408:840d:2700::/42
2408:840d:2740::/43
2408:840d:2900::/42
2408:840d:2b00::/42
2408:840d:2b40::/43
2408:840d:2d00::/42
2408:840d:3400::/42
2408:840d:3440::/43
2408:840d:3600::/42
2408:840d:3800::/42
2408:840d:3840::/43
2408:840d:3a00::/42
2408:840d:400::/42
2408:840d:40::/43
2408:840d:440::/43
2408:840d:4e00::/42
2408:840d:4e40::/43
2408:840d:5000::/42
2408:840d:5200::/42
2408:840d:5240::/43
2408:840d:5400::/42
2408:840d:5b00::/42
2408:840d:5b40::/43
2408:840d:5d00::/42
2408:840d:5f00::/42
2408:840d:5f40::/43
2408:840d:600::/42
2408:840d:6100::/42
2408:840d:6800::/42
2408:840d:6840::/43
2408:840d:6a00::/42
2408:840d:6c00::/42
2408:840d:6c40::/43
2408:840d:6e00::/42
2408:840d:7500::/42
2408:840d:7540::/43
2408:840d:7700::/42
2408:840d:7900::/42
2408:840d:7940::/43
2408:840d:7b00::/42
2408:840d:8200::/42
2408:840d:8240::/43
2408:840d:8400::/42
2408:840d:8600::/42
2408:840d:8640::/43
2408:840d:8800::/42
2408:840d:8f00::/42
2408:840d:8f40::/43
2408:840d:9100::/42
2408:840d:9300::/42
2408:840d:9340::/43
2408:840d:9500::/42
2408:840d:9c00::/42
2408:840d:9c40::/43
2408:840d:9e00::/42
2408:840d::/42
2408:840d:a000::/42
2408:840d:a040::/43
2408:840d:a200::/42
2408:840d:a900::/42
2408:840d:a940::/43
2408:840d:ab00::/42
2408:840d:ad00::/42
2408:840d:ad40::/43
2408:840d:af00::/42
2408:840d:b600::/42
2408:840d:b640::/43
2408:840d:b800::/42
2408:840d:ba00::/42
2408:840d:ba40::/43
2408:840d:bc00::/42
2408:840d:c300::/42
2408:840d:c340::/43
2408:840d:c500::/42
2408:840d:c700::/42
2408:840d:c740::/43
2408:840d:c900::/42
2408:840d:d000::/42
2408:840d:d00::/42
2408:840d:d040::/43
2408:840d:d200::/42
2408:840d:d400::/42
2408:840d:d40::/43
2408:840d:d440::/43
2408:840d:d600::/42
2408:840d:dd00::/42
2408:840d:dd40::/43
2408:840d:de00::/42
2408:840d:f00::/42
2408:840e:dd00::/40
@@ -1192,6 +1109,7 @@
2408:8878::/31
2408:887e::/32
2408:8906:20::/44
2408:8906:40::/43
2408:8907:9000::/44
2408:890c::/31
2408:8912::/31
@@ -1228,13 +1146,9 @@
2408:8a05:8000::/36
2408:8a06:100::/47
2408:8a06::/47
2408:8a07::/40
2408:8a21:4000::/35
2408:8a22:9200::/39
2408:8a22:9400::/38
2408:8a22:9800::/40
2408:8a22:9a00::/39
2408:8a22:9c00::/38
2408:8a22:a000::/37
2408:8a22::/35
2408:8a23:4000::/34
2408:8a24:4000::/34
2408:8a26:c000::/34
@@ -1358,13 +1272,20 @@
240d:4000::/21
240e::/20
2602:f46d:6::/48
2602:f92a:a460::/48
2602:f92a:a462::/48
2602:f92a:a468::/48
2602:f92a:a46d::/48
2602:f92a:a46f::/48
2602:f92a:a474::/48
2602:f92a:a47d::/48
2602:f9ba:10c::/48
2602:f9ba:a8::/48
2602:f9f6:400::/47
2602:f9f6::/48
2602:f9f6:402::/48
2602:f9f6:450::/48
2602:faa8:702::/48
2602:faa8:708::/47
2602:faa8:70c::/47
2602:faa8:70f::/48
2602:fbda:600::/48
2602:fbda:610::/48
2602:fbda:620::/48
@@ -1382,7 +1303,6 @@
2605:9d80:9042::/48
2605:9d80:9071::/48
2605:9d80:9092::/48
2620:57:4004::/48
2804:1e48:9001::/48
2804:1e48:9002::/48
2a04:3e00:1002::/48
@@ -1416,92 +1336,118 @@
2a06:3600:fc00::/38
2a06:3605::/32
2a06:3606::/31
2a06:9f81:4600::/43
2a06:9f81:4620::/44
2a06:9f81:4640::/43
2a06:a005:260::/43
2a06:a005:280::/43
2a06:a005:2a0::/44
2a06:de00:de00::/48
2a07:54c1:2200::/46
2a07:54c1:2205::/48
2a0a:d680:8100::/47
2a0a:d680:a31::/48
2a0a:d681:e000::/40
2a0a:d681:fb00::/40
2a0a:d681:fc00::/38
2a0a:d685:1ff::/48
2a0a:d685:200::/48
2a0a:d687:f001::/48
2a0a:d687:f008::/48
2a0b:4340:90::/48
2a0b:4340:97::/48
2a0c:b641:570::/47
2a0c:b641:573::/48
2a0d:c7c7:400::/38
2a0e:aa06:400::/44
2a0e:aa06:440::/48
2a0e:aa06:450::/44
2a0e:aa06:490::/44
2a0e:aa07:e025::/48
2a0e:aa07:e200::/44
2a0e:aa06:4ea::/48
2a0e:aa06::/40
2a0e:aa07:e144::/48
2a0e:aa07:e146::/48
2a0e:aa07:e148::/48
2a0e:aa07:e280::/47
2a0e:aa07:e284::/46
2a0e:aa07:e288::/46
2a0e:aa07:e28d::/48
2a0e:aa07:e28e::/48
2a0e:aa07:f0d0::/46
2a0e:aa07:f0d4::/47
2a0e:aa07:f0d8::/48
2a0e:aa07:f0de::/47
2a0e:b107:14a0::/44
2a0e:b107:1522::/48
2a0e:b107:2440::/44
2a0e:b107:740::/44
2a0e:b107:da0::/44
2a0f:1cc5:1000::/48
2a0f:1cc5:1010::/44
2a0f:1cc5:1032::/47
2a0f:1cc5:1034::/47
2a0f:1cc5:1041::/48
2a0f:1cc5:110::/44
2a0f:1cc5:130::/44
2a0f:1cc5:140::/44
2a0f:1cc5:140::/42
2a0f:1cc5:14::/46
2a0f:1cc5:1600::/44
2a0f:1cc5:1c00::/47
2a0f:1cc5:1c02::/48
2a0f:1cc5:1c20::/48
2a0f:1cc5:1c30::/48
2a0f:1cc5:1cc0::/48
2a0f:1cc5:1d10::/47
2a0f:1cc5:1d14::/48
2a0f:1cc5:1f::/48
2a0f:1cc5:2000::/40
2a0f:1cc5:2510::/44
2a0f:1cc5:2520::/44
2a0f:1cc5:2600::/40
2a0f:1cc5:2600::/41
2a0f:1cc5:2680::/42
2a0f:1cc5:2d01::/48
2a0f:1cc5:2d03::/48
2a0f:1cc5:3203::/48
2a0f:1cc5:3222::/48
2a0f:1cc5:3700::/43
2a0f:1cc5:40::/48
2a0f:1cc5:600::/47
2a0f:1cc5:603::/48
2a0f:1cc5:645::/48
2a0f:1cc5:661::/48
2a0f:1cc5:662::/48
2a0f:1cc5:690::/48
2a0f:1cc5:6a0::/48
2a0f:1cc5:f00::/45
2a0f:1cc5:f01::/48
2a0f:1cc5:f02::/47
2a0f:1cc5:f04::/46
2a0f:1cc5:f08::/47
2a0f:1cc5:fff::/48
2a0f:1cc6:b110::/47
2a0f:1cc6:b210::/47
2a0f:1cc6:b212::/48
2a0f:2706::/32
2a0f:6284:4c00::/44
2a0f:6284:4c20::/44
2a0f:6284:4c30::/48
2a0f:6284:4c40::/43
2a0f:6284:4c60::/44
2a0f:6284:4c80::/43
2a0f:6284:4ca0::/44
2a0f:6284:4cd0::/44
2a0f:7803:fc00::/39
2a0f:85c1:bfe::/48
2a0f:9400:6110::/48
2a10:ccc0:cc1::/48
2a10:ccc0:cc2::/48
2a10:ccc0:ccc0::/48
2a10:ccc0:ccc::/48
2a12:cb46:6000::/44
2a12:cb41:1200::/44
2a12:cb41:1300::/44
2a12:cb41:13f0::/44
2a12:cb41::/44
2a12:cb46::/36
2a12:cb47:ffff::/48
2a13:1800:10::/48
2a13:1800:300::/44
2a13:1800:80::/44
2a13:1800::/48
2a13:1801:180::/43
2a13:1801:200::/44
2a13:1802::/43
2a13:8c87::/32
2a13:a5c3:f000::/40
2a13:a5c3:ff41::/48
2a13:a5c3:ff50::/44
2a13:a5c5::/48
2a13:aac4:f000::/44
2a13:b487:1200::/42
2a14:67c1:a110::/44
2a14:67c1:b500::/47
2a14:67c1:b500::/48
2a14:67c1:b511::/48
2a14:67c1:b514::/48
2a14:67c1:b530::/44
2a14:67c1:b561::/48
2a14:67c1:b563::/48
2a14:67c1:b578::/48
2a14:67c1:b586::/47
@@ -1509,19 +1455,32 @@
2a14:67c1:b590::/48
2a14:67c1:b599::/48
2a14:67c1:b5e0::/44
2a14:67c3:30::/44
2a14:67c3:6668::/45
2a14:67c2:519::/48
2a14:67c2:a10::/47
2a14:67c2:a21::/48
2a14:67c2:a22::/47
2a14:67c2:a2f::/48
2a14:67c2:a30::/48
2a14:67c2:a41::/48
2a14:67c2:a50::/48
2a14:67c2:a70::/47
2a14:67c2:a80::/47
2a14:67c2:a90::/48
2a14:67c3:1100::/47
2a14:67c3:9990::/44
2a14:67c3:c0::/48
2a14:7580:740::/44
2a14:7580:7a0::/48
2a14:7580:d00::/43
2a14:7580:d20::/46
2a14:7580:d41::/48
2a14:7580:d42::/47
2a14:7580:dff::/48
2a14:7580:fffa::/48
2a14:7581:3810::/47
2a14:7581:3814::/48
2a14:7581:3818::/47
2a14:7581:381b::/48
2a14:7581:ffb::/48
2a14:7583:f220::/43
2a14:7583:f240::/42
2a14:7583:f411::/48
2a14:7583:f4f0::/48
2a14:7583:f4f4::/48
@@ -1534,12 +1493,16 @@
2a14:7583:f743::/48
2a14:7583:f744::/48
2a14:7583:f764::/48
2a14:7586:6100::/46
2a14:7586:6104::/48
2a14:7586:6107::/48
2a14:7586:6100::/47
2a14:7586:6103::/48
2a14:7586:6104::/47
2a14:7586:6106::/48
2a14:7586:6110::/48
2a14:7586:6113::/48
2a14:7586:6300::/44
2a14:7586:6500::/48
2a14:7dc0:506::/48
2a14:ae00:50::/44
2c0f:f7a8:8011::/48
2c0f:f7a8:8050::/48
2c0f:f7a8:805f::/48
@@ -1,4 +1,3 @@
cn
apple.com
microsoft.com
dyndns.com
@@ -13,6 +13,7 @@
173ng.com
18board.com
18comic.org
18mh.net
1984bbs.com
1991way.com
1e100.net
@@ -25,6 +26,7 @@
2047.one
2049bbs.xyz
233abc.com
24hbook.com
24hrs.ca
32red.com
36rain.com
@@ -72,6 +74,7 @@
9cache.com
9gag.com
9news.com.au
9oju31.launches.appsflyersdk.com
a-normal-day.com
a248.e.akamai.net
aamacau.com
@@ -86,8 +89,10 @@ about.gitlab.com
about.me
abplive.com
acast.com
accountboy.com
accountkit.com
acevpn.com
acg.mn
acg.rip
acg18.me
acgbox.org
@@ -205,13 +210,18 @@ aoxvpn.com
apartmentratings.com
apartments.com
apat1989.org
api-gl.lbkrs.com
api-secure.recaptcha.net
api-verify.recaptcha.net
api.ai
api.futunn.com
api.lbkrs.com
api.moomoobull.com
api.palworldgame.com
api.pureapk.com
api.recaptcha.net
api.steampowered.com
api5.futunn.com
apiary.io
apigee.com
apk.support
@@ -257,6 +267,7 @@ arte.tv
artstation.com
arvanstorage.ir
arweave.org
as.mr
asacp.org
asiaharvest.org
asianage.com
@@ -321,6 +332,7 @@ bangchen.net
bangdream.space
bangkokpost.com
bangumi.moe
bangumi.tv
bangyoulater.com
bankmobilevibe.com
bannedbook.org
@@ -376,6 +388,7 @@ bettween.com
betvictor.com
bfnn.org
bfsh.hk
bgm.tv
bgme.me
bgvpn.com
biblesforamerica.org
@@ -386,6 +399,7 @@ bigjapanesesex.com
bignews.org
bigone.com
bild.de
bilinovel.com
biliworld.com
binance.com
binance.org
@@ -413,6 +427,7 @@ bl-doujinsouko.com
blacked.com
blackmagicdesign.com
blackvpn.com
bleepingcomputer.com
blinkx.com
blip.tv
blockcast.it
@@ -525,6 +540,7 @@ bookdepository.com
books.com.tw
booktopia.com.au
bookwalker.com.tw
boomplay.com
bootstrapcdn.com
borgenmagazine.com
botanwang.com
@@ -648,6 +664,7 @@ cdjp.org
cdn-images.mailchimp.com
cdn-telegram.org
cdn.arstechnica.net
cdn.futustatic.com
cdn.jwplayer.com
cdn.printfriendly.com
cdn.seatguru.com
@@ -671,6 +688,7 @@ centurys.net
certificate-transparency.org
certificate.revocationcheck.com
cfr.org
cg.play-analytics.com
cgdepot.org
change.org
changp.com
@@ -692,6 +710,7 @@ chenpokongvip.com
chenshan20042005.wordpress.com
cherrysave.com
chhongbi.org
chii.in
china-mmm.net
china-review.com.ua
china-week.com
@@ -736,6 +755,7 @@ chineseupress.com
chingcheong.com
chinman.net
chobit.cc
chonglangtv.org
chrdnet.com
christianfreedom.org
christianstudy.com
@@ -871,6 +891,7 @@ csw.org.uk
ct.org.tw
ctinets.com
ctinews.com
ctinsider.com
ctitv.com.tw
ctowc.org
cts.com.tw
@@ -913,6 +934,7 @@ darpa.mil
darrenliuwei.com
dashlane.com
data-vocabulary.org
data18.com
daum.net
david-kilgour.com
dawangidc.com
@@ -1011,7 +1033,9 @@ doublethinklab.org
douchi.space
dougscripts.com
doujincafe.com
dowjones.io
download.dappcdn.com
download.futunn.com
dpool.top
dpp.org.tw
dpr.info
@@ -1024,6 +1048,7 @@ dropboxapi.com
dropboxusercontent.com
dscn.info
dstk.dk
dt18.com
dtiblog.com
dtic.mil
dubox.com
@@ -1065,6 +1090,7 @@ ecfa.org.tw
ecimg.tw
economist.com
edgecastcdn.net
edigest.hk
edubridge.com
edx-cdn.org
eesti.ee
@@ -1143,6 +1169,7 @@ eyny.com
f-droid.org
f2pool.com
f8.com
f95zone.to
facebook.com
facebook.de
facebook.design
@@ -1324,12 +1351,42 @@ funkyimg.com
furbo.org
furinkan.com
furrybar.com
futu.cn
futu.com
futu.link
futu0.com
futu1.com
futu2.com
futu3.com
futu4.com
futu5.com
futu6.com
futu7.com
futu8.com
futu9.com
futuau.com
futubull.cn
futuchain.com
futuesop.com
futufin.com
futuhk.com
futuhk2.com
futuhkapp.com
futuhn.com
futuholdings.com
futuinc.com
futuniuniu.com
futunn.com
futuremessage.org
futustatic.com
fututrade.com
fututrustee.com
fw.cm
fxcm-chinese.com
fxnetworks.com
g-area.org
g-queen.com
g.ai
g.co
g0v.social
g6hentai.com
@@ -1361,6 +1418,7 @@ gdaily.org
geek-art.net
gekikame.com
gelbooru.com
gencraft.com
generated.photos
genius.com
geph.io
@@ -1774,6 +1832,7 @@ heyuedi.com
hicairo.com
hiccears.com
hidden-advent.org
hiddify.com
hide.me
hideipvpn.com
hideman.net
@@ -1789,6 +1848,7 @@ hindustantimes.com
hinet.net
hitbtc.com
hitomi.la
hive.blog
hiveon.net
hk-pub.com
hk.gradconnection.com
@@ -1963,6 +2023,7 @@ indiatoday.in
indiemerch.com
inews-api.tvb.com
info-graf.fr
infosec.exchange
infura.io
inherit.live
initiativesforchina.org
@@ -2022,6 +2083,7 @@ itasoftware.com
itch.io
itemfix.com
itiger.com
itigerup.com
itshidden.com
itweet.net
iuhrdf.org
@@ -2101,6 +2163,7 @@ kanshifang.com
kantie.org
kaotic.com
karayou.com
kathmandupost.com
kawaiikawaii.jp
kawase.com
kb.monitorware.com
@@ -2159,12 +2222,15 @@ landofhope.tv
lantern.io
laogai.org
laogairesearch.org
laohu8.com
laqingdan.net
larsgeorge.com
lastcombat.com
lastfm.es
lausan.hk
lbank.info
lbctrl.com
lbkrs.com
ldplayer.net
ldplayer.tw
le-vpn.com
@@ -2175,7 +2241,9 @@ left21.hk
legra.ph
leisurepro.com
lematin.ch
lemonde.fr
lenwhite.com
leonardo.ai
lesoir.be
letscorp.net
lexica.art
@@ -2187,6 +2255,7 @@ liaowangxizang.net
liberal.org.hk
libertysculpturepark.com
libertytimes.com.tw
libgen.is
library-access.sk
library.usc.cuhk.edu.hk
libredd.it
@@ -2230,6 +2299,15 @@ localdomain.ws
lockestek.com
login.target.com
logos.com.hk
longbridge.cloud
longbridge.com
longbridge.global
longbridge.hk
longbridge.sg
longbridgeapp.com
longbridgehk.com
longportapp.cn
longportapp.com
longtermly.net
longtoes.com
lookpic.com
@@ -2282,6 +2360,7 @@ martau.com
martsangkagyuofficial.org
marxist.net
marxists.org
mas.to
mash.to
mastodon.cloud
mastodon.host
@@ -2308,6 +2387,7 @@ meansys.com
media.nu.nl
mediachinese.com
mediafreakcity.com
mediamatters.org
mediawiki.org
medium.com
meee.com.tw
@@ -2387,6 +2467,7 @@ mixx.com
mizzmona.com
mji.rip
mjj.rip
mjj.today
mjlsh.usc.cuhk.edu.hk
mlc.ai
mlzs.work
@@ -2413,6 +2494,9 @@ monitorchina.org
monocloud.me
monster.com
moodyz.com
moomoo.com
moomooequity.com
moomootrustee.com
moon.fm
moonbbs.com
moonbingo.com
@@ -2424,6 +2508,7 @@ mosavi.io
motherless.com
movements.org
moviefap.com
mozilla.ai
mpettis.com
mpfinance.com
mpinews.com
@@ -2436,6 +2521,7 @@ mthruf.com
mubi.com
mullvad.net
multiply.com
music.amazon.com
musixmatch.com
muzi.com
muzi.net
@@ -2486,6 +2572,7 @@ ncn.org
ndi.org
nekoslovakia.net
neo-miracle.com
neodb.social
neowin.net
nephobox.com
netalert.me
@@ -2509,10 +2596,12 @@ news1.kr
news18.com
newsancai.com
newsblur.com
newshub.co.nz
newsmax.com
newstamago.com
newstapa.org
newstatesman.com
newstimes.com
newsweek.com
newtalk.tw
newthuhole.com
@@ -2527,6 +2616,8 @@ nflximg.com
nflximg.net
nflxso.net
nflxvideo.net
nfsc.press
nfscofficial.com
nftstorage.link
nga.mil
nhentai.net
@@ -2646,6 +2737,13 @@ ooni.io
ooni.org
open.firstory.me
openai.com
openapi-quote.longbridge.cn
openapi-quote.longbridge.com
openapi-trade.longbridge.cn
openapi-trade.longbridge.com
openapi.futunn.com
openapi.longbridge.cn
openapi.longbridge.com
openart.ai
opencritic.com
opendemocracy.net
@@ -2672,6 +2770,7 @@ oursteps.com.au
ourtv.hk
overcast.fm
overdaily.org
overdrive.com
overplay.net
oversea.istarshine.com
ovpn.com
@@ -2684,7 +2783,6 @@ pachosting.com
pacom.mil
pacopacomama.com
page.link
pages.dev
paimon.moe
pancakeswap.finance
pandafan.pub
@@ -2723,6 +2821,7 @@ pekingduck.org
pemulihan.or.id
pen.io
pendrivelinux.com
penguin.com.au
pentoy.hk
peoplenews.tw
peopo.org
@@ -2899,12 +2998,15 @@ qmp4.com
qoos.com
qq.co.za
qstatus.com
qtcard.futunn.com
qtcardfthk.futufin.com
qtrac.eu
questvisual.com
quitccp.org
quiz.directory
quora.com
quoracdn.net
quote.longbridge.global
quran.com
qz.com
r-pool.net
@@ -2930,6 +3032,7 @@ raindrop.io
raizoji.or.jp
rakuten.co.jp
ramcity.com.au
raphael.app
rapidmoviez.com
rapidvpn.com
rarbgprx.org
@@ -3008,6 +3111,8 @@ rthk.org.hk
rti.org.tw
rti.tw
rtm.tnt-ea.com
rts.ch
rule34.us
rule34.xxx
rule34video.com
rumble.com
@@ -3042,10 +3147,11 @@ savetibetstore.org
saveuighur.org
sbme.me
sbti.unun.dev
scache.vzw.com
scache1.vzw.com
scache2.vzw.com
schema.org
schwab.co.uk
schwab.com
schwab.com.cn
schwab.com.hk
scmp.com
scramble.io
scratch.mit.edu
@@ -3084,6 +3190,7 @@ sexinsex.net
sf.net
sfshibao.com
sftuk.org
sgqt0j.launches.appsflyersdk.com
shadeyouvpn.com
shadowsocks.be
shadowsocks.com.hk
@@ -3108,11 +3215,13 @@ shodanhq.com
shooshtime.com
shopee.tw
shopping.yahoo.co.jp
shortconn.im.qcloud.com
showwe.tw
shutterstock.com
shwchurch.org
shwchurch3.com
sidelinesnews.com
sider.ai
signal.org
silvergatebank.com
simbolostwitter.com
@@ -3122,6 +3231,7 @@ simplecd.org
simpleswap.io
simplex.chat
sina.com.hk
sinchew.com.my
singaporepools.com.sg
singlelogin.se
singtao.com
@@ -3130,6 +3240,7 @@ sinoants.com
sinoca.com
sinocast.com
sinoinsider.com
sinyalee.com
sipml5.org
sis001.com
site.new
@@ -3165,7 +3276,7 @@ socialblade.com
socks-proxy.net
sockslist.net
socrec.org
softether-download.com
softether.co.jp
softether.org
softfamous.com
softwarebychuck.com
@@ -3186,6 +3297,7 @@ sorting-algorithms.com
sos.org
sosad.fun
sosreader.com
sotwe.com
soubory.com
soulcaliburhentai.net
soundcloud.com
@@ -3224,7 +3336,6 @@ springwood.me
sproutcore.com
squirrelvpn.com
ss-link.com
ss7.vzw.com
ssglobal.co
ssl.webpack.de
sspanel.net
@@ -3289,11 +3400,13 @@ supchina.com
superpages.com
supervpn.net
superzooi.com
support.futunn.com
suprememastertv.com
surfeasy.com
surfeasy.com.au
surfshark.com
surrenderat20.net
suyingtv.com
swagbucks.com
swapspace.co
swissinfo.ch
@@ -3343,6 +3456,7 @@ tbsec.org
tbsn.org
tbssqh.org
teachparentstech.org
techbang.com
technews.tw
techviz.net
teck.in
@@ -3373,6 +3487,8 @@ tfhub.dev
tfiflve.com
tg-me.com
tg.dev
tgstat.com
the-sun.com
theatlantic.com
theatrum-belli.com
thebcomplex.com
@@ -3405,6 +3521,7 @@ thestandnews.com
thetatoken.org
thetibetpost.com
thetvdb.com
theweek.com
thewgo.org
thewirechina.com
theync.com
@@ -3472,6 +3589,12 @@ tibettelegraph.com
tibettimes.net
tibettruth.com
tibetwrites.org
tigerbbs.cn
tigerbbs.com
tigerbrokers.com
tigerbrokers.net
tigerbrokers.nz
tigerfintech.com
tigervpn.com
tiktok.com
tiktokcdn-eu.com
@@ -3534,6 +3657,9 @@ totalvpn.com
tou.tv
tpi.org.tw
tracfone.com
trade.futunn.com
trade.longportapp.com
tradeup.com
tradingview.com
translate.goog
transparency.org
@@ -3578,6 +3704,7 @@ tv.com
tv.jtbc.joins.com
tvbanywhere.com
tvboxnow.com
tvdy1.com
tvunetworks.com
tw-blog.com
tw.jiepang.com
@@ -3664,6 +3791,7 @@ ulop.net
ultrasurf.us
ultravpn.com
ultravpn.fr
umap.openstreetmap.fr
unblock-us.com
unblock.cn.com
unblockdmm.com
@@ -3687,6 +3815,7 @@ upghsbc.com
upmedia.mg
upornia.com
uproxy.org
upsangel.com
uptodown.com
uraban.me
urbandictionary.com
@@ -3734,6 +3863,7 @@ vaticannews.va
vatn.org
vcf-online.org
vcfbuilder.org
veed.io
vegas.williamhill.com
vegasred.com
venetianmacao.com
@@ -3785,6 +3915,7 @@ vod.wwe.com
voicettank.org
vot.org
vovo2000.com
vox.com
voxer.com
vpl.bibliocommons.com
vpn.ac
@@ -3854,6 +3985,7 @@ wav.tv
waveprotocol.org
waybig.com
waymo.com
wbrks.com
wd.bible
wealth.com.tw
wearn.com
@@ -3960,12 +4092,14 @@ work2icu.org
workatruna.com
workerempowerment.org
workers.dev
worldjournal.com
worldvpn.net
wowgirls.com
wowhead.com
wowporn.com
woyaolian.org
wp.com
wplace.live
wpoforum.com
writesonic.com
wsj.com
@@ -4029,6 +4163,7 @@ xgmyd.com
xhamster.com
xianjian.tw
xiaohexie.com
xiaohu8.com
xiaolan.me
xiaoma.org
xiaomi.eu
@@ -4053,6 +4188,7 @@ xn--noss43i.com
xn--oiq.cc
xn--p8j9a0d9c9a.xn--q9jyb4c
xn--u2u927b.com
xn--vuqv2cf7wzyig79c.com
xnpool.com
xnxx.com
xpud.org
@@ -4099,7 +4235,6 @@ yeyeclub.com
yfsp.tv
yhcw.net
yibaochina.com
yidio.com
yigeni.com
yipub.com
yizhihongxing.com
@@ -4162,11 +4297,14 @@ zh.ecdm.wikia.com
zh.pokerstrategy.com
zh.wikiquote.org
zhangtianliang.com
zhangzhehan.net
zhanlve.org
zhao.1984.city
zhengjian.org
zhengwunet.org
zhenxiang.biz
zhijianfengyi.cn
zhijianfengyi.com
zhizhu.top
zhongguo.ca
zhongguotese.net
+4 -4
View File
@@ -2,14 +2,14 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-run
PKG_VERSION:=1.0.0
PKG_RELEASE:=4
PKG_RELEASE:=5
LUCI_TITLE:=LuCI support for running makeself .run installers
LUCI_DESCRIPTION:=Upload and execute makeself-generated .run installers from LuCI.
LUCI_TITLE:=LuCI support for running installers and packages
LUCI_DESCRIPTION:=Upload and execute .run, .sh, .ipk and .apk files from LuCI.
LUCI_DEPENDS:=+luci-base +rpcd +libubox
LUCI_PKGARCH:=all
PKG_MAINTAINER:=wukongdaily <2666180@gmail.com>
PKG_MAINTAINER:=wukongdaily <wukongdaily@gmail.com>
# 定义版本号用于缓存刷新
define Package/luci-app-run/postinst
@@ -0,0 +1,54 @@
{
"zh": {
"title": "Run安装器",
"desc": "在路由器上上传并执行脚本或安装包,注意架构务必匹配。",
"drop_tip": "拖入文件,或从电脑选择。",
"choose_file": "选择 .run 或 .sh 文件",
"choose_ipk": "选择 .ipk 包",
"choose_apk": "选择 .apk 包",
"execute": "执行",
"clean_up": "清理",
"upload_title": "上传文件",
"log_title": "执行日志",
"clean_done": "临时文件与日志已清理。",
"only_supported": "仅支持 .run、.sh、.ipk 和 .apk 文件。",
"prepare_upload": "准备上传:%s (%s)",
"upload_failed": "上传失败。",
"uploading": "正在上传 %s:%d%%",
"upload_err": "上传请求失败。",
"upload_invalid": "上传返回格式无效。",
"upload_done": "上传完成:%s (%s)",
"starting": "正在启动安装器...",
"started": "安装器已启动,PID %d。",
"running": "安装器正在运行。",
"last_file": "上一次安装包:%s",
"err_no_opkg": "您的系统不支持 ipk 包安装,请选择 apk 包。",
"err_no_apk": "您的系统不支持 apk 包安装,请选择 ipk 包。"
},
"en": {
"title": "Run Installer",
"desc": "Upload and execute scripts or packages on this router, ensuring architecture compatibility.",
"drop_tip": "Drop a file here, or choose one from your computer.",
"choose_file": "Choose .run or .sh file",
"choose_ipk": "Choose .ipk package",
"choose_apk": "Choose .apk package",
"execute": "Execute",
"clean_up": "Clean up",
"upload_title": "Upload file",
"log_title": "Execution log",
"clean_done": "Temporary files and logs were removed.",
"only_supported": "Only .run, .sh, .ipk and .apk files are accepted.",
"prepare_upload": "Preparing upload: %s (%s)",
"upload_failed": "Upload failed.",
"uploading": "Uploading %s: %d%%",
"upload_err": "Upload request failed.",
"upload_invalid": "Invalid upload response.",
"upload_done": "Upload complete: %s (%s)",
"starting": "Starting installer...",
"started": "Installer started, PID %d.",
"running": "Installer is running.",
"last_file": "Last installer: %s",
"err_no_opkg": "Your system does not support ipk package installation. Please use .apk packages instead.",
"err_no_apk": "Your system does not support apk package installation. Please use .ipk packages instead."
}
}
@@ -4,10 +4,37 @@
'require ui';
'require poll';
// ====================== 纯JSON国际化 · 中英双语 ======================
const RUN_LANG = (function () {
var I18N = null;
function loadI18N() {
if (I18N)
return Promise.resolve();
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/luci-static/resources/view/run/i18n.json', true);
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
try {
I18N = JSON.parse(xhr.responseText);
resolve();
} catch (e) {
reject(e);
}
} else {
reject(new Error('Failed to load i18n.json'));
}
};
xhr.onerror = function () {
reject(new Error('Network error loading i18n.json'));
};
xhr.send();
});
}
function getLang() {
try {
const m = document.cookie.match(/luci_lang=([a-zA-Z-]+)/);
var m = document.cookie.match(/luci_lang=([a-zA-Z-]+)/);
if (m) return m[1].substring(0, 2).toLowerCase();
if (window.L && L.env && L.env.lang)
@@ -17,60 +44,17 @@ const RUN_LANG = (function () {
} catch (e) {
return 'zh';
}
})();
const I18N = {
zh: {
title: "Run安装器",
desc: "在路由器上上传并执行 .run 安装包或 .sh 脚本,注意架构务必匹配。",
drop_tip: "拖入一个 .run 或 .sh 文件,或从电脑选择。",
choose_file: "选择 .run 或 .sh 文件",
execute: "执行",
clean_up: "清理",
upload_title: "上传安装脚本 (.run / .sh)",
log_title: "执行日志",
clean_done: "临时文件与日志已清理。",
only_run: "仅支持 .run 和 .sh 文件。",
prepare_upload: "准备上传:%s (%s)",
upload_failed: "上传失败。",
uploading: "正在上传 %s:%d%%",
upload_err: "上传请求失败。",
upload_invalid: "上传返回格式无效。",
upload_done: "上传完成:%s (%s)",
starting: "正在启动安装器...",
started: "安装器已启动,PID %d。",
running: "安装器正在运行。",
last_file: "上一次安装包:%s"
},
en: {
title: "Run Installer",
desc: "Upload and execute .run packages or .sh scripts on this router, ensuring architecture compatibility.",
drop_tip: "Drop a .run or .sh file here, or choose one from your computer.",
choose_file: "Choose .run or .sh file",
execute: "Execute",
clean_up: "Clean up",
upload_title: "Upload installer script (.run / .sh)",
log_title: "Execution log",
clean_done: "Temporary files and logs were removed.",
only_run: "Only .run and .sh files are accepted.",
prepare_upload: "Preparing upload: %s (%s)",
upload_failed: "Upload failed.",
uploading: "Uploading %s: %d%%",
upload_err: "Upload request failed.",
upload_invalid: "Invalid upload response.",
upload_done: "Upload complete: %s (%s)",
starting: "Starting installer...",
started: "Installer started, PID %d.",
running: "Installer is running.",
last_file: "Last installer: %s"
}
};
}
function _(key) {
const str = I18N[RUN_LANG]?.[key] || I18N.zh[key] || key;
return str.format.apply(str, Array.prototype.slice.call(arguments, 1));
if (!I18N)
return key;
var lang = getLang();
var str = I18N[lang]?.[key] || I18N.zh[key] || key;
var args = Array.prototype.slice.call(arguments, 1);
return str.format.apply(str, args);
}
// ====================================================================
var uploadStart = rpc.declare({
object: 'luci-app-run',
@@ -106,6 +90,11 @@ var getVersion = rpc.declare({
method: 'version'
});
var getCapabilities = rpc.declare({
object: 'luci-app-run',
method: 'capabilities'
});
var readLog = rpc.declare({
object: 'luci-app-run',
method: 'read_log',
@@ -146,23 +135,53 @@ return view.extend({
logOffset: 0,
currentUploadId: null,
appVersion: 'unknown',
capabilities: { opkg: 1, apk: 1 },
load: function () {
var self = this;
return getVersion().then(function (res) {
if (res && res.version) {
self.appVersion = res.version;
// 检查版本是否变化,如果变化则强制刷新页面
var storedVersion = localStorage.getItem('luci-app-run-version');
if (storedVersion && storedVersion !== self.appVersion) {
localStorage.setItem('luci-app-run-version', self.appVersion);
window.location.reload(true);
} else {
localStorage.setItem('luci-app-run-version', self.appVersion);
return loadI18N().then(function () {
return getVersion().then(function (res) {
if (res && res.version) {
self.appVersion = res.version;
var storedVersion = localStorage.getItem('luci-app-run-version');
if (storedVersion && storedVersion !== self.appVersion) {
localStorage.setItem('luci-app-run-version', self.appVersion);
window.location.reload(true);
} else {
localStorage.setItem('luci-app-run-version', self.appVersion);
}
}
}
return getStatus().catch(function () {
return {};
return getCapabilities().then(function (cap) {
if (cap) {
self.capabilities = {
opkg: cap.opkg || 0,
apk: cap.apk || 0
};
}
return getStatus().catch(function () {
return {};
});
}).catch(function () {
return getStatus().catch(function () {
return {};
});
});
}).catch(function () {
return getCapabilities().then(function (cap) {
if (cap) {
self.capabilities = {
opkg: cap.opkg || 0,
apk: cap.apk || 0
};
}
return getStatus().catch(function () {
return {};
});
}).catch(function () {
return getStatus().catch(function () {
return {};
});
});
});
}).catch(function () {
return getStatus().catch(function () {
@@ -176,7 +195,19 @@ return view.extend({
var fileInput = E('input', {
'type': 'file',
accept: '.run,.sh,application/x-shellscript,application/octet-stream',
accept: '.run,.sh,.ipk,.apk,application/x-shellscript,application/octet-stream',
style: 'display:none'
});
var ipkInput = E('input', {
'type': 'file',
accept: '.ipk',
style: 'display:none'
});
var apkInput = E('input', {
'type': 'file',
accept: '.apk',
style: 'display:none'
});
@@ -194,17 +225,36 @@ return view.extend({
}, ['']);
var pickButton = E('button', {
class: 'btn cbi-button cbi-button-apply',
class: 'cbi-button cbi-button-apply run-btn',
style: 'background:#333!important;background-color:#333!important;background-image:none!important;color:#fff!important;border-color:#333!important;box-shadow:none!important;text-shadow:none!important;opacity:1!important',
click: function (ev) {
ev.preventDefault();
fileInput.click();
}
}, [_('choose_file')]);
var ipkButton = E('button', {
class: 'cbi-button cbi-button-add run-btn',
style: 'margin-left:10px;background:#2E7D32!important;background-color:#2E7D32!important;background-image:none!important;color:#fff!important;border-color:#2E7D32!important;box-shadow:none!important;text-shadow:none!important;opacity:1!important',
click: function (ev) {
ev.preventDefault();
ipkInput.click();
}
}, [_('choose_ipk')]);
var apkButton = E('button', {
class: 'cbi-button cbi-button-add run-btn',
style: 'margin-left:10px;background:#1565C0!important;background-color:#1565C0!important;background-image:none!important;color:#fff!important;border-color:#1565C0!important;box-shadow:none!important;text-shadow:none!important;opacity:1!important',
click: function (ev) {
ev.preventDefault();
apkInput.click();
}
}, [_('choose_apk')]);
var runButton = E('button', {
class: 'btn cbi-button cbi-button-action',
class: 'cbi-button cbi-button-action run-btn',
disabled: true,
style: 'min-width:140px;margin-left:15px;',
style: 'min-width:140px;margin-left:15px;background:#7B1FA2!important;background-color:#7B1FA2!important;background-image:none!important;color:#fff!important;border-color:#7B1FA2!important;box-shadow:none!important;text-shadow:none!important;opacity:1!important',
click: function (ev) {
ev.preventDefault();
self.startRun(runButton, state);
@@ -212,8 +262,8 @@ return view.extend({
}, [_('execute')]);
var cleanButton = E('button', {
class: 'btn cbi-button cbi-button-reset',
style: 'margin-left:35px;',
class: 'cbi-button cbi-button-reset run-btn',
style: 'margin-left:35px;background:#C62828!important;background-color:#C62828!important;background-image:none!important;color:#fff!important;border-color:#C62828!important;box-shadow:none!important;text-shadow:none!important;opacity:1!important',
click: function (ev) {
ev.preventDefault();
cleanup().then(function (res) {
@@ -251,9 +301,12 @@ return view.extend({
}, [
E('h3', [_('upload_title')]),
E('p', [state]),
E('p', [pickButton, runButton, cleanButton]),
E('p', [pickButton, ipkButton, apkButton]),
E('p', { style: 'margin-top:10px' }, [runButton, cleanButton]),
progress,
fileInput
fileInput,
ipkInput,
apkInput
]);
fileInput.addEventListener('change', function () {
@@ -261,6 +314,16 @@ return view.extend({
self.uploadFile(fileInput.files[0], progress, state, runButton);
});
ipkInput.addEventListener('change', function () {
if (ipkInput.files && ipkInput.files.length)
self.uploadFile(ipkInput.files[0], progress, state, runButton);
});
apkInput.addEventListener('change', function () {
if (apkInput.files && apkInput.files.length)
self.uploadFile(apkInput.files[0], progress, state, runButton);
});
poll.add(function () {
return self.refreshLog(log, state);
}, 1);
@@ -290,9 +353,8 @@ return view.extend({
uploadFile: function (file, progress, state, runButton) {
var self = this;
// 支持 .run 和 .sh 文件
if (!file.name.match(/\.(run|sh)$/i)) {
ui.addNotification(null, E('p', [_('only_run')]), 'danger');
if (!file.name.match(/\.(run|sh|ipk|apk)$/i)) {
ui.addNotification(null, E('p', [_('only_supported')]), 'danger');
return Promise.reject();
}
@@ -361,8 +423,15 @@ return view.extend({
state.textContent = _('starting');
return runInstaller(this.currentUploadId).then(function (res) {
if (res && res.error)
throw new Error(res.error);
if (res && res.error) {
var errorMsg = res.error;
if (res.error === 'ERR_NO_OPKG') {
errorMsg = _('err_no_opkg');
} else if (res.error === 'ERR_NO_APK') {
errorMsg = _('err_no_apk');
}
throw new Error(errorMsg);
}
self.logOffset = 0;
state.textContent = _('started', res.pid);
+69 -20
View File
@@ -115,7 +115,8 @@ method_list() {
"offset": "Integer"
},
"cleanup": {},
"version": {}
"version": {},
"capabilities": {}
}
JSON
}
@@ -132,8 +133,8 @@ upload_start() {
local clean id token dir file
clean="$(sanitize_name "$filename")"
case "$clean" in
*.run|*.sh) ;;
*) json_error "Only .run and .sh files are accepted"; return ;;
*.run|*.sh|*.ipk|*.apk) ;;
*) json_error "Only .run, .sh, .ipk and .apk files are accepted"; return ;;
esac
id="$(date +%s)_$$"
@@ -225,14 +226,6 @@ run_installer() {
name="$(cat "$dir/name" 2>/dev/null)"
file="$dir/$name"
# 确保文件可执行(.run 和 .sh 都需要)
chmod 700 "$file" 2>/dev/null || true
[ -x "$file" ] || {
json_error "Uploaded file is not executable. Please check file permissions."
return
}
read_state
if is_running "$PID"; then
json_error "Another installer is already running"
@@ -244,15 +237,56 @@ run_installer() {
log="$work/output.log"
mkdir -p "$work" || { json_error "Unable to create run directory"; return; }
(
cd "$work" || exit 1
printf 'luci-app-run: started %s\n' "$now"
printf 'luci-app-run: executing %s\n\n' "$file"
"$file"
rc=$?
printf '\nluci-app-run: exited with status %s at %s\n' "$rc" "$(date '+%Y-%m-%d %H:%M:%S')"
exit "$rc"
) > "$log" 2>&1 &
case "$name" in
*.ipk)
if ! command -v opkg >/dev/null 2>&1; then
json_error "ERR_NO_OPKG"
return
fi
(
cd "$work" || exit 1
printf 'luci-app-run: started %s\n' "$now"
printf 'luci-app-run: installing ipk package %s\n\n' "$file"
opkg install "$file"
rc=$?
printf '\nluci-app-run: opkg exited with status %s at %s\n' "$rc" "$(date '+%Y-%m-%d %H:%M:%S')"
exit "$rc"
) > "$log" 2>&1 &
;;
*.apk)
if ! command -v apk >/dev/null 2>&1; then
json_error "ERR_NO_APK"
return
fi
(
cd "$work" || exit 1
printf 'luci-app-run: started %s\n' "$now"
printf 'luci-app-run: installing apk package %s\n\n' "$file"
apk add --allow-untrusted "$file"
rc=$?
printf '\nluci-app-run: apk exited with status %s at %s\n' "$rc" "$(date '+%Y-%m-%d %H:%M:%S')"
exit "$rc"
) > "$log" 2>&1 &
;;
*)
chmod 700 "$file" 2>/dev/null || true
[ -x "$file" ] || {
json_error "Uploaded file is not executable. Please check file permissions."
return
}
(
cd "$work" || exit 1
printf 'luci-app-run: started %s\n' "$now"
printf 'luci-app-run: executing %s\n\n' "$file"
"$file"
rc=$?
printf '\nluci-app-run: exited with status %s at %s\n' "$rc" "$(date '+%Y-%m-%d %H:%M:%S')"
exit "$rc"
) > "$log" 2>&1 &
;;
esac
pid="$!"
write_state "$pid" "$file" "$log" "$now"
@@ -336,6 +370,20 @@ version() {
json_dump
}
capabilities() {
local has_opkg=0
local has_apk=0
command -v opkg >/dev/null 2>&1 && has_opkg=1
command -v apk >/dev/null 2>&1 && has_apk=1
json_init
json_add_int code 0
json_add_int opkg "$has_opkg"
json_add_int apk "$has_apk"
json_dump
}
case "$1" in
list)
method_list
@@ -350,6 +398,7 @@ case "$1" in
read_log) read_log ;;
cleanup) cleanup ;;
version) version ;;
capabilities) capabilities ;;
*) json_error "Unknown method" ;;
esac
;;
@@ -1,6 +1,6 @@
{
"luci-app-run": {
"description": "Grant access to upload and execute .run installers",
"description": "Grant access to upload and execute .run, .sh, .ipk and .apk files",
"read": {
"ubus": {
"luci-app-run": [ "status", "read_log" ]
@@ -7,54 +7,54 @@ MAX_SIZE=$((256 * 1024 * 1024))
umask 077
header() {
printf 'Status: %s\r\n' "$1"
printf 'Content-Type: application/json\r\n'
printf 'Cache-Control: no-store\r\n'
printf '\r\n'
printf 'Status: %s\r\n' "$1"
printf 'Content-Type: application/json\r\n'
printf 'Cache-Control: no-store\r\n'
printf '\r\n'
}
json_escape() {
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'
}
fail() {
header "${2:-400 Bad Request}"
printf '{"code":1,"error":"%s"}\n' "$(json_escape "$1")"
exit 0
header "${2:-400 Bad Request}"
printf '{"code":1,"error":"%s"}\n' "$(json_escape "$1")"
exit 0
}
ok() {
header '200 OK'
printf '{"code":0,"size":%s}\n' "$1"
exit 0
header '200 OK'
printf '{"code":0,"size":%s}\n' "$1"
exit 0
}
urldecode() {
local value="${1//+/ }"
printf '%b' "${value//%/\\x}"
local value="${1//+/ }"
printf '%b' "${value//%/\\x}"
}
query_value() {
local key="$1" pair name value oldifs
oldifs="$IFS"
IFS='&'
for pair in $QUERY_STRING; do
name="${pair%%=*}"
value="${pair#*=}"
if [ "$name" = "$key" ]; then
IFS="$oldifs"
urldecode "$value"
return
fi
done
IFS="$oldifs"
local key="$1" pair name value oldifs
oldifs="$IFS"
IFS='&'
for pair in $QUERY_STRING; do
name="${pair%%=*}"
value="${pair#*=}"
if [ "$name" = "$key" ]; then
IFS="$oldifs"
urldecode "$value"
return
fi
done
IFS="$oldifs"
}
valid_id() {
case "$1" in
""|*[!A-Za-z0-9_-]*) return 1 ;;
esac
return 0
case "$1" in
""|*[!A-Za-z0-9_-]*) return 1 ;;
esac
return 0
}
[ "$REQUEST_METHOD" = "POST" ] || fail "POST required" "405 Method Not Allowed"
@@ -72,13 +72,17 @@ saved_token="$(cat "$dir/token" 2>/dev/null)"
name="$(cat "$dir/name" 2>/dev/null)"
case "$name" in
*.run)
;;
*.sh)
;;
*)
fail "Invalid filename"
;;
*.run)
;;
*.sh)
;;
*.ipk)
;;
*.apk)
;;
*)
fail "Invalid filename"
;;
esac
length="${CONTENT_LENGTH:-0}"
@@ -91,8 +95,8 @@ tmp="$file.upload"
cat > "$tmp" || fail "Unable to receive upload"
actual="$(wc -c < "$tmp" 2>/dev/null)"
[ "$actual" -eq "$length" ] 2>/dev/null || {
rm -f "$tmp"
fail "Upload size mismatch"
rm -f "$tmp"
fail "Upload size mismatch"
}
mv "$tmp" "$file" || fail "Unable to save upload"
+3 -1
View File
@@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus
LUCI_PKGARCH:=all
PKG_NAME:=luci-app-ssr-plus
PKG_VERSION:=195
PKG_RELEASE:=29
PKG_RELEASE:=30
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
@@ -62,6 +62,7 @@ choice
config PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy
bool "Iptables Transparent Proxy"
depends on !PACKAGE_firewall4
select PACKAGE_dnsmasq_full_ipset
select PACKAGE_ipset
select PACKAGE_iptables
@@ -74,6 +75,7 @@ config PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy
config PACKAGE_$(PKG_NAME)_Nftables_Transparent_Proxy
bool "Nftables Transparent Proxy"
depends on PACKAGE_firewall4
select PACKAGE_dnsmasq_full_nftset
select PACKAGE_nftables
select PACKAGE_kmod-nft-socket
@@ -338,14 +338,14 @@ local function global_client_running()
return true
end
if (global_type == "clash" or global_type == "tuic" or global_type == "ss")
if (global_type == "clash" or global_type == "v2ray" or global_type == "tuic" or global_type == "ss")
and process_list:find("ssr%-retcp") then
return true
end
if (global_type == "clash" or global_type == "tuic" or global_type == "ss")
if (global_type == "clash" or global_type == "v2ray" or global_type == "tuic" or global_type == "ss")
and process_list:find("mihomo")
and (process_list:find("/clash%-") or process_list:find("/tuic%-") or process_list:find("/ss%-")) then
and (process_list:find("/clash%-") or process_list:find("/v2ray%-") or process_list:find("/tuic%-") or process_list:find("/ss%-")) then
return true
end
@@ -368,6 +368,8 @@ local function get_active_node_runtime(sid)
local backend
local protocol
local is_mihomo_running = luci.sys.call("pgrep -x ssr-retcp >/dev/null 2>&1") == 0
if stype == "ss" then
backend = translate("Mihomo")
protocol = translate("Shadowsocks")
@@ -391,7 +393,11 @@ local function get_active_node_runtime(sid)
shadowsocks = "Shadowsocks",
http = "HTTP"
}
backend = translate("Xray")
if is_mihomo_running then
backend = translate("Mihomo")
else
backend = translate("Xray")
end
if proto_map[proto] then
protocol = translate(proto_map[proto])
end
@@ -347,7 +347,7 @@ if has_mihomo then
o:value("ss", translate("ShadowSocks"))
end
if has_ss_rust then
o:value("ss-rust", translate("ShadowSocks"))
o:value("ss-rust", translate("ShadowSocks-Rust"))
end
if is_finded("naive") then
o:value("naiveproxy", translate("NaiveProxy"))
@@ -122,7 +122,8 @@ if global_type == "socks5" and Process_list:find("ipt2socks") then
end
end
if (global_type == "clash" or global_type == "tuic" or global_type == "ss") and Process_list:find("ssr%-retcp") then
if (global_type == "clash" or global_type == "v2ray" or global_type == "tuic" or global_type == "ss")
and Process_list:find("ssr%-retcp") then
redir_run = 1
reudp_run = 1
if global_socks_enabled and (global_socks_server == "same" or global_socks_server == global_server) then
@@ -130,7 +131,9 @@ if (global_type == "clash" or global_type == "tuic" or global_type == "ss") and
end
end
if (global_type == "clash" or global_type == "tuic" or global_type == "ss") and Process_list:find("mihomo") and (Process_list:find("/clash%-") or Process_list:find("/tuic%-") or Process_list:find("/ss%-")) then
if (global_type == "clash" or global_type == "v2ray" or global_type == "tuic" or global_type == "ss")
and Process_list:find("mihomo")
and (Process_list:find("/clash%-") or Process_list:find("/v2ray%-") or Process_list:find("/tuic%-") or Process_list:find("/ss%-")) then
redir_run = 1
reudp_run = 1
if global_socks_enabled and (global_socks_server == "same" or global_socks_server == global_server) then
@@ -160,7 +163,7 @@ if Process_list:find("ssrplus/bin/dns2tcp") or
pdnsd_run = 1
end
if pdnsd_mode == "7" and (global_type == "clash" or global_type == "tuic" or global_type == "ss") and Process_list:find("ssr%-retcp") then
if pdnsd_mode == "7" and (global_type == "clash" or global_type == "v2ray" or global_type == "tuic" or global_type == "ss") and Process_list:find("ssr%-retcp") then
pdnsd_run = 1
end
+69 -65
View File
@@ -96,7 +96,7 @@ msgstr ""
msgid "Accept LAN Access"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:627
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:633
msgid "Access Control"
msgstr ""
@@ -129,11 +129,11 @@ msgstr ""
msgid "Address"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:628
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:634
msgid "Advanced Settings"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:274
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:277
msgid "Advertising Data"
msgstr ""
@@ -210,7 +210,7 @@ msgstr ""
msgid "Apple Domains DNS"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:267
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:270
msgid "Apple Domains Data"
msgstr ""
@@ -274,7 +274,7 @@ msgstr ""
msgid "Backup or Restore Client and Server Configurations."
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:252
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:255
msgid "Baidu Connectivity"
msgstr ""
@@ -362,7 +362,7 @@ msgstr ""
msgid "Check Server"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:280
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:283
msgid "Check Server Port"
msgstr ""
@@ -395,7 +395,7 @@ msgstr ""
msgid "Checking..."
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:261
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:264
msgid "China IP Data"
msgstr ""
@@ -415,7 +415,7 @@ msgstr ""
msgid "Clang.CN.CIDR"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:376
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:378
msgid "Clash"
msgstr ""
@@ -501,7 +501,7 @@ msgstr ""
msgid "Component"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:630
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:636
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/component.lua:5
msgid "Component Update"
msgstr ""
@@ -631,7 +631,7 @@ msgstr ""
msgid "DNS"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:192
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:195
msgid "DNS Anti-pollution"
msgstr ""
@@ -1088,7 +1088,7 @@ msgstr ""
msgid "Fragmented packet length (byte)"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:256
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:259
msgid "GFW List Data"
msgstr ""
@@ -1100,7 +1100,7 @@ msgstr ""
msgid "Game Mode Host List"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:183
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:186
msgid "Game Mode UDP Relay"
msgstr ""
@@ -1130,12 +1130,12 @@ msgstr ""
msgid "GitHub Direct"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:175
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:178
msgid "Global Client"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:194
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:210
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:213
msgid "Global HTTP/HTTPS Proxy Server"
msgstr ""
@@ -1144,7 +1144,7 @@ msgid "Global Mode"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:152
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:201
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:204
msgid "Global SOCKS5 Proxy Server"
msgstr ""
@@ -1156,7 +1156,7 @@ msgstr ""
msgid "Go to relevant configuration page"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:248
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:251
msgid "Google Connectivity"
msgstr ""
@@ -1259,7 +1259,7 @@ msgstr ""
msgid "Httpupgrade Path"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:407
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:413
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:422
msgid "Hysteria2"
msgstr ""
@@ -1389,7 +1389,7 @@ msgstr ""
msgid "KCP Write Buffer Size"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:231
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:234
msgid "KcpTun"
msgstr ""
@@ -1409,7 +1409,7 @@ msgstr ""
msgid "KcpTun Port"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:228
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:231
msgid "KcpTun Version"
msgstr ""
@@ -1503,7 +1503,7 @@ msgstr ""
msgid "Local Port"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:219
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:222
msgid "Local Servers"
msgstr ""
@@ -1511,7 +1511,7 @@ msgstr ""
msgid "Local addresses"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:643
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:649
msgid "Log"
msgstr ""
@@ -1566,9 +1566,10 @@ msgstr ""
msgid "Maximum packet size the socks5 server can receive from external"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:372
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:375
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:378
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:374
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:377
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:380
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:397
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:9
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:395
msgid "Mihomo"
@@ -1651,7 +1652,7 @@ msgstr ""
msgid "NOT RUNNING"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:401
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:407
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:353
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:13
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:396
@@ -1674,9 +1675,9 @@ msgstr ""
msgid "Next"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:249
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:253
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:282
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:252
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:256
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:285
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:116
msgid "No Check"
msgstr ""
@@ -1743,13 +1744,13 @@ msgstr ""
msgid "None"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:180
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:188
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:197
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:206
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:215
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:224
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:236
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:183
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:191
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:200
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:209
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:218
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:227
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:239
msgid "Not Running"
msgstr ""
@@ -1997,16 +1998,16 @@ msgstr ""
msgid "RST Backup"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:429
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:435
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/status.htm:7
msgid "RUNNING"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:422
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:428
msgid "RUNNING in %s (%s) Mode"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:426
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:432
msgid "RUNNING in %s Mode"
msgstr ""
@@ -2037,10 +2038,10 @@ msgstr ""
msgid "Reapply"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:259
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:264
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:270
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:277
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:262
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:267
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:273
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:280
msgid "Records"
msgstr ""
@@ -2141,11 +2142,11 @@ msgstr ""
msgid "Resolve Dns Mode"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:241
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:244
msgid "Restart Service"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:240
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:243
msgid "Restart ShadowSocksR Plus+"
msgstr ""
@@ -2158,13 +2159,13 @@ msgstr ""
msgid "Restore to default configuration"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:178
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:186
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:195
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:204
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:213
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:222
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:234
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:181
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:189
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:198
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:207
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:216
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:225
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:237
msgid "Running"
msgstr ""
@@ -2172,7 +2173,7 @@ msgstr ""
msgid "Running Mode"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:403
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:409
msgid "SOCKS5"
msgstr ""
@@ -2180,11 +2181,11 @@ msgstr ""
msgid "SS URL base64 sstr format not recognized."
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:625
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:631
msgid "SSR Client"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:629
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:635
msgid "SSR Server"
msgstr ""
@@ -2261,7 +2262,7 @@ msgstr ""
msgid "Server failsafe auto swith and custom update settings"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:626
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:632
msgid "Servers Nodes"
msgstr ""
@@ -2283,17 +2284,20 @@ msgid "Shadow-TLS ChainPoxy type"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:347
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:350
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:417
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:61
msgid "ShadowSocks"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:350
msgid "ShadowSocks-Rust"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:791
msgid "ShadowSocks-rust Version"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:622
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:628
msgid "ShadowSocksR Plus+"
msgstr ""
@@ -2301,11 +2305,11 @@ msgstr ""
msgid "ShadowSocksR Plus+ Settings"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:405
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:411
msgid "ShadowTLS"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:373
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:375
msgid "Shadowsocks"
msgstr ""
@@ -2314,11 +2318,11 @@ msgstr ""
msgid "Shadowsocks Password"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:383
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:385
msgid "Shadowsocks-rust"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:381
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:383
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:344
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:64
msgid "ShadowsocksR"
@@ -2393,7 +2397,7 @@ msgstr ""
msgid "Starting subscription update..."
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:631
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:637
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:114
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:116
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:118
@@ -2544,7 +2548,7 @@ msgstr ""
msgid "TLS is used to verify the leaf certificate name."
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:379
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:381
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:359
msgid "TUIC"
msgstr ""
@@ -2658,7 +2662,7 @@ msgstr ""
msgid "Transport Protocol"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:399
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:405
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:416
msgid "Trojan"
msgstr ""
@@ -3001,7 +3005,7 @@ msgstr ""
msgid "XTLS"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:394
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:399
msgid "Xray"
msgstr ""
+73 -69
View File
@@ -100,7 +100,7 @@ msgstr "一个合法的文件路径。在运行之前,此文件必须不存在
msgid "Accept LAN Access"
msgstr "接受局域网访问"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:627
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:633
msgid "Access Control"
msgstr "访问控制"
@@ -133,11 +133,11 @@ msgstr "附加版本"
msgid "Address"
msgstr "地址"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:628
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:634
msgid "Advanced Settings"
msgstr "高级设置"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:274
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:277
msgid "Advertising Data"
msgstr "【广告屏蔽】数据库"
@@ -214,7 +214,7 @@ msgstr "访问国外域名 DNS 服务器"
msgid "Apple Domains DNS"
msgstr "Apple 域名 DNS"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:267
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:270
msgid "Apple Domains Data"
msgstr "【Apple 域名】数据库"
@@ -278,7 +278,7 @@ msgstr "备份还原"
msgid "Backup or Restore Client and Server Configurations."
msgstr "备份或还原客户端及服务端配置。"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:252
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:255
msgid "Baidu Connectivity"
msgstr "【百度】连通性检查"
@@ -366,7 +366,7 @@ msgstr "检查连通性"
msgid "Check Server"
msgstr "检查服务器"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:280
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:283
msgid "Check Server Port"
msgstr "【服务器端口】检查"
@@ -399,7 +399,7 @@ msgstr "正在检查..."
msgid "Checking..."
msgstr "检查中..."
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:261
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:264
msgid "China IP Data"
msgstr "【中国大陆 IP 段】数据库"
@@ -419,7 +419,7 @@ msgstr ""
msgid "Clang.CN.CIDR"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:376
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:378
msgid "Clash"
msgstr "Clash"
@@ -505,7 +505,7 @@ msgstr "正在收集数据中..."
msgid "Component"
msgstr "组件"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:630
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:636
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/component.lua:5
msgid "Component Update"
msgstr "组件升级"
@@ -636,7 +636,7 @@ msgstr "下载备份"
msgid "DNS"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:192
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:195
msgid "DNS Anti-pollution"
msgstr "DNS 防污染服务"
@@ -1097,7 +1097,7 @@ msgstr "分片间隔(ms)"
msgid "Fragmented packet length (byte)"
msgstr "分片包长 (byte)"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:256
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:259
msgid "GFW List Data"
msgstr "【GFW 列表】数据库"
@@ -1109,7 +1109,7 @@ msgstr "GFW 列表模式"
msgid "Game Mode Host List"
msgstr "增强游戏模式客户端 LAN IP"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:183
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:186
msgid "Game Mode UDP Relay"
msgstr "游戏模式 UDP 中继"
@@ -1139,12 +1139,12 @@ msgstr "GeoSite 数据库"
msgid "GitHub Direct"
msgstr "GitHub 直连"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:175
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:178
msgid "Global Client"
msgstr "TCP 透明代理"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:194
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:210
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:213
msgid "Global HTTP/HTTPS Proxy Server"
msgstr "HTTP/HTTPS 代理服务端(全局)"
@@ -1153,7 +1153,7 @@ msgid "Global Mode"
msgstr "全局模式"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:152
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:201
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:204
msgid "Global SOCKS5 Proxy Server"
msgstr "SOCKS5 代理服务端(全局)"
@@ -1165,7 +1165,7 @@ msgstr "全局设置"
msgid "Go to relevant configuration page"
msgstr "前往相关配置页面"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:248
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:251
msgid "Google Connectivity"
msgstr "【谷歌】连通性检查"
@@ -1268,7 +1268,7 @@ msgstr "HTTPUpgrade 主机名"
msgid "Httpupgrade Path"
msgstr "HTTPUpgrade 路径"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:407
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:413
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:422
msgid "Hysteria2"
msgstr ""
@@ -1399,7 +1399,7 @@ msgstr "KCP 上行链路容量"
msgid "KCP Write Buffer Size"
msgstr "KCP 写缓冲区大小"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:231
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:234
msgid "KcpTun"
msgstr ""
@@ -1419,7 +1419,7 @@ msgstr "KcpTun 密码"
msgid "KcpTun Port"
msgstr "KcpTun 端口"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:228
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:231
msgid "KcpTun Version"
msgstr "KcpTun 版本号"
@@ -1513,7 +1513,7 @@ msgstr "加载中..."
msgid "Local Port"
msgstr "本地端口"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:219
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:222
msgid "Local Servers"
msgstr "本机服务端"
@@ -1521,7 +1521,7 @@ msgstr "本机服务端"
msgid "Local addresses"
msgstr "本地地址"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:643
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:649
msgid "Log"
msgstr "日志"
@@ -1578,9 +1578,10 @@ msgstr "最大分片数"
msgid "Maximum packet size the socks5 server can receive from external"
msgstr "socks5 服务器可以从外部接收的最大数据包大小(单位:字节)"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:372
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:375
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:378
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:374
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:377
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:380
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:397
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:9
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:395
msgid "Mihomo"
@@ -1665,7 +1666,7 @@ msgstr ""
msgid "NOT RUNNING"
msgstr "未运行"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:401
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:407
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:353
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:13
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:396
@@ -1688,9 +1689,9 @@ msgstr ""
msgid "Next"
msgstr "下一页"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:249
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:253
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:282
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:252
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:256
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:285
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:116
msgid "No Check"
msgstr "未检查"
@@ -1758,13 +1759,13 @@ msgstr "噪声"
msgid "None"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:180
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:188
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:197
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:206
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:215
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:224
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:236
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:183
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:191
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:200
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:209
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:218
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:227
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:239
msgid "Not Running"
msgstr "未运行"
@@ -2012,16 +2013,16 @@ msgstr ""
msgid "RST Backup"
msgstr "恢复备份"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:429
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:435
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/status.htm:7
msgid "RUNNING"
msgstr "运行中"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:422
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:428
msgid "RUNNING in %s (%s) Mode"
msgstr "运行中,当前为 %s(%s)模式"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:426
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:432
msgid "RUNNING in %s Mode"
msgstr "运行中,当前为 %s 模式"
@@ -2052,10 +2053,10 @@ msgstr ""
msgid "Reapply"
msgstr "重新应用"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:259
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:264
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:270
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:277
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:262
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:267
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:273
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:280
msgid "Records"
msgstr "条记录"
@@ -2115,7 +2116,7 @@ msgstr "Reno"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:156
msgid "Required for VMess/VLESS. Generate with: uuidgen"
msgstr ""
msgstr "VMess/VLESS 协议必需,可使用:uuidgen 命令生成。"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1281
msgid "Reserved bytes(optional)"
@@ -2156,11 +2157,11 @@ msgstr "正在重置默认值..."
msgid "Resolve Dns Mode"
msgstr "DNS 解析方式"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:241
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:244
msgid "Restart Service"
msgstr "重启服务"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:240
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:243
msgid "Restart ShadowSocksR Plus+"
msgstr "重启 ShadowSocksR Plus+"
@@ -2173,13 +2174,13 @@ msgstr "恢复备份文件"
msgid "Restore to default configuration"
msgstr "恢复默认配置"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:178
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:186
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:195
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:204
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:213
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:222
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:234
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:181
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:189
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:198
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:207
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:216
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:225
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/status.lua:237
msgid "Running"
msgstr "运行中"
@@ -2187,7 +2188,7 @@ msgstr "运行中"
msgid "Running Mode"
msgstr "运行模式"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:403
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:409
msgid "SOCKS5"
msgstr "SOCKS5"
@@ -2195,11 +2196,11 @@ msgstr "SOCKS5"
msgid "SS URL base64 sstr format not recognized."
msgstr "无法识别 SS URL 的 Base64 格式。"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:625
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:631
msgid "SSR Client"
msgstr "客户端"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:629
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:635
msgid "SSR Server"
msgstr "服务端"
@@ -2277,7 +2278,7 @@ msgstr "服务端类型"
msgid "Server failsafe auto swith and custom update settings"
msgstr "服务器节点故障自动切换/广告屏蔽/中国大陆 IP 段数据库更新设置"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:626
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:632
msgid "Servers Nodes"
msgstr "服务器节点"
@@ -2299,17 +2300,20 @@ msgid "Shadow-TLS ChainPoxy type"
msgstr "代理链类型"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:347
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:350
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:417
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:61
msgid "ShadowSocks"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:350
msgid "ShadowSocks-Rust"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:791
msgid "ShadowSocks-rust Version"
msgstr "ShadowSocks-rust 版本"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:622
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:628
msgid "ShadowSocksR Plus+"
msgstr ""
@@ -2317,11 +2321,11 @@ msgstr ""
msgid "ShadowSocksR Plus+ Settings"
msgstr "ShadowSocksR Plus+ 设置"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:405
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:411
msgid "ShadowTLS"
msgstr "ShadowTLS"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:373
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:375
msgid "Shadowsocks"
msgstr "Shadowsocks"
@@ -2330,11 +2334,11 @@ msgstr "Shadowsocks"
msgid "Shadowsocks Password"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:383
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:385
msgid "Shadowsocks-rust"
msgstr "Shadowsocks-rust"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:381
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:383
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:344
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:64
msgid "ShadowsocksR"
@@ -2409,7 +2413,7 @@ msgstr "开始探测"
msgid "Starting subscription update..."
msgstr "正在开始更新订阅..."
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:631
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:637
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:114
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:116
#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/component.htm:118
@@ -2515,7 +2519,7 @@ msgstr "正在切换..."
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:284
msgid "TCP Camouflage Type"
msgstr ""
msgstr "TCP 伪装类型"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:771
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1728
@@ -2562,7 +2566,7 @@ msgstr "TLS 主机名"
msgid "TLS is used to verify the leaf certificate name."
msgstr "TLS 用于验证 leaf 证书的 name。"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:379
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:381
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:359
msgid "TUIC"
msgstr "TUIC"
@@ -2684,7 +2688,7 @@ msgstr "传输协议"
msgid "Transport Protocol"
msgstr "传输协议"
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:399
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:405
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:416
msgid "Trojan"
msgstr "Trojan"
@@ -3029,7 +3033,7 @@ msgstr "XHTTP 路径"
msgid "XTLS"
msgstr ""
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:394
#: applications/luci-app-ssr-plus/luasrc/controller/shadowsocksr.lua:399
msgid "Xray"
msgstr "Xray"
@@ -3127,11 +3131,11 @@ msgstr "禁用"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:230
msgid "e.g.: /etc/ssl/fullchain.pem"
msgstr ""
msgstr "例如:/etc/ssl/fullchain.pem"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:235
msgid "e.g.: /etc/ssl/private.key"
msgstr ""
msgstr "例如:/etc/ssl/private.key"
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1314
#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1423
+2 -2
View File
@@ -10,8 +10,8 @@ LUCI_TITLE:=Luci app for ssw
LUCI_DEPENDS:= +luci-app-modeminfo
PKG_LICENSE:=GPLv3
PKG_VERSION:=0.0.2
PKG_RELEASE:=2
PKG_VERSION:=0.0.3
PKG_RELEASE:=3
include $(TOPDIR)/feeds/luci/luci.mk
@@ -10,63 +10,172 @@
return view.extend({
render: function(modems) {
var m, s, o
var m, s, o;
m = new form.Map('ssw', _('SSW - SIM Card switch'))
m = new form.Map('ssw', _('SSW - SIM Card switch'));
s = m.section(form.TypedSection, 'modem');
o = s.option(form.ListValue, 'value', _('State'));
s = m.section(form.TypedSection, 'modem', _('Modem'));
s.anonymous = true;
s.addremove = false;
o = s.option(form.ListValue, 'value', _('State'),
_('Enable the modem upon router startup.'));
o.value(1, _('Enable'));
o.value(0, _('Disable'));
s = m.section(form.TypedSection, 'sim');
o = s.option(form.ListValue, 'value', _('Default SIM Slot'));
s = m.section(form.TypedSection, 'sim', _('SIM Slot'));
s.anonymous = true;
s.addremove = false;
o = s.option(form.ListValue, 'value', _('Default SIM Slot'),
_('Select the primary slot. The other becomes the backup.'));
o.value(1, _('SLOT 1'));
o.value(0, _('SLOT 2'));
s = m.section(form.TypedSection, 'failover');
o = s.option(form.Flag, 'enable', _('Enable'));
// ── Failover section ──────────────────────────────────────────────
s = m.section(form.TypedSection, 'failover',
_('Signal-based failover'),
_('Monitors signal quality (RSRP/RSCP) and link state via mwan3.<br />' +
'Switches to the reserve SIM when the average signal drops below the threshold<br />' +
'or the interface loses connectivity. Operates independently of the scheduled switch.'));
s.anonymous = true;
s.addremove = false;
o = s.option(form.Value, 'apn1', _('APN Default SIM'));
o = s.option(form.Flag, 'enable', _('Enable failover'),
_('Enable automatic SIM switching based on signal quality and link state.'));
o = s.option(form.Value, 'apn1', _('APN — default SIM'),
_('Access Point Name used when operating on the default SIM slot.<br />' +
'Applied automatically when reverting from the reserve SIM.'));
o.placeholder = 'internet';
o.depends({enable: '1'});
o = s.option(form.Value, 'apn2', _('APN Reserved SIM'));
o = s.option(form.Value, 'apn2', _('APN — reserve SIM'),
_('Access Point Name used when switching to the reserve SIM slot.'));
o.placeholder = 'internet';
o.depends({enable: '1'});
o = s.option(form.Flag, 'revert', _('Revert'),
_('Revert to default sim slot. Each failed attempt doubles revert time.'));
o = s.option(form.Flag, 'revert', _('Auto-revert to default SIM'),
_('Automatically switch back to the default SIM after a period of time.<br />' +
'The revert timeout starts at <code>2 × (Interval × Probes)</code> seconds<br />' +
'and doubles with each consecutive failed attempt.'));
o.depends({enable: '1'});
o = s.option(form.ListValue, 'rsrp', _('RSRP/RSCP value'),
_('Switch sim lower by value. For 4G/5G is RSRP, for 3G RSCP.'));
o = s.option(form.ListValue, 'rsrp', _('Signal threshold (RSRP/RSCP)'),
_('Switch to the reserve SIM when the averaged signal falls below this value.<br />' +
'For LTE and 5G use <strong>RSRP</strong>; for 3G (WCDMA) use <strong>RSCP</strong>.<br />' +
'Typical thresholds: &minus;95 dBm (good), &minus;105 dBm (acceptable), &minus;115 dBm (poor).'));
for (var rsrp = -120; rsrp <= -50; rsrp++) {
o.value(rsrp, rsrp +' '+ _('dBm'));
};
o.value(rsrp, rsrp + ' ' + _('dBm'));
}
o.depends({enable: '1'});
o = s.option(form.Value, 'interval',
_('Interval check. sec'));
o.value('5', 5 +' '+ _('sec'));
for (var sec = 10; sec <= 60; sec+=10) {
o.value(sec,sec +' '+ _('sec'));
};
o.value('2m', 2 +' '+ _('minute'));
o.value('5m', 5 +' '+ _('minute'));
for (var d = 10; d <= 60; d+=10) {
o.value(d+'m',d +' '+ _('minute'));
};
o.value('2h', 2 +' '+ _('hour'));
o.value('4h', 4 +' '+ _('hour'));
o = s.option(form.Value, 'interval', _('Check interval'),
_('How often the daemon polls signal quality and link state.<br />' +
'Shorter intervals react faster but increase CPU and modem load.<br />' +
'The total evaluation window is <code>Interval × Probes</code>.'));
o.value('5', 5 + ' ' + _('sec'));
for (var sec = 10; sec <= 60; sec += 10) {
o.value(sec, sec + ' ' + _('sec'));
}
o.value('2m', 2 + ' ' + _('minute'));
o.value('5m', 5 + ' ' + _('minute'));
for (var d = 10; d <= 60; d += 10) {
o.value(d + 'm', d + ' ' + _('minute'));
}
o.value('2h', 2 + ' ' + _('hour'));
o.value('4h', 4 + ' ' + _('hour'));
o.depends({enable: '1'});
o = s.option(form.Value, 'times_rsrp', _('Probes'),
_('RSRP check average values.<br />NOTE: all time check is <code>Interval*Probes</code><br />Example: <code>Interval=60</code> sec, <code>Probes=5</code> times, all time check <code>300</code> sec.'));
for (var p = 5; p <=10; p++) {
o.value(p,p);
_('Number of signal samples to average before making a switch decision.<br />' +
'More probes smooth out momentary fluctuations but slow reaction time.<br />' +
'Total evaluation window: <code>Interval × Probes</code>.<br />' +
'Example: <code>Interval = 60 sec</code>, <code>Probes = 5</code> → decision after <code>300 sec</code>.'));
for (var p = 5; p <= 10; p++) {
o.value(p, p);
}
o.depends({enable: '1'});
// ── Schedule section ──────────────────────────────────────────────
s = m.section(form.TypedSection, 'schedule',
_('Scheduled SIM switch'),
_('Unconditional switch to the reserve SIM at a fixed time.<br />' +
'Choose how often the switch repeats: every day, every N days, or on a specific weekday.<br />' +
'Optionally reverts to the default SIM after a set number of minutes.'));
s.anonymous = true;
s.addremove = false;
// Enable flag
o = s.option(form.Flag, 'enable', _('Enable scheduled switch'));
o.default = '0';
// Switch time
o = s.option(form.Value, 'time_on', _('Switch time (HH:MM)'),
_('Time of day to switch to the reserve SIM (24 h format, e.g. <code>02:00</code>).'));
o.placeholder = '02:00';
o.rmempty = false;
o.validate = function(section_id, value) {
if (!/^\d{1,2}:\d{2}$/.test(value))
return _('Use HH:MM format');
var parts = value.split(':');
if (parseInt(parts[0]) > 23 || parseInt(parts[1]) > 59)
return _('Invalid time value');
return true;
};
o.depends({enable: '1'});
// Period selector
o = s.option(form.ListValue, 'period', _('Repeat period'));
o.value('daily', _('Every day'));
o.value('interval', _('Every N days'));
o.value('weekly', _('Weekly (specific weekday)'));
o.default = 'daily';
o.depends({enable: '1'});
// Every-N-days field (shown only when period=interval)
o = s.option(form.Value, 'period_days', _('Repeat every (days)'),
_('Switch to the reserve SIM every this many days. Minimum 2.'));
o.placeholder = '3';
o.datatype = 'uinteger';
o.default = '3';
o.validate = function(section_id, value) {
var n = parseInt(value);
if (isNaN(n) || n < 2)
return _('Must be 2 or more');
return true;
};
o.depends({enable: '1', period: 'interval'});
// Weekday selector (shown only when period=weekly)
o = s.option(form.ListValue, 'weekday', _('Weekday'),
_('Day of the week on which the switch fires.'));
o.value('0', _('Sunday'));
o.value('1', _('Monday'));
o.value('2', _('Tuesday'));
o.value('3', _('Wednesday'));
o.value('4', _('Thursday'));
o.value('5', _('Friday'));
o.value('6', _('Saturday'));
o.default = '1';
o.depends({enable: '1', period: 'weekly'});
// Revert duration
o = s.option(form.Value, 'duration', _('Revert after (minutes)'),
_('Minutes until automatic revert to the default SIM.<br />' +
'Set to <code>0</code> to stay on the reserve SIM indefinitely.'));
o.placeholder = '60';
o.datatype = 'uinteger';
o.default = '0';
o.depends({enable: '1'});
// APN override
o = s.option(form.Value, 'apn', _('APN for scheduled switch'),
_('APN to use during the scheduled window.<br />' +
'Leave empty to use <em>APN Reserved SIM</em> from Failover settings.'));
o.placeholder = 'internet';
o.depends({enable: '1'});
return m.render();
}
});
+233 -21
View File
@@ -1,38 +1,250 @@
# Russian translation for luci-app-ssw
# Copyright (C) 2025-2026 Konstantine Shevlakov <shevlakov@132lan.ru>
# This file is distributed under the same license as the luci-app-ssw package.
#
msgid ""
msgstr ""
"Project-Id-Version: luci-app-ssw\n"
"PO-Revision-Date: 2025-01-01 00:00+0300\n"
"Last-Translator: Konstantine Shevlakov <shevlakov@132lan.ru>\n"
"Language-Team: Russian\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
# ── Map title ─────────────────────────────────────────────────────────────────
msgid "SSW - SIM Card switch"
msgstr "SSW - управление SIM картами"
msgstr "SSW — переключение SIM-карт"
# ── Modem / SIM sections ──────────────────────────────────────────────────────
msgid "Modem"
msgstr "Модем"
msgid "State"
msgstr "Состояние"
msgid "Enable the modem upon router startup."
msgstr "Включить модем при загрузке роутера."
msgid "Enable"
msgstr "Включить"
msgstr "Включён"
msgid "Disable"
msgstr "Отключить"
msgstr "Выключен"
msgid "SIM Slot"
msgstr "Слот SIM"
msgid "Default SIM Slot"
msgstr "SIM cлот по-умолчанию"
msgstr "Основной слот SIM"
msgid "APN Default SIM"
msgstr "APN SIM по-умолчанию"
msgid "Select the primary slot. The other becomes the backup."
msgstr "Выбрать, какой слот будет основным. Другой слот становится резервным."
msgid "APN Reserved SIM"
msgstr "APN резервной SIM"
msgid "SLOT 1"
msgstr "Слот 1"
msgid "Revert"
msgstr "Вернуть"
msgid "SLOT 2"
msgstr "Слот 2"
msgid "Revert to default sim slot. Each failed attempt doubles revert time."
msgstr "Вернуть на SIM слот по-умолчанию. Каждая неудачная попытка увеличивает время возврата."
# ── Failover section ──────────────────────────────────────────────────────────
msgid "RSRP/RSCP value"
msgstr "Значение RSRP/RSCP"
msgid "Signal-based failover"
msgstr "Переключение по качеству сигнала"
msgid "Switch sim lower by value. For 4G/5G is RSRP, for 3G RSCP."
msgstr "Переключить sim ниже значения. Для 4G/5G значение RSRP, для 3G - RSCP."
msgid ""
"Monitors signal quality (RSRP/RSCP) and link state via mwan3.<br />"
"Switches to the reserve SIM when the average signal drops below the threshold<br />"
"or the interface loses connectivity. Operates independently of the scheduled switch."
msgstr ""
"Отслеживает качество сигнала (RSRP/RSCP) и состояние канала через mwan3.<br />"
"Переключается на резервную SIM, когда средний сигнал падает ниже порогового<br />"
"значения или интерфейс теряет связь. Работает независимо от переключения по расписанию."
msgid "Interval check. sec"
msgstr "Интервал проверки. сек"
msgid "Enable failover"
msgstr "Включить переключение по сигналу"
msgid "Enable automatic SIM switching based on signal quality and link state."
msgstr ""
"Включить автоматическое переключение SIM-карты на основе качества сигнала и "
"состояния канала."
msgid "APN — default SIM"
msgstr "APN — основная SIM"
msgid ""
"Access Point Name used when operating on the default SIM slot.<br />"
"Applied automatically when reverting from the reserve SIM."
msgstr ""
"Точка доступа (APN), используемая при работе с основным слотом SIM.<br />"
"Применяется автоматически при возврате с резервной SIM."
msgid "APN — reserve SIM"
msgstr "APN — резервная SIM"
msgid "Access Point Name used when switching to the reserve SIM slot."
msgstr "Точка доступа (APN), используемая при переключении на резервный слот SIM."
msgid "Auto-revert to default SIM"
msgstr "Автоматический возврат на основную SIM"
msgid ""
"Automatically switch back to the default SIM after a period of time.<br />"
"The revert timeout starts at <code>2 × (Interval × Probes)</code> seconds<br />"
"and doubles with each consecutive failed attempt."
msgstr ""
"Автоматически вернуться на основную SIM через некоторое время.<br />"
"Начальный таймаут возврата равен <code>2 × (Интервал × Попытки)</code> секунд<br />"
"и удваивается при каждой последующей неудачной попытке переключения."
msgid "Signal threshold (RSRP/RSCP)"
msgstr "Порог сигнала (RSRP/RSCP)"
msgid ""
"Switch to the reserve SIM when the averaged signal falls below this value.<br />"
"For LTE and 5G use <strong>RSRP</strong>; for 3G (WCDMA) use <strong>RSCP</strong>.<br />"
"Typical thresholds: &minus;95 dBm (good), &minus;105 dBm (acceptable), &minus;115 dBm (poor)."
msgstr ""
"Переключиться на резервную SIM, если усреднённый сигнал опустится ниже этого значения.<br />"
"Для LTE и 5G используется <strong>RSRP</strong>, для 3G (WCDMA) — <strong>RSCP</strong>.<br />"
"Типичные пороги: −95 дБм (хорошо), −105 дБм (допустимо), −115 дБм (плохо)."
msgid "Check interval"
msgstr "Интервал проверки"
msgid ""
"How often the daemon polls signal quality and link state.<br />"
"Shorter intervals react faster but increase CPU and modem load.<br />"
"The total evaluation window is <code>Interval × Probes</code>."
msgstr ""
"Как часто демон опрашивает качество сигнала и состояние канала.<br />"
"Меньший интервал ускоряет реакцию, но увеличивает нагрузку на CPU и модем.<br />"
"Суммарное окно оценки: <code>Интервал × Попыток</code>."
msgid "Probes"
msgstr "Попытки"
msgstr "Попыток"
msgid "RSRP check average values.<br />NOTE: all time check is <code>Interval*Probes</code><br />Example: <code>Interval=60</code> sec, <code>Probes=5</code> times, all time check <code>300</code> sec."
msgstr "Проверяется усреднённое значение RSRP.<br />ВНИМАНИЕ: общее время итоговой проверки равно <code>Интервал*Попытки</code><br />Например: <code>интервал=60</code> sec, <code>попыток=5</code>, время до переключения <code>300</code> сек."
msgid ""
"Number of signal samples to average before making a switch decision.<br />"
"More probes smooth out momentary fluctuations but slow reaction time.<br />"
"Total evaluation window: <code>Interval × Probes</code>.<br />"
"Example: <code>Interval = 60 sec</code>, <code>Probes = 5</code> → decision after <code>300 sec</code>."
msgstr ""
"Количество замеров сигнала для усреднения перед принятием решения о переключении.<br />"
"Больше попыток сглаживает кратковременные флуктуации, но замедляет реакцию.<br />"
"Суммарное окно оценки: <code>Интервал × Попыток</code>.<br />"
"Например: <code>Интервал = 60 сек</code>, <code>Попыток = 5</code> → решение через <code>300 сек</code>."
msgid "dBm"
msgstr "дБм"
msgid "sec"
msgstr "сек"
msgid "minute"
msgstr "мин"
msgid "hour"
msgstr "ч"
# ── Schedule section ──────────────────────────────────────────────────────────
msgid "Scheduled SIM switch"
msgstr "Переключение по расписанию"
msgid ""
"Unconditional switch to the reserve SIM at a fixed time.<br />"
"Choose how often the switch repeats: every day, every N days, or on a specific weekday.<br />"
"Optionally reverts to the default SIM after a set number of minutes."
msgstr ""
"Безусловное переключение на резервную SIM в заданное время.<br />"
"Выберите, как часто повторяется переключение: каждый день, раз в N дней или в определённый день недели.<br />"
"Опционально возвращается на основную SIM через заданное количество минут."
msgid "Enable scheduled switch"
msgstr "Включить переключение по расписанию"
msgid "Switch time (HH:MM)"
msgstr "Время переключения (ЧЧ:ММ)"
msgid "Time of day to switch to the reserve SIM (24 h format, e.g. <code>02:00</code>)."
msgstr "Время суток для переключения на резервную SIM (24-часовой формат, например <code>02:00</code>)."
msgid "Use HH:MM format"
msgstr "Используйте формат ЧЧ:ММ"
msgid "Invalid time value"
msgstr "Недопустимое значение времени"
msgid "Repeat period"
msgstr "Период повторения"
msgid "Every day"
msgstr "Каждый день"
msgid "Every N days"
msgstr "Раз в N дней"
msgid "Weekly (specific weekday)"
msgstr "Еженедельно (определённый день)"
msgid "Repeat every (days)"
msgstr "Повторять каждые (дней)"
msgid "Switch to the reserve SIM every this many days. Minimum 2."
msgstr "Переключаться на резервную SIM раз в указанное количество дней. Минимум 2."
msgid "Must be 2 or more"
msgstr "Должно быть 2 или более"
msgid "Weekday"
msgstr "День недели"
msgid "Day of the week on which the switch fires."
msgstr "День недели, в который выполняется переключение."
msgid "Sunday"
msgstr "Воскресенье"
msgid "Monday"
msgstr "Понедельник"
msgid "Tuesday"
msgstr "Вторник"
msgid "Wednesday"
msgstr "Среда"
msgid "Thursday"
msgstr "Четверг"
msgid "Friday"
msgstr "Пятница"
msgid "Saturday"
msgstr "Суббота"
msgid "Revert after (minutes)"
msgstr "Вернуться через (минут)"
msgid ""
"Minutes until automatic revert to the default SIM.<br />"
"Set to <code>0</code> to stay on the reserve SIM indefinitely."
msgstr ""
"Через сколько минут автоматически вернуться на основную SIM.<br />"
"Установите <code>0</code>, чтобы оставаться на резервной SIM до следующего переключения."
msgid "APN for scheduled switch"
msgstr "APN для переключения по расписанию"
msgid ""
"APN to use during the scheduled window.<br />"
"Leave empty to use <em>APN Reserved SIM</em> from Failover settings."
msgstr ""
"APN, используемый в окне переключения по расписанию.<br />"
"Оставьте пустым, чтобы использовать значение «APN — резервная SIM» "
"из настроек переключения по сигналу."
@@ -103,8 +103,10 @@ local methods = {
elseif fs.access("/sys/module/nft_fullcone/refcnt") and
(readfile("/sys/module/nft_fullcone/refcnt") or "0") ~= "0" then
fctype = "nft_FULLCONENAT"
elseif sys.call("iptables -t nat -L zone_wan_postrouting | grep -q fullcone") == 0 then
fctype = "Boardcom Fullcone"
elseif sys.call("nft list ruleset 2>/dev/null | grep -q 'masquerade fullcone'") == 0 then
fctype = "Boardcom Fullcone NAT1"
elseif sys.call("iptables -t nat -L zone_wan_postrouting 2>/dev/null | grep -q fullcone") == 0 then
fctype = "Boardcom Fullcone NAT1"
end
print(json.stringify({ type = fctype }))
end
+2 -3
View File
@@ -228,9 +228,8 @@ const methods = {
getFeatures: {
call: function() {
const kernel_version = popen('echo -n `uname -r`').read('all');
const has_fw3 = access('/sbin/fw3') == true;
const has_fw4 = access('/sbin/fw4') == true;
const has_fw4 = access('/sbin/fw4') == true || access('/usr/sbin/fw4') == true;
const has_ipt_flowoffload = access('/sys/module/xt_FLOWOFFLOAD/refcnt') == true;
const has_nft_flowoffload = access('/sys/module/nft_flow_offload/refcnt') == true;
const ubus = connect();
@@ -249,7 +248,7 @@ const methods = {
mii_tool: access('/usr/sbin/mii-tool'),
offloading: (has_fw3 && has_ipt_flowoffload) || (has_fw4 && has_nft_flowoffload),
offloading_hw: has_hw_offloading,
fullcone: access(`/lib/modules/${kernel_version}/xt_FULLCONENAT.ko`) == true || access(`/lib/modules/${kernel_version}/nft_fullcone.ko`) == true,
fullcone: access('/sys/module/xt_FULLCONENAT/refcnt') == true || access('/sys/module/nft_fullcone/refcnt') == true,
br2684ctl: access('/usr/sbin/br2684ctl') == true,
swconfig: access('/sbin/swconfig') == true,
zram: access('/sys/class/zram-control') == true,
+2 -2
View File
@@ -8,10 +8,10 @@ include $(TOPDIR)/rules.mk
LUCI_TITLE:=Support for OpenVPN Client
LUCI_DESCRIPTION:=This package provides support for OpenVPN client configuration in LuCI.
LUCI_DEPENDS:=+openvpn +kmod-tun +firewall
LUCI_DEPENDS:=+openvpn +kmod-tun +PACKAGE_firewall4:firewall4 +!PACKAGE_firewall4:firewall
LUCI_PKGARCH:=all
PKG_VERSION:=1
PKG_RELEASE:=1
PKG_RELEASE:=2
include $(TOPDIR)/feeds/luci/luci.mk
+2 -2
View File
@@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=natflow
PKG_VERSION:=20260531
PKG_RELEASE:=18
PKG_RELEASE:=19
PKG_SOURCE:=$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://github.com/ptpt52/natflow.git
PKG_SOURCE_PROTO:=git
PKG_SOURCE_VERSION:=1843a42b122ff3fa94a49cf8e1994de83a340537
PKG_SOURCE_VERSION:=d048ff525d0ab9780a2af16a56a1359b7b14beb4
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_MAINTAINER:=Chen Minqiang <ptpt52@gmail.com>
PKG_LICENSE:=GPL-2.0
Executable → Regular
+1 -1
View File
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=pcie_mhi
PKG_VERSION:=1.3.8
PKG_RELEASE:=22
PKG_RELEASE:=23
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk
+2 -2
View File
@@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ssw
PKG_VERSION:=0.0.2
PKG_RELEASE:=2
PKG_VERSION:=0.0.3
PKG_RELEASE:=3
PKG_MAINTAINER:=Konstantine Shevlakov <shevlakov@132lan.ru>
include $(INCLUDE_DIR)/package.mk
+8
View File
@@ -9,3 +9,11 @@ config sim 'sim'
config failover 'failover'
config schedule 'schedule'
option enable '0'
option period 'daily'
option period_days '3'
option weekday '1'
option time_on '02:00'
option duration '120'
option apn ''
+234 -119
View File
@@ -1,11 +1,8 @@
#!/bin/sh
# SIM slot switcher for HuastLink HC-G60 or ZBT-WE2806-A
# or similar CPE OpenWrt-routers
# by Konstantine Shevlakov at <shevlakov@132lan.ru> 2025
# Audited & fixed 2026
NODE="SW SIM"
# or similiar cpe OpenWrt-routers
# by Konstantine Shevlakov at <shevlakov@132lan.ru> 2025-2026
# config file stored in /etc/config/ssw
# define gpios in /etc/config/system
@@ -34,67 +31,72 @@ NODE="SW SIM"
# option gpio 'sim'
# option value '1'
# Schedule switch section example /etc/config/ssw:
#
# config schedule 'schedule'
# option enable '1'
# option time_on 'HH:MM' # time to switch to reserve SIM (24h format)
# option duration '60' # minutes until revert to default SIM (0 = no revert)
# option apn 'internet' # APN for reserve SIM during schedule switch
# option period 'daily' # daily | interval | weekly
# option period_days '3' # for period=interval: every N days
# option weekday '1' # for period=weekly: 0=Sun 1=Mon … 6=Sat
. /lib/functions.sh
# Callback failover section
_load_failover(){
config_get enable "$1" enable ""
config_get interval "$1" interval 60
config_get revert "$1" revert ""
config_get rsrp "$1" rsrp ""
config_get times_rsrp "$1" times_rsrp 5
config_get apn1 "$1" apn1 ""
config_get apn2 "$1" apn2 ""
}
NODE="SW SIM"
# Callback sections modem / sim (gpio type)
_load_gpio(){
local _gpio _value
config_get _gpio "$1" gpio ""
config_get _value "$1" value ""
eval "${1}_gpio=\"$_gpio\""
eval "${1}_value=\"$_value\""
}
# Get Variables — update for every cycle
# Get Variables
get_vars(){
reset_cb
config_load ssw
config_foreach _load_failover failover
config_foreach _load_gpio modem
config_foreach _load_gpio sim
for v in enable interval revert rsrp times_rsrp apn1 apn2; do
eval $v=$(uci -q get ssw.failover.${v} 2>/dev/null)
done
for d in modem sim; do
for s in gpio value; do
eval "${d}_${s}=$(uci -q get ssw.${d}.${s} 2>/dev/null)"
done
done
[ -n "$interval" ] || interval=60
[ -n "$times_rsrp" ] || times_rsrp=5
# Schedule variables
sched_enable=$(uci -q get ssw.schedule.enable 2>/dev/null)
sched_time_on=$(uci -q get ssw.schedule.time_on 2>/dev/null)
sched_duration=$(uci -q get ssw.schedule.duration 2>/dev/null)
sched_apn=$(uci -q get ssw.schedule.apn 2>/dev/null)
sched_period=$(uci -q get ssw.schedule.period 2>/dev/null)
sched_period_days=$(uci -q get ssw.schedule.period_days 2>/dev/null)
sched_weekday=$(uci -q get ssw.schedule.weekday 2>/dev/null)
[ -n "$sched_duration" ] || sched_duration=0
[ -n "$sched_period" ] || sched_period=daily
[ -n "$sched_period_days" ] || sched_period_days=1
[ -n "$sched_weekday" ] || sched_weekday=1
}
# SIM Switch
sw_sim(){
case "$cur_sim" in
case $cur_sim in
0) next_sim=1 ;;
1) next_sim=0 ;;
*)
logger -t "$NODE" "ERROR: cur_sim has unexpected value '$cur_sim'. Aborting sw_sim."
return 1
;;
esac
echo "0" > /sys/class/gpio/"$modem_gpio"/value
echo "$next_sim" > /sys/class/gpio/"$sim_gpio"/value
echo "0" > /sys/class/gpio/$modem_gpio/value
echo "$next_sim" > /sys/class/gpio/$sim_gpio/value
if [ "$modem_value" = "1" ]; then
sleep 2
echo "1" > /sys/class/gpio/"$modem_gpio"/value
echo "1" > /sys/class/gpio/$modem_gpio/value
if [ -x /etc/init.d/smstools3 ]; then
/etc/init.d/smstools3 restart
fi
fi
set > /tmp/apn.ssw
}
# Revert rule switch
# Revert rule switch (failover)
sw_rule(){
if [ -f /tmp/ssw.vars ]; then
. /tmp/ssw.vars
fi
# Revert SIM card to default slot
if [ "$cur_sim" -ne "$sim_value" ]; then
if [ "$(date +%s)" -gt "$SWDATE" ]; then
logger -t "$NODE" "Revert to default SIM slot with $apn"
@@ -103,61 +105,176 @@ sw_rule(){
fi
}
# Schedule: revert to default SIM after duration
sched_revert(){
[ -f /tmp/ssw_sched.vars ] && . /tmp/ssw_sched.vars
if [ -n "$SCHED_REVERT_AT" ] && [ "$(date +%s)" -ge "$SCHED_REVERT_AT" ]; then
cur_sim=$(cat /sys/class/gpio/$sim_gpio/value)
if [ "$cur_sim" -ne "$sim_value" ]; then
logger -t "$NODE" "Schedule: reverting to default SIM slot"
iface=$(uci show network | awk -F [.] '/devices/{gsub("'\''","");print $2}' | tail -1)
uci set network.$iface.apn="${apn1:-internet}"
uci commit network
reload_config network
sw_sim && sleep 20 && reload_iface &
fi
rm -f /tmp/ssw_sched.vars
logger -t "$NODE" "Schedule: revert done, schedule state cleared"
fi
}
# Check if today matches the configured schedule period.
# Returns 0 (true) if the switch should fire today, 1 otherwise.
sched_day_match(){
today=$(date +%Y%m%d)
now_dow=$(date +%w) # 0=Sun .. 6=Sat
case "$sched_period" in
daily)
return 0
;;
weekly)
[ "$now_dow" = "$sched_weekday" ] && return 0
return 1
;;
interval)
# Read the date of the last successful switch from persistent state.
# We keep it in /tmp/ssw_sched_last.date so it survives across
# the daemon's iterations but resets on reboot (intentional —
# after reboot the interval counter restarts from today).
last_date=""
[ -f /tmp/ssw_sched_last.date ] && last_date=$(cat /tmp/ssw_sched_last.date)
if [ -z "$last_date" ]; then
# First run ever (or after reboot): trigger today.
return 0
fi
# Calculate elapsed days between last_date and today (YYYYMMDD arithmetic).
# Use date to convert both to unix timestamps then divide.
ts_last=$(date -d "$last_date" +%s 2>/dev/null)
[ -z "$ts_last" ] && ts_last=$(date -jf "%Y%m%d" "$last_date" +%s 2>/dev/null)
ts_now=$(date +%s)
elapsed_days=$(( (ts_now - ts_last) / 86400 ))
[ "$elapsed_days" -ge "$sched_period_days" ] && return 0
return 1
;;
*)
# Unknown period — treat as daily
return 0
;;
esac
}
# Schedule: switch to reserve SIM at configured time
check_schedule(){
[ "$sched_enable" = "1" ] || return
[ -n "$sched_time_on" ] || return
# Handle pending revert first — takes priority over new switch logic.
if [ -f /tmp/ssw_sched.vars ]; then
sched_revert
return
fi
# Parse HH:MM (strip leading zeros to avoid octal)
sched_h=$(echo "$sched_time_on" | cut -d: -f1 | sed 's/^0*//')
sched_m=$(echo "$sched_time_on" | cut -d: -f2 | sed 's/^0*//')
[ -z "$sched_h" ] && sched_h=0
[ -z "$sched_m" ] && sched_m=0
now_h=$(date +%H | sed 's/^0*//')
now_m=$(date +%M | sed 's/^0*//')
[ -z "$now_h" ] && now_h=0
[ -z "$now_m" ] && now_m=0
# Check time window: [sched_time .. sched_time + ceil(interval/60)) minutes
now_total=$(( now_h * 60 + now_m ))
sched_total=$(( sched_h * 60 + sched_m ))
interval_min=$(( interval / 60 + 1 ))
diff=$(( now_total - sched_total ))
# Not in the time window yet
if [ "$diff" -lt 0 ] || [ "$diff" -ge "$interval_min" ]; then
return
fi
# Check if the period condition is met (daily / weekly / every N days)
sched_day_match || return
# Check if we already fired today (prevents re-triggering within the same window)
today=$(date +%Y%m%d)
if [ -f /tmp/ssw_sched_fired.date ]; then
fired=$(cat /tmp/ssw_sched_fired.date)
[ "$fired" = "$today" ] && return
fi
# All conditions met — switch to reserve SIM
cur_sim=$(cat /sys/class/gpio/$sim_gpio/value)
if [ "$cur_sim" -ne "$sim_value" ]; then
# Already on reserve SIM (e.g. failover active), skip but record the day.
logger -t "$NODE" "Schedule: already on reserve SIM, skipping switch"
echo "$today" > /tmp/ssw_sched_fired.date
return
fi
logger -t "$NODE" "Schedule: switching to reserve SIM (period=$sched_period, time=$sched_time_on)"
iface=$(uci show network | awk -F [.] '/devices/{gsub("'\''","");print $2}' | tail -1)
apn_use="${sched_apn:-${apn2:-internet}}"
uci set network.$iface.apn="$apn_use"
uci commit network
reload_config network
sw_sim && sleep 20 && reload_iface &
# Record fire date (suppress re-trigger within same day/window)
echo "$today" > /tmp/ssw_sched_fired.date
# For interval mode: record as the last successful switch date
if [ "$sched_period" = "interval" ]; then
echo "$today" > /tmp/ssw_sched_last.date
fi
# Arm the revert timer if duration > 0
if [ "$sched_duration" -gt 0 ]; then
revert_at=$(( $(date +%s) + sched_duration * 60 ))
echo "SCHED_REVERT_AT=$revert_at" > /tmp/ssw_sched.vars
logger -t "$NODE" "Schedule: will revert to default SIM in ${sched_duration} min"
else
logger -t "$NODE" "Schedule: no auto-revert configured"
fi
}
# Check interface state via mwan3
monitor_mwan3(){
iface=$(uci show network | awk -F'[.]' '/devices/{print $2}' | tail -1)
# Check link status
if [ -r "/tmp/run/mwan3/iface_state/$iface" ]; then
link_status=$(grep -c online "/tmp/run/mwan3/iface_state/$iface" || echo 0)
iface=$(uci show network | awk -F [.] '/devices/{print $2}')
if [ -r /tmp/run/mwan3/iface_state/$iface ]; then
link_status=$(cat /tmp/run/mwan3/iface_state/$iface | grep online | wc -l)
else
# Disable track link via mwan3
link_status=1
fi
}
check_signal(){
local gen="$1" signal_json="$2"
local metric value
case "$gen" in
lte|5g) metric="rsrp" ;;
3g) metric="rscp" ;;
*)
logger -t "$NODE" "check_signal: unknown generation '$gen'"
return 1
;;
esac
value=$(echo "$signal_json" \
| jsonfilter -e "@[\"modem\"][*][\"${gen}\"][\"${metric}\"]" 2>/dev/null \
| awk '{printf "%.0f\n", $1}')
[ -n "$value" ] && echo "$value"
}
# RSRP/RSCP average value by modemmanager. Enable signal monitor!
# RSRP average value by modemmanager. Enable signal monitor!
monitor_rsrp(){
local device SIGNAL CRSRP
device="$(uci show network | awk -F'[=]' '/devices/{gsub("'\''",""); print $2}' | tail -1)"
SIGNAL="$(mmcli -J -m "$device" --signal-get 2>/dev/null)"
for gen in lte 5g 3g; do
CRSRP=$(check_signal "$gen" "$SIGNAL")
[ -n "$CRSRP" ] && break
done
if [ -n "$CRSRP" ] && [ "$CRSRP" -ne 0 ]; then
echo "$CRSRP" >> /tmp/ssw_rsrp.var
device="$(uci show network | awk -F [=] '/devices/{gsub("'\''","");print $2}')"
SIGNAL="$(mmcli -J -m $device --signal-get)"
CRSRP=$(echo "$SIGNAL" | jsonfilter -e '@["modem"][*]["lte"]["rsrp"]' | awk '{printf "%.0f\n", $1}')
if ! [ $CRSRP ]; then
CRSRP=$(echo "$SIGNAL" | jsonfilter -e '@["modem"][*]["5g"]["rsrp"]' | awk '{printf "%.0f\n", $1}')
fi
if [ "$cnt" -eq "$times_rsrp" ]; then
if [ -s /tmp/ssw_rsrp.var ]; then
RSRP=$(awk '{sum+=$1} END { printf "%.0f\n", sum/NR }' /tmp/ssw_rsrp.var)
fi
: > /tmp/ssw_rsrp.var
if [ -n "$RSRP" ] && [ "$RSRP" -lt "$rsrp" ]; then
if [ $CRSRP -ne 0 ]; then
echo $CRSRP >> /tmp/ssw_rsrp.var
fi
if [ $cnt -eq $times_rsrp ]; then
RSRP=$(awk '{sum+=$1} END { printf "%.0f\n", sum/NR }' /tmp/ssw_rsrp.var)
cat /dev/null > /tmp/ssw_rsrp.var
if [ $RSRP -lt $rsrp ]; then
mon_rsrp=0
else
mon_rsrp=1
@@ -169,74 +286,72 @@ monitor_rsrp(){
reload_iface(){
[ "$iface" ] && {
for i in $iface; do
ifup "$i"
ifup $i
done
}
}
cnt=0
# Stuff
cnt=1
while true; do
get_vars
sleep "$interval"
sleep $interval
# Schedule check runs every iteration, independently of failover
check_schedule
if [ "$enable" = "1" ]; then
cur_sim=$(cat /sys/class/gpio/"$sim_gpio"/value)
cnt=$(( cnt + 1 ))
cur_sim=$(cat /sys/class/gpio/$sim_gpio/value)
monitor_rsrp
monitor_mwan3
if [ "$cnt" -eq "$times_rsrp" ]; then
if [ "$link_status" = "0" ] || [ "$mon_rsrp" = "0" ]; then
if [ "$link_status" = "0" -o "$mon_rsrp" = "0" ]; then
if [ "$sim_value" -eq "$cur_sim" ]; then
apn=$apn2
else
apn=$apn1
fi
iface=$(uci show network | awk -F'[.]' '/devices/{gsub("'\''",""); print $2}' | tail -1)
if [ -n "$RSRP" ]; then
iface=$(uci show network | awk -F [.] '/devices/{gsub("'\''","");print $2}' | tail -1)
if [ $RSRP ]; then
if [ "$mon_rsrp" = "0" ]; then
logger -t "$NODE" "Modem interface: $iface average RSRP=${RSRP} dBm. Min. value ${rsrp} dBm."
logger -t "$NODE" "Modem interface: $iface is average RSRP= ${RSRP} dBm. Min. value ${rsrp} dBm."
fi
if [ "$link_status" = "0" ]; then
logger -t "$NODE" "Modem interface: $iface lost connectivity."
logger -t "$NODE" "Modem interface: $iface is loss connectivity"
fi
else
logger -t "$NODE" "WARNING: RSRP value not available. Check 'Refresh signal' option of modem interface!"
logger -t "$NODE" "WARNING: RSRP value not exist. Please check \"Resfesh signal\" option of modem interface!"
fi
if [ "${#apn}" -gt 0 ]; then
uci set network."$iface".apn="$apn"
if [ "${#apn}" -gt "0" ]; then
uci set network.$iface.apn="$apn"
logger -t "$NODE" "Switch SIM-card slot with APN: $apn"
else
logger -t "$NODE" "WARNING: APN not defined. Switching SIM-card slot with default APN."
uci set network."$iface".apn="internet"
logger -t "$NODE" "WARNING: APN not defined. Switch SIM-card slot with default APN."
uci set network.$iface.apn="internet"
fi
uci commit network
reload_config
reload_config network
if [ "$revert" = "1" ]; then
if [ "$cur_sim" -eq "$sim_value" ]; then
FBT=${FBT:=$(( (interval + times_rsrp) * 2 ))}
FBT=$(( FBT * 2 ))
SWDATE=$(( $(date +%s) + FBT ))
printf 'FBT=%s\nSWDATE=%s\n' "$FBT" "$SWDATE" > /tmp/ssw.vars
logger -t "$NODE" "Back to default SIM-slot after $(date -d @"${SWDATE}")"
FBT=${FBT:=$((($interval+$times_rsrp)*2))}
FBT=$(($FBT*2))
SWDATE=$((`date +%s`+$FBT))
echo "FBT=$FBT" > /tmp/ssw.vars
echo SWDATE=$SWDATE >> /tmp/ssw.vars
logger -t "$NODE" "Back to default SIM-slot after $(date -d @${SWDATE})"
fi
fi
sw_sim && sleep 20 && reload_iface &
elif [ "$revert" = "1" ]; then
fi
if [ "$revert" = "1" ]; then
sw_rule && sleep 20 && reload_iface &
fi
cnt=1
cnt=0
else
cnt=$(($cnt+1))
fi
fi
done
done
+2 -2
View File
@@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=Xray-core
PKG_VERSION:=26.6.1
PKG_RELEASE:=16
PKG_VERSION:=26.6.22
PKG_RELEASE:=17
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/XTLS/Xray-core/tar.gz/v$(PKG_VERSION)?