Fork of dklasens/MU5250-OpenUI that adds a mihomo proxy manager (subscriptions, node selection, rule presets, PAC, LAN-wide transparent proxy via TUN with a mainland bypass that keeps domestic traffic on hardware offload) and control of as much of the device as the firmware allows: mobile data and monthly limit, guest Wi-Fi, per-device names/traffic/blocking, port forwarding, DMZ/UPnP, static DHCP, connection watchdog, sleep and scheduled reboot, carrier selection, SMS forwarding, and settings backup. The dashboard defaults to Chinese with an English switch. Verified on CN firmware
BD_CNMU5250V1.0.0B31.中文使用说明:docs/GUIDE.zh-CN.md
A custom control plane for the ZTE U60 Pro (MU5250) 5G modem: a Rust agent
running on the device exposes a JSON API (http://192.168.0.1:9090), and a
React dashboard served from the device (http://192.168.0.1:8080) turns it
into a full-featured modem management UI — plus tooling to unlock, provision
and update both.
Credit: based on jesther-ai/open-u60-pro.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Screenshots: demo data from the mock agent (web-app/tools/screenshots.mjs).
Upstream's English screenshots:
Browser ── HTTP/JSON ──► React dashboard (:8080, isolated uhttpd, /data/www.current)
│
│ bearer-token JSON API
▼
zte-agent (:9090, Rust, tiny_http thread pool)
│
┌───────────────┼────────────────────────┐
▼ ▼ ▼
ubus / uci AT ports sysfs / procfs
(wifi, router, (signal, SMS, (thermals, battery,
clients, WAN) cell/band lock) charge control)
- Agent (
agent/) — Rust HTTP backend, no async runtime, minimal deps (serde,tiny_http,sha2,libc). Talks to ubus/uci, AT ports, sysfs and device services. TTL caches decouple client poll rate from expensive subprocess reads, with bounded execution and output. Radio samples are shared with loggers; buffered writes and streamed CSV exports limit overhead. The charge-limit enforcer combinesubus listenevents with periodic policy reconciliation. Auth via bearer tokens with sliding 1 h expiry, rate-limited login, LAN-only bind. Destructive actions requireX-Confirm: true; the AT console is allowlisted to read-only commands. - Dashboard (
web-app/) — React 19 + Vite + Tailwind SPA served by the device itself. Lazy-loaded groups, light/dark theme, bottom tabs on phones / sidebar on desktop. A shared polling implementation provides in-memory caching, visibility-aware scheduling, non-overlapping requests and protection against obsolete responses after edits or navigation. Home uses a batched/api/dashboardrequest, with source freshness and collection errors surfaced in the interface. - Contract —
scripts/check-api-contract.pychecks route coverage across the agent, dashboard client and mock agent; regression tests cover selected response shapes and behavior.
| Group | What you get |
|---|---|
| Home | live signal, modem mode, throughput, battery, connection, device info and data usage from a single batched poll |
| Signal | per-carrier LTE/NR detail (PCI, ARFCN, RSRP/RSRQ/SINR), matching UL and Active/Idle indicators on desktop and mobile when reported, network mode, band lock, one-tap cell lock from live cells, manual carrier search and registration with a way back to automatic |
| Network | clients by Wi-Fi/USB-C/Ethernet with link details, per-device names, internet traffic and rates, Wi-Fi disconnect and a Wi-Fi block list; validated per-band Wi-Fi updates with rollback on observed failures and a guest network (password, time limit); LAN/DHCP changes with reconnection confirmation and automatic rollback, fixed IP addresses (static DHCP), DNS; port forwarding and mapping, UPnP, DMZ, remote management and WAN ping |
| Modem | mobile data on/off, manual APN profiles (add, edit, activate), data usage + reset day + monthly limit with alert, TTL clamping, SMS (inbox/sent, compose, delete) and SMS forwarding to Bark, Server酱, WeCom, Telegram or a webhook |
| Proxy | mihomo service control with live throughput and the route in use, subscription management (add/edit/update, usage and expiry from the provider, or the subscription's own full config with its groups and rules), node groups with latency tests and one-tap switching, Rule/Global/Direct modes, routing presets, PAC + manual proxy setup for devices, transparent proxy (TUN) for the whole LAN that survives reboots, a mainland bypass that keeps domestic traffic on hardware offload, its own NTP clock and a self-healing watchdog |
| System | thermals, battery health, reconciled charge control (stop/resume + limit enforcer), signal/connection loggers with CSV export, read-only AT console, on-demand process list, device/SIM info with PIN status and the router clock, guarded USB mode + powerbank transitions, device sleep, scheduled reboot, connection watchdog, settings backup and restore, power actions |
v2.3 also refreshes the home/login and Signal icons and browser favicon. The screenshots above are retained as an overview; minor artwork and status details may differ from the current release.
Details: docs/DASHBOARD.md (pages, source layout, local demo without hardware) and docs/AGENT.md (endpoint reference).
Release builds run Rust, dashboard and native-installer checks in GitHub Actions, including failure-injection tests for deployment and recovery. The v2.3 changes also passed a staged physical deployment with stock service, WAN, SSH and reboot checks. See docs/REMEDIATION.md for evidence and remaining hardware/platform limits. Firmware emulators and local test environments are not included in this repository or release.
Windows and macOS users can install, repair, or update the complete stack with
the native Open U60 Pro Installer from GitHub Releases. It has a guided
interface, bundles ADB, selects only compatible ZTE MU5250 devices, and requires
no terminal or language runtimes. Packages are available for macOS 15+ Apple Silicon
and Intel (.dmg / .app.zip) and Windows x64 (MSI, setup EXE or portable ZIP).
The installer downloads checksum-verified agent/dashboard assets; verified
offline bundles can also be reused. Windows may require a compatible USB driver
and the built-in OpenSSH Client. The v2.4 Mac apps are ad-hoc signed, not
Apple-notarized; Windows packages are unsigned. See installer/README.md.
For a locked modem, enter its router admin password and the backup-key suffix. The backup key/suffix is available in the upstream unlock discussion, issue #8. Use the suffix appropriate to the device firmware; v2.4 requires this input and does not bundle the key. The dashboard password is chosen separately during installation, with an optional six-digit PIN.
Start with Check device, then review the model, firmware and release before installing. Updates preserve existing dashboard passwords and PIN settings by default; changing either is explicit. The installer provides native folder browsing, an Open dashboard action and guided recovery after an interrupted deployment. See the v2.4 wireframes.
Deployment checks device identity, firmware, storage and artifacts before activation, retains recovery snapshots, and verifies key-only SSH access. Failed deployments attempt snapshot recovery; retain the reported recovery files until the installation has been checked.
For locked firmware, follow the compatibility guidance in docs/DEPLOYMENT.md. The staged unlock/deployment was tested on HK B04; this does not establish support for every later HK or CN release.
The source dashboard build requires Node.js ^20.19.0 || >=22.12.0 and npm;
deploy-dashboard.sh installs the locked dependencies with npm ci. The
native desktop installer uses prebuilt assets and does not require Node.js.
python3 scripts/zunlock.py --dry-run # validate backup preparation before unlocking
python3 scripts/zunlock.py # 1. unlock → adbd (config backup/restore route)
bash setup.sh # 2. download or build, then install the agent
bash scripts/zharden.sh # 3. SSH, rc.local cleanup, dashboard :8080, FOTA off
bash deploy-dashboard.sh # 4. build + push the web UI
bash scripts/deploy-mihomo.sh # 5. (optional) install the mihomo core for the Proxy pageFull instructions, requirements (backup-key suffix), updates and post-FOTA recovery: docs/DEPLOYMENT.md.
agent/ Rust agent (runs on the modem, port 9090)
web-app/ React dashboard (served from the modem, port 8080)
installer/ native macOS/Windows installer (Tauri + React)
process-runner/ shared bounded subprocess runner for agent and installer
scripts/ unlock + hardening + recon tooling
research/ quarantined exploit tools — see its README before touching
docs/ documentation (below)
setup.sh first-time provisioning (unlock + agent install)
deploy.sh agent updates over SSH
deploy-dashboard.sh dashboard build + push
scripts/deploy-mihomo.sh mihomo core + geodata install/update (verified)
zte-script-ng.js community-vetted reference of safe ubus calls
| Doc | Contents |
|---|---|
| docs/DEPLOYMENT.md | unlock, install, harden, update, post-FOTA recovery |
| installer/README.md | desktop installer, offline bundles, recovery and platform requirements |
| docs/releases/v2.4.md | v2.4 installer changes, downloads, validation and limitations |
| docs/INSTALLER-WIREFRAMES.md | publishable installer wireframes with sample data |
| docs/AGENT.md | agent architecture, endpoint reference, safety constraints |
| docs/DASHBOARD.md | dashboard pages, source layout, dev + local demo |
| docs/SAFETY.md | read first — brick-prevention rules, daemon sync barrier, recovery commands, safety audit |
| docs/reference/ | device reference material (rpcd ACL dump, USB mode findings) |
This device was bricked once by going beyond the sanctioned path. The rules
that keep it alive: shell/ssh/adb only — no boot hooks outside
/etc/rc.local, no system-service modifications, never disable a
zte_topsw_daemon.conf daemon via init.d, stay out of partitions, and treat
scripts/research/ as quarantined. Everything else — including what the
deploy path does and deliberately does not touch — is in
docs/SAFETY.md.
Dashboard/API traffic remains HTTP on the LAN; key-only SSH does not encrypt browser traffic. Physical Wi-Fi/LAN changes, USB/charger failure paths and all firmware variants have not been comprehensively tested. Recovery snapshots reduce deployment risk but cannot guarantee against device failure.
MIT. Derived in part from jesther-ai/open-u60-pro (MIT, Copyright (c) 2025-present Jesther Silvestre).
Exception: zte-script-ng.js is a community reference script licensed
separately under AGPLv3+ — see its header.
If this README and the code ever disagree:
agent/src/server.rs— HTTP routing tableagent/src/auth.rs— auth and token behaviorweb-app/src/App.tsx— navigation groups mounted in the UIweb-app/src/data/api.ts— client-side API bindings and payload shapes





