muslim-kh09/NexusFi-app

GitHub: muslim-kh09/NexusFi-app

一个运行在 Root Android/Termux 上的自包含微型 ISP 平台,提供热点强制门户、会话管理、带宽控制及离线本地云服务。

Stars: 1 | Forks: 0

NexusFi Banner
# NexusFi (微型 ISP 与本地云生态系统) ### 面向 Root Android / Termux 的生产级热点基础设施
Build: Passing Version: 3.0.0 Platform: Android/Termux
## 目录 1. [系统概述](#1-system-overview) 2. [架构与技术栈](#2-architecture--tech-stack) 3. [核心创新与基础设施](#3-core-innovations--infrastructure) - [PENTA-SHIELD 设备指纹](#31-penta-shield-device-fingerprinting) - [幽灵雷达与会话管理](#32-ghost-radar--session-management) - [智能存储与硬件遥测](#33-smart-storage--hardware-telemetry) 4. [游戏化与忠诚度引擎](#4-the-gamification--loyalty-engine) 5. [本地云(离线内联网)](#5-the-local-cloud-offline-intranet) 6. [数据层与安全架构](#6-data-layer--security-architecture) 7. [部署与启动序列](#7-deployment--startup-sequence) 8. [截图画廊](#8-screenshots-gallery) ## 1. 系统概述 该平台构成了一个完全在 rooted Android 硬件上运行的完整**微型互联网服务提供商 (Micro-ISP)** 技术栈。它专为密集型、受控访问的 Wi-Fi 环境而设计,运营者可以在其中进行精细的会话控制、可靠的收入追踪,并拥有丰富的离线内容生态系统——所有这些都不依赖于远程服务器、VPS 或云基础设施。 该系统管理着客户端连接的整个生命周期: 1. 设备连接到 Wi-Fi 接入点,并立即被 captive portal 防火墙拦截。 2. 用户通过 voucher 代码或免费试用进行身份验证,触发实时 `iptables` 规则注入以授权该特定设备。 3. 活动会话通过心跳循环持续监控。一旦过期或超时,防火墙规则将被原子性地撤销,并且会话在数据库中关闭。 4. 在整个会话期间,使用能够在 MAC 地址随机化后依然生效的多信号方法对设备进行指纹采集。忠诚度积分随之累积,用户无需运营者干预即可兑换赚取的礼物。 5. 用户随时可以访问完全离线的内联网——媒体服务器、社交网络、应用程序库——这些服务通过本地网络从同一台 Android 设备上提供,互联网带宽消耗为零。 该系统架构分为三个独立但紧密耦合的层级,每层都有明确的职责边界。 ## 2. 架构与技术栈 ``` ┌─────────────────────────────────────────────────────────────────────────┐ │ ANDROID DEVICE (Rooted) │ │ │ │ ┌──────────────────┐ ┌─────────────────────────────────────────────┐ │ │ │ TIER 3 │ │ TIER 1 — PHP/SQLite Hotspot Backend │ │ │ │ Native Android │ │ │ │ │ │ App (Java) │ │ ┌──────────────────┐ ┌────────────────┐ │ │ │ │ │ │ │ Captive Portal │ │ Admin Panel │ │ │ │ │ • WifiService │──▶│ │ index.php │ │ admin.php │ │ │ │ │ • Heartbeat Loop │ │ │ status.php │ │ │ │ │ │ │ • PENTA-SHIELD │ │ └──────────────────┘ └────────────────┘ │ │ │ │ DNA injection │ │ │ │ │ │ │ └──────────────────┘ │ ┌──────────▼──────────────────▼─────────┐ │ │ │ │ │ INCLUDES LAYER │ │ │ │ ┌──────────────────┐ │ │ SessionManager │ firewall.php │ │ │ │ │ TIER 2 │ │ │ auth.php │ mac_detection.php │ │ │ │ │ FastAPI Local │ │ │ gift_system.php │ accounting.php │ │ │ │ │ Cloud (Python) │ │ │ device_telemetry│ captive_trace.php │ │ │ │ │ │ │ └───────────────────────────────────────┘ │ │ │ │ • Media Hub (VOD)│ │ │ │ │ │ │ • Social Network │ │ ┌──────────▼───────────────────────────┐ │ │ │ │ • File Library │ │ │ API LAYER (/api/) │ │ │ │ │ │ │ │ heartbeat.php │ payments.php │ │ │ │ │ • Admin UI │ │ │ users.php │ analytics.php │ │ │ │ │ • WebSocket │ │ │ vouchers.php │ system.php │ │ │ │ │ Telemetry │ │ └──────────────────────────────────────┘ │ │ │ └──────────────────┘ │ │ │ │ │ :8090 │ ┌──────────▼───────────────────────────┐ │ │ │ │ │ SQLite (WAL Mode) — hotspot.db │ │ │ │ ┌──────────────────┐ │ └──────────────────────────────────────┘ │ │ │ │ DAEMONS │ └─────────────────────────────────────────────┘ │ │ │ ghost_radar.sh │ │ │ │ fw-worker.php │ ┌─────────────────────────────────────────────┐ │ │ │ captive_dns │ │ KERNEL LAYER │ │ │ │ _server.php │ │ iptables │ tc (HTB) │ /proc/net/arp │ │ │ └──────────────────┘ └─────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ │ Wi-Fi AP Interface │ ┌─────────────────────┴─────────────────────┐ │ Wi-Fi Clients │ │ Browser (Captive Portal) → :8080 │ │ Offline Platform → :8090 │ └────────────────────────────────────────────┘ ``` ### 各层技术栈 | 层级 | 技术 | 选择理由 | |---|---|---| | **热点后端** | PHP (CLI Server, 4 workers) | 原生 Termux 支持;无需单独的 HTTP 服务器 | | **数据库 (Hotspot)** | SQLite 3 (WAL + `mmap`) | 原子写入,防崩溃,无守护进程,兼容 SD 卡 | | **本地云** | FastAPI + `aiosqlite` (Python) | 异步 I/O 在单核上处理并发媒体流而不阻塞 | | **WSGI/ASGI Server** | Uvicorn (`--workers 1`) | Android 内核缺乏 `multiprocessing.fork`;asyncio 是正确的模型 | | **防火墙** | `iptables-legacy` / `/system/bin/iptables` | 运行时检测;当 legacy 不可用时回退到原生 Android iptables | | **带宽整形** | Linux `tc` HTB (Hierarchical Token Bucket) | 每用户专用类别;在内核支持的地方使用 `fq_codel` 叶节点 | | **DNS** | 自定义 PHP UDP DNS 服务器 | 双模式:强制门户 (欺骗) 和托管 (拦截列表 + 日志) | | **Android App** | 原生 Java (Android SDK) | 通过 `NetworkInterface`、`ActivityManager` 直接进行内核级硬件访问 | | **会话存储** | SQLite (`local_platform.db`) | 与 hotspot 数据库隔离,防止跨层级锁定 | ## 3. 核心创新与基础设施 ### 3.1 PENTA-SHIELD 设备指纹 **问题:** 现代 Android 设备 (Android 10+) 默认针对每个 Wi-Fi 网络随机化其 MAC 地址。用户的硬件地址在每次重新连接时都会改变,这使得在标准方法下,所有基于 MAC 的会话跟踪和计费从根本上变得不可靠。 **解决方案:** PENTA-SHIELD 是一个五信号设备身份系统,它构建了一个持久的、不可变的设备指纹,能够在 MAC 随机化后依然生效。它跨越原生 Android 应用程序和基于浏览器的 captive portal JavaScript 运行。 #### 信号层 1:原生 Android 应用注入 (最高信任度) `WifiService` 前台服务通过 `Settings.Secure` 读取设备的 `ANDROID_ID`(一种基于硬件的、恢复出厂设置后才会改变的唯一标识符),并将其作为每次心跳 POST 请求中的 `native_id` 字段进行传输。`ConnectivityChecker` 进一步读取 `Build.BRAND`、`Build.MODEL` 以及通过 `ActivityManager.MemoryInfo` 获取的物理 RAM 总量,在页面渲染前将这些作为查询参数 (`n_brand`、`n_model`、`n_ram`、`native_id`) 直接注入到 captive portal URL 中。这些数据在*用户甚至还没与门户交互之前*就已到达服务器端。 当后端收到 `native_id` 时,它会覆盖所有其他 token 来源: ``` // STRICT ANCHOR: If native_id is present, it is the ultimate, immutable device token. $native_id = $payload['native_id'] ?? $profile['native_id'] ?? ''; if (!empty($native_id)) { $token = device_telemetry_text($native_id, 128); } ``` 携带 `native_id` 的会话将被永久标记为 `device_token = 'native_app'`。此 token 在数据库中受写保护——随后的任何遥测更新都无法覆盖它。 #### 信号层 2:浏览器端 DNA 采集 嵌入式 JavaScript 遥测脚本 (`device_telemetry.php`) 在每次页面加载和心跳时收集 13 个维度的硬件指纹: | 信号 | 方法 | |---|---| | **操作系统与浏览器** | User-Agent 解析 + `navigator.userAgentData.getHighEntropyValues()` | | **品牌与型号** | UA Client Hints (API)、UA 字符串回退、平台检查 | | **内存** | `navigator.deviceMemory` | | **CPU 核心** | `navigator.hardwareConcurrency` | | **屏幕几何尺寸** | `screen.width × screen.height` (横/竖屏归一化) | | **GPU 特性 Hash** | WebGL `UNMASKED_RENDERER_WEBGL`、视口尺寸、纹理限制 | | **Canvas Hash** | GPU 渲染的 2D Canvas 像素 hash (亚像素渲染因 GPU 而异) | | **音频 Hash** | WebAudio `DynamicsCompressor` 参数指纹 | | **字体 Hash** | 13 种字体系列的字符规格测量 | | **语言与时区** | `navigator.language`、`Intl.DateTimeFormat().resolvedOptions().timeZone` | 这些信号在设备端进行哈希处理,并作为 `raw_dna` POST 到 `api/heartbeat.php`。服务器端的 `calculate_fuzzy_match()` 函数会计算这 13 个维度的加权余弦相似度得分。如果匹配度超过可配置的阈值,则确认设备连续性,即使在 MAC 地址更改后也是如此。 #### 信号层 3:Evercookie 持久化 浏览器端的遥测脚本会同时将 `device_token` 写入三个独立的存储位置: - `localStorage` - `sessionStorage` - HTTP Cookie (`max-age=31536000`,`SameSite=Lax`) 这种三重写入方法确保 token 在单个存储被清除后依然能够存活。恢复时会从这三个存储中读取,并且每次访问时都会重新同步这三个存储。 #### 信号层 4:影子档案与 MAC 变更迁移 每次提交遥测数据都会触发以 `mac_address` 为键向 `shadow_profiles` 表中进行 UPSERT 操作。当检测到 MAC 变更(相同的 `device_token`,不同的 MAC)时,`updateMacAddress()` 会在单个事务中原子性地迁移 `vouchers`、`users`、`free_trials`、`payment_requests` 和 `gifts` 表中的所有关联记录——从而在新的硬件地址下保留完整的购买和会话历史记录。 #### 信号层 5:ARP 表主权 后端从不仅将客户端提交的 MAC 地址作为主要来源信任。规范的 MAC 解析顺序是: 1. `/proc/net/arp` 内核表(直接读取文件,无 shell 执行)——由内核不可伪造地设置 2. `ip neigh show` 命令(Linux 邻居缓存——L2 硬件表) 3. GET 参数(仅当步骤 1 和 2 未产生结果时使用——竞态条件回退) ### 3.2 幽灵雷达与会话管理 幽灵雷达是会话过期和执行子系统。它由两个协同工作的组件组成:`ghost_radar.sh` 监督守护进程和 `SessionManager` PHP 类。 #### ghost_radar.sh — 看门狗循环 `ghost_radar.sh` 作为持久后台守护进程在基于 `mkdir` 的锁定下运行(在 `flock` 不可靠的 Android 上是 POSIX 安全的)。它以可配置的间隔(默认:30 秒)执行 `admin.php ghost_radar`,并在失败时以 5 秒的退避时间自动重启。这确保了过期执行流程始终在运行并具有自我修复能力。 #### SessionManager — 防火墙状态机 `SessionManager` 是数据库状态与实时 `iptables` 规则集之间关系的唯一权威。它实现了文件锁 (`flock(LOCK_EX)`),以防止并发会话发出冲突的防火墙修改指令。 **核心操作:** - **`reconcileClientAccess($mac)`** — 主要的单设备对账路径。从数据库读取所需的授权状态,从 `iptables` 计数器同步任何待处理的计费字节(单调计费修复——防止在清空链时丢失数据),然后调用 `firewall_apply_client_state()`。 - **`reconcileAll($pdo)`** — 启动时和定期运行的全面扫描对账。执行一次 `deepCleanupFirewall()` 清理过程,清除未在授权列表中的 MAC 对应的任何 `ipset` 条目,然后为所有当前活动的 voucher 重新应用规则。 - **`invalidateClientAccess($mac)` — 断头台** — 在检测到心跳超时时调用。执行三个原子操作: 1. `firewall_apply_client_state($mac, ..., authorized=false)` — 删除该 MAC 的所有 ACCEPT/RETURN 规则。 2. `UPDATE vouchers SET ended_at = ..., end_reason = 'heartbeat_timeout'` — 在数据库中关闭会话。 3. 向 captive 跟踪日志写入 `guillotine_fired` 事件。 - **`suspendClientAccess($mac)` — 软挂起** — 当原生 Android 应用会话静默超过 600 秒但 voucher 仍然有效时应用。它不会终止会话,而是应用 `is_soft_dropped` 标志,并重新配置防火墙以发出 `REJECT --reject-with icmp-port-unreachable` 响应,这会迫使 OS captive portal 检测引擎触发并提示用户重新打开门户。 - **`guillotineSweep($pdo)`** — 主动识别上次心跳时间戳早于 600 秒,或者其心跳 token 不再是 `native_app` 的、活动的、非软挂起的 `native_android` 会话。这些会话被批量标记为 `is_soft_dropped = 1`,并被推送到异步防火墙工作队列。 #### L2 物理层取消身份验证 — `hotspot_l2_kick_client()` 当会话被撤销 (`authorized=false`) 时,防火墙模块通过内核驱动程序直接向客户端发出 Layer 2 Wi-Fi 取消身份验证帧: ``` iw dev $iface station del $mac # 或 fallback: hostapd_cli -i $iface deauthenticate $mac ``` 这是一种物理层的强制断开连接。客户端的 Wi-Fi 协议栈断开链路,OS 检测到重新连接,captive portal 检测引擎立即重新触发——无需用户任何操作。取消身份验证在后台以非阻塞方式执行,以防止 PHP 进程停滞。 #### 防火墙架构 — 自定义 iptables 链 所有防火墙规则都在隔离的、应用拥有的链中运行,以防止干扰现有的 Android 网络共享规则: | 链 | 表 | 用途 | |---|---|---| | `CP_NAT` | `nat PREROUTING` | 默认拒绝的重定向 (HTTP→:8080, DNS→盲解析器) | | `CP_FILTER` | `filter FORWARD` | 针对未授权客户端的基于 MAC/IP 的 REJECT | | `CP_NODOT` | `filter FORWARD` | 全局屏蔽 DNS-over-TLS (端口 853) 和已知的 DoH 端点 | | `NOC_ACCT` | `filter FORWARD` | 父级计费链,跳转至各 voucher 的 `ACCT_V_{id}` 子链 | | `ACCT_V_{id}` | `filter FORWARD` | 用于带宽计费的会话级字节计数器链 | | `CP_SPEED` | `filter FORWARD` | 限速链钩子 | | `CP_MANGLE` | `mangle POSTROUTING` | TTL 归一化 (设为 64) 以对抗网络共享检测 | | `CP_FILTER_V6` | `ip6tables filter` | 通过 `icmp6-port-unreachable` 全屏蔽 IPv6 | **路由覆盖:** 高优先级的 `ip rule` (`priority 15000`) 强制将来自热点接口的所有流量引入 `main` 路由表,抢占 Android 用于自身网络共享子系统的 OEM 表 1028/97/98。 **DNS 架构 — 两种模式:** 自定义 PHP DNS 服务器 (`tools/captive_dns_server.php`) 在不同端口上以两种模式运行: - **Captive 模式** (盲解析器端口):使用网关 IP 响应所有 DNS 查询,将所有 HTTP 流量困在 captive portal 中。 - **托管模式** (标准端口):作为授权客户端的透明转发解析器,应用下载的域名拦截列表(色情、赌博、管理类)并将所有 DNS 查询记录到流量日志中。 **DoH/DoT 抑制:** `CP_NODOT` 链使用 `tcp-reset` 拒绝 DNS-over-TLS (TCP/UDP 端口 853),并阻止对 14 个已知公共 DoH 提供商 (Google, Cloudflare, Quad9 等) 的所有 HTTPS 访问。使用 `tcp-reset` 响应是刻意为之——它会导致即时 TLS 失败,从而触发 Android 11+ 和 iOS 14+ captive portal 检测中的 HTTP 回退,而不是发出网络“被管理性阻止”的信号,否则将完全抑制 captive portal 通知。 ### 3.3 智能存储与硬件遥测 #### USB 混合存储向导 启动时,`start.sh` 会在四个存储命名空间中执行多轮存储候选发现扫描: 1. **内部存储** — 应用根文件系统 2. **原始 SD 卡** — `/mnt/media_rw/` (通过 `su -c` 进行 root 提权的 `df` 读取) 3. **FUSE SD 卡** — `/storage/` (同一张物理卡的 FUSE 覆盖层) 4. **可采纳存储** — `/mnt/expand/` (格式化为内部存储的 SD 卡) 5. **USB OTG 驱动器** — 硬编码路径 + `/mnt/*usb*` 的通配符扫描 每个候选者都要通过最低可用空间 (>50 MB) 的资格验证,通过 `/proc/mounts` 进行文件系统类型检测,并进行去重。如果存在多个候选者,将显示一个带有 30 秒超时的交互式菜单。选定的路径将作为 `OFFLINE_STORAGE_PATH` 导出,并在启动时注入 FastAPI 服务器和 PHP 门户。 FastAPI 媒体服务器使用由本地 SQLite 设置表支持运行时设置 (`storage_mode`:`internal` | `usb`) 动态切换活动上传根目录,从而无需重启即可在存储后端之间进行热切换。 #### 实时硬件遥测 (FastAPI) FastAPI 本地云管理面板通过 `asyncio` 后台任务维护每 2 秒运行一次的实时遥测循环: | 指标 | 来源 | |---|---| | **CPU %** | `psutil.cpu_percent()` (3 次采样滚动平均值) | | **RAM %** | `psutil.virtual_memory().percent` (3 次采样滚动平均值) | | **CPU 温度** | `psutil.sensors_temperatures()` → 标签启发式算法 (`cpu`, `soc`, `core`, `cluster`) | | **表面温度** | 主板/电池传感器,或以 CPU 温度的 60% 作为校准估算值 | | **DB 延迟** | `DBTimerMiddleware` 拦截每个请求周期,按间隔聚合 | | **电池 %** | `psutil.sensors_battery()` | | **磁盘 I/O** | `psutil.disk_io_counters()` 每秒增量 | | **网络 I/O** | `psutil.net_io_counters()` 每秒增量 | | **活跃 WebSocket 连接数** | 来自 `ConnectionManager` 的实时计数 | 所有遥测数据同时通过 WebSocket 广播给所有已连接的管理面板客户端。`DBTimerMiddleware` ASGI 层拦截每个 HTTP 请求周期以记录响应延迟,该延迟经聚合后被推送为 `db_latency` 指标。 PHP 热点管理面板通过查询 `/sys/class/thermal/` 内核节点和 `/proc/meminfo` 获取 CPU 温度和 RAM 统计信息,独立读取硬件状态。 ## 4. 游戏化与忠诚度引擎 忠诚度系统是一种可消耗的积分机制,旨在通过免费上网时间奖励回头客,同时提供防止重复兑换和并发会话滥用的保障措施。 ### 积分累积 每个互联网套餐都带有可配置的积分值(例如,24h = 1 积分,72h = 3 积分,168h = 7 积分)。积分作为 `total_purchases` 存储在 `users` 表中,并在每次付费 voucher 激活时递增。忠诚度阈值(默认:10 次购买)是运行时可配置的系统设置。 ### 礼物计算 — `calculate_and_award_gifts()` 奖励计算是严格确定性的,而不是累加的: ``` earned_gifts = floor(total_purchases / loyalty_threshold) pending_gifts = COUNT(*) FROM gifts WHERE mac = ? AND status IN ('pending', 'redeeming') new_gifts = MAX(0, earned_gifts - pending_gifts) ``` 该公式是幂等的。它可以随时被调用而没有重复奖励的风险——因为礼物是基于总购买账本计算的,而不是基于增量。`redeeming` 状态充当悲观锁:已经进入兑换流程但尚未完全提交的礼物,将被计入待处理总数,以防止竞态条件。 ### 礼物兑换 — `redeem_gift()` 兑换流程在数据库事务内原子性地强制执行以下不变性: 1. **强制单次使用:** 礼物记录被选中并进行 `FOR UPDATE` (通过 `UPDATE ... WHERE status = 'pending'` 并检查 `rowCount() === 1`)。如果两个并发请求试图兑换同一个礼物,只有一个会成功。 2. **无并发活动会话:** 对活动(未过期、未作废)voucher 的检查可防止在另一个套餐仍在运行时激活礼物。用户必须等到当前会话过期。 3. **悲观锁状态:** 在创建 voucher 之前,礼物会立即过渡到 `status = 'redeeming'`。此点之后的任何失败都会使礼物保持锁定状态,这可以通过计划的清理任务来解决。 4. **积分扣除:** 成功兑换后,`total_purchases` 将精确减去 `loyalty_threshold`,消耗掉赚取的礼物。这确保下一个礼物周期能从剩余部分干净利落地开始。 5. **防火墙对账:** 提交后立即调用 `SessionManager::reconcileClientAccess()`,以将新的授权状态推送到内核。 ## 5. 本地云(离线内联网) 离线内联网作为独立进程 (`local_server/app.py`) 在端口 8090 上运行。所有连接的客户端(无论是否授权)都可以通过隔离区 (`walled-garden`) 的 `iptables` ACCEPT 规则 (`-p tcp --dport 8090 -j ACCEPT`) 访问它,该规则插入在 NAT `PREROUTING` 链的顶部,绕过所有 captive portal 重定向逻辑。这意味着用户无需购买任何上网时间即可浏览整个离线资料库。 ### 媒体中心 (VOD) 一个结构化的文件库,分为 5 个顶级类别和 22 个子类别: - **视频:** 电影、剧集、动漫、教程、YouTube 归档、短片 - **音频:** 古兰经、音乐、播客、有声读物 - **应用与游戏:** Android APK、PC 软件、游戏 - **图片:** 梗图、壁纸、设计图、常规照片 - **文档:** 书籍、学习资料、研究论文 文件通过支持 byte-range 的 FastAPI `StreamingResponse` 作为分块流式响应提供,从而实现原生 HTML5 视频和音频的进度拖拽,而无需完整下载文件。全局异步令牌桶限流器 (`_throttle()`) 将所有同时进行的文件流聚合上限限制为 1 MB/s,保护 Wi-Fi 半双工芯片免受 I/O 饱和的影响,同时保持 HTML 页面加载的即时性。 上传限流也在 ASGI 中间件层 (`UploadThrottleMiddleware`) 强制执行,它包装了 `receive` 可调用对象,以脉冲方式接收传入的数据块,而不是接受会导致事件循环停滞的突发上传。 ### 本地社交网络 一个功能齐全的社交平台,具有以下功能: - 用户注册、身份验证和个人资料管理(头像、个人简介、显示名称) - 带有文本和图像内容的动态信息流;实时点赞和评论系统 - 具有 24 小时可见性、观看追踪和点赞反应的快闻 - 通过 WebSocket (`ConnectionManager` 及广播) 进行实时群聊 - 用户通知系统(点赞、评论、关注、帖子互动) - 管理员审核面板:用户封禁、上传权限授予、内容管理 - 具有以 JSON 序列化的细粒度权限集的所有者角色系统 所有社交内容都存储在 `local_platform.db` (aiosqlite, WAL 模式) 中,与热点计费数据库完全隔离。 ### 内容管理 FastAPI 管理面板提供: - 实时硬件遥测仪表板(WebSocket 推送,2 秒刷新) - 文件管理器:多类别上传、内联媒体预览、删除 - USB/SD 存储模式切换,带有实时路径验证 - 用户管理:封禁、提升、授予大文件上传权限 - 带有分页功能的活动日志查看器 - 维护模式切换(阻止所有非管理员访问) ## 6. 数据层与安全架构 ### SQLite 配置 — 针对 Android eMMC 优化 两个数据库实例(hotspot 和本地平台)的配置完全相同,以确保在 Android 存储上的稳定性: ``` PRAGMA journal_mode = WAL; -- Concurrent readers + single writer PRAGMA busy_timeout = 15000; -- 15-second lock wait before error PRAGMA synchronous = NORMAL; -- Crash-safe without full fsync on every write PRAGMA temp_store = MEMORY; -- Avoid temp file creation on flash storage PRAGMA cache_size = -10000; -- 10 MB page cache PRAGMA mmap_size = 268435456; -- 256 MB memory-mapped I/O PRAGMA wal_autocheckpoint = 100; -- Checkpoint every ~400 KB to prevent WAL bloat ``` 存储窒息防护 (`disk_free_space() < 10MB`) 会在任何写入操作可能导致部分提交或 WAL 文件损坏之前,以 `503 Service Unavailable` 响应暂停数据库层。 ### 管理员身份验证 管理面板实现了一个经过强化的登录系统: - 密码存储为 `bcrypt` 哈希 (`PASSWORD_DEFAULT`,成本因子约为 11) - 登录时重新生成会话 token (`session_regenerate_id(true)`) - 会话在不活动 30 分钟后过期 (`SESSION_LIFETIME`) - 暴力破解防护:5 次失败尝试将触发由 `login_attempts` 表支持的 30 分钟 IP 锁定 - 锁定在 GET 和 POST 期间均被强制执行——登录表单在锁定期间完全隐藏,取而代之的是实时倒计时 - 过期锁定记录的被动清理在每次登录尝试时运行,增加了零后台开销 ### 防火墙安全不变性 - **设计上默认关闭:** 所有 iptables 链都使用捕获所有的 `REJECT --reject-with icmp-port-unreachable` 规则进行初始化。未授权流量将被拒绝 (REJECT) 而不是丢弃 (DROP)——这很重要,因为 DROP 会导致 OS captive portal 引擎超时并将网络标记为损坏,从而抑制 captive portal 通知。 - **HTTPS 强制设为 `tcp-reset`:** 对于未授权客户端,端口 443 被拒绝时会使用 TCP 重置 (而不是 ICMP),这会导致即时 TLS 失败,从而在所有现代 Android 和 iOS 版本上触发 OS captive portal HTTP 回退。 - **防网络共享 (TTL/HL 篡改):** `MANGLE` 链将出站的 TTL 归一化为 64,从而击败蜂窝网络基于 TTL 的热点共享检测。 - **在 AP 接口上完全禁用 IPv6:** 通过 `/proc/sys/net/ipv6/conf/{iface}/disable_ipv6` 抑制 IPv6,以防止客户端通过 IPv6 连接绕过 captive portal。保留原始内核状态并在关机时恢复。 ## 7. 部署与启动序列 系统通过单一入口点 `start.sh` 进行引导。启动序列具有严格的顺序: **阶段 1 — 存储向导:** 交互式或自动选择离线平台的存储后端。对内部、SD 卡(原始 + FUSE)、可采纳存储和 USB OTG 挂载点进行多轮扫描。 **阶段 1.5 — 带宽配置:** 交互式提示输入默认下载速度和突发储层容量。这些值被写入 `config_override.php`,以便它们在 PHP worker 重启后依然保留,而无需重新运行向导。 **阶段 2 — FastAPI 服务器启动:** `uvicorn` 通过 `setsid`(进程会话领导者)和 `nohup` 启动,使其免疫 shell 退出。该进程被授予 OOM 豁免权 (`oom_score_adj = -1000`),以防止 Android 的 Low Memory Killer 在内存紧张时将其驱逐。 **阶段 2.5 — APK 自动更新程序:** 后台 shell 循环每 24 小时轮询一次 GitHub Releases 以寻找新的 `app-release.apk`,并在成功时原子性地替换本地副本。 **阶段 3 — 热点监督器交接:** `exec bin/hotspot start` 完全替换 shell 进程,使 FastAPI 进程同级进程保持活动。然后监督器会: 1. 验证并配置网络接口 2. 附加默认关闭的防火墙 (`setup_fail_closed_firewall()`) 3. 启动具有 4 个 worker 的 PHP 内置服务器 4. 以 captive 和托管模式启动自定义 DNS 服务器 5. 启动 `ghost_radar.sh` 和异步防火墙 worker (`fw-worker.php`) 6. 进入主监控循环 **关机:** `SIGTERM`/`SIGINT` 触发 `cleanup_app_firewall_rules()`,该函数原子性地移除所有自定义链和钩子,恢复网络接口的 IPv6 状态,并清理 TC 带宽整形器——使内核保持在干净的状态。 ## 8. 截图画廊
Admin Login
Overview Dashboard
Live Monitoring
Financial Report
Customers
Vouchers
User Profile
Secondary Profile
Maintenance Mode
System Settings
Secondary Overview
*系统版本:`APP_DB_VERSION 2.1` — 架构文档源自对 `/root/wifi-4.5` 的源码审计。*
标签:Termux, 域名枚举, 安卓, 强制门户, 微型ISP, 本地云, 用户忠诚度, 网络基础设施, 逆向工具