Compare commits

...

354 Commits

Author SHA1 Message Date
hotyue
ccddaf4386 chore(release): bump version to v4.0.3 2026-04-25 06:26:23 +00:00
hotyue
0f0ba46989 feat(core): 优化部署与升级链路,新节点入列及 OTA 捷报底部追加 [一键唤醒控制台] 按钮 2026-04-25 06:18:22 +00:00
hotyue
f83db38a6b feat(agent): 优化实时日志推送链路,底部追加 [一键唤醒控制台] 交互式内联按钮 2026-04-25 06:09:37 +00:00
hotyue
ba5582ab4c fix(master): 修复态势感知面板升级 JSON 交互后的换行符乱码 (%0A 转换为 \n) 2026-04-25 06:02:25 +00:00
hotyue
fb4e1d9b31 feat(master): 优化态势感知面板,底部追加 [一键唤醒控制台] 交互式内联按钮 2026-04-25 05:57:10 +00:00
hotyue
2dea6e382b feat(agent): 优化每日简报推送链路,底部追加 [一键唤醒控制台] 交互式内联按钮 2026-04-25 05:48:53 +00:00
hotyue
fa8eada97b docs: 更新 README.md,增加对底层 IP 质量检测组件 xykt/IPQuality 的开源鸣谢 2026-04-25 01:34:32 +00:00
hotyue
c102f66234 docs: 更新 README.md,增加对底层 IP 质量检测组件 xykt/IPQuality 的开源鸣谢 2026-04-25 01:33:22 +00:00
hotyue
68a50fdb4a docs: 更新 README.md,增加对底层 IP 质量检测组件 xykt/IPQuality 的开源鸣谢 2026-04-25 01:32:20 +00:00
hotyue
aac83acb8f docs: 更新 README.md,增加对底层 IP 质量检测组件 xykt/IPQuality 的开源鸣谢 2026-04-25 01:30:24 +00:00
hotyue
4be4d5e9ef docs: 更新 README.md,增加对底层 IP 质量检测组件 xykt/IPQuality 的开源鸣谢 2026-04-25 01:29:30 +00:00
hotyue
1f925b307f docs: 更新 README.md,增加对底层 IP 质量检测组件 xykt/IPQuality 的开源鸣谢 2026-04-25 01:27:08 +00:00
hotyue
49afe032d6 fix(agent): 重构 Google 区域探测逻辑,穿透 YouTube GeoIP 底层彻底解决跨区漂移与假阳性误判 (Resolves #14, Resolves #35) 2026-04-25 00:48:00 +00:00
hotyue
f0f054c8cd feat(data): 扩容美国得克萨斯州 (Texas/Dallas) 部署坐标与地图基建 (Resolves #33) 2026-04-25 00:36:07 +00:00
hotyue
699e9ca31a feat(master): 重构全球旗帜渲染引擎,支持 US-* 等州级行政区划自适应 (Resolves #33) 2026-04-25 00:25:06 +00:00
github-actions[bot]
76cace4ff6 chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [2026-04-24] 2026-04-24 19:03:51 +00:00
hotyue
9f3218ab7f chore: release v4.0.2 版本号跃升 2026-04-24 15:23:39 +00:00
hotyue
8a61f518f5 fix(agent): 移除 awk 暴力裁剪引发的 UTF-8 中文多字节劈裂乱码 Bug 2026-04-24 15:13:14 +00:00
hotyue
e9d5023263 fix: 紧急重构态势感知入库链路,引入交互式 [存档] 按钮,彻底解决 TG API 消息监听死锁 2026-04-24 15:06:02 +00:00
hotyue
05b1e21bba fix(master): 紧急修复 tr 命令语法死锁,并彻底解决态势感知面板的 URL-encoded 换行排版问题 2026-04-24 14:53:38 +00:00
hotyue
4a496fdab3 fix(master): 紧急修复 tr 命令中单引号转义引发的 Bash 语法崩溃死锁 2026-04-24 14:46:23 +00:00
hotyue
8ae3a6534d feat: 🚀 跃升至 v4.0.2,全面重构 IP 质量态势感知矩阵,新增 Google 与 ChatGPT 历史轨迹追踪 2026-04-24 14:36:36 +00:00
hotyue
3269376c94 fix(agent): 彻底重构探针参数装配机制,完美兼容多IP站群并补回尾部直达链接所需IP变量 2026-04-24 14:01:20 +00:00
hotyue
7a92de4d62 fix(agent): 重构探针参数装配机制,完美兼容多IP站群路由绑定与 NAT 容灾,并修复底部 Scamalytics 链接的变量丢失问题 2026-04-24 13:47:10 +00:00
hotyue
5fbc1e3fb3 fix(agent): 修复 NAT 架构下强制绑定出口导致探针崩溃的死锁,注入 -f 标志输出完整明文 IP,并规范化面板术语 2026-04-24 13:36:11 +00:00
hotyue
d73c3154f9 feat(agent): 丰富深海声呐战报,底部追加探针引擎的运行时版本号与情报生成时间戳 2026-04-24 12:29:54 +00:00
hotyue
b3fbed4a94 chore: 🚀 跃升至 v4.0.1,防弹装甲专项重构全面闭环 2026-04-24 10:53:08 +00:00
hotyue
71fe3bde51 fix(master): 补齐 Master 部署脚本缺失的 openssl 核心依赖,杜绝纯净系统下因 HMAC 签名生成失败导致指令被全网拒收的致命隐患 2026-04-24 10:48:18 +00:00
hotyue
c739f58cc5 refactor(agent): 🛡️ 终极安全重构 - 阻断 FD 文件锁继承导致的任务死锁,并将深海声呐探针收编本地化执行,彻底铲除第三方 RCE 投毒风险 2026-04-24 10:29:11 +00:00
hotyue
2c50c72fcb refactor(agent): 🛡️ 终极安全重构 - 阻断 FD 文件锁继承导致的任务死锁,并将深海声呐探针收编本地化执行,彻底铲除第三方 RCE 投毒风险 2026-04-24 10:28:38 +00:00
hotyue
8d16c549fc fix(agent): 修复公网 IP 变动重新注册时丢失 OTA 权限的漏洞,并彻底肃清质量检测路由中的僵尸进程残留 2026-04-24 10:09:18 +00:00
hotyue
d74d6d8775 fix(agent): 🚨 彻底废除官方网关模式下的 HTTP 裸奔漏洞,实现全网节点 100% 强制 TLS 加密,配合主控端 Strict-TLS 2026-04-24 10:02:40 +00:00
hotyue
853e6c09e1 fix(install): 修复 Alpine Linux 下 dcron 依赖缺失导致 openssl 链式静默安装失败的漏洞 2026-04-24 09:44:29 +00:00
hotyue
1f21ac9a7e fix: 🚨 破除 Strict-TLS 死亡锁死,强制全网挂载 openssl 证书,并为 OTA 指令开辟一次性 HTTP 灾难救援通道 2026-04-24 09:36:58 +00:00
hotyue
28fd94eff5 fix(agent): 🚀 全面排雷 - 修复 IPv6 映射监听失败、60秒 HMAC 并发重放漏洞、长效守护引发的僵尸进程泄露,并实现 OTA 源地址动态解耦 2026-04-24 07:30:12 +00:00
hotyue
7460935acc fix(master): 🚨 彻底废除 HTTP 强制降级漏洞,实现全链路 Strict-TLS 加密,封堵明文劫持入口 2026-04-24 07:16:08 +00:00
hotyue
109ae6f319 Merge PR #32: 引入双写日志架构,全面打通 Systemd Journal 遥测通道 2026-04-24 06:45:01 +00:00
hotyue
6b3acf5787 docs: 更新项目文档,彰显 V4.0.0 深海声呐全维探针与趋势追踪架构 2026-04-24 03:30:20 +00:00
hotyue
b1ecbd4f9a chore: 恢复拉取源为 main 并移除 Beta 标识,准备发布 v4.0.0 正式版 2026-04-24 03:25:32 +00:00
hotyue
4d091e4dd9 fix(agent): 增加双栈容灾试探,修复纯V6环境下提取云端版本号超时导致被异常降级的Bug 2026-04-24 03:25:01 +00:00
hotyue
ae6559c850 fix(master): 同步修复 V6 环境下提取云端版本号超时的 Bug,并抬高兜底版本至 v4.0.0 2026-04-24 03:24:24 +00:00
hotyue
5cfaebceab Merge remote-tracking branch 'origin/main' into dev/v4.0.0-sonar 2026-04-24 03:15:31 +00:00
github-actions[bot]
88f55cbab9 chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [2026-04-23] 2026-04-23 19:22:57 +00:00
IcySteam
1204336612 fix(telemetry): Restore dual-write logging to the Systemd journal
Reapply commit `e77b7c0`, which was (inadvertently?) omitted in the recent upstream rollup `34320b2`.

Original commit description:
```
This commit refactors the internal logging functions across all core modules to guarantee telemetry reaches the Systemd journal. Sentinels now mirror their physical log outputs directly to the OS `logger`, ensuring flawless `journalctl` visibility even when modules are spawned in detached subshells.
```
2026-04-24 01:47:56 +10:00
hotyue
49a65a5f11 fix(agent): 移除过度严格的 sed 过滤,修复因不可见字符导致的 JSON 截断告警,确立终极情报版战报排版 2026-04-23 14:14:24 +00:00
hotyue
7e5b836a49 feat(agent): 彻底重构声呐战报,解决广告字符干扰,实现全库打分矩阵与流媒体高亮排版 2026-04-23 14:08:07 +00:00
hotyue
18f80400ef feat(agent): 升级深海声呐为满血版,补充展示 ASN/归属地/原生IP/25端口及 Abuse 投诉分 2026-04-23 13:58:18 +00:00
hotyue
eca4b41da4 feat(agent): 丰富深海声呐战报,增加 YouTube/Disney/TikTok 解锁展示与 Google 送中警告 2026-04-23 13:51:08 +00:00
hotyue
a24a533165 fix(agent): 修复 webhook 路由 Python 严格缩进错误导致的进程崩溃问题 2026-04-23 13:40:12 +00:00
hotyue
d2b575fe85 chore: 临时将全局拉取源切换至 dev/v4.0.0-sonar,准备进行深海声呐实弹测试 2026-04-23 13:33:07 +00:00
hotyue
cb0aa2049e chore: 移除 beta 标识,准备发布 v4.0.0 正式版 2026-04-23 13:28:49 +00:00
hotyue
981b9e4859 feat(master): 完善部署脚本,新增 ip_trend_log 数据表以支持 IP 污染趋势追踪 2026-04-23 13:26:11 +00:00
hotyue
eeee1b6811 feat(agent): 新增深海声呐核心模块 (mod_quality.sh),实现异步 IP 质量探测与隐写战报回传 2026-04-23 13:25:54 +00:00
hotyue
e6852d0c9d feat(agent): 将深海声呐武器 mod_quality.sh 接入 install 部署/OTA 补给线 2026-04-23 13:22:22 +00:00
hotyue
23ea08f981 feat(agent): Webhook 追加 /trigger_quality 路由,支持异步拉起深海声呐 2026-04-23 13:17:36 +00:00
hotyue
580a3d7fd5 feat(master): 完善深海声呐与趋势监测中枢,指令与 UI 面板彻底闭环 2026-04-23 13:13:06 +00:00
hotyue
6eabb60c28 chore: 开启 v4.0.0-sonar 深海声呐模块开发分支,升级版本号至 beta 2026-04-23 12:27:11 +00:00
hotyue
7fd432ffee fix(install): 修复装机量统计逻辑,仅在全新部署时触发探针,彻底解决平滑升级导致的数据虚高与 Cloudflare KV 写入配额耗尽问题 2026-04-23 11:18:46 +00:00
github-actions[bot]
351143e59d chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [2026-04-23] 2026-04-23 01:59:32 +00:00
hotyue
725e8ae8c9 ci: 全局挂载 FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true 消除 Node.js 20 弃用警告 2026-04-23 01:58:44 +00:00
github-actions[bot]
1e9de46fc5 chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [2026-04-23] 2026-04-23 01:56:38 +00:00
hotyue
543ab5c8bd Merge branch 'main' of https://github.com/hotyue/IP-Sentinel 2026-04-23 01:53:47 +00:00
hotyue
972cd02874 fix(scripts): 修复 MY 战区 Yahoo RSS 拒绝 GitHub IP (403) 问题,切换为高可用 Google News 源 2026-04-23 01:53:36 +00:00
github-actions[bot]
9c37cb9df3 chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [2026-04-23] 2026-04-23 01:51:45 +00:00
hotyue
2a8a6b6fa7 feat(region): 拓展亚太战区,新增马来西亚 (MY) 节点及本地骨干网与 RSS 活体流 (Resolves #31) 2026-04-23 01:50:15 +00:00
hotyue
e4b4c747eb chore(data): 初始化 MY (马来西亚) 战区热点词库基石,防止边缘节点初次部署时 404 2026-04-23 01:49:39 +00:00
github-actions[bot]
eabd33e6b2 chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [2026-04-22] 2026-04-22 19:24:05 +00:00
hotyue
233af7181f release: bump AGENT_VERSION to v3.6.4 for Trust module Live News Engine 2026-04-22 14:03:41 +00:00
github-actions[bot]
62fb19f0c5 chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [2026-04-22] 2026-04-22 13:49:03 +00:00
hotyue
54178ddcf1 fix(scripts): 修复 TW 战区 Yahoo RSS 拒绝 GitHub Actions IP 访问 (403) 的问题,切换至高可用 Google News TW 源 2026-04-22 13:48:06 +00:00
github-actions[bot]
92a65d8308 chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [2026-04-22] 2026-04-22 13:45:37 +00:00
hotyue
eaaa7dabf0 Merge branch 'main' of https://github.com/hotyue/IP-Sentinel 2026-04-22 13:43:44 +00:00
hotyue
e797c8203f fix(scripts): 修复 HK 与 TW 战区 RSS 情报源失效报 404/解析错误的问题,切换至高可用源 2026-04-22 13:43:31 +00:00
github-actions[bot]
9ecf50c153 chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [2026-04-22] 2026-04-22 13:37:10 +00:00
hotyue
c02b7eecc9 feat(scripts): 引入 v3.6.4 活体新闻融合引擎,重构 Action 流水线实现冷热数据合并原子提交 2026-04-22 13:35:20 +00:00
hotyue
6af8b6b25d chore(data): 注入全球国家级权威骨干网基石,重构 Trust 模块冷数据结构 2026-04-22 13:31:28 +00:00
hotyue
7081aa77cc fix(core): 废除 OnBootSec 相对开机时间,改用高兼容性的 OnActiveSec,彻底修复老内核系统下自动巡逻瘫痪的 Bug 2026-04-22 12:42:04 +00:00
hotyue
5e48edb030 fix(core): 废除物理阉割,全量下载模块脚本,彻底修复动态启用模块后提示 403 文件不存在的 Bug 2026-04-22 11:53:20 +00:00
github-actions[bot]
5f0f677f59 chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-21] 2026-04-21 19:22:42 +00:00
hotyue
7f0c3e3e29 release: bump version to v3.6.3 for final release 2026-04-21 09:50:14 +00:00
hotyue
c03f6ca9ba chore: 准备 v3.6.3 正式发布,将所有云端资源路由切换回 main 主干分支 2026-04-21 09:48:14 +00:00
hotyue
66f3ba7d06 perf(master): 优化包管理器参数,拒绝冗余依赖捆绑,实现 Master 中枢极致轻量化部署 2026-04-21 09:32:54 +00:00
hotyue
511ba90378 perf(core): 优化包管理器安装参数,拒绝冗余依赖捆绑,实现 Agent 节点极致轻量化部署 2026-04-21 09:30:04 +00:00
hotyue
01806d20dd fix(core): 引入智能网卡生存探测机制,彻底解决多 IP 站群机因 IP 漂移导致的 curl 死锁断网问题 2026-04-21 09:20:55 +00:00
hotyue
049278c458 fix(master): 修复 Telegram 429 频率限制拦截,延长全军简报下发间距至 2 秒,确保并发战报 100% 送达 2026-04-21 07:19:04 +00:00
hotyue
0aaa2d44a0 fix(master): 修复 db_exec 致命的标准输出混叠漏洞,改用静默的 .timeout 指令彻底消除面板 5000 乱码 2026-04-21 07:08:43 +00:00
hotyue
3f139a593e fix(master): 修复 db_exec 输出泄露导致的节点计数与战区列表乱码问题 2026-04-21 07:01:54 +00:00
hotyue
bee6fef69c fix(master): 启用 SQLite WAL 高并发引擎与 5000ms 锁排队机制,彻底解决全舰队并发通讯时的 database is locked 报错 2026-04-21 06:51:49 +00:00
hotyue
f283a8a4c6 fix(master): 完善向下兼容机制,对未升级老节点自动降级回退至 HTTP 通讯,确保私有司令部平滑过渡 2026-04-21 06:47:02 +00:00
hotyue
0d2433d850 feat(security): 引入动态 TLS 降级机制与自签名证书,全域 Webhook 通讯升级为强加密 HTTPS,彻底阻断明文嗅探风险并完美兼容官方网关 2026-04-21 06:27:58 +00:00
hotyue
a6b01bd8d5 chore(core): 恢复 install.sh 语法完整性,完成 OTA 防砖机制实弹演习 2026-04-21 06:12:38 +00:00
hotyue
8f2279b7e2 chore(core): 破坏 install.sh 语法完整性,用于 OTA 防砖机制实弹演习 2026-04-21 06:09:48 +00:00
hotyue
d37d26708d chore(core): 恢复 install.sh 语法完整性,完成 OTA 防砖机制实弹演习 2026-04-21 06:07:50 +00:00
hotyue
6234d7c49a fix(ota): 重构 Agent 防砖机制,引入双重 Base64 隔离,彻底杜绝 Shell 注入与换行截断,并实现失败主动告警 2026-04-21 06:05:39 +00:00
hotyue
f9a7bba32a Update install.sh
test
2026-04-21 13:52:06 +08:00
hotyue
068734da16 fix(ota): 引入 bash -n 语法树完整性校验,彻底阻断因网络波动下载不全导致的单点死机风险 2026-04-21 05:45:50 +00:00
hotyue
09a4108bcc docs(readme): 更新 Legacy 分支部署指令,全站统一采用更安全的落地执行法 2026-04-21 02:47:18 +00:00
hotyue
a7f08ec7a7 chore(release): 解除测试沙箱 URL 劫持,跃升至 v3.6.2,正式开启 Systemd 与智能双栈纪元 2026-04-21 02:42:04 +00:00
hotyue
f075fcce36 fix(master): 修复 Systemd 沙盒环境变量丢失问题,打通跨进程通讯,确保 OTA 升级捷报正常下发 2026-04-21 02:30:45 +00:00
hotyue
0bb96169e5 fix(core): 引入 Ceasefire Protocol (停火协议),彻底解决 Systemd 架构下 OTA 升级引发的无限重启风暴 2026-04-21 02:21:43 +00:00
hotyue
34320b2385 refactor(core): 手工融合 Systemd 引擎与 Root 权限校验 (提取自 PR #25),修复 Cgroup 误杀与交互逻辑陷阱,构建灰度测试候选版 2026-04-21 02:00:10 +00:00
github-actions[bot]
aeed9f0e57 chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-20] 2026-04-20 19:17:23 +00:00
hotyue
c04a4c41e4 fix(core): 修复内核级禁用 IPv6 时 Python Webhook 假死的问题,引入智能 IPv4 降级回退机制 (Resolves #23) 2026-04-20 17:41:17 +00:00
hotyue
3b28ead0e4 chore: 战略撤退,代码全量回滚至 9a38fb6 (PR 引入前的纯净状态) 2026-04-20 17:37:47 +00:00
hotyue
d0ea5d09b1 chore(release): 跃升至 v3.6.2,引入 Systemd 守护与智能双栈降级引擎 2026-04-20 17:20:09 +00:00
hotyue
a119973ec0 chore(release): 暂时回退至 v3.6.1 2026-04-20 17:18:17 +00:00
hotyue
b8b91ac17e chore(release): 跃升至 v3.6.2,引入 Systemd 守护与智能双栈降级引擎 2026-04-20 17:17:38 +00:00
hotyue
34f2c7e123 fix(core): 引入 systemd-run 逃逸机制,彻底修复 OTA 升级时因子进程被 Cgroup 误杀导致的假死漏洞 2026-04-20 17:13:48 +00:00
hotyue
172f1e0209 chore(release): 暂时回退至 v3.6.1 2026-04-20 17:11:05 +00:00
hotyue
1d5ed5d0cb chore(release): 跃升至 v3.6.2,引入 Systemd 守护与智能双栈降级引擎 2026-04-20 17:06:38 +00:00
hotyue
1e150f26f1 fix(core): 修复内核级禁用 IPv6 时 Python Webhook 假死的问题,引入智能 IPv4 降级回退机制 (Resolves #23) 2026-04-20 16:59:28 +00:00
hotyue
03e735a44b docs(readme): 重构系统部署指令,采用落地执行模式彻底修复管道符交互闪退与进程误杀漏洞 2026-04-20 16:55:12 +00:00
hotyue
011c1faad4 fix(core): 移除 agent_daemon.sh 尾部的 nohup 后台逻辑,适配 Systemd Type=simple 的前台阻塞监听,修复 cgroup 误杀导致的无限重启死循环 2026-04-20 16:46:45 +00:00
hotyue
2325a8abdf fix(core): 修复节点部署多城市选择分支下 CITY_NAME 变量未赋值导致播报为空的 UI 瑕疵 2026-04-20 16:41:00 +00:00
hotyue
201df489db refactor(core): 缝合 Systemd 架构,修复 PR #25 中的管道符闪退及 oneshot 守护进程死锁漏洞 2026-04-20 16:24:32 +00:00
IcySteam
2d680c5fc7 refactor(core): Enable Systemd and upgrade Sentinel service orchestration
The legacy crontabs have been superseded by Systemd to fortify orchestration of our global fleet of Sentinels.

While cron relies on timed, fire-and-forget execution, Systemd elevates our operations into natively integrated, state-aware OS daemons. This paradigm shift unlocks precise lifecycle management, unified logging (inspect all service logs with `journalctl -t ip-sentinel`), and absolute control over module deployment.

- Battle-Hardened: Sentinels now auto-resurrect upon failure, bypassing minute-long cron wait times.
- Zero-Impact Missions: Sentinels now operate under strict `idle` CPU/IO scheduling. This guarantees that automated maintenance cycles yield to high-priority user interactions, and never impact primary server workloads.
- Field Intelligence Auto-Stagger: Service-level `RandomizedDelaySec` natively staggers Agent check-ins to protect the Command Center.
- Legacy Fallback: OS interrogation on deployment ensures a seamless fallback to cron for Sentinels operating in Alpine/OpenRC environments.

The fleet is more resilient than ever, but the architecture is always evolving. I highly welcome any reviews/suggestions from the original Author/Commander to perfect this pull request!
2026-04-21 00:27:01 +10:00
IcySteam
e77b7c0319 fix(telemetry): Implement dual-write logging for Systemd integration
This commit refactors the internal logging functions across all core modules to guarantee telemetry reaches the Systemd journal. Sentinels now mirror their physical log outputs directly to the OS `logger`, ensuring flawless `journalctl` visibility even when modules are spawned in detached subshells.
2026-04-21 00:12:03 +10:00
IcySteam
2283da7421 docs(readme): Update setup instructions to use sudo pipes
The installation instructions in the README have been updated to pipe the `curl` output directly into `sudo bash`.

As we now mandate root privileges on setup, the standard `bash <(curl...)` command fails when prepended with `sudo` due to process substitution permissions. This fix ensures all new Commanders can deploy their Sentinels flawlessly on the first attempt.
2026-04-20 23:01:34 +10:00
IcySteam
4a28f7f395 fix(core): Mandate root privileges for all setup scripts
The old setup scripts assume root privileges. We are fixing this by explicitly requiring an `$EUID` root check before execution so that no borked, non-root installations happen.
2026-04-20 19:46:30 +10:00
github-actions[bot]
9a38fb62d0 chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-19] 2026-04-19 19:01:27 +00:00
hotyue
fefd5dc60c fix(master): 修复双栈机 IPv6 黑洞导致轮询假死的致命 Bug 2026-04-19 15:06:56 +00:00
hotyue
89aa1ead33 docs: 新增动态贡献者头像墙 (Contributors Wall),致敬开源极客 2026-04-19 14:36:48 +00:00
hotyue
a5f2fb53ed feat(data): 建立韩国 (KR) 战区拓扑,新增首尔节点信标及本土化高频活体词库 2026-04-19 14:23:50 +00:00
hotyue
bd26f1011d fix(master): 统一全域雷达面板的国旗状态机映射数组,修复删除节点后小众国家国旗丢失的 UI 渲染问题 2026-04-19 14:13:28 +00:00
hotyue
cfaf156e03 Merge pull request #24 from IcySteam/main
feat: Activate the AU command theater, deploy sentinel to 5 major Australian cities
2026-04-19 22:03:44 +08:00
github-actions[bot]
75cf50ce0c chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-18] 2026-04-18 19:01:49 +00:00
IcySteam
e2b6bbc347 master(AU): Add AU flag to TG menu 2026-04-19 01:05:38 +10:00
IcySteam
cd5160d1ea core(AU): Add AU flag to TG menu 2026-04-19 01:05:28 +10:00
IcySteam
040827aa27 data(AU): activate AU command theater, deploy sentinel to 5 major Australian cities 2026-04-19 00:57:01 +10:00
IcySteam
d00317a645 feat(map): establish the Oceania (AU) command theater 2026-04-19 00:53:00 +10:00
hotyue
60317b4444 docs: 更新项目文档,正式发布 v3.6.1 扁平化指控矩阵与司令部金蝉脱壳 (Master OTA) 架构 2026-04-18 00:54:27 +00:00
hotyue
a0bb0f30f2 chore(master): 移除安装向导测试期锚点,恢复生产环境 main 主分支直链 2026-04-18 00:54:22 +00:00
hotyue
cc6f7bf958 chore(master): 移除调度枢纽测试期锚点,恢复生产环境 main 主分支直链 2026-04-18 00:54:17 +00:00
hotyue
583e0b00d8 chore(release): 升级双端版本信标至 v3.6.1,激活扁平化矩阵与中枢 OTA 引擎 2026-04-18 00:54:09 +00:00
hotyue
c27f2fced9 feat(master): 实装司令部金蝉脱壳 (Silent Override) 架构,新增中枢免交互 OTA 热重载能力与自动捷报推送 2026-04-18 00:41:03 +00:00
hotyue
8baa141339 chore(master): 临时切换 install_master.sh 拉取直链至 dev-v3.6.1 分支以支持扁平化 UI 演习测试 2026-04-18 00:20:45 +00:00
hotyue
2eceb43ac3 chore(master): 临时切换 install_master.sh 拉取直链至 dev-v3.6.1 分支以支持扁平化 UI 演习测试 2026-04-18 00:17:12 +00:00
hotyue
8ce9eb256b refactor(master): 重构 M 菜单为扁平化指挥矩阵 (Flat Command Matrix),优化 L0-L3 层级逻辑,新增全局返回逃生舱,并实现统一哨兵终端的原位丝滑重绘 2026-04-18 00:15:33 +00:00
github-actions[bot]
bf2cfb7da0 chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-17] 2026-04-17 19:11:44 +00:00
hotyue
5dfaa19cca chore: 移除测试期 dev-v3.6.0 专属锚点,全系组件直链恢复至 main 主分支,准备发布正式版 2026-04-17 15:07:45 +00:00
hotyue
3404666b8e chore(release): 升级双端版本信标至 v3.6.0,全面激活零信任 OTA 引擎 2026-04-17 15:05:28 +00:00
hotyue
b64ab95658 docs: 重构项目文档,正式发布 v3.6.0 零信任 OTA 架构及全舰队升级指引 2026-04-17 15:05:05 +00:00
hotyue
f19d165ece refactor(master): 移植 Agent 级智能依赖探测引擎,实现缺啥补啥的优雅部署,并增加二次复检熔断机制 2026-04-17 14:49:10 +00:00
hotyue
602919dc18 fix(master): 修正 send_ui 函数的 JSON 载荷换行符为 \n,解决带按钮面板的排版乱码问题 2026-04-17 14:43:27 +00:00
hotyue
722db9f6d1 style(core): 引入终端 OSC 8 超链接特性,重构教程链接交互为点击即达,提升终端沉浸式体验 2026-04-17 14:35:55 +00:00
hotyue
970867f3c7 fix(master): 司令部启动追加 disown 脱钩指令,抹除卸载与升级时底层 Bash 的 Killed 进程报错,提升静默优雅度 2026-04-17 14:18:39 +00:00
hotyue
e22d8d3cd0 fix(master): 修复官方机器人 OTA 按钮 UI 泄露问题,精准挂载 IS_OFFICIAL_GATEWAY 标识完成渲染层拦截 2026-04-17 14:10:54 +00:00
hotyue
cfe6dd59c8 feat(master): 部署向导新增官方与私有网关身份选择,固化 IS_OFFICIAL_GATEWAY 标识以支持 UI 级物理熔断 2026-04-17 14:10:40 +00:00
hotyue
b46e257545 fix(master): 修正 TG 报文换行符为 %0A,解决 Markdown 解析排版异常 2026-04-17 13:39:59 +00:00
hotyue
3e9a82a657 chore: 临时将各组件拉取直链指向 dev-v3.6.0 分支,修复跨分支拉取导致的数据解析错位 2026-04-17 13:27:20 +00:00
hotyue
4cf687f436 feat(master): 控制面板实装单点与全舰队级 OTA 升级核按钮及二次确认防抖,重构底层注册逻辑以兼容 7 字段解析入库 2026-04-17 13:08:04 +00:00
hotyue
e88cf4ac5b feat(master): 部署引擎移植全境兼容嗅探器,并预建 SQLite 数据库的 enable_ota 控制字段 2026-04-17 13:07:14 +00:00
hotyue
898349d22e feat(core): Webhook 通讯引擎新增 /trigger_ota 高危路由,实装本地与网关双重熔断校验,并支持后台剥离交互的静默热重载 2026-04-17 13:06:44 +00:00
hotyue
9ea188cb6d feat(core): 部署向导新增静默接管模式 (SILENT_OTA),并实现基于双轨网关的 OTA 权限物理熔断与配置下发 2026-04-17 13:06:37 +00:00
hotyue
03d4c6160a docs: 恢复英文提示词 2026-04-17 09:02:38 +00:00
hotyue
cf4433cdd6 docs: 修改提示词 2026-04-17 08:55:17 +00:00
hotyue
ae80f25c67 docs: 增加Bot Token 及 Chat ID获取教程链接 2026-04-17 08:28:15 +00:00
hotyue
5b2c294c61 docs: 增加官方机器人直达链接 2026-04-17 08:19:00 +00:00
hotyue
a1595ab0c5 docs: 增加官方机器人直达链接 2026-04-17 08:17:30 +00:00
hotyue
0be1e92ac5 docs: 优化部署指南,将私有独立部署提升为首选推荐,并预告 OTA 远程升级战略 2026-04-17 08:02:59 +00:00
hotyue
cf3e5dca2f docs: 优化部署指南,将私有独立部署提升为首选推荐,并预告 OTA 远程升级战略 2026-04-17 07:58:54 +00:00
hotyue
902f612d31 chore(release): bump version to v3.5.4 2026-04-17 07:20:05 +00:00
hotyue
45475f14b7 feat(core): 优化中枢接入交互引导,将私有独立部署设为首选默认项,为后续 OTA 远程平滑升级铺路 2026-04-17 07:06:45 +00:00
hotyue
30f396aefe fix(core): 升级智能包管理器嗅探器,彻底修复 Alpine/Arch 依赖安装失败 Bug,并重构 Master 接入交互逻辑防止误触跳过 (Resolves #21) 2026-04-17 06:49:16 +00:00
hotyue
7cf7117615 fix(core): 增强安装引擎容错能力,加固 Cron 清理逻辑并严格限制底层物理标识符格式 2026-04-17 05:32:19 +00:00
hotyue
062305d126 fix(core): Webhook 引擎引入 fcntl 排他写锁防配置文件损坏,强制清洗底层物理主键 2026-04-17 05:32:15 +00:00
hotyue
f451aea643 fix(core): 优化战报日志提取逻辑,改用精确截断替代全量扫描,大幅降低 I/O 消耗 2026-04-17 05:32:09 +00:00
hotyue
64342b2846 fix(master): 批量调度引擎引入流量削峰机制,杜绝瞬间并发导致的网络栈与文件句柄耗尽 2026-04-17 05:32:03 +00:00
hotyue
d96b6e769a fix(core): 引入 flock 排他锁,彻底解决 Cron 任务重入导致的内存雪崩与 Fork 炸弹 2026-04-17 05:31:58 +00:00
hotyue
539de62eee chore(release): bump version to v3.5.3 2026-04-17 03:00:11 +00:00
hotyue
d514106e65 docs: [v3.5.3] 重构 README 极客特征文案,合并冗余架构特性并引入常青化排版 2026-04-17 03:00:05 +00:00
hotyue
7f9c8a4dea feat(master): [v3.5.3] 引入L5降维控制面板与内联UI重绘,实装红绿灯状态机与模块动态启停 (Resolves #17, Resolves #19) 2026-04-17 02:40:27 +00:00
hotyue
31014e571d feat(master): [v3.5.3] 升级 SQLite 初始表结构,新增模块状态追踪字段以支持红绿灯 UI (Resolves #19) 2026-04-17 02:40:23 +00:00
hotyue
f5aa68a8dc feat(core): [v3.5.3] Webhook 引擎新增模块动态启停(Toggle)路由,支持安全重写本地配置 (Resolves #19) 2026-04-17 02:40:19 +00:00
hotyue
63bbbd549e feat(agent): [v3.5.3] 优化安装向导,默认全量部署养护模块以支持远端动态控制 (Resolves #19) 2026-04-17 02:40:14 +00:00
hotyue
5e40ed426b chore: revert failed v3.6.0 attempts, rollback to safe state 2026-04-17 02:24:07 +00:00
hotyue
aebf3a9e90 fix(core): [v3.6.0] 终极修复 OTA 死锁:解决 curl 管道吞噬脚本 Bug,并应用底层网络脱壳机制 2026-04-17 02:17:32 +00:00
hotyue
8a3d7c305b fix(core): [v3.6.0] 彻底重构 OTA 升级调度,引入外挂延时脚本实现 100% 的网络脱壳与静默重启 2026-04-17 02:09:05 +00:00
hotyue
2d580eaea2 fix(core): [v3.6.0] 彻底解决 OTA 升级 TCP 通讯超时 Bug,引入 close_fds 剥离套接字继承机制 2026-04-17 01:59:29 +00:00
hotyue
d7ab695372 fix(core): [v3.6.0] 彻底解决 OTA 升级 TCP 通讯超时 Bug,引入异步守护线程与套接字剥离机制 2026-04-17 01:48:46 +00:00
hotyue
0c250dfd17 fix(core): [v3.6.0] 修复 OTA 升级时的竞态自杀 Bug,引入 TCP 强制刷新与 3 秒延迟脱壳机制 2026-04-17 01:44:40 +00:00
hotyue
52b12c7057 feat(master): [v3.6.0] 深度重构中枢调度,引入L5降维控制面板、红绿灯模块启停与全网 OTA 静默升级 (Resolves #17, Resolves #19) 2026-04-17 01:19:27 +00:00
hotyue
2166753569 feat(master): [v3.6.0] 司令部部署引入 OTA 下发权限控制,重构 SQLite 初始表结构以支持状态机 (Resolves #17, Resolves #19) 2026-04-17 01:19:20 +00:00
hotyue
46e418dfd0 feat(core): [v3.6.0] Webhook 引擎新增 OTA 升级与动态启停路由,实装底层权限物理熔断机制 (Resolves #17, Resolves #19) 2026-04-17 01:19:13 +00:00
hotyue
673e0ce3e6 feat(agent): [v3.6.0] 重构安装向导,引入静默 OTA 嗅探机制与双端授权防线,默认全量部署养护模块 (Resolves #17, Resolves #19) 2026-04-17 01:19:06 +00:00
github-actions[bot]
6203249782 chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-16] 2026-04-16 19:25:36 +00:00
hotyue
05e708ed21 fix(master): [v3.5.2] 修复交互向导首选项的默认值丢失问题,防止直接回车导致主控数据库被误删 2026-04-16 07:57:02 +00:00
hotyue
c4faa102cf fix(installer): [v3.5.2] 修复交互向导首选项的默认值丢失问题,防止直接回车导致平滑升级失效被误删档 2026-04-16 07:52:45 +00:00
hotyue
4a1b32278c fix(core): [v3.5.2] 补充 version.txt 尾部换行符,防止环境变量读取截断 2026-04-16 06:54:29 +00:00
hotyue
584ead387e docs: [v3.5.2] 更新 README 战报日志,全系版本号正式锚定 v3.5.2 2026-04-16 06:52:06 +00:00
hotyue
efdc62ba68 feat(map): 更新全球战区拓扑,挂载考文垂与蒙特利尔节点索引 2026-04-16 06:32:47 +00:00
hotyue
67618587e4 feat(data): 新增节点数据 - 加拿大蒙特利尔 (CA, Montreal) 2026-04-16 06:32:42 +00:00
hotyue
a2c045a841 feat(data): 新增节点数据 - 英国考文垂 (UK, Coventry) 2026-04-16 06:32:37 +00:00
hotyue
9b35c87cb4 fix(master): [v3.5.2] 修复 Telegram 纯文本 API 下发消息时的换行符 (%0A) 转义问题 2026-04-16 06:02:51 +00:00
hotyue
e6c6e66e4b feat(agent): [v3.5.2] 剥除改名后的冗余 TG 推送报文,实现静默修改配置与底层 HTTP 回执 2026-04-16 05:51:04 +00:00
hotyue
f1d36a2148 feat(master): [v3.5.2] 实现全自动丝滑改名,接收 Agent 成功回执后瞬间刷新本地 SQLite 数据库 2026-04-16 05:50:58 +00:00
hotyue
41906d0570 revert: 紧急回滚至稳定版 9768bed (修复加密升级导致的通讯中断) 2026-04-16 03:24:11 +00:00
hotyue
dc7d1c0f40 feat: [v3.5.2] 终极安全与逻辑闭环补丁
1. 升级军工级 HMAC 签名:将数据负载 (Base64) 卷入哈希,封死中间人篡改路径。
2. 引入高熵复合密钥:结合 CHAT_ID 与 TG_TOKEN,大幅提升抗暴力破解强度。
3. 实现全自动改名闭环:Master 确认 Agent 修改成功后自动同步数据库,彻底告别手动复制。
2026-04-16 03:14:12 +00:00
hotyue
9768bed637 fix(master): [v3.5.2] 废除原生 tr 命令的失效中文白名单,改用黑名单过滤,确保中文字符完美送入 Base64 编码 2026-04-16 02:43:52 +00:00
hotyue
fa202a0405 fix(core): [v3.5.2] 采用 Base64 编码彻底重构别名同步链路,免疫 WAF 拦截与中英文符号解析崩溃 2026-04-16 02:24:50 +00:00
hotyue
b8bcd09134 fix(agent): [v3.5.2] 修复别名同步时的中文 UTF-8 编码崩溃,改用 curl 绕过 WAF 拦截,并拦截下划线防止 TG 面板渲染异常 2026-04-16 01:55:57 +00:00
hotyue
ef8dc033cc feat(master): [v3.5.2] 中枢支持解析 6 字段注册包,面板适配别名并新增重命名状态机 (Resolves #9) 2026-04-16 01:35:16 +00:00
hotyue
03a54bcca0 chore(master): [v3.5.2] 完善全新部署时的 SQLite 表结构 (增加 region 与 node_alias) 2026-04-16 01:35:16 +00:00
hotyue
f4f93d8955 feat(agent): [v3.5.2] 每日战报全面适配 NODE_ALIAS 展示字段 2026-04-16 01:35:16 +00:00
hotyue
07cac792f0 feat(agent): [v3.5.2] 守护进程新增 /trigger_rename 接口,实现免注入安全重命名 2026-04-16 01:35:16 +00:00
hotyue
50edad9e25 feat(agent): [v3.5.2] 部署引擎引入双轨身份,支持自定义节点展示别名 2026-04-16 01:35:16 +00:00
hotyue
69edf12620 feat(map): [v3.5.2] 全球大地图更新,正式集成台湾 (TW) 及美国本土 6 大新州节点 2026-04-16 01:35:16 +00:00
hotyue
0b448e2b7e data(US): [v3.5.2] 深度扩容美国版图,新增 IL, UT, WA, NV, NC, OR 六大节点 (Resolves #15, 感谢 NQ 论坛 @yct002, @Ideal 提交的需求) 2026-04-16 01:35:16 +00:00
github-actions[bot]
d7b95136dd data(TW): [v3.5.2] 新增台湾战区数据与台北锚点 (Resolves #11) 2026-04-16 01:35:16 +00:00
github-actions[bot]
80d74111c4 chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-15] 2026-04-15 19:37:24 +00:00
hotyue
223d7c4b56 docs(readme): 更新项目架构图,同步 v3.5.1 双端版本解耦信标说明 2026-04-15 06:47:43 +00:00
hotyue
de3b4ca6d3 chore: 正式发布 v3.5.1,引入双端版本解耦架构 (KV 解析法) 2026-04-15 06:15:59 +00:00
hotyue
423a765e5f feat(core): 引入 KV 环境分解法,实现 Agent 与 Master 版本独立解耦 2026-04-15 05:58:28 +00:00
github-actions[bot]
ca74c31b96 chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-15] 2026-04-15 04:50:05 +00:00
hotyue
9366240d62 chore: 正式发布 v3.5.0,整合大洲战区架构与全球版图扩张 (NL, ES, CA, VN) 2026-04-15 04:39:43 +00:00
hotyue
1fa2cd10b1 feat(map): 全球版图正式扩充,集成 VN, NL, ES, CA 节点并修正更新日期 2026-04-15 04:36:52 +00:00
hotyue
3210c8cfcc data(VN): 新增越南 (Vietnam) 战区数据与核心规则 2026-04-15 04:35:22 +00:00
hotyue
d7e1e8fc8f data(CA): 新增加拿大 (Canada) 战区数据与核心规则 2026-04-15 04:35:12 +00:00
hotyue
a81f0564f1 data(ES): 新增西班牙 (Spain) 战区数据与核心规则 2026-04-15 04:35:04 +00:00
hotyue
3b20630e9e data(NL): 新增荷兰 (Netherlands) 战区数据与核心规则 2026-04-15 04:33:17 +00:00
hotyue
7321b76bb5 fix(scripts): 升级热搜词抓取引擎,适配 v3.5.0 大洲战区多层级解析 2026-04-15 04:25:25 +00:00
hotyue
8016b0531c docs(readme): 全面同步 v3.5.0 特性,更新大洲战区贡献规范与 SSOT 架构说明 2026-04-15 03:57:18 +00:00
hotyue
c7c93ea22e refactor(core): 全面肃清硬编码版本注释,适配动态锚点架构 2026-04-15 03:57:12 +00:00
hotyue
9aef79831c refactor(daemon): 动态注入节点防撞身份与运行时版本号至 UA 请求头及交互播报中 2026-04-15 03:57:02 +00:00
hotyue
43f2e98459 refactor(master): 剥离写死版本,严格落实运行态配置继承,优化卸载进程绞杀逻辑 2026-04-15 03:56:55 +00:00
hotyue
5627c0115a feat(installer): 引入 SSOT 动态版本抓取机制,并重构边缘节点战区分组交互 UI 2026-04-15 03:56:45 +00:00
hotyue
f252b26088 feat(data): 重构 map.json 至 v3.5.0 大洲战区 (Continental Grouping) 降维拓扑架构 2026-04-15 03:56:36 +00:00
github-actions[bot]
12e6619ab9 chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-14] 2026-04-14 19:26:11 +00:00
hotyue
a0bad1acf0 docs: 📝 更新 README 以适配 v3.4.0 架构特性与版本路由逻辑 2026-04-14 08:26:31 +00:00
hotyue
01d65972fd feat(master): 🗑️ Master 卸载程序同步 v3.4.0 焦土逻辑 2026-04-14 08:00:48 +00:00
hotyue
b1334fc06a feat(master): 🤖 调度中枢 UI 重构,接入 v3.4.0 实时版本监控 2026-04-14 08:00:47 +00:00
hotyue
918c73b5dc feat(master): 🧠 中枢安装脚本实现版本号补录与无损热升级 2026-04-14 08:00:47 +00:00
hotyue
28f04a4eb9 feat(core): 🗑️ 卸载脚本增加版本感知识别逻辑 2026-04-14 08:00:41 +00:00
hotyue
26328e66c4 feat(core): 🛡️ Trust 净化模块同步 v3.4.0 版本追踪标识 2026-04-14 08:00:40 +00:00
hotyue
1d85837e79 feat(core): 📍 Google 养护模块日志格式化对齐 v3.4.0 2026-04-14 08:00:40 +00:00
hotyue
ba8e2f1625 feat(core): 📊 战报模块注入云端版本感知与 OTA 提醒 2026-04-14 08:00:40 +00:00
hotyue
6b809138e5 feat(core): 🔄 更新引擎同步 v3.4.0 版本锚点架构 2026-04-14 08:00:40 +00:00
hotyue
6f4e871c7c feat(core): ⏱️ 调度引擎注入版本探针日志追踪 2026-04-14 08:00:40 +00:00
hotyue
fe2c9de80b fix(core): 🐍 守护进程同步 v3.4.0 标识并修正节点命名连接符 2026-04-14 08:00:40 +00:00
hotyue
6c0a589395 feat(core): 🚀 部署引擎升级至 v3.4.0 (引入版本路由与状态机) 2026-04-14 08:00:40 +00:00
hotyue
42a128fd6b feat: 🚩 建立云端版本锚点 v3.4.0 2026-04-14 08:00:32 +00:00
hotyue
a891f2017a fix(core): 🚑 替换节点命名连接符为中划线,彻底修复 Telegram Markdown V1 解析崩溃 Bug 2026-04-14 06:58:00 +00:00
hotyue
66fdfb1908 fix(install): 🐛 修复热更新节点失联问题,引入静默兼容基因锁 2026-04-14 06:44:17 +00:00
hotyue
aa2874fdcd chore(master): ⬆️ 对齐主控端安装脚本头部版本号 2026-04-14 06:18:12 +00:00
hotyue
120dd264c2 feat(master): 扩充全球战区国旗字典,完美适配无界战区版图的 UI 渲染 2026-04-14 06:17:24 +00:00
hotyue
455f98fafd fix(report): 🐛 同步防撞甲逻辑,确保每日战报身份代号与初始注册绝对统一 (v3.3.2) 2026-04-14 06:17:20 +00:00
hotyue
2c1041ebed fix(install): 🐛 引入 IP 指纹哈希防撞机制,粉碎克隆节点同名覆盖 Bug (v3.3.2) 2026-04-14 06:17:15 +00:00
github-actions[bot]
0af3ff5cd8 chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-13] 2026-04-13 19:22:53 +00:00
hotyue
6faa7b2c2a fix(install): 🚑 引入老版本配置无损热迁移装甲,确保 NAT 修复特性在平滑升级中完美生效 2026-04-13 12:10:34 +00:00
hotyue
873b6996ca chore(updater): ⬆️ 对齐脚本头部版本号至 v3.3.1 2026-04-13 12:06:16 +00:00
hotyue
84832395bd fix(daemon): 🔇 引入公网 IP 兜底机制,彻底拦截因 API 探测失败导致的幽灵注册风暴 2026-04-13 12:06:16 +00:00
hotyue
96a7400be8 fix(trust): 🐛 净化模块同步修复哈希种子逻辑,确保活体设备唯一性 2026-04-13 12:06:16 +00:00
hotyue
ba565978c6 fix(google): 🐛 重写哈希种子提取逻辑,彻底杜绝 NAT 节点指纹同质化灾难 2026-04-13 12:06:16 +00:00
hotyue
b53032cc92 fix(report): 🐛 战报 IP 探测接入 PUBLIC_IP 兜底,完美兼容 NAT 架构 2026-04-13 12:06:16 +00:00
hotyue
e96eacd6f8 feat(install): 重构网络锚定逻辑,引入双核身份剥离与双栈 NAT 嗅探 2026-04-13 12:06:16 +00:00
github-actions[bot]
4cac51673a chore(data): 🤖 自动机兵:刷新全战区热点词库 [2026-04-13] 2026-04-13 08:37:41 +00:00
hotyue
be75e5b65c fix(scripts): 🐛 修复地图解析逻辑,深度穿透 JSON 锁定真实战区 2026-04-13 08:37:12 +00:00
hotyue
c7ece6620c chore(test): 故意制造数据缺口,诱导自动机兵修复 2026-04-13 08:30:07 +00:00
hotyue
7e9da4b82a ci(workflows): 🔧 修复 Actions 推送逻辑,适配 main 分支保护规则 2026-04-13 08:27:33 +00:00
hotyue
c657c92b27 docs(readme): 📝 更新特性列表,加入 OTA 动态活体词库与智能错峰调度说明 2026-04-13 08:18:16 +00:00
hotyue
d43163703e chore(master): ⬆️ 对齐主控端版本号至 v3.3.0 2026-04-13 08:18:10 +00:00
hotyue
1150450718 feat(core): 🚀 升级 Agent 安装脚本,注入错峰时间戳与每日调度 Cron 2026-04-13 08:18:05 +00:00
hotyue
df6483afa8 feat(core): 🔄 升级 updater 引入每日词库同步与指纹库 30 天错峰调度 2026-04-13 08:17:58 +00:00
hotyue
29de2eadf8 ci(workflows): 🤖 部署 OTA 动态词库每日自动生成流水线 2026-04-13 08:17:51 +00:00
hotyue
318689f163 feat(scripts): 🐍 新增 Google Trends 动态热搜抓取引擎 2026-04-13 08:17:47 +00:00
hotyue
6b9563b858 fix(deploy): 🐛 [v3.2.3] 修复防火墙提示盲区,支持根据 IPv4/IPv6 动态下发 iptables/ip6tables 放行指令 2026-04-13 03:32:41 +00:00
hotyue
2c7491449c docs: 📝 [v3.2.2] 更新 README,补充平滑热更新与多级容灾特性说明 2026-04-13 01:52:56 +00:00
hotyue
f698bc4b92 feat(deploy): 🚀 [v3.2.2] 引入全系平滑热更新引擎,支持 Agent 与 Master 状态机嗅探及无损覆盖安装 2026-04-13 01:43:03 +00:00
hotyue
c18a10dbd5 feat(core): 🚀 [v3.2.2] 重构 tg_report 多级容灾探针,植入底层协议自适应,并按共识原则清洗 AS 号 2026-04-13 00:51:49 +00:00
hotyue
69e7803c40 fix(core): 🚀 [v3.2.1] 植入双栈协议自适应逻辑修复 curl 绑定冲突,扩容 Trust 模块状态码容错区间 2026-04-12 13:51:11 +00:00
hotyue
b2a5afe562 feat(core): 🚀 升级 v3.2.2 高精度容错探针 (处理断网误判),并优化 .com 免签节点的战报显示 2026-04-12 13:21:16 +00:00
hotyue
45fda5f498 docs: 📝 更新 README.md,补充 v3.2.x 核心极客特性与存量节点升级指引 2026-04-12 12:19:35 +00:00
hotyue
1459d5efec docs: 📝 更新 README.md,补充 v3.2.x 核心极客特性与存量节点升级指引 2026-04-12 12:18:40 +00:00
hotyue
b7375e5e7d docs: 📝 更新 README.md,补充 v3.2.x 核心极客特性与存量节点升级指引 2026-04-12 12:16:28 +00:00
hotyue
4a7f88a0da docs: 📝 更新 README.md,补充 v3.2.x 核心极客特性与存量节点升级指引 2026-04-12 12:11:03 +00:00
hotyue
a0ec759dd7 fix(core): 🚑 紧急修复 v3.2.1 注入 --interface 参数强制锚定底层物理出口 IP 2026-04-12 06:57:03 +00:00
hotyue
fe1e4c0e6f feat(core): 🚀 升级 v3.1.5 引入哈希锚定法,实现边缘节点设备资产持久化 2026-04-12 06:01:33 +00:00
github-actions[bot]
62770ba50c chore(data): 🤖 自动机兵:刷新 4000 条绝对坐标指纹库 2026-04-12 05:52:11 +00:00
hotyue
11bdece9e2 feat: 部署 v3.1.5 自动化指纹兵工厂 2026-04-12 05:46:02 +00:00
hotyue
2c5df879c0 chore(data): 扩充并升级 UA 设备指纹池,提升网络拟真度与风控防御等级 2026-04-12 05:17:30 +00:00
hotyue
862de2e49e feat(core/runner): 引入 TTY 交互式终端探测,人工调试时自动跳过防并发休眠 (Jitter) 2026-04-12 04:37:05 +00:00
hotyue
26e3fd435d chore(core/uninstall): 升级无痕焦土卸载策略,引入 pkill 语法并彻底抹除 /tmp 系统缓存碎屑 2026-04-12 04:36:52 +00:00
hotyue
e279fc6e38 fix(core/updater): 重构 OTA 静默更新逻辑,引入 find 拓扑自适应拉取,并根除私库死链 2026-04-12 04:36:41 +00:00
hotyue
acff304a35 fix(core/daemon): 剥离全局统筹路由,修复单模块节点无法响应 /trigger_run 一键维护的逻辑死角 2026-04-12 04:18:16 +00:00
hotyue
9fe39fc274 fix(core/trust): 适配多级大区拓扑 (find 穿透抓取),修复私库直链死角,并恢复终端双向日志输出 2026-04-12 04:18:09 +00:00
hotyue
9eccace3bc fix(core/google): 修复多区域判定逻辑,兼容 Google 欧洲区无跳转新规,并解除香港节点误判 2026-04-12 03:44:10 +00:00
hotyue
cf410fce61 docs: 增加 Legacy 战区引导说明,收编 Debian 9 老旧节点 2026-04-11 13:56:28 +00:00
hotyue
0ffb173bb5 docs: 增加 Legacy 战区引导说明,收编 Debian 9 老旧节点 2026-04-11 13:55:08 +00:00
hotyue
edd6425fe5 docs: 修正内容 2026-04-11 13:42:57 +00:00
hotyue
16b6c3f20a feat(core/daemon): 适配 V3.1.3 协议,IP变动或重连时自动上报大区坐标 2026-04-11 11:51:24 +00:00
hotyue
e3750f4565 feat(core/install): 适配 V3.1.3 协议,新节点注册暗号自动注入国家大区 (REGION_CODE) 2026-04-11 11:51:19 +00:00
hotyue
d3face9621 feat(master): V3.1.3 面板重构,新增大区多级折叠目录与双列排版,平滑升级 DB 协议 2026-04-11 11:51:14 +00:00
hotyue
aeeb9e1a43 docs: 完善 README 文档,新增玻璃房透明遥测、丝滑交互特性说明及完整拓扑架构 2026-04-11 11:27:40 +00:00
hotyue
09c6bab04a fix(master): 收敛 offset 记录文件至私有目录,修复 /tmp 侧信道劫持隐患 2026-04-11 11:24:13 +00:00
hotyue
2e73aa8833 feat(data): 新增美西核心节点 - 加州圣何塞 (San Jose) LBS 与专属配置 2026-04-11 11:21:57 +00:00
hotyue
03d88f4856 feat(master): 优化 TG 交互体验,哨兵节点注册成功后自动呼出最新活跃节点面板 2026-04-11 08:15:16 +00:00
hotyue
3cab2b2379 chore(core): 将官方公共机器人安全网关 API 从测试环境切换为正式生产环境 2026-04-11 07:55:30 +00:00
hotyue
87faeae8f7 fix(core): 修复首次安装时 agent_daemon 抢跑导致的重复注册推送问题 2026-04-11 07:33:44 +00:00
hotyue
19f0bb7c36 docs: 全面刷新 README 文档,点亮 v3.1.2 透明装机量徽章并重写核心极客特性 2026-04-11 07:12:48 +00:00
hotyue
01305f98b5 feat(master): Master 脚本接入透明统计,并新增部署前旧进程自洁功能 2026-04-11 07:08:21 +00:00
hotyue
a3ae3b29f9 feat(core): Agent 安装脚本接入透明统计,安装尾声展示全球哨兵编号 2026-04-11 07:08:13 +00:00
hotyue
053c9805d4 feat(telemetry): 开源玻璃房计划 (Glasshouse) Cloudflare Worker 计数器源码 2026-04-11 07:08:05 +00:00
hotyue
be51aab0e0 feat(core): 升级全球节点拓扑图接入香港阵地,正式发布 v3.1.1 2026-04-11 05:32:03 +00:00
hotyue
426fa74ff1 feat(data): 新增亚太核心枢纽 中国香港(HK) 节点配置文件与本土化搜索词库 2026-04-11 05:31:56 +00:00
hotyue
9904246e45 feat(core): 优化 Agent 安装逻辑,新增部署前环境自洁功能 (自动清理僵尸进程与冗余定时任务) 2026-04-11 05:31:52 +00:00
hotyue
06f52cbe1d feat(core): 升级全球节点拓扑图,正式跃升至 v3.1.0 2026-04-11 02:38:27 +00:00
hotyue
33d75925a6 feat(data): 新增亚太枢纽 新加坡 节点配置文件与本土化搜索词库 2026-04-11 02:38:25 +00:00
hotyue
52fe92efe5 feat(data): 新增欧洲枢纽 法国(巴黎) 节点配置文件与本土化搜索词库 2026-04-11 02:38:25 +00:00
hotyue
7fec21280f feat(data): 新增欧洲枢纽 德国(法兰克福) 节点配置文件与本土化搜索词库 2026-04-11 02:38:25 +00:00
hotyue
84b5fef640 feat(data): 新增欧洲枢纽 英国(伦敦) 节点配置文件与本土化搜索词库 2026-04-11 02:38:25 +00:00
hotyue
9d2aa9fcd5 fix(agent): 提拔 urllib 依赖至全局作用域,修复局部变量遮蔽导致的 Webhook 空回复崩溃 bug (v3.0.4-hotfix) 2026-04-11 02:23:52 +00:00
hotyue
ca2608756d security(core): 引入时间戳与动态 HMAC-SHA256 签名,彻底斩断明文 PSK 泄露与重放攻击隐患 (v3.0.4) 2026-04-11 01:51:03 +00:00
hotyue
27ebcfd418 security(agent): Webhook 引入 ThreadingMixIn 升级为多线程并发模型,彻底免疫 Slowloris 慢速网络耗尽攻击 (v3.0.3-part4) 2026-04-11 00:34:53 +00:00
hotyue
62deadda1e security(master): 部署脚本新增配置文件与数据库权限收敛 (chmod 600),防止 Bot Token 与节点网络拓扑泄露 (v3.0.3-part3) 2026-04-11 00:30:58 +00:00
hotyue
990d60f63a security(agent): 部署脚本新增配置文件权限收敛 (chmod 600),防止敏感 Token 发生本地提权泄露 (v3.0.3-part2) 2026-04-11 00:28:22 +00:00
hotyue
0571fcfd32 feat(install): 引入随机高位端口探测与占用校验,配合本地防火墙智能放行指引,提升防扫描隐蔽性 (v3.0.3-part1) 2026-04-11 00:12:12 +00:00
hotyue
4a77cb66d4 fix(agent): 引入 HTML 转义与 UA 伪装,修复日志回传中的 Markdown 解析冲突 (v3.0.2-final) 2026-04-10 16:25:04 +00:00
hotyue
26fdb8f899 security(agent): 纯 Python 重构彻底消除 Bash RCE 隐患,引入全局鉴权拦截未授权扫描与 DDoS (v3.0.2) 2026-04-10 16:03:31 +00:00
hotyue
5635c5d851 security(master): 构筑 SSRF 内网物理隔离墙,并为全网广播追加 PSK 鉴权令牌 (v3.0.2) 2026-04-10 16:03:24 +00:00
hotyue
00ec07b88a security(master): 修复高危 SQL 注入漏洞,重构回调交互消除面板延迟与刷屏 (v3.0.1) 2026-04-10 14:49:06 +00:00
hotyue
ef84979f91 feat(master): 司令部交互重构,新增 answerCallbackQuery 消除延迟并实现菜单原位无痕刷新 (v3.0.1) 2026-04-10 14:28:25 +00:00
hotyue
d63df0c48e fix(trust): 净化流量全面适配 IPv6 隧道,杜绝系统默认路由导致的锚点偏移 (v3.0.1) 2026-04-10 14:13:02 +00:00
hotyue
002e5f304d fix(google): 剥离冗余 IP 探测,强制全局 curl 请求遵循 IP_PREF 锚点协议出网 (v3.0.1) 2026-04-10 14:12:57 +00:00
hotyue
4bfe9ea9ca fix(report): 增加 ISP 探针多节点容灾逻辑,API 阻断时强制回退使用锚点 IP (v3.0.1) 2026-04-10 14:12:53 +00:00
hotyue
b7988dc666 fix(install): 引入多节点雷达容灾机制,新增双栈 IP 动态数组交互菜单 (v3.0.1) 2026-04-10 14:12:49 +00:00
hotyue
5463372b66 fix(report): 战报与 ISP 探针强制使用锚点协议出口,完善 IPv6 自动化方括号包裹展示 2026-04-10 13:30:47 +00:00
hotyue
85525580c6 fix(daemon): 同步锁定网络协议防重复发报,重构 Python Webhook 支持双栈及纯 IPv6 监听 2026-04-10 13:30:42 +00:00
hotyue
c1cfdb17f3 fix(install): 增加双栈网络探测与交互式 IP 锚点锁定机制,彻底修复 IPv6 格式化拼接报错问题 2026-04-10 13:30:36 +00:00
hotyue
f8b4777ed8 feat(master): 新增 Master 中枢一键卸载功能及安装脚本交互菜单 2026-04-10 12:50:53 +00:00
hotyue
f7bbfe9010 feat(master): 新增 Master 中枢一键卸载功能及安装脚本交互菜单 2026-04-10 12:42:28 +00:00
hotyue
690aa2c189 chore: 切回官方源,准备发布 v3.0.0 2026-04-10 08:59:35 +00:00
hotyue
989db0b49b fix(core): 修正 install.sh 注册暗号分隔符与主机名变量,确保 Master 准确解析 2026-04-10 08:53:16 +00:00
hotyue
90fc8adb74 feat(security): 启用 Cloudflare 安全网关,全面重构节点发报链路,彻底消除明文 Token 隐患 2026-04-10 08:40:45 +00:00
hotyue
1b7d7e7b64 docs: 完善 v3.0.0 (Global Nexus) 架构说明与全球节点文档 2026-04-10 07:32:41 +00:00
hotyue
472ead88b0 feat(core): install.sh 核心重构,引入基于 jq 的动态地图解析引擎 2026-04-10 07:29:17 +00:00
hotyue
cb788ab730 refactor(data): 升级至 v3.0 多级拓扑目录并引入 map.json 全球索引 2026-04-10 07:28:43 +00:00
hotyue
3730bd638a feat: 升级至 v2.1.0,引入官方机器人公共中枢模式并优化 README 2026-04-10 05:57:23 +00:00
hotyue
7e9da94881 feat: 升级 install.sh 至 v2.1.0,支持官方机器人一键接入与自动注册推送 2026-04-10 05:43:49 +00:00
hotyue
f023707809 docs: 在 README 中将地址迁移回github官方 2026-04-10 03:16:59 +00:00
hotyue
2160ec4f29 Merge branch 'main' of https://github.com/hotyue/IP-Sentinel 2026-04-03 03:34:18 +00:00
hotyue
2965408c3d Initial commit 2026-04-03 11:25:40 +08:00
hotyue
30132f34b2 docs: 在 README 中植入 TG 交流频道链接并优化 V2.0 架构说明 2026-04-03 02:42:44 +00:00
hotyue
c34f53591c docs: 在 README 中植入 TG 交流频道链接并优化 V2.0 架构说明 2026-04-03 02:40:58 +00:00
hotyue
47c11b76f4 fix(rules): 修正日本区域 Google 后缀规则,适配谷歌全球同域路由策略,消除假阳性警告 2026-04-02 13:16:25 +00:00
hotyue
d1b5e9df81 refactor(report): 战报模块深度重构,支持动态读取功能开关,实现 Google/Trust 数据解耦与自适应排版 2026-04-02 09:57:42 +00:00
hotyue
ef06dc1fc3 fix(uninstall): 补齐 V2.0 架构遗漏进程,彻底清除 webhook、agent_daemon、mod_trust 等衍生驻留进程 2026-04-02 09:54:25 +00:00
hotyue
c30f34aea6 chore: 统一为所有 Shell 脚本配置 Git 可执行权限 (mode 100755) 2026-04-02 09:27:55 +00:00
hotyue
b5bb178708 feat(master): TG 面板深度适配多模块,拆分独立控制按钮 (Google/Trust),并新增对节点 403 拒绝状态的拦截警告 2026-04-02 09:18:46 +00:00
hotyue
aebf70ea3b feat(daemon): Webhook 升级独立路由分发,引入文件探针校验,对未安装模块精准实施 HTTP 403 权限拦截 2026-04-02 09:18:42 +00:00
hotyue
7deee7a764 refactor(runner): 升级为主控调度引擎,新增智能轮盘算法 (70% Google / 30% Trust) 与开关判定,彻底杜绝小鸡 OOM 2026-04-02 09:18:37 +00:00
hotyue
9681bc16b5 feat(install): 引入模块化按需加载 (Feature Flag),支持交互式选择开启 Google 纠偏或 IP 信用净化,实现极简按需下载 2026-04-02 09:18:33 +00:00
hotyue
14f0f792b2 feat: 新增 mod_trust 信用净化模块及重构云端区域 JSON 规则库 2026-04-02 09:05:49 +00:00
hotyue
b881db6b62 fix: 修复获取公网 IP 时附带换行符导致节点重启后重复触发注册申请的 Bug 2026-04-01 13:53:32 +00:00
hotyue
e584a2a0c3 feat: V1.2.1 增加 [全节点日报汇总] 批量指令分发功能 2026-04-01 13:45:04 +00:00
70 changed files with 12626 additions and 450 deletions

52
.github/workflows/daily_keywords.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Daily Data Factory
on:
schedule:
# 每天 UTC 18:00 (北京时间凌晨 02:00) 执行赶在节点凌晨3点更新前造好子弹
- cron: '0 18 * * *'
workflow_dispatch:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: write
jobs:
update-data:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Execute Trends Engine (搜索词库)
run: python scripts/fetch_trends.py
- name: Execute Trust URL Engine (活体新闻流融合)
run: python scripts/fetch_trust_urls.py
- name: Commit and Push All Data
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
# 一揽子添加搜索词库和地区白名单的变化
git add data/keywords/
git add data/regions/
# 防御机制:如果没有新数据,就静默退出,不产生空提交
if git diff --staged --quiet; then
echo "No changes, skipping."
exit 0
fi
# 策略:将两路数据的更新合并为一个原子提交
git commit -m "chore(data): 🤖 自动机兵:同步全战区热点词库与活体新闻流 [$(date +'%Y-%m-%d')]"
git push origin main

33
.github/workflows/ua_factory.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Automated Massive UA Factory
on:
schedule:
# 每个月 1 号凌晨 00:00 执行
- cron: '0 0 1 * *'
workflow_dispatch: # 允许手动点击运行
jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: write # 必须赋予写入权限,否则无法更新仓库文件
steps:
- name: 📥 Checkout Repository
uses: actions/checkout@v4
- name: ⚙️ Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: 🚀 Run UA Factory Generator
run: python scripts/ua_generator.py
- name: 📤 Commit and Push to Main
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add data/user_agents.txt
# 只有在文件内容确实发生变化时才执行提交
git diff --quiet && git diff --staged --quiet || (git commit -m "chore(data): 🤖 自动机兵:刷新 4000 条绝对坐标指纹库" && git push)

661
LICENSE
View File

@@ -0,0 +1,661 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.

151
README.md
View File

@@ -1,16 +1,32 @@
# 🛡️ IP-Sentinel (分布式 IP 哨兵集群)
![Agent Installs](https://img.shields.io/endpoint?url=https://ip-sentinel-count.samanthaestime296.workers.dev/stats/agent)
![Master Commands](https://img.shields.io/endpoint?url=https://ip-sentinel-count.samanthaestime296.workers.dev/stats/master)
![License](https://img.shields.io/github/license/hotyue/IP-Sentinel)
> **一个极度轻量、零感知、支持中枢遥控的 VPS IP 自动化养护与区域纠偏引擎。**
专为解决 VPS IPv4 被 Google 等数据库错误定位到中国大陆/香港俗称“送中”等问题而生。IP-Sentinel 已从单机脚本全面跃升为 **Master-Agent 分布式架构**。它像影子一样潜伏在全球各地的服务器后台,通过高度拟真的真实用户行为为你默默积累 IP 权重,并允许你通过 Telegram 随时随地对整个舰队进行毫秒级“点名”与“遥控”。
📢 官方战术交流频道: 🛰️ [IP-Sentinel Matrix](https://t.me/IP_Sentinel_Matrix)
## ✨ 核心极客特性
专为解决 VPS IP 被 Google 等数据库错误定位到中国大陆/香港俗称“送中”等问题而生。IP-Sentinel 已从单机脚本全面跃升为 **Master-Agent 分布式架构**。它像影子一样潜伏在全球各地的服务器后台,通过高度拟真的真实用户行为为你默默积累 IP 权重,并允许你通过 Telegram 随时随地对整个舰队进行毫秒级“点名”与“遥控”。
* 🧠 **分布式中枢 (Master-Agent)**:彻底解决多台 VPS 的管理痛点。一台 Master 主控集成 SQLite 数据库与 Telegram 机器人,统管无数台 Agent 边缘节点,告别 API 消息冲突。
* 🎮 **TG 战术面板 (Command Center)**:无需记忆繁琐命令,原生 Inline Keyboard 按钮驱动。支持一键调出节点列表、一键下发伪装指令、一键索要精准战报、**毫秒级抓取实时运行日志**。
* 🛡️ **NAT 穿透与安全网关 (NAT-Friendly)**:边缘节点采用 Python3 极轻量 Webhook 监听,**完全自定义通信端口**,完美支持受限 NAT 小鸡。独创 TG 转发授权机制,杜绝野生节点恶意接入
* 👻 **高仿真人类行为 (Human-Like)**:摒弃死板的 Ping/Curl引入单次会话指纹锁定、10 米级 GPS 坐标微抖动、以及 60~150 秒的真实阅读停顿拉伸,完美避开 AI 封控
* 📡 **OTA 静默进化 (Smart Updates)**:系统每周日凌晨自动从云端拉取最新的“热搜词汇”和“真实设备指纹池”,确保养护行为与时俱进、永不过时
## ✨ 核心极客特性 (Core Architecture)
- 📊 **深海声呐全维探针 (Deep Sea Sonar v4.0)**:内嵌强效正则清洗的 JSON 提取引擎,异步生成情报级 IP 质量战报。聚合 Scamalytics、AbuseIPDB 等五大权威防欺诈库,精准嗅探代理/VPN特征、25端口封堵情况及原生流媒体Netflix/Disney+/TikTok等解锁状态并自带 Google “送中”高危预警与基于 SQLite 的历史污染趋势追踪图谱
- **无损高并发引擎 (WAL Concurrency)**:司令部 SQLite 数据库全面激活 `WAL` (Write-Ahead Logging) 模式与毫秒级排队削峰算法。即使您同时对 500 台边缘节点发起全军总攻,也能完美规避 `database is locked` 与 Telegram `429` 频率拦截,实现 100% 战报送达
- 🪶 **抽脂级极简部署 (Zero-Bloat Native)**:全栈剔除 `pip``flask` 等臃肿第三方依赖,完全基于 Python3 原生标准库运行。安装底层强制注入 `--no-install-recommends` 防捆绑参数。无论是 128MB 内存的极简 NAT 小鸡,还是 Alpine/Arch Linux 特种系统,均可如丝般顺滑运行
- 🎛️ **扁平化指挥矩阵 (Flat Command Matrix)**[v3.6.1 重构] 引入扁平化 L0-L3 四级战区降维视图与双轨身份制。深度定制 Inline Keyboard 逃生舱交互,支持在统一哨兵终端进行原位丝滑重绘 (In-place UI Edit),实现毫秒级模块热启停与日志抓取,彻底告别刷屏烦恼。
- 🔄 **全栈零信任 OTA 引擎 (Zero-Trust OTA Upgrade)**:首创双端物理熔断机制。长官可通过私有中枢,一键向全舰队下发静默热重载指令;更支持**「司令部金蝉脱壳」**,中枢大脑可在此面板自我抛出幽灵进程进行免交互直装覆盖,实现真正的全栈去 SSH 化运维。
- 🛡️ **SSOT 溯源与热更新装甲 (Smooth Upgrade Engine)**:全系脚本彻底消灭硬编码,部署时动态抓取云端版本信标。自带状态机嗅探逻辑与防撞甲探测,即使是手动在终端运行安装,也仅需回车瞬间完成配置继承、数据同步与无损换代。
- 🗺️ **全球拓扑矩阵与活体词库 (Global Nexus)**:守护版图横跨亚欧美三大洲。接入 GitHub Actions 云端流水线,每日静默同步全球各大区当日 Google 真实热搜榜单与高权重本土站点,让伪装行为永远贴合当地网络脉搏。
- 👻 **资产持久化与错峰调度 (Hash-Seeded Persona)**:摒弃随机抽取指纹,基于节点物理 IP 哈希永久锁定 3 个绝对专属设备,完美构建高权重真实家庭内网画像。叠加按需智能分频与随机防并发休眠,化解“惊群效应”。
- 🖧 **底层路由死锁与高精度探针 (Hard-Bind Routing)**:底层探测引擎强力接管 curl 核心参数 (`--interface`),将发出的每一滴伪装流量死死绑定在物理网卡或隧道 IP 上。配合多级 ISP 容灾链路,彻底杜绝双栈环境下的流量溢出与 API 误判。
**—— 💎 骨干基建特征 ——**
- 🏭 **自动化指纹兵工厂**:依托 GitHub Actions CI/CD 流水线,每月 1 日无人值守锻造 4000+ 带绝对物理分区的真实终端设备数据。
- 🔒 **叹息之墙 (Zero-Trust HMAC)**:底层通讯引入 时间戳 + HMAC-SHA256 军用级动态签名。指令有效期仅 60 秒(阅后即焚),未授权请求直接触发系统级 403 物理熔断,彻底免疫中间人抓包与重放攻击。
- ☁️ **云端中枢 (Public Master)**:官方公共机器人 [@OmniBeacon_bot](https://t.me/OmniBeacon_bot) ,新手免自建,一键接入极速入伍!同时支持硬核极客私有化 SQLite 分布式部署。
- 👁️‍🗨️ **玻璃房透明遥测 (Glasshouse)**:基于 Cloudflare Workers 的全透明计数中枢,绝对零隐私收集,仅作原子累加,底层网关源码全开源。
## 📂 项目架构 (Monorepo)
@@ -18,43 +34,118 @@
```text
📦 IP-Sentinel
┣ 📂 master/ # 🧠 司令部SQLite 存储、TG 监听与 Webhook 调度中心
┣ 📂 core/ # 🛡️ 边缘哨兵Webhook 被动监听、高拟真养护引擎
📂 data/ # 🗂 全球数据规则库
┣ 📂 regions/ # 🧊 冷数据:各地区 GPS 基准配置 (固化)
┣ 📂 keywords/ # 🔥 热数据:动态搜索词库 (OTA 自动更新)
📜 user_agents.txt # 🔥 热数据:全局真实设备指纹池
┣ 📂 .github/workflows/ # 🏭 自动化兵工厂:每月定时触发指纹生成的 CI/CD 流水线
┣ 📂 master/ # 🧠 司令部SQLite 存储 (含 ip_trend_log 趋势跟踪表)、TG 监听与 Webhook 调度
📂 core/ # 🛡 边缘哨兵Webhook 被动监听、哈希锚定执行引擎 (集成深海声呐探测模块)
┣ 📂 scripts/ # 🐍 兵工厂引擎:基于 Python 的多物理分区 UA 生成器
┣ 📂 data/ # 🗂️ 全球数据规则库 (动态拓扑)
📜 map.json # 🌍 全球区域大脑 (v3.5.0 大洲战区拓扑)
┃ ┣ 📂 regions/ # 🧊 冷数据:按 [国家/省州/城市] 深度细分的 LBS 锚点
┃ ┣ 📂 keywords/ # 🔥 热数据:按国家归类的动态搜索词库 (OTA 自动更新)
┃ ┗ 📜 user_agents.txt # 🔥 热数据:由兵工厂每月锻造的绝对坐标专属设备库
┣ 📜 version.txt # 🚩 双端版本信标Agent/Master 独立解耦的 KV 环境配置
┗ 📂 telemetry/ # 👁️‍🗨️ 玻璃房计划Cloudflare Workers 透明计数器网关源码
```
🚀 极速部署 (Quick Start)
请准备一个 Telegram Bot Token 和你的个人 Chat ID。整个集群的部署分为两步
## 🚀 极速部署 (Quick Start)
> 🛡️ **跨平台装甲支持**Debian / Ubuntu / CentOS / RHEL / Alpine Linux / Arch Linux
系统现提供两种接入模式,请根据您的战术需求选择:
第一步:部署中枢司令部 (Master)
找一台网络稳定的 VPS 作为大脑(仅需部署一台),以 root 身份执行:
### 🔹 模式 A私有独立模式 (全自主、强烈推荐)
适合追求绝对数据隐私与舰队最高控制权的领主。
> ☢️ **核按钮系统已就绪**:采用私有部署,您将解锁 **OTA 远程静默升级** 权限!所有私有前线节点均可通过您的 TG 面板实现一键全网代码热重载换代!
- **部署 Master (中枢大脑)**:找一台 VPS 作为司令部(仅需部署一台),执行:
```bash
curl -fsSL https://raw.githubusercontent.com/hotyue/IP-Sentinel/main/master/install_master.sh -o /tmp/ins_master.sh && sudo bash /tmp/ins_master.sh
```
- 部署 Agent (边缘哨兵):在需要养护的机器上执行 Agent 脚本,安装时选择私有独立中枢,并分别输入您自建机器人的 [Token](https://blog.iot-architect.com/engineering-practice/create-private-telegram-bot-via-botfather) 以及您的个人 [Chat ID](https://blog.iot-architect.com/engineering-practice/get-telegram-personal-id-via-userinfobot)
```Bash
bash <(curl -sL https://git.94211762.xyz/hotyue/IP-Sentinel/raw/branch/main/master/install_master.sh)
curl -fsSL https://raw.githubusercontent.com/hotyue/IP-Sentinel/main/core/install.sh -o /tmp/ins_agent.sh && sudo bash /tmp/ins_agent.sh
```
完成后,你的机器人将开始全局接客,等待边缘节点注册
- 激活节点:安装完成后,您的手机会收到一条 #REGISTER# 注册暗号,将其转发给您自己的机器人即可完成编队入库
第二步:部署边缘哨兵 (Agent)
在你需要养护 IP 的无数台目标机器(包括 NAT 机器)上执行:
### 🔸 模式 B官方公共模式 (最简体验)
适合不想折腾、只想快速体验养护效果的新兵。
- 关注机器人:在 TG 中关注官方安全网关 [@OmniBeacon_bot](https://t.me/OmniBeacon_bot) 并发送 /start。
- 部署 Agent在目标 VPS 上执行以下指令,安装过程中选择官方公共网关,并输入您的 Chat ID
```Bash
bash <(curl -sL https://git.94211762.xyz/hotyue/IP-Sentinel/raw/branch/main/core/install.sh)
curl -fsSL https://raw.githubusercontent.com/hotyue/IP-Sentinel/main/core/install.sh -o /tmp/ins_agent.sh && sudo bash /tmp/ins_agent.sh
```
安装时输入与 Master 相同的 Bot Token 及自定义 Webhook 端口。安装完毕后,请在手机 TG 端将生成的 #REGISTER# 暗号转发给机器人,完成安全授权入库!
- 激活节点:同上,将收到的暗号转发给官方机器人即可。
🗑️ 一键无痕卸载
如果你需要清理某个边缘节点,只需重新运行 core/install.sh 并选择 [3],或直接在节点终端执行:
## 🆙 架构级无损热升级指引 (Upgrade Guide)
### 📡 方式一OTA 远程静默升级 (私有中枢专属)
如果您是私有中枢领主,当司令部首页 (`/start`) 或每日战报提示发现新版本时:
1. **升级 Master 司令部自身**:在司令部顶级菜单,点击最上方的 `[ 🆙 升级司令部至 vX.X.X ]`。中枢将释放幽灵进程静默重构,数秒后向您发送捷报。
2. **升级全舰队 Agent**:在司令部顶级菜单,点击 `[ ☢️ 全舰队 OTA 热重载 ]`
3. **升级单节点 Agent**:进入 `🌍 全球战区雷达` -> 选择目标节点 -> 在统一终端面板点击 `[ 🆙 OTA 静默升级 ]`
*(⚠️ 节点收到指令后会在后台挂起静默拉取,全程无需登录 SSH完成后将主动发回心跳确认)*
### 💻 方式二SSH 终端平滑直装 (适用于官方网关或老旧节点)
如果您的节点不支持 OTA或者您的节点版本过于陈旧 (如 v3.3.1)
- 登录该节点的 SSH 终端,再次运行上面的 core/install.sh 官方安装指令。
- 安装引擎自带状态机嗅探逻辑它会自动读取老旧数据您只需一路回车3 秒即可在本地完成配置继承、数据同步与新内核的无损覆盖热重载!
## 🗑️ 一键无痕卸载
如果你需要清理某个边缘节点,只需重新运行 `core/install.sh` 并选择 **[2]**,或直接在节点终端执行:
```Bash
bash /opt/ip_sentinel/core/uninstall.sh
```
🤝 参与贡献
如果你想为项目增加新的节点区域(例如德国、英国、新加坡等),或者提供更丰富的本土化搜索词库,非常欢迎提交 Pull Request
只需在 data/regions/ 新增对应国家的 JSON 规则,并在 data/keywords/ 新增词库 txt 即可。
## 🧓 传家宝老旧系统专用通道 (Debian 9)
⚠️ 免责声明
本项目仅供网络原理研究、个人 VPS 维护学习使用。请遵守当地法律法规及目标服务商的 TOS服务条款切勿用于恶意高频请求或任何非法用途。使用者需自行承担因不当使用造成的 IP 封禁或其他相关风险。
如果你的小鸡系统版本过低(如 Debian 9由于官方 APT 源已关闭且 Python 版本过旧,无法使用主线版本,请使用 **Legacy 兼容分支** 部署。
*(注意:该分支仅作基础维护,不享受新功能迭代,请尽可能升级你的系统)*
```bash
bash <(curl -sL https://raw.githubusercontent.com/hotyue/IP-Sentinel/legacy/core/install.sh)
```
## 📡 战术联络 (Community)
如果你在使用过程中遇到任何疑难杂症,或者想围观大佬们的养护战报,欢迎加入我们的基地:
- Telegram 频道: [@IP_Sentinel_Matrix](https://t.me/IP_Sentinel_Matrix)
## 🤝 参与贡献 (Contributors)
**🌟 感谢以下所有为 IP-Sentinel 添砖加瓦的指挥官们!** 你们的每一次 PR 都在让这艘战舰的全球雷达覆盖得更广。
<a href="https://github.com/hotyue/IP-Sentinel/graphs/contributors">
<img src="https://contrib.rocks/image?repo=hotyue/IP-Sentinel" alt="Contributors" />
</a>
如果你想为项目增加新的节点区域(例如德国、英国、大洋洲等),或者提供更丰富的本土化搜索词库,非常欢迎提交 Pull Request
> - 感谢 @xykt 本项目IP质量检测采用[xykt/IPQuality](https://github.com/xykt/IPQuality) 脚本!
**💡 全球节点贡献规范:**
1.`data/regions/国家代码/省州代码/` 目录下新增对应城市的配置 `.json`
2.`data/keywords/` 目录下新增或完善配套国家的词库 `kw_XX.txt`
3. **最重要的一步:**`data/map.json` 中登记你的国家、省州与城市信息。安装脚本将自动读取地图,在全球雷达中点亮你的节点!
## ⚠️ 免责声明
本项目仅供网络原理研究、个人 VPS 维护学习使用。请遵守当地法律法规及目标服务商的 TOS服务条款切勿用于恶意高频请求或任何非法用途。使用者需自行承担因不当使用造成的 IP 封禁或其他相关风险。
## 保持联系
[![Blog](https://img.shields.io/badge/Blog-个人博客-blue)](https://blog.iot-architect.com)
如果你觉得这个项目对你有帮助,欢迎关注我的个人博客,我会定期分享技术教程。
## Stargazers over time
[![Stargazers over time](https://starchart.cc/hotyue/IP-Sentinel.svg?variant=adaptive)](https://starchart.cc/hotyue/IP-Sentinel)

523
core/agent_daemon.sh Normal file → Executable file
View File

@@ -1,13 +1,13 @@
#!/bin/bash
# ==========================================================
# 脚本名称: agent_daemon.sh (受控节点 Webhook 守护进程 V1.2)
# 核心功能: 智能防打扰注册、进程防冲突自检、后台静默监听
# 脚本名称: agent_daemon.sh (受控节点 Webhook 守护进程 - 动态锚点版)
# 核心功能: 智能防打扰注册、进程自检、模块级路由分发(403拦截)
# ==========================================================
INSTALL_DIR="/opt/ip_sentinel"
CONFIG_FILE="${INSTALL_DIR}/config.conf"
IP_CACHE="${INSTALL_DIR}/core/.last_ip" # 【新增】本地 IP 状态缓存文件
IP_CACHE="${INSTALL_DIR}/core/.last_ip"
[ ! -f "$CONFIG_FILE" ] && exit 1
source "$CONFIG_FILE"
@@ -17,91 +17,514 @@ source "$CONFIG_FILE"
# 默认 Webhook 监听端口
AGENT_PORT=${AGENT_PORT:-9527}
NODE_NAME=$(hostname | cut -c 1-15)
# --- [重点升级 1: 守护进程防冲突自检] ---
# 检查是否已经有 webhook 进程在监听当前端口,如果有,直接安静退出 (Cron 友好)
if pgrep -f "webhook.py $AGENT_PORT" > /dev/null; then
# 保持静默,不输出多余日志,防止打扰系统的 syslog
exit 0
# [v3.5.2 核心] 载入不可变主键与可变展示名 (双轨身份)
if [ -z "$NODE_NAME" ]; then
IP_HASH=$(echo "${PUBLIC_IP:-127.0.0.1}" | md5sum | cut -c 1-4 | tr 'a-z' 'A-Z')
NODE_NAME="$(hostname | tr -cd 'a-zA-Z0-9' | cut -c 1-10)-${IP_HASH}"
fi
NODE_ALIAS="${NODE_ALIAS:-$NODE_NAME}"
# 1. 获取本机原生公网 IPv4
AGENT_IP=$(curl -4 -s -m 5 api.ip.sb/ip)
# 1. 尝试获取实时公网 IP
RAW_IP=$(curl -${IP_PREF:-4} -s -m 5 api.ip.sb/ip | tr -d '[:space:]')
# [v3.3.1 修改] 为新获取到的 v6 自动加方括号;如果网络波动没抓到,强制信任本地 config 中的公网面孔
if [ -n "$RAW_IP" ]; then
if [[ "$RAW_IP" == *":"* ]] && [[ "$RAW_IP" != *"["* ]]; then
AGENT_IP="[${RAW_IP}]"
else
AGENT_IP="$RAW_IP"
fi
else
AGENT_IP="${PUBLIC_IP:-${BIND_IP:-Unknown}}"
fi
if [ -n "$AGENT_IP" ]; then
# --- [重点升级 2: 智能防打扰注册机制] ---
LAST_IP=""
[ -f "$IP_CACHE" ] && LAST_IP=$(cat "$IP_CACHE")
[ -f "$IP_CACHE" ] && LAST_IP=$(cat "$IP_CACHE" | tr -d '[:space:]')
# 只有当这是第一次运行,或者公网 IP 发生变动时,才发送 Telegram 申请
if [ "$AGENT_IP" != "$LAST_IP" ]; then
REG_MSG="👋 **[边缘节点接入申请]**%0A节点: \`${NODE_NAME}\`%0A地址: \`${AGENT_IP}:${AGENT_PORT}\`%0A%0A⚠ **安全验证**: 为防止非法节点接入,请长按复制下方代码,并**发送给我**以完成最终授权录入:%0A%0A\`#REGISTER#|${NODE_NAME}|${AGENT_IP}|${AGENT_PORT}\`"
# [v3.6.0 核心修复] 携带 7 字段身份发起注册申请 (追加 ENABLE_OTA防止 IP 变动重新注册时丢失 OTA 权限)
REG_MSG="👋 **[边缘节点接入申请]**%0A大区: \`${REGION_CODE}\`%0A节点: \`${NODE_ALIAS}\`%0A地址: \`${AGENT_IP}:${AGENT_PORT}\`%0A%0A⚠ **安全验证**: 为防止非法节点接入,请长按复制下方代码,并**发送给我**以完成最终授权录入:%0A%0A\`#REGISTER#|${REGION_CODE}|${NODE_NAME}|${AGENT_IP}|${AGENT_PORT}|${NODE_ALIAS}|${ENABLE_OTA:-false}\`"
curl -s -m 5 -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
curl -s -m 5 -X POST "${TG_API_URL}" \
-d "chat_id=${CHAT_ID}" \
-d "text=${REG_MSG}" \
-d "parse_mode=Markdown" > /dev/null
echo "✅ [Agent] 已向司令部发送接入申请,请在 Telegram 手机端完成授权!"
# 记录当前 IP 到缓存文件
echo "$AGENT_IP" > "$IP_CACHE"
else
echo " [Agent] IP 未变动 ($AGENT_IP),跳过重复注册申请。"
fi
fi
# 3. 启动轻量级 Python3 Webhook 监听服务
# ================== [v3.6.3 新增: 自动生成自签名 TLS 加密证书] ==================
# [修复] 彻底废除官方网关免 TLS 的裸奔逻辑,全网强制生成证书装甲
CERT_FILE="${INSTALL_DIR}/core/cert.pem"
KEY_FILE="${INSTALL_DIR}/core/key.pem"
if [ ! -f "$CERT_FILE" ] || [ ! -f "$KEY_FILE" ]; then
echo "🔐 [Agent] 正在生成本地自签名 TLS 加密证书 (2048位 RSA)..."
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout "$KEY_FILE" -out "$CERT_FILE" \
-subj "/C=US/O=IP-Sentinel/CN=Agent-Sec" >/dev/null 2>&1 || true
fi
# ==============================================================================
# 3. 启动轻量级 Python3 Webhook 监听服务 (v3.0.4 动态 HMAC 签名防重放)
cat > "${INSTALL_DIR}/core/webhook.py" << 'EOF'
import http.server
import socketserver
import subprocess
import sys
import os
import html
# ================== [v3.0.4 新增密码学与解析依赖] ==================
import urllib.parse
import urllib.request
import hmac
import hashlib
import time
# ====================================================================
PORT = int(sys.argv[1])
# 🛡️ 防重放攻击 (Nonce 缓存池)
USED_SIGNS = {}
def clean_used_signs():
now = time.time()
# 清理过期签名 (超 60 秒的安全窗口)
expired = [s for s, t in USED_SIGNS.items() if now - t > 65]
for s in expired:
del USED_SIGNS[s]
# 🛡️ 提取全局鉴权 Token (利用 CHAT_ID 作为 PSK 预共享密钥)
AUTH_TOKEN = ""
if os.path.exists('/opt/ip_sentinel/config.conf'):
with open('/opt/ip_sentinel/config.conf', 'r') as f:
for line in f:
line = line.strip()
if line.startswith('CHAT_ID='):
AUTH_TOKEN = line.split('=', 1)[1].strip('"\'')
break
class AgentHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
# 统一返回成功,防止 Master 请求超时阻塞
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Agent Received Action\n")
# 🛡️ [v3.0.4 核心] URL 解析与动态 HMAC-SHA256 签名校验
parsed = urllib.parse.urlparse(self.path)
req_path = parsed.path
# 路由分发
if self.path == '/trigger_run':
subprocess.Popen(['bash', '/opt/ip_sentinel/core/mod_google.sh'])
elif self.path == '/trigger_report':
subprocess.Popen(['bash', '/opt/ip_sentinel/core/tg_report.sh'])
elif self.path == '/trigger_log':
bash_cmd = """
source /opt/ip_sentinel/config.conf
LOG_DATA=$(tail -n 15 /opt/ip_sentinel/logs/sentinel.log)
NODE=$(hostname | cut -c 1-15)
curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=📄 **[${NODE}] 实时运行日志:**%0A\`\`\`log%0A${LOG_DATA}%0A\`\`\`" \
-d "parse_mode=Markdown"
"""
subprocess.Popen(['bash', '-c', bash_cmd])
if AUTH_TOKEN:
query = urllib.parse.parse_qs(parsed.query)
req_t = query.get('t', [''])[0]
req_sign = query.get('sign', [''])[0]
# 校验 1参数是否齐全
if not req_t or not req_sign:
self.send_response(401)
self.end_headers()
self.wfile.write(b"401 Unauthorized: Missing Signature\n")
return
try:
current_time = int(time.time())
# 校验 2时间戳防重放 (误差 ±60秒 内有效,拒绝隔夜抓包重放)
if abs(current_time - int(req_t)) > 60:
self.send_response(401)
self.end_headers()
self.wfile.write(b"401 Unauthorized: Request Expired\n")
return
except ValueError:
self.send_response(401)
self.end_headers()
return
# 校验 2.5:基于 60秒 窗口的精确重放拦截 (拦截 MITM 并发洗劫)
clean_used_signs()
if req_sign in USED_SIGNS:
self.send_response(401)
self.end_headers()
self.wfile.write(b"401 Unauthorized: Replay Attack Detected\n")
return
# 校验 3HMAC 数据完整性与身份合法性校验
msg = f"{req_path}:{req_t}".encode('utf-8')
expected_sign = hmac.new(AUTH_TOKEN.encode('utf-8'), msg, hashlib.sha256).hexdigest()
# 使用 compare_digest 防御时序攻击
if not hmac.compare_digest(expected_sign, req_sign):
self.send_response(401)
self.end_headers()
self.wfile.write(b"401 Unauthorized: Signature Mismatch\n")
return
# 鉴权通过,记录该签名至防重放内存池
USED_SIGNS[req_sign] = current_time
# ================== 路由分发 (恢复为安全的精确匹配) ==================
# 路由 0: 全局统筹调度
if req_path == '/trigger_run':
if os.path.exists('/opt/ip_sentinel/core/runner.sh'):
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Action Accepted: runner\n")
os.system("nohup bash /opt/ip_sentinel/core/runner.sh >/dev/null 2>&1 &")
else:
self.send_response(404)
self.end_headers()
# 路由 1: Google 区域纠偏
elif req_path == '/trigger_google':
if os.path.exists('/opt/ip_sentinel/core/mod_google.sh'):
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Action Accepted: mod_google\n")
os.system("nohup bash /opt/ip_sentinel/core/mod_google.sh >/dev/null 2>&1 &")
else:
self.send_response(403)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"403 Forbidden: Google Module Disabled\n")
# 路由 2: IP 信用净化
elif req_path == '/trigger_trust':
if os.path.exists('/opt/ip_sentinel/core/mod_trust.sh'):
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Action Accepted: mod_trust\n")
os.system("nohup bash /opt/ip_sentinel/core/mod_trust.sh >/dev/null 2>&1 &")
else:
self.send_response(403)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"403 Forbidden: Trust Module Disabled\n")
# 路由 3: 触发战报推送
elif req_path == '/trigger_report':
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Action Accepted: tg_report\n")
os.system("nohup bash /opt/ip_sentinel/core/tg_report.sh >/dev/null 2>&1 &")
# 路由 4: 抓取并回传实时日志
elif req_path == '/trigger_log':
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Action Accepted: fetch_log\n")
try:
config = {}
if os.path.exists('/opt/ip_sentinel/config.conf'):
with open('/opt/ip_sentinel/config.conf', 'r') as f:
for line in f:
line = line.strip()
if '=' in line and not line.startswith('#'):
key, val = line.split('=', 1)
config[key] = val.strip('"\'')
log_data = "日志文件不存在或为空"
log_path = '/opt/ip_sentinel/logs/sentinel.log'
if os.path.exists(log_path):
with open(log_path, 'r', errors='ignore') as f:
lines = f.readlines()
if lines:
log_data = html.escape("".join(lines[-15:]))
# [v3.5.2 核心] 获取版本与节点展示别名
local_ver = config.get('AGENT_VERSION', '未知')
node_alias = config.get('NODE_ALIAS', config.get('NODE_NAME', 'Unknown-Node'))
text_msg = f"📄 <b>[{node_alias}] 实时日志 (v{local_ver}):</b>\n<pre><code>{log_data}</code></pre>"
# [v4.0.3 体验升级] 引入 json 模块并改用 JSON Payload挂载返回控制台按钮
import json
node_name_cb = config.get('NODE_NAME', 'Unknown')
payload = {
'chat_id': config.get('CHAT_ID', ''),
'text': text_msg,
'parse_mode': 'HTML',
'reply_markup': {
'inline_keyboard': [[{'text': '⚙️ 调出该节点控制台', 'callback_data': f'manage:{node_name_cb}'}]]
}
}
data = json.dumps(payload).encode('utf-8')
req = urllib.request.Request(
config.get('TG_API_URL', ''),
data=data,
# [动态化] 彻底消灭硬编码,使用运行态版本号,并声明 JSON 头
headers={
'User-Agent': f'IP-Sentinel-Agent/{local_ver}',
'Content-Type': 'application/json'
}
)
urllib.request.urlopen(req, timeout=10)
except Exception as e:
print(f"Log transmission failed: {e}")
# ================== [v4.0.0 新增: 触发深海声呐] ==================
elif req_path == '/trigger_quality':
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Action Accepted: trigger_quality\n")
if os.path.exists('/opt/ip_sentinel/core/mod_quality.sh'):
os.system("nohup bash /opt/ip_sentinel/core/mod_quality.sh >/dev/null 2>&1 &")
# =================================================================
# 路由 5: 节点重命名展示别名同步接口 (Base64 终极防御版)
elif req_path == '/trigger_rename':
b64_alias = query.get('b64', [''])[0]
if not b64_alias:
self.send_response(400)
self.end_headers()
self.wfile.write(b"400 Bad Request: Alias is empty\n")
return
import re
import base64
try:
# 1. 还原 URL 安全的 Base64 字符并解码 (杜绝乱码与 WAF 拦截)
pad = len(b64_alias) % 4
if pad > 0:
b64_alias += '=' * (4 - pad)
b64_alias = b64_alias.replace('-', '+').replace('_', '/')
raw_alias = base64.b64decode(b64_alias).decode('utf-8', errors='ignore')
# 2. 强清洗:杜绝 TG Markdown 崩溃严格限制中英数最大20字符
decoded_alias = raw_alias.replace('_', '-')
safe_alias = re.sub(r'[^a-zA-Z0-9\-\u4e00-\u9fa5]', '', decoded_alias)[:20]
if safe_alias:
# 3. 强容错读写 config.conf (引入 fcntl 排他锁与 r+ 模式防并发清空)
config_path = '/opt/ip_sentinel/config.conf'
import fcntl
with open(config_path, 'r+', encoding='utf-8', errors='ignore') as f:
fcntl.flock(f, fcntl.LOCK_EX)
lines = f.readlines()
alias_found = False
for i, line in enumerate(lines):
if line.startswith('NODE_ALIAS='):
lines[i] = f'NODE_ALIAS="{safe_alias}"\n'
alias_found = True
break
if not alias_found:
lines.append(f'NODE_ALIAS="{safe_alias}"\n')
f.seek(0)
f.writelines(lines)
f.truncate()
fcntl.flock(f, fcntl.LOCK_UN)
# [v3.5.2 极致丝滑] 移除向 TG 推送冗余报文的逻辑,直接向 Master 回执成功状态即可
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Action Accepted: trigger_rename\n")
return
except Exception as e:
self.send_response(500)
self.end_headers()
self.wfile.write(f"500 Internal Error: {str(e)}\n".encode('utf-8'))
return
self.send_response(400)
self.end_headers()
self.wfile.write(b"400 Bad Request: Invalid Characters\n")
# ================== [v3.5.3 新增: 模块动态启停接口] ==================
elif req_path == '/trigger_toggle':
mod_name = query.get('mod', [''])[0]
target_state = query.get('state', [''])[0].lower()
if mod_name not in ['google', 'trust'] or target_state not in ['true', 'false']:
self.send_response(400)
self.end_headers()
self.wfile.write(b"400 Bad Request: Invalid parameters\n")
return
config_key = f"ENABLE_{mod_name.upper()}="
try:
config_path = '/opt/ip_sentinel/config.conf'
import fcntl
with open(config_path, 'r+', encoding='utf-8', errors='ignore') as f:
fcntl.flock(f, fcntl.LOCK_EX)
lines = f.readlines()
found = False
for i, line in enumerate(lines):
if line.startswith(config_key):
lines[i] = f'{config_key}"{target_state}"\n'
found = True
break
if not found:
lines.append(f'{config_key}"{target_state}"\n')
f.seek(0)
f.writelines(lines)
f.truncate()
fcntl.flock(f, fcntl.LOCK_UN)
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Action Accepted: trigger_toggle\n")
except Exception as e:
self.send_response(500)
self.end_headers()
self.wfile.write(f"500 Internal Error: {str(e)}\n".encode('utf-8'))
# ================== [v3.6.0 新增: 零信任 OTA 远程静默升级路由] ==================
elif req_path == '/trigger_ota':
try:
# 动态读取最新 config 内存态
config_mem = {}
config_path = '/opt/ip_sentinel/config.conf'
if os.path.exists(config_path):
with open(config_path, 'r', errors='ignore') as f:
for line in f:
line = line.strip()
if '=' in line and not line.startswith('#'):
key, val = line.split('=', 1)
config_mem[key] = val.strip('"\'')
# 🛡️ 熔断校验 1: Agent 本地是否开启了 OTA 授权
if config_mem.get('ENABLE_OTA', 'false').lower() != 'true':
self.send_response(403)
self.end_headers()
self.wfile.write(b"403 Forbidden: OTA Upgrade Disabled locally\n")
return
# 🛡️ 熔断校验 2: 是否处于官方公共网关下 (强行硬编码拦截)
if config_mem.get('TG_TOKEN', '') == 'OFFICIAL_GATEWAY_MODE':
self.send_response(403)
self.end_headers()
self.wfile.write(b"403 Forbidden: OTA strictly disabled under Public Gateway mode\n")
return
# 校验通过,立即返回 200 回执,释放 Master 连接池
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(b"Action Accepted: trigger_ota\n")
# [修复] 逃逸 Systemd Cgroup并引入 bash -n 语法树校验防砖机制
import shutil
import base64
# 动态提取部署时的源地址,废除强制写死 main 分支,保障隔离测试环境
repo_url = "https://raw.githubusercontent.com/hotyue/IP-Sentinel/main"
if os.path.exists('/opt/ip_sentinel/core/install.sh'):
with open('/opt/ip_sentinel/core/install.sh', 'r') as f:
for line in f:
if line.startswith('REPO_RAW_URL='):
repo_url = line.split('=', 1)[1].strip('"\'')
break
# 动态构建报错回执文本 (第一层 Base64 隔离换行与特殊字符)
err_msg = f"❌ **OTA 熔断告警**\n📍 节点: `{config_mem.get('NODE_ALIAS', '未知')}`\n⚠ 原因: 脚本语法校验(bash -n)未通过,下载可能不完整。\n🚀 状态: 升级已取消,节点安全。"
err_msg_b64 = base64.b64encode(err_msg.encode('utf-8')).decode('utf-8')
tg_url = config_mem.get('TG_API_URL', '')
chat_id = config_mem.get('CHAT_ID', '')
# [v3.6.3 究极防御] 采用 Base64 将整个 OTA 执行脚本封装 (第二层隔离)
# 彻底免疫因为 python 变量掺杂引号而导致的 shell 注入或截断
ota_script = f"""
export SILENT_OTA="true"
curl -fsSL {repo_url}/core/install.sh -o /tmp/ota_agent.sh
if bash -n /tmp/ota_agent.sh; then
bash /tmp/ota_agent.sh > /opt/ip_sentinel/logs/ota_upgrade.log 2>&1
else
MSG=$(echo '{err_msg_b64}' | base64 -d)
curl -s -m 10 -X POST "{tg_url}" -d "chat_id={chat_id}" -d "text=$MSG" -d "parse_mode=Markdown" > /dev/null 2>&1
echo "OTA Checksum Failed: Script corrupted" > /opt/ip_sentinel/logs/ota_upgrade.log
fi
"""
ota_script_b64 = base64.b64encode(ota_script.encode('utf-8')).decode('utf-8')
# 安全解包并执行
if shutil.which("systemd-run"):
full_cmd = f"systemd-run --quiet --no-block bash -c \"echo '{ota_script_b64}' | base64 -d | bash\""
else:
full_cmd = f"nohup bash -c \"echo '{ota_script_b64}' | base64 -d | bash\" >/dev/null 2>&1 &"
# 彻底统一为 os.system消灭最后一个可能游离的 Popen 僵尸进程
os.system(full_cmd)
except Exception as e:
self.send_response(500)
self.end_headers()
self.wfile.write(f"500 Internal Error: {str(e)}\n".encode('utf-8'))
else:
self.send_response(404)
self.end_headers()
def log_message(self, format, *args):
# 关闭默认的控制台日志输出,保持后台清爽
pass
import socket
# ================== [v3.0.3 变更: 引入多线程模型抵抗 Slowloris 攻击] ==================
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
allow_reuse_address = True # 开启端口复用,防止热重启时端口冲突
# [核心修复] 显式关闭 V6ONLY 参数,治愈大量云主机纯双栈下的 IPv4 耳聋现象
def server_bind(self):
if self.address_family == socket.AF_INET6:
try:
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
except Exception:
pass
super().server_bind()
try:
with socketserver.TCPServer(("", PORT), AgentHandler) as httpd:
httpd.serve_forever()
# 1. 优先尝试监听双栈/IPv6
ThreadedServer.address_family = socket.AF_INET6
httpd = ThreadedServer(("::", PORT), AgentHandler)
except Exception:
# 2. [核心修复 Issue #23] 若系统内核已禁用 IPv6抛弃报错智能回退至纯 IPv4 监听
ThreadedServer.address_family = socket.AF_INET
httpd = ThreadedServer(("0.0.0.0", PORT), AgentHandler)
# ================== [v3.6.3 核心: 挂载 TLS 加密隧道 (强制装甲版)] ==================
import ssl
cert_path = '/opt/ip_sentinel/core/cert.pem'
key_path = '/opt/ip_sentinel/core/key.pem'
# 全网强制启用 TLS 装甲,彻底消灭 HTTP 裸奔漏洞
if os.path.exists(cert_path) and os.path.exists(key_path):
try:
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile=cert_path, keyfile=key_path)
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
except Exception as e:
print(f"SSL 隧道构建失败,退化为 HTTP: {e}")
# ======================================================================================
try:
httpd.serve_forever()
except Exception as e:
sys.exit(1)
# ====================================================================================
EOF
# --- [重点升级 3: 真正的静默后台启动] ---
echo "🚀 [Agent] 正在后台启动 Webhook 监听服务 (端口: $AGENT_PORT)..."
# 使用 nohup 和 & 将进程完全推入后台,不阻塞当前终端
nohup python3 "${INSTALL_DIR}/core/webhook.py" "$AGENT_PORT" > /dev/null 2>&1 &
# 尝试脱离终端会话控制 (忽略报错以兼容不同 shell 环境)
disown 2>/dev/null || true
echo "✅ [Agent] 守护进程启动完毕,可安全关闭终端。"
# --- [重点升级 3: 移交系统级守护进程接管 (阻塞模式)] ---
echo "🚀 [Agent] 正在启动 Webhook 监听服务 (端口: $AGENT_PORT)..."
exec python3 "${INSTALL_DIR}/core/webhook.py" "$AGENT_PORT"

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
#!/bin/bash
# ==========================================================
# 脚本名称: mod_google.sh (Google 业务逻辑模块)
# 脚本名称: mod_google.sh (Google 业务逻辑模块 - 动态锚点版)
# 核心功能: 执行坐标微抖动、模拟真实阅读时长、会话行为拉伸
# ==========================================================
@@ -16,11 +16,26 @@ else
exit 1
fi
# 容错机制:如果父进程没有传递 log 函数,则本地定义一个作为 fallback
# 容错机制:如果父进程没有传递 log 函数,则本地定义一个作为 fallback (v3.4.0 引入版本探针)
if ! type log >/dev/null 2>&1; then
log() {
# [v3.4.0 核心] 提取当前配置中的版本锚点
local local_ver="${AGENT_VERSION:-未知}"
# 保证日志目录存在
mkdir -p "${INSTALL_DIR}/logs"
printf "[$(date '+%Y-%m-%d %H:%M:%S')] [%-5s] [%-7s] [%s] %s\n" "$2" "$1" "$REGION_CODE" "$3" >> "${INSTALL_DIR}/logs/sentinel.log"
# 日志格式注入 [版本号] 追踪标识
local core_msg=$(printf "[v%-5s] [%-5s] [%-7s] [%s] %s" "$local_ver" "$2" "$1" "$REGION_CODE" "$3")
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $core_msg" >> "${INSTALL_DIR}/logs/sentinel.log"
# 强制推送到 Systemd Journal (如果系统支持)
if command -v logger >/dev/null 2>&1; then
logger -t ip-sentinel "$core_msg"
else
# 降级输出到 stdout让 Systemd 捕获
echo "$core_msg"
fi
}
fi
@@ -48,11 +63,32 @@ get_random_coord() {
}
# --- [环境初始化] ---
# 获取当前出口 IP 仅用于日志记录
CURRENT_V4=$(curl -4 -m 10 -s https://api.ip.sb/ip || echo "获取IP失败")
# [v3.3.1修改] 优先读取对外公网面孔作为哈希种子,兼容 NAT 机的空 BIND_IP
CURRENT_IP="${PUBLIC_IP:-${BIND_IP:-Unknown}}"
# 会话锁定:单次执行内使用固定的浏览器指纹
SESSION_UA=${UA_POOL[$RANDOM % ${#UA_POOL[@]}]}
# -----------------------------------------------------------
# [V3.1.5] 哈希锚定法 (Hash-Seeded Persona)
# 利用 IP 算力固定 3 个永久化专属指纹,破除僵尸网络同质化特征
# -----------------------------------------------------------
TOTAL_UA=${#UA_POOL[@]}
if [ "$TOTAL_UA" -gt 0 ]; then
# 1. 以本地锁定的公网 IP 为种子,计算固定不变的 CRC32 哈希值
SEED=$(echo -n "$CURRENT_IP" | cksum | awk '{print $1}')
# 2. 利用确定的种子和质数乘数,在全球 4000 的库中计算出本机的 3 个绝对专属坐标
IDX1=$(( SEED % TOTAL_UA ))
IDX2=$(( (SEED * 17) % TOTAL_UA ))
IDX3=$(( (SEED * 31) % TOTAL_UA ))
# 3. 将绝对坐标映射为该节点的“专属设备库”
MY_UA_POOL=("${UA_POOL[$IDX1]}" "${UA_POOL[$IDX2]}" "${UA_POOL[$IDX3]}")
# 4. 本次会话从这 3 台专属设备中随机挑选 1 台进行模拟
SESSION_UA=${MY_UA_POOL[$RANDOM % 3]}
else
# 兜底容错机制
SESSION_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
fi
# 位置锁定:在基准点(比如东京新宿)附近 3 公里内随机生成本次上网的“固定咖啡馆”坐标
SESSION_BASE_LAT=$(get_random_coord $BASE_LAT 270)
SESSION_BASE_LON=$(get_random_coord $BASE_LON 270)
@@ -60,10 +96,36 @@ SESSION_BASE_LON=$(get_random_coord $BASE_LON 270)
# 【核心升级】随机决定本次上网深度 (6 - 10 个复合动作,配合高频长效拉伸)
TOTAL_ACTIONS=$((6 + RANDOM % 5))
log "$MODULE_NAME" "INFO " "当前出网 IP: $CURRENT_V4"
log "$MODULE_NAME" "INFO " "当前出网 IP: $CURRENT_IP"
log "$MODULE_NAME" "INFO " "设备指纹锁定: ${SESSION_UA:0:45}..."
log "$MODULE_NAME" "INFO " "虚拟驻留坐标: $SESSION_BASE_LAT, $SESSION_BASE_LON"
# -----------------------------------------------------------
# [V3.2.1 热修复] 网络锚定与协议自适应构建
# 强制 curl 绑定网卡,并自动匹配 IPv4/v6 协议,杜绝 curl 冲突报错
# -----------------------------------------------------------
CURL_BIND_OPT=""
DYNAMIC_IP_PREF="-${IP_PREF:-4}" # 默认提取用户配置
if [[ -n "$BIND_IP" && "$BIND_IP" =~ ^[0-9a-fA-F:\.]+$ ]]; then
# [v3.6.3 容错层补丁] 探测物理网卡/虚拟 IP 存活状态
RAW_BIND_IP=$(echo "$BIND_IP" | tr -d '[]')
if ! ip addr show 2>/dev/null | grep -qw "$RAW_BIND_IP"; then
log "$MODULE_NAME" "WARN " "检测到配置的出口 IP ($RAW_BIND_IP) 已丢失,自动降级为系统默认路由出网!"
CURL_BIND_OPT=""
else
CURL_BIND_OPT="--interface $BIND_IP"
# 智能探测:带冒号为 V6带点号为 V4
if [[ "$BIND_IP" == *":"* ]]; then
DYNAMIC_IP_PREF="-6"
log "$MODULE_NAME" "INFO " "底层路由锁定: 绑定 IPv6 出口及协议 ($BIND_IP)"
elif [[ "$BIND_IP" == *"."* ]]; then
DYNAMIC_IP_PREF="-4"
log "$MODULE_NAME" "INFO " "底层路由锁定: 绑定 IPv4 出口及协议 ($BIND_IP)"
fi
fi
fi
# --- [行为循环模拟] ---
for ((i=1; i<=TOTAL_ACTIONS; i++)); do
# 模拟真实移动设备拿在手里时的 GPS 信号微抖动 (范围约 10 米)
@@ -77,21 +139,22 @@ for ((i=1; i<=TOTAL_ACTIONS; i++)); do
# 随机选择一种上网行为
ACTION_TYPE=$((1 + RANDOM % 4))
# [V3.2.1 热修复] 注入 $CURL_BIND_OPT 与 $DYNAMIC_IP_PREF 协议自适应
case $ACTION_TYPE in
1) # 搜索行为
CODE=$(curl -4 -m 15 -s -L -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
CODE=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 15 -s -L -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
"https://www.google.com/search?q=${ENCODED_KEY}&${LANG_PARAMS}")
;;
2) # 浏览本土新闻
CODE=$(curl -4 -m 15 -s -L -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
CODE=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 15 -s -L -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
"https://news.google.com/home?${LANG_PARAMS}")
;;
3) # 地图坐标查询
CODE=$(curl -4 -m 15 -s -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
"https://www.google.com/maps/search/${ENCODED_KEY}/@${ACTION_LAT},${ACTION_LON},17z?${LANG_PARAMS}")
CODE=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 15 -s -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
"https://www.google.com/maps/search/$${ENCODED_KEY}/@${ACTION_LAT},${ACTION_LON},17z?${LANG_PARAMS}")
;;
4) # 触发移动端系统底层位置检测像素
CODE=$(curl -4 -m 10 -s -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
CODE=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 10 -s -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
"https://connectivitycheck.gstatic.com/generate_204")
;;
esac
@@ -107,16 +170,32 @@ for ((i=1; i<=TOTAL_ACTIONS; i++)); do
fi
done
# --- [结果纠偏自检] ---
# 去掉所有语言参数,进行一次最干净的直连测试
FINAL_URL=$(curl -4 -m 15 -s -L -o /dev/null -w "%{url_effective}" https://www.google.com)
# --- [结果纠偏自检 (V4.0.3 终极真理版: 穿透 Google 真实 GeoIP 数据库)] ---
# 彻底抛弃不可靠的前端 URL 重定向判定 (解决 Issue #35 和 #14 的假阳性问题)
# 战术揭秘Google 与 YouTube 共享绝对一致的底层 GeoIP 库。
# 我们直接抓取 YouTube 源码内部的 "GL" (Geo-Location) 环境变量,拿到 Google 视角的 2 位国家代码!
if [[ "$FINAL_URL" == *"$VALID_URL_SUFFIX"* ]]; then
STATUS="✅ 目标区域达成 ($VALID_URL_SUFFIX)"
elif [[ "$FINAL_URL" == *"google.com.hk"* ]]; then
STATUS="❌ 判定为送中区 (CN/HK)"
log "$MODULE_NAME" "INFO " "正在穿透获取 Google 底层真实 GeoIP 锚点..."
YT_HTML=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 15 -s -L https://www.youtube.com)
# 精准正则提取 "GL":"XX" 中的两位字母 (完美兼容所有老旧系统环境)
REAL_REGION=$(echo "$YT_HTML" | grep -o '"GL":"[A-Za-z]\{2\}"' | head -n 1 | cut -d'"' -f4 | tr 'a-z' 'A-Z')
if [ -z "$REAL_REGION" ]; then
STATUS="🚨 探针失效 (网络阻断,或已被 Google 验证码/5秒盾拦截)"
else
STATUS="⚠️ 其他分站跳板 ($FINAL_URL)"
# [基准对齐] 提取配置大区 (兼容州级穿透,如 US-TX -> US),并修正英国的 ISO 标准代码
TARGET_CC="${REGION_CODE%%-*}"
[ "$TARGET_CC" == "UK" ] && TARGET_CC="GB"
# 终极审判逻辑
if [ "$REAL_REGION" == "CN" ]; then
STATUS="❌ 严重高危IP 已被 Google 判定为中国大陆 (送中)"
elif [ "$REAL_REGION" == "$TARGET_CC" ]; then
STATUS="✅ 目标区域达成 (底层真实锚定: $REAL_REGION)"
else
STATUS="⚠️ 区域发生漂移!目标 $TARGET_CC,实际归属 $REAL_REGION (跨区送医/送美)"
fi
fi
log "$MODULE_NAME" "SCORE" "自检结论: $STATUS"

206
core/mod_quality.sh Executable file
View File

@@ -0,0 +1,206 @@
#!/bin/bash
# ==========================================================
# IP-Sentinel: 深海声呐 (IP 质量全维异步检测模块 v4.0.0)
# ==========================================================
source /opt/ip_sentinel/config.conf
# ==========================================
# 1. 动态网络锚定与协议自适应 (专为多 IP / NAT 架构打造)
# ==========================================
DYNAMIC_IP_PREF="${IP_PREF:-4}"
PROBE_ARGS=("-y" "-j" "-f") # 默认注入: 自动确认、JSON格式、明文无掩码IP
# 强壮正则:支持 V4, V6 以及带有 [] 护甲的 V6 (兼容多 IP 站群机)
if [[ -n "$BIND_IP" && "$BIND_IP" =~ ^[0-9a-fA-F:\[\]\.]+$ ]]; then
RAW_BIND_IP=$(echo "$BIND_IP" | tr -d '[]')
# 严格探测物理网卡/虚拟 IP 存活状态,防止 IP 漂移导致探针彻底报错
if ip addr show 2>/dev/null | grep -qw "$RAW_BIND_IP"; then
# 核心:精准锁定多 IP 机器的出口网卡,指哪打哪
PROBE_ARGS+=("-i" "$RAW_BIND_IP")
# 智能识别 V4 / V6强制覆盖系统默认的 IP_PREF
if [[ "$RAW_BIND_IP" == *":"* ]]; then
DYNAMIC_IP_PREF="6"
elif [[ "$RAW_BIND_IP" == *"."* ]]; then
DYNAMIC_IP_PREF="4"
fi
fi
fi
# 补齐协议版本参数 (-4 或 -6)
PROBE_ARGS+=("-${DYNAMIC_IP_PREF}")
# 2. 静默拉取原始数据 (消除短链接 RCE 劫持风险,收编为本地固化执行)
PROBE_SCRIPT="/opt/ip_sentinel/core/ip_probe.sh"
if [ ! -x "$PROBE_SCRIPT" ]; then
# 若本地探针尚未就绪,直接从 GitHub 官方主干拉取底层源码,绕过未知域名
curl -sL "https://raw.githubusercontent.com/xykt/IPQuality/main/ip.sh" -o "$PROBE_SCRIPT" 2>/dev/null
chmod +x "$PROBE_SCRIPT" 2>/dev/null
fi
# 采用本地执行,将动态参数阵列展开,彻底封死外部投毒与 NAT 死锁陷阱
RAW_OUTPUT=$(timeout 180 bash "$PROBE_SCRIPT" "${PROBE_ARGS[@]}" 2>/dev/null)
# 2. 极致截取 JSON (无视开头的赞助商广告与不可见字符,精准提取)
JSON_DATA="{${RAW_OUTPUT#*\{}"
# 2. 提取基础物理定位与身份特征 (兼作合法性校验)
IP_ADDR=$(echo "$JSON_DATA" | jq -r '.Head.IP // empty' 2>/dev/null)
if [ -z "$IP_ADDR" ]; then
curl -s -X POST "${TG_API_URL}" \
-d "chat_id=${CHAT_ID}" \
-d "parse_mode=Markdown" \
-d "text=❌ *深海声呐探测失败*
📍 节点:\`${NODE_ALIAS}\`
🌐 锁定IP\`${PUBLIC_IP}\`
⚠️ *未收到有效回波。检测源超时或数据解析受阻。*" >/dev/null
exit 1
fi
[ -z "$IP_ADDR" ] && IP_ADDR="$PUBLIC_IP"
ASN=$(echo "$JSON_DATA" | jq -r '.Info.ASN // "Unknown"' 2>/dev/null)
ORG=$(echo "$JSON_DATA" | jq -r '.Info.Organization // "Unknown"' 2>/dev/null)
CITY=$(echo "$JSON_DATA" | jq -r '.Info.City.Name // "Unknown"' 2>/dev/null)
COUNTRY=$(echo "$JSON_DATA" | jq -r '.Info.Region.Name // "Unknown"' 2>/dev/null)
IP_TYPE=$(echo "$JSON_DATA" | jq -r '.Info.Type // "未知属性"' 2>/dev/null)
USAGE_TYPE=$(echo "$JSON_DATA" | jq -r '.Type.Usage.IPinfo // "未知场景"' 2>/dev/null)
# 3. 深度欺诈与信用评估 (各大权威库联查)
SCAM_SCORE=$(echo "$JSON_DATA" | jq -r '.Score.SCAMALYTICS // "0"' 2>/dev/null)
ABUSE_SCORE=$(echo "$JSON_DATA" | jq -r '.Score.AbuseIPDB // "0"' 2>/dev/null)
IPQS_SCORE=$(echo "$JSON_DATA" | jq -r '.Score.IPQS // "0"' 2>/dev/null)
IP2L_SCORE=$(echo "$JSON_DATA" | jq -r '.Score.IP2LOCATION // "0"' 2>/dev/null)
FRAUD_RISK=$(echo "$JSON_DATA" | jq -r '.Score.ipapi // "0%"' 2>/dev/null)
# [修复] 清洗 API 阻断返回的 null 值,保障面板整洁
[ "$SCAM_SCORE" == "null" ] || [ -z "$SCAM_SCORE" ] && SCAM_SCORE="N/A"
[ "$ABUSE_SCORE" == "null" ] || [ -z "$ABUSE_SCORE" ] && ABUSE_SCORE="N/A"
[ "$IPQS_SCORE" == "null" ] || [ -z "$IPQS_SCORE" ] && IPQS_SCORE="N/A"
[ "$IP2L_SCORE" == "null" ] || [ -z "$IP2L_SCORE" ] && IP2L_SCORE="N/A"
[ "$FRAUD_RISK" == "null" ] || [ -z "$FRAUD_RISK" ] && FRAUD_RISK="N/A"
# 代理/VPN 特征探针 (只要有一家认为是代理,就亮黄灯)
IS_PROXY="🟢 干净"
if echo "$JSON_DATA" | jq -e '.Factor.Proxy | to_entries | any(.value == true)' >/dev/null 2>&1 || \
echo "$JSON_DATA" | jq -e '.Factor.VPN | to_entries | any(.value == true)' >/dev/null 2>&1; then
IS_PROXY="🟡 疑似代理/VPN"
fi
# 4. 提取流媒体与 AI 解锁指标 (带解锁类型)
parse_media() {
local status=$(echo "$JSON_DATA" | jq -r ".Media.$1.Status // \"未知\"" 2>/dev/null)
local reg=$(echo "$JSON_DATA" | jq -r ".Media.$1.Region // \"\"" 2>/dev/null)
local type=$(echo "$JSON_DATA" | jq -r ".Media.$1.Type // \"\"" 2>/dev/null)
if [[ "$status" == *"解锁"* ]]; then
echo "🟢 ${reg} (${type})"
elif [[ "$status" == *"仅"* ]] || [[ "$status" == *"机房"* ]] || [[ "$status" == *"待支持"* ]]; then
# 捕捉 Netflix "仅自制"、ChatGPT "仅网页"、TikTok "机房" 等半残状态
echo "🟡 ${status} ${reg}"
elif [[ "$status" == *"屏蔽"* ]] || [[ "$status" == *"失败"* ]] || [[ "$status" == *"中国"* ]] || [[ "$status" == *"禁"* ]]; then
# 捕捉 "屏蔽"、"失败"、"禁会员"、"中国"(送中)
echo "🔴 ${status}"
else
echo "${status}"
fi
}
NF_STAT=$(parse_media "Netflix")
YT_STAT=$(parse_media "Youtube")
DP_STAT=$(parse_media "DisneyPlus")
TK_STAT=$(parse_media "TikTok")
GPT_STAT=$(parse_media "ChatGPT")
APV_STAT=$(parse_media "AmazonPrimeVideo")
# 提取原生 JSON 里的原始状态用于底层隐写回传
RAW_NF_STAT=$(echo "$JSON_DATA" | jq -r '.Media.Netflix.Status // "Unknown"' 2>/dev/null)
RAW_YT_REG=$(echo "$JSON_DATA" | jq -r '.Media.Youtube.Region // ""' 2>/dev/null)
RAW_YT_STAT=$(echo "$JSON_DATA" | jq -r '.Media.Youtube.Status // "Unknown"' 2>/dev/null)
# 5. 邮局连通性与黑名单
PORT25=$(echo "$JSON_DATA" | jq -r '.Mail.Port25 // "false"' 2>/dev/null)
[ "$PORT25" == "true" ] && P25_TEXT="✅ 畅通" || P25_TEXT="❌ 封堵"
DNS_BLACK=$(echo "$JSON_DATA" | jq -r '.Mail.DNSBlacklist.Blacklisted // "0"' 2>/dev/null)
DNS_MARK=$(echo "$JSON_DATA" | jq -r '.Mail.DNSBlacklist.Marked // "0"' 2>/dev/null)
# 6. “送中” 逻辑判定
WARNING_MSG=""
# [修复] 官方 JSON 已经去除了方括号,直接匹配 CN 或者状态包含中国
if [[ "$RAW_YT_REG" == "CN" ]] || [[ "$RAW_YT_STAT" == *"中国"* ]]; then
WARNING_MSG="%0A🚨 **[高危] 该节点已被 Google 判定为中国大陆 (送中)**%0A"
fi
# 7. 组装情报级 Markdown 战报
# 提取本地运行态版本与生成时间戳
LOCAL_VER="${AGENT_VERSION:-未知}"
CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S")
# [核心修复] 抛弃本地残缺配置,直接提取探针刚刚实测拿到的真实出口 IP 拼接链接!
LINK_IP=$(echo "$IP_ADDR" | tr -d '[]')
REPORT="🎯 *IP-Sentinel 深海声呐报告*
📍 节点:\`${NODE_ALIAS}\`
🌐 地址:\`${IP_ADDR}\`${WARNING_MSG}
*🏢 物理身份与网络属性*
\`AS${ASN}\` | \`${ORG}\`
**定位:** \`${COUNTRY} - ${CITY}\`
**属性:** \`${IP_TYPE}\` | \`${USAGE_TYPE}\`
**探针:** ${IS_PROXY}
*🛡️ 欺诈雷达 (0为最优)*
• **Scamalytics:** \`${SCAM_SCORE}/100\`
• **AbuseIPDB:** \`${ABUSE_SCORE}/100\`
• **IPQS:** \`${IPQS_SCORE}/100\`
• **IP2Location:** \`${IP2L_SCORE}/100\`
• **IPAPI 风险率:** \`${FRAUD_RISK}\`
*🎬 核心业务解锁*
• **YouTube:** ${YT_STAT}
• **Netflix:** ${NF_STAT}
• **Disney+:** ${DP_STAT}
• **PrimeVideo:** ${APV_STAT}
• **TikTok:** ${TK_STAT}
• **ChatGPT:** ${GPT_STAT}
*✉️ 邮局与污染度*
• **25 端口出站:** ${P25_TEXT}
• **DNS 污染库:** 严重 \`${DNS_BLACK}\` | 轻微 \`${DNS_MARK}\`
_👉 [🔍 详细信用图谱直达 (Scamalytics)](https://scamalytics.com/ip/${LINK_IP})_
⏱️ \`${CURRENT_TIME}\` | ⚙️ \`v${LOCAL_VER}\`"
# [修复] 剥离显示层的 N/A确保传给 Master 趋势数据库的是纯数字 (无效则记为0)
SAFE_SCAM_SCORE=$(echo "$SCAM_SCORE" | tr -cd '0-9')
[ -z "$SAFE_SCAM_SCORE" ] && SAFE_SCAM_SCORE="0"
# [v4.0.2 扩容] 提取 Google(基于YouTube) 和 ChatGPT 的原生状态
RAW_GOOG_STAT="${RAW_YT_REG:-$RAW_YT_STAT}"
[ -z "$RAW_GOOG_STAT" ] && RAW_GOOG_STAT="未知"
RAW_GPT_STAT=$(echo "$JSON_DATA" | jq -r '.Media.ChatGPT.Status // "未知"' 2>/dev/null)
# [修复] 废除会导致中文 UTF-8 字节被劈裂(产生乱码 )的 awk 暴力截断。
# 原始状态文本极短(如"解锁"、"屏蔽"、"US"),只需洗掉隐形换行符即可安全传输。
S_GOOG=$(echo "$RAW_GOOG_STAT" | tr -d '\n\r ')
S_NF=$(echo "$RAW_NF_STAT" | tr -d '\n\r ')
S_GPT=$(echo "$RAW_GPT_STAT" | tr -d '\n\r ')
CB_DATA="svq|${NODE_NAME}|${SAFE_SCAM_SCORE}|${S_GOOG}|${S_NF}|${S_GPT}"
# 8. 挂载内联键盘并直送指挥部
JSON_PAYLOAD=$(jq -n \
--arg cid "$CHAT_ID" \
--arg txt "$REPORT" \
--arg cb "$CB_DATA" \
'{
chat_id: $cid,
text: $txt,
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_markup: {
inline_keyboard: [[{text: "📥 将本次体检录入趋势库", callback_data: $cb}]]
}
}')
curl -s -X POST "${TG_API_URL}" -H "Content-Type: application/json" -d "$JSON_PAYLOAD" >/dev/null

163
core/mod_trust.sh Executable file
View File

@@ -0,0 +1,163 @@
#!/bin/bash
# ==========================================================
# 脚本名称: mod_trust.sh (IP 信用净化模块 - 动态锚点版)
# 核心功能: 动态扫描本地 LBS 冷数据,提取权威白名单,执行流量净化
# ==========================================================
INSTALL_DIR="/opt/ip_sentinel"
CONFIG_FILE="${INSTALL_DIR}/config.conf"
UA_FILE="${INSTALL_DIR}/data/user_agents.txt"
# 你的 GitHub 仓库 Raw 数据直链前缀
REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/main"
# 临时改为私库地址用于测试
# REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/v3.6.2-rc"
# 1. 基础环境校验
[ ! -f "$CONFIG_FILE" ] && exit 1
source "$CONFIG_FILE"
REGION=${REGION_CODE:-"US"}
LOG_FILE="${INSTALL_DIR}/logs/sentinel.log"
# 2. 动态获取配置 (V3 拓扑自适应与兜底)
# 利用 find 穿透多级子目录,自动抓取安装时落地的那份专属 json 文件
REGION_JSON_FILE=$(find "${INSTALL_DIR}/data/regions" -name "*.json" 2>/dev/null | head -n 1)
# 兼容旧节点兜底:如果本地真没找到 json回退到拉取云端通用大区配置
if [ -z "$REGION_JSON_FILE" ] || [ ! -f "$REGION_JSON_FILE" ]; then
REGION_JSON_FILE="${INSTALL_DIR}/data/regions/${REGION}.json"
mkdir -p "${INSTALL_DIR}/data/regions"
curl -${IP_PREF:-4} -sL "${REPO_RAW_URL}/data/regions/${REGION}.json" -o "$REGION_JSON_FILE"
fi
# 使用 jq 将 json 中的网址数组安全地读入 Bash 数组
if [ -f "$REGION_JSON_FILE" ]; then
mapfile -t TRUST_URLS < <(jq -r '.trust_module.white_urls[]' "$REGION_JSON_FILE" 2>/dev/null)
fi
# 兜底:如果仓库挂了或者解析失败,提供国际通用白名单
if [ ${#TRUST_URLS[@]} -eq 0 ]; then
TRUST_URLS=("https://en.wikipedia.org/wiki/Special:Random" "https://www.apple.com/" "https://www.microsoft.com/")
fi
# 3. 日志规范化 (v3.4.0 引入版本探针)
log_msg() {
local TYPE=$1
local MSG=$2
local TIME=$(date "+%Y-%m-%d %H:%M:%S")
# [v3.4.0 核心] 提取当前配置中的版本锚点
local local_ver="${AGENT_VERSION:-未知}"
# 日志格式注入 [版本号] 追踪标识,保持对齐
echo "[$TIME] [v%-5s] [%-5s] [Trust ] [$REGION] $MSG" | sed "s/%-5s/$local_ver/;s/%-5s/$TYPE/" | tee -a "$LOG_FILE"
}
# 4. 锁定单次会话指纹
# -----------------------------------------------------------
# [V3.1.5] 哈希锚定法 (Hash-Seeded Persona)
# 利用 IP 算力固定 3 个永久化专属指纹,破除僵尸网络同质化特征
# -----------------------------------------------------------
if [ -f "$UA_FILE" ]; then
mapfile -t UA_POOL < <(grep -v '^$' "$UA_FILE")
TOTAL_UA=${#UA_POOL[@]}
if [ "$TOTAL_UA" -gt 0 ]; then
# [v3.3.1修改] 优先使用固化的公网 IP 作为哈希种子,防止 NAT 节点指纹同质化
SEED=$(echo -n "${PUBLIC_IP:-${BIND_IP:-127.0.0.1}}" | cksum | awk '{print $1}')
# 利用确定的种子,在全球 4000 的库中,计算出本机的 3 个绝对专属坐标
IDX1=$(( SEED % TOTAL_UA ))
IDX2=$(( (SEED * 17) % TOTAL_UA ))
IDX3=$(( (SEED * 31) % TOTAL_UA ))
# 将专属坐标映射为专属设备库
MY_UA_POOL=("${UA_POOL[$IDX1]}" "${UA_POOL[$IDX2]}" "${UA_POOL[$IDX3]}")
# 本次会话从这 3 台专属设备中随机挑选 1 台 (模拟真实的家庭多设备环境)
CURRENT_UA=${MY_UA_POOL[$RANDOM % 3]}
else
# 兜底容错
CURRENT_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
fi
else
CURRENT_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
fi
# ==========================================
# 🚀 净化行动开始
# ==========================================
log_msg "START" "========== 启动区域 IP 信用净化会话 =========="
log_msg "INFO " "已载入 [${REGION}] 区域白名单,配置库条目: ${#TRUST_URLS[@]}"
log_msg "INFO " "已锁定本地伪装指纹: $(echo $CURRENT_UA | cut -d' ' -f1-2)..."
# -----------------------------------------------------------
# [V3.2.1 热修复] 网络锚定与协议自适应构建
# 强制 curl 绑定网卡,并自动匹配 IPv4/v6 协议,杜绝 curl 冲突报错
# -----------------------------------------------------------
CURL_BIND_OPT=""
DYNAMIC_IP_PREF="-${IP_PREF:-4}" # 默认提取用户配置
if [[ -n "$BIND_IP" && "$BIND_IP" =~ ^[0-9a-fA-F:\.]+$ ]]; then
# [v3.6.3 容错层补丁] 探测物理网卡/虚拟 IP 存活状态
RAW_BIND_IP=$(echo "$BIND_IP" | tr -d '[]')
if ! ip addr show 2>/dev/null | grep -qw "$RAW_BIND_IP"; then
log_msg "WARN " "检测到配置的出口 IP ($RAW_BIND_IP) 已丢失,自动降级为系统默认路由出网!"
CURL_BIND_OPT=""
else
CURL_BIND_OPT="--interface $BIND_IP"
# 智能探测:带冒号为 V6带点号为 V4
if [[ "$BIND_IP" == *":"* ]]; then
DYNAMIC_IP_PREF="-6"
log_msg "INFO " "底层路由锁定: 绑定 IPv6 出口及协议 ($BIND_IP)"
elif [[ "$BIND_IP" == *"."* ]]; then
DYNAMIC_IP_PREF="-4"
log_msg "INFO " "底层路由锁定: 绑定 IPv4 出口及协议 ($BIND_IP)"
fi
fi
fi
STEP_COUNT=$((RANDOM % 4 + 3))
SUCCESS_INJECT=0
for ((i=1; i<=STEP_COUNT; i++)); do
# 随机抽取本地区域权威网址
TARGET_URL=${TRUST_URLS[$RANDOM % ${#TRUST_URLS[@]}]}
# [v3.0.1修复] 注入高权重流量时,强制从绑定的 IPv4 或 IPv6 隧道出网
# [V3.2.1 热修复] 注入 $CURL_BIND_OPT 与 $DYNAMIC_IP_PREF 协议自适应
HTTP_CODE=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -A "$CURRENT_UA" \
-H "Accept: text/html,application/xhtml+xml;q=0.9,image/avif,image/webp,*/*;q=0.8" \
-H "Accept-Language: en-US,en;q=0.9" \
-H "Sec-Fetch-Dest: document" \
-H "Sec-Fetch-Mode: navigate" \
-H "Upgrade-Insecure-Requests: 1" \
--compressed \
-s -o /dev/null -w "%{http_code}" -m 15 "$TARGET_URL")
# 扩大 HTTP 状态码容错区间:包含所有 20x (如亚马逊的 202) 和 30x 重定向
if [[ "$HTTP_CODE" =~ ^(20[0-9]|30[1-8])$ ]]; then
log_msg "EXEC " "动作[$i/$STEP_COUNT]完成 | 状态: $HTTP_CODE | 注入: $TARGET_URL"
((SUCCESS_INJECT++))
else
log_msg "EXEC " "动作[$i/$STEP_COUNT]异常 | 状态: $HTTP_CODE | 阻拦: $TARGET_URL"
fi
if [ $i -lt $STEP_COUNT ]; then
SLEEP_TIME=$((RANDOM % 76 + 45))
log_msg "WAIT " "正在浏览本地高权重页面,模拟停留 $SLEEP_TIME 秒..."
sleep $SLEEP_TIME
fi
done
# ==========================================
# 📊 结论判定与输出
# ==========================================
if [ "$SUCCESS_INJECT" -ge $((STEP_COUNT / 2)) ]; then
log_msg "SCORE" "自检结论: ✅ 信用净化完成 (已成功注入 $SUCCESS_INJECT 条无害流量)"
else
log_msg "SCORE" "自检结论: ❌ 净化受阻 (部分站点拦截或网络超时)"
fi
log_msg "END " "========== 会话结束,释放进程 =========="
log_msg "INFO " "系统级调度完毕,信任因子持续积累中..."

View File

@@ -1,8 +1,8 @@
#!/bin/bash
# ==========================================================
# 脚本名称: runner.sh (IP-Sentinel 主控调度引擎)
# 核心功能: 防并发随机延迟启动、加载本地固化配置、调度业务模块
# 脚本名称: runner.sh (IP-Sentinel 主控调度引擎 - 动态锚点版)
# 核心功能: 防并发延迟启动、功能开关(Feature Flag)自适应、多模块概率轮盘调度
# ==========================================================
INSTALL_DIR="/opt/ip_sentinel"
@@ -15,34 +15,86 @@ if [ ! -f "$CONFIG_FILE" ]; then
fi
source "$CONFIG_FILE"
# 2. 全局日志写入函数 (导出给子进程共享使用)
# ================== [新增: 文件排他锁,防止并发重入引发内存雪崩] ==================
exec 200>"/tmp/ip_sentinel_runner.lock"
if ! flock -n 200; then
echo "[$(date)] ⚠️ 上一轮巡逻任务尚未结束,本次触发自动取消。" >> "$LOG_FILE"
exit 0
fi
# ==================================================================================
# 2. 全局日志写入函数 (导出给子进程共享使用v3.4.0 引入版本探针)
log() {
local module=$1
local level=$2
local msg=$3
# [v3.4.0 核心] 提取当前配置中的版本锚点
local local_ver="${AGENT_VERSION:-未知}"
# 保证日志目录存在
mkdir -p "${INSTALL_DIR}/logs"
printf "[$(date '+%Y-%m-%d %H:%M:%S')] [%-5s] [%-7s] [%s] %s\n" "$level" "$module" "$REGION_CODE" "$msg" >> "$LOG_FILE"
# 日志格式注入 [版本号] 追踪标识
local core_msg=$(printf "[v%-5s] [%-5s] [%-7s] [%s] %s" "$local_ver" "$level" "$module" "$REGION_CODE" "$msg")
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $core_msg" >> "$LOG_FILE"
# 强制推送到 Systemd Journal (如果系统支持)
if command -v logger >/dev/null 2>&1; then
logger -t ip-sentinel "$core_msg"
else
# 降级输出到 stdout让 Systemd 捕获
echo "$core_msg"
fi
}
export -f log
export CONFIG_FILE INSTALL_DIR
# 3. 防僵尸网络特征 (Cron Jitter) - 核心隐蔽逻辑
# 【核心升级】配合每 30 分钟的调度周期,将随机休眠控制在 0 到 180 秒 (3分钟) 内,彻底打散全球并发请求
JITTER_TIME=$((RANDOM % 180))
log "SYSTEM" "INFO" "主控引擎被 Cron 唤醒,进入防并发随机休眠状态: ${JITTER_TIME} 秒..."
sleep $JITTER_TIME
# 4. 唤醒并调度业务模块
log "SYSTEM" "INFO" "休眠结束,开始执行养护任务..."
# 调度 Google 模块
if [ -x "${INSTALL_DIR}/core/mod_google.sh" ]; then
log "SYSTEM" "INFO" "加载子模块: Google 业务模拟"
# 核心降耗逻辑:使用 nice -n 19 赋予进程最低 CPU 优先级,绝不抢占 VPS 正常业务的资源
nice -n 19 bash "${INSTALL_DIR}/core/mod_google.sh"
# 配合每 30 分钟的调度周期,将随机休眠控制在 0 到 180 秒内,彻底打散全球并发请求
if [ -t 1 ]; then
log "SYSTEM" "INFO " "💻 检测到人工终端干预,跳过静默休眠,立即执行任务!"
else
log "SYSTEM" "ERROR" "未找到可执行的 Google 模块"
JITTER_TIME=$((RANDOM % 180))
log "SYSTEM" "INFO " "⏱️ 主控引擎由后台唤醒,进入防并发随机休眠状态: ${JITTER_TIME} 秒..."
sleep $JITTER_TIME
fi
# 4. 唤醒并读取功能开关,执行智能调度 (Feature Flag)
log "SYSTEM" "INFO" "休眠结束,开始计算本轮任务轮盘..."
TARGET_MOD=""
MOD_NAME=""
# 智能轮盘赌算法
if [ "$ENABLE_GOOGLE" == "true" ] && [ "$ENABLE_TRUST" == "true" ]; then
# 双管齐下: 70% 概率跑 Google 稳固定位30% 概率跑 Trust 洗刷风控分
ROLL=$((RANDOM % 100 + 1))
if [ $ROLL -le 70 ]; then
TARGET_MOD="mod_google.sh"
MOD_NAME="Google 区域纠偏"
else
TARGET_MOD="mod_trust.sh"
MOD_NAME="IP 信用净化"
fi
elif [ "$ENABLE_GOOGLE" == "true" ]; then
TARGET_MOD="mod_google.sh"
MOD_NAME="Google 区域纠偏"
elif [ "$ENABLE_TRUST" == "true" ]; then
TARGET_MOD="mod_trust.sh"
MOD_NAME="IP 信用净化"
else
log "SYSTEM" "WARN" "节点未开启任何养护模块,跳过本轮执行。"
exit 0
fi
# 5. 拉起选定的业务模块
if [ -n "$TARGET_MOD" ] && [ -x "${INSTALL_DIR}/core/${TARGET_MOD}" ]; then
log "SYSTEM" "INFO" "命中触发条件,加载并执行子模块: ${MOD_NAME}"
# 核心降耗逻辑:使用 nice -n 19 赋予进程最低 CPU 优先级,绝不抢占 VPS 正常业务的资源
# [安全修复] 注入 200>&-,强行关闭子进程对排他锁的继承权!防止子进程假死导致全局死锁
nice -n 19 bash "${INSTALL_DIR}/core/${TARGET_MOD}" 200>&-
else
log "SYSTEM" "ERROR" "配置了模块 ${MOD_NAME},但未找到对应的可执行脚本: ${TARGET_MOD}"
fi
log "SYSTEM" "INFO" "本轮所有模块调度完毕,哨兵继续隐蔽待命。"

View File

@@ -1,8 +1,8 @@
#!/bin/bash
# ==========================================================
# 脚本名称: tg_daemon.sh (Telegram 互动监听守护进程)
# 核心功能: 极低功耗长轮询监听 TG 指令,实现远程控制
# 脚本名称: tg_daemon.sh (Telegram 互动监听守护进程 - 动态锚点版)
# 核心功能: 极低功耗长轮询监听、节点溯源、版本继承
# ==========================================================
INSTALL_DIR="/opt/ip_sentinel"
@@ -16,6 +16,11 @@ source "$CONFIG_FILE"
# 如果没有配置 TG 机器人,则安静退出守护进程
[ -z "$TG_TOKEN" ] || [ -z "$CHAT_ID" ] && exit 0
# [核心: 动态版本锚点与防撞甲身份载入]
LOCAL_VER="${AGENT_VERSION:-未知}"
IP_HASH=$(echo "${PUBLIC_IP:-127.0.0.1}" | md5sum | cut -c 1-4 | tr 'a-z' 'A-Z')
NODE_NAME="$(hostname | cut -c 1-10)-${IP_HASH}"
# 2. 初始化消息偏移量 (Offset) 记录文件,防止重启后重复处理老消息
OFFSET=0
[ -f "$OFFSET_FILE" ] && OFFSET=$(cat "$OFFSET_FILE")
@@ -44,20 +49,20 @@ while true; do
if [ "$MSG_CHAT_ID" == "$CHAT_ID" ]; then
case "$MSG_TEXT" in
"/run")
send_msg "🚀 **[指令下达]** 正在后台立即触发 IP 养护任务..."
send_msg "🚀 **[${NODE_NAME}]** 正在后台触发 IP 养护任务 (v${LOCAL_VER})..."
# 使用 nohup 另起后台独立进程运行,防止阻塞当前监听器的循环
nohup bash "${INSTALL_DIR}/core/mod_google.sh" >/dev/null 2>&1 &
;;
"/log")
LOG_DATA=$(tail -n 15 "${INSTALL_DIR}/logs/sentinel.log")
send_msg "📄 **[最近 15 行系统日志]**%0A\`\`\`log%0A${LOG_DATA}%0A\`\`\`"
send_msg "📄 **[${NODE_NAME}] 实时日志 (v${LOCAL_VER}):**%0A\`\`\`log%0A${LOG_DATA}%0A\`\`\`"
;;
"/report")
# 触发生成一次战报
bash "${INSTALL_DIR}/core/tg_report.sh"
;;
"/help"|"/start")
HELP_MSG="🛡️ **IP-Sentinel 控制台**%0A/run - 立刻执行一次养护%0A/log - 抓取最新运行日志%0A/report - 手动生成统计简报"
HELP_MSG="🛡️ **IP-Sentinel 边缘控制台**%0A📍 节点: \`${NODE_NAME}\`%0A🔖 版本: \`v${LOCAL_VER}\`%0A%0A/run - 立刻执行一次养护%0A/log - 抓取最新运行日志%0A/report - 手动生成统计简报"
send_msg "$HELP_MSG"
;;
esac

View File

@@ -1,8 +1,8 @@
#!/bin/bash
# ==========================================================
# 脚本名称: tg_report.sh (Telegram 每日战报模块 V5.3 缝合加强版)
# 核心功能: 分析日志并推送 24 小时统计数据到 TG (修复 Markdown 断联Bug)
# 脚本名称: tg_report.sh (Telegram 每日战报模块 - 动态锚点版)
# 核心功能: 适配 Feature Flag 架构按需展示独立统计数据OTA 更新预警
# ==========================================================
INSTALL_DIR="/opt/ip_sentinel"
@@ -18,96 +18,206 @@ if [ -z "$TG_TOKEN" ] || [ -z "$CHAT_ID" ]; then
exit 0
fi
# 2. 节点元数据抓取
NODE_NAME=$(hostname | cut -c 1-15)
CURRENT_IP=$(curl -4 -s -m 5 api.ip.sb/ip || echo "Unknown")
# 2. 节点元数据抓取 (v3.2.2 协议自适应与多级容灾版)
# [v3.5.2 核心: 引入双轨身份架构]
if [ -z "$NODE_NAME" ]; then
IP_HASH=$(echo "${PUBLIC_IP:-127.0.0.1}" | md5sum | cut -c 1-4 | tr 'a-z' 'A-Z')
NODE_NAME="$(hostname | cut -c 1-10)-${IP_HASH}"
fi
NODE_ALIAS="${NODE_ALIAS:-$NODE_NAME}"
# --- [防线 1: 底层路由锁定与协议自适应] ---
CURL_BIND_OPT=""
DYNAMIC_IP_PREF="-${IP_PREF:-4}"
if [[ -n "$BIND_IP" && "$BIND_IP" =~ ^[0-9a-fA-F:\.]+$ ]]; then
# [v3.6.3 容错层补丁] 探测物理网卡/虚拟 IP 存活状态
RAW_BIND_IP=$(echo "$BIND_IP" | tr -d '[]')
if ! ip addr show 2>/dev/null | grep -qw "$RAW_BIND_IP"; then
CURL_BIND_OPT=""
else
CURL_BIND_OPT="--interface $BIND_IP"
if [[ "$BIND_IP" == *":"* ]]; then
DYNAMIC_IP_PREF="-6"
elif [[ "$BIND_IP" == *"."* ]]; then
DYNAMIC_IP_PREF="-4"
fi
fi
fi
# 多节点容灾探测出口 IP (注入协议自适应)
CURRENT_IP=$( (curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -s -m 5 api.ip.sb/ip || curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -s -m 5 ifconfig.me) 2>/dev/null | tr -d '[:space:]' )
# [v3.3.1 修改] 强制兜底:如果外部 API 挂了,优先使用固化的对外公网面孔 (兼容 NAT 机的空 BIND_IP)
[ -z "$CURRENT_IP" ] && CURRENT_IP="${PUBLIC_IP:-$BIND_IP}"
# 为可能获取到的 IPv6 自动添加方括号护甲
[[ "$CURRENT_IP" == *":"* ]] && [[ "$CURRENT_IP" != *"["* ]] && CURRENT_IP="[${CURRENT_IP}]"
# --- [防线 2: 多级 ISP 容灾探针链路] ---
ISP_INFO=""
# 探针 A: 纯文本 API (免 jq极速稳定)
ISP_INFO=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -s -m 5 ipinfo.io/org 2>/dev/null)
# 探针 B: 备用纯文本 API
if [ -z "$ISP_INFO" ] || [[ "$ISP_INFO" == *"error"* ]]; then
ISP_INFO=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -s -m 5 ip-api.com/line/?fields=isp 2>/dev/null)
fi
# 探针 C: 原版的 JSON API (需要 jq 兜底)
if [ -z "$ISP_INFO" ] || [[ "$ISP_INFO" == *"error"* ]]; then
if command -v jq &> /dev/null; then
ISP_INFO=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -s -m 5 api.ip.sb/geoip | jq -r '.organization' 2>/dev/null)
fi
fi
# --- [防线 3: 数据清洗 (遵循底层共识原则)] ---
# 剔除 ipinfo 返回的开头 AS 号 (例如 "AS137535 JT TELECOM" -> "JT TELECOM")
ISP_INFO=$(echo "$ISP_INFO" | sed -E 's/^AS[0-9]+ //')
# 最终兜底判断
[ -z "$ISP_INFO" ] || [ "$ISP_INFO" == "null" ] && ISP_INFO="未知 ISP"
# 智能判断 IP 属性 (通过检查 ISP 标识)
ISP_INFO=$(curl -4 -s -m 5 api.ip.sb/geoip | jq -r '.organization' 2>/dev/null)
if [[ "$ISP_INFO" == *"Cloudflare"* ]]; then
IP_TYPE="Cloudflare Warp 🛰️"
else
IP_TYPE="Native 原生网卡 🏠"
IP_TYPE="$ISP_INFO 🏠"
fi
# 3. 截取过去 24 小时的日志
LOG_CONTENT=$(find "$LOG_FILE" -mtime -1 -exec cat {} \; 2>/dev/null)
# 动态国旗
case "$REGION_CODE" in
"JP") FLAG="🇯🇵" ;;
"US") FLAG="🇺🇸" ;;
"DE") FLAG="🇩🇪" ;;
"SG") FLAG="🇸🇬" ;;
"HK") FLAG="🇭🇰" ;;
"GB"|"UK") FLAG="🇬🇧" ;;
"AU") FLAG="🇦🇺" ;;
*) FLAG="🌐" ;;
esac
# 3. 截取过去 24 小时的日志 (每天48次轮询保留最新 1000 行足以覆盖单日战报)
LOG_CONTENT=$(tail -n 1000 "$LOG_FILE" 2>/dev/null)
if [ -z "$LOG_CONTENT" ]; then
# 修复了换行问题,统一用 EOF 块构造
read -r -d '' MSG <<EOT
🛑 **[IP-Sentinel] 告警:节点异常**
----------------------------
📍 **节点名称**: \`${NODE_NAME}\`
📍 **节点名称**: \`${NODE_ALIAS}\`
⚠️ **警告**: 过去 24 小时无运行日志!
🛠️ **建议**: 节点可能刚部署完毕,请手动执行一次 [执行深度伪装]
🛠️ **建议**: 节点可能刚部署完毕,请在面板手动执行一次养护动作
EOT
else
# 4. 数据精准分析
TOTAL_SESSIONS=$(echo "$LOG_CONTENT" | grep "\[START\]" -c)
SUCCESS_COUNT=$(echo "$LOG_CONTENT" | grep "✅" -c)
FAILED_COUNT=$(echo "$LOG_CONTENT" | grep "❌" -c)
UNKNOWN_COUNT=$(echo "$LOG_CONTENT" | grep "⚠️" -c)
# ==========================================
# 4. 动态模块数据分析 (核心升级)
# ==========================================
# 提取最近一次运行的快照 (智能识别所属模块)
LAST_LOG_LINE=$(echo "$LOG_CONTENT" | grep "\[SCORE\]" | tail -n 1)
LAST_TIME=$(echo "$LAST_LOG_LINE" | awk '{print $1,$2}' | tr -d '[]')
LAST_MOD=$(echo "$LAST_LOG_LINE" | awk '{print $4}' | tr -d '[]')
LAST_SCORE=$(echo "$LAST_LOG_LINE" | awk -F'自检结论: ' '{print $2}')
# 提取最近一次运行的时间和结论文本
# (⚠️ 核心 Bug 修复: 用 awk 切割并过滤掉中括号 [],防止触发 TG Markdown 语法错误导致消息丢弃)
LAST_TIME=$(echo "$LOG_CONTENT" | grep "\[END" | tail -n 1 | awk '{print $1,$2}' | tr -d '[]')
LAST_SCORE=$(echo "$LOG_CONTENT" | grep "\[SCORE\]" | tail -n 1 | awk -F'自检结论: ' '{print $2}' | tr -d '[]')
# 计算成功率
if [ "$TOTAL_SESSIONS" -gt 0 ]; then
RATE=$(awk "BEGIN {printf \"%.1f\", ($SUCCESS_COUNT/$TOTAL_SESSIONS)*100}")
else
RATE=0
fi
# 状态表情逻辑:成功率 100% 显绿色0% 显红色,中间显黄色
if [ "$SUCCESS_COUNT" -eq "$TOTAL_SESSIONS" ] && [ "$TOTAL_SESSIONS" -gt 0 ]; then
STATUS_EMOJI="🟢 隐匿完美"
elif [ "$SUCCESS_COUNT" -gt 0 ]; then
STATUS_EMOJI="🟡 伪装拉锯中"
else
STATUS_EMOJI="🔴 目标已暴露"
fi
# 动态国旗
case "$REGION_CODE" in
"JP") FLAG="🇯🇵" ;;
"US") FLAG="🇺🇸" ;;
"DE") FLAG="🇩🇪" ;;
"SG") FLAG="🇸🇬" ;;
*) FLAG="🌐" ;;
esac
# 5. 组装 Markdown 消息体 (吸收了老版本的优点)
read -r -d '' MSG <<EOT
📊 **IP-Sentinel 每日简报 (${FLAG} ${REGION_NAME})**
# 开始组装战报头部
MSG="📊 **IP-Sentinel 每日简报 (${FLAG} ${REGION_NAME})**
----------------------------
📍 **节点名称**: \`${NODE_NAME}\`
📍 **节点名称**: \`${NODE_ALIAS}\`
📡 **出口 IP**: \`${CURRENT_IP}\`
🛡️ **IP 属性**: ${IP_TYPE}
🔰 **当前状态**: ${STATUS_EMOJI}
🛡️ **IP 属性**: ${IP_TYPE}"
📅 **24H 统计数据**:
🚀 执行总数: ${TOTAL_SESSIONS} 次
✅ 成功伪装: ${SUCCESS_COUNT} 次
❌ 判定送中: ${FAILED_COUNT} 次
⚠️ 未知跳转: ${UNKNOWN_COUNT} 次
📈 综合胜率: **${RATE}%**
# --- [分析块 1: Google 纠偏模块] ---
if [ "$ENABLE_GOOGLE" == "true" ]; then
GOOGLE_LOGS=$(echo "$LOG_CONTENT" | grep "\[Google")
G_TOTAL=$(echo "$GOOGLE_LOGS" | grep "\[START\]" -c)
G_SUCCESS=$(echo "$GOOGLE_LOGS" | grep "✅" -c)
G_FAILED=$(echo "$GOOGLE_LOGS" | grep "❌" -c)
G_WARN=$(echo "$GOOGLE_LOGS" | grep "⚠️" -c)
G_RATE="0.0"
[ "$G_TOTAL" -gt 0 ] && G_RATE=$(awk "BEGIN {printf \"%.1f\", ($G_SUCCESS/$G_TOTAL)*100}")
🕒 **最近执行快照**:
MSG="$MSG
🎯 **[Google 区域纠偏]**
🚀 执行总数: ${G_TOTAL} 次 (胜率: **${G_RATE}%**)
✅ 成功: ${G_SUCCESS} | ❌ 送中: ${G_FAILED} | ⚠️ 警告: ${G_WARN}"
fi
# --- [分析块 2: IP 信用净化模块] ---
if [ "$ENABLE_TRUST" == "true" ]; then
TRUST_LOGS=$(echo "$LOG_CONTENT" | grep "\[Trust")
T_TOTAL=$(echo "$TRUST_LOGS" | grep "\[START\]" -c)
T_SUCCESS=$(echo "$TRUST_LOGS" | grep "✅" -c)
T_FAILED=$(echo "$TRUST_LOGS" | grep "❌" -c)
T_RATE="0.0"
[ "$T_TOTAL" -gt 0 ] && T_RATE=$(awk "BEGIN {printf \"%.1f\", ($T_SUCCESS/$T_TOTAL)*100}")
MSG="$MSG
🔰 **[IP 信用净化]**
🚀 净化总数: ${T_TOTAL} 轮 (成功率: **${T_RATE}%**)
✅ 成功注入: ${T_SUCCESS} | ❌ 访问受阻: ${T_FAILED}"
fi
# 组装战报尾部 (最近快照)
MSG="$MSG
🕒 **最近执行快照 [${LAST_MOD:-"System"}]:**
时间: ${LAST_TIME:-"暂无数据"}
结论: ${LAST_SCORE:-"暂无数据"}
----------------------------
💡 哨兵正在后台默默守护您的资产。
EOT
结论: ${LAST_SCORE:-"暂无数据"}"
fi
# 6. 调用 API 推送 (增加返回值校验输出,方便查错)
RESPONSE=$(curl -s -m 10 -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
-d "chat_id=${CHAT_ID}" \
-d "text=${MSG}" \
-d "parse_mode=Markdown")
# ==========================================
# 5. [核心: OTA 云端版本探针与告警模块]
# ==========================================
# 从配置文件提取当前本地版本,若无则默认为未知
LOCAL_VER="${AGENT_VERSION:-未知}"
# 极轻量级探针: 抓取 GitHub 云端的 version.txt (超时 3 秒KV解析法)
REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/main"
REMOTE_VER=$(curl -s -m 3 "${REPO_RAW_URL}/version.txt" | grep "^AGENT_VERSION=" | cut -d'=' -f2 | tr -d '[:space:]')
# 构建底部引擎状态块
MSG="$MSG
----------------------------
🛡️ **系统引擎状态**
当前运行版本: \`v${LOCAL_VER}\`"
# 比对逻辑:如果成功抓到了远端版本,且和本地不一样
if [ -n "$REMOTE_VER" ] && [ "$REMOTE_VER" != "$LOCAL_VER" ]; then
MSG="$MSG
最新官方版本: \`v${REMOTE_VER}\` (✨有新版)
💡 *司令部提示:检测到新版装甲,请长官登录节点执行平滑热更新!*"
elif [ -n "$REMOTE_VER" ] && [ "$REMOTE_VER" == "$LOCAL_VER" ]; then
MSG="$MSG
最新官方版本: \`v${REMOTE_VER}\` (✅已是最新)
💡 *哨兵正在后台默默守护您的资产。*"
else
# 抓取失败兜底
MSG="$MSG
💡 *哨兵正在后台默默守护您的资产。*"
fi
# 5. 调用 API 推送 (接入安全网关,挂载交互式控制台按钮)
JSON_PAYLOAD=$(jq -n \
--arg cid "$CHAT_ID" \
--arg txt "$MSG" \
--arg cb "manage:${NODE_NAME}" \
'{
chat_id: $cid,
text: $txt,
parse_mode: "Markdown",
disable_web_page_preview: true,
reply_markup: {
inline_keyboard: [[{text: "⚙️ 调出该节点控制台", callback_data: $cb}]]
}
}')
RESPONSE=$(curl -s -m 10 -X POST "${TG_API_URL}" \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
if [[ "$RESPONSE" != *"\"ok\":true"* ]]; then
echo "❌ 战报发送失败API 响应: $RESPONSE" >> "${INSTALL_DIR}/logs/error.log"

View File

@@ -1,35 +1,84 @@
#!/bin/bash
# 脚本名称: uninstall.sh (IP-Sentinel 一键卸载脚本 - 动态锚点版)
# 核心功能: 无痕清理守护进程、定时任务、运行目录及临时缓存
# ==========================================================
# 脚本名称: uninstall.sh (IP-Sentinel 一键卸载脚本)
# 核心功能: 清除守护进程、清理系统定时任务、删除所有程序文件
# ==========================================================
# 🛑 核心权限防线: 检查是否以 root 权限运行
# ==========================================================
if [ "$EUID" -ne 0 ]; then
echo -e "\033[31m❌ 权限被拒绝: 卸载 IP-Sentinel 需要最高系统权限。\033[0m"
echo -e "💡 请切换到 root 用户 (执行 su root 或 sudo -i) 后重新运行指令。"
exit 1
fi
INSTALL_DIR="/opt/ip_sentinel"
echo "========================================================"
echo " 🗑️ 准备卸载 IP-Sentinel (VPS IP 自动养护哨兵)"
echo " 🗑️ 准备卸载 IP-Sentinel (边缘节点 Edge Agent)"
# [核心: 动态读取并播报即将销毁的本地版本号]
CONFIG_FILE="${INSTALL_DIR}/config.conf"
if [ -f "$CONFIG_FILE" ]; then
CURRENT_VER=$(grep "^AGENT_VERSION=" "$CONFIG_FILE" | cut -d'"' -f2)
[ -n "$CURRENT_VER" ] && echo " 📍 目标版本: v${CURRENT_VER}"
fi
echo "========================================================"
# 1. 停止运行中的守护进程与主控模块
echo "[1/3] 正在终止后台 Telegram 守护进程与养护任务..."
pgrep -f tg_daemon.sh | xargs -r kill -9 >/dev/null 2>&1
pgrep -f runner.sh | xargs -r kill -9 >/dev/null 2>&1
pgrep -f mod_google.sh | xargs -r kill -9 >/dev/null 2>&1
# 1. 停止并删除 Systemd 服务 (适配新架构)
echo "[1/4] 正在停止并删除 Systemd 服务..."
if command -v systemctl >/dev/null 2>&1; then
echo "💡 检测到 Systemd 环境,正在抹除 Systemd 服务单元..."
systemctl disable --now ip-sentinel-runner.service ip-sentinel-runner.timer \
ip-sentinel-updater.service ip-sentinel-updater.timer \
ip-sentinel-report.service ip-sentinel-report.timer \
ip-sentinel-agent-daemon.service >/dev/null 2>&1
rm -f /etc/systemd/system/ip-sentinel-runner.service
rm -f /etc/systemd/system/ip-sentinel-runner.timer
rm -f /etc/systemd/system/ip-sentinel-updater.service
rm -f /etc/systemd/system/ip-sentinel-updater.timer
rm -f /etc/systemd/system/ip-sentinel-report.service
rm -f /etc/systemd/system/ip-sentinel-report.timer
rm -f /etc/systemd/system/ip-sentinel-agent-daemon.service
systemctl daemon-reload
systemctl reset-failed
else
echo "💡 未检测到 Systemd跳过此步骤..."
fi
# 2. 清除系统定时任务 (Cron)
echo "[2/3] 正在清理系统定时任务 (Cron)..."
crontab -l 2>/dev/null | grep -v "ip_sentinel" > /tmp/cron_backup
crontab /tmp/cron_backup
rm -f /tmp/cron_backup
# 2. 停止运行中的守护进程与主控模块 (兜底清理老版进程)
echo "[2/4] 正在终止后台守护进程与所有养护任务..."
pkill -9 -f "tg_daemon.sh" >/dev/null 2>&1
pkill -9 -f "agent_daemon.sh" >/dev/null 2>&1
pkill -9 -f "python3.*webhook.py" >/dev/null 2>&1
pkill -9 -f "webhook.py" >/dev/null 2>&1
pkill -9 -f "runner.sh" >/dev/null 2>&1
pkill -9 -f "updater.sh" >/dev/null 2>&1
pkill -9 -f "tg_report.sh" >/dev/null 2>&1
pkill -9 -f "mod_google.sh" >/dev/null 2>&1
pkill -9 -f "mod_trust.sh" >/dev/null 2>&1
# 3. 删除所有文件与日志
echo "[3/3] 正在抹除核心程序、配置文件与系统日志..."
# 3. 清除系统定时任务 (Cron)
echo "[3/4] 正在清理系统定时任务 (Cron)..."
if crontab -l >/dev/null 2>&1; then
crontab -l | grep -v "ip_sentinel" > /tmp/cron_backup
crontab /tmp/cron_backup
rm -f /tmp/cron_backup
fi
# 4. 删除所有文件、日志与临时缓存
echo "[4/4] 正在抹除核心程序、配置文件与系统痕迹..."
if [ -d "$INSTALL_DIR" ]; then
rm -rf "$INSTALL_DIR"
fi
# 拔除 /tmp 目录下的所有更新下载临时文件和 V1/V2 遗留的偏移量记录
rm -f /tmp/ip_sentinel_*.txt
rm -f /tmp/ip_sentinel_*.json
echo "========================================================"
echo "✅ 卸载彻底完成IP-Sentinel 已从您的系统中无痕移除。"
echo "👋 感谢您的使用,期待未来再次为您守护 IP"
echo "💡 提示:如果安装时在防火墙放行了 Webhook 随机端口,请您按需手动关闭。"
echo "👋 感谢您的使用,期待未来再次为您守护资产!"
echo "========================================================"

View File

@@ -1,14 +1,18 @@
#!/bin/bash
# ==========================================================
# 脚本名称: updater.sh (IP-Sentinel 养料注入与系统维护模块)
# 核心功能: 定期静默更新热数据、清理瘦身日志文件
# 脚本名称: updater.sh (IP-Sentinel 养料注入与分频调度中枢 - 动态锚点版)
# 核心功能: 静默更新热数据/LBS、指纹库错峰调度、强制出站死锁、版本无缝继承
# ==========================================================
INSTALL_DIR="/opt/ip_sentinel"
CONFIG_FILE="${INSTALL_DIR}/config.conf"
# 你的专属 Forgejo 仓库 Raw 数据直链前缀
REPO_RAW_URL="https://git.94211762.xyz/hotyue/IP-Sentinel/raw/branch/main"
UA_TIME_FILE="${INSTALL_DIR}/core/.ua_last_update"
# GitHub 仓库 Raw 数据直链前缀
REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/main"
# 临时改为开发地址用于测试
# REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/v3.6.2-rc"
# 1. 加载本地冷数据配置
if [ ! -f "$CONFIG_FILE" ]; then
@@ -16,37 +20,133 @@ if [ ! -f "$CONFIG_FILE" ]; then
fi
source "$CONFIG_FILE"
# 2. 全局日志写入函数
# 2. 全局日志写入函数 (v3.4.0 引入版本探针)
log() {
# [v3.4.0 核心] 提取当前配置中的版本锚点
local local_ver="${AGENT_VERSION:-未知}"
# 保证日志目录存在
mkdir -p "${INSTALL_DIR}/logs"
printf "[$(date '+%Y-%m-%d %H:%M:%S')] [%-5s] [%-7s] [%s] %s\n" "$2" "$1" "$REGION_CODE" "$3" >> "$LOG_FILE"
# 日志格式注入 [版本号] 追踪标识
local core_msg=$(printf "[v%-5s] [%-5s] [%-7s] [%s] %s" "$local_ver" "$2" "$1" "$REGION_CODE" "$3")
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $core_msg" >> "$LOG_FILE"
# 强制推送到 Systemd Journal (如果系统支持)
if command -v logger >/dev/null 2>&1; then
logger -t ip-sentinel "$core_msg"
else
# 降级输出到 stdout让 Systemd 捕获
echo "$core_msg"
fi
}
log "Updater" "INFO " "========== 触发后台静默 OTA 热数据更新 =========="
# 3. 容灾机制拉取 UA 池
TMP_UA="/tmp/ip_sentinel_ua.txt"
curl -sL "${REPO_RAW_URL}/data/user_agents.txt" -o "$TMP_UA"
if [ -s "$TMP_UA" ]; then
mv "$TMP_UA" "${INSTALL_DIR}/data/user_agents.txt"
log "Updater" "INFO " "✅ 设备指纹池 (User-Agents) 更新成功"
else
log "Updater" "WARN " "❌ UA 池拉取失败或为空,保留本地旧数据防崩溃"
rm -f "$TMP_UA"
# ==========================================================
# 🛡️ 终极护城河:构建强锚定出站的 curl 请求引擎
# ==========================================================
# 基础参数:跟随 install.sh 锁定的协议偏好 (4 或 6)
CURL_CMD="curl -${IP_PREF:-4} -sL"
# 【防坑核心】如果用户配置了死锁锚点,必须强制绑定网卡,杜绝流量溢出!
if [ -n "$BIND_IP" ]; then
# curl 的 --interface 参数不支持带方括号的 IPv6 地址,必须强行脱壳
RAW_BIND_IP=$(echo "$BIND_IP" | tr -d '[]')
# [v3.6.3 容错层补丁] 探测网卡存活状态,防止 IP 漂移导致永久断网
if ! ip addr show 2>/dev/null | grep -qw "$RAW_BIND_IP"; then
log "Updater" "WARN " "检测到绑定的出口 IP ($RAW_BIND_IP) 已丢失,自动退回默认路由!"
else
CURL_CMD="$CURL_CMD --interface $RAW_BIND_IP"
fi
fi
# 4. 容灾机制拉取当地最新搜索词库
# ==========================================================
# 3. 容灾机制拉取 UA 指纹池 (V3.3.0 引入 30 天错峰防惊群逻辑)
# ==========================================================
NOW=$(date +%s)
LAST_UPDATE=0
# 读取上一次更新的时间戳
if [ -f "$UA_TIME_FILE" ]; then
# tr -d 清除可能存在的换行或回车符,防止算术崩溃
LAST_UPDATE=$(cat "$UA_TIME_FILE" | tr -d '\r\n')
fi
# 校验数据合法性,防崩溃
if ! [[ "$LAST_UPDATE" =~ ^[0-9]+$ ]]; then
LAST_UPDATE=0
fi
DIFF=$((NOW - LAST_UPDATE))
# 距离上次拉取超过 30 天 (2592000 秒),才执行下载
if [ "$DIFF" -ge 2592000 ] || [ "$LAST_UPDATE" -eq 0 ]; then
TMP_UA="/tmp/ip_sentinel_ua.txt"
# 使用重装升级后的 CURL_CMD
$CURL_CMD "${REPO_RAW_URL}/data/user_agents.txt" -o "$TMP_UA"
if [ -s "$TMP_UA" ]; then
mv "$TMP_UA" "${INSTALL_DIR}/data/user_agents.txt"
echo "$NOW" > "$UA_TIME_FILE"
log "Updater" "INFO " "✅ 设备指纹池 (User-Agents) 30天错峰滚动更新成功"
else
log "Updater" "WARN " "❌ UA 池拉取失败,保留本地旧数据防崩溃"
rm -f "$TMP_UA"
fi
else
DAYS_LEFT=$(((2592000 - DIFF) / 86400))
log "Updater" "INFO " "⏳ 设备指纹池处于 30 天静默期 (剩余约 ${DAYS_LEFT} 天),跳过拉取"
fi
# ==========================================================
# 4. 容灾机制拉取当地最新搜索词库 (每日高频拉取,保证活体新鲜度)
# ==========================================================
TMP_KW="/tmp/ip_sentinel_kw.txt"
curl -sL "${REPO_RAW_URL}/data/keywords/kw_${REGION_CODE}.txt" -o "$TMP_KW"
$CURL_CMD "${REPO_RAW_URL}/data/keywords/kw_${REGION_CODE}.txt" -o "$TMP_KW"
if [ -s "$TMP_KW" ]; then
mv "$TMP_KW" "${INSTALL_DIR}/data/keywords/kw_${REGION_CODE}.txt"
log "Updater" "INFO " "✅ 区域搜索词库 (kw_${REGION_CODE}) 更新成功"
log "Updater" "INFO " "✅ 区域搜索词库 (kw_${REGION_CODE}) 每日同步成功"
else
log "Updater" "WARN " "❌ 搜索词库拉取失败,保留本地旧数据防崩溃"
rm -f "$TMP_KW"
fi
# 5. 【升级点】日志防满瘦身机制 (保留最近 2000 行)
# ==========================================================
# 5. 自适应拉取本地 LBS 专属 JSON 规则库 (每日同步)
# ==========================================================
REGION_JSON_FILE=$(find "${INSTALL_DIR}/data/regions" -name "*.json" 2>/dev/null | head -n 1)
if [ -n "$REGION_JSON_FILE" ] && [ -f "$REGION_JSON_FILE" ]; then
REL_PATH=${REGION_JSON_FILE#*${INSTALL_DIR}/}
TMP_JSON="/tmp/ip_sentinel_region.json"
$CURL_CMD "${REPO_RAW_URL}/${REL_PATH}" -o "$TMP_JSON"
if [ -s "$TMP_JSON" ]; then
mv "$TMP_JSON" "$REGION_JSON_FILE"
log "Updater" "INFO " "✅ 核心战区规则库 ($REL_PATH) 每日同步成功"
else
log "Updater" "WARN " "❌ 战区规则库拉取失败,保留本地旧数据"
rm -f "$TMP_JSON"
fi
fi
# ==========================================================
# 5.5. 容灾更新深海声呐底层探针 (彻底消除第三方 RCE 依赖)
# ==========================================================
TMP_PROBE="/tmp/ip_sentinel_probe.sh"
$CURL_CMD "https://raw.githubusercontent.com/xykt/IPQuality/main/ip.sh" -o "$TMP_PROBE"
if [ -s "$TMP_PROBE" ]; then
mv "$TMP_PROBE" "${INSTALL_DIR}/core/ip_probe.sh"
chmod +x "${INSTALL_DIR}/core/ip_probe.sh"
log "Updater" "INFO " "✅ 深海声呐底层探针 (ip_probe.sh) 源文件安全对齐"
fi
# ==========================================================
# 6. 日志防满瘦身机制 (保留最近 2000 行)
# ==========================================================
if [ -f "$LOG_FILE" ]; then
tail -n 2000 "$LOG_FILE" > "${LOG_FILE}.tmp"
mv "${LOG_FILE}.tmp" "$LOG_FILE"

200
data/keywords/kw_AU.txt Normal file
View File

@@ -0,0 +1,200 @@
alex de minaur
sunderland vs nottm forest
real betis vs real madrid
sai sudharsan
jannik sinner
gt vs rcb
amd stock
carey mulligan
jermaine jackson
hulk hogan
coles
elon musk
ben roberts-smith
ig
danish malewar
assassin's creed black flag resynced
sarfaraz khan
kartik sharma
instagram stories not working
meningococcal b
sundaresh menon
thunder vs suns
cade cunningham
real salt lake vs inter miami
pope francis
camera
anzac
teams
kids news
bonds
hung cao
classroom
michael jackson biopic movie
india women vs south africa women
nato
bayern munich
barcelona vs celta vigo
bournemouth vs leeds
leverkusen vs bayern
psl
burnley vs man city
elche vs atlético madrid
lsg vs rr
pakistan super league
kyle sandilands alleged rant jackie o
carrie bickmore
adam levine
alexandra eala
tubi
charles melton
nuclear weapon
janet jackson
justin bieber australia tour
fleche wallonne 2026
ange postecoglou
john hattie
airbus a380
real madrid vs alavés
brighton vs chelsea
woolworth
nitish rana
lyrid meteor shower
世界地球日
youth gang
earth day
crystal palace vs west ham
d4vd
mi vs gt
perth weather
elijah hollands carlton football club
fair work commission fuel
vanguard
sydney sweeney
cailee spaeny
psg vs lyon
sporting vs benfica
celtics vs 76ers
bundesliga
pl
afc cup
mars rover
celtic fc
bayern vs vfb stuttgart
bom radar
sydney weather
melbourne weather
brisbane weather
adelaide weather
myGov login
news.com.au
abc news
nrl ladder
afl scores
afl fixture
matildas
sam kerr
bunnings opening hours
coles catalogue
woolies specials
qantas
virgin australia
jetstar flights
commbank
asx 200
sydney morning herald
the age
ticketek
ticketmaster
opal card top up
myki top up
translink timetable
transperth journey planner
adelaide metro
adelaide 500
adelaide crows
port adelaide
penrith panthers
brisbane broncos
collingwood fc
sydney swans
west coast eagles
fremantle dockers
canberra raiders
mcg events
optus stadium
the gabba
state of origin
australian open
melbourne cup
masterchef australia
mafs australia
petrol prices near me
australia post tracking
service nsw login
vicroads
queensland health
medicare
ato
jb hi-fi
kmart
amazon.com.au
vivid sydney
mona hobart
dark mofo
floriade canberra
rottnest island ferry
sydney airport arrivals
rba interest rate
nsw school holidays
qld school holidays
wa school holidays
m4 traffic updates
west gate tunnel updates
bruce highway traffic
taylor swift
netflix
gemini
chatgpt
margot robbie
oscar piastri
formula 1
supercars championship
ufc
optus sport
telstra outage
kayo sports
domain real estate
realestate.com.au
seek jobs
gumtree
westpac login
anz internet banking
nab login
aldi catalogue
big w
target australia
the good guys
officeworks
dan murphys
bws
chemist warehouse
priceline
uber eats
menulog
dominos
centrelink login
medicare online
passport renewal
aec enrolment
agl energy
origin energy
stan
binge
9now
7plus
abc iview
hoyts cinemas
event cinemas
big bash league
the ashes

150
data/keywords/kw_CA.txt Normal file
View File

@@ -0,0 +1,150 @@
lpga leaderboard
randy travis
execution by firing squad
nelly korda
leicester city vs millwall
asteroid
sunderland vs nottm forest
real betis vs real madrid
betis real madrid
napoli vs cremonese
gta 6
japon
padres vs rockies
guide de la révolution de l'iran
casa pia vs braga
denaturalization
ocean
alberta referendum
vfb stuttgart vs sc freiburg
gpt 5.5
noah cates
pwhl scores
hank idsinga
karoline leavitt
ottawa charge
million dollar secret
white sox vs diamondbacks
suns vs thunder
stars vs wild
jaafar jackson
airport
grand theft auto vi
pentagone
etats unis
monette farms news
jose soriano
jon cooper
barcelona vs celta vigo
764
david scott
rodrigo duterte
u18 world championship
zara tindall
graham platner
lsg vs rr
nikki glaser
global news edmonton
policier
nuclear weapon
motorcycle
msc francesca
poet stock
fifa tickets
7 jours
alexandra eala
earth
zara larsson
girona vs real betis
kevyn adams
ali khamenei
inter côme
leicester city vs hull
fenerbahçe
françois bonnardel
missile
real madrid vs alavés
vrabel and russini photos
will trent
ibm
lecce vs fiorentina
celeste rivas hernandez
abhishek bachchan
national guard of the united states
triathlon
vincent trocheck
benyamin netanyahou
kings vs avalanche
crème solaire
trabzonspor vs istanbul başakşehir
indigenous rights
meghan, duchess of sussex
gwyneth paltrow
toronto gas prices
président
mets vs cubs
matt fitzpatrick
sénateurs hurricanes
senators vs hurricanes
man utd
spurs
evan mobley
chelsea vs man united
atlético madrid vs real sociedad
roma vs atalanta
cf montreal
jakob poeltl
ukraine
contrôle routier québec
bachelorette 2026
lens toulouse
arber xhekaj
leylah fernandez
anthropic
paige wwe
inter cagliari
carrie ann inaba
syria
highway hotline sk
real betis vs braga
vincent bolloré
europa conference league
resident alien
battlefield 6
aston villa vs bologna
nottm forest vs porto
soccer
lamour est dans le pré
luis suárez
listeria
strc
bayern
arda güler
aleksandar pavlović
kooora
yalla kora
ina garten
jordan goodwin
jerami grant
jimmy snuggerud
clav
bts
zach galifianakis
billy crystal
club américa vs nashville
allison williams
CBC News
Canada.ca
Toronto Weather
NHL Scores
Amazon.ca
Air Canada
Service Canada
CRA login
Rogers
Bell Internet
Tim Hortons
Indigo
Canadian Tire
Walmart Canada
Toronto Raptors

173
data/keywords/kw_DE.txt Normal file
View File

@@ -0,0 +1,173 @@
christian lindner
kevin costner
samu haber
gillian anderson
peggy jerofke
rafael jódar
ernie dosio
bibi heinicke
denia
der alte blaue stunde
matthias ginter
ralf schmitz
maximilian eggestein
hull city
demirovic
elton john
jeff chabot
lindt schokolade
manzambi
angelo stiller
lamine yamal verletzung
peer steinbrück
h&m
lotto 6aus49
pistons magic
chemnitzer fc erzgebirge aue
asiago
23 nisan
sternschnuppen heute lyriden
aryna sabalenka
michael douglas
herman van veen
georgina fleur
tui
trainer bayern münchen
katie holmes
prinz frederic
bayern vs
flekken
бернли манчестер сити
ard
queen camilla
clankriminalität
politik
gladbach-news
sara gündogan
krankenversicherung
jan-lennard struff
bryan lasme
republikanische partei
thailand
robin gosens
maremma
tennis madrid
osterburg
برايتون ضد تشيلسي
sebastian hoeneß
ncis
menowin fröhlich
maren gilzer
cineplex
gina schumacher
alexander räuscher
riza kayaalp
heppenheim
ministerpräsident
robbie williams
brian littrell
saarbrücken hauptbahnhof
frauen-bundesliga
lemgo
kommissar rex
hemsbach
benjamin weber
sydney sweeney
martin schindler
robert kennedy
antoni kowalski
luna
paris-sg lyon
arte live
dominik kohr
dumbledores geheimnisse
kampf der realitystars
kerner
tennessee
billy idol
kfc uerdingen
bastian pastewka
gnabry
lok leipzig heute live ticker
true lies wahre lügen
челси манчестер юнайтед
nurburgring
fortnite server status
süperlig
ronaldinho
esther schweins let's dance
michael jackson film 2026
oliver pocher
die queen film
milano
straße von hormus
motsi mabuse
rayo vallecano
harry meghan
irland
betis sevilla
vermisste person
konferenz league
garda
judith hoersch
jörg pilawa
strasbourg
real madrid vs bayern
kicker
mbappe
flashscore
sport1
vini jr
bet365
kompany
jude bellingham
upamecano
gute zeiten, schlechte zeiten
inflation
fog warning
wetter bochum
wetter aachen
wetter bonn
onet
protest
jamie dornan
heizöl
champions league
uefa champions league
keytruda
péter magyar
psg
hechingen
şampiyonlar ligi
tschernobyl 1986
amazon video
paris saint-germain
dietrich grönemeyer
fränkische schweiz
scarlett johansson
jeff bezos
dan brown
паспорт громадянина україни для виїзду за кордон
serena williams
манчестер юнайтед лидс
catherine deneuve
bobzin
sprit
kev
abschiebung
steuer
masters rory mcilroy
großglockner
news38
jessie cave
michael schulte
wetter frankfurt heute
bundesliga ergebnisse
aktuelle nachrichten deutschland
restaurant in der nähe
deutsche bahn fahrplan
urlaub buchen
rezept für kartoffelsalat
dax aktueller stand
apotheke notdienst frankfurt
günstige flüge

149
data/keywords/kw_ES.txt Normal file
View File

@@ -0,0 +1,149 @@
rafa jodar
samantha vallejo-nágera
ريال بتيس ضد الريال
nvidia
rafael jódar
jodar tenista
sunderland afc - nottingham forest
rb leipzig - fc union berlin
julián alvarez
stade brestois - lens
clasificación de primera división
javier hidalgo
cayetano martínez de irujo
llanes
vfb stuttgart freiburg
roca rey
psv - zwolle
daredevil
a que estas esperando
real oviedo - villarreal
real salt lake - inter miami
pistons - magic
barcelona sc - mushuc runa
kick
raphinha
lluvia estrellas liridas
frenkie de jong
santos - coritiba
del cerro grande
phillip cocu
cospedal
david wilcock
barcelona - celta de vigo
barcelone celta vigo
macarena gómez
luis merlo
bournemouth vs leeds
racing de estrasburgo - niza
burnley vs man city
alaska cantante
raúl gonzález blanco
marta sanchez
roberto bautista
cifras y letras
xbox game pass ultimate
horse powertrain
las hurdes
herbicida cancer colon
lluvia de barro
ripoll
manilva
steve jobs
berrettini
prizmic
laura moure
lens - toulouse
girona vs real betis
yuri berchiche
clasificacion liga
posiciones de la liga
resultados liga
lfp
umar sadiq
реал мадрид алавес
jan virgili
moreirense - estoril
downton abbey
koldo garcía izaguirre
jorge martín
mike james
carla leite
eclipse solar del 12 de agosto de 2026
crystal palace - west ham
luz valdenebro
porto - tondela
santos - fluminense
juventus
almería - málaga
punjab kings vs lucknow super giants standings
mönchengladbach mainz
victor eloy
paris-sg lyon
psg vs lyon
zamora - osasuna b
estrecho
nurburgring
la 1 directo
oyarzabal
enrique cerezo
fraude
tasa
la 1
tve directo
cuántas copas del rey tiene la real sociedad
eugenia martínez de irujo
ccoo
racing de santander
racing
baliza v16
st. pauli köln
iphone 18
st. pauli - colonia
nico paz
lionel messi
armengol
pau víctor
braga fc
fiorentina vs crystal palace
morante hoy
iago aspas
aston villa
real betis vs braga
ministerio de sanidad
az - shakhtar
arsenal
tiktok
harry kane
sudan
lunin
airef
tiempo de juego
fc bayern
militao
bellingham
supervivientes
jalen green
rockstar games
bam adebayo
china
suns - trail blazers
euromillones
ldu quito - mirassol
davion mitchell
universitario - coquimbo unido
El País
Marca
RTVE Noticias
La Liga
Real Madrid
Barcelona FC
Tiempo Madrid
Renfe
Iberia
Amazon España
El Corte Inglés
Hacienda
Mercadona
YouTube Música
Entradas Cine

167
data/keywords/kw_FR.txt Normal file
View File

@@ -0,0 +1,167 @@
lena situation
rafael jódar
mask singer
alex de minaur
oyonnax agen
lucie castets
napoli - cremonese
ligue1+
agnes lassalle
jean luc reichmann
m6
caitlyn jenner
star academy
bfm marseille provence
hunter schafer
unchosen netflix
john travolta
valence-romans brive
reem kherici
will smith
real salt lake inter miami
neymar
les traîtres
jacob elordi
pistons magic
invincible
santos coritiba
ios 18
la liga
royaume uni interdiction tabac
stephane tapie
tondelier
benjamin duhamel
loto 22 avril 2026
interdiction tabac royaume uni
lol qui rit sort
eva longoria
alain bauer
achraf hakimi
ibrahim mbaye
mma
roberto calvet
budget
coupe du monde de football 2006
plus belle la vie en avance
mateus fernandes
tour des alpes 2026
lorenzo finn
maine-et-loire
mathieu flamini
kamel daoud
vandalisme
sydney sweeney
julien odoul
france2
xavier dupont de ligonnès
elisabeth 2
antibes
girona betis
christine bravo
الريال ضد ألافيس
madonna age
margot haddad
ana riera
hinaupoko devèze
bruce toussaint
cheque energie
reid wiseman
loto 20 avril 2026
from serie
toulouse
racing 92 stade français
juventus - bologna
film une annee difficile
échouement
programme tv ce soir
porto tondela
matthieu pigasse
santos fluminense
gta 6
laetitia milot
loto 18 avril 2026
bercy
pierre lellouche
adele
adil rami
castres toulouse
angel
stéphane bern
anne claire coudray
pmu résultat
laury thilleman et paul mirabel
quinté du jour
euromillions 17 avril 2026
uson
guillaume meurice
pmu
grenoble oyonnax
bagarre
programme télé
tchernobyl
géraldine maillet
biot
racing
liga europa
tv ce soir
programme tv de ce soir
brad pitt
aston villa
michael olise
robert ménard
match ce soir
sporting
ester exposito
bellingham
iptv
militao
jeff goldblum
lunin
kiev
julien royal
viktor orbán
aqababe
nhl
suns trail blazers
bam adebayo
davion mitchell
l
santos recoleta football club
atletico madrid
tf1
uefa champions league
camille cerf
giorgi mamardashvili
streaming football
atlético madryt fc barcelona
miss france
rts
leonardo balerdi
yann barthes
alain delon
loto du 13 avril 2026
juan arbeláez
hbo
katy perry justin trudeau
tondela gil vicente
le rugbynistère
epstein
kino
horoscope du 13 avril 2026
golf masters augusta 2026
boursorama bourse
cac 40
sept à huit
ligne 12 métro
alice taglioni
pedro sánchez
meteo paris
actualités en direct
résultats ligue 1
pharmacie de garde
horaires sncf
recette crêpes
cac 40 en direct
acheter billet louvre
boulangerie autour de moi
carte vitale ameli

162
data/keywords/kw_HK.txt Normal file
View File

@@ -0,0 +1,162 @@
米高積遜
jaafar jackson
nvda
吳業坤
麻疹
林盛斌
cuaca besok
明天的天氣
weather tomorrow
rthk
weather hong kong
天文台
hk observatory
observatory
csk vs mi
長沙灣
魔音女團
球迷世界
天星銀行
game
林嘉華
套餐
賈曉晨
hk weather
綠色債券
barcelona vs celta vigo
weather
7-eleven
天气
班來 對 曼城
埃爾切 對 馬德里競技
rosenior
艾納斯
liam rosenior
巴黎聖日耳曼 對 南特
chatgpt image 2
啟德醫院
李泳漢老婆
破產
繼承人
英皇群星演唱會
布浩榮
新聞
貨幣貶值
居 屋 2025
3988
李泳豪老婆
皇家馬德里 對 艾拉維斯
李泳漢
鄭欣宜
srh vs dc
鍾嘉欣
張柏芝
江美儀
全港戲院日 2026
江旻憓
陶傑
水晶宮 對 西漢姆聯
吉達艾阿里
山口智子
百佳超級市場
利息
戴祖儀
陳若思
麥當勞
首岸
中国商飞c919
pl
bundesliga
hailey bieber
德甲
cherki
now
曼城
now tv
al nassr
洪金寶
曼聯
車路士
切爾西 對 曼聯
英超
何沛珈
熱刺
tottenham vs brighton
熱刺 對 布萊頓
epl
司機
补贴
華富邨
零售
藍莓
商湯科技
周國豐
啟點
歐聯
神戶勝利船
潘宏彬
姚正菁
木乃伊
ios 26
李克寧木乃伊
田啟文
曼寧加
arsenal
ucl
歐洲聯賽冠軍盃
arsenal vs sporting
bayern vs real madrid
real madrid
皇馬
拜仁慕尼黑 對 皇家馬德里
claude
補貼
nba 直播
航空公司
向華強
李嘉欣
typhoon
nba
nba線上看
nba直播
全民國家安全教育日
運輸署
liverpool vs psg
利物浦
barcelona
歐冠
馬德里競技 對 巴塞隆納
利物浦 對 巴黎聖日耳曼
hkjc
馬會
航空
2035
man united vs leeds
曼聯 對 里茲聯
prediction market
預測市場
polymarket
巴基斯坦
sndk
楊何蓓茵
樂珈嘉
姜濤
日經平均指數
飲茶
上市公司
daniel caesar
中年好聲音4
香港天文台
煤氣
livenation
政府
香港天文台天氣預報
MTR 港鐵路線圖
OpenRice 附近美食
LIHKG 討論區
恆生指數今日行情
SCMP breaking news
HKEX 港交所股價
國泰航空航班狀態
香港迪士尼樂園門票
百佳超級市場網購

View File

@@ -1,7 +1,163 @@
ベティス 対 rマドリード
dior
伊藤美来
フィギュア
玉置浩二
生田絵梨花
日本高野連会長辞任
anaheim
sbiグローバルアセットマネジメント
ストレンジャーシングス
石油
ios 26.4 2
ポケモンカード
シュトゥットガルト 対 フライブルク
ドラクエ スマグロ 攻略
ipl
kick
アコム
鈴木愛理
sox指数
村上世彰
桐山 照史
マラッカ海峡
ソニック
sbi新生銀行 株価
マイクラ
川口 春奈
サンダー 対 サンズ
インフルエンサー
サンケイビル
岡村隆史
上田竜也
メタプラネット
バルセロナ 対 セルタ
三橋くん
エルニーニョ
バーンリー 対 マンc
ボーンマス 対 リーズ u
elche vs atlético madrid
レバークーゼン 対 バイエルン
ソシエダ 対 ヘタフェ
サイメモリ
b リーグ 順位
日ハム
ナダル
失点
岩瀬洋志
ファイターズ 試合
江村美咲
宝島社
井ノ原 快彦
ファイターズ
西郷隆盛
ボーダー
チェルシー
関税
ブライトン
佳子内親王
rマドリード 対 アラベス
鳥貴族
ブライトン 対 チェルシー
アシエンダ乗馬学校
ngày trái đất
加藤小夏
町田ゼルビア
モンスターハンターシリーズ
クリスタル・パレス 対 ウェストハム
吉田正尚
旭琉會
神戸
てんちむ
浜辺美波
デーブ ロバーツ
皇治
小雪
にじさんじデビュー
ちゃんよた
坂本 花織
松山 千春
リーグアン
伊勢谷友介
bayern vs vfb stuttgart
chelsea vs man united
唐田えりか
102回目のプロポーズ
デゼルビ
アトレティコ 対 ソシエダ
チェルシー 対 マンu
スパーズ
清春
ディエゴ・ゴメス
ps5
ハイウェイ の 堕 天使 興行 収入
カブス 対 メッツ
dazn
サッスオーロ 対 コモ
杉咲花
町田 対 アル・イテハド
家計
週末旅の極意
北斗の拳
qvc
小芝風花
中井亜美
afc u20女子アジアカップ
ネオジオ
uefaヨーロッパリーグ
加藤史帆
志田未来
伊藤英明
島田麻央
al-nassr vs al-ettifaq
arsenal
レアル・マドリード
バイエルン
abema
real madrid
lucknow super giants vs royal challengers bengaluru standings
bayern vs real madrid
給付
wowow
小泉進次郎
政権
ミキティ
今日のドジャースの結果
新名神高速道路
わたせせいぞう
ピーチ航空
山本由伸
アレックス・ベシア
リバプール
champions league
アトレティコ 対 バルセロナ
オープンワールド
atlético madrid vs barcelona
松田好花
リコール
man united vs leeds
白鵬翔
日本アカデミー賞 最優秀助演男優賞
マンu 対 リーズ u
サンディスク 株価
らじるらじる
マクドナルド
ロシア
広島市
ゲイブル・スティーブソン
日本維新の会
新 日本 繊維
高見沢 俊彦
不登校
後期高齢者医療制度
バーミヤン
宮澤エマ
チケプラ
横綱
宮里美香
東京 天気 明日
新宿 おすすめ 居酒屋
最新のニュース 速報
ゴールド 相場 チャート
近くの静かなカフェ
地震 速報
円安 影響 生活
円安 影響 生活

110
data/keywords/kw_KR.txt Normal file
View File

@@ -0,0 +1,110 @@
트와이스
s
엔비디아 주가
이경실
신발
하현상
김수희
gt vs rcb
야닉 시너
amd 주가
왕다루
시그널
모하메드 살라
공화당
윤하정
청남대
더보이즈
노민우
서비스나우
김민지
박해미
국가유산청
삼성전자 주가
두산에너빌리티 주가
김성수
한국사
삼성전기 주가
국립중앙박물관
대우건설 주가
지방 선거
서정대학교
캔바
한국항공우주산업
디트로이트 대 올랜도
리그 1
elche vs atlético madrid
알나스르
al-nassr vs al ahli
10
로세니어
psg 대 낭트
테슬라 실적발표
루카스 모우라
9950x3d2
삼천당 제약 간담회
김재윤
k리그1 순위
유영찬
이호연
sxmb
문재인
생산직
강훈식
cnn
리그오브레전드
박환희
박지현
카토
와우넷
지구의 날
컴프야
차지연
크리스털 팰리스 대 웨스트 햄
비상계엄
연기금
배틀그라운드
제이홉
두산로보틱스
부부
미노이 우원재
danish malewar
mi vs gt
양치 승
프리미어리그
pl
bundesliga
맨체스터 시티 fc
fotmob
윤아
김영인
манчестер сити арсенал
케이뱅크
날씨
환율
손흥민
토트넘 경기 일정
넷플릭스
국민은행
네이버웹툰
로또 당첨번호
쿠팡
KBO 리그
프로야구 순위
아이폰 15
챗gpt
인스타그램
유튜브 밴스드
이강인
김민재
LCK 일정
T1
페이커
무빙
카카오톡 PC버전
당근마켓
배달의민족
올리브영
메이플스토리

44
data/keywords/kw_MY.txt Normal file
View File

@@ -0,0 +1,44 @@
sunderland vs nottm forest
real betis lwn real madrid cf
napoli vs cremonese
real betis vs real madrid
perfect crown ep 5
siti mastura mohamad
jannik sinner
sai sudharsan
yaris cross hybrid
cretaceous kraken
rayo vallecano vs espanyol
dji lito x1
levante vs sevilla
danish malewar
mukesh choudhary
lyrid meteor showers
jamie overton
piala uber
madrid open
dewald brevis
counter strike
pistons vs magic
real salt lake vs inter miami
chart gpt
asiago
liza hanim
good morning
pandikar amin mulia
勒沃库森 - 拜仁
santos vs coritiba
Malaysia
Kuala Lumpur
Bursa Malaysia
Ringgit
Maybank
CIMB
Shopee MY
Lazada Malaysia
KWSP i-Akaun
LHDN MyTax
Anwar Ibrahim
Johor Bahru
Penang
Nasi Lemak

146
data/keywords/kw_NL.txt Normal file
View File

@@ -0,0 +1,146 @@
wesley sonck
arnold schwarzenegger
devil wears prada
jagiellonia białystok górnik zabrze
unchosen
max verstappen redbull
mvv - top oss
energiecontract
real betis - real madrid
fc den bosch
maarten van rossem
jake paul
financiën
zonnepaneel
xrp
cyprus
verdachte
112 eerbeek
golden earring
sergiño dest
david wilcock
asiago
shownieuws
nijmegen
keira knightley
112 meldingen amsterdam
dierenmishandeling
112 amsterdam
freek rikkerink
poetin
atalanta - lazio
mr nobody against putin
club brugge - mechelen
frank hosmar
barcelona - celta
kees flodder
burnley - manchester city
lodewijk asscher
vallende sterren
guus meeuwis
hoofddorp
kaja kallas
politiek
stroomstoring amersfoort
solvinity digid
wout weghorst
jamie kames
bitvavo
box 3
ronde van de alpen
matthias uhl
taken film
robot
girona - real betis
real madryt deportivo alaves
tbilisi
southampton - bristol city
vittoria guazzini
oppo find x9 ultra
real madrid - alavés
الريال ضد ألافيس
lecce - fiorentina
pogoda jutro
vierhouten
weather tomorrow
over mijn lijk 2026 overleden
crystal palace - west ham
f-16 fighting falcon
klagenfurt
italië
ruud gullit
perfil falso
psg - lyon
juventus - bologna
troy parrott
az - nec opstellingen
caroline tensen
asielbeleid
philippe sandler
keerbergen
peer koopmeiners
nederlands elftal
pogoń szczecin lech poznań
stand premier league
bulgarije
chelsea - man utd
atlético madrid - real sociedad
xavi simons
ayase ueda
roma - atalanta
rtv noord
paraguay
sergio herman
fed
keuken kampioen
legia warszawa zagłębie lubin
ripple
voorzitter fed
bahamas
overtreding
almere city
real betis
sean connery
l1 nieuws
ronaldinho
demi de boer
bondgenoten
frank masmeijer
real betis - braga
ethereum
aston villa - bologna
manuel neuer
neuer
olise
mbappe
sporting
live tv
bayern munchen
arda güler
ziggo
arda guler
netflix
frenkie de jong
kanye west
vandaag inside
at5
veroordeling
verenigde staten
alec baldwin
anna paulowna
şampiyonlar ligi
NOS Nieuws
Buienradar
Rijksoverheid
Albert Heijn
Funda
Marktplaats
KLM
Ziggo
ING Bank
Eredivisie
Amsterdam Weer
Bol.com
Treinkaartjes NS
PostNL
Pathé

168
data/keywords/kw_SG.txt Normal file
View File

@@ -0,0 +1,168 @@
sunderland vs nottm forest
real betis vs real madrid
anne hathaway
michael jackson
sai sudharsan
madrid open
amd
gt vs rcb
ijooz
raghav chadha
darren wang
mukesh choudhary
danish malewar
tamil nadu election results
allah ghazanfar
peregrine falcon
airasia flight
arrest
hao mart singapore
kartik sharma
real salt lake vs inter miami
pistons vs magic
krisflyer
michael jackson biopic
新加坡
atalanta vs lazio
伯恩利 - 曼城
porto vs sporting
cdl directors resign millennium copthorne
tsla
leverkusen vs bayern
burnley vs man city
elche vs atlético madrid
psg vs nantes
al-nassr vs al ahli
mohsin khan
changi
rr vs lsg
primary school
alexandra eala
tan su shan
sundaresh menon
moulin rouge musical singapore
south korea
step
gamba osaka vs avispa fukuoka
honor 600 pro
china shipyards oil tanker orders
coe
lebron james
real madrid vs alavés
brighton vs chelsea
nitish rana
earth day
michael movie
kevin warsh
srh vs dc
chinese aircraft carrier liaoning
andie chen
jesseca liu wins best actress
crystal palace vs west ham
grok
gemini
claude ai
gpt
ai
is chatgpt down
strait of hormuz news
mi vs gt
psg vs lyon
sporting vs benfica
bayern munich
pl
bangkok weather
starhub
廖子妤
曼城 - 阿森纳
bayern vs vfb stuttgart
英超
chelsea vs man united
perfect crown
ayush mhatre
sarfaraz khan
napoli vs lazio
tottenham vs brighton
abhishek sharma
tinie tempah
wrexham vs stoke city
sassuolo vs como
the straits times
india women vs south africa women
beef season 2
loyang valley
world cup 2026
afc champions league
hormuz
malacca strait
kkr vs gt
aston villa vs bologna
mumbai indians vs punjab kings standings
al sadd vs vissel kobe
amd share price
opus 4.7
pete hegseth
naman dhir
yen singapore dollar
mayank rawat
dji pocket 4
real madrid
al-nassr vs al-ettifaq
bayern vs real madrid
arsenal vs sporting
lucknow super giants vs royal challengers bengaluru standings
is claude down
claude
allbirds
red sea
rcb vs lsg
retirement
asia flights delays cancellations
suns vs trail blazers
johnny somali
bam adebayo
zhang linghe pursuit of jade
roman gofman
cruz azul vs lafc
ocbc
santos vs recoleta
atlético madrid vs barcelona
ipl schedule
liverpool vs psg
iran blockade strait of hormuz
kartik tyagi
carlos alcaraz
propertylimbrothers
byeon woo-seok
mahathir mohamad
csk vs kkr
man united vs leeds
cbse class 10 result 2026 date
euphoria season 3
srh vs rr
tamil new year 2026
low de wei
pope
flexar
microsoft outlook
new rolex 2026
medical classification
blasphemy law
big bang coachella 2026
小贩
malaysia fuel price crisis
sbti personality test
cancer survivor
tim cook
spurs vs nuggets
asia flights cancelled delayed
singapore weather forecast
mrt map singapore
straitstimes breaking news
cpf board login
hdb bto launch updates
best chicken rice near me
public holidays sg
singpass login portal
changi airport flight status
iras tax filing

122
data/keywords/kw_TW.txt Normal file
View File

@@ -0,0 +1,122 @@
cpo概念股
anaheim
iu
山口智子
蔡依珊
林岱安
michael jackson 電影
行動電源
地震
地震速報
宋祖兒
porter
謝京穎
德州儀器
台新綜合證券
希臘
費城半導體
mrvl
狄鶯
三星罷工
00981a
馬斯克
辛耘
宏碁股價
0056
2330
雷霆 對 太陽
0050股價
006208
景碩
女警陳芊雯
廢死聯盟
西甲
台灣積體電路製造
高頻寬 記憶 體
戴奧辛
3665
宋晟睿
黃 甘霖
劉家翔
王耿豪
王勝偉
009816
thời tiết ngày mai
明天的天氣
總部
美光科技
cpbl
中華職棒
中職
黃甘霖
軍 公教
6147
earth day
陳哲遠
台鐵
斯普拉遁 塗擊隊
麥可傑克森
神將彩券行
米可白
洪敬堯
華邦電子
柔美的細胞小將 3
底特律老虎
三 商 美邦
川 普
英雄聯盟
聯電adr
rklb
amd stock
宋仲基
兵工廠
德甲
塞爾提克 對 76人
justin bieber 演唱會
拜仁慕尼黑
何潤東
廖子妤
英超
許凱
tottenham vs brighton
長野縣
交通安全
朋友收集夢想生活
麥克傑克森
王濛
騎士 對 暴龍
熱刺 對 布萊頓
iem rio 2026
garret anderson
墓乃伊
曹格
claude design
柯文哲
金剛
荷 姆 茲 海峽
東北 季風
斯圖加特公開賽
歐聯
菡生婦幼診所
台鐵訂票
飛機
東光路
货币
amd
航空母艦
axti
Yahoo奇摩
天氣
蝦皮購物
PChome
Momo購物網
Mobile01
Dcard
巴哈姆特
中時電子報
聯合新聞網
台灣高鐵
台鐵時刻表
中華電信
統一發票
勞動部

171
data/keywords/kw_UK.txt Normal file
View File

@@ -0,0 +1,171 @@
napoli
alex de minaur
tigers vs hull fc
edinburgh vs sharks
mark williams snooker
criminal record
alex sinclair israeli police detention
st. johnstone vs raith rovers
mo farah
newcastle vs bristol
tbilisi
connor storrie
georgia
stephen bunting
great british menu 2026
ravi eastenders
salford city fc
national grid
mass effect
salford city vs bromley
real salt lake vs inter miami
provinces of the pantheon
mls
russell brand
john phelan
hung cao
pistons vs magic
jerry bruckheimer
st. george's day
asiago
framework laptop 13 pro
boro
interactive investor
mint
believe me itv
amanda bynes
strasbourg vs nice
chase bank
jak jones
chase
rodri
christopher trybus
lsg vs rr
pension
hebden bridge
sandra bullock practical magic
rolls-royce share price drop
invincible season 5
josé mourinho
chris wakelin
jimmy bullard adam thomas
aer lingus flight cancellations
sam west
oxford united
liam delap
wba
реал мадрид алавес
coppa italia
girona vs real betis
marcus rashford
الريال ضد ألافيس
supreme leader of iran
oscar isaac
xrp ledger
pablo
is tane leaving home and away
julie andrews
danny boyle
nina eastenders
john stones
amazon vega os fire tv
porto vs tondela
santos vs fluminense
martin brundle lost f1 seat
keegan bradley
david attenborough
antoni kowalski
kezia dugdale
car
beef netflix
juventus vs bologna
losc vs nice
david szalay
the killer
joe cole
lille fc
simon cowell
pl
frank lampard everton
nottingham forest fixtures
everton manager
dragons vs bulls
suede
lahore
wrestlemania 2026
giants vs rhinos
glenrothan
york knights vs leopards
tim sherwood
redditch
ccfc
europa conference league
bromley fc
paul merton
chris wood
istanbul
turkey
lucy watson
thiago silva
bednarek
jan bednarek
vincent kompany
mbappe
luis suarez sporting
madrid fc
andriy lunin
what did bec say to rachel mafs
yalla kora
geovany quenda
sporting cp
pavlovic
talktalk
arne slot drops mohamed salah
suns vs trail blazers
italian
used cars
mlb
roman
johnny somali
windows update
davion mitchell
hbo max
bolton wanderers
barca vs atletico
kemi badenoch
warren zaïre-emery
barca
samuel west
barcelona fc
lamine yamal
hbomax
noah okafor
casemiro
talksport
lazio
leeds united fixtures
bruno fernandes
afc champions league
meteor
carlos queiroz
travel warning
tori amos
cloud
reading
rolls-royce smr
istanbul airport
a27
bridget phillipson
tottenham standings
may bank holiday 2026
toto wolff
london weather today
bbc news latest
premier league fixtures
tesco near me
tube map london
uk bank holidays
royal family news
how to make english tea
nhs symptom checker
property for sale in london

View File

@@ -1,6 +1,174 @@
alex de minaur
rafael jodar
adam levine face
howard frankland bridge
vibrio vulnificus new york waters
stade brestois - lens
moustapha thiam
us asylum seeker border reopening
sunderland vs nottm forest
leicester city vs millwall
brandon marsh
psv vs pec zwolle
daniel merida aguilar
william byron
eve plumb
mall of louisiana
real oviedo vs villarreal
real oviedo - villarreal
call of duty: black ops 7
tarik skubal
cubs game today
mike repole
okc thunder
atlanta braves
mlb scores today
braves standings
kevin mckidd
dan vladar
mls standings
dodgers - giants
jon ossoff
ozzy survivor
braves score
washington nationals
alex bregman
peter lambert
darrell sheets
ludwig kaiser
edina shooting
atalanta - lazio
barcelona vs celta vigo
rivian r2
pick 4
aoc
cleveland browns
nintendo switch gamecube games
lsg vs rr
spirit
atlanta fire
deshaun watson
good morning america
pittsburgh
strands answers
scientist
mark cuban pharmacy
inter milan
lens vs toulouse
david james
andy weir
noah kahan tiny desk concert
jennifer garner 54th birthday photos
troy baker
real madrid - alavés
girona - real betis
girona vs real betis
arc raiders
schd etf dividend yield
deportación
lecce - fiorentina
valley forge high school
betty yee
seth trimble
bill belichick
winter storm
jim parsons
kings vs avalanche
suns vs thunder
wolf
santos - fluminense
mets - cubs
alexander manninger
santos vs fluminense
disclosure day
tobias myers
vladimir putin
knicks game
ben rice
prem
timberwolves vs nuggets
cody bellinger
nik khamenia
real sociedad
nurburgring crash
atlético madrid - real sociedad
ruke orhorhoro
radar
the weather channel
kttc
luke gulbranson
kttc weather
comcast data breach settlement
tornado watch
moisés ballesteros
mets game today
giancarlo stanton
real betis
prosecution of daniel duggan
liv morgan
mikey williams
indiana fever sophie cunningham baptism
gregory donnell morgan jr
why are the sirens going off
leylah fernandez
strasbourg vs mainz
michael olise
ريال مدريد
dazn
paramount
univision
jude bellingham
sam antonacci
real madrid
bayern
arda güler
los angeles dodgers
vandenberg launch schedule
ryan dunn
alex vesia
ken jennings
ucla baseball
padres standings
mets vs dodgers match player stats
bo bichette
jorge polanco
psg
barca
vix
fcb
barcelona schedule
tarjeta roja
a knight of the seven kingdoms season 2
charlotte flair
usa network
natalie sago
carlos queiroz
carlos batista
katie boulter
levante - getafe
levante vs getafe
mcilroy green jacket presentation
man united vs leeds
7-eleven closing locations
cloud
sports
sony playstation
alaska airline
toronto
sydney
paris
tokyo
delhi
sykkuno drama
Los Angeles weather today
S&P 500 stock chart
local coffee shops near me
latest tech news
California traffic updates
AI startups in Silicon Valley
AI startups in Silicon ValleySan Jose weather this weekend
Silicon Valley tech news
best tacos in San Jose
Apple park visitor center hours
Seattle Weather
Las Vegas strip
Charlotte Hornets

146
data/keywords/kw_VN.txt Normal file
View File

@@ -0,0 +1,146 @@
napoli
sunderland đấu với nottm forest
betis đấu với real madrid
napoli đấu với cremonese
leipzig đấu với union berlin
sunderland
mẫu iphone 18
oppo find x9 ultra
xem phim
andoni iraola
stuttgart đấu với freiburg
levante sevilla
giao dịch tài chính
sevilla
rayo đấu với espanyol
levante đấu với sevilla
bong ma hanh phuc
aryna sabalenka
mason nguyễn
marcus rashford
hà nội
salt lake đấu với inter miami
hung cao
neymar
cầu phú mỹ
nhac
wordle
날씨
giá cà phê hôm nay
premier league standings
mls
phạm nhật vượng
cristiano roland
burnley vs man city
bayern munich
atalanta đấu với lazio
barcelona đấu với celta
mc vs
psg nantes
leverkusen đấu với bayern
elche atlético madrid
bryan mbeumo
al nasr
trực tiếp bóng đá hôm nay
vtv3
vtv3 trực tiếp
tv
vtv
vtv6
360
lê khánh
ô tô
lê phương
trực tiếp bóng đá u17 hôm nay
inter milan
chelsea
girona đấu với betis
real madrid đấu với alavés
brighton vs chelsea
brighton đấu với chelsea
ath. bilbao đấu với osasuna
pep guardiola
zelvia đấu với shabab al-ahli
cầu thủ
lecce vs fiorentina
fiorentina
crystal palace đấu với west ham
afc champions league
eduardo camavinga
vissel kobe
gemi
idp
bảo hiểm y tế
crystal palace vs west ham
sporting lisbon
psg vs lyon
ca sĩ
juventus đấu với bologna
gladbach đấu với mainz
twitch
psg đấu với lyon
juventus
ligue 1
trận đấu ngoại hạng anh
chelsea đấu với man utd
atlético madrid đấu với real sociedad
roma đấu với atalanta
epl
iem rio 2026
tot
tập đoàn gelex
đường ray
inter
inter đấu với cagliari
sassuolo vs como
david alaba
claude design
fenerbahçe đấu với rizespor
como
como vs
thẻ đỏ
al ahli
porto vs
crystal palace
porto
uefa europa conference
betis đấu với braga
real betis vs braga
aston villa đấu với bologna
fiorentina đấu với crystal palace
c2
cup c2
thể thao
arda güler
aleksandar pavlović
ars
90
real
real madrid
xoi
luong sơn
fpt
phan văn giang
nhà ở xã hội
club america
giàu
đỗ mỹ linh
sun group
hưng yên
nvl
américa đấu với nashville
VnExpress
Zing News
Thời tiết Hà Nội
Giá vàng hôm nay
Shopee VN
Tiki
Vietjet Air
Vietnam Airlines
Bóng đá trực tuyến
Lịch thi đấu Euro
Xổ số miền Bắc
Grab Vietnam
VTV Go
Học tiếng Anh
Du lịch Đà Lạt

407
data/map.json Normal file
View File

@@ -0,0 +1,407 @@
{
"version": "3.5.2",
"updated_at": "2026-04-19",
"continents": [
{
"id": "ASIA",
"name": "亚太战区 (Asia-Pacific)",
"countries": [
{
"id": "JP",
"name": "Japan (日本)",
"keyword_file": "kw_JP.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Tokyo",
"name": "Tokyo (东京)"
}
]
}
]
},
{
"id": "SG",
"name": "Singapore (新加坡)",
"keyword_file": "kw_SG.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Singapore",
"name": "Singapore (新加坡)"
}
]
}
]
},
{
"id": "KR",
"name": "South Korea (韩国)",
"keyword_file": "kw_KR.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Seoul",
"name": "Seoul (首尔)"
}
]
}
]
},
{
"id": "HK",
"name": "Hong Kong (香港)",
"keyword_file": "kw_HK.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "HongKong",
"name": "Hong Kong (香港)"
}
]
}
]
},
{
"id": "VN",
"name": "Vietnam (越南)",
"keyword_file": "kw_VN.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Hanoi",
"name": "Hanoi (河内)"
}
]
}
]
},
{
"id": "TW",
"name": "Taiwan (台湾)",
"keyword_file": "kw_TW.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Taipei",
"name": "Taipei (台北)"
}
]
}
]
},
{
"id": "MY",
"name": "Malaysia (马来西亚)",
"keyword_file": "kw_MY.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Kuala_Lumpur",
"name": "Kuala Lumpur (吉隆坡)"
}
]
}
]
}
]
},
{
"id": "EUROPE",
"name": "欧洲战区 (Europe)",
"countries": [
{
"id": "UK",
"name": "United Kingdom (英国)",
"keyword_file": "kw_UK.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "London",
"name": "London (伦敦)"
},
{
"id": "Coventry",
"name": "Coventry (考文垂)"
}
]
}
]
},
{
"id": "DE",
"name": "Germany (德国)",
"keyword_file": "kw_DE.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Frankfurt",
"name": "Frankfurt (法兰克福)"
}
]
}
]
},
{
"id": "FR",
"name": "France (法国)",
"keyword_file": "kw_FR.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Paris",
"name": "Paris (巴黎)"
}
]
}
]
},
{
"id": "NL",
"name": "Netherlands (荷兰)",
"keyword_file": "kw_NL.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Amsterdam",
"name": "Amsterdam (阿姆斯特丹)"
}
]
}
]
},
{
"id": "ES",
"name": "Spain (西班牙)",
"keyword_file": "kw_ES.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Madrid",
"name": "Madrid (马德里)"
}
]
}
]
}
]
},
{
"id": "AMERICAS",
"name": "美洲战区 (Americas)",
"countries": [
{
"id": "US",
"name": "United States (美国)",
"keyword_file": "kw_US.txt",
"states": [
{
"id": "CA",
"name": "California (加州)",
"cities": [
{
"id": "Los_Angeles",
"name": "Los Angeles (洛杉矶)"
},
{
"id": "San_Jose",
"name": "San Jose (圣何塞)"
}
]
},
{
"id": "IL",
"name": "Illinois (伊利诺伊州)",
"cities": [
{
"id": "Warrenville",
"name": "Warrenville (沃伦维尔)"
}
]
},
{
"id": "NC",
"name": "North Carolina (北卡罗来纳州)",
"cities": [
{
"id": "Charlotte",
"name": "Charlotte (夏洛特)"
}
]
},
{
"id": "NV",
"name": "Nevada (内华达州)",
"cities": [
{
"id": "Las_Vegas",
"name": "Las Vegas (拉斯维加斯)"
}
]
},
{
"id": "OR",
"name": "Oregon (俄勒冈州)",
"cities": [
{
"id": "Bend",
"name": "Bend (本德)"
}
]
},
{
"id": "UT",
"name": "Utah (犹他州)",
"cities": [
{
"id": "Salt_Lake_City",
"name": "Salt Lake City (盐湖城)"
}
]
},
{
"id": "WA",
"name": "Washington (华盛顿州)",
"cities": [
{
"id": "Seattle",
"name": "Seattle (西雅图)"
}
]
},
{
"id": "TX",
"name": "Texas (得克萨斯州)",
"cities": [
{
"id": "Dallas",
"name": "Dallas (达拉斯)"
}
]
}
]
},
{
"id": "CA",
"name": "Canada (加拿大)",
"keyword_file": "kw_CA.txt",
"states": [
{
"id": "Default",
"name": "Default State",
"cities": [
{
"id": "Toronto",
"name": "Toronto (多伦多)"
},
{
"id": "Montreal",
"name": "Montreal (蒙特利尔)"
}
]
}
]
}
]
},
{
"id": "OCEANIA",
"name": "大洋洲战区 (Oceania)",
"countries": [
{
"id": "AU",
"name": "Australia (澳大利亚)",
"keyword_file": "kw_AU.txt",
"states": [
{
"id": "NSW",
"name": "New South Wales (新南威尔士州)",
"cities": [
{
"id": "Sydney",
"name": "Sydney (悉尼)"
}
]
},
{
"id": "VIC",
"name": "Victoria (维多利亚州)",
"cities": [
{
"id": "Melbourne",
"name": "Melbourne (墨尔本)"
}
]
},
{
"id": "QLD",
"name": "Queensland (昆士兰州)",
"cities": [
{
"id": "Brisbane",
"name": "Brisbane (布里斯班)"
}
]
},
{
"id": "WA",
"name": "Western Australia (西澳大利亚州)",
"cities": [
{
"id": "Perth",
"name": "Perth (珀斯)"
}
]
},
{
"id": "SA",
"name": "South Australia (南澳大利亚州)",
"cities": [
{
"id": "Adelaide",
"name": "Adelaide (阿德莱德)"
}
]
}
]
}
]
}
]
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "Australia - Sydney",
"google_module": {
"base_lat": -33.8697,
"base_lon": 151.2085,
"lang_params": "hl=en-AU&gl=AU",
"valid_url_suffix": "com.au"
},
"trust_module": {
"white_urls": [
"https://www.abc.net.au/news/2026-04-24/india-delimitation-redraw-electoral-map-southern-states/106591486",
"https://www.seek.com.au/",
"https://www.abc.net.au/news/2026-04-24/kezie-apps-says-womens-state-of-origin-timing-not-ideal/106604306",
"https://www.abc.net.au/news/2026-04-25/outcome-farrer-byelection-one-nation-watershed-moment/106485956",
"https://www.woolworths.com.au/",
"https://www.abc.net.au/news/2026-04-25/how-iran-regime-changed-after-us-israel-middle-east-war/106595956",
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.abc.net.au/news/2026-04-25/sa-wwii-veterans-meet-after-more-than-80-years/106590394",
"https://www.abc.net.au/news/2026-04-25/nato-falklands-spain/106604984",
"https://www.abc.net.au/news/2026-04-24/act-government-will-not-cancel-big-splash-operators-lease/106603388",
"https://www.abc.net.au/news/2026-04-24/norway-plans-to-introduce-under-16s-social-media-ban/106604296",
"https://www.abc.net.au/news/2026-04-24/oyster-growing-closed-again-toxic-phytoplankton-yorke-peninsula/106601670",
"https://www.abc.net.au/news/2026-04-24/woman-chooses-to-go-blind-after-delays-at-adelaide-clinic/106602574",
"https://www.amazon.com.au/",
"https://www.commbank.com.au/",
"https://www.abc.net.au/news/2026-04-25/how-the-cost-of-the-ndis-blew-out/106604488",
"https://www.bom.gov.au/",
"https://www.bunnings.com.au/",
"https://www.abc.net.au/news/2026-04-24/nt-doctor-gross-indecency-rape-trial-court-suppression-order/106603984",
"https://www.realestate.com.au/",
"https://www.coles.com.au/",
"https://www.abc.net.au/news/2026-04-24/nrl-live-updates-cowboys-sharks-broncos-bulldogs/106591508",
"https://www.abc.net.au/news/2026-04-25/netanyahu-treated-for-prostate-cancer/106605028",
"https://www.abc.net.au/news/2026-04-25/april-25-5050-quiz/106601084"
],
"static_urls": [
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.bom.gov.au/",
"https://www.commbank.com.au/",
"https://www.seek.com.au/",
"https://www.realestate.com.au/",
"https://www.woolworths.com.au/",
"https://www.coles.com.au/",
"https://www.amazon.com.au/",
"https://www.bunnings.com.au/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "Australia - Brisbane",
"google_module": {
"base_lat": -27.4697,
"base_lon": 153.0252,
"lang_params": "hl=en-AU&gl=AU",
"valid_url_suffix": "com.au"
},
"trust_module": {
"white_urls": [
"https://www.abc.net.au/news/2026-04-24/act-government-will-not-cancel-big-splash-operators-lease/106603388",
"https://www.ato.gov.au/",
"https://www.abc.net.au/news/2026-04-25/netanyahu-treated-for-prostate-cancer/106605028",
"https://www.coles.com.au/",
"https://www.seek.com.au/",
"https://www.abc.net.au/news/2026-04-24/india-delimitation-redraw-electoral-map-southern-states/106591486",
"https://www.abc.net.au/news/2026-04-25/how-the-cost-of-the-ndis-blew-out/106604488",
"https://www.abc.net.au/news/2026-04-24/norway-plans-to-introduce-under-16s-social-media-ban/106604296",
"https://www.abc.net.au/news/2026-04-24/oyster-growing-closed-again-toxic-phytoplankton-yorke-peninsula/106601670",
"https://www.abc.net.au/news/2026-04-25/sa-wwii-veterans-meet-after-more-than-80-years/106590394",
"https://www.abc.net.au/news/2026-04-25/nato-falklands-spain/106604984",
"https://www.abc.net.au/news/2026-04-25/april-25-5050-quiz/106601084",
"https://www.abc.net.au/news/2026-04-24/nt-doctor-gross-indecency-rape-trial-court-suppression-order/106603984",
"https://www.abc.net.au/news/2026-04-24/nrl-live-updates-cowboys-sharks-broncos-bulldogs/106591508",
"https://www.woolworths.com.au/",
"https://www.commbank.com.au/",
"https://www.bom.gov.au/",
"https://www.abc.net.au/news/2026-04-24/woman-chooses-to-go-blind-after-delays-at-adelaide-clinic/106602574",
"https://www.amazon.com.au/",
"https://www.abc.net.au/news/2026-04-24/kezie-apps-says-womens-state-of-origin-timing-not-ideal/106604306",
"https://www.realestate.com.au/",
"https://my.gov.au/",
"https://www.abc.net.au/news/2026-04-25/how-iran-regime-changed-after-us-israel-middle-east-war/106595956",
"https://www.abc.net.au/news/2026-04-25/outcome-farrer-byelection-one-nation-watershed-moment/106485956",
"https://www.bunnings.com.au/"
],
"static_urls": [
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.bom.gov.au/",
"https://www.commbank.com.au/",
"https://www.seek.com.au/",
"https://www.realestate.com.au/",
"https://www.woolworths.com.au/",
"https://www.coles.com.au/",
"https://www.amazon.com.au/",
"https://www.bunnings.com.au/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "Australia - Adelaide",
"google_module": {
"base_lat": -34.9227,
"base_lon": 138.6016,
"lang_params": "hl=en-AU&gl=AU",
"valid_url_suffix": "com.au"
},
"trust_module": {
"white_urls": [
"https://www.bom.gov.au/",
"https://www.amazon.com.au/",
"https://www.abc.net.au/news/2026-04-24/norway-plans-to-introduce-under-16s-social-media-ban/106604296",
"https://www.abc.net.au/news/2026-04-25/outcome-farrer-byelection-one-nation-watershed-moment/106485956",
"https://www.abc.net.au/news/2026-04-25/april-25-5050-quiz/106601084",
"https://www.abc.net.au/news/2026-04-24/woman-chooses-to-go-blind-after-delays-at-adelaide-clinic/106602574",
"https://www.abc.net.au/news/2026-04-24/nrl-live-updates-cowboys-sharks-broncos-bulldogs/106591508",
"https://www.bunnings.com.au/",
"https://www.realestate.com.au/",
"https://www.commbank.com.au/",
"https://www.ato.gov.au/",
"https://www.abc.net.au/news/2026-04-25/netanyahu-treated-for-prostate-cancer/106605028",
"https://www.abc.net.au/news/2026-04-24/kezie-apps-says-womens-state-of-origin-timing-not-ideal/106604306",
"https://www.coles.com.au/",
"https://www.abc.net.au/news/2026-04-24/act-government-will-not-cancel-big-splash-operators-lease/106603388",
"https://www.seek.com.au/",
"https://www.abc.net.au/news/2026-04-25/how-the-cost-of-the-ndis-blew-out/106604488",
"https://www.woolworths.com.au/",
"https://www.abc.net.au/news/2026-04-25/sa-wwii-veterans-meet-after-more-than-80-years/106590394",
"https://my.gov.au/",
"https://www.abc.net.au/news/2026-04-24/india-delimitation-redraw-electoral-map-southern-states/106591486",
"https://www.abc.net.au/news/2026-04-24/oyster-growing-closed-again-toxic-phytoplankton-yorke-peninsula/106601670",
"https://www.abc.net.au/news/2026-04-24/nt-doctor-gross-indecency-rape-trial-court-suppression-order/106603984",
"https://www.abc.net.au/news/2026-04-25/how-iran-regime-changed-after-us-israel-middle-east-war/106595956",
"https://www.abc.net.au/news/2026-04-25/nato-falklands-spain/106604984"
],
"static_urls": [
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.bom.gov.au/",
"https://www.commbank.com.au/",
"https://www.seek.com.au/",
"https://www.realestate.com.au/",
"https://www.woolworths.com.au/",
"https://www.coles.com.au/",
"https://www.amazon.com.au/",
"https://www.bunnings.com.au/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "Australia - Melbourne",
"google_module": {
"base_lat": -37.8106,
"base_lon": 144.9624,
"lang_params": "hl=en-AU&gl=AU",
"valid_url_suffix": "com.au"
},
"trust_module": {
"white_urls": [
"https://www.abc.net.au/news/2026-04-24/nt-doctor-gross-indecency-rape-trial-court-suppression-order/106603984",
"https://www.ato.gov.au/",
"https://www.abc.net.au/news/2026-04-24/kezie-apps-says-womens-state-of-origin-timing-not-ideal/106604306",
"https://www.abc.net.au/news/2026-04-24/woman-chooses-to-go-blind-after-delays-at-adelaide-clinic/106602574",
"https://www.bunnings.com.au/",
"https://www.coles.com.au/",
"https://www.abc.net.au/news/2026-04-25/netanyahu-treated-for-prostate-cancer/106605028",
"https://www.abc.net.au/news/2026-04-25/sa-wwii-veterans-meet-after-more-than-80-years/106590394",
"https://www.realestate.com.au/",
"https://www.abc.net.au/news/2026-04-24/oyster-growing-closed-again-toxic-phytoplankton-yorke-peninsula/106601670",
"https://www.abc.net.au/news/2026-04-24/india-delimitation-redraw-electoral-map-southern-states/106591486",
"https://www.abc.net.au/news/2026-04-24/norway-plans-to-introduce-under-16s-social-media-ban/106604296",
"https://www.amazon.com.au/",
"https://www.abc.net.au/news/2026-04-25/april-25-5050-quiz/106601084",
"https://www.abc.net.au/news/2026-04-25/nato-falklands-spain/106604984",
"https://www.abc.net.au/news/2026-04-25/how-the-cost-of-the-ndis-blew-out/106604488",
"https://www.seek.com.au/",
"https://www.commbank.com.au/",
"https://www.bom.gov.au/",
"https://www.abc.net.au/news/2026-04-25/how-iran-regime-changed-after-us-israel-middle-east-war/106595956",
"https://my.gov.au/",
"https://www.woolworths.com.au/",
"https://www.abc.net.au/news/2026-04-24/nrl-live-updates-cowboys-sharks-broncos-bulldogs/106591508",
"https://www.abc.net.au/news/2026-04-24/act-government-will-not-cancel-big-splash-operators-lease/106603388",
"https://www.abc.net.au/news/2026-04-25/outcome-farrer-byelection-one-nation-watershed-moment/106485956"
],
"static_urls": [
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.bom.gov.au/",
"https://www.commbank.com.au/",
"https://www.seek.com.au/",
"https://www.realestate.com.au/",
"https://www.woolworths.com.au/",
"https://www.coles.com.au/",
"https://www.amazon.com.au/",
"https://www.bunnings.com.au/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "Australia - Perth",
"google_module": {
"base_lat": -31.9545,
"base_lon": 115.8582,
"lang_params": "hl=en-AU&gl=AU",
"valid_url_suffix": "com.au"
},
"trust_module": {
"white_urls": [
"https://www.abc.net.au/news/2026-04-24/oyster-growing-closed-again-toxic-phytoplankton-yorke-peninsula/106601670",
"https://www.abc.net.au/news/2026-04-24/india-delimitation-redraw-electoral-map-southern-states/106591486",
"https://www.abc.net.au/news/2026-04-25/outcome-farrer-byelection-one-nation-watershed-moment/106485956",
"https://www.abc.net.au/news/2026-04-25/netanyahu-treated-for-prostate-cancer/106605028",
"https://my.gov.au/",
"https://www.abc.net.au/news/2026-04-25/april-25-5050-quiz/106601084",
"https://www.abc.net.au/news/2026-04-24/woman-chooses-to-go-blind-after-delays-at-adelaide-clinic/106602574",
"https://www.seek.com.au/",
"https://www.ato.gov.au/",
"https://www.abc.net.au/news/2026-04-24/nt-doctor-gross-indecency-rape-trial-court-suppression-order/106603984",
"https://www.abc.net.au/news/2026-04-24/norway-plans-to-introduce-under-16s-social-media-ban/106604296",
"https://www.commbank.com.au/",
"https://www.abc.net.au/news/2026-04-25/how-the-cost-of-the-ndis-blew-out/106604488",
"https://www.bunnings.com.au/",
"https://www.abc.net.au/news/2026-04-25/sa-wwii-veterans-meet-after-more-than-80-years/106590394",
"https://www.abc.net.au/news/2026-04-24/nrl-live-updates-cowboys-sharks-broncos-bulldogs/106591508",
"https://www.amazon.com.au/",
"https://www.coles.com.au/",
"https://www.woolworths.com.au/",
"https://www.abc.net.au/news/2026-04-24/act-government-will-not-cancel-big-splash-operators-lease/106603388",
"https://www.abc.net.au/news/2026-04-25/nato-falklands-spain/106604984",
"https://www.abc.net.au/news/2026-04-25/how-iran-regime-changed-after-us-israel-middle-east-war/106595956",
"https://www.abc.net.au/news/2026-04-24/kezie-apps-says-womens-state-of-origin-timing-not-ideal/106604306",
"https://www.realestate.com.au/",
"https://www.bom.gov.au/"
],
"static_urls": [
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.bom.gov.au/",
"https://www.commbank.com.au/",
"https://www.seek.com.au/",
"https://www.realestate.com.au/",
"https://www.woolworths.com.au/",
"https://www.coles.com.au/",
"https://www.amazon.com.au/",
"https://www.bunnings.com.au/"
]
}
}

View File

@@ -0,0 +1,46 @@
{
"region_name": "Canada - Montreal",
"google_module": {
"base_lat": 45.5017,
"base_lon": -73.5673,
"lang_params": "hl=en&gl=CA",
"valid_url_suffix": "ca"
},
"trust_module": {
"white_urls": [
"https://www.cbc.ca/music/taylor-kirk-timber-timbre-obit-9.7176057?cmp=rss",
"https://www.cbc.ca/sports/hockey/pwhl/pwhl-super-saturday-regular-season-finale-april-2026-9.7174583?cmp=rss",
"https://www.cbc.ca/news/canada/hamilton/cooney-hamber-trial-decision-date-9.7174773?cmp=rss",
"https://www.cbc.ca/news/canada/kitchener-waterloo/livestory/jeffrey-sloka-sexual-assault-trial-ruling-decision-9.7175767?cmp=rss",
"https://www.cbc.ca/news/politics/ukraine-war-nato-carignan-trump-9.7175303?cmp=rss",
"https://www.cbc.ca/books/canadian-poet-karen-solie-wins-239k-windham-campbell-prize-9.7173005?cmp=rss",
"https://www.cbc.ca/news/canada/toronto/ticketmaster-delist-resale-tickets-ontario-9.7175775?cmp=rss",
"https://www.cra-arc.gc.ca/",
"https://www.amazon.ca/",
"https://www.cbc.ca/news/canada/nova-scotia/tiffany-cameron-halifax-tides-northern-super-league-women-s-soccer-anthem-victory-9.7174310?cmp=rss",
"https://www.cbc.ca/news/politics/trudeau-china-economic-coercion-9.7175918?cmp=rss",
"https://www.td.com/",
"https://www.canada.ca/en.html",
"https://www.cbc.ca/news/canada/calgary/powerful-winds-calgary-damage-9.7176144?cmp=rss",
"https://www.cbc.ca/news/canada/calgary/ottawa-approves-enbridge-s-4b-sunrise-natural-gas-pipeline-expansion-project-9.7175787?cmp=rss",
"https://www.rbcroyalbank.com/",
"https://www.canadapost-postescanada.ca/",
"https://www.cbc.ca/news/investigates/ancestral-remains-wolfe-island-ontario-9.7174129?cmp=rss",
"https://www.cbc.ca/news/science/climate-summit-transition-fossil-fuels-9.7175158?cmp=rss",
"https://www.cbc.ca/news/canada/calgary/analysis-alberta-electoral-boundary-new-maps-danielle-smith-naheed-nenshi-9.7175296?cmp=rss",
"https://www.theweathernetwork.com/ca",
"https://www.cbc.ca/news/canada/manitoba/death-threats-genocide-winnipegger-charged-9.7175921?cmp=rss",
"https://www.utoronto.ca/"
],
"static_urls": [
"https://www.canada.ca/en.html",
"https://www.cra-arc.gc.ca/",
"https://www.canadapost-postescanada.ca/",
"https://www.utoronto.ca/",
"https://www.td.com/",
"https://www.rbcroyalbank.com/",
"https://www.amazon.ca/",
"https://www.theweathernetwork.com/ca"
]
}
}

View File

@@ -0,0 +1,46 @@
{
"region_name": "Canada - Toronto",
"google_module": {
"base_lat": 43.6532,
"base_lon": -79.3832,
"lang_params": "hl=en&gl=CA",
"valid_url_suffix": "ca"
},
"trust_module": {
"white_urls": [
"https://www.canada.ca/en.html",
"https://www.cbc.ca/sports/hockey/pwhl/pwhl-super-saturday-regular-season-finale-april-2026-9.7174583?cmp=rss",
"https://www.cbc.ca/news/politics/ukraine-war-nato-carignan-trump-9.7175303?cmp=rss",
"https://www.cbc.ca/news/canada/calgary/ottawa-approves-enbridge-s-4b-sunrise-natural-gas-pipeline-expansion-project-9.7175787?cmp=rss",
"https://www.cbc.ca/news/science/climate-summit-transition-fossil-fuels-9.7175158?cmp=rss",
"https://www.cbc.ca/news/canada/manitoba/death-threats-genocide-winnipegger-charged-9.7175921?cmp=rss",
"https://www.canadapost-postescanada.ca/",
"https://www.cbc.ca/news/investigates/ancestral-remains-wolfe-island-ontario-9.7174129?cmp=rss",
"https://www.cbc.ca/news/canada/nova-scotia/tiffany-cameron-halifax-tides-northern-super-league-women-s-soccer-anthem-victory-9.7174310?cmp=rss",
"https://www.theweathernetwork.com/ca",
"https://www.cbc.ca/news/canada/calgary/analysis-alberta-electoral-boundary-new-maps-danielle-smith-naheed-nenshi-9.7175296?cmp=rss",
"https://www.cbc.ca/music/taylor-kirk-timber-timbre-obit-9.7176057?cmp=rss",
"https://www.td.com/",
"https://www.cbc.ca/news/canada/hamilton/cooney-hamber-trial-decision-date-9.7174773?cmp=rss",
"https://www.cbc.ca/news/canada/kitchener-waterloo/livestory/jeffrey-sloka-sexual-assault-trial-ruling-decision-9.7175767?cmp=rss",
"https://www.cra-arc.gc.ca/",
"https://www.cbc.ca/books/canadian-poet-karen-solie-wins-239k-windham-campbell-prize-9.7173005?cmp=rss",
"https://www.amazon.ca/",
"https://www.rbcroyalbank.com/",
"https://www.cbc.ca/news/canada/calgary/powerful-winds-calgary-damage-9.7176144?cmp=rss",
"https://www.utoronto.ca/",
"https://www.cbc.ca/news/canada/toronto/ticketmaster-delist-resale-tickets-ontario-9.7175775?cmp=rss",
"https://www.cbc.ca/news/politics/trudeau-china-economic-coercion-9.7175918?cmp=rss"
],
"static_urls": [
"https://www.canada.ca/en.html",
"https://www.cra-arc.gc.ca/",
"https://www.canadapost-postescanada.ca/",
"https://www.utoronto.ca/",
"https://www.td.com/",
"https://www.rbcroyalbank.com/",
"https://www.amazon.ca/",
"https://www.theweathernetwork.com/ca"
]
}
}

View File

@@ -0,0 +1,46 @@
{
"region_name": "Germany - Frankfurt",
"google_module": {
"base_lat": 50.1109,
"base_lon": 8.6821,
"lang_params": "hl=de&gl=DE",
"valid_url_suffix": "de"
},
"trust_module": {
"white_urls": [
"https://www.amazon.de/",
"https://www.tagesschau.de/ausland/europa/impfstoffallianz-malaria-who-100.html",
"https://www.tagesschau.de/ausland/europa/eu-gipfel-zypern-iran-krieg-ukraine-100.html",
"https://www.tagesschau.de/ausland/europa/norwegen-social-media-verbot-100.html",
"https://www.tagesschau.de/ausland/europa/eu-gipfel-zypern-106.html",
"https://www.tagesschau.de/ausland/europa/eu-gipfel-zypern-102.html",
"https://www.tagesschau.de/wirtschaft/konjunktur/ifo-index-stimmung-wirtschaft-100.html",
"https://www.arbeitsagentur.de/",
"https://www.bahn.de/",
"https://www.tum.de/",
"https://www.bundesregierung.de/",
"https://www.sparkasse.de/",
"https://www.tagesschau.de/ausland/amerika/ermittlungen-powell-eingestellt-100.html",
"https://www.tagesschau.de/ausland/europa/ukraine-odessa-tote-100.html",
"https://www.tagesschau.de/inland/innenpolitik/rente-debatte-100.html",
"https://www.tagesschau.de/inland/regional/berlin/berliner-kultursenatorin-ruecktritt-100.html",
"https://www.tagesschau.de/wirtschaft/verbraucher/spritpreise-tanken-102.html",
"https://www.spiegel.de/",
"https://www.tagesschau.de/ausland/asien/faq-israel-libanon-usa-waffenruhe-100.html",
"https://www.tagesschau.de/inland/bundestag-tankrabatt-praemie-100.html",
"https://www.ebay.de/",
"https://www.tagesschau.de/wirtschaft/finanzen/marktberichte/marktbericht-130.html",
"https://www.tagesschau.de/inland/regional/brandenburg/flughafen-ryanair-rueckzug-berlin-100.html"
],
"static_urls": [
"https://www.bundesregierung.de/",
"https://www.arbeitsagentur.de/",
"https://www.tum.de/",
"https://www.sparkasse.de/",
"https://www.bahn.de/",
"https://www.amazon.de/",
"https://www.ebay.de/",
"https://www.spiegel.de/"
]
}
}

View File

@@ -0,0 +1,44 @@
{
"region_name": "Spain - Madrid",
"google_module": {
"base_lat": 40.4168,
"base_lon": -3.7038,
"lang_params": "hl=es&gl=ES",
"valid_url_suffix": "es"
},
"trust_module": {
"white_urls": [
"https://elpais.com/internacional/2026-04-24/trump-envia-a-pakistan-a-sus-dos-principales-negociadores-para-retomar-el-dialogo-con-teheran.html",
"https://elpais.com/cultura/2026-04-24/xavier-lozano-y-la-historia-detras-de-la-flauta-silla-de-amaia-vinieron-a-verme-y-lo-hizo-bastante-bien.html",
"https://elpais.com/economia/negocios/2026-04-19/joseph-stiglitz-premio-nobel-de-economia-la-ideologia-de-los-millonarios-tiene-actualmente-un-grado-de-egoismo-alucinante.html",
"https://elpais.com/icon/2026-04-23/una-experiencia-inmersiva-para-redefinir-el-automovil-como-espacio-vital.html",
"https://elpais.com/salud-y-bienestar/2026-04-24/el-14-de-los-adultos-espanoles-padece-insomnio.html",
"https://www.amazon.es/",
"https://elpais.com/espana/catalunya/2026-04-24/illa-reivindica-su-fomento-del-catalan-en-sant-jordi-en-medio-de-las-criticas-de-la-oposicion.html",
"https://elpais.com/economia/2026-04-24/bayer-espera-cerrar-pronto-las-demandas-por-el-glifosato-con-un-desembolso-legal-que-ronda-los-24000-millones.html",
"https://elpais.com/gente/2026-04-24/donald-trump-responde-a-las-palabras-de-enrique-de-inglaterra-en-ucrania-yo-represento-mas-al-reino-unido-que-el.html",
"https://www.zara.com/es/",
"https://elpais.com/gente/2026-04-24/al-actor-billy-porter-no-le-importa-que-no-le-inviten-a-la-gala-del-met-desde-2019-ya-no-necesito-la-validacion-de-los-demas.html",
"https://www.elcorteingles.es/",
"https://elpais.com/videos/2026-04-24/tras-los-noes-de-rajoy-y-cospedal-ahora-que.html",
"https://administracion.gob.es/",
"https://elpais.com/eps/2026-04-24/lilia-mendez-una-mujer-contra-el-olvido-de-la-artesania-textil-gallega.html",
"https://www.santander.es/",
"https://elpais.com/economia/2026-04-24/espana-se-suma-a-italia-y-pide-a-bruselas-suspender-las-reglas-fiscales-por-la-crisis-energetica.html",
"https://elpais.com/eps/2026-04-21/roberto-paparcone-el-arquitecto-que-dejo-su-trabajo-para-moldear-barro.html",
"https://elpais.com/economia/vivienda/2026-04-24/consumo-intensifica-la-presion-y-envia-mas-de-500-cartas-a-grandes-tenedores-para-que-acepten-la-prorroga-de-los-alquileres.html",
"https://elpais.com/cultura/2026-04-24/critica-del-nuevo-disco-de-foo-fighters-solo-con-la-rabia-no-es-suficiente.html",
"https://www.renfe.com/",
"https://www.agenciatributaria.es/"
],
"static_urls": [
"https://administracion.gob.es/",
"https://www.agenciatributaria.es/",
"https://www.santander.es/",
"https://www.renfe.com/",
"https://www.amazon.es/",
"https://www.zara.com/es/",
"https://www.elcorteingles.es/"
]
}
}

View File

@@ -0,0 +1,44 @@
{
"region_name": "France - Paris",
"google_module": {
"base_lat": 48.8566,
"base_lon": 2.3522,
"lang_params": "hl=fr&gl=FR",
"valid_url_suffix": "fr"
},
"trust_module": {
"white_urls": [
"https://www.france24.com/fr/sports/20260424-roland-garros-carlos-alcaraz-champion-titre-participera-raison-blessure-poignet-tennis-jannick-sinner-grand-chelem",
"https://www.cdiscount.com/",
"https://www.sorbonne-universite.fr/",
"https://www.france24.com/fr/vid%C3%A9o/20260424-%C3%A9tats-unis-tornade-d%C3%A9vastatrice-dans-le-nord-de-l-oklahoma",
"https://www.amazon.fr/",
"https://www.france24.com/fr/%C3%A9missions/aux-4-coins-de-l-europe/20260424-transports-en-europe-embarquement-imm%C3%A9diat-partie-1",
"https://www.france24.com/fr/vid%C3%A9o/20260424-eurovision-plus-d-un-millier-d-artistes-appellent-au-boycott-du-concours",
"https://www.france24.com/fr/vid%C3%A9o/20260424-au-pakistan-une-reprise-des-n%C3%A9gociations-entre-les-%C3%A9tats-unis-et-l-iran",
"https://www.sncf.com/",
"https://www.credit-agricole.fr/",
"https://www.france24.com/fr/%C3%A9co-tech/20260424-le-manifeste-de-palantir-pour-une-silicon-valley-en-armes",
"https://www.france24.com/fr/%C3%A9missions/outre-mer/20260424-des-%C3%A9l%C3%A8ves-priv%C3%A9s-d-%C3%A9cole-depuis-deux-semaines-%C3%A0-mayotte",
"https://www.france24.com/fr/vid%C3%A9o/20260424-sommet-europ%C3%A9en-%C3%A0-chypre-apr%C3%A8s-l-ukraine-le-moyen-orient-au-menu-des-discussions",
"https://www.impots.gouv.fr/",
"https://www.france24.com/fr/vid%C3%A9o/20260424-russie-pluie-noire-sur-une-ville-apr%C3%A8s-une-frappe-de-kiev-contre-une-raffinerie",
"https://www.france24.com/fr/moyen-orient/20260424-de-retour-dans-le-sud-des-libanais-d%C3%A9vast%C3%A9s-isra%C3%ABl-d%C3%A9truit-des-maisons-des-routes-m%C3%AAme-les-arbres",
"https://www.france24.com/fr/vid%C3%A9o/20260424-%C3%A9tats-unis-risque-de-p%C3%A9nurie-de-missiles-tomahawk-apr%C3%A8s-leur-usage-massif-au-moyen-orient",
"https://www.france24.com/fr/%C3%A9missions/aux-4-coins-de-l-europe/20260424-transports-en-europe-embarquement-imm%C3%A9diat-partie-2",
"https://www.service-public.fr/",
"https://www.france24.com/fr/vid%C3%A9o/20260424-liban-sixi%C3%A8me-casque-bleu-tu%C3%A9-depuis-le-d%C3%A9but-de-la-guerre-france-24-re%C3%A7oit-dany-ghafary-finul",
"https://www.france24.com/fr/vid%C3%A9o/20260424-pape-l%C3%A9on-xiv-cl%C3%B4ture-de-sa-tourn%C3%A9e-africaine-de-onze-jours-en-guin%C3%A9e-%C3%A9quatoriale",
"https://www.france24.com/fr/afrique/20260424-togo-france-affirme-soutenir-initiatives-r%C3%A9gionales-contenir-risque-terroriste-organisation-%C3%A9tat-islamique-al-qa%C3%AFda"
],
"static_urls": [
"https://www.service-public.fr/",
"https://www.impots.gouv.fr/",
"https://www.sorbonne-universite.fr/",
"https://www.credit-agricole.fr/",
"https://www.sncf.com/",
"https://www.amazon.fr/",
"https://www.cdiscount.com/"
]
}
}

View File

@@ -0,0 +1,44 @@
{
"region_name": "Hong Kong",
"google_module": {
"base_lat": 22.2847,
"base_lon": 114.1582,
"lang_params": "hl=zh-HK&gl=HK",
"valid_url_suffix": "com.hk"
},
"trust_module": {
"white_urls": [
"https://hk.news.yahoo.com/%E5%8F%88-%E6%9D%91%E8%8A%B1%E5%9C%92%E4%BF%B1%E6%A8%82%E9%83%A8%E6%B4%A99%E5%8D%83%E4%BA%BA%E8%B3%87%E6%96%99-%E7%A7%81%E9%9A%B1%E5%B0%88%E5%93%A1%E8%A3%81%E5%AE%9A%E9%81%95%E7%A7%81%E9%9A%B1%E6%A2%9D%E4%BE%8B-200000176.html",
"https://www.hktvmall.com/",
"https://hk.news.yahoo.com/%E8%8B%B1%E5%9C%8B%E6%94%BF%E5%BA%9C%E7%B8%AE%E6%B8%9B%E8%B5%A4%E5%AD%97%E6%9C%89%E6%88%90%E6%95%88-%E5%B0%88%E5%AE%B6%E8%AD%A6%E5%91%8A%E4%B8%AD%E6%9D%B1%E6%88%B0%E7%88%AD%E6%81%90%E6%8E%A8%E5%8D%87%E8%88%89%E5%82%B5%E6%88%90%E6%9C%AC-132005020.html",
"https://www.gov.hk/",
"https://www.hsbc.com.hk/",
"https://hk.news.yahoo.com/%E8%87%AA%E5%8B%95%E6%8B%86%E5%8D%B8%E7%B5%84%E8%A3%9D%E5%A4%A7%E6%B8%9B%E4%BA%BA%E6%89%8B%E5%B7%A5%E6%99%82-%E6%B8%AF%E9%90%B5%E9%A6%96%E8%BC%AA%E5%B0%8D%E7%B6%AD%E4%BF%AE%E4%B8%AD%E5%BF%83%E5%B0%87%E9%81%8B%E4%BD%9C-200000982.html",
"https://hk.news.yahoo.com/%E7%84%A1%E5%A4%96%E9%81%8A%E5%81%87%E5%8F%97%E5%82%B7-%E9%A8%99%E6%97%85%E9%81%8A%E4%BF%9D%E9%9A%AA%E7%B4%A2%E5%84%9F-9%E4%BA%BA%E8%A2%AB%E6%8D%95%E6%B6%8970%E6%A1%88170%E8%90%AC-200000121.html",
"https://hk.news.yahoo.com/%E6%AD%90%E5%85%83%E5%8D%80pmi%E8%B7%8C%E7%A0%B4%E6%A6%AE%E6%9E%AF%E7%B7%9A-%E5%8F%97%E4%B8%AD%E6%9D%B1%E6%88%B0%E4%BA%8B%E6%8B%96%E7%B4%AF-113502050.html",
"https://hk.news.yahoo.com/%E5%90%88%E8%B3%87%E5%A5%AA%E4%B8%AD%E7%92%B0%E6%B5%B7%E6%BF%B1%E6%B4%BB%E5%8B%95%E7%A9%BA%E9%96%93%E7%A7%9F%E7%B4%84-%E6%81%92%E5%9F%BA%E8%88%87%E8%80%80%E6%A6%AE-%E5%BC%95%E5%9C%8B%E9%9A%9B%E7%B4%9A%E7%9B%9B%E4%BA%8B-%E5%AE%9A%E6%99%82%E9%96%8B%E6%94%BE%E6%95%B4%E5%80%8B%E7%A9%BA%E9%96%93-200000497.html",
"https://www.hko.gov.hk/",
"https://www.mtr.com.hk/",
"https://hk.news.yahoo.com/%E7%BE%8E%E8%BB%8D%E6%94%94%E6%88%AA%E6%AA%A2%E6%9F%A5%E5%8D%B0%E5%BA%A6%E6%B4%8B-%E8%89%98%E6%B2%B9%E8%BC%AA-%E6%8E%A7%E9%81%8B%E8%BC%89%E4%BC%8A%E6%9C%97%E7%9F%B3%E6%B2%B9-140505715.html",
"https://hk.news.yahoo.com/%E7%BE%8E%E4%BC%8A%E8%AB%87%E5%88%A4%E9%80%B2%E5%B1%95%E8%86%A0%E8%91%97-%E4%BB%A5%E9%BB%8E%E5%81%9C%E7%81%AB%E5%BB%B6%E9%95%B73%E5%91%A8-060502014.html",
"https://hk.news.yahoo.com/%E7%87%92%E5%82%B77-5-%E5%B1%85%E6%B0%91%E5%81%95%E7%88%B6%E5%9B%9E%E5%AE%B6%E5%9F%B7%E6%8B%BE-%E8%BF%91%E8%B5%B7%E7%81%AB%E9%BB%9E%E4%BD%8F%E6%88%B6%E5%98%86-%E5%AE%9A%E5%94%94%E5%A5%BD%E5%8F%97-200000405.html",
"https://hk.news.yahoo.com/%E6%8C%AA%E5%A8%81%E6%93%AC%E7%A6%8116%E6%AD%B2%E4%BB%A5%E4%B8%8B%E5%85%92%E5%B0%91%E4%BD%BF%E7%94%A8%E7%A4%BE%E7%BE%A4%E5%AA%92%E9%AB%94-080501788.html",
"https://www.hku.hk/",
"https://www.police.gov.hk/",
"https://hk.news.yahoo.com/%E5%B7%9D%E6%99%AE%E7%A8%B1%E4%B8%8D%E6%80%A5%E6%96%BC%E7%B5%90%E6%9D%9F%E8%88%87%E4%BC%8A%E6%9C%97%E6%88%B0%E7%88%AD-%E4%B8%8D%E6%9C%83%E5%8B%95%E7%94%A8%E6%A0%B8%E6%AD%A6-222004956.html",
"https://hk.news.yahoo.com/%E4%BB%8A%E6%97%A9%E9%99%8D%E6%BA%AB-%E4%BD%8E%E8%A6%8B19%E5%BA%A6-%E4%BB%8A%E6%97%A5%E6%9C%89%E7%8B%82%E9%A2%A8%E9%9B%B7%E6%9A%B4-%E9%9B%A8%E5%8B%A2%E9%A0%97%E5%A4%A7-200000766.html",
"https://hk.news.yahoo.com/%E7%BE%8E%E5%9C%8B%E5%8B%99%E9%99%A2%E6%87%B8%E8%B3%9E%E9%80%BE3%E5%84%84-%E7%B7%9D%E6%8D%95%E4%BC%8A%E6%8B%89%E5%85%8B%E6%AD%A6%E8%A3%9D%E7%B5%84%E7%B9%94%E9%A0%98%E8%A2%96-152002118.html",
"https://hk.news.yahoo.com/%E7%A0%B4%E5%A4%A9%E8%8D%92-%E7%BE%85%E5%85%B5%E5%92%B8%E9%A0%90%E7%95%9910%E5%84%84%E5%9B%9E%E6%B0%B4%E6%81%92%E5%A4%A7%E8%82%A1%E6%9D%B1-%E6%9C%83%E8%B2%A1%E5%B1%80%E5%8F%A6%E7%BD%B03%E5%84%84-%E8%AD%89%E7%9B%A3-%E5%90%91%E5%AF%A9%E8%A8%88%E7%95%8C%E7%99%BC%E6%98%8E%E7%A2%BA%E8%A8%8A%E6%81%AF-200000502.html",
"https://hk.news.yahoo.com/%E6%9C%80%E6%96%B0%E5%A4%B1%E6%A5%AD%E7%8E%873-7-%E5%8B%9D%E9%A0%90%E6%9C%9F-%E6%94%BF%E5%BA%9C-%E8%A7%80%E5%AF%9F%E5%9C%B0%E7%B7%A3%E6%94%BF%E6%B2%BB%E5%B1%80%E5%8B%A2%E5%BD%B1%E9%9F%BF-200000451.html"
],
"static_urls": [
"https://www.gov.hk/",
"https://www.hko.gov.hk/",
"https://www.police.gov.hk/",
"https://www.hku.hk/",
"https://www.hsbc.com.hk/",
"https://www.mtr.com.hk/",
"https://www.hktvmall.com/"
]
}
}

View File

@@ -1,10 +0,0 @@
{
"region_code": "JP",
"region_name": "日本 (东京)",
"google_module": {
"base_lat": 35.6895,
"base_lon": 139.6917,
"lang_params": "hl=ja&gl=jp&ceid=JP:ja",
"valid_url_suffix": "google.co.jp"
}
}

View File

@@ -0,0 +1,39 @@
{
"region_name": "日本 (东京)",
"google_module": {
"base_lat": 35.6812,
"base_lon": 139.7671,
"lang_params": "hl=ja&gl=JP",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://news.yahoo.co.jp/pickup/6577513?source=rss",
"https://news.yahoo.co.jp/pickup/6577514?source=rss",
"https://www.u-tokyo.ac.jp/",
"https://news.yahoo.co.jp/pickup/6577515?source=rss",
"https://www.mhlw.go.jp/",
"https://news.yahoo.co.jp/pickup/6577495?source=rss",
"https://www.rakuten.co.jp/",
"https://news.yahoo.co.jp/pickup/6577518?source=rss",
"https://www.yahoo.co.jp/",
"https://www.jreast.co.jp/",
"https://www.amazon.co.jp/",
"https://www.smbc.co.jp/",
"https://news.yahoo.co.jp/pickup/6577511?source=rss",
"https://www.japan.go.jp/",
"https://news.yahoo.co.jp/pickup/6577506?source=rss",
"https://news.yahoo.co.jp/pickup/6577486?source=rss"
],
"static_urls": [
"https://www.japan.go.jp/",
"https://www.mhlw.go.jp/",
"https://www.u-tokyo.ac.jp/",
"https://www.smbc.co.jp/",
"https://www.jreast.co.jp/",
"https://www.yahoo.co.jp/",
"https://www.amazon.co.jp/",
"https://www.rakuten.co.jp/"
]
}
}

View File

@@ -0,0 +1,36 @@
{
"region_name": "South Korea - Seoul",
"google_module": {
"base_lat": 37.5665,
"base_lon": 126.978,
"lang_params": "hl=ko&gl=KR",
"valid_url_suffix": "co.kr"
},
"trust_module": {
"white_urls": [
"https://www.yonhapnewstv.co.kr/news/MYH202604242115160Bi",
"https://www.yonhapnewstv.co.kr/news/MYH20260424232327PlQ",
"https://www.naver.com/",
"https://www.yonhapnewstv.co.kr/news/AKR20260424211617lP3",
"https://www.coupang.com/",
"https://www.hometax.go.kr/",
"https://www.yonhapnewstv.co.kr/news/MYH20260424224141clh",
"https://www.korea.kr/",
"https://www.daum.net/",
"https://www.kbstar.com/",
"https://www.yonhapnewstv.co.kr/news/MYH20260424212713ARq",
"https://www.snu.ac.kr/",
"https://www.kakao.com/"
],
"static_urls": [
"https://www.korea.kr/",
"https://www.hometax.go.kr/",
"https://www.snu.ac.kr/",
"https://www.kbstar.com/",
"https://www.naver.com/",
"https://www.daum.net/",
"https://www.coupang.com/",
"https://www.kakao.com/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "Malaysia - Kuala Lumpur",
"google_module": {
"base_lat": 3.139,
"base_lon": 101.6869,
"lang_params": "hl=en-MY&gl=MY",
"valid_url_suffix": "com.my"
},
"trust_module": {
"white_urls": [
"https://news.google.com/rss/articles/CBMivAFBVV95cUxPZTJSUTBfRXJ5alNuZUlQMlJYTE4tZUdXOW9vWC1TdFlBRC1fc3dHN19iNm5MTHBBVXdMOEZzZkpoR29CN1hibzI4cHVUNkVwWnc1SmtaaTk4YjBVVGJMUjI1X0lxbW1ILVRqTmhpS3Z6RXozZW9tNkYzVHpBbmNBQ29GZHJyOUpSXzAtNExnT0tGRjZWUHBvaDd2ZXNxbWtMMWMxRTNqWGdEdDZnejZlT0JkM1V1Qkhrd2t1UA?oc=5",
"https://news.google.com/rss/articles/CBMiUEFVX3lxTFBIRXB0VVVsbUQyNFlKeU4zR3BZMV95M3pPa2pPY3o4eDFiWmIxdWV6TlBHbk8wZTJQVEtxT1I1TktkUFEzZ0k0b1MtQjNfT012?oc=5",
"https://www.kwsp.gov.my/",
"https://um.edu.my/",
"https://news.google.com/rss/articles/CBMisAFBVV95cUxOZWY5eU9nblU5OVNFZVNNa0hBMFAzbmNjZG5Gelk2WjlYM3duelpuZVR0a0xlT2ZRM09jNjFKUzNWU1cwMlFCYnRCbkFuLUFaMkVnaU9GWW1SRmM5V0FwbDZhRWVCdk9aUzRMWEUtd3NlOWJwQnZXOHJTc3VrMHBDWWlYam5rZC1SNG5BX3hCTU4zN3F0U19URmpuNDkyckV0VGh4ZTVveDJIRnB0U0JrVw?oc=5",
"https://news.google.com/rss/articles/CBMi8wFBVV95cUxOWDdveGRmZkI2MDFtMjc0cWJJSnJqWHM3cTJRcU9iVVkwd3VJMC1RR0h1cG9BTWVBSzQ4Q2pFb3VmTWpFc2VucVV1c2dNRGZMaWd6TnJ6UnJlRURCYW1jRHgzMzBPUW01elJrSnF5VEVIT1dmcFYxNk5pZ2ZtWHlNV0VCUV9FSnFzdHdERzFFQng4dHJ2c1BtY3NzdkpCTjFVTG0yc0N4VWY2TDdfNzh2THl4MjRNMlF0S1ljYXlRNWlGbFFIRDFRNTc5d3ZsUDd2Yzc2NXMtRS15eHE3TEFrVHRSaF94N2hUbVU2eHd5SjBmX0nSAfgBQVVfeXFMTmJmZ3hLeGh0bDM5VFA5TjNDUjVmclZRZ29ISllyRmQ4VUdTWE9IbHcyV2JzT2Q2enJLZzdLOEEtYWczY2VsRk9pdTIyaV9UZU5IZ0hIb2p0eGpHMHFhMzhmcmc0cFRIWEVTS0g5b0lHRGs5amotc0F6VEloNmhXWGFWLXluemR2amxqSkRQLWhkM3VibjNHNVZHUERUaEFyVW1idUtGRV9nb2FxYkhnVk90OGpzWE5FY2NxSXRwNGFjVm1KeWhNX0t3WkpVVzNScUlldi1xUFNLb2ppZlFxMFpNQVg3ZURUT1hubm9ibkhicmdhOGRudkQ?oc=5",
"https://news.google.com/rss/articles/CBMitAFBVV95cUxPbFU5dUFjT2t5LXVxdFhmTlh5YVh2M01qOGNhTUpTdE9PRVg2TG56VklHV2w5T1ZndERyTW16VlFxQlhOTnE4d2p5b3QxNUdWa2hYTHNOcjViLW5jR0NxQkJFdWUyblZhV2EzUlBmcE5aSy1BOGtoR0xFM0hzdzdZX2lEN1NIV01QODJrRTk3MEJIQWg1dVlaaWcwSjZKNEJGb2dwbFY1bklDWVQ0dTV0cG9kYUk?oc=5",
"https://www.maybank2u.com.my/",
"https://news.google.com/rss/articles/CBMiXkFVX3lxTFAwTl8tYzE3VWx2bjRfS3NrWllQZF9FRWVyMnJPVGxvTVdJenpqd3VEUmVaTnNxTHZqTXBaZWZKMlhNbkI1MnV6dGZISm5fQmREWl8xUHY5c3czSE5SZWc?oc=5",
"https://news.google.com/rss/articles/CBMiwAFBVV95cUxPeDNGSlFPYkdjTDBKdWR2MFVIeHV6VHJWdnUwbzdjeHlRSGFVVUhsZlNQQUZicUVaS2pKRG1DRW9TdHpvNENFV1JXLTdPZUc3WEZYQTFqYThXWmZncjZhU3R4dGdab0FRNUlHbUsyQnhBTjhuLTRjWU5ZR1dzbHlmaHpUUzhzTlhwSnJxWi1Bdjd0WEZlZXo1UkY5LXJNb3BUQjUwRnA0ZXF2bUlBdk44LTNLRlF2Wkd2NFRiX0kxQW8?oc=5",
"https://www.malaysia.gov.my/",
"https://news.google.com/rss/articles/CBMiuwFBVV95cUxNRVk0VVMtNWxDcUluZkV3NnFlcU5RYXVqdmUydjlyaG1KNlpmbUh3UGt2WlhsTVNLNjVMSGh1SnFGZ0ZIZEllNnUxdjNzenloZEJJcXhWWXdDQm5iU3l0azJiWkRxV3RTb29ZLVpjaFBOanB3RzZqTkMwVWJNNS1mVWNGZFYtMW5sYmZkR09sbnhhSmVYUGdtM2prSmtEWXlmX3ZtTVRIOFI0Z1AybVN2d1Vaa19NU19ZSTVn?oc=5",
"https://www.cimbclicks.com.my/",
"https://news.google.com/rss/articles/CBMirgFBVV95cUxOM1VobXV0X0kyQkxTNTRrMHBJYmIzZ2lZWU1jV2ZTSW1xMXV0TXZvLUUwbGVkUmZhRE1pNlo2THpaeFBlOGRaN293MW1vclhIdndLMjdwZzlfdFY3MDUtX3FQVmRQcHVZUUR1QWxrNTRNZElfVTl5Ti1sUGRwOWttMFRLVWlkOU1vUTJ1QTZqTWFvVl9Qdjh6UzNYcXBFNnRCcWtTQ09tOHl0aEp1NWc?oc=5",
"https://www.pos.com.my/",
"https://www.thestar.com.my/",
"https://news.google.com/rss/articles/CBMivwFBVV95cUxPYkRPNVBFanVWRnBXb0Y0ZXRlWmtiN2dsT1Bya1RaaGZZalJQUWZJY1lud3IxcVpsZFpNdlRubmFxMlk3dUM3bi1keVJlaS1uMEotbWhBWWFZTTBlUW5hNFpQZEhjMGl0U1NWdUdsVTlVdGMzRFJPcjZXMjlHX3ZOZW5LNTIyRFI1cnEzMUhpNXhnNVFHTlpYSlRXRnFJZmJsSG1fc0FyUXJFUnlPNmtjeDVnd0VLNm52QVgtLUJYb9IBxAFBVV95cUxOV0R5WGowY0dSME1zdVZnbHdDUnBKUmJ0Nk1uZENzNm9NdngzR3k1bXRmY29SWG04MGU2aUhaUVRkeXRQZk9GemxQYzZKbTdkM0RQZjFlR1lzYnhnLUdqbW1uUE01UXVnN1JHd0RCLTRyUHFHUmtMZmoxVkpKdGZBSlFjaDlnbkJIdzZjZ1Vra0dnQzltRXFoWTdzLTZNdXNvS1VfbHFMYnN0WnJlazJsa25HLWdfOUw4Sm9PTmZveVJYZTJs?oc=5",
"https://news.google.com/rss/articles/CBMizwFBVV95cUxPZGJadEJvZHA0MVlsTWVWcmhWN2ttOXJrZjY4SXdXMTNuUVFlWjlXY080SzlyMVh5Tl9hZE85aWhGTTVxQi0tY1JUZDBzSDRRQ3Qxc1BzekJ2Nnk4WEt3dXd2NUdQZ0U4SzdaSFE0ZExIVlpQTmpCS2RpM1JBSUNRaVBtR3phOXJCOFdsUWpsTXllVDNHcUp4Y0pSbWF6SFN0bHFHdWVsdy1FY01idE44eDNqVy1zRENjMXZKS3hwYXZYcTdwdW5hYlpJMVpwZkk?oc=5",
"https://shopee.com.my/",
"https://news.google.com/rss/articles/CBMiwAFBVV95cUxOTnZYOEYtQ0ZlZEtxZUlucnM1ZnJvYkVkdFVCbTZPdG1MNmlzNjcwMTR4SVBvWWdyMkhHQ3BQOFZ4Ty1XQ3dCUmhIV2RDQjJCV3BSTjZyZ2txWGo4Mmpmb3VTZVdlV0JGYk8xVTNBUUdFc21nU19oYlhETmN0NkdtcmRJR0xEV1lSb3E5ekZsYlFsazZCaGVGMjlneFp5ZXN5S0FIZ0YwUmdVcG1CWWdVYjJSLVBWNjRuVnVqUGVGS2U?oc=5",
"https://news.google.com/rss/articles/CBMioAFBVV95cUxNeWMweUVJV3ZFYkxxbGljVW05ZHdENWxENFhRWFlNWWhiQ2VxZGo4OVFkVEV5REtRbnB2eGRpY2wwNjJadGtwdUIwamUyRkZWempoMFF2elppczhGUGRNQ2hkaEtrRHBTTVRkaV9GakQwSnhzUnVNQk5CVEhrNWFRNkd3VllJbTk5czJmUVFKMmZWNU01OUdmQXJONlB6TjZN0gGmAUFVX3lxTFB0MVo3dmRaWG90ZXJ1Z0tJSnJrd1EtZTZEVXJRUjRuMWpiR1pQNmZxTGtyWmkyd0llQzhUZ183Sk8tNFpZRW9nS2Mwb2dEUGlkTWNhc1VOWnFDSmRZUDJaNEdXSUVtQzdJVGxzTnlQUDJJNG81c3F1WjgwT1ZGOW41M29vc1RmemlhQjRPMzJWV3p0WU5qZl9qLUxnNngwaDJRX2hIcWc?oc=5",
"https://news.google.com/rss/articles/CBMigAFBVV95cUxQdFZFRHZIN09tV1Zzd19JcUVWNFUzc0xnaFN1VkgwVUFyV3ZPWXlURlk1N21VdkxvQ0NhcERmMFBCcy10NGd2ek56Yy1WYzBZSU5aUnAtNXpHUHAwZlRmUWhTNDFUSjJZaVY5QXEyYlhDLWtyVWdCd2hBcmU3dzc0bA?oc=5",
"https://news.google.com/rss/articles/CBMi3wFBVV95cUxQQzk2M1FMSmVTRkcxdHhsdW5jc0RCZi1pOGtqMDFjSGt4MHhPU2luYUNDSGJ0OGxzcXJwUnVaaG9sWDUtZ0FNenNfMGtBZ0xjZlNZNUtMX0w3cmtJU2tOOTVLelpQNFFDN2c3elpSZF9qNFJqQmJpUWhZdUpCNXlxMXRFZVFLal95ajhxam9MYWpwTGwwWS1EanpoWnVFd0NubGg4SWxTdlprSEpjeTRmVmd3dnpVSGZFUlgzV0tHM19waDc2LXhxNlJjOWZUOEV6OHJNSDFJaUpBdDgzS0hR0gHkAUFVX3lxTE5NOFNBVlo5b1ZuT2JwbEstVk1vbEN4NFM0ejdXbkhhSTJfLURHQXZCTDlpdFRMZlRNV1g0LWY0cEdvdjRFa1d2dmMtVWdPN3I2NDZhdExsSkpGSmM2NDZwT3NyR3NjbGdXODlDSWhvYUtGcGZLd0lZVHZ5SUVBSlJCdGxDQkNjNjltVkg3VW5PeXVyeWRWbnZ1ZDJ0cDJhaThPQ3gxZW1RTUN6ZXd3VW9fUFUxMFBZblczMFd5dy1Nd01MZ3JLNVg2S0dFTWVEdzNKUWZwNm5WcG00cnJiZUtuQXRfcg?oc=5",
"https://www.hasil.gov.my/",
"https://www.lazada.com.my/"
],
"static_urls": [
"https://www.malaysia.gov.my/",
"https://www.hasil.gov.my/",
"https://www.kwsp.gov.my/",
"https://um.edu.my/",
"https://www.maybank2u.com.my/",
"https://www.cimbclicks.com.my/",
"https://www.thestar.com.my/",
"https://shopee.com.my/",
"https://www.lazada.com.my/",
"https://www.pos.com.my/"
]
}
}

View File

@@ -0,0 +1,44 @@
{
"region_name": "Netherlands - Amsterdam",
"google_module": {
"base_lat": 52.3676,
"base_lon": 4.9041,
"lang_params": "hl=nl&gl=NL",
"valid_url_suffix": "nl"
},
"trust_module": {
"white_urls": [
"https://www.ing.nl/",
"https://nos.nl/l/2611855",
"https://www.ns.nl/",
"https://www.belastingdienst.nl/",
"https://nos.nl/l/2611872",
"https://nos.nl/l/2611850",
"https://nos.nl/l/2611861",
"https://nos.nl/l/2611835",
"https://www.bol.com/",
"https://nos.nl/l/2611825",
"https://nos.nl/l/2611863",
"https://www.marktplaats.nl/",
"https://www.rijksoverheid.nl/",
"https://nos.nl/l/2611823",
"https://nos.nl/l/2611873",
"https://nos.nl/l/2611871",
"https://nos.nl/l/2611859",
"https://nos.nl/l/2611843",
"https://nos.nl/l/2611819",
"https://nos.nl/l/2611827",
"https://www.buienradar.nl/",
"https://nos.nl/l/2611849"
],
"static_urls": [
"https://www.rijksoverheid.nl/",
"https://www.belastingdienst.nl/",
"https://www.ing.nl/",
"https://www.ns.nl/",
"https://www.bol.com/",
"https://www.marktplaats.nl/",
"https://www.buienradar.nl/"
]
}
}

View File

@@ -0,0 +1,46 @@
{
"region_name": "Singapore - Singapore",
"google_module": {
"base_lat": 1.3521,
"base_lon": 103.8198,
"lang_params": "hl=en-SG&gl=SG",
"valid_url_suffix": "com.sg"
},
"trust_module": {
"white_urls": [
"https://www.channelnewsasia.com/business/us-chipmakers-hit-record-highs-intel-turbocharges-ai-rally-6079431",
"https://www.fairprice.com.sg/",
"https://www.channelnewsasia.com/world/us-justice-department-closes-investigation-fed-chair-jerome-powell-6079516",
"https://www.channelnewsasia.com/sport/nzs-bracewell-handed-two-year-ban-after-testing-positive-cocaine-6079351",
"https://www.nus.edu.sg/",
"https://www.channelnewsasia.com/world/pentagon-chief-hegseth-says-iran-has-chance-make-good-deal-6079101",
"https://www.channelnewsasia.com/sport/alcarazs-french-open-three-peat-dreams-dashed-wrist-injury-forces-withdrawal-6079616",
"https://www.singpass.gov.sg/",
"https://www.iras.gov.sg/",
"https://www.channelnewsasia.com/sport/west-bromwich-albion-deducted-two-points-back-in-relegation-mix-6079696",
"https://www.gov.sg/",
"https://www.shopee.sg/",
"https://www.dbs.com.sg/",
"https://www.channelnewsasia.com/sport/sunderlands-brobbey-deserved-red-foul-spurs-romero-premier-league-panel-says-6079656",
"https://www.cpf.gov.sg/",
"https://www.channelnewsasia.com/sport/kohli-leads-bengaluru-chase-in-ipl-sudharsans-ton-goes-in-vain-6079791",
"https://www.channelnewsasia.com/business/google-invest-up-40-billion-in-ai-rival-anthropic-6079611",
"https://www.channelnewsasia.com/sport/frances-cosmobilis-in-talks-buy-world-rally-championship-rights-sources-say-6079736",
"https://www.channelnewsasia.com/sport/third-third-bottom-tottenhams-survival-fight-takes-them-wolves-6079546",
"https://www.channelnewsasia.com/business/german-prosecutors-investigate-phishing-attack-targeting-politicians-6079586",
"https://www.channelnewsasia.com/sport/arsenal-welcome-back-saka-final-push-in-premier-league-title-race-6079441",
"https://www.channelnewsasia.com/business/us-justice-department-intervenes-in-xai-challenge-colorado-tech-law-6079606",
"https://www.channelnewsasia.com/today/up-close/pro-female-basketball-3x3-singapore-national-athlete-sports-pressure-6077861"
],
"static_urls": [
"https://www.gov.sg/",
"https://www.cpf.gov.sg/",
"https://www.iras.gov.sg/",
"https://www.singpass.gov.sg/",
"https://www.nus.edu.sg/",
"https://www.dbs.com.sg/",
"https://www.shopee.sg/",
"https://www.fairprice.com.sg/"
]
}
}

View File

@@ -0,0 +1,48 @@
{
"region_name": "Taiwan - Taipei",
"google_module": {
"base_lat": 25.033,
"base_lon": 121.5654,
"lang_params": "hl=zh-TW&gl=TW",
"valid_url_suffix": "com.tw"
},
"trust_module": {
"white_urls": [
"https://www.post.gov.tw/",
"https://news.google.com/rss/articles/CBMijgNBVV95cUxPRWQ4dndjaC1VSE5lUFM5WFJYUm1jR3pDbUZsc3JUa2dXdVIyU092cDlnMnRXaDRhTlZ2X3RuRXNsczFvenpjcEtKR3k4VkFnbU1QZjZZLWhFYUU3OGdtUDNSX2wtd0ZhMkgxU2pFbG1NQjhscE8yenctMVRUdllXMXIwM0xuLVZIQnpaYWdvX2dKbFlnYW42N3NZZDRnel9vWmdQb3VwMTNjRDFCYWRNclVaamhZbFJDVHVZcTFSWTM2UVlBeFgzMHpZN1lQdmZ2MURQazNSWUZFVzhaNlhkRElFQmdEWlNyd2dxc2hjTndSY1RIVG54RS1MWHF3MlpBN21IOWMwX0ZQdXhRRU1xLV9fcGNUV2VQRWt5eWJzOU9iWVUtM2ZVaU8tY1BqaXU3emtYZWFlMGlzWHlVeUhlYXh0YXJxU01wbThMLUp6cE1LY014LVAtS3JJTGk0QUR4RlNFYll5WVk0NDNSbnMwZmJRZmpZZ1pVNnZ2WlhEUTBsT241c1M3bTl6Y01IQQ?oc=5",
"https://news.google.com/rss/articles/CBMiWEFVX3lxTE9ha2FzeEUzQUNTWG5XZm4yakpBb09Qc05seDhXcWFsNXk4ZlA2bUEzaFFXQU40RVpiRHAzYkxOMHFQSTF5a2g4QldWVExDUzV3UEpKMGtTOTM?oc=5",
"https://news.google.com/rss/articles/CBMi6AJBVV95cUxQZnJUa0xNUEFFWE9ZdFRSZ05lSFN1b3ByczRqaWM4enhLS1hfS2NmbHcxbjJYWnYyMUU1bVdZY0xkSUpkNTE4dVFCN1hLU3dHZ2k4S1ltX2pUWmRxTGtUZThfR1RtMkhWSFh5b3V0S2Y2SDNOaWVWajBvMXJsa0pkM0pyWENVZmpFalpFTWNVV2tMeUh2eVcyUldHS0pjM2pMcVB1Y3JfMWVfaDNGUjlxSUMzVzhzclJaSlNKS0JkYVUzNmhCbmZOTlA0ZFF4N3ZXYmlkZXJ3amtnWndCa3hoT3hrbzRzUkY0V0RKcmt5MVRmZVFrX2VjTE44a1hHNWxWeGo2OWJNRHE2V2NGNlJsMWZ5WS1VYU1LM0hNQ3o5WXlQWFNxdW1LN2hWeTdKbGl3Wk5uNG9WRE1NVGNCOFRqV2x2UFpacl9DWmZQbExKTGhEcWpsWDRFNE5jUFZGdE9JY2lJWmFBVnI?oc=5",
"https://www.momoshop.com.tw/",
"https://news.google.com/rss/articles/CBMiUEFVX3lxTE1RWVU3RDhPd1pobEs3aDE3QjRkd25pTWdReU83OENZU280aDZvOE1sMkI2Y19ZOGt5eHRTTl92ZGVjX2xtc01tRVc3VDBXRHJx?oc=5",
"https://news.google.com/rss/articles/CBMiYEFVX3lxTFBKRmJSck9sZ3ZuLWp6N2kxa0FEd0lmQjNKQkktM2VhejNYQWRscFpGdTRPOU90VTFubThfUVVZdjhZRTRmbTBSMThra3JlalBuUUhSQTFENS1BQnlmUTJZN9IBZkFVX3lxTE0xMUdHNnduQXdqV21yTkZETXdTQjk5MlhhbGxMeEd5Y0daVWdnemI5TDRmWFZUS2I0QW5RcXpxWGVfeC11X3R3NmZCVkljZUUxM2ZtRUtpR1h4ci1rdEUzMjNzRkhxQQ?oc=5",
"https://news.google.com/rss/articles/CBMiW0FVX3lxTE1Tc3ptaDJCY0lEQWNrYjNFMnVaS1dBN1FCSTFGR3p4ekItbDUyWEZiLXB1TkpWTkd1WUFMYWNuMEVwZWFKMGhvQ0dyWnVCZmdlUTZwU2NOUW5pYzTSAWBBVV95cUxOWTFIYmpocUQwX012NkRsY0JRemNxbV95NWNZNG9halFYLXdPLS1EbEF3aU42NW5MeUpOZFVjRGs2azRyZ2hUQTlGTHMwREdOYWYySEtGUUJiRjZqYktLcGU?oc=5",
"https://tw.yahoo.com/",
"https://www.dcard.tw/",
"https://news.google.com/rss/articles/CBMiT0FVX3lxTFBpc29SNm5FZTdDampFWVdIakxYc0k3a0ZfUGJMUWlzRWFXa2IxQXlicUZ4eGR1al9tZk1HaFhKOTJydUdlQ0ZmRHFkZ19DSDQ?oc=5",
"https://www.thsrc.com.tw/",
"https://www.ntu.edu.tw/",
"https://www.cathaybk.com.tw/",
"https://news.google.com/rss/articles/CBMiX0FVX3lxTE9hYThuYy1SeFVtVmtlRWloazhGcXQ2RThNWFZxVjdpSVFuek9UcUVoMXdpdWI4NWgzOXVaWmRSR2J5X1JCV1hVZXFrOW11V1JXcmlPREMyb1V3MC1sRHBj?oc=5",
"https://news.google.com/rss/articles/CBMiUEFVX3lxTE5zLVNDaGlzQnhOM0JoOG9NSWJLSVhMc0xUWjBYUkpyR3hFMXc3bU4zZGdtSlU2Q3ViTlJkVlQ5aVJQNWhvRjlSQVhFeXNxY0tt0gFWQVVfeXFMTUVvWDNUZmpCM1RhdkdFWV83WmpQMjkxUTV6MWJncGJPWS1PSHVyVFVSLTVsZkFna2MxemVnMkJVbHNqZWVMcmtTeXdMQWtJcXUtemJpUkE?oc=5",
"https://news.google.com/rss/articles/CBMiUEFVX3lxTE5xcDdhYjQwcVBQSDIxREN1SnlqY2Z6dE4yaGcySjFlc2dBeWNNRGFfTjFzNndYXy1nRHM0X3BSRTVNek5UVWxsVGR0RzZtQkcy0gFWQVVfeXFMTXVBRWxEUzZQQ2xvYlJVd25jTk5kRGRvb2xPRmdwckw2UGtXZXA2a2FvUTVMc2YtZmJhRFNzMUtLYTNqZXlFM1V0YmlrY1JIUkxZU01QREE?oc=5",
"https://news.google.com/rss/articles/CBMi6AJBVV95cUxONXJKMzQxOGhGQ0RDZVpkNkxodkFTOUZPSnBUOGVBRWpwR2JicmptR1JhWGh6XzRsREVNblJfLVRoemZEblVUeWtWWmFfS19wRzE5RFRybGw5bVJ3RE9RbllQMjdHVGYzM3RkMmhLX240RjFWM09lRlN6d3dET2N0REozdDdaUDc0N3NMeXJBNFNtdzZaTzViRnZBOVFGMHRDd2pWT0ttQTVaRmVIR3pSU05vNHMyMEw0blpka3ZkeWdkSjNRSDZ2Z2o5akFUYmJ5a2twdWRKb0tvem83ZFFOZTNNTFNjb0VmZHV3OUltam0xNmdlSWs0UzlDcUtybk4xLUFMU2FZZTNLWHNTYkRsWUR3RUdmSzRheGt1aG52dDZFU0JrNWF3ZWVpeHhGcVNFaW04TWFyeVFnNUpqT0RqalQ4RGx0YXZ3QlBVV1NDM0FqVjlyblg2NUNRV0U2WFVsTDlkNXZkQXo?oc=5",
"https://news.google.com/rss/articles/CBMiWkFVX3lxTE9wck9XVUlqa3FCY1I1VmNMeURQc3dRQWpIamhXdlpfUjRNeGtkQmV4VU8xa3JKRzRreDNQRU9IQWtIU05Xa1k3M19WRktrVGJqMUt1Yk9fNXY4UdIBX0FVX3lxTFA0SXZIRTZvS3JwQW96eU0teVk2VGVvd3A2S0dZZFFTWUNhbWZCbGxBdl9Sa1ZxUG1FRkNIajFJSkR0QmNpd0w4MS1KTHBXQ2FuSklnSlFld3dWbWdybVZn?oc=5",
"https://news.google.com/rss/articles/CBMiTkFVX3lxTE8wMkF1X2l6QUxUMDU0TTJ5UGliYy1OSDBQdnNXLWdkb1h3WndWSk5McDhvcFFtbGpIWnBRY0xJNjFmX0Z5SGZmVWxvX0ROZ9IBakFVX3lxTE9iMFFLNnNtTGl5T3FNMURvd3pGU2RTcTg5SENmMXFKUWdScXVkaUNVTXdTd1JVbWFkX0pRbzhJWFV1eUxaU0RhdFpFSFUxOWRUVDFuRWFfM2hHTEJ6VFNIdEpBVDlOcXQ5OWc?oc=5",
"https://news.google.com/rss/articles/CBMixwJBVV95cUxPeWtRdFpPd3FMT3BSazFyOE1IRy1ERnFPTlV0Q3dfUVJISkRSaUVfdlRCY3FOemEyTkxaaDQ4V09iMF8ySDRNcU91c3BPUzhCNmFRSkZDbi1VZWlJbEpRVnNCd1k3ZFpDZXc2U2tWMHRMUE54eGh1S1MtWXdIM25LUGVpbm5xMVZQRmp2ZHBqOV9fY24xOEsyUExEQVZ0T3VQYzBha20tZm1PdjU3R2hWOUdKWTBBU3VCNWkwVGRhMHZMYnpjSnFSVFNoRFV3ekVMbFczeFJNOVVfLV93aWtOeWZyUG5mUTloRThzYTA2TEN3UElrM1R3SnFyVEFrbjVVYmdWSWx2Rklyb0pBMDhia3pIa2ZtaFRVamxqTjRDeHkteFdOSnVUOXpJLVpxd2xrRVY4RXdIdi13RXhpWGZ1Q1Q1T3M2UWM?oc=5",
"https://www.gov.tw/",
"https://news.google.com/rss/articles/CBMilARBVV95cUxNdnBaYklQVkwwMXlyOWF2WDJWNHhiMGkzNXlCSW1Malo1bS1BRDJKaVBBSGRpYS1wUVRKandHVXB6TlpUNHpSbHJ3TWpfSGZCY2RjY3pUXzdJYkNCVkNYbnNTbzU1bTZLRG1GOVd3eWhxZnllRFdmbHc3UGJ5VWtMQ2FZVjZtSVgxczZORlJDN3lZWTh5SktvZUNzTC1tYzdzUDJ1MFpPa2Y4VmJ5LUljelRjMlplVTZHcFJUVUFoWi04UzhLbHhOSThvNGowYkNpc096V1FDNG9CQW1lelFheGg3YXRMRWxnQUVXVGlmZEs4SUV3RFVzbTRmT3V5RmV4akFjekZHb3ZaRG44SWlrQ3ozLXByNmNuY2p1ZGhqVndzSmx3c2lvOFRzc0c2UDhQMVpkbHdtT3ExZTNlRXFjQnJRcV9jLUtKY0R1c29iU2k0UG4zOEx5di1wSENUN3FHX0twUnVXNDNWS1F5MWZabTR2TVlBQnJ6eUNDcUdlR0VqV1F4R2ZqWnlCQnExVGp1M1BNX0F3TDJOTlk5T3lJTVJEendvMjNEb3lucUZwSkRVckQ4NmhrTV9GcHhhSHB5My1NZTlqYk9aaTgxYWtXcXc4WXlRRENIVTVaT0x4Z2UxOFZSVFo5RnNzNTVHR0wzSHJmVHl4SlcyOGtHM0pVZFd4YzFjaHNyRWQ0eWdNTGpVU0x6?oc=5",
"https://www.pchome.com.tw/"
],
"static_urls": [
"https://www.gov.tw/",
"https://www.post.gov.tw/",
"https://www.ntu.edu.tw/",
"https://www.cathaybk.com.tw/",
"https://www.thsrc.com.tw/",
"https://tw.yahoo.com/",
"https://www.momoshop.com.tw/",
"https://www.pchome.com.tw/",
"https://www.dcard.tw/"
]
}
}

View File

@@ -0,0 +1,46 @@
{
"region_name": "United Kingdom - Coventry",
"google_module": {
"base_lat": 52.4068,
"base_lon": -1.5197,
"lang_params": "hl=en&gl=GB",
"valid_url_suffix": "co.uk"
},
"trust_module": {
"white_urls": [
"https://www.barclays.co.uk/",
"https://www.bbc.com/news/articles/c77m242z2j8o?at_medium=RSS&at_campaign=rss",
"https://www.bbc.co.uk/sounds/play/p0ng84b4?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cz78x703lrvo?at_medium=RSS&at_campaign=rss",
"https://www.nationalrail.co.uk/",
"https://www.amazon.co.uk/",
"https://www.bbc.com/news/articles/cvg30jkvklno?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/videos/c75kpx2w452o?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cdrmvx8m8vgo?at_medium=RSS&at_campaign=rss",
"https://www.ebay.co.uk/",
"https://www.bbc.com/sport/football/articles/c0rxl475x8jo?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/ckgw72lrvn3o?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cz67qjn48eqo?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cn08j2g9ze9o?at_medium=RSS&at_campaign=rss",
"https://www.nhs.uk/",
"https://www.postoffice.co.uk/",
"https://www.bbc.com/news/articles/c74v2enw8l7o?at_medium=RSS&at_campaign=rss",
"https://www.gov.uk/",
"https://www.bbc.co.uk/iplayer/episode/b01p6y1c/puss-in-boots?at_mid=ovYA47yS9y&at_campaign=Film_Puss_in_Boots&at_medium=display_ad&at_campaign_type=owned&at_nation=NET&at_audience_id=SS&at_product=iplayer&at_brand=b01p6y1c&at_ptr_name=bbc&at_ptr_type=media&at_format=image&at_objective=consumption&at_link_title=Film_Puss_in_Boots&at_bbc_team=BBC&at_creation=Film",
"https://www.bbc.com/news/articles/cvg09n7gj3lo?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cj37d4gzz4xo?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cq8wnzly5j5o?at_medium=RSS&at_campaign=rss",
"https://www.ox.ac.uk/"
],
"static_urls": [
"https://www.gov.uk/",
"https://www.nhs.uk/",
"https://www.ox.ac.uk/",
"https://www.barclays.co.uk/",
"https://www.postoffice.co.uk/",
"https://www.nationalrail.co.uk/",
"https://www.amazon.co.uk/",
"https://www.ebay.co.uk/"
]
}
}

View File

@@ -0,0 +1,46 @@
{
"region_name": "United Kingdom - London",
"google_module": {
"base_lat": 51.5074,
"base_lon": -0.1278,
"lang_params": "hl=en&gl=GB",
"valid_url_suffix": "co.uk"
},
"trust_module": {
"white_urls": [
"https://www.postoffice.co.uk/",
"https://www.bbc.com/news/articles/c77m242z2j8o?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cn08j2g9ze9o?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/videos/c75kpx2w452o?at_medium=RSS&at_campaign=rss",
"https://www.ox.ac.uk/",
"https://www.bbc.com/news/articles/cvg30jkvklno?at_medium=RSS&at_campaign=rss",
"https://www.ebay.co.uk/",
"https://www.bbc.com/news/articles/cz78x703lrvo?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/ckgw72lrvn3o?at_medium=RSS&at_campaign=rss",
"https://www.bbc.co.uk/iplayer/episode/b01p6y1c/puss-in-boots?at_mid=ovYA47yS9y&at_campaign=Film_Puss_in_Boots&at_medium=display_ad&at_campaign_type=owned&at_nation=NET&at_audience_id=SS&at_product=iplayer&at_brand=b01p6y1c&at_ptr_name=bbc&at_ptr_type=media&at_format=image&at_objective=consumption&at_link_title=Film_Puss_in_Boots&at_bbc_team=BBC&at_creation=Film",
"https://www.bbc.com/news/articles/cj37d4gzz4xo?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/sport/football/articles/c0rxl475x8jo?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cvg09n7gj3lo?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cdrmvx8m8vgo?at_medium=RSS&at_campaign=rss",
"https://www.amazon.co.uk/",
"https://www.gov.uk/",
"https://www.nhs.uk/",
"https://www.bbc.com/news/articles/cq8wnzly5j5o?at_medium=RSS&at_campaign=rss",
"https://www.nationalrail.co.uk/",
"https://www.barclays.co.uk/",
"https://www.bbc.co.uk/sounds/play/p0ng84b4?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/cz67qjn48eqo?at_medium=RSS&at_campaign=rss",
"https://www.bbc.com/news/articles/c74v2enw8l7o?at_medium=RSS&at_campaign=rss"
],
"static_urls": [
"https://www.gov.uk/",
"https://www.nhs.uk/",
"https://www.ox.ac.uk/",
"https://www.barclays.co.uk/",
"https://www.postoffice.co.uk/",
"https://www.nationalrail.co.uk/",
"https://www.amazon.co.uk/",
"https://www.ebay.co.uk/"
]
}
}

View File

@@ -1,10 +0,0 @@
{
"region_code": "US",
"region_name": "美国 (美西洛杉矶)",
"google_module": {
"base_lat": 34.0522,
"base_lon": -118.2437,
"lang_params": "hl=en&gl=us&ceid=US:en",
"valid_url_suffix": "google.com"
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "United States - Los Angeles",
"google_module": {
"base_lat": 34.0522,
"base_lon": -118.2437,
"lang_params": "hl=en&gl=US",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://www.cnn.com/2023/04/18/politics/white-house-toddler/index.html",
"https://www.cdc.gov/",
"https://www.cnn.com/style/article/ai-photo-win-sony-scli-intl/index.html",
"https://www.cnn.com/videos/politics/2023/04/18/kevin-mccarthy-wall-street-speech-debt-ceiling-biden-economy-vpx.cnn",
"https://www.irs.gov/",
"https://www.cnn.com/cnn-underscored/reviews/mmmat-silicone-mats?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/2023/04/17/opinions/jim-jordan-clarence-thomas-judiciary-committee-obeidallah/index.html",
"https://www.cnn.com/cnn-underscored/money/high-yield-savings-accounts?iid=CNNUnderscoredHPcontainer",
"https://www.usa.gov/",
"https://www.cnn.com/videos/travel/2023/04/18/century-old-shipwrecks-lake-superior-discovery-contd-orig-zt.cnn",
"https://www.cnn.com/2023/04/18/politics/mccarthy-biden-debt-ceiling/index.html",
"https://www.chase.com/",
"https://www.harvard.edu/",
"https://www.cnn.com/cnn-underscored/money/how-to-file-taxes?iid=CNNUnderscoredHPcontainer",
"https://www.npr.org/2026/04/24/nx-s1-5794052/nfl-draft-pittsburgh-fans",
"https://www.walmart.com/",
"https://www.target.com/",
"https://www.cnn.com/2023/04/18/us/benadryl-tiktok-challenge-teen-death-wellness/index.html",
"https://www.bankofamerica.com/",
"https://www.usps.com/",
"https://www.npr.org/2026/04/24/nx-s1-5797964/after-2-failed-votes-mike-johnson-unveils-new-plan-to-extend-key-u-s-spy-powers",
"https://www.cnn.com/2023/04/18/entertainment/jake-gyllenhaal-jamie-lee-curtis-pandemic-living/index.html",
"https://www.cnn.com/2023/04/18/opinions/medication-abortion-mifepristone-miscarriage-jones-ctpr/index.html",
"https://www.amazon.com/",
"https://www.cnn.com/2023/04/16/opinions/top-secrets-come-spilling-out-opinion-column-galant/index.html"
],
"static_urls": [
"https://www.usa.gov/",
"https://www.irs.gov/",
"https://www.cdc.gov/",
"https://www.harvard.edu/",
"https://www.chase.com/",
"https://www.bankofamerica.com/",
"https://www.amazon.com/",
"https://www.target.com/",
"https://www.walmart.com/",
"https://www.usps.com/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "United States - San Jose",
"google_module": {
"base_lat": 37.3382,
"base_lon": -121.8863,
"lang_params": "hl=en&gl=US",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://www.cnn.com/2023/04/18/us/benadryl-tiktok-challenge-teen-death-wellness/index.html",
"https://www.cnn.com/cnn-underscored/reviews/mmmat-silicone-mats?iid=CNNUnderscoredHPcontainer",
"https://www.bankofamerica.com/",
"https://www.cnn.com/2023/04/18/entertainment/jake-gyllenhaal-jamie-lee-curtis-pandemic-living/index.html",
"https://www.cnn.com/videos/politics/2023/04/18/kevin-mccarthy-wall-street-speech-debt-ceiling-biden-economy-vpx.cnn",
"https://www.walmart.com/",
"https://www.cnn.com/2023/04/16/opinions/top-secrets-come-spilling-out-opinion-column-galant/index.html",
"https://www.chase.com/",
"https://www.cnn.com/style/article/ai-photo-win-sony-scli-intl/index.html",
"https://www.usps.com/",
"https://www.cnn.com/2023/04/18/politics/mccarthy-biden-debt-ceiling/index.html",
"https://www.irs.gov/",
"https://www.amazon.com/",
"https://www.usa.gov/",
"https://www.harvard.edu/",
"https://www.cnn.com/cnn-underscored/money/high-yield-savings-accounts?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/2023/04/17/opinions/jim-jordan-clarence-thomas-judiciary-committee-obeidallah/index.html",
"https://www.cnn.com/cnn-underscored/money/how-to-file-taxes?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/videos/travel/2023/04/18/century-old-shipwrecks-lake-superior-discovery-contd-orig-zt.cnn",
"https://www.cnn.com/2023/04/18/opinions/medication-abortion-mifepristone-miscarriage-jones-ctpr/index.html",
"https://www.npr.org/2026/04/24/nx-s1-5797964/after-2-failed-votes-mike-johnson-unveils-new-plan-to-extend-key-u-s-spy-powers",
"https://www.cnn.com/2023/04/18/politics/white-house-toddler/index.html",
"https://www.target.com/",
"https://www.cdc.gov/",
"https://www.npr.org/2026/04/24/nx-s1-5794052/nfl-draft-pittsburgh-fans"
],
"static_urls": [
"https://www.usa.gov/",
"https://www.irs.gov/",
"https://www.cdc.gov/",
"https://www.harvard.edu/",
"https://www.chase.com/",
"https://www.bankofamerica.com/",
"https://www.amazon.com/",
"https://www.target.com/",
"https://www.walmart.com/",
"https://www.usps.com/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "United States - Warrenville",
"google_module": {
"base_lat": 41.8164,
"base_lon": -88.1748,
"lang_params": "hl=en&gl=US",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://www.npr.org/2026/04/24/nx-s1-5797964/after-2-failed-votes-mike-johnson-unveils-new-plan-to-extend-key-u-s-spy-powers",
"https://www.harvard.edu/",
"https://www.npr.org/2026/04/24/nx-s1-5794052/nfl-draft-pittsburgh-fans",
"https://www.cnn.com/2023/04/18/politics/white-house-toddler/index.html",
"https://www.cnn.com/cnn-underscored/money/high-yield-savings-accounts?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/2023/04/18/entertainment/jake-gyllenhaal-jamie-lee-curtis-pandemic-living/index.html",
"https://www.chase.com/",
"https://www.cnn.com/2023/04/18/politics/mccarthy-biden-debt-ceiling/index.html",
"https://www.bankofamerica.com/",
"https://www.cnn.com/videos/travel/2023/04/18/century-old-shipwrecks-lake-superior-discovery-contd-orig-zt.cnn",
"https://www.cnn.com/cnn-underscored/reviews/mmmat-silicone-mats?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/2023/04/17/opinions/jim-jordan-clarence-thomas-judiciary-committee-obeidallah/index.html",
"https://www.cnn.com/2023/04/16/opinions/top-secrets-come-spilling-out-opinion-column-galant/index.html",
"https://www.cnn.com/videos/politics/2023/04/18/kevin-mccarthy-wall-street-speech-debt-ceiling-biden-economy-vpx.cnn",
"https://www.cnn.com/2023/04/18/opinions/medication-abortion-mifepristone-miscarriage-jones-ctpr/index.html",
"https://www.walmart.com/",
"https://www.cdc.gov/",
"https://www.usa.gov/",
"https://www.irs.gov/",
"https://www.target.com/",
"https://www.cnn.com/cnn-underscored/money/how-to-file-taxes?iid=CNNUnderscoredHPcontainer",
"https://www.usps.com/",
"https://www.cnn.com/style/article/ai-photo-win-sony-scli-intl/index.html",
"https://www.amazon.com/",
"https://www.cnn.com/2023/04/18/us/benadryl-tiktok-challenge-teen-death-wellness/index.html"
],
"static_urls": [
"https://www.usa.gov/",
"https://www.irs.gov/",
"https://www.cdc.gov/",
"https://www.harvard.edu/",
"https://www.chase.com/",
"https://www.bankofamerica.com/",
"https://www.amazon.com/",
"https://www.target.com/",
"https://www.walmart.com/",
"https://www.usps.com/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "United States - Charlotte",
"google_module": {
"base_lat": 35.2271,
"base_lon": -80.8431,
"lang_params": "hl=en&gl=US",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://www.usps.com/",
"https://www.target.com/",
"https://www.amazon.com/",
"https://www.bankofamerica.com/",
"https://www.cnn.com/2023/04/16/opinions/top-secrets-come-spilling-out-opinion-column-galant/index.html",
"https://www.cnn.com/videos/travel/2023/04/18/century-old-shipwrecks-lake-superior-discovery-contd-orig-zt.cnn",
"https://www.cnn.com/2023/04/18/politics/white-house-toddler/index.html",
"https://www.cnn.com/cnn-underscored/reviews/mmmat-silicone-mats?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/videos/politics/2023/04/18/kevin-mccarthy-wall-street-speech-debt-ceiling-biden-economy-vpx.cnn",
"https://www.npr.org/2026/04/24/nx-s1-5797964/after-2-failed-votes-mike-johnson-unveils-new-plan-to-extend-key-u-s-spy-powers",
"https://www.cnn.com/2023/04/18/entertainment/jake-gyllenhaal-jamie-lee-curtis-pandemic-living/index.html",
"https://www.harvard.edu/",
"https://www.chase.com/",
"https://www.cnn.com/cnn-underscored/money/high-yield-savings-accounts?iid=CNNUnderscoredHPcontainer",
"https://www.npr.org/2026/04/24/nx-s1-5794052/nfl-draft-pittsburgh-fans",
"https://www.usa.gov/",
"https://www.walmart.com/",
"https://www.cnn.com/2023/04/18/opinions/medication-abortion-mifepristone-miscarriage-jones-ctpr/index.html",
"https://www.cnn.com/2023/04/18/us/benadryl-tiktok-challenge-teen-death-wellness/index.html",
"https://www.cnn.com/2023/04/17/opinions/jim-jordan-clarence-thomas-judiciary-committee-obeidallah/index.html",
"https://www.cdc.gov/",
"https://www.irs.gov/",
"https://www.cnn.com/style/article/ai-photo-win-sony-scli-intl/index.html",
"https://www.cnn.com/2023/04/18/politics/mccarthy-biden-debt-ceiling/index.html",
"https://www.cnn.com/cnn-underscored/money/how-to-file-taxes?iid=CNNUnderscoredHPcontainer"
],
"static_urls": [
"https://www.usa.gov/",
"https://www.irs.gov/",
"https://www.cdc.gov/",
"https://www.harvard.edu/",
"https://www.chase.com/",
"https://www.bankofamerica.com/",
"https://www.amazon.com/",
"https://www.target.com/",
"https://www.walmart.com/",
"https://www.usps.com/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "United States - Las Vegas",
"google_module": {
"base_lat": 36.1699,
"base_lon": -115.1398,
"lang_params": "hl=en&gl=US",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://www.cnn.com/cnn-underscored/reviews/mmmat-silicone-mats?iid=CNNUnderscoredHPcontainer",
"https://www.irs.gov/",
"https://www.harvard.edu/",
"https://www.npr.org/2026/04/24/nx-s1-5794052/nfl-draft-pittsburgh-fans",
"https://www.cnn.com/style/article/ai-photo-win-sony-scli-intl/index.html",
"https://www.cnn.com/videos/politics/2023/04/18/kevin-mccarthy-wall-street-speech-debt-ceiling-biden-economy-vpx.cnn",
"https://www.cnn.com/2023/04/18/us/benadryl-tiktok-challenge-teen-death-wellness/index.html",
"https://www.cdc.gov/",
"https://www.target.com/",
"https://www.cnn.com/2023/04/18/opinions/medication-abortion-mifepristone-miscarriage-jones-ctpr/index.html",
"https://www.walmart.com/",
"https://www.amazon.com/",
"https://www.cnn.com/cnn-underscored/money/high-yield-savings-accounts?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/2023/04/18/politics/white-house-toddler/index.html",
"https://www.cnn.com/2023/04/18/entertainment/jake-gyllenhaal-jamie-lee-curtis-pandemic-living/index.html",
"https://www.cnn.com/2023/04/17/opinions/jim-jordan-clarence-thomas-judiciary-committee-obeidallah/index.html",
"https://www.cnn.com/2023/04/18/politics/mccarthy-biden-debt-ceiling/index.html",
"https://www.cnn.com/videos/travel/2023/04/18/century-old-shipwrecks-lake-superior-discovery-contd-orig-zt.cnn",
"https://www.chase.com/",
"https://www.cnn.com/cnn-underscored/money/how-to-file-taxes?iid=CNNUnderscoredHPcontainer",
"https://www.usa.gov/",
"https://www.usps.com/",
"https://www.npr.org/2026/04/24/nx-s1-5797964/after-2-failed-votes-mike-johnson-unveils-new-plan-to-extend-key-u-s-spy-powers",
"https://www.bankofamerica.com/",
"https://www.cnn.com/2023/04/16/opinions/top-secrets-come-spilling-out-opinion-column-galant/index.html"
],
"static_urls": [
"https://www.usa.gov/",
"https://www.irs.gov/",
"https://www.cdc.gov/",
"https://www.harvard.edu/",
"https://www.chase.com/",
"https://www.bankofamerica.com/",
"https://www.amazon.com/",
"https://www.target.com/",
"https://www.walmart.com/",
"https://www.usps.com/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "United States - Bend",
"google_module": {
"base_lat": 44.0582,
"base_lon": -121.3153,
"lang_params": "hl=en&gl=US",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://www.bankofamerica.com/",
"https://www.chase.com/",
"https://www.npr.org/2026/04/24/nx-s1-5794052/nfl-draft-pittsburgh-fans",
"https://www.cnn.com/videos/politics/2023/04/18/kevin-mccarthy-wall-street-speech-debt-ceiling-biden-economy-vpx.cnn",
"https://www.cnn.com/2023/04/18/politics/white-house-toddler/index.html",
"https://www.cnn.com/2023/04/18/us/benadryl-tiktok-challenge-teen-death-wellness/index.html",
"https://www.cnn.com/cnn-underscored/money/how-to-file-taxes?iid=CNNUnderscoredHPcontainer",
"https://www.irs.gov/",
"https://www.amazon.com/",
"https://www.npr.org/2026/04/24/nx-s1-5797964/after-2-failed-votes-mike-johnson-unveils-new-plan-to-extend-key-u-s-spy-powers",
"https://www.cnn.com/style/article/ai-photo-win-sony-scli-intl/index.html",
"https://www.cnn.com/cnn-underscored/money/high-yield-savings-accounts?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/cnn-underscored/reviews/mmmat-silicone-mats?iid=CNNUnderscoredHPcontainer",
"https://www.harvard.edu/",
"https://www.cnn.com/videos/travel/2023/04/18/century-old-shipwrecks-lake-superior-discovery-contd-orig-zt.cnn",
"https://www.usps.com/",
"https://www.cnn.com/2023/04/18/opinions/medication-abortion-mifepristone-miscarriage-jones-ctpr/index.html",
"https://www.cnn.com/2023/04/18/politics/mccarthy-biden-debt-ceiling/index.html",
"https://www.cnn.com/2023/04/17/opinions/jim-jordan-clarence-thomas-judiciary-committee-obeidallah/index.html",
"https://www.cnn.com/2023/04/16/opinions/top-secrets-come-spilling-out-opinion-column-galant/index.html",
"https://www.cdc.gov/",
"https://www.target.com/",
"https://www.walmart.com/",
"https://www.usa.gov/",
"https://www.cnn.com/2023/04/18/entertainment/jake-gyllenhaal-jamie-lee-curtis-pandemic-living/index.html"
],
"static_urls": [
"https://www.usa.gov/",
"https://www.irs.gov/",
"https://www.cdc.gov/",
"https://www.harvard.edu/",
"https://www.chase.com/",
"https://www.bankofamerica.com/",
"https://www.amazon.com/",
"https://www.target.com/",
"https://www.walmart.com/",
"https://www.usps.com/"
]
}
}

View File

@@ -0,0 +1,45 @@
{
"region_name": "United States - Dallas",
"google_module": {
"base_lat": 32.7767,
"base_lon": -96.7970,
"lang_params": "hl=en&gl=US",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://www.dallasnews.com/",
"https://www.texas.gov/",
"https://www.wfaa.com/",
"https://www.nbcdfw.com/",
"https://www.fox4news.com/",
"https://www.dallascityhall.com/",
"https://www.cnn.com/",
"https://www.foxnews.com/",
"https://www.nytimes.com/",
"https://www.wsj.com/",
"https://www.usatoday.com/",
"https://www.amazon.com/",
"https://www.walmart.com/",
"https://www.target.com/",
"https://www.chase.com/",
"https://www.bankofamerica.com/",
"https://www.wellsfargo.com/",
"https://www.zillow.com/",
"https://www.espn.com/",
"https://www.weather.com/"
],
"static_urls": [
"https://www.texas.gov/",
"https://www.dallasnews.com/",
"https://www.cnn.com/",
"https://www.foxnews.com/",
"https://www.nytimes.com/",
"https://www.amazon.com/",
"https://www.walmart.com/",
"https://www.target.com/",
"https://www.chase.com/",
"https://www.bankofamerica.com/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "United States - Salt Lake City",
"google_module": {
"base_lat": 40.7608,
"base_lon": -111.891,
"lang_params": "hl=en&gl=US",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://www.cnn.com/2023/04/18/entertainment/jake-gyllenhaal-jamie-lee-curtis-pandemic-living/index.html",
"https://www.cnn.com/2023/04/16/opinions/top-secrets-come-spilling-out-opinion-column-galant/index.html",
"https://www.npr.org/2026/04/24/nx-s1-5794052/nfl-draft-pittsburgh-fans",
"https://www.cnn.com/style/article/ai-photo-win-sony-scli-intl/index.html",
"https://www.cnn.com/videos/politics/2023/04/18/kevin-mccarthy-wall-street-speech-debt-ceiling-biden-economy-vpx.cnn",
"https://www.cnn.com/2023/04/18/politics/mccarthy-biden-debt-ceiling/index.html",
"https://www.cnn.com/cnn-underscored/money/high-yield-savings-accounts?iid=CNNUnderscoredHPcontainer",
"https://www.chase.com/",
"https://www.harvard.edu/",
"https://www.cnn.com/2023/04/17/opinions/jim-jordan-clarence-thomas-judiciary-committee-obeidallah/index.html",
"https://www.npr.org/2026/04/24/nx-s1-5797964/after-2-failed-votes-mike-johnson-unveils-new-plan-to-extend-key-u-s-spy-powers",
"https://www.cnn.com/2023/04/18/politics/white-house-toddler/index.html",
"https://www.cnn.com/cnn-underscored/reviews/mmmat-silicone-mats?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/videos/travel/2023/04/18/century-old-shipwrecks-lake-superior-discovery-contd-orig-zt.cnn",
"https://www.target.com/",
"https://www.cnn.com/2023/04/18/opinions/medication-abortion-mifepristone-miscarriage-jones-ctpr/index.html",
"https://www.cdc.gov/",
"https://www.bankofamerica.com/",
"https://www.cnn.com/2023/04/18/us/benadryl-tiktok-challenge-teen-death-wellness/index.html",
"https://www.irs.gov/",
"https://www.usa.gov/",
"https://www.walmart.com/",
"https://www.amazon.com/",
"https://www.usps.com/",
"https://www.cnn.com/cnn-underscored/money/how-to-file-taxes?iid=CNNUnderscoredHPcontainer"
],
"static_urls": [
"https://www.usa.gov/",
"https://www.irs.gov/",
"https://www.cdc.gov/",
"https://www.harvard.edu/",
"https://www.chase.com/",
"https://www.bankofamerica.com/",
"https://www.amazon.com/",
"https://www.target.com/",
"https://www.walmart.com/",
"https://www.usps.com/"
]
}
}

View File

@@ -0,0 +1,50 @@
{
"region_name": "United States - Seattle",
"google_module": {
"base_lat": 47.6062,
"base_lon": -122.3321,
"lang_params": "hl=en&gl=US",
"valid_url_suffix": "com"
},
"trust_module": {
"white_urls": [
"https://www.cnn.com/2023/04/18/politics/white-house-toddler/index.html",
"https://www.cnn.com/cnn-underscored/money/high-yield-savings-accounts?iid=CNNUnderscoredHPcontainer",
"https://www.walmart.com/",
"https://www.cnn.com/2023/04/18/us/benadryl-tiktok-challenge-teen-death-wellness/index.html",
"https://www.npr.org/2026/04/24/nx-s1-5797964/after-2-failed-votes-mike-johnson-unveils-new-plan-to-extend-key-u-s-spy-powers",
"https://www.cnn.com/2023/04/18/opinions/medication-abortion-mifepristone-miscarriage-jones-ctpr/index.html",
"https://www.cnn.com/style/article/ai-photo-win-sony-scli-intl/index.html",
"https://www.cnn.com/cnn-underscored/money/how-to-file-taxes?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/videos/travel/2023/04/18/century-old-shipwrecks-lake-superior-discovery-contd-orig-zt.cnn",
"https://www.usa.gov/",
"https://www.cnn.com/cnn-underscored/reviews/mmmat-silicone-mats?iid=CNNUnderscoredHPcontainer",
"https://www.cnn.com/2023/04/18/politics/mccarthy-biden-debt-ceiling/index.html",
"https://www.cnn.com/videos/politics/2023/04/18/kevin-mccarthy-wall-street-speech-debt-ceiling-biden-economy-vpx.cnn",
"https://www.harvard.edu/",
"https://www.npr.org/2026/04/24/nx-s1-5794052/nfl-draft-pittsburgh-fans",
"https://www.cnn.com/2023/04/16/opinions/top-secrets-come-spilling-out-opinion-column-galant/index.html",
"https://www.bankofamerica.com/",
"https://www.cnn.com/2023/04/18/entertainment/jake-gyllenhaal-jamie-lee-curtis-pandemic-living/index.html",
"https://www.cdc.gov/",
"https://www.target.com/",
"https://www.amazon.com/",
"https://www.chase.com/",
"https://www.usps.com/",
"https://www.irs.gov/",
"https://www.cnn.com/2023/04/17/opinions/jim-jordan-clarence-thomas-judiciary-committee-obeidallah/index.html"
],
"static_urls": [
"https://www.usa.gov/",
"https://www.irs.gov/",
"https://www.cdc.gov/",
"https://www.harvard.edu/",
"https://www.chase.com/",
"https://www.bankofamerica.com/",
"https://www.amazon.com/",
"https://www.target.com/",
"https://www.walmart.com/",
"https://www.usps.com/"
]
}
}

View File

@@ -0,0 +1,44 @@
{
"region_name": "Vietnam - Hanoi",
"google_module": {
"base_lat": 21.0285,
"base_lon": 105.8542,
"lang_params": "hl=vi&gl=VN",
"valid_url_suffix": "vn"
},
"trust_module": {
"white_urls": [
"https://shopee.vn/",
"https://vnexpress.net/nguoi-dan-ong-dam-o-2-be-gai-bi-bat-5066872.html",
"https://vnexpress.net/sat-hai-dong-nghiep-roi-khai-gian-la-tai-nan-5066845.html",
"https://vnexpress.net/tim-mot-nguoi-de-o-lai-khong-phai-de-di-qua-5066545.html",
"https://www.vietcombank.com.vn/",
"https://vnexpress.net/de-xuat-doi-dat-ben-xe-mien-dong-lam-du-an-giam-ket-xe-hang-xanh-binh-trieu-5066900.html",
"https://vnexpress.net/thoi-trang-sanh-doi-cua-hau-ve-vu-van-thanh-va-ban-gai-5065410.html",
"https://vnu.edu.vn/",
"https://vnexpress.net/toi-chon-o-do-bua-bon-giong-chong-de-gia-dinh-luon-vui-ve-5066891.html",
"https://vnexpress.net/viet-nam-mua-oto-tu-nuoc-nao-nhieu-nhat-5066853.html",
"https://vnexpress.net/msb-dat-muc-tieu-lai-8-000-ty-dong-5066868.html",
"https://vnexpress.net/",
"https://vnexpress.net/tim-nguoi-dong-hanh-chan-thanh-giua-cuoc-song-gian-di-5066547.html",
"https://dichvucong.gov.vn/",
"https://vnexpress.net/van-may-12-con-giap-con-giap-may-man-hom-nay-4-con-giap-thu-nhap-gap-doi-giau-sang-phu-quy-vao-cuoi-tuan-5066289.html",
"https://vnexpress.net/cuu-vien-pho-va-kiem-sat-vien-vu-nu-sinh-tu-vong-o-vinh-long-bi-khoi-to-5066878.html",
"https://tiki.vn/",
"https://vnexpress.net/petrolimex-du-kien-lo-hon-1-000-ty-dong-kinh-doanh-xang-dau-quy-i-5066857.html",
"https://vnexpress.net/khung-hoang-nha-ve-sinh-cong-cong-o-anh-5066244.html",
"https://vnexpress.net/trang-phuc-cua-phu-nhan-tong-thong-han-quoc-khi-o-viet-nam-5066803.html",
"https://vnexpress.net/bao-malaysia-viet-nam-qua-manh-5066906.html",
"https://chinhphu.vn/"
],
"static_urls": [
"https://chinhphu.vn/",
"https://dichvucong.gov.vn/",
"https://vnu.edu.vn/",
"https://www.vietcombank.com.vn/",
"https://shopee.vn/",
"https://tiki.vn/",
"https://vnexpress.net/"
]
}
}

File diff suppressed because it is too large Load Diff

358
master/install_master.sh Normal file → Executable file
View File

@@ -1,39 +1,258 @@
#!/bin/bash
# ==========================================================
# 脚本名称: install_master.sh (IP-Sentinel 控制中枢部署脚本)
# 核心功能: 安装 SQLite3、初始化数据库表、配置后台守护进程
# 脚本名称: install_master.sh (IP-Sentinel 控制中枢部署脚本 - 动态锚点版)
# 核心功能: 部署/卸载调度中枢、SQLite 资产管理、平滑热更新引擎
# ==========================================================
# ==========================================================
# 🛑 核心权限防线: 检查是否以 root 权限运行
# ==========================================================
if [ "$EUID" -ne 0 ]; then
echo -e "\033[31m❌ 权限被拒绝: 部署 IP-Sentinel 需要最高系统权限。\033[0m"
echo -e "💡 请切换到 root 用户 (执行 su root 或 sudo -i) 后重新运行指令。"
exit 1
fi
# 你的 GitHub 仓库 Raw 数据直链前缀
REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/main"
# 临时改为开发地址用于测试
# REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/v3.6.2-rc"
# [核心: 动态提取 Master 专属版本锚点 (KV 解析法)]
# 通过 grep 定位 MASTER_VERSION 行,再通过 cut 提取等号右侧的值
# [修复] 增加 -L 与双栈容灾 (-4),解决纯 V6 或 V6 优先机器连接 GitHub Raw 易超时的问题
TARGET_VERSION=$( (curl -sL -m 5 "${REPO_RAW_URL}/version.txt" || curl -4 -sL -m 5 "${REPO_RAW_URL}/version.txt") 2>/dev/null | grep "^MASTER_VERSION=" | cut -d'=' -f2 | tr -d '[:space:]')
# 🛡️ 兜底防线:如果网络波动拉取失败,启用内置的最新兜底版本
TARGET_VERSION=${TARGET_VERSION:-"4.0.0"}
MASTER_DIR="/opt/ip_sentinel_master"
DB_FILE="${MASTER_DIR}/sentinel.db"
echo "========================================================"
echo " 🧠 准备部署 IP-Sentinel Master 控制中枢"
# [修改] 将欢迎语改为更通用的文案,因为现在不仅能部署,还能卸载
echo " 🧠 欢迎使用 IP-Sentinel Master (控制中枢) v${TARGET_VERSION}"
echo "========================================================"
# 1. 环境依赖安装
echo "[1/4] 安装核心依赖 (curl, jq, sqlite3)..."
if [ -f /etc/debian_version ]; then
apt-get update -y >/dev/null 2>&1
apt-get install -y curl jq sqlite3 procps >/dev/null 2>&1
elif [ -f /etc/redhat-release ]; then
yum install -y curl jq sqlite >/dev/null 2>&1
# ==========================================================
# [v3.6.1 核心] 拦截司令部静默 OTA 升级模式 (强行接管执行流)
# ==========================================================
if [ "$SILENT_MASTER_OTA" == "true" ]; then
echo -e "\n⏳ [OTA] 中枢重构指令已确认,正在剥离控制台交互..."
ACTION_CHOICE=1
UPGRADE_MODE="true"
KEEP_DB="true"
# 汲取原配置进入内存
if [ -f "${MASTER_DIR}/master.conf" ]; then
source "${MASTER_DIR}/master.conf"
# 同步新版本号至配置文件
if grep -q "^MASTER_VERSION=" "${MASTER_DIR}/master.conf"; then
sed -i "s/^MASTER_VERSION=.*/MASTER_VERSION=\"$TARGET_VERSION\"/" "${MASTER_DIR}/master.conf"
else
echo "MASTER_VERSION=\"$TARGET_VERSION\"" >> "${MASTER_DIR}/master.conf"
fi
fi
echo -e "\033[32m✅ 已激活 [中枢静默重构模式],即将无损覆写内核...\033[0m"
else
# [新增] 交互式操作菜单:支持选择部署或调用卸载程序
echo -e "\n请选择操作:"
echo " 1) 🚀 部署 Master 控制中枢"
echo " 2) 🗑️ 一键卸载 Master 中枢"
read -p "请输入选择 [1-2] (默认1): " ACTION_CHOICE
# [v3.5.2 修复] 防止用户直接回车导致变量为空,从而漏过下方的平滑升级判定被误删档
ACTION_CHOICE=${ACTION_CHOICE:-1}
if [ "$ACTION_CHOICE" == "2" ]; then
echo -e "\n⏳ 正在拉取卸载程序..."
curl -sL "${REPO_RAW_URL}/master/uninstall_master.sh" -o "/tmp/uninstall_master.sh"
chmod +x "/tmp/uninstall_master.sh"
bash "/tmp/uninstall_master.sh"
rm -f "/tmp/uninstall_master.sh"
exit 0
fi
# ================== [v3.2.2 新增: 平滑升级模式嗅探] ==================
UPGRADE_MODE="false"
KEEP_DB="true"
if [ "$ACTION_CHOICE" == "1" ] && [ -f "${MASTER_DIR}/master.conf" ]; then
echo -e "\n\033[33m💡 司令部雷达提示:检测到本机已部署过 Master 中枢。\033[0m"
read -p "👉 是否按原配置直接进行平滑升级?(y/n, 默认y): " UPGRADE_CHOICE
if [[ -z "$UPGRADE_CHOICE" || "$UPGRADE_CHOICE" =~ ^[Yy]$ ]]; then
UPGRADE_MODE="true"
read -p "👉 是否保留历史节点数据库 (SQLite)(y/n, 默认y): " DB_CHOICE
if [[ "$DB_CHOICE" =~ ^[Nn]$ ]]; then
KEEP_DB="false"
fi
source "${MASTER_DIR}/master.conf"
if grep -q "^MASTER_VERSION=" "${MASTER_DIR}/master.conf"; then
sed -i "s/^MASTER_VERSION=.*/MASTER_VERSION=\"$TARGET_VERSION\"/" "${MASTER_DIR}/master.conf"
else
echo "MASTER_VERSION=\"$TARGET_VERSION\"" >> "${MASTER_DIR}/master.conf"
fi
echo -e "\033[32m✅ 已激活 [平滑升级模式],版本已锚定为 v${TARGET_VERSION}...\033[0m"
else
echo -e "\033[33m🔄 您选择了重新配置,旧的中枢数据将被彻底抹除。\033[0m"
fi
fi
fi
# ================== [v3.2.2 优化: 安装前环境纯净度清理与数据保护] ==================
echo -e "\n⏳ 正在清理旧版 Master 守护进程..."
# [新增] 优雅停止 Systemd 服务,防止代码替换时引发无限复活风暴
if command -v systemctl >/dev/null 2>&1; then
systemctl stop ip-sentinel-master.service >/dev/null 2>&1 || true
fi
pkill -9 -f "tg_master.sh" >/dev/null 2>&1 || true
if [ "$UPGRADE_MODE" == "true" ]; then
if [ "$KEEP_DB" == "false" ]; then
rm -f "$DB_FILE" 2>/dev/null
echo -e "🗑️ 历史节点数据库已按指令清空。"
else
echo -e "📦 历史节点数据库 (SQLite) 已绝密保留。"
fi
# 删除旧的核心脚本,准备拉取新的
rm -f "${MASTER_DIR}/tg_master.sh" 2>/dev/null
else
# 焦土政策:如果不是升级模式,直接扬了整个司令部目录
rm -rf "$MASTER_DIR" 2>/dev/null
fi
echo -e "\033[32m✅ 旧进程已肃清!\033[0m"
# =======================================================================
# 1. 依赖检查与智能安装 (v3.6.0 兼容性与优雅性升级)
echo -e "\n[1/4] 正在探测核心依赖 (curl, jq, sqlite3, crontab, pgrep, openssl)..."
REQUIRED_CMDS=("curl" "jq" "sqlite3" "crontab" "pgrep" "openssl")
MISSING_CMDS=()
# 基础探测:预检查缺失的命令
for cmd in "${REQUIRED_CMDS[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
MISSING_CMDS+=("$cmd")
fi
done
# 如果有缺失,才执行包管理器拉取逻辑
if [ ${#MISSING_CMDS[@]} -gt 0 ]; then
echo "⏳ 发现缺失依赖: ${MISSING_CMDS[*]},正在尝试自动补齐..."
if command -v apt-get >/dev/null 2>&1; then
apt-get update -y >/dev/null 2>&1
# [v3.6.3 抽脂级优化] 注入 --no-install-recommends 拒绝捆绑销售
apt-get install -y --no-install-recommends curl jq sqlite3 cron procps openssl >/dev/null 2>&1
systemctl enable cron >/dev/null 2>&1 && systemctl start cron >/dev/null 2>&1
elif command -v yum >/dev/null 2>&1 || command -v dnf >/dev/null 2>&1; then
PKG_MGR="yum"
OPT_ARGS=""
if command -v dnf >/dev/null 2>&1; then
PKG_MGR="dnf"
# [v3.6.3 抽脂级优化] 强行关闭 DNF 的弱依赖拉取
OPT_ARGS="--setopt=install_weak_deps=False"
fi
$PKG_MGR install -y $OPT_ARGS curl jq sqlite cronie procps-ng openssl >/dev/null 2>&1
systemctl enable crond >/dev/null 2>&1 && systemctl start crond >/dev/null 2>&1
elif command -v apk >/dev/null 2>&1; then
echo "Alpine 探测到系统类型为 Alpine Linux正在执行轻量级安装..."
# [修复] 优先尝试 cronie若失败则回退至系统内置 cron彻底避免单点依赖拖垮全局
apk add --no-cache curl jq sqlite cronie procps bash openssl || apk add --no-cache curl jq sqlite procps bash openssl
mkdir -p /var/spool/cron/crontabs
rc-update add crond default >/dev/null 2>&1
service crond start >/dev/null 2>&1
elif command -v pacman >/dev/null 2>&1; then
pacman -Sy --noconfirm curl jq sqlite cronie procps-ng openssl >/dev/null 2>&1
mkdir -p /root/.cache/crontab 2>/dev/null
systemctl enable cronie >/dev/null 2>&1 && systemctl start cronie >/dev/null 2>&1
else
echo -e "\033[31m❌ 自动安装失败:系统未知的包管理器。\033[0m"
echo -e "\033[33m⚠ 请手动执行以下安装命令后重新运行本脚本:\033[0m"
echo -e " Debian/Ubuntu: \033[36mapt-get update && apt-get install -y --no-install-recommends curl jq sqlite3 cron procps openssl\033[0m"
echo -e " CentOS/RHEL: \033[36myum install -y curl jq sqlite cronie procps-ng openssl\033[0m"
echo -e " Alpine Linux: \033[36mapk add --no-cache curl jq sqlite cronie procps bash openssl\033[0m"
echo -e " Arch Linux: \033[36mpacman -Sy curl jq sqlite cronie procps-ng openssl\033[0m"
exit 1
fi
# 安装后二次复检
for cmd in "${REQUIRED_CMDS[@]}"; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo -e "\033[31m❌ 致命错误:核心命令 '$cmd' 仍未找到!\033[0m"
echo -e "请手动修复您的包管理器源,或联系 VPS 供应商。"
exit 1
fi
done
fi
echo -e "\033[32m✅ 基础环境检测通过。\033[0m"
mkdir -p "$MASTER_DIR"
# 2. 交互配置机器人
echo -e "\n[2/4] 配置控制中枢机器人:"
read -p "请输入 Telegram Bot Token: " TG_TOKEN
# ==========================================================
# 🛑 如果是全新部署,才询问 Token 并写入配置
# ==========================================================
if [ "$UPGRADE_MODE" == "false" ]; then
# 2. 交互配置机器人
echo -e "\n[2/4] 配置控制中枢机器人:"
read -p "请输入 Telegram Bot Token: " TG_TOKEN
# [v3.6.0 新增] 官方网关模式选项 (用于屏蔽全局 OTA 按钮)
echo -e "\n请选择您的部署环境身份:"
echo " 1) 🛡️ 私有独立中枢 (默认推荐,保留完整 OTA 遥控权限)"
echo " 2) ☁️ 官方公共网关 (面向大众服务,将强制物理隐藏全局 OTA 按钮防滥用)"
read -p "请输入选择 [1-2] (默认1): " GATEWAY_TYPE
GATEWAY_TYPE=${GATEWAY_TYPE:-1}
IS_OFFICIAL_GATEWAY="false"
ENABLE_MASTER_OTA="false"
if [ "$GATEWAY_TYPE" == "2" ]; then
IS_OFFICIAL_GATEWAY="true"
echo -e "\033[33m⚠ 已开启官方公共网关模式,全舰队与司令部的 OTA 将被强制屏蔽。\033[0m"
else
# [v3.6.1] 私有模式开放中枢 OTA 授权向导
echo -e "\n[2.1/4] 司令部自我进化授权"
echo -e "💡 开启后,您可以在 TG 菜单一键将中枢核心系统热更新至最新版本。"
read -p "是否允许司令部接收 OTA 重构指令?(y/n, 默认y): " M_OTA_CHOICE
if [[ "$M_OTA_CHOICE" =~ ^[Nn]$ ]]; then
ENABLE_MASTER_OTA="false"
echo -e "🛡️ \033[33m已关闭司令部 OTA 权限,中枢内核未来仅支持 SSH 升级。\033[0m"
else
ENABLE_MASTER_OTA="true"
echo -e "✅ \033[32m已开启司令部 OTA 权限,金蝉脱壳引信已挂载。\033[0m"
fi
fi
cat > "${MASTER_DIR}/master.conf" << EOF
cat > "${MASTER_DIR}/master.conf" << EOF
# IP-Sentinel Master 本地固化配置 (v${TARGET_VERSION})
MASTER_VERSION="$TARGET_VERSION"
TG_TOKEN="$TG_TOKEN"
DB_FILE="$DB_FILE"
MASTER_DIR="$MASTER_DIR"
# [v3.6.0 核心] 官方网关 UI 熔断标识
IS_OFFICIAL_GATEWAY="$IS_OFFICIAL_GATEWAY"
# [v3.6.1 新增] 司令部自身 OTA 授权标识
ENABLE_MASTER_OTA="$ENABLE_MASTER_OTA"
EOF
fi
# 3. 初始化 SQLite 数据库
# [v3.6.1 热修复] 老司令部平滑升级时,自动补齐缺失字段
if [ "$UPGRADE_MODE" == "true" ]; then
if ! grep -q "^IS_OFFICIAL_GATEWAY=" "${MASTER_DIR}/master.conf"; then
echo "IS_OFFICIAL_GATEWAY=\"false\"" >> "${MASTER_DIR}/master.conf"
fi
if ! grep -q "^ENABLE_MASTER_OTA=" "${MASTER_DIR}/master.conf"; then
echo "ENABLE_MASTER_OTA=\"false\"" >> "${MASTER_DIR}/master.conf"
fi
fi
# 🛑 拦截块结束
# 3. 初始化 SQLite 数据库 (幂等操作,升级模式下由 tg_master.sh 负责热修补)
echo -e "\n[3/4] 正在初始化 SQLite 数据库表结构..."
sqlite3 "$DB_FILE" <<EOF
CREATE TABLE IF NOT EXISTS nodes (
@@ -42,26 +261,113 @@ CREATE TABLE IF NOT EXISTS nodes (
agent_ip TEXT,
agent_port TEXT,
last_seen DATETIME DEFAULT CURRENT_TIMESTAMP,
region TEXT DEFAULT 'UNKNOWN',
node_alias TEXT,
enable_google TEXT DEFAULT 'true',
enable_trust TEXT DEFAULT 'true',
enable_ota TEXT DEFAULT 'false',
PRIMARY KEY(chat_id, node_name)
);
-- [v4.0.0 新增, v4.0.2 扩容] 核心情报表:记录历史 IP 质量数据,用于绘制趋势图
CREATE TABLE IF NOT EXISTS ip_trend_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
node_name TEXT,
check_time DATETIME DEFAULT CURRENT_TIMESTAMP,
scam_score INTEGER,
goog_status TEXT,
nf_status TEXT,
gpt_status TEXT
);
EOF
echo "✅ 数据库创建成功: $DB_FILE"
# ================== [v3.0.3 变更: 敏感文件权限收敛] ==================
chmod 600 "${MASTER_DIR}/master.conf"
chmod 600 "$DB_FILE"
# ====================================================================
# 4. 拉取核心调度代码并运行
echo -e "\n[4/4] 部署 TG 调度守护进程..."
curl -sL "https://git.94211762.xyz/hotyue/IP-Sentinel/raw/branch/main/master/tg_master.sh" -o "${MASTER_DIR}/tg_master.sh"
# [修改] 剥离了写死的网址,改用顶部的 ${REPO_RAW_URL} 变量,确保与卸载脚本的数据源同源
curl -sL "${REPO_RAW_URL}/master/tg_master.sh" -o "${MASTER_DIR}/tg_master.sh"
chmod +x "${MASTER_DIR}/tg_master.sh"
# 写入看门狗 Cron
crontab -l 2>/dev/null | grep -v "tg_master.sh" > /tmp/cron_master
echo "* * * * * pgrep -f tg_master.sh >/dev/null || nohup bash ${MASTER_DIR}/tg_master.sh >/dev/null 2>&1 &" >> /tmp/cron_master
crontab /tmp/cron_master
rm -f /tmp/cron_master
if command -v systemctl >/dev/null 2>&1; then
echo "💡 检测到 Systemd 环境,正在部署原生守护服务..."
cat > /etc/systemd/system/ip-sentinel-master.service << EOF
[Unit]
Description=IP-Sentinel Master Command Center Service
After=network.target
# 立刻启动
pgrep -f tg_master.sh >/dev/null || nohup bash "${MASTER_DIR}/tg_master.sh" >/dev/null 2>&1 &
[Service]
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SyslogIdentifier=ip-sentinel
Type=simple
ExecStart=/bin/bash ${MASTER_DIR}/tg_master.sh
Restart=always
RestartSec=5
User=root
WorkingDirectory=${MASTER_DIR}
CPUSchedulingPolicy=idle
IOSchedulingClass=idle
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now ip-sentinel-master.service
systemctl restart ip-sentinel-master.service
# 清理可能残留的历史 Cron
crontab -l 2>/dev/null | grep -v "tg_master.sh" > /tmp/cron_master || true
[ -f /tmp/cron_master ] && crontab /tmp/cron_master 2>/dev/null
rm -f /tmp/cron_master
else
echo "💡 未检测到 Systemd回退到 Cron 看门狗调度模式..."
crontab -l 2>/dev/null | grep -v "tg_master.sh" > /tmp/cron_master || true
echo "* * * * * pgrep -f tg_master.sh >/dev/null || nohup bash ${MASTER_DIR}/tg_master.sh >/dev/null 2>&1 &" >> /tmp/cron_master
[ -f /tmp/cron_master ] && crontab /tmp/cron_master 2>/dev/null
rm -f /tmp/cron_master
pgrep -f tg_master.sh >/dev/null || { nohup bash "${MASTER_DIR}/tg_master.sh" >/dev/null 2>&1 & disown 2>/dev/null; }
fi
# ================== [v3.2.2 优化 & v3.6.1 OTA捷报: 战报文案分流] ==================
echo "========================================================"
echo "🎉 Master 控制中枢部署完成!"
echo "🤖 机器人现已开始全局接客,等待边缘节点注册。"
echo "========================================================"
if [ "$UPGRADE_MODE" == "true" ]; then
echo "🎉 Master 控制中枢平滑热更新完成!"
echo "🤖 新版中枢引擎已接管数据库,继续等待边缘节点汇报。"
# [v3.6.1 核心] 静默 OTA 完成后,由幽灵进程主动向指挥官发送捷报
if [ "$SILENT_MASTER_OTA" == "true" ] && [ -n "$OTA_CHAT_ID" ] && [ -n "$TG_TOKEN" ]; then
echo -e "\n📡 正在向指挥官发送司令部重构捷报..."
curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
-d "chat_id=${OTA_CHAT_ID}" \
-d "parse_mode=Markdown" \
-d "text=✨ *司令部中枢热重载完成!*
🚀 当前内核已跃升至:\`v${TARGET_VERSION}\`
🤖 新版金蝉脱壳引擎已接管阵地,全舰队指控链路恢复正常。" > /dev/null
fi
else
echo "🎉 Master 控制中枢部署完成!"
echo "🤖 机器人现已开始全局接客,等待边缘节点注册。"
fi
echo "========================================================"
# =================================================================
# ================== [v3.1.2 新增: 玻璃房透明装机统计] ==================
# [修复] 仅在全新部署时触发统计,司令部热重载时绝对不触发
if [ "$UPGRADE_MODE" == "false" ]; then
echo -e "\n📡 正在向开源社区汇报装机量 (完全匿名不收集IP)..."
MASTER_COUNT=$(curl -s -m 3 "https://ip-sentinel-count.samanthaestime296.workers.dev/ping/master" || echo "")
if [ -n "$MASTER_COUNT" ] && [[ "$MASTER_COUNT" =~ ^[0-9]+$ ]]; then
echo -e "\033[32m✅ 感谢您成为全球第 ${MASTER_COUNT} 名 IP-Sentinel 指挥官!\033[0m"
else
echo -e "\033[32m✅ 感谢您建立 IP-Sentinel 司令部!\033[0m"
fi
echo -e "\n"
fi

819
master/tg_master.sh Normal file → Executable file
View File

@@ -1,38 +1,124 @@
#!/bin/bash
# ==========================================================
# 脚本名称: tg_master.sh (Master 端调度枢纽 V1.2)
# 核心功能: 监听 TG、操作 SQLite、Webhook 调度、僵尸节点清理
# 脚本名称: tg_master.sh (Master 端调度枢纽 - 动态锚点版)
# 核心功能: 监听 TG、操作 SQLite、Webhook 精准调度、403权限拦截、僵尸节点清理
# ==========================================================
CONF="/opt/ip_sentinel_master/master.conf"
[ ! -f "$CONF" ] && exit 1
source "$CONF"
OFFSET_FILE="/tmp/tg_master_offset"
# [核心: 运行态版本继承与云通信地址]
REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/main"
# MASTER_VERSION 已经在上方的 source "$CONF" 中被载入
# 如果本地极度陈旧没有该变量,才给定一个基础兜底值,避免变量为空导致崩溃
MASTER_VERSION=${MASTER_VERSION:-"3.5.0"}
OFFSET_FILE="${MASTER_DIR}/.tg_offset"
[[ -f $OFFSET_FILE ]] || echo "0" > $OFFSET_FILE
# --- 工具函数 ---
# ================== [v4.0.3 核心: 全球全能旗帜渲染引擎] ==================
get_flag() {
local region=$(echo "$1" | tr 'a-z' 'A-Z')
local base_cc="${region%%-*}" # 提取横杠前的主国家代码 (例如 US-TX 提取为 US)
local flag="🌐"
case "$base_cc" in
US) flag="🇺🇸" ;; JP) flag="🇯🇵" ;; HK) flag="🇭🇰" ;; TW) flag="🇹🇼" ;; SG) flag="🇸🇬" ;;
UK|GB) flag="🇬🇧" ;; DE) flag="🇩🇪" ;; FR) flag="🇫🇷" ;; NL) flag="🇳🇱" ;; CA) flag="🇨🇦" ;;
AU) flag="🇦🇺" ;; KR) flag="🇰🇷" ;; IN) flag="🇮🇳" ;; BR) flag="🇧🇷" ;; RU) flag="🇷🇺" ;;
CH) flag="🇨🇭" ;; SE) flag="🇸🇪" ;; NO) flag="🇳🇴" ;; DK) flag="🇩🇰" ;; FI) flag="🇫🇮" ;;
IT) flag="🇮🇹" ;; ES) flag="🇪🇸" ;; PT) flag="🇵🇹" ;; IE) flag="🇮🇪" ;; PL) flag="🇵🇱" ;;
AT) flag="🇦🇹" ;; BE) flag="🇧🇪" ;; TR) flag="🇹🇷" ;; ZA) flag="🇿🇦" ;; AE) flag="🇦🇪" ;;
MY) flag="🇲🇾" ;; ID) flag="🇮🇩" ;; VN) flag="🇻🇳" ;; TH) flag="🇹🇭" ;; PH) flag="🇵🇭" ;;
NZ) flag="🇳🇿" ;; AR) flag="🇦🇷" ;; CL) flag="🇨🇱" ;; MX) flag="🇲🇽" ;; IL) flag="🇮🇱" ;;
SA) flag="🇸🇦" ;; EG) flag="🇪🇬" ;; NG) flag="🇳🇬" ;; KE) flag="🇰🇪" ;; RO) flag="🇷🇴" ;;
BG) flag="🇧🇬" ;; CZ) flag="🇨🇿" ;; HU) flag="🇭🇺" ;; GR) flag="🇬🇷" ;; UA) flag="🇺🇦" ;;
esac
echo "$flag"
}
send_ui() {
curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
curl -s --connect-timeout 5 -m 10 -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d "{\"chat_id\":\"$1\",\"text\":\"$2\",\"parse_mode\":\"Markdown\",\"reply_markup\":{\"inline_keyboard\":$3}}" > /dev/null
}
send_msg() {
curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
curl -s --connect-timeout 5 -m 10 -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
-d "chat_id=$1" -d "text=$2" -d "parse_mode=Markdown" > /dev/null
}
# 数据库执行函数
db_exec() {
sqlite3 "$DB_FILE" "$1"
# ================== [v3.0.1 新增: 消息原位刷新函数] ==================
edit_msg() {
curl -s --connect-timeout 5 -m 10 -X POST "https://api.telegram.org/bot${TG_TOKEN}/editMessageText" \
-d "chat_id=$1" -d "message_id=$2" -d "text=$3" -d "parse_mode=Markdown" > /dev/null
}
# [v3.5.3 新增: 支持内联键盘的原位 UI 重绘函数]
edit_ui() {
curl -s --connect-timeout 5 -m 10 -X POST "https://api.telegram.org/bot${TG_TOKEN}/editMessageText" \
-H "Content-Type: application/json" \
-d "{\"chat_id\":\"$1\",\"message_id\":\"$2\",\"text\":\"$3\",\"parse_mode\":\"Markdown\",\"reply_markup\":{\"inline_keyboard\":$4}}" > /dev/null
}
# 数据库执行函数 (v3.6.3 终极静默版: 动用 .timeout 点命令防泄露)
db_exec() {
printf ".timeout 5000\n%s\n" "$1" | sqlite3 "$DB_FILE"
}
# ================== [v3.0.4 核心: 动态 HMAC 签名生成器] ==================
# 用法: generate_signed_url <IP> <PORT> <PATH>
generate_signed_url() {
local target_ip=$1
local target_port=$2
local action_path=$3
local current_t=$(date +%s)
# 构建加密载荷: "路径:时间戳"
local payload="${action_path}:${current_t}"
# 使用 CHAT_ID 作为密钥,生成 SHA256 HMAC 签名
local signature=$(echo -n "$payload" | openssl dgst -sha256 -hmac "$CHAT_ID" | awk '{print $NF}')
# 返回最终带签名的 URL
echo "https://${target_ip}:${target_port}${action_path}?t=${current_t}&sign=${signature}"
}
# ========================================================================
# ================== [v3.6.3 核心: 激活 SQLite 高并发 WAL 引擎] ==================
db_exec "PRAGMA journal_mode=WAL;" > /dev/null 2>&1
db_exec "PRAGMA synchronous=NORMAL;" > /dev/null 2>&1
# ==============================================================================
# ================== [v3.1.3-v3.6.0 核心: 数据库结构无损热升级] ==================
# 自动探测并增加缺失字段,屏蔽已存在的报错,保护老节点数据
db_exec "ALTER TABLE nodes ADD COLUMN region TEXT DEFAULT 'UNKNOWN';" 2>/dev/null
db_exec "ALTER TABLE nodes ADD COLUMN node_alias TEXT;" 2>/dev/null
db_exec "ALTER TABLE nodes ADD COLUMN enable_google TEXT DEFAULT 'true';" 2>/dev/null
db_exec "ALTER TABLE nodes ADD COLUMN enable_trust TEXT DEFAULT 'true';" 2>/dev/null
db_exec "ALTER TABLE nodes ADD COLUMN enable_ota TEXT DEFAULT 'false';" 2>/dev/null
# ========================================================================
# ================== [v4.0.0/v4.0.2 核心: 增加 IP 质量趋势追踪表] ==================
db_exec "CREATE TABLE IF NOT EXISTS ip_trend_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
node_name TEXT,
check_time DATETIME DEFAULT CURRENT_TIMESTAMP,
scam_score INTEGER,
nf_status TEXT
);" 2>/dev/null
# [v4.0.2 热更新] 动态扩容 谷歌 与 ChatGPT 状态追踪字段
db_exec "ALTER TABLE ip_trend_log ADD COLUMN goog_status TEXT DEFAULT 'Unknown';" 2>/dev/null
db_exec "ALTER TABLE ip_trend_log ADD COLUMN gpt_status TEXT DEFAULT 'Unknown';" 2>/dev/null
# ========================================================================
# --- 核心轮询循环 ---
while true; do
OFFSET=$(cat $OFFSET_FILE)
UPDATES=$(curl -s "https://api.telegram.org/bot${TG_TOKEN}/getUpdates?offset=${OFFSET}&timeout=30")
UPDATES=$(curl -s --connect-timeout 5 -m 35 "https://api.telegram.org/bot${TG_TOKEN}/getUpdates?offset=${OFFSET}&timeout=30")
COUNT=$(echo "$UPDATES" | jq -r '.result | length' 2>/dev/null)
@@ -44,98 +130,713 @@ while true; do
CHAT_ID=$(echo "$UPDATE" | jq -r '.message.chat.id // .callback_query.message.chat.id')
TEXT=$(echo "$UPDATE" | jq -r '.message.text // .callback_query.data')
# ================== [v4.0.2 核心: 态势感知按钮一键入库] ==================
if [[ "$TEXT" == "svq|"* ]]; then
# 格式: svq|NODE_NAME|SCORE|GOOG|NF|GPT
IFS='|' read -r MAGIC NODE_ID SCORE GOOG_ST NF_ST GPT_ST <<< "$TEXT"
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
if [ -n "$NODE_ID" ] && [ -n "$SCORE" ]; then
# 1. 写入 SQLite
db_exec "INSERT INTO ip_trend_log (node_name, scam_score, goog_status, nf_status, gpt_status) VALUES ('$NODE_ID', '$SCORE', '$GOOG_ST', '$NF_ST', '$GPT_ST');"
# 2. 无损修改原消息:移除入库按钮,展示绿勾状态 (不破坏 Markdown 战报原文)
if [ -n "$MSG_ID" ]; then
curl -s --connect-timeout 5 -m 10 -X POST "https://api.telegram.org/bot${TG_TOKEN}/editMessageReplyMarkup" \
-H "Content-Type: application/json" \
-d "{\"chat_id\":\"${CHAT_ID}\",\"message_id\":\"${MSG_ID}\",\"reply_markup\":{\"inline_keyboard\":[[{\"text\":\"✅ 此报告已存档\",\"callback_data\":\"ignore\"}]]}}" > /dev/null
fi
fi
continue
fi
# ======================================================================
REPLY_TO_TEXT=$(echo "$UPDATE" | jq -r '.message.reply_to_message.text // empty')
# ================== [v3.5.2 新增: 拦截别名修改的对话回复] ==================
if [[ "$REPLY_TO_TEXT" == *"✏️ 请回复本消息以重命名节点:"* ]]; then
# 精准提取被回复消息中的节点主键名
TARGET_NODE=$(echo "$REPLY_TO_TEXT" | grep -v "✏️" | grep -v "仅限" | tr -d '\` ' | tr -cd 'a-zA-Z0-9_.-' | head -n 1)
# [v3.5.2 热修复] 废除 Bash 原生 tr 命令的中文白名单 (不支持 Unicode 会误删中文)。
# 改用黑名单策略:仅自动转化下划线,剔除引号、特殊符号和冒号(防止破坏内部路由)
# 将完整的中文原样送入 Base64 编码,最终严格正则清洗交由 Agent 的 Python 引擎处理!
NEW_ALIAS=$(echo "$TEXT" | sed 's/_/-/g' | tr -d '"'\''\`\$\|&;<>\n\r:' | cut -c 1-30)
if [ -n "$TARGET_NODE" ] && [ -n "$NEW_ALIAS" ]; then
# 强行重写内部路由
TEXT="do_rename:${TARGET_NODE}:${NEW_ALIAS}"
fi
fi
# ================== [v3.0.1 新增: 消除转圈圈与获取消息ID] ==================
CB_ID=$(echo "$UPDATE" | jq -r '.callback_query.id // empty')
MSG_ID=$(echo "$UPDATE" | jq -r '.callback_query.message.message_id // empty')
# 告诉 TG 官方“指令已收到”,立刻消除按钮上的加载圈圈
if [ -n "$CB_ID" ]; then
curl -s --connect-timeout 5 -m 10 -X POST "https://api.telegram.org/bot${TG_TOKEN}/answerCallbackQuery" -d "callback_query_id=${CB_ID}" > /dev/null
fi
# ==========================================
# 1. 节点注册通道 (处理 Agent 发来的注册暗号)
# 格式: #REGISTER#|<NodeName>|<IP>|<Port>
# 1. 节点注册通道 (V3.1.3 大区拓扑升级版)
# ==========================================
if [[ "$TEXT" == *"#REGISTER#"* ]]; then
# 提取包含暗号的那一行,并剔除可能误复制的反引号和空格
REG_LINE=$(echo "$TEXT" | grep "#REGISTER#" | head -n 1 | tr -d '\` ')
IFS='|' read -r MAGIC NODE_NAME AGENT_IP AGENT_PORT <<< "$REG_LINE"
# UPSERT 逻辑
db_exec "INSERT INTO nodes (chat_id, node_name, agent_ip, agent_port, last_seen) VALUES ('$CHAT_ID', '$NODE_NAME', '$AGENT_IP', '$AGENT_PORT', CURRENT_TIMESTAMP) ON CONFLICT(chat_id, node_name) DO UPDATE SET agent_ip='$AGENT_IP', agent_port='$AGENT_PORT', last_seen=CURRENT_TIMESTAMP;"
send_msg "$CHAT_ID" "✅ 司令部已确认!节点接入成功: \`$NODE_NAME\` ($AGENT_IP:$AGENT_PORT)"
# V3.6.0 兼容性拆包: 支持 7字段(OTA)、6字段(双轨)、5字段(单轨)、4字段(远古)
FIELD_COUNT=$(echo "$REG_LINE" | awk -F'|' '{print NF}')
if [ "$FIELD_COUNT" -ge 7 ]; then
IFS='|' read -r MAGIC RAW_REGION RAW_NODE RAW_IP RAW_PORT RAW_ALIAS RAW_OTA <<< "$REG_LINE"
elif [ "$FIELD_COUNT" -eq 6 ]; then
IFS='|' read -r MAGIC RAW_REGION RAW_NODE RAW_IP RAW_PORT RAW_ALIAS <<< "$REG_LINE"
RAW_OTA="false"
elif [ "$FIELD_COUNT" -eq 5 ]; then
IFS='|' read -r MAGIC RAW_REGION RAW_NODE RAW_IP RAW_PORT <<< "$REG_LINE"
RAW_ALIAS="$RAW_NODE"
RAW_OTA="false"
else
IFS='|' read -r MAGIC RAW_NODE RAW_IP RAW_PORT <<< "$REG_LINE"
RAW_REGION="UNKNOWN"
RAW_ALIAS="$RAW_NODE"
RAW_OTA="false"
fi
# 🛡️ 强制字符白名单过滤:保留历史特征不变
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
AGENT_REGION=$(echo "$RAW_REGION" | tr -cd 'a-zA-Z0-9' | cut -c 1-10)
NODE_NAME=$(echo "$RAW_NODE" | tr -cd 'a-zA-Z0-9_.-' | cut -c 1-30)
AGENT_IP=$(echo "$RAW_IP" | tr -cd 'a-zA-Z0-9.:\[\]-' | cut -c 1-50)
AGENT_PORT=$(echo "$RAW_PORT" | tr -cd '0-9' | cut -c 1-5)
NODE_ALIAS=$(echo "$RAW_ALIAS" | tr -d '"'\''\`\$\|&;<>\n\r' | cut -c 1-30)
[ -z "$NODE_ALIAS" ] && NODE_ALIAS="$NODE_NAME"
AGENT_OTA=$(echo "$RAW_OTA" | tr -cd 'a-z')
[ -z "$AGENT_OTA" ] && AGENT_OTA="false"
if [[ "$AGENT_IP" =~ ^127\.|^10\.|^192\.168\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^::1$|^localhost$ ]]; then
send_msg "$CHAT_ID" "⛔ **安全拦截**:禁止注册内网或回环 IP防止 SSRF 攻击渗透。"
continue
fi
if [ -z "$NODE_NAME" ] || [ -z "$AGENT_IP" ] || [ -z "$AGENT_PORT" ] || [ -z "$CHAT_ID" ]; then
send_msg "$CHAT_ID" "⛔ **安全拦截**:检测到非法注册载荷,请求已拒绝。"
continue
fi
# [核心] 入库时追加 node_alias 与 enable_ota 字段
db_exec "INSERT INTO nodes (chat_id, node_name, agent_ip, agent_port, last_seen, region, node_alias, enable_ota) VALUES ('$CHAT_ID', '$NODE_NAME', '$AGENT_IP', '$AGENT_PORT', CURRENT_TIMESTAMP, '$AGENT_REGION', '$NODE_ALIAS', '$AGENT_OTA') ON CONFLICT(chat_id, node_name) DO UPDATE SET agent_ip='$AGENT_IP', agent_port='$AGENT_PORT', last_seen=CURRENT_TIMESTAMP, region='$AGENT_REGION', node_alias='$NODE_ALIAS', enable_ota='$AGENT_OTA';"
send_msg "$CHAT_ID" "✅ **司令部确认 (v${MASTER_VERSION})**%0A节点 \`${NODE_ALIAS}\` 档案已录入!"
# ================== [v3.1.3 丝滑连招: 直接呼出全球大区雷达] ==================
REGION_DATA=$(db_exec "SELECT region, COUNT(*) FROM nodes WHERE chat_id='$CHAT_ID' GROUP BY region;")
if [ -n "$REGION_DATA" ]; then
BTNS="["
while IFS='|' read -r REGION_NAME NODE_COUNT; do
[ -z "$REGION_NAME" ] && REGION_NAME="UNKNOWN"
FLAG=$(get_flag "$REGION_NAME")
BTNS="$BTNS[{\"text\":\"$FLAG $REGION_NAME ($NODE_COUNT 台)\",\"callback_data\":\"region:$REGION_NAME\"}],"
done <<< "$REGION_DATA"
BTNS="${BTNS%,}]"
send_ui "$CHAT_ID" "🌍 **全视界战略雷达**\n请选择要检阅的战区" "$BTNS"
fi
# ========================================================================
continue
fi
# ==========================================
# 2. 交互菜单与下发通道 (主控逻辑)
# 2. 交互菜单与下发通道
# ==========================================
case "$TEXT" in
"/start"|"/menu")
BTNS="[[{\"text\":\"🖥️ 我的节点列表\",\"callback_data\":\"list_nodes\"}], [{\"text\":\"🚀 全节点一键维护\",\"callback_data\":\"all_run\"}]]"
send_ui "$CHAT_ID" "🛡️ **IP-Sentinel 司令部**\n欢迎回来长官。请下达指令" "$BTNS"
# [核心: 抓取云端最新 Master 版本 (KV 解析法)]
REMOTE_VER=$(curl -s -m 2 "${REPO_RAW_URL}/version.txt" | grep "^MASTER_VERSION=" | cut -d'=' -f2 | tr -d '[:space:]')
VER_INFO="当前版本: \`v${MASTER_VERSION}\`"
BTN_MASTER_OTA=""
if [ -n "$REMOTE_VER" ] && [ "$REMOTE_VER" != "$MASTER_VERSION" ]; then
VER_INFO="${VER_INFO}\n✨ **发现新版本**: \`v${REMOTE_VER}\` (可执行中枢热重载)"
# 仅当非官方网关 且 开启了中枢 OTA 权限时,才渲染升级按钮
if [ "$IS_OFFICIAL_GATEWAY" != "true" ] && [ "${ENABLE_MASTER_OTA:-false}" == "true" ]; then
BTN_MASTER_OTA="[{\"text\":\"🆙 升级司令部至 v${REMOTE_VER}\",\"callback_data\":\"master_ota_confirm\"}],"
fi
fi
NODE_COUNT=$(db_exec "SELECT COUNT(*) FROM nodes WHERE chat_id='$CHAT_ID';")
[ -z "$NODE_COUNT" ] && NODE_COUNT=0
# L0 扁平化重构:将司令部升级按钮动态置于最顶层
if [ "$IS_OFFICIAL_GATEWAY" != "true" ]; then
BTNS="[${BTN_MASTER_OTA}[{\"text\":\"🌍 进入全球战区雷达 (管理节点)\",\"callback_data\":\"list_nodes\"}], [{\"text\":\"🚀 全军总攻\",\"callback_data\":\"all_run\"}, {\"text\":\"📊 全军简报\",\"callback_data\":\"all_reports\"}], [{\"text\":\"☢️ 全舰队 OTA 热重载\",\"callback_data\":\"all_ota_confirm\"}]]"
else
BTNS="[[{\"text\":\"🌍 进入全球战区雷达 (管理节点)\",\"callback_data\":\"list_nodes\"}], [{\"text\":\"🚀 全军总攻\",\"callback_data\":\"all_run\"}, {\"text\":\"📊 全军简报\",\"callback_data\":\"all_reports\"}]]"
fi
TEXT_MSG="🛡️ **IP-Sentinel 司令部**\n${VER_INFO}\n\n📊 舰队状态: 共有 \`${NODE_COUNT}\` 台哨兵在线\n欢迎回来长官。请下达战略指令"
send_ui "$CHAT_ID" "$TEXT_MSG" "$BTNS"
;;
"all_ota_confirm")
CONFIRM_BTNS="[[{\"text\":\"🚨 我已了解风险,下发核按钮指令!\",\"callback_data\":\"all_ota_execute\"}], [{\"text\":\"取消操作\",\"callback_data\":\"/start\"}]]"
WARNING_MSG="☢️ **【最高指令:全舰队 OTA 升级】**\n\n此操作将向您名下**所有开启 OTA 权限的节点**下发重组指令,强制从云端拉取最新代码并进行热重载。\n\n⚠ **核按钮风险提示**\n1. 升级过程中守护进程会短暂重启,节点可能出现临时离线。\n2. 若遇 GitHub 源屏蔽或网络极度恶劣,少数节点可能需要手动干预。\n\n**是否确定挂载并执行 OTA 指令?**"
send_ui "$CHAT_ID" "$WARNING_MSG" "$CONFIRM_BTNS"
;;
"all_ota_execute")
NODE_DATA=$(db_exec "SELECT node_name, agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID' AND enable_ota='true';")
if [ -z "$NODE_DATA" ]; then
send_msg "$CHAT_ID" "⚠️ 您名下暂无开启 OTA 权限的在线节点。"
else
send_msg "$CHAT_ID" "📢 **司令部指令下达:正在唤醒全舰队执行 OTA 升级...**%0A*(节点升级成功后会主动发回新的入库确认,请注意查收)*"
echo "$NODE_DATA" | while IFS='|' read -r NNAME AIP APORT; do
TARGET_URL=$(generate_signed_url "$AIP" "$APORT" "/trigger_ota")
# [灾难救援通道] 仅针对 OTA 允许一次明文回退,抢救缺失证书的老节点
{ curl -k -s -m 5 "$TARGET_URL" || curl -s -m 5 "${TARGET_URL/https:\/\//http:\/\/}"; } > /dev/null &
sleep 0.3 # 严格流量削峰
done
fi
;;
"master_ota_confirm")
CONFIRM_BTNS="[[{\"text\":\"🚨 确认重构司令部\",\"callback_data\":\"master_ota_execute\"}], [{\"text\":\"取消操作\",\"callback_data\":\"/start\"}]]"
WARNING_MSG="☢️ **【最高指令:中枢金蝉脱壳】**\n\n此操作将拉取最新源码并强行覆盖司令部核心进程。\n\n⚠ **风险提示**\n升级期间司令部将短暂失联约3-5秒。完成后会自动发送捷报。\n\n**是否确定执行司令部自我升级?**"
if [ -n "$MSG_ID" ]; then
edit_ui "$CHAT_ID" "$MSG_ID" "$WARNING_MSG" "$CONFIRM_BTNS"
else
send_ui "$CHAT_ID" "$WARNING_MSG" "$CONFIRM_BTNS"
fi
;;
"master_ota_execute")
if [ -n "$MSG_ID" ]; then
edit_msg "$CHAT_ID" "$MSG_ID" "⏳ 正在下载重构图纸,司令部即将进入静默重启..."
else
send_msg "$CHAT_ID" "⏳ 正在下载重构图纸,司令部即将进入静默重启..."
fi
# 下载最新的 master install 脚本作为幽灵进程
curl -fsSL "${REPO_RAW_URL}/master/install_master.sh" -o "/tmp/install_master.sh"
# [v3.6.3 修复] 🚀 OTA 防砖机制:严格校验脚本完整性
if ! bash -n "/tmp/install_master.sh" >/dev/null 2>&1; then
if [ -n "$MSG_ID" ]; then
edit_msg "$CHAT_ID" "$MSG_ID" "❌ OTA 传输受损:脚本下载不完整,已触发防砖熔断,升级取消!"
else
send_msg "$CHAT_ID" "❌ OTA 传输受损:脚本下载不完整,已触发防砖熔断,升级取消!"
fi
continue
fi
chmod +x "/tmp/install_master.sh"
# 抛出幽灵进程进行脱壳升级,传递静默变量与回执 ID
# [修复] 必须显式将环境变量注入到 bash -c 的指令串中,防止被 systemd-run 沙盒隔离丢弃
if command -v systemd-run >/dev/null 2>&1; then
systemd-run --quiet --no-block /bin/bash -c "export SILENT_MASTER_OTA='true'; export OTA_CHAT_ID='$CHAT_ID'; bash /tmp/install_master.sh"
else
export SILENT_MASTER_OTA="true"
export OTA_CHAT_ID="$CHAT_ID"
nohup bash /tmp/install_master.sh >/dev/null 2>&1 & disown
fi
# 当前旧进程休眠并等待被幽灵进程处决
sleep 10
;;
"all_reports")
NODE_DATA=$(db_exec "SELECT node_name, agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID';")
if [ -z "$NODE_DATA" ]; then
send_msg "$CHAT_ID" "⚠️ 您名下暂无在线节点。"
else
# [文案优化] 提前告知指挥官需要排队等待
send_msg "$CHAT_ID" "📢 **司令部指令下达:正在召唤所有哨兵回传简报...**%0A*(为防止触发 TG 官方限流,简报将排队依次送达,请耐心等待)*"
echo "$NODE_DATA" | while IFS='|' read -r NNAME AIP APORT; do
TARGET_URL=$(generate_signed_url "$AIP" "$APORT" "/trigger_report")
curl -k -s -m 5 "$TARGET_URL" > /dev/null &
# [致命修复] 强行休眠 2 秒!错开 TG 官方 1条/秒 的发信红线
sleep 2
done
fi
;;
# ================== [补充缺失的全节点一键维护功能] ==================
"all_run")
NODE_DATA=$(db_exec "SELECT node_name, agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID';")
if [ -z "$NODE_DATA" ]; then
send_msg "$CHAT_ID" "⚠️ 您名下暂无在线节点。"
else
send_msg "$CHAT_ID" "📢 **司令部指令下达:正在唤醒所有哨兵执行系统维护...**"
echo "$NODE_DATA" | while IFS='|' read -r NNAME AIP APORT; do
TARGET_URL=$(generate_signed_url "$AIP" "$APORT" "/trigger_run")
curl -k -s -m 5 "$TARGET_URL" > /dev/null &
sleep 0.2 # [新增] 流量削峰:防止瞬间 fork 导致句柄耗尽
done
fi
;;
# ====================================================================
# ------------------- 🚨 请将下面这段代码插入在这里 -------------------
# ================== [v4.0.0 新增: 文本指令直接控制通道] ==================
"/quality"|"/quality@"*)
TARGET_NODE=$(echo "$TEXT" | awk '{print $2}')
if [ -z "$TARGET_NODE" ]; then
send_msg "$CHAT_ID" "⚠️ 请指定目标节点。例如: \`/quality HK-1\`%0A或通过雷达面板进行选择操作。"
else
TARGET_NODE=$(echo "$TARGET_NODE" | tr -cd 'a-zA-Z0-9_.-')
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
# [加密通讯逻辑]
AGENT_INFO=$(db_exec "SELECT agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
AGENT_IP=$(echo "$AGENT_INFO" | cut -d'|' -f1)
AGENT_PORT=$(echo "$AGENT_INFO" | cut -d'|' -f2)
if [ -n "$AGENT_IP" ] && [ -n "$AGENT_PORT" ]; then
send_msg "$CHAT_ID" "⏳ 正在向 \`$TARGET_NODE\` ($AGENT_IP) 下发 [quality] 指令,请稍候..."
# 动态 HMAC 签名防篡改
TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_quality")
RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED")
if [ "$RESPONSE" == "FAILED" ] || [ -z "$RESPONSE" ]; then
TARGET_URL_HTTP="${TARGET_URL/https:\/\//http:\/\/}"
RESPONSE=$(curl -s -m 5 "$TARGET_URL_HTTP" || echo "FAILED")
fi
# 结果判定
if [ "$RESPONSE" == "FAILED" ]; then
send_msg "$CHAT_ID" "❌ 指令下发超时或失败!请检查节点公网 IP 或防火墙端口 ($AGENT_PORT) 是否放行。"
elif [[ "$RESPONSE" == *"403"* ]]; then
send_msg "$CHAT_ID" "⚠️ **拒绝执行**:该节点未在本地开启此模块,请检查安装时的配置!"
else
send_msg "$CHAT_ID" "✅ 节点 \`$TARGET_NODE\` 回应: 🔍 深海声呐已投放!请等待异步战报回传。"
fi
else
send_msg "$CHAT_ID" "❌ 数据库中未找到该节点的通讯地址。"
fi
fi
;;
"/trend"|"/trend@"*)
TARGET_NODE=$(echo "$TEXT" | awk '{print $2}')
if [ -z "$TARGET_NODE" ]; then
send_msg "$CHAT_ID" "⚠️ 请指定目标节点。例如: \`/trend HK-1\`%0A或通过雷达面板进行选择操作。"
else
TARGET_NODE=$(echo "$TARGET_NODE" | tr -cd 'a-zA-Z0-9_.-')
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
TREND_DATA=$(db_exec "SELECT datetime(check_time, 'localtime'), scam_score, goog_status, nf_status, gpt_status FROM ip_trend_log WHERE node_name='$TARGET_NODE' ORDER BY check_time DESC LIMIT 15;")
if [ -z "$TREND_DATA" ]; then
send_msg "$CHAT_ID" "⚠️ 节点 \`$TARGET_NODE\` 暂无历史体检档案。请先执行 /quality 投放声呐进行探测。"
else
TARGET_ALIAS=$(db_exec "SELECT IFNULL(node_alias, node_name) FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
[ -z "$TARGET_ALIAS" ] && TARGET_ALIAS="$TARGET_NODE"
TEXT_RES="📈 *[${TARGET_ALIAS}] 历史态势感知 (近15次)*\n\n"
TEXT_RES+="时间(本地) | 风险 | 谷歌 | NF | GPT\n"
TEXT_RES+="-----------------------------------------\n"
while IFS='|' read -r c_time score goog nf gpt; do
[ -z "$score" ] && score="0"
[ -z "$goog" ] && goog="未知"
[ -z "$nf" ] && nf="未知"
[ -z "$gpt" ] && gpt="未知"
short_time=$(echo "$c_time" | cut -c 6-16)
if [ "$score" -le 20 ]; then SCORE_EMJ="🟢"
elif [ "$score" -le 60 ]; then SCORE_EMJ="🟡"
else SCORE_EMJ="🔴"
fi
TEXT_RES+="\`${short_time}\` | ${SCORE_EMJ}\`${score}\` | \`${goog}\` | \`${nf}\` | \`${gpt}\`\n"
done <<< "$TREND_DATA"
TEXT_RES+="\n_💡 提示:🔴风险分 >60 极易触发网页验证码拦截;谷歌显示 CN 即为高危送中。_"
# [v4.0.3 体验升级] 注入交互式控制台按钮
BTNS="[[{\"text\":\"⚙️ 调出该节点控制台\",\"callback_data\":\"manage:$TARGET_NODE\"}]]"
send_ui "$CHAT_ID" "$TEXT_RES" "$BTNS"
fi
fi
;;
# ------------------- 🚨 插入代码到此结束 -------------------
"list_nodes")
# 从 SQLite 查询属于该 CHAT_ID 的节点
NODE_LIST=$(db_exec "SELECT node_name FROM nodes WHERE chat_id='$CHAT_ID';")
if [ -z "$NODE_LIST" ]; then
# 【V3.1.3】一级菜单:大区聚合并列出数量
REGION_DATA=$(db_exec "SELECT region, COUNT(*) FROM nodes WHERE chat_id='$CHAT_ID' GROUP BY region;")
if [ -z "$REGION_DATA" ]; then
send_msg "$CHAT_ID" "⚠️ 您名下暂无在线节点,请先在边缘机执行部署。"
else
BTNS="["
for N in $NODE_LIST; do
BTNS="$BTNS[{\"text\":\"🖥️ $N\",\"callback_data\":\"manage:$N\"}],"
done
BTNS="${BTNS%,}]"
send_ui "$CHAT_ID" "🔍 您名下的活跃节点:" "$BTNS"
while IFS='|' read -r REGION_NAME NODE_COUNT; do
[ -z "$REGION_NAME" ] && REGION_NAME="UNKNOWN"
FLAG=$(get_flag "$REGION_NAME")
BTNS="$BTNS[{\"text\":\"$FLAG $REGION_NAME ($NODE_COUNT 台)\",\"callback_data\":\"region:$REGION_NAME\"}],"
done <<< "$REGION_DATA"
# L1 追加返回中枢逃生舱
BTNS="$BTNS[{\"text\":\"🏠 回到司令部\",\"callback_data\":\"/start\"}]]"
send_ui "$CHAT_ID" "🌍 **全视界战略雷达**\n已为您聚合当前舰队的部署大区请选择要检阅的战区" "$BTNS"
fi
;;
region:*)
# 【V3.1.3】二级菜单:目标大区下的节点双列排版
TARGET_REGION=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9')
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
# [v3.5.2] 提取物理主键和展示别名
NODE_LIST=$(db_exec "SELECT node_name, IFNULL(node_alias, node_name) FROM nodes WHERE chat_id='$CHAT_ID' AND region='$TARGET_REGION';")
if [ -z "$NODE_LIST" ]; then
send_msg "$CHAT_ID" "⚠️ 该战区下暂无可用节点。"
else
BTNS="["
COL=0
ROW_STR="["
while IFS='|' read -r N_NAME N_ALIAS; do
[ -z "$N_NAME" ] && continue
ROW_STR="$ROW_STR{\"text\":\"🖥️ $N_ALIAS\",\"callback_data\":\"manage:$N_NAME\"},"
COL=$((COL+1))
if [ $COL -eq 2 ]; then
ROW_STR="${ROW_STR%,}]"
BTNS="$BTNS$ROW_STR,"
COL=0
ROW_STR="["
fi
done <<< "$NODE_LIST"
# 如果是奇数,补齐最后的尾巴
if [ $COL -eq 1 ]; then
ROW_STR="${ROW_STR%,}]"
BTNS="$BTNS$ROW_STR,"
fi
# L2 追加双重逃生舱
BTNS="$BTNS[{\"text\":\"⬅️ 返回战区地图\",\"callback_data\":\"list_nodes\"}, {\"text\":\"🏠 回到司令部\",\"callback_data\":\"/start\"}]]"
send_ui "$CHAT_ID" "📍 **[$TARGET_REGION] 战区哨兵矩阵**\n请锁定要执行战术动作的具体目标" "$BTNS"
fi
;;
manage:*)
TARGET_NODE=${TEXT#*:}
# 【升级点 1】重构战术面板排版新增 [剔除失联节点] 按钮,采用 3 行优雅布局
BTNS="[[{\"text\":\"▶️ 执行深度伪装\",\"callback_data\":\"run:$TARGET_NODE\"}, {\"text\":\"📜 查看实时日志\",\"callback_data\":\"log:$TARGET_NODE\"}], [{\"text\":\"📊 索要统计战报\",\"callback_data\":\"report:$TARGET_NODE\"}, {\"text\":\"🗑️ 剔除失联节点\",\"callback_data\":\"del:$TARGET_NODE\"}], [{\"text\":\"⬅️ 返回主列表\",\"callback_data\":\"list_nodes\"}]]"
send_ui "$CHAT_ID" "⚙️ **目标锁定**: \`$TARGET_NODE\`\n请选择战术动作" "$BTNS"
;;
del:*)
# 【升级点 2】执行数据库硬删除并自动刷新节点列表
TARGET_NODE=${TEXT#*:}
db_exec "DELETE FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE';"
send_msg "$CHAT_ID" "🗑️ 节点 \`$TARGET_NODE\` 的档案已从司令部彻底销毁!"
TARGET_NODE=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9_.-')
TARGET_ALIAS=$(db_exec "SELECT IFNULL(node_alias, node_name) FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
[ -z "$TARGET_ALIAS" ] && TARGET_ALIAS="$TARGET_NODE"
# 删除后自动重新渲染节点列表展示
NODE_LIST=$(db_exec "SELECT node_name FROM nodes WHERE chat_id='$CHAT_ID';")
if [ -z "$NODE_LIST" ]; then
send_msg "$CHAT_ID" "⚠️ 当前司令部已无任何节点挂载。"
# 抓取节点全景元数据
TOGGLE_INFO=$(db_exec "SELECT enable_google, enable_trust, enable_ota, agent_ip, IFNULL(last_seen, '未知') FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
ST_GOOGLE=$(echo "$TOGGLE_INFO" | cut -d'|' -f1)
ST_TRUST=$(echo "$TOGGLE_INFO" | cut -d'|' -f2)
ST_OTA=$(echo "$TOGGLE_INFO" | cut -d'|' -f3)
A_IP=$(echo "$TOGGLE_INFO" | cut -d'|' -f4)
LAST_SEEN=$(echo "$TOGGLE_INFO" | cut -d'|' -f5)
# 动态渲染状态文字
[ "$ST_GOOGLE" == "true" ] && BTN_G="🟢 Google巡逻: 已开" && ACT_G="false" || { BTN_G="🔴 Google巡逻: 已停"; ACT_G="true"; }
[ "$ST_TRUST" == "true" ] && BTN_T="🟢 信用净化: 已开" && ACT_T="false" || { BTN_T="🔴 信用净化: 已停"; ACT_T="true"; }
# 模块一:即时战术动作 (V4.0.0 引入深海声呐与趋势面板)
BTN_ACTION="[{\"text\":\"📍 触发 Google 纠偏\",\"callback_data\":\"google:$TARGET_NODE\"}, {\"text\":\"🛡️ 触发信用净化\",\"callback_data\":\"trust:$TARGET_NODE\"}], [{\"text\":\"🔍 投放深海声呐 (查IP质量)\",\"callback_data\":\"quality:$TARGET_NODE\"}, {\"text\":\"📈 查看 IP 污染趋势图\",\"callback_data\":\"trend:$TARGET_NODE\"}], [{\"text\":\"📜 提取终端实时日志\",\"callback_data\":\"log:$TARGET_NODE\"}, {\"text\":\"📊 生成单机战报\",\"callback_data\":\"report:$TARGET_NODE\"}]"
# 模块二:养护状态启停
BTN_TOGGLE="[{\"text\":\"$BTN_G\",\"callback_data\":\"toggle:google:$TARGET_NODE:$ACT_G\"}, {\"text\":\"$BTN_T\",\"callback_data\":\"toggle:trust:$TARGET_NODE:$ACT_T\"}]"
# 模块三:深度配置管理 (结合 UI 熔断)
if [ "$IS_OFFICIAL_GATEWAY" != "true" ] && [ "$ST_OTA" == "true" ]; then
BTN_CONFIG="[{\"text\":\"✏️ 更改终端展示代号\",\"callback_data\":\"rename:$TARGET_NODE\"}, {\"text\":\"🆙 OTA 静默升级\",\"callback_data\":\"ota_confirm:$TARGET_NODE\"}]"
else
BTNS="["
for N in $NODE_LIST; do
BTNS="$BTNS[{\"text\":\"🖥️ $N\",\"callback_data\":\"manage:$N\"}],"
done
BTNS="${BTNS%,}]"
send_ui "$CHAT_ID" "🔍 刷新后的节点列表:" "$BTNS"
BTN_CONFIG="[{\"text\":\"✏️ 更改终端展示代号\",\"callback_data\":\"rename:$TARGET_NODE\"}]"
fi
# 模块四:危险区与逃生舱
BTN_DANGER="[{\"text\":\"🗑️ 从中枢销毁该档案\",\"callback_data\":\"del:$TARGET_NODE\"}, {\"text\":\"⬅️ 返回战区列表\",\"callback_data\":\"list_nodes\"}]"
# 组合终极矩阵
BTNS="[$BTN_ACTION, $BTN_TOGGLE, $BTN_CONFIG, $BTN_DANGER]"
TEXT_MSG="⚙️ **目标锁定**: \`$TARGET_ALIAS\`\n(底层标识: \`$TARGET_NODE\`)\n🌐 IP 坐标: \`$A_IP\`\n🕒 最后通讯: \`$LAST_SEEN\`\n\n请下达精确控制指令"
if [ -n "$MSG_ID" ]; then
edit_ui "$CHAT_ID" "$MSG_ID" "$TEXT_MSG" "$BTNS"
else
send_ui "$CHAT_ID" "$TEXT_MSG" "$BTNS"
fi
;;
run:*|report:*|log:*)
ACTION_TYPE=$(echo "$TEXT" | cut -d':' -f1)
TARGET_NODE=$(echo "$TEXT" | cut -d':' -f2)
toggle:*)
# [动态启停通信闭环]
IFS=':' read -r CMD MOD_NAME TARGET_NODE TARGET_STATE <<< "$TEXT"
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
AGENT_INFO=$(db_exec "SELECT agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
AGENT_IP=$(echo "$AGENT_INFO" | cut -d'|' -f1)
AGENT_PORT=$(echo "$AGENT_INFO" | cut -d'|' -f2)
if [ -n "$AGENT_IP" ] && [ -n "$AGENT_PORT" ]; then
TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_toggle")
TARGET_URL="${TARGET_URL}&mod=${MOD_NAME}&state=${TARGET_STATE}"
RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED")
if [[ "$RESPONSE" == *"Action Accepted"* ]]; then
# 下发成功,更新 DB原位重绘
db_exec "UPDATE nodes SET enable_${MOD_NAME}='$TARGET_STATE' WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE';"
TOGGLE_INFO=$(db_exec "SELECT enable_google, enable_trust FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
ST_GOOGLE=$(echo "$TOGGLE_INFO" | cut -d'|' -f1)
ST_TRUST=$(echo "$TOGGLE_INFO" | cut -d'|' -f2)
[ "$ST_GOOGLE" == "true" ] && BTN_G="🔴 停用 Google 纠偏" && ACT_G="false" || { BTN_G="🟢 启用 Google 纠偏"; ACT_G="true"; }
[ "$ST_TRUST" == "true" ] && BTN_T="🔴 停用信用净化" && ACT_T="false" || { BTN_T="🟢 启用信用净化"; ACT_T="true"; }
# 切换后直接复用扁平化 L3 面板的重绘逻辑
TOGGLE_INFO=$(db_exec "SELECT enable_google, enable_trust, enable_ota, agent_ip, IFNULL(last_seen, '未知') FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
ST_GOOGLE=$(echo "$TOGGLE_INFO" | cut -d'|' -f1)
ST_TRUST=$(echo "$TOGGLE_INFO" | cut -d'|' -f2)
ST_OTA=$(echo "$TOGGLE_INFO" | cut -d'|' -f3)
A_IP=$(echo "$TOGGLE_INFO" | cut -d'|' -f4)
LAST_SEEN=$(echo "$TOGGLE_INFO" | cut -d'|' -f5)
[ "$ST_GOOGLE" == "true" ] && BTN_G="🟢 Google巡逻: 已开" && ACT_G="false" || { BTN_G="🔴 Google巡逻: 已停"; ACT_G="true"; }
[ "$ST_TRUST" == "true" ] && BTN_T="🟢 信用净化: 已开" && ACT_T="false" || { BTN_T="🔴 信用净化: 已停"; ACT_T="true"; }
# 模块一:即时战术动作 (V4.0.0 引入深海声呐与趋势面板)
BTN_ACTION="[{\"text\":\"📍 触发 Google 纠偏\",\"callback_data\":\"google:$TARGET_NODE\"}, {\"text\":\"🛡️ 触发信用净化\",\"callback_data\":\"trust:$TARGET_NODE\"}], [{\"text\":\"🔍 投放深海声呐 (查IP质量)\",\"callback_data\":\"quality:$TARGET_NODE\"}, {\"text\":\"📈 查看 IP 污染趋势图\",\"callback_data\":\"trend:$TARGET_NODE\"}], [{\"text\":\"📜 提取终端实时日志\",\"callback_data\":\"log:$TARGET_NODE\"}, {\"text\":\"📊 生成单机战报\",\"callback_data\":\"report:$TARGET_NODE\"}]"
BTN_TOGGLE="[{\"text\":\"$BTN_G\",\"callback_data\":\"toggle:google:$TARGET_NODE:$ACT_G\"}, {\"text\":\"$BTN_T\",\"callback_data\":\"toggle:trust:$TARGET_NODE:$ACT_T\"}]"
if [ "$IS_OFFICIAL_GATEWAY" != "true" ] && [ "$ST_OTA" == "true" ]; then
BTN_CONFIG="[{\"text\":\"✏️ 更改终端展示代号\",\"callback_data\":\"rename:$TARGET_NODE\"}, {\"text\":\"🆙 OTA 静默升级\",\"callback_data\":\"ota_confirm:$TARGET_NODE\"}]"
else
BTN_CONFIG="[{\"text\":\"✏️ 更改终端展示代号\",\"callback_data\":\"rename:$TARGET_NODE\"}]"
fi
BTN_DANGER="[{\"text\":\"🗑️ 从中枢销毁该档案\",\"callback_data\":\"del:$TARGET_NODE\"}, {\"text\":\"⬅️ 返回战区列表\",\"callback_data\":\"list_nodes\"}]"
BTNS="[$BTN_ACTION, $BTN_TOGGLE, $BTN_CONFIG, $BTN_DANGER]"
TARGET_ALIAS=$(db_exec "SELECT IFNULL(node_alias, node_name) FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
TEXT_MSG="⚙️ **目标锁定**: \`$TARGET_ALIAS\`\n(底层标识: \`$TARGET_NODE\`)\n🌐 IP 坐标: \`$A_IP\`\n🕒 最后通讯: \`$LAST_SEEN\`\n\n✅ **执行成功**: 模块 [$MOD_NAME] 状态已切换为 $TARGET_STATE"
edit_ui "$CHAT_ID" "$MSG_ID" "$TEXT_MSG" "$BTNS"
else
send_msg "$CHAT_ID" "❌ 指令下发失败,安全策略禁止降级重试。"
fi
fi
;;
del:*)
# 🛡️ 提取并强制过滤节点名与 CHAT_ID 防注入
TARGET_NODE=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9_.-')
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
db_exec "DELETE FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE';"
send_msg "$CHAT_ID" "🗑️ 节点 \`$TARGET_NODE\` 的档案已从司令部彻底销毁!"
# 剔除后直接返回上级一级雷达菜单
REGION_DATA=$(db_exec "SELECT region, COUNT(*) FROM nodes WHERE chat_id='$CHAT_ID' GROUP BY region;")
if [ -z "$REGION_DATA" ]; then
send_msg "$CHAT_ID" "⚠️ 当前司令部已无任何节点挂载。"
else
BTNS="["
while IFS='|' read -r REGION_NAME NODE_COUNT; do
[ -z "$REGION_NAME" ] && REGION_NAME="UNKNOWN"
FLAG=$(get_flag "$REGION_NAME")
BTNS="$BTNS[{\"text\":\"$FLAG $REGION_NAME ($NODE_COUNT 台)\",\"callback_data\":\"region:$REGION_NAME\"}],"
done <<< "$REGION_DATA"
BTNS="${BTNS%,}]"
send_ui "$CHAT_ID" "🌍 刷新后的全视界雷达:" "$BTNS"
fi
;;
rename:*)
TARGET_NODE=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9_.-')
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
# [v3.5.2] 发送 ForceReply 引导用户回复
curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d "{\"chat_id\":\"$CHAT_ID\",\"text\":\"✏️ 请回复本消息以重命名节点:\n\`$TARGET_NODE\`\n(仅限中英文、数字最长20字符)\",\"parse_mode\":\"Markdown\",\"reply_markup\":{\"force_reply\":true}}" > /dev/null
;;
do_rename:*)
# [v3.5.2] 内部重命名路由 (已被第2处的代码拦截并格式化)
IFS=':' read -r CMD TARGET_NODE NEW_ALIAS <<< "$TEXT"
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
# 从 DB 提取 IP 和 Port
AGENT_INFO=$(db_exec "SELECT agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
AGENT_IP=$(echo "$AGENT_INFO" | cut -d'|' -f1)
AGENT_PORT=$(echo "$AGENT_INFO" | cut -d'|' -f2)
if [ -n "$AGENT_IP" ] && [ -n "$AGENT_PORT" ]; then
send_msg "$CHAT_ID" "⏳ 正在向 \`$TARGET_NODE\` ($AGENT_IP) 下发 [$ACTION_TYPE] 指令,请稍候..."
send_msg "$CHAT_ID" "⏳ 正在向 \`$TARGET_NODE\` 下发重命名指令,正在建立加密隧道..."
# 向 Agent 的开放端口发送动态 Webhook 唤醒指令
RESPONSE=$(curl -s -m 5 "http://${AGENT_IP}:${AGENT_PORT}/trigger_${ACTION_TYPE}" || echo "FAILED")
TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_rename")
# [绝密防线: Base64 编码绕过一切传输限制与 WAF 拦截]
ALIAS_B64=$(echo -n "$NEW_ALIAS" | base64 | tr -d '\n' | tr '+/' '-_')
TARGET_URL="${TARGET_URL}&b64=${ALIAS_B64}"
RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED")
if [ "$RESPONSE" == "FAILED" ]; then
send_msg "$CHAT_ID" "❌ 指令下发超时或失败!请检查节点公网 IP 或防火墙端口 ($AGENT_PORT) 是否放行。"
send_msg "$CHAT_ID" "❌ 指令下发超时!为防范劫持风险,已终止请求。"
elif [[ "$RESPONSE" == *"Action Accepted"* ]]; then
# [v3.5.2 极致丝滑] 确认 Agent 修改成功后Master 立即自动同步本地 SQLite 数据库!
db_exec "UPDATE nodes SET node_alias='$NEW_ALIAS' WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE';"
send_msg "$CHAT_ID" "✅ 通讯成功!节点别名已下发: \`$NEW_ALIAS\`%0A*(司令部档案已自动刷新,雷达面板已同步)*"
else
if [ "$ACTION_TYPE" == "run" ]; then
send_msg "$CHAT_ID" " 节点 \`$TARGET_NODE\` 回应: 指令已接收,伪装程序启动。"
fi
# 增加输出 RESPONSE 调试信息,排查任何拦截死因
send_msg "$CHAT_ID" "⚠️ 节点拒绝了请求,请确保 Agent 已更新至 v3.5.2%0A(回传信息: \`${RESPONSE}\`)"
fi
else
send_msg "$CHAT_ID" "❌ 数据库中未找到该节点的通讯地址。"
fi
;;
ota_confirm:*)
TARGET_NODE=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9_.-')
# 将取消动作引导回 manage因为 adv 已经被删除了
CONFIRM_BTNS="[[{\"text\":\"🚨 确认执行远程升级\",\"callback_data\":\"ota_execute:$TARGET_NODE\"}], [{\"text\":\"取消\",\"callback_data\":\"manage:$TARGET_NODE\"}]]"
send_ui "$CHAT_ID" "☢️ **操作确认**:即将向 \`$TARGET_NODE\` 下发 OTA 热更新指令。\n节点更新完成后会自动发送包含新版本号的注册回执确定执行" "$CONFIRM_BTNS"
;;
ota_execute:*)
TARGET_NODE=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9_.-')
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
AGENT_INFO=$(db_exec "SELECT agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
AGENT_IP=$(echo "$AGENT_INFO" | cut -d'|' -f1)
AGENT_PORT=$(echo "$AGENT_INFO" | cut -d'|' -f2)
if [ -n "$AGENT_IP" ] && [ -n "$AGENT_PORT" ]; then
if [ -n "$MSG_ID" ]; then
edit_msg "$CHAT_ID" "$MSG_ID" "⏳ 正在向 \`$TARGET_NODE\` 发送 OTA 触发报文..."
else
send_msg "$CHAT_ID" "⏳ 正在向 \`$TARGET_NODE\` 发送 OTA 触发报文..."
fi
TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_ota")
RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED")
# [灾难救援通道] 仅针对 OTA 开放一次性明文降级,用于抢救缺失 openssl 证书的老节点
if [ "$RESPONSE" == "FAILED" ]; then
TARGET_URL_HTTP="${TARGET_URL/https:\/\//http:\/\/}"
RESPONSE=$(curl -s -m 5 "$TARGET_URL_HTTP" || echo "FAILED")
if [[ "$RESPONSE" == *"Action Accepted"* ]]; then
TEXT_RES="⚠️ **明文救援成功**:该节点因缺失证书处于 HTTP 裸奔状态!已强行下发 OTA 抢救指令,请等待其重构 TLS 装甲。"
else
TEXT_RES="❌ OTA 指令下发彻底失败!节点已失联或网络阻断。"
fi
elif [[ "$RESPONSE" == *"403"* ]]; then
TEXT_RES="⚠️ **节点拒绝执行**:该节点本地未开启 OTA 权限或运行在官方网关下!"
else
TEXT_RES="✅ OTA (TLS加密) 触发成功!节点正在后台执行拉取重构..."
fi
if [ -n "$MSG_ID" ]; then
edit_msg "$CHAT_ID" "$MSG_ID" "$TEXT_RES"
else
send_msg "$CHAT_ID" "$TEXT_RES"
fi
else
send_msg "$CHAT_ID" "❌ 数据库中未找到该节点的通讯地址。"
fi
;;
# 【核心升级 v4.0.0】增加拦截规则,支持 quality 前缀
google:*|trust:*|run:*|report:*|log:*|quality:*)
# 🛡️ 提取并强制过滤动作参数、节点名与 CHAT_ID
ACTION_TYPE=$(echo "$TEXT" | cut -d':' -f1)
TARGET_NODE=$(echo "$TEXT" | cut -d':' -f2 | tr -cd 'a-zA-Z0-9_.-')
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
AGENT_INFO=$(db_exec "SELECT agent_ip, agent_port FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
AGENT_IP=$(echo "$AGENT_INFO" | cut -d'|' -f1)
AGENT_PORT=$(echo "$AGENT_INFO" | cut -d'|' -f2)
if [ -n "$AGENT_IP" ] && [ -n "$AGENT_PORT" ]; then
# [v3.0.2 防刷屏] 原位刷新菜单为等待状态
if [ -n "$MSG_ID" ]; then
edit_msg "$CHAT_ID" "$MSG_ID" "⏳ 正在向 \`$TARGET_NODE\` ($AGENT_IP) 下发 [$ACTION_TYPE] 指令,请稍候..."
else
send_msg "$CHAT_ID" "⏳ 正在向 \`$TARGET_NODE\` ($AGENT_IP) 下发 [$ACTION_TYPE] 指令,请稍候..."
fi
# 🛡️ [v3.0.4] 动态签名生成与触发 (防重放与防篡改)
TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_${ACTION_TYPE}")
RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED")
# 结果判定
if [ "$RESPONSE" == "FAILED" ]; then
TEXT_RES="❌ 指令下发超时或失败!为保护链路安全,已终止通信 (严禁降级为 HTTP)。"
elif [[ "$RESPONSE" == *"403"* ]]; then
TEXT_RES="⚠️ **拒绝执行**:该节点未在本地开启此模块,请检查安装时的配置!"
else
if [ "$ACTION_TYPE" == "google" ] || [ "$ACTION_TYPE" == "run" ]; then
TEXT_RES="✅ 节点 \`$TARGET_NODE\` 回应: 📍 Google 纠偏程序启动。"
elif [ "$ACTION_TYPE" == "trust" ]; then
TEXT_RES="✅ 节点 \`$TARGET_NODE\` 回应: 🛡️ IP 信用净化程序启动。"
elif [ "$ACTION_TYPE" == "quality" ]; then
TEXT_RES="✅ 节点 \`$TARGET_NODE\` 回应: 🔍 深海声呐已投放!请等待异步战报回传。"
elif [ "$ACTION_TYPE" == "log" ]; then
TEXT_RES="✅ 节点 \`$TARGET_NODE\` 正在抓取日志..."
else
TEXT_RES="✅ 节点 \`$TARGET_NODE\` 接收指令: $ACTION_TYPE"
fi
fi
# [v3.0.1 防刷屏] 将等待状态刷新为最终结果
if [ -n "$MSG_ID" ]; then
edit_msg "$CHAT_ID" "$MSG_ID" "$TEXT_RES"
else
send_msg "$CHAT_ID" "$TEXT_RES"
fi
else
send_msg "$CHAT_ID" "❌ 数据库中未找到该节点的通讯地址。"
fi
;;
trend:*)
# [v4.0.2 优化: 扩容 15 次追踪并引入 GOOG/GPT 状态]
TARGET_NODE=$(echo "${TEXT#*:}" | tr -cd 'a-zA-Z0-9_.-')
CHAT_ID=$(echo "$CHAT_ID" | tr -cd '0-9-')
TREND_DATA=$(db_exec "SELECT datetime(check_time, 'localtime'), scam_score, goog_status, nf_status, gpt_status FROM ip_trend_log WHERE node_name='$TARGET_NODE' ORDER BY check_time DESC LIMIT 15;")
if [ -z "$TREND_DATA" ]; then
TEXT_RES="⚠️ 节点 \`$TARGET_NODE\` 暂无历史体检档案。请先执行 [🔍 投放深海声呐] 进行探测。"
else
TARGET_ALIAS=$(db_exec "SELECT IFNULL(node_alias, node_name) FROM nodes WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE' LIMIT 1;")
[ -z "$TARGET_ALIAS" ] && TARGET_ALIAS="$TARGET_NODE"
TEXT_RES="📈 *[${TARGET_ALIAS}] 历史态势感知 (近15次)*\n\n"
TEXT_RES+="时间(本地) | 风险 | 谷歌 | NF | GPT\n"
TEXT_RES+="-----------------------------------------\n"
while IFS='|' read -r c_time score goog nf gpt; do
[ -z "$score" ] && score="0"
[ -z "$goog" ] && goog="未知"
[ -z "$nf" ] && nf="未知"
[ -z "$gpt" ] && gpt="未知"
# 时间做极简切割 (截取 04-24 20:52) 节省横向空间
short_time=$(echo "$c_time" | cut -c 6-16)
if [ "$score" -le 20 ]; then SCORE_EMJ="🟢"
elif [ "$score" -le 60 ]; then SCORE_EMJ="🟡"
else SCORE_EMJ="🔴"
fi
# 拼接紧凑排版
TEXT_RES+="\`${short_time}\` | ${SCORE_EMJ}\`${score}\` | \`${goog}\` | \`${nf}\` | \`${gpt}\`\n"
done <<< "$TREND_DATA"
TEXT_RES+="\n_💡 提示:🔴风险分 >60 极易触发网页验证码拦截;谷歌显示 CN 即为高危送中。_"
fi
# [v4.0.3 体验升级] 注入交互式控制台按钮,并调用原生 UI 重绘函数
BTNS="[[{\"text\":\"⚙️ 调出该节点控制台\",\"callback_data\":\"manage:$TARGET_NODE\"}]]"
if [ -n "$MSG_ID" ]; then
edit_ui "$CHAT_ID" "$MSG_ID" "$TEXT_RES" "$BTNS"
else
send_ui "$CHAT_ID" "$TEXT_RES" "$BTNS"
fi
;;
esac
done
fi

View File

@@ -0,0 +1,67 @@
#!/bin/bash
# ==========================================================
# 脚本名称: uninstall_master.sh (IP-Sentinel Master 一键卸载脚本 - 动态锚点版)
# 核心功能: 终止调度进程、清理看门狗定时任务、抹除数据库与配置
# ==========================================================
# ==========================================================
# 🛑 核心权限防线: 检查是否以 root 权限运行
# ==========================================================
if [ "$EUID" -ne 0 ]; then
echo -e "\033[31m❌ 权限被拒绝: 卸载 IP-Sentinel 需要最高系统权限。\033[0m"
echo -e "💡 请切换到 root 用户 (执行 su root 或 sudo -i) 后重新运行指令。"
exit 1
fi
MASTER_DIR="/opt/ip_sentinel_master"
CONF_FILE="${MASTER_DIR}/master.conf"
echo "========================================================"
echo " 🗑️ 准备卸载 IP-Sentinel Master (控制中枢)"
# [v3.4.0 优化] 卸载前读取并播报中枢版本号
if [ -f "$CONF_FILE" ]; then
MASTER_VER=$(grep "^MASTER_VERSION=" "$CONF_FILE" | cut -d'"' -f2)
[ -n "$MASTER_VER" ] && echo " 📍 目标版本: v${MASTER_VER}"
fi
echo "========================================================"
echo -e "\n⚠ 警告: 此操作将永久删除包含所有节点档案的 SQLite 数据库!"
read -p "确定要继续卸载吗?(y/n) [默认 n]: " CONFIRM_DEL
if [[ ! "$CONFIRM_DEL" =~ ^[Yy]$ ]]; then
echo "已取消卸载操作。"
exit 0
fi
# 1. 停止并删除 Systemd 服务 (适配新架构)
echo "[1/4] 正在停止并删除 Systemd 服务..."
if command -v systemctl >/dev/null 2>&1; then
echo "💡 检测到 Systemd 环境,正在抹除 Systemd 服务单元..."
systemctl disable --now ip-sentinel-master.service >/dev/null 2>&1
rm -f /etc/systemd/system/ip-sentinel-master.service
systemctl daemon-reload
systemctl reset-failed
else
echo "💡 未检测到 Systemd跳过此步骤..."
fi
# 2. 停止运行中的 Master 守护进程 (兜底清理老版进程)
echo "[2/4] 正在终止后台中枢调度进程..."
pkill -9 -f "tg_master.sh" >/dev/null 2>&1 || true
# 3. 清除看门狗定时任务 (Cron)
echo "[3/4] 正在清理系统定时任务 (Cron)..."
crontab -l 2>/dev/null | grep -v "tg_master.sh" > /tmp/cron_backup
crontab /tmp/cron_backup
rm -f /tmp/cron_backup
# 4. 删除所有文件、配置与数据库
echo "[4/4] 正在抹除核心程序、配置文件与 SQLite 数据库..."
if [ -d "$MASTER_DIR" ]; then
rm -rf "$MASTER_DIR"
fi
echo "========================================================"
echo "✅ 卸载彻底完成Master 司令部已从您的系统中无痕移除。"
echo "========================================================"

83
scripts/fetch_trends.py Normal file
View File

@@ -0,0 +1,83 @@
import urllib.request
import xml.etree.ElementTree as ET
import os
import json
import re
# ================== [路径防弹装甲] ==================
# 无论在哪里执行该脚本,都能精准反推项目根目录
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_ROOT = os.path.dirname(SCRIPT_DIR)
MAP_JSON_PATH = os.path.join(PROJECT_ROOT, "data", "map.json")
DATA_DIR = os.path.join(PROJECT_ROOT, "data", "keywords")
# ====================================================
# 特殊战区代码映射 (Google Trends RSS 要求)
GEO_FIX = {'UK': 'GB'}
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
def get_active_regions():
"""动态提取 map.json 中的战区 (适配 v3.5.0 大洲战区降维架构)"""
try:
with open(MAP_JSON_PATH, 'r', encoding='utf-8') as f:
data = json.load(f)
regions = []
# 第一层穿透:遍历所有大洲战区 (continents)
for continent in data.get('continents', []):
# 第二层穿透:遍历大洲下的所有国家 (countries)
for country in continent.get('countries', []):
if 'id' in country:
regions.append(country['id'])
return regions
except Exception as e:
print(f"❌ [读取地图失败]: {e}")
return []
def fetch_trends(region_code):
"""从 Google Trends 抓取当日热搜"""
geo = GEO_FIX.get(region_code, region_code)
url = f"https://trends.google.com/trending/rss?geo={geo}"
try:
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=10) as response:
xml_data = response.read()
root = ET.fromstring(xml_data)
return [re.sub(r'[\n\r\t]', ' ', item.find('title').text).strip()
for item in root.findall('./channel/item')
if item.find('title') is not None]
except Exception as e:
print(f"⚠️ {region_code} 抓取异常: {e}")
return []
def update_file(region, new_words):
"""滑动窗口更新,保留 200 条最热记录"""
os.makedirs(DATA_DIR, exist_ok=True)
file_path = os.path.join(DATA_DIR, f"kw_{region}.txt")
old_words = []
if os.path.exists(file_path):
with open(file_path, 'r', encoding='utf-8') as f:
old_words = [l.strip() for l in f if l.strip()]
# 新词排在最前面,去重
combined = new_words + [w for w in old_words if w not in new_words]
final_list = combined[:200]
with open(file_path, 'w', encoding='utf-8') as f:
f.write('\n'.join(final_list) + '\n')
print(f"✅ [同步完成] {region}: 注入 {len(new_words)} 条新热点")
if __name__ == '__main__':
regions = get_active_regions()
if not regions:
print("🛑 未发现活跃战区,请检查 map.json")
exit(1)
for r in regions:
print(f"📡 正在拉取 {r} 战区情报...")
words = fetch_trends(r)
if words:
update_file(r, words)

103
scripts/fetch_trust_urls.py Normal file
View File

@@ -0,0 +1,103 @@
import urllib.request
import xml.etree.ElementTree as ET
import os
import json
import random
# ================== [路径防弹装甲] ==================
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_ROOT = os.path.dirname(SCRIPT_DIR)
REGIONS_DIR = os.path.join(PROJECT_ROOT, "data", "regions")
# ====================================================
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}
# 全球骨干新闻 RSS 监听矩阵
RSS_FEEDS = {
"US": ["http://rss.cnn.com/rss/cnn_topstories.rss", "https://feeds.npr.org/1001/rss.xml"],
"UK": ["http://feeds.bbci.co.uk/news/rss.xml"],
"AU": ["https://www.abc.net.au/news/feed/51120/rss.xml"],
"CA": ["https://www.cbc.ca/cmlink/rss-topstories"],
"DE": ["https://www.tagesschau.de/xml/rss2"],
"FR": ["https://www.france24.com/fr/rss"],
"ES": ["https://feeds.elpais.com/mrss-s/pages/ep/site/elpais.com/portada"],
"JP": ["https://news.yahoo.co.jp/rss/topics/top-picks.xml"],
"HK": ["https://hk.news.yahoo.com/rss/hong-kong"],
"TW": ["https://news.google.com/rss?hl=zh-TW&gl=TW&ceid=TW:zh-Hant"],
"KR": ["https://www.yonhapnewstv.co.kr/category/news/headline/feed/"],
"SG": ["https://www.channelnewsasia.com/api/v1/rss-outbound-feed?_format=xml"],
"NL": ["https://feeds.nos.nl/nosnieuwsalgemeen"],
"VN": ["https://vnexpress.net/rss/tin-moi-nhat.rss"],
"MY": ["https://news.google.com/rss?hl=en-MY&gl=MY&ceid=MY:en"]
}
def fetch_rss_links(region_code, max_items=15):
"""抓取该战区最新的 RSS 新闻链接"""
feeds = RSS_FEEDS.get(region_code, [])
if not feeds:
return []
links = []
for url in feeds:
try:
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=10) as response:
xml_data = response.read()
root = ET.fromstring(xml_data)
for item in root.findall('.//item'):
link = item.find('link')
if link is not None and link.text:
clean_link = link.text.strip()
if clean_link.startswith('http'):
links.append(clean_link)
except Exception as e:
print(f"⚠️ [{region_code}] RSS 抓取异常 ({url}): {e}")
# 去重并截取最新
return list(set(links))[:max_items]
def process_json_file(file_path, region_code):
"""融合静态基石与动态新闻"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
trust_mod = data.get("trust_module", {})
if not trust_mod or "static_urls" not in trust_mod:
return
static_urls = trust_mod.get("static_urls", [])
# 抓取今日该战区的活体新闻流
daily_news_urls = fetch_rss_links(region_code)
# 战术混合:基石(保证高权重) + 新闻(保证活体动态)
combined_urls = static_urls + daily_news_urls
# 深度洗牌,打破机械顺序特征
combined_urls = list(set(combined_urls))
random.shuffle(combined_urls)
# 覆写回供 Agent 拉取的 white_urls
trust_mod["white_urls"] = combined_urls
data["trust_module"] = trust_mod
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"✅ [信用融合] {os.path.basename(file_path)}: 骨干 {len(static_urls)} 条 + 活体 {len(daily_news_urls)}")
except Exception as e:
print(f"❌ [处理失败] {file_path}: {e}")
if __name__ == '__main__':
print("========== 启动 IP-Sentinel 活体新闻流融合引擎 ==========")
for root_dir, _, files in os.walk(REGIONS_DIR):
for file in files:
if file.endswith(".json"):
file_path = os.path.join(root_dir, file)
region_code = os.path.relpath(file_path, REGIONS_DIR).split(os.sep)[0]
process_json_file(file_path, region_code)
print("========== 融合引擎执行完毕 ==========")

77
scripts/ua_generator.py Normal file
View File

@@ -0,0 +1,77 @@
import random
import os
# ==========================================
# IP-Sentinel 超大型高保真指纹工厂 (V3.1.5)
# 无需第三方库,直接生成千万级组合的真实指纹
# ==========================================
def generate_chrome_version():
# 模拟 2024 年主流 Chrome 内核号 (122 - 125)
major = random.randint(122, 125)
build = random.randint(5000, 6500)
patch = random.randint(10, 150)
return f"{major}.0.{build}.{patch}"
def generate_windows_ua(count=1000):
uas = set()
while len(uas) < count:
# 现代 Windows UA 已经固化为 Windows NT 10.0
uas.add(f"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{generate_chrome_version()} Safari/537.36")
return list(uas)
def generate_macos_ua(count=1000):
uas = set()
while len(uas) < count:
mac_os_minor = random.randint(11, 15)
mac_os_patch = random.randint(1, 6)
if random.choice([True, False]):
# Chrome on Mac
uas.add(f"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_{mac_os_minor}_{mac_os_patch}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{generate_chrome_version()} Safari/537.36")
else:
# Safari on Mac
safari_build = f"605.1.{random.randint(10, 15)}"
safari_version = f"17.{random.randint(1, 4)}"
uas.add(f"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_{mac_os_minor}_{mac_os_patch}) AppleWebKit/{safari_build} (KHTML, like Gecko) Version/{safari_version} Safari/{safari_build}")
return list(uas)
def generate_ios_ua(count=1000):
uas = set()
devices = ["iPhone", "iPad"]
while len(uas) < count:
device = random.choice(devices)
ios_major = random.randint(16, 17)
ios_minor = random.randint(1, 5)
ios_patch = random.randint(1, 3)
safari_build = f"605.1.{random.randint(10, 15)}"
safari_version = f"{ios_major}.{random.choice(['0', '1', '2', '3'])}"
uas.add(f"Mozilla/5.0 ({device}; CPU {'iPhone ' if device=='iPhone' else ''}OS {ios_major}_{ios_minor}_{ios_patch} like Mac OS X) AppleWebKit/{safari_build} (KHTML, like Gecko) Version/{safari_version} Mobile/15E148 Safari/604.1")
return list(uas)
def generate_android_ua(count=1000):
uas = set()
# 主流 Android 机型库
models = ["Pixel 8 Pro", "Pixel 8", "Pixel 7a", "Pixel 7 Pro", "SM-S928B", "SM-S928U", "SM-S918B", "SM-A546B", "SM-A346B", "23113RKC6C", "23049PCD8G", "CPH2437", "V2227A", "PGT-AN10", "NX729J"]
while len(uas) < count:
android_ver = random.randint(12, 14)
model = random.choice(models)
uas.add(f"Mozilla/5.0 (Linux; Android {android_ver}; {model}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{generate_chrome_version()} Mobile Safari/537.36")
return list(uas)
if __name__ == "__main__":
# 确保输出目录存在
os.makedirs('data', exist_ok=True)
# 严格按照“绝对坐标”顺序生成 4000 条数据
pool = []
pool.extend(generate_windows_ua(1000)) # 行 1-1000
pool.extend(generate_macos_ua(1000)) # 行 1001-2000
pool.extend(generate_ios_ua(1000)) # 行 2001-3000
pool.extend(generate_android_ua(1000)) # 行 3001-4000
with open('data/user_agents.txt', 'w') as f:
for ua in pool:
f.write(ua + '\n')
print(f"✅ 成功生成 4000 条高保真绝对坐标指纹库!")

75
telemetry/worker.js Normal file
View File

@@ -0,0 +1,75 @@
// IP-Sentinel Glasshouse Telemetry (全透明装机量统计中枢)
// 部署环境: Cloudflare Workers + KV
// 隐私声明: 绝对不采集、不存储用户的 IP 地址、Header、Token 及任何系统特征参数。仅做纯粹的原子累加。
export default {
async fetch(request, env) {
const url = new URL(request.url);
const path = url.pathname;
// 全局跨域头,确保 GitHub README 的 Shields.io 徽章能正常读取
const corsHeaders = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET",
};
// 核心原子操作:无情的 +1 机器
async function incrementCounter(key) {
let count = await env.SENTINEL_KV.get(key);
count = count ? parseInt(count) + 1 : 1;
await env.SENTINEL_KV.put(key, count.toString());
return count;
}
async function getCounter(key) {
let count = await env.SENTINEL_KV.get(key);
return count ? parseInt(count) : 0;
}
try {
// 1. Agent (哨兵) 部署触发接口
if (path === '/ping/agent') {
const count = await incrementCounter('agent_count');
return new Response(count.toString(), { headers: corsHeaders });
}
// 2. Master (指挥部) 部署触发接口
if (path === '/ping/master') {
const count = await incrementCounter('master_count');
return new Response(count.toString(), { headers: corsHeaders });
}
// 3. GitHub README Agent 徽章接口 (输出给 Shields.io)
if (path === '/stats/agent') {
const count = await getCounter('agent_count');
const shield = {
schemaVersion: 1,
label: "Agent Nodes",
message: count.toString(),
color: "blue"
};
return new Response(JSON.stringify(shield), {
headers: { ...corsHeaders, "Content-Type": "application/json" }
});
}
// 4. GitHub README Master 徽章接口 (输出给 Shields.io)
if (path === '/stats/master') {
const count = await getCounter('master_count');
const shield = {
schemaVersion: 1,
label: "Master Commands",
message: count.toString(),
color: "orange"
};
return new Response(JSON.stringify(shield), {
headers: { ...corsHeaders, "Content-Type": "application/json" }
});
}
return new Response("IP-Sentinel Glasshouse Telemetry API (No IP Logged, 100% Transparent)", { status: 200 });
} catch (err) {
return new Response("Error", { status: 500 });
}
}
};

2
version.txt Normal file
View File

@@ -0,0 +1,2 @@
MASTER_VERSION=4.0.3
AGENT_VERSION=4.0.3