⚠️ For educational and research purposes only. Changing a device's IMEI may be illegal in your jurisdiction. The author does not encourage or endorse any use. You alone are responsible for your actions.
Fork of srlabs/blue-merle for the GL-E750 Mudi 4G travel router. Fixes upstream bugs, adds an Apple-device masquerade, and hardens every IMEI/identity code path.
- Target: firmware
4.3.26, MCU ≥1.0.7 - Package:
blue-merle_3.0.5-local(opkg name unchanged) - Usage:
USAGE.md - AI agents:
AGENTS.md - License: BSD-3-Clause
Download from Releases, verify the checksum, then:
scp -O blue-merle_3.0.5-local-*.ipk root@192.168.8.1:/tmp/
ssh root@192.168.8.1 'opkg update && opkg install --force-reinstall /tmp/blue-merle_*.ipk && reboot'opkg update is mandatory: package lists live in RAM and are wiped every
reboot — without it the python3-logging/python3-urllib deps fail to
resolve (pkg_hash_check_unresolved).
After reboot the WiFi name changes (e.g. GL-E750-a19 → Emma's iPhone).
Reconnect with the same password — it never rotates.
- No full IMEI/IMSI anywhere: masked in syslog, MCU, LuCI RPC and the generator's stderr (which is also dropped at non-interactive call sites); one canonical masked form per identifier class, fail-closed
/root/esim+/etc/oui-tertfon tmpfs — IMEI and the client-MAC database live in RAM only, wiped on poweroff- MAC generator always sets the U/L bit;
shred→rm(theatrical on NAND, pointless on tmpfs)
- Modem control:
AT+CFUN=1,1reset (wasAT+QPOWDpoweroff), serial reads loop until OK/ERROR, IMSI regex 14–15 digits (ITU-T E.212) - Entropy:
random.choices(no sampling fingerprint),_rand16from/proc/sys/kernel/random/uuid(busybox has nood) - One shared flock across CLI/toggle/LuCI; modem TTY probed via AT
- Fail-closed everywhere: bounded retry loops, errors → safe poweroff; stage1 persists originals for stage2; tmpfs mounts stop gl_clients first
- CLI refuses non-interactive stdin — a closed stdin used to answer "yes" to every prompt and end in an unattended poweroff
- Install/uninstall lifecycle:
postrmcommits UCI,prermstops services and unmounts tmpfs; dead Lua Luhn path removed
- Apple OUI pool (30 prefixes) + paired identity: one picked name →
SSID
<Name>'s iPhone, hostname<Name>s-iPhone(244 names) - TAC policy: module mode preserves the baseline modem TAC; phone mode is user-supplied, fail-closed (no guessed GSMA data shipped)
- Per-uplink MAC rotation on
ifdown; hotplug BSSID rotation;stable_identityflag freezes all identifiers across reboots blue-merle-newmac/blue-merle-newssidCLIs
97 unit tests (static privacy invariants + functional regressions):
python3 tests/run_all.pyRotating hostname/BSSID/SSID every boot defeats cross-location correlation; a real iPhone keeps them stable, so an observer may flag an "iPhone" that changes its name every reboot as anomalous. Default is unlinkability. To freeze identity:
uci set blue-merle.main.stable_identity=1 && uci commit blue-merle- DHCP fingerprinting — Linux DHCP client, not iOS.
- TLS fingerprinting — traffic carries the client's ClientHello.
- Traffic analysis — volume/timing/destinations visible to ISP.
- Physical seizure — RAM recoverable via cold-boot, flash via chip-off; physical destruction is the only countermeasure.
- Flash history — UCI commits may leave stale values in NAND erase blocks (volatile UCI overlay not enabled).
No feeds update needed — the package is plain files:
cd "$OPENWRT_SDK" # OpenWrt 23.05, ath79/nand
mkdir -p package/blue-merle
ln -s "$PWD/../blue-merle-fork"/{Makefile,files} package/blue-merle/
echo "CONFIG_SIGNED_PACKAGES=n" > .config
make defconfig
make -j"$(nproc)" package/blue-merle/compile V=s
# ipk: bin/packages/mips_24kc/base/Monero (XMR):
835zUaFETfmc3q5UtUCTvNUD8Z7mfPUztDYpN8bbq7PpUute1qGqDiHgGKENCHGP3YDKEmHmgdXLf4umLmfDyXjaDxcPkNf
Bitcoin (Lightning):
thefuzzstone@npub.cash
Ethereum (ETH)
0x5d16518610D401842327A5533eDa97511c94e754