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