Compare commits

...

51 Commits

Author SHA1 Message Date
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
33 changed files with 1340 additions and 150 deletions

View File

@@ -12,6 +12,8 @@
## ✨ 核心极客特性 (Core Architecture)
-**无损高并发引擎 (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)**:全系脚本彻底消灭硬编码,部署时动态抓取云端版本信标。自带状态机嗅探逻辑与防撞甲探测,即使是手动在终端运行安装,也仅需回车瞬间完成配置继承、数据同步与无损换代。
@@ -45,6 +47,7 @@
```
## 🚀 极速部署 (Quick Start)
> 🛡️ **跨平台装甲支持**Debian / Ubuntu / CentOS / RHEL / Alpine Linux / Arch Linux
系统现提供两种接入模式,请根据您的战术需求选择:
### 🔹 模式 A私有独立模式 (全自主、强烈推荐)
@@ -54,12 +57,12 @@
- **部署 Master (中枢大脑)**:找一台 VPS 作为司令部(仅需部署一台),执行:
```bash
bash <(curl -sL https://raw.githubusercontent.com/hotyue/IP-Sentinel/main/master/install_master.sh)
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://raw.githubusercontent.com/hotyue/IP-Sentinel/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
```
- 激活节点:安装完成后,您的手机会收到一条 #REGISTER# 注册暗号,将其转发给您自己的机器人即可完成编队入库。
@@ -71,7 +74,7 @@ bash <(curl -sL https://raw.githubusercontent.com/hotyue/IP-Sentinel/main/core/i
- 部署 Agent在目标 VPS 上执行以下指令,安装过程中选择官方公共网关,并输入您的 Chat ID
```Bash
bash <(curl -sL https://raw.githubusercontent.com/hotyue/IP-Sentinel/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
```
- 激活节点:同上,将收到的暗号转发给官方机器人即可。
@@ -114,12 +117,17 @@ bash <(curl -sL https://raw.githubusercontent.com/hotyue/IP-Sentinel/legacy/core
如果你在使用过程中遇到任何疑难杂症,或者想围观大佬们的养护战报,欢迎加入我们的基地:
- Telegram 频道: [@IP_Sentinel_Matrix](https://t.me/IP_Sentinel_Matrix)
## 🤝 参与贡献
## 🤝 参与贡献 (Contributors)
如果你想为项目增加新的节点区域(例如德国、英国、新加坡等),或者提供更丰富的本土化搜索词库,非常欢迎提交 Pull Request
**🌟 感谢以下所有为 IP-Sentinel 添砖加瓦的指挥官们!** 你们的每一次 PR 都在让这艘战舰的全球雷达覆盖得更广。
## **v3.0 全球节点贡献规范:**
<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
**💡 全球节点贡献规范:**
1.`data/regions/国家代码/省州代码/` 目录下新增对应城市的配置 `.json`
2.`data/keywords/` 目录下新增或完善配套国家的词库 `kw_XX.txt`
3. **最重要的一步:**`data/map.json` 中登记你的国家、省州与城市信息。安装脚本将自动读取地图,在全球雷达中点亮你的节点!

View File

@@ -24,10 +24,6 @@ if [ -z "$NODE_NAME" ]; then
fi
NODE_ALIAS="${NODE_ALIAS:-$NODE_NAME}"
# --- [重点升级 1: 守护进程防冲突自检] ---
if pgrep -f "webhook.py $AGENT_PORT" > /dev/null; then
exit 0
fi
# 1. 尝试获取实时公网 IP
RAW_IP=$(curl -${IP_PREF:-4} -s -m 5 api.ip.sb/ip | tr -d '[:space:]')
@@ -65,6 +61,20 @@ if [ -n "$AGENT_IP" ]; then
fi
fi
# ================== [v3.6.3 新增: 自动生成自签名 TLS 加密证书] ==================
# [修复] 仅在私有中枢模式下生成证书。官方网关模式下CF Worker 严格拒绝自签名,必须回退 HTTP
if [ "$TG_TOKEN" != "OFFICIAL_GATEWAY_MODE" ]; then
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
fi
# ==============================================================================
# 3. 启动轻量级 Python3 Webhook 监听服务 (v3.0.4 动态 HMAC 签名防重放)
cat > "${INSTALL_DIR}/core/webhook.py" << 'EOF'
import http.server
@@ -374,11 +384,40 @@ class AgentHandler(http.server.BaseHTTPRequestHandler):
self.end_headers()
self.wfile.write(b"Action Accepted: trigger_ota\n")
# 挂起异步升级进程 (注入 SILENT_OTA 旁路变量跳过所有 read -p 交互)
# 注意:这里我们写死拉取 dev-v3.6.0 分支的安装脚本进行覆盖测试,未来正式版上线时会改回 main
repo_url = "https://raw.githubusercontent.com/hotyue/IP-Sentinel/dev-v3.6.0"
ota_cmd = f"export SILENT_OTA='true'; curl -sL {repo_url}/core/install.sh | bash > /opt/ip_sentinel/logs/ota_upgrade.log 2>&1 &"
subprocess.Popen(['bash', '-c', ota_cmd])
# [修复] 逃逸 Systemd Cgroup并引入 bash -n 语法树校验防砖机制
import shutil
import base64
repo_url = "https://raw.githubusercontent.com/hotyue/IP-Sentinel/main"
# 动态构建报错回执文本 (第一层 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 &"
subprocess.Popen(full_cmd, shell=True)
except Exception as e:
self.send_response(500)
@@ -394,21 +433,49 @@ class AgentHandler(http.server.BaseHTTPRequestHandler):
import socket
# ================== [v3.0.3 变更: 引入多线程模型抵抗 Slowloris 攻击] ==================
class ThreadedDualStackServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
class ThreadedServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
allow_reuse_address = True # 开启端口复用,防止热重启时端口冲突
address_family = socket.AF_INET6 if socket.has_ipv6 else socket.AF_INET
try:
bind_addr = "::" if socket.has_ipv6 else ""
with ThreadedDualStackServer((bind_addr, PORT), AgentHandler) as httpd:
httpd.serve_forever()
# 1. 优先尝试监听双栈/IPv6 (大多数 Linux 默认支持 IPv4 映射接入)
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'
# 核心判定:提取配置中的 TOKEN 标识
is_official_gateway = False
if os.path.exists('/opt/ip_sentinel/config.conf'):
with open('/opt/ip_sentinel/config.conf', 'r') as f:
for line in f:
if line.startswith('TG_TOKEN=') and 'OFFICIAL_GATEWAY_MODE' in line:
is_official_gateway = True
break
# 仅在非官方网关且证书存在时,才挂载 TLS 装甲
if not is_official_gateway and 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 python3 "${INSTALL_DIR}/core/webhook.py" "$AGENT_PORT" > /dev/null 2>&1 &
disown 2>/dev/null || true
echo "✅ [Agent] 守护进程启动完毕,可安全关闭终端。"
# --- [重点升级 3: 移交系统级守护进程接管 (阻塞模式)] ---
echo "🚀 [Agent] 正在启动 Webhook 监听服务 (端口: $AGENT_PORT)..."
exec python3 "${INSTALL_DIR}/core/webhook.py" "$AGENT_PORT"

View File

@@ -5,10 +5,19 @@
# 核心功能: 战区分组菜单、模块按需开启、官方机器人一键配置、版本状态机路由
# ==========================================================
# ==========================================================
# 🛑 核心权限防线: 检查是否以 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/dev-v3.6.0"
# REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/v3.6.2-rc"
INSTALL_DIR="/opt/ip_sentinel"
CONFIG_FILE="${INSTALL_DIR}/config.conf"
@@ -44,37 +53,41 @@ if [ ${#MISSING_CMDS[@]} -gt 0 ]; then
if command -v apt-get >/dev/null 2>&1; then
# Debian / Ubuntu 系列
apt-get update -y >/dev/null 2>&1
apt-get install -y curl jq cron procps python3 >/dev/null 2>&1
# [v3.6.3 抽脂级优化] 注入 --no-install-recommends 拒绝捆绑销售,大幅节省磁盘与内存
apt-get install -y --no-install-recommends curl jq cron procps python3 >/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
# RHEL / CentOS / AlmaLinux 系列
PKG_MGR="yum"
command -v dnf >/dev/null 2>&1 && PKG_MGR="dnf"
$PKG_MGR install -y curl jq cronie procps-ng python3 >/dev/null 2>&1
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 cronie procps-ng python3 >/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
# [核心修复 Issue #21] Alpine Linux 系列
# Alpine 本身就是极致精简,无需特殊参数
echo "Alpine 探测到系统类型为 Alpine Linux正在执行轻量级安装..."
apk add --no-cache curl jq dcron procps python3 bash >/dev/null 2>&1
# Alpine 下必须手动创建 cron spool 目录并启动 crond
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
# [核心修复 Issue #250] Arch Linux 系列
# Arch Linux 系列
pacman -Sy --noconfirm curl jq cronie procps-ng python >/dev/null 2>&1
# Arch 下某些 cronie 实现可能缺少 /root/.cache 权限,做个兼容保障
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 curl jq cron procps python3\033[0m"
echo -e " Debian/Ubuntu: \033[36mapt-get update && apt-get install -y --no-install-recommends curl jq cron procps python3\033[0m"
echo -e " CentOS/RHEL: \033[36myum install -y curl jq cronie procps-ng python3\033[0m"
echo -e " Alpine Linux: \033[36mapk add --no-cache curl jq dcron procps python3 bash\033[0m"
echo -e " Arch Linux: \033[36mpacman -Sy curl jq cronie procps-ng python\033[0m"
@@ -155,6 +168,11 @@ fi
# ================== [v3.1.1/v3.2.2 优化: 安装前环境纯净度清理] ==================
echo -e "\n⏳ 正在清理旧版守护进程与冗余任务..."
# [新增] 优雅停止 Systemd 服务,防止代码替换时引发无限复活风暴
if command -v systemctl >/dev/null 2>&1; then
systemctl stop ip-sentinel-runner.timer ip-sentinel-updater.timer ip-sentinel-report.timer ip-sentinel-agent-daemon.service >/dev/null 2>&1 || true
fi
# 1. 强制超度可能存活的 Webhook 及各类看门狗进程,释放端口
pkill -9 -f "webhook.py" >/dev/null 2>&1 || true
pkill -9 -f "agent_daemon.sh" >/dev/null 2>&1 || true
@@ -249,15 +267,17 @@ if [ "$UPGRADE_MODE" == "false" ]; then
IFS="|" read -r CITY_ID CITY_NAME < /tmp/cities.txt
echo -e "\033[32m💡 该区域下仅有单一城市 [$CITY_NAME],已自动锁定。\033[0m"
else
i=1; CITY_MAP=()
i=1; CITY_MAP=(); CITY_NAME_MAP=()
while IFS="|" read -r c_id c_name; do
echo " $i) $c_name"
CITY_MAP[$i]="$c_id"
CITY_NAME_MAP[$i]="$c_name"
((i++))
done < /tmp/cities.txt
read -p "请输入选择 [1-$((i-1))] (默认1): " CI_SEL
CI_SEL=${CI_SEL:-1}
CITY_ID="${CITY_MAP[$CI_SEL]}"
CITY_NAME="${CITY_NAME_MAP[$CI_SEL]}"
fi
# 清理临时文件 (增加清理 continents.txt)
@@ -622,37 +642,139 @@ fi
chmod +x ${INSTALL_DIR}/core/*.sh
# 7. 配置系统定时任务 (高频调度与看门狗)
echo -e "\n[7/7] 正在注入系统定时任务与看门狗进程..."
crontab -l 2>/dev/null | grep -v "ip_sentinel" > /tmp/cron_backup || true
# 核心养护模块: 每 30 分钟触发一次
echo "*/30 * * * * ${INSTALL_DIR}/core/runner.sh >/dev/null 2>&1" >> /tmp/cron_backup
# 养料更新模块: (v3.3.0升级) 每天凌晨 3 点触发,由中枢自动进行分频调度
echo "0 3 * * * ${INSTALL_DIR}/core/updater.sh >/dev/null 2>&1" >> /tmp/cron_backup
echo -e "\n[7/7] 正在注入系统守护进程与调度器..."
# [v3.3.0 新增] 初始化 UA 指纹库更新时间戳,确立 30 天滚动周期的计算锚点
echo $(date +%s) > "${INSTALL_DIR}/core/.ua_last_update"
# 如果配置了联控,启动 Webhook 与战报任务
if [[ -n "$TG_TOKEN" ]] && [[ -n "$CHAT_ID" ]]; then
# 每天早上 8 点发送昨天的统计战报
echo "0 8 * * * ${INSTALL_DIR}/core/tg_report.sh >/dev/null 2>&1" >> /tmp/cron_backup
if command -v systemctl >/dev/null 2>&1; then
echo "💡 检测到 Systemd 环境,正在部署原生守护服务..."
# [v3.0.1新增修改 3: 删除原来的 curl 取 IP直接使用我们上方锁定的 BIND_IP]
# 并提前写入 IP 缓存,彻底阻断 agent_daemon 首次启动时的重复推送
# [修复竞态]: 提前写入公网 IP 缓存,彻底阻断 agent_daemon 首次启动时的抢跑推送
echo "$SAFE_PUBLIC_IP" > "${INSTALL_DIR}/core/.last_ip"
# 双保险守护进程看门狗
echo "@reboot nohup bash ${INSTALL_DIR}/core/agent_daemon.sh >/dev/null 2>&1 &" >> /tmp/cron_backup
echo "* * * * * nohup bash ${INSTALL_DIR}/core/agent_daemon.sh >/dev/null 2>&1 &" >> /tmp/cron_backup
# 安装时立刻启动一次边缘守护进程
nohup bash "${INSTALL_DIR}/core/agent_daemon.sh" >/dev/null 2>&1 &
fi
# 1. Runner 核心养护模块服务与定时器
cat > /etc/systemd/system/ip-sentinel-runner.service << EOF
[Unit]
Description=IP-Sentinel Runner Service
After=network.target
[Service]
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SyslogIdentifier=ip-sentinel
Type=oneshot
ExecStart=/bin/bash ${INSTALL_DIR}/core/runner.sh
User=root
CPUSchedulingPolicy=idle
IOSchedulingClass=idle
EOF
[ -f /tmp/cron_backup ] && crontab /tmp/cron_backup 2>/dev/null
rm -f /tmp/cron_backup
cat > /etc/systemd/system/ip-sentinel-runner.timer << EOF
[Unit]
Description=Timer for IP-Sentinel Runner Service
[Timer]
OnBootSec=10
OnUnitActiveSec=30min
RandomizedDelaySec=180
Persistent=true
Unit=ip-sentinel-runner.service
[Install]
WantedBy=timers.target
EOF
# 2. Updater 养料更新模块服务与定时器
cat > /etc/systemd/system/ip-sentinel-updater.service << EOF
[Unit]
Description=IP-Sentinel Updater Service
After=network.target
[Service]
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SyslogIdentifier=ip-sentinel
Type=oneshot
ExecStart=/bin/bash ${INSTALL_DIR}/core/updater.sh
User=root
CPUSchedulingPolicy=idle
IOSchedulingClass=idle
EOF
cat > /etc/systemd/system/ip-sentinel-updater.timer << EOF
[Unit]
Description=Timer for IP-Sentinel Updater Service
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
Unit=ip-sentinel-updater.service
[Install]
WantedBy=timers.target
EOF
systemctl daemon-reload
systemctl enable --now ip-sentinel-runner.timer ip-sentinel-updater.timer
if [[ -n "$TG_TOKEN" ]] && [[ -n "$CHAT_ID" ]]; then
# 3. TG 战报服务与定时器
cat > /etc/systemd/system/ip-sentinel-report.service << EOF
[Unit]
Description=IP-Sentinel Telegram Report Service
After=network.target
[Service]
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SyslogIdentifier=ip-sentinel
Type=oneshot
ExecStart=/bin/bash ${INSTALL_DIR}/core/tg_report.sh
User=root
CPUSchedulingPolicy=idle
IOSchedulingClass=idle
EOF
cat > /etc/systemd/system/ip-sentinel-report.timer << EOF
[Unit]
Description=Timer for IP-Sentinel Telegram Report Service
[Timer]
OnCalendar=*-*-* 08:00:00
Unit=ip-sentinel-report.service
[Install]
WantedBy=timers.target
EOF
# 4. [排雷修复] Agent Daemon Webhook 监听守护服务 (Type=simple, 常驻执行)
cat > /etc/systemd/system/ip-sentinel-agent-daemon.service << EOF
[Unit]
Description=IP-Sentinel Agent Daemon Service
After=network.target
[Service]
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
SyslogIdentifier=ip-sentinel
Type=simple
ExecStart=/bin/bash ${INSTALL_DIR}/core/agent_daemon.sh
Restart=always
RestartSec=5
User=root
CPUSchedulingPolicy=idle
IOSchedulingClass=idle
[Install]
WantedBy=multi-user.target
EOF
# [修复竞态]: 提前写入公网 IP 缓存,阻断重复推送
echo "$SAFE_PUBLIC_IP" > "${INSTALL_DIR}/core/.last_ip"
systemctl daemon-reload
systemctl enable --now ip-sentinel-report.timer
systemctl enable --now ip-sentinel-agent-daemon.service
fi
else
echo "💡 未检测到 Systemd (可能是 Alpine Linux),回退到 Cron 调度模式..."
crontab -l 2>/dev/null | grep -v "ip_sentinel" > /tmp/cron_backup || true
echo "*/30 * * * * ${INSTALL_DIR}/core/runner.sh >/dev/null 2>&1" >> /tmp/cron_backup
echo "0 3 * * * ${INSTALL_DIR}/core/updater.sh >/dev/null 2>&1" >> /tmp/cron_backup
if [[ -n "$TG_TOKEN" ]] && [[ -n "$CHAT_ID" ]]; then
echo "0 8 * * * ${INSTALL_DIR}/core/tg_report.sh >/dev/null 2>&1" >> /tmp/cron_backup
echo "$SAFE_PUBLIC_IP" > "${INSTALL_DIR}/core/.last_ip"
echo "@reboot nohup bash ${INSTALL_DIR}/core/agent_daemon.sh >/dev/null 2>&1 &" >> /tmp/cron_backup
echo "* * * * * nohup bash ${INSTALL_DIR}/core/agent_daemon.sh >/dev/null 2>&1 &" >> /tmp/cron_backup
nohup bash "${INSTALL_DIR}/core/agent_daemon.sh" >/dev/null 2>&1 &
fi
[ -f /tmp/cron_backup ] && crontab /tmp/cron_backup 2>/dev/null
rm -f /tmp/cron_backup
fi
# ================== [v3.4.0 核心: 状态机驱动的热更新路由] ==================
if [[ -n "$TG_TOKEN" ]] && [[ -n "$CHAT_ID" ]]; then
@@ -769,5 +891,5 @@ if [ -n "$AGENT_COUNT" ] && [[ "$AGENT_COUNT" =~ ^[0-9]+$ ]]; then
echo -e "\033[32m✅ 感谢您成为全球第 ${AGENT_COUNT} 名 IP-Sentinel 哨兵!\033[0m"
else
echo -e "\033[32m✅ 感谢您加入 IP-Sentinel 哨兵阵列!\033[0m"
fi
echo -e "\n"
fi
echo -e "\n"

View File

@@ -97,14 +97,21 @@ CURL_BIND_OPT=""
DYNAMIC_IP_PREF="-${IP_PREF:-4}" # 默认提取用户配置
if [[ -n "$BIND_IP" && "$BIND_IP" =~ ^[0-9a-fA-F:\.]+$ ]]; then
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)"
# [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

View File

@@ -11,7 +11,7 @@ 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://git.94211762.xyz/hotyue/IP-Sentinel/raw/branch/main"
# REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/v3.6.2-rc"
# 1. 基础环境校验
[ ! -f "$CONFIG_FILE" ] && exit 1
@@ -99,14 +99,21 @@ CURL_BIND_OPT=""
DYNAMIC_IP_PREF="-${IP_PREF:-4}" # 默认提取用户配置
if [[ -n "$BIND_IP" && "$BIND_IP" =~ ^[0-9a-fA-F:\.]+$ ]]; then
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)"
# [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

View File

@@ -31,11 +31,17 @@ CURL_BIND_OPT=""
DYNAMIC_IP_PREF="-${IP_PREF:-4}"
if [[ -n "$BIND_IP" && "$BIND_IP" =~ ^[0-9a-fA-F:\.]+$ ]]; then
CURL_BIND_OPT="--interface $BIND_IP"
if [[ "$BIND_IP" == *":"* ]]; then
DYNAMIC_IP_PREF="-6"
elif [[ "$BIND_IP" == *"."* ]]; then
DYNAMIC_IP_PREF="-4"
# [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
@@ -86,6 +92,7 @@ case "$REGION_CODE" in
"SG") FLAG="🇸🇬" ;;
"HK") FLAG="🇭🇰" ;;
"GB"|"UK") FLAG="🇬🇧" ;;
"AU") FLAG="🇦🇺" ;;
*) FLAG="🌐" ;;
esac

View File

@@ -1,10 +1,18 @@
#!/bin/bash
# ==========================================================
# 脚本名称: 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 "========================================================"
@@ -18,13 +26,31 @@ if [ -f "$CONFIG_FILE" ]; then
fi
echo "========================================================"
# 1. 停止运行中的守护进程与主控模块 (涵盖所有历史版本进程)
echo "[1/3] 正在终止后台守护进程与所有养护任务..."
# 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
# 使用 pkill 替代传统的 pgrep | xargs指令更短、容错率更高
# 2. 停止运行中的守护进程与主控模块 (兜底清理老版进程)
echo "[2/4] 正在终止后台守护进程与所有养护任务..."
pkill -9 -f "tg_daemon.sh" >/dev/null 2>&1
pkill -9 -f "agent_daemon.sh" >/dev/null 2>&1
# [v3.4.0 优化] 确保清理所有 python3 调起的 Webhook 实例
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
@@ -33,16 +59,16 @@ 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
# 2. 清除系统定时任务 (Cron)
echo "[2/3] 正在清理系统定时任务 (Cron)..."
# 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
# 3. 删除所有文件、日志与临时缓存
echo "[3/3] 正在抹除核心程序、配置文件与系统痕迹..."
# 4. 删除所有文件、日志与临时缓存
echo "[4/4] 正在抹除核心程序、配置文件与系统痕迹..."
if [ -d "$INSTALL_DIR" ]; then
rm -rf "$INSTALL_DIR"
fi

View File

@@ -12,7 +12,7 @@ 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/dev-v3.6.0"
# REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/v3.6.2-rc"
# 1. 加载本地冷数据配置
if [ ! -f "$CONFIG_FILE" ]; then
@@ -42,7 +42,12 @@ CURL_CMD="curl -${IP_PREF:-4} -sL"
if [ -n "$BIND_IP" ]; then
# curl 的 --interface 参数不支持带方括号的 IPv6 地址,必须强行脱壳
RAW_BIND_IP=$(echo "$BIND_IP" | tr -d '[]')
CURL_CMD="$CURL_CMD --interface $RAW_BIND_IP"
# [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
# ==========================================================

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

@@ -0,0 +1,169 @@
crystal palace vs west ham
d4vd
danish malewar
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
psl
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
ange postecoglou
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
socceroos
bathurst 1000
booking.com
airbnb
webjet
bali weather
smartraveller
lotto results
powerball results
oz lotto
public holidays 2026
mothers day 2026
carsales
redbook
nrma
racv
racq
petrol spy
optus login
vodafone
kogan
catch.com.au
mecca
sydney fish market
queen victoria market
taronga zoo
dreamworld
movie world
wotif
anytime fitness
time in london

View File

@@ -1,3 +1,33 @@
will trent
ibm
lecce vs fiorentina
celeste rivas hernandez
grand theft auto vi
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

View File

@@ -1,3 +1,33 @@
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
@@ -55,7 +85,6 @@ jeff bezos
dan brown
паспорт громадянина україни для виїзду за кордон
serena williams
kampf der realitystars
манчестер юнайтед лидс
catherine deneuve
bobzin

View File

@@ -1,3 +1,33 @@
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
luis merlo
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

View File

@@ -1,3 +1,33 @@
madonna age
margot haddad
ana riera
hinaupoko devèze
bruce toussaint
cheque energie
reid wiseman
mma
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

View File

@@ -1,8 +1,36 @@
水晶宮 對 西漢姆聯
吉達艾阿里
山口智子
百佳超級市場
利息
戴祖儀
陳若思
麥當勞
首岸
中国商飞c919
pl
bundesliga
hailey bieber
德甲
cherki
now
曼城
now tv
al nassr
洪金寶
曼聯
車路士
切爾西 對 曼聯
英超
何沛珈
熱刺
tottenham vs brighton
熱刺 對 布萊頓
epl
司機
补贴
華富邨
江美儀
戴祖儀
零售
藍莓
商湯科技

View File

@@ -1,3 +1,33 @@
町田ゼルビア
モンスターハンターシリーズ
クリスタル・パレス 対 ウェストハム
吉田正尚
旭琉會
神戸
kick
てんちむ
浜辺美波
デーブ ロバーツ
皇治
小雪
にじさんじデビュー
ちゃんよた
坂本 花織
松山 千春
dior
リーグアン
伊勢谷友介
bayern vs vfb stuttgart
chelsea vs man united
唐田えりか
102回目のプロポーズ
デゼルビ
アトレティコ 対 ソシエダ
チェルシー 対 マンu
スパーズ
清春
ディエゴ・ゴメス
ps5
ハイウェイ の 堕 天使 興行 収入
カブス 対 メッツ
dazn
@@ -14,7 +44,6 @@ afc u20女子アジアカップ
ネオジオ
uefaヨーロッパリーグ
加藤史帆
町田ゼルビア
志田未来
伊藤英明
島田麻央

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

@@ -0,0 +1,47 @@
크리스털 팰리스 대 웨스트 햄
비상계엄
연기금
배틀그라운드
제이홉
두산로보틱스
부부
미노이 우원재
danish malewar
mi vs gt
양치 승
프리미어리그
pl
bundesliga
맨체스터 시티 fc
fotmob
윤아
김영인
манчестер сити арсенал
케이뱅크
날씨
환율
삼성전자 주가
손흥민
토트넘 경기 일정
넷플릭스
국민은행
네이버웹툰
로또 당첨번호
쿠팡
KBO 리그
프로야구 순위
아이폰 15
챗gpt
인스타그램
유튜브 밴스드
이강인
김민재
LCK 일정
T1
페이커
무빙
카카오톡 PC버전
당근마켓
배달의민족
올리브영
메이플스토리

View File

@@ -1,3 +1,33 @@
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

View File

@@ -1,3 +1,32 @@
crystal palace vs west ham
grok
gemini
claude ai
gpt
ai
is chatgpt down
strait of hormuz news
danish malewar
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

View File

@@ -1,6 +1,34 @@
洪敬堯
華邦電子
柔美的細胞小將 3
底特律老虎
三 商 美邦
川 普
英雄聯盟
聯電adr
rklb
amd stock
宋仲基
兵工廠
德甲
塞爾提克 對 76人
justin bieber 演唱會
拜仁慕尼黑
何潤東
廖子妤
英超
許凱
tottenham vs brighton
長野縣
交通安全
朋友收集夢想生活
麥克傑克森
王濛
騎士 對 暴龍
熱刺 對 布萊頓
iem rio 2026
garret anderson
墓乃伊
iem rio 2026
曹格
claude design
柯文哲
@@ -15,7 +43,6 @@ claude design
東光路
货币
amd
rklb
航空母艦
axti
Yahoo奇摩

View File

@@ -1,3 +1,33 @@
oscar isaac
xrp ledger
believe me itv
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

View File

@@ -1,3 +1,32 @@
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

View File

@@ -1,3 +1,33 @@
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
bayern munich
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
napoli
đường ray
inter
inter đấu với cagliari
sassuolo vs como

View File

@@ -1,6 +1,6 @@
{
"version": "3.5.2",
"updated_at": "2026-04-16",
"updated_at": "2026-04-19",
"continents": [
{
"id": "ASIA",
@@ -22,6 +22,14 @@
{ "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 (香港)",
@@ -178,6 +186,54 @@
]
}
]
},
{
"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,35 @@
{
"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://en.wikipedia.org/wiki/Special:Random",
"https://www.smh.com.au/",
"https://www.dailytelegraph.com.au/",
"https://www.service.nsw.gov.au/",
"https://transportnsw.info/",
"https://www.bom.gov.au/",
"https://www.woolworths.com.au/",
"https://www.coles.com.au/",
"https://www.bunnings.com.au/",
"https://www.abc.net.au/",
"https://www.news.com.au/",
"https://www.nine.com.au/",
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.commbank.com.au/",
"https://www.westpac.com.au/",
"https://www.realestate.com.au/",
"https://www.domain.com.au/",
"https://www.seek.com.au/",
"https://www.nrl.com/",
"https://premier.ticketek.com.au/",
"https://www.amazon.com.au/"
]
}
}

View File

@@ -0,0 +1,36 @@
{
"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://en.wikipedia.org/wiki/Special:Random",
"https://www.couriermail.com.au/",
"https://www.brisbanetimes.com.au/",
"https://www.qld.gov.au/",
"https://translink.com.au/",
"https://www.health.qld.gov.au/",
"https://www.bom.gov.au/",
"https://www.bunnings.com.au/",
"https://www.woolworths.com.au/",
"https://www.coles.com.au/",
"https://www.abc.net.au/",
"https://www.news.com.au/",
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.commbank.com.au/",
"https://www.suncorp.com.au/",
"https://www.boq.com.au/",
"https://www.realestate.com.au/",
"https://www.domain.com.au/",
"https://www.seek.com.au/",
"https://www.nrl.com/",
"https://premier.ticketek.com.au/",
"https://www.amazon.com.au/"
]
}
}

View File

@@ -0,0 +1,35 @@
{
"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://en.wikipedia.org/wiki/Special:Random",
"https://www.adelaidenow.com.au/",
"https://indaily.com.au/",
"https://www.sa.gov.au/",
"https://www.adelaidemetro.com.au/",
"https://www.sapowernetworks.com.au/",
"https://www.bom.gov.au/",
"https://www.bunnings.com.au/",
"https://www.coles.com.au/",
"https://www.woolworths.com.au/",
"https://www.abc.net.au/",
"https://www.news.com.au/",
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.commbank.com.au/",
"https://www.bendigobank.com.au/",
"https://www.realestate.com.au/",
"https://www.domain.com.au/",
"https://www.seek.com.au/",
"https://www.afl.com.au/",
"https://premier.ticketek.com.au/",
"https://www.amazon.com.au/"
]
}
}

View File

@@ -0,0 +1,35 @@
{
"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://en.wikipedia.org/wiki/Special:Random",
"https://www.theage.com.au/",
"https://www.heraldsun.com.au/",
"https://www.vic.gov.au/",
"https://www.ptv.vic.gov.au/",
"https://www.vicroads.vic.gov.au/",
"https://www.bom.gov.au/",
"https://www.bunnings.com.au/",
"https://www.kmart.com.au/",
"https://www.abc.net.au/",
"https://www.news.com.au/",
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.nab.com.au/",
"https://www.anz.com.au/",
"https://www.woolworths.com.au/",
"https://www.coles.com.au/",
"https://www.realestate.com.au/",
"https://www.seek.com.au/",
"https://www.afl.com.au/",
"https://www.ticketmaster.com.au/",
"https://www.amazon.com.au/"
]
}
}

View File

@@ -0,0 +1,35 @@
{
"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://en.wikipedia.org/wiki/Special:Random",
"https://thewest.com.au/",
"https://www.perthnow.com.au/",
"https://www.wa.gov.au/",
"https://www.transperth.wa.gov.au/",
"https://www.bom.gov.au/",
"https://www.bunnings.com.au/",
"https://www.coles.com.au/",
"https://www.woolworths.com.au/",
"https://www.kmart.com.au/",
"https://www.abc.net.au/",
"https://www.news.com.au/",
"https://my.gov.au/",
"https://www.ato.gov.au/",
"https://www.commbank.com.au/",
"https://www.bankwest.com.au/",
"https://reiwa.com.au/",
"https://www.realestate.com.au/",
"https://www.seek.com.au/",
"https://www.afl.com.au/",
"https://premier.ticketek.com.au/",
"https://www.amazon.com.au/"
]
}
}

View File

@@ -0,0 +1,22 @@
{
"region_name": "South Korea - Seoul",
"google_module": {
"base_lat": 37.5665,
"base_lon": 126.9780,
"lang_params": "hl=ko&gl=KR",
"valid_url_suffix": "co.kr"
},
"trust_module": {
"white_urls": [
"https://ko.wikipedia.org/wiki/특수:임의문서",
"https://www.naver.com/",
"https://www.daum.net/",
"https://namu.wiki/",
"https://www.tistory.com/",
"https://www.coupang.com/",
"https://www.chosun.com/",
"https://www.yna.co.kr/",
"https://www.kakaocorp.com/"
]
}
}

View File

@@ -5,10 +5,19 @@
# 核心功能: 部署/卸载调度中枢、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/dev-v3.6.1"
# REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/v3.6.2-rc"
# [核心: 动态提取 Master 专属版本锚点 (KV 解析法)]
# 通过 grep 定位 MASTER_VERSION 行,再通过 cut 提取等号右侧的值
@@ -96,6 +105,10 @@ 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
@@ -133,12 +146,18 @@ if [ ${#MISSING_CMDS[@]} -gt 0 ]; then
if command -v apt-get >/dev/null 2>&1; then
apt-get update -y >/dev/null 2>&1
apt-get install -y curl jq sqlite3 cron procps >/dev/null 2>&1
# [v3.6.3 抽脂级优化] 注入 --no-install-recommends 拒绝捆绑销售
apt-get install -y --no-install-recommends curl jq sqlite3 cron procps >/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"
command -v dnf >/dev/null 2>&1 && PKG_MGR="dnf"
$PKG_MGR install -y curl jq sqlite cronie procps-ng >/dev/null 2>&1
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 >/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正在执行轻量级安装..."
@@ -153,7 +172,7 @@ if [ ${#MISSING_CMDS[@]} -gt 0 ]; then
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 curl jq sqlite3 cron procps\033[0m"
echo -e " Debian/Ubuntu: \033[36mapt-get update && apt-get install -y --no-install-recommends curl jq sqlite3 cron procps\033[0m"
echo -e " CentOS/RHEL: \033[36myum install -y curl jq sqlite cronie procps-ng\033[0m"
echo -e " Alpine Linux: \033[36mapk add --no-cache curl jq sqlite dcron procps bash\033[0m"
exit 1
@@ -260,14 +279,47 @@ echo -e "\n[4/4] 部署 TG 调度守护进程..."
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 || 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
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
# 立刻启动 (追加 disown 彻底脱离终端管控,实现绝对静默)
pgrep -f tg_master.sh >/dev/null || { nohup bash "${MASTER_DIR}/tg_master.sh" >/dev/null 2>&1 & disown 2>/dev/null; }
[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 "========================================================"

View File

@@ -12,7 +12,7 @@ source "$CONF"
# [核心: 运行态版本继承与云通信地址]
REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/main"
# 临时改为开发地址用于测试
# REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/dev-v3.6.1"
# REPO_RAW_URL="https://raw.githubusercontent.com/hotyue/IP-Sentinel/v3.6.2-rc"
# MASTER_VERSION 已经在上方的 source "$CONF" 中被载入
# 如果本地极度陈旧没有该变量,才给定一个基础兜底值,避免变量为空导致崩溃
MASTER_VERSION=${MASTER_VERSION:-"3.5.0"}
@@ -22,32 +22,32 @@ OFFSET_FILE="${MASTER_DIR}/.tg_offset"
# --- 工具函数 ---
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
}
# ================== [v3.0.1 新增: 消息原位刷新函数] ==================
edit_msg() {
curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/editMessageText" \
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 -X POST "https://api.telegram.org/bot${TG_TOKEN}/editMessageText" \
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() {
sqlite3 "$DB_FILE" "$1"
printf ".timeout 5000\n%s\n" "$1" | sqlite3 "$DB_FILE"
}
# ================== [v3.0.4 核心: 动态 HMAC 签名生成器] ==================
@@ -65,10 +65,15 @@ generate_signed_url() {
local signature=$(echo -n "$payload" | openssl dgst -sha256 -hmac "$CHAT_ID" | awk '{print $NF}')
# 返回最终带签名的 URL
echo "http://${target_ip}:${target_port}${action_path}?t=${current_t}&sign=${signature}"
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
@@ -81,7 +86,7 @@ db_exec "ALTER TABLE nodes ADD COLUMN enable_ota TEXT DEFAULT 'false';" 2>/dev/n
# --- 核心轮询循环 ---
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)
@@ -116,7 +121,7 @@ while true; do
# 告诉 TG 官方“指令已收到”,立刻消除按钮上的加载圈圈
if [ -n "$CB_ID" ]; then
curl -s -X POST "https://api.telegram.org/bot${TG_TOKEN}/answerCallbackQuery" -d "callback_query_id=${CB_ID}" > /dev/null
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
# ==========================================
@@ -178,7 +183,8 @@ while true; do
case "$REGION_NAME" in
"US") FLAG="🇺🇸" ;; "JP") FLAG="🇯🇵" ;; "HK") FLAG="🇭🇰" ;;
"SG") FLAG="🇸🇬" ;; "UK"|"GB") FLAG="🇬🇧" ;; "DE") FLAG="🇩🇪" ;; "FR") FLAG="🇫🇷" ;;
"CA") FLAG="🇨🇦" ;; "AU") FLAG="🇦🇺" ;; "KR") FLAG="🇰🇷" ;; "NL") FLAG="🇳🇱" ;; "BR") FLAG="🇧🇷" ;; "IN") FLAG="🇮🇳" ;; "TW") FLAG="🇹🇼" ;;
"CA") FLAG="🇨🇦" ;; "AU") FLAG="🇦🇺" ;; "KR") FLAG="🇰🇷" ;; "NL") FLAG="🇳🇱" ;;
"BR") FLAG="🇧🇷" ;; "IN") FLAG="🇮🇳" ;; "TW") FLAG="🇹🇼" ;;
esac
BTNS="$BTNS[{\"text\":\"$FLAG $REGION_NAME ($NODE_COUNT 台)\",\"callback_data\":\"region:$REGION_NAME\"}],"
done <<< "$REGION_DATA"
@@ -236,7 +242,7 @@ while true; do
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")
curl -s -m 5 "$TARGET_URL" > /dev/null &
{ curl -k -s -m 5 "$TARGET_URL" || curl -s -m 5 "${TARGET_URL/https:\/\//http:\/\/}"; } > /dev/null &
sleep 0.3 # 严格流量削峰
done
fi
@@ -260,13 +266,29 @@ while true; do
fi
# 下载最新的 master install 脚本作为幽灵进程
curl -sL "${REPO_RAW_URL}/master/install_master.sh" -o "/tmp/install_master.sh"
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
export SILENT_MASTER_OTA="true"
export OTA_CHAT_ID="$CHAT_ID"
nohup bash /tmp/install_master.sh >/dev/null 2>&1 & disown
# [修复] 必须显式将环境变量注入到 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
@@ -277,11 +299,13 @@ while true; do
if [ -z "$NODE_DATA" ]; then
send_msg "$CHAT_ID" "⚠️ 您名下暂无在线节点。"
else
send_msg "$CHAT_ID" "📢 **司令部指令下达:正在召唤所有哨兵回传简报...**"
# [文案优化] 提前告知指挥官需要排队等待
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 -s -m 5 "$TARGET_URL" > /dev/null &
sleep 0.2 # [新增] 流量削峰:每秒最多并发下发 5 个,保护 Master 网络栈
{ curl -k -s -m 5 "$TARGET_URL" || curl -s -m 5 "${TARGET_URL/https:\/\//http:\/\/}"; } > /dev/null &
# [致命修复] 强行休眠 2 秒!错开 TG 官方 1条/秒 的发信红线
sleep 2
done
fi
;;
@@ -295,7 +319,7 @@ while true; do
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 -s -m 5 "$TARGET_URL" > /dev/null &
curl -k -s -m 5 "$TARGET_URL" > /dev/null &
sleep 0.2 # [新增] 流量削峰:防止瞬间 fork 导致句柄耗尽
done
fi
@@ -313,9 +337,10 @@ while true; do
[ -z "$REGION_NAME" ] && REGION_NAME="UNKNOWN"
FLAG="🌐"
case "$REGION_NAME" in
"US") FLAG="🇺🇸" ;; "JP") FLAG="🇯🇵" ;; "HK") FLAG="🇭🇰" ;;
"SG") FLAG="🇸🇬" ;; "UK"|"GB") FLAG="🇬🇧" ;; "DE") FLAG="🇩🇪" ;; "FR") FLAG="🇫🇷" ;;
"CA") FLAG="🇨🇦" ;; "AU") FLAG="🇦🇺" ;; "KR") FLAG="🇰🇷" ;; "NL") FLAG="🇳🇱" ;; "BR") FLAG="🇧🇷" ;; "IN") FLAG="🇮🇳" ;; "TW") FLAG="🇹🇼" ;;
"US") FLAG="🇺🇸" ;; "JP") FLAG="🇯🇵" ;; "HK") FLAG="🇭🇰" ;;
"SG") FLAG="🇸🇬" ;; "UK"|"GB") FLAG="🇬🇧" ;; "DE") FLAG="🇩🇪" ;; "FR") FLAG="🇫🇷" ;;
"CA") FLAG="🇨🇦" ;; "AU") FLAG="🇦🇺" ;; "KR") FLAG="🇰🇷" ;; "NL") FLAG="🇳🇱" ;;
"BR") FLAG="🇧🇷" ;; "IN") FLAG="🇮🇳" ;; "TW") FLAG="🇹🇼" ;;
esac
BTNS="$BTNS[{\"text\":\"$FLAG $REGION_NAME ($NODE_COUNT 台)\",\"callback_data\":\"region:$REGION_NAME\"}],"
done <<< "$REGION_DATA"
@@ -418,7 +443,13 @@ while true; do
TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_toggle")
TARGET_URL="${TARGET_URL}&mod=${MOD_NAME}&state=${TARGET_STATE}"
RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED")
RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED")
# [向下兼容补丁] 若 HTTPS 拒绝或超时,回退 HTTP 试探老节点
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" == *"Action Accepted"* ]]; then
# 下发成功,更新 DB原位重绘
db_exec "UPDATE nodes SET enable_${MOD_NAME}='$TARGET_STATE' WHERE chat_id='$CHAT_ID' AND node_name='$TARGET_NODE';"
@@ -481,6 +512,8 @@ while true; do
case "$REGION_NAME" in
"US") FLAG="🇺🇸" ;; "JP") FLAG="🇯🇵" ;; "HK") FLAG="🇭🇰" ;;
"SG") FLAG="🇸🇬" ;; "UK"|"GB") FLAG="🇬🇧" ;; "DE") FLAG="🇩🇪" ;; "FR") FLAG="🇫🇷" ;;
"CA") FLAG="🇨🇦" ;; "AU") FLAG="🇦🇺" ;; "KR") FLAG="🇰🇷" ;; "NL") FLAG="🇳🇱" ;;
"BR") FLAG="🇧🇷" ;; "IN") FLAG="🇮🇳" ;; "TW") FLAG="🇹🇼" ;;
esac
BTNS="$BTNS[{\"text\":\"$FLAG $REGION_NAME ($NODE_COUNT 台)\",\"callback_data\":\"region:$REGION_NAME\"}],"
done <<< "$REGION_DATA"
@@ -516,7 +549,12 @@ while true; do
ALIAS_B64=$(echo -n "$NEW_ALIAS" | base64 | tr -d '\n' | tr '+/' '-_')
TARGET_URL="${TARGET_URL}&b64=${ALIAS_B64}"
RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED")
RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED")
# [向下兼容补丁] 若 HTTPS 拒绝或超时,回退 HTTP 试探老节点
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" "❌ 指令下发超时!请检查节点连通性。"
@@ -556,7 +594,12 @@ while true; do
fi
TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_ota")
RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED")
RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED")
# [向下兼容补丁] 若 HTTPS 拒绝或超时,回退 HTTP 试探老节点
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
TEXT_RES="❌ OTA 指令下发超时!请检查节点公网连通性。"
@@ -597,7 +640,12 @@ while true; do
# 🛡️ [v3.0.4] 动态签名生成与触发 (防重放与防篡改)
TARGET_URL=$(generate_signed_url "$AGENT_IP" "$AGENT_PORT" "/trigger_${ACTION_TYPE}")
RESPONSE=$(curl -s -m 5 "$TARGET_URL" || echo "FAILED")
RESPONSE=$(curl -k -s -m 5 "$TARGET_URL" || echo "FAILED")
# [向下兼容补丁] 若 HTTPS 拒绝或超时,回退 HTTP 试探老节点
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

View File

@@ -5,6 +5,15 @@
# 核心功能: 终止调度进程、清理看门狗定时任务、抹除数据库与配置
# ==========================================================
# ==========================================================
# 🛑 核心权限防线: 检查是否以 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"
@@ -25,19 +34,30 @@ if [[ ! "$CONFIRM_DEL" =~ ^[Yy]$ ]]; then
exit 0
fi
# 1. 停止运行中的 Master 守护进程
echo "[1/3] 正在终止后台中枢调度进程..."
# [优化] 使用 pkill 替代 pgrep | xargs指令更短、容错率更高
# 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
# 2. 清除看门狗定时任务 (Cron)
echo "[2/3] 正在清理系统定时任务 (Cron)..."
# 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
# 3. 删除所有文件、配置与数据库
echo "[3/3] 正在抹除核心程序、配置文件与 SQLite 数据库..."
# 4. 删除所有文件、配置与数据库
echo "[4/4] 正在抹除核心程序、配置文件与 SQLite 数据库..."
if [ -d "$MASTER_DIR" ]; then
rm -rf "$MASTER_DIR"
fi

View File

@@ -1,2 +1,2 @@
AGENT_VERSION=3.6.1
MASTER_VERSION=3.6.1
MASTER_VERSION=3.6.3
AGENT_VERSION=3.6.3