{"id":49182266,"url":"https://github.com/franckferman/red-merle","last_synced_at":"2026-04-23T02:01:12.985Z","repository":{"id":347877685,"uuid":"1195243590","full_name":"franckferman/red-merle","owner":"franckferman","description":"Reducing your Cellular Footprint.","archived":false,"fork":false,"pushed_at":"2026-04-14T13:28:33.000Z","size":1759,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"stable","last_synced_at":"2026-04-14T13:29:29.050Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://franckferman.github.io/red-merle/","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/franckferman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-29T12:29:14.000Z","updated_at":"2026-04-14T13:28:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/franckferman/red-merle","commit_stats":null,"previous_names":["franckferman/red-merle"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/franckferman/red-merle","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/franckferman%2Fred-merle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/franckferman%2Fred-merle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/franckferman%2Fred-merle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/franckferman%2Fred-merle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/franckferman","download_url":"https://codeload.github.com/franckferman/red-merle/tar.gz/refs/heads/stable","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/franckferman%2Fred-merle/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32162611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T17:06:48.269Z","status":"online","status_checked_at":"2026-04-23T02:00:06.710Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-23T02:01:11.751Z","updated_at":"2026-04-23T02:01:12.967Z","avatar_url":"https://github.com/franckferman.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# red-merle\n\nThe *red-merle* software package enhances anonymity and reduces forensic traceability of the **GL-E750 / Mudi 4G mobile wi-fi router (\"Mudi router\")**. It is a fork of [blue-merle](https://github.com/srlabs/blue-merle) by SRLabs with additional features and continued maintenance.\n\n*red-merle* addresses the traceability drawbacks of the Mudi router by adding the following features:\n\n1. Mobile Equipment Identity (IMEI) changer (random, deterministic or static)\n2. Media Access Control (MAC) address log wiper\n3. Basic Service Set Identifier (BSSID) randomization\n4. WAN MAC address randomization\n\n## Threat model\n\n*red-merle*'s protections are layered. Their relevance depends on who you are defending against:\n\n**Carrier-level analytics** (the most common threat for journalists and activists): carriers log which IMEI connects to which cell tower, on which frequency band, at what time. An analyst searching for spoofed IMEIs can filter by:\n1. Known blue-merle TAC prefixes (16 fixed values, public on GitHub)\n2. Frequency band mismatch between the TAC's expected device and the actual connection\n3. Serial number digit patterns (no repeated digits = statistical anomaly)\n\n*red-merle* defeats all three filters: band-aligned TACs, expanded prefix pool (24+ per modem variant), and corrected serial entropy.\n\n**Device seizure** (law enforcement, border crossing, theft): without log wiping, `logread | grep merle` on a seized Mudi reveals the complete IMEI change history with timestamps. *red-merle* wipes system logs at boot, after each IMEI change, and at shutdown, leaving no forensic trace of past identities.\n\n**Silent carrier geolocation** (intelligence services, lawful interception): carriers can request GPS coordinates from the modem via LPP/SUPL/RRLP without any user-visible indication. *red-merle* disables this at every boot.\n\n**Retrospective network analysis** (the hardest to defend against): an adversary with months of carrier logs can correlate sessions by timing, cell tower patterns, and traffic fingerprints even across IMEI changes. *red-merle* mitigates some of this (DNS flush, MAC randomization) but cannot fully prevent time-based correlation. The standard advice remains: **change your IMEI, change your SIM, and change your location before reconnecting**.\n\n## Hardening modes and security paradoxes\n\n*red-merle* offers two distinct operational modes that represent different philosophies in privacy protection: **anonymity through uniformity** versus **security through attack surface reduction**.\n\n### The fundamental paradox\n\nModern privacy tools face a classic dilemma: the more secure you make your device, the more identifiable it becomes. This creates a trade-off between **individual security** and **population-level anonymity**.\n\n```\nNormal user population (50M subscribers):\n[VoLTE: ON] [SUPL: ON] [OMA-DM: ON] [Bands: 4G/3G/2G]\n\nHardened red-merle user:\n[VoLTE: OFF] [SUPL: OFF] [OMA-DM: OFF] [Bands: 4G only]\n= Unique network signature detectable by carrier analysis\n```\n\n### Stealth mode: Invisible protection\n\n**Philosophy**: Blend in with the normal user population while applying network-level protections.\n\n| Protection | Carrier visibility | Effectiveness |\n|------------|-------------------|---------------|\n| iptables blocking (SUPL/OMA-DM ports) | ❌ Invisible | ✅ Blocks tracking requests |\n| MAC randomization | ❌ Local only | ✅ Prevents WiFi correlation |\n| Log sanitization | ❌ Device-local | ✅ Prevents forensic recovery |\n| AT command modifications | ❌ **None applied** | ❌ Modem features remain active |\n\n**Advantages**:\n- Indistinguishable from normal users in carrier logs\n- No technical profiling risk (\"this user knows about privacy tools\")\n- Optimal against mass surveillance and bulk collection\n- Safe for use in authoritarian contexts where technical sophistication is flagged\n\n**Trade-offs**:\n- GPS/SUPL requests still reach the modem (blocked at network layer)\n- IMS/VoLTE metadata collection continues\n- Vulnerable to sophisticated modem-level positioning requests\n- Partial protection against IMSI catchers (no 4G-only enforcement)\n\n### Hardening mode: Maximum protection\n\n**Philosophy**: Disable all tracking capabilities at the modem level, accepting network-level detectability.\n\n| Protection | Carrier visibility | Effectiveness |\n|------------|-------------------|---------------|\n| All stealth protections | ❌ Invisible | ✅ Same as stealth |\n| GPS/SUPL AT commands | ✅ **Highly visible** | ✅ Complete modem-level blocking |\n| IMS/VoLTE disabling | ✅ **Visible** | ✅ Prevents metadata collection |\n| 4G-only enforcement | ✅ **Visible** | ✅ Blocks IMSI catcher downgrade attacks |\n| Dynamic modem detection | ❌ Invisible | ✅ Optimized per hardware variant |\n\n**Advantages**:\n- Maximum attack surface reduction\n- Complete protection against silent positioning\n- Resistance to IMSI catchers and 2G/3G vulnerabilities\n- Optimal for targeted threats and known surveillance\n\n**Trade-offs**:\n- Creates unique \"privacy-conscious user\" network signature\n- Correlatable with other red-merle users through behavioral analysis\n- May trigger additional scrutiny from sophisticated adversaries\n- Potentially counterproductive in mass surveillance contexts\n\n### Decision framework\n\n### Critical decision framework\n\n**The choice between modes cannot be solved universally**. It requires personal risk assessment based on your specific context, adversaries, and acceptable trade-offs.\n\n**Core question**: *Do I gain MORE from protecting against specific documented attack vectors (accepting detectability) or from temporarily blending with normal users (buying time before pattern recognition)?*\n\n**Critical clarification**: \"Maximum protection\" does NOT mean comprehensive security. Hardening mode only blocks a specific set of known carrier-level tracking methods. It does not protect against:\n- Zero-day exploits in modem firmware\n- Advanced persistent threats with unknown capabilities  \n- Sophisticated correlation attacks using other data sources\n- Physical surveillance or device compromise\n- Social engineering or operational security failures\n\nThe question is really: *\"Are the specific GPS/SUPL/IMS protections worth the increased detectability risk in MY situation?\"*\n\n#### Stealth mode considerations\n\n**When stealth may be optimal**:\n- Mass surveillance is your primary concern\n- You want to avoid technical profiling (\"person of interest\")\n- Your adversaries lack sophisticated individual targeting capabilities\n- Privacy tool usage itself creates suspicion in your environment\n- You're not currently under active investigation\n\n**Stealth mode trade-offs**:\n- ✅ **Invisible** to carrier behavioral analysis (initially)\n- ✅ **Buys time** by blending with millions of similar profiles\n- ✅ **No immediate escalation** of surveillance attention\n- ❌ **Temporary protection** - pattern recognition will eventually identify you\n- ❌ **Human behavioral patterns** - timing, locations, usage create unique signatures\n- ❌ **False security** - \"indistinguishable\" is temporary, not permanent\n- ❌ **Sophisticated correlation** - enough data points will reveal patterns regardless of mode\n\n#### Hardening mode considerations\n\n**When hardening may be optimal**:\n- You face technical threats requiring protection against specific GPS/SUPL vectors\n- You want to block carrier-initiated positioning requests (but NOT triangulation)\n- You've detected active targeting (IMSI catchers, forced downgrades)\n- Your technical sophistication is already known/assumed\n- Physical safety outweighs operational security concerns\n\n**Hardening mode trade-offs**:\n- ✅ **Specific vector protection** - blocks GPS/SUPL/IMS/OMA-DM tracking\n- ✅ **Documented attack resistance** - prevents known carrier positioning methods\n- ✅ **IMSI catcher mitigation** - 4G-only enforcement\n- ⚠️ **Limited scope** - only protects against documented, AT-command-controllable vectors\n- ❌ **Highly detectable** signature (\"privacy-conscious user\")\n- ❌ **Population correlation** - linkable with other red-merle users  \n- ❌ **Attention escalation** - may trigger enhanced surveillance\n- ❌ **False security** - may feel more protected than you actually are\n\n**What hardening does NOT protect against**:\n- **Cell tower triangulation** - inherent to cellular network operation, unavoidable\n- **Timing-based positioning** - signal timing between towers reveals location\n- **Network registration location** - carrier knows which cell towers you connect to\n- Modem firmware vulnerabilities or backdoors\n- Zero-day exploits in baseband processors\n- Advanced correlation using cell tower timing/patterns\n- Side-channel attacks through power consumption or RF signatures\n- Social engineering, physical surveillance, or device seizure\n- Unknown positioning methods not controllable via AT commands\n\n**Critical location reality**: As long as your device connects to cellular networks, your approximate location is known to the carrier through basic network operation. Hardening mode only prevents **additional GPS-precision positioning requests** - it cannot hide that you're connected to specific cell towers.\n\n#### The personal calculation\n\n**Questions to ask yourself**:\n\n1. **Threat sophistication**: Can my adversaries already identify me through other means?\n2. **Current exposure**: Do they already know I use privacy tools?\n3. **Detection consequences**: What happens if I'm flagged as \"technical\"?\n4. **Protection value**: How much does GPS/SUPL blocking actually help my situation?\n5. **Time horizon**: Am I defending against immediate or long-term threats?\n6. **Alternative measures**: Do I have other privacy layers (VPN, Tor, burner devices)?\n\n**Example scenarios**:\n\n- *Journalist in authoritarian country*: Stealth may be better - being identified as \"technical\" could trigger investigation\n- *Activist under active surveillance*: Hardening may be better - they already know you're a target\n- *General privacy user*: Stealth usually optimal - mass surveillance is the main threat\n- *High-value target with physical threats*: Hardening may be necessary despite detectability\n\n**Switch dynamically**:\n```sh\n# Default: invisible protection\nred-merle-mode-switch stealth\n\n# Escalate when threats become targeted\nred-merle-mode-switch hardening\n\n# Return to stealth when context changes\nred-merle-mode-switch stealth\n```\n\n### The adoption paradox\n\nThe effectiveness of each mode depends on **population-level adoption patterns**:\n\n| User base size | Hardening mode detectability | Stealth mode necessity |\n|----------------|------------------------------|------------------------|\n| \u003c1,000 users | Highly detectable signature | Essential for most users |\n| 1K-100K users | Detectable but with noise | Recommended default |\n| 1M+ users | Statistical background | Stealth becomes optional |\n| Mainstream adoption | New \"normal\" baseline | Hardening becomes default |\n\n**Current reality (2024)**: *red-merle* has a small, technical user base. Hardening mode creates a detectable signature that could be used to profile privacy-conscious users. This may change as adoption scales.\n\n**Strategic implications**:\n- **Individual users** should default to stealth mode unless facing specific technical threats\n- **Community growth** benefits everyone by diluting hardening mode signatures\n- **Long-term** success depends on making privacy protection indistinguishable from normal usage\n\n### Honest assessment: No perfect choices\n\n**Both modes involve fundamental trade-offs with no universally correct answer.**\n\n#### Stealth mode reality check\n\n**What it actually provides**:\n- Protection against mass automated collection\n- Invisibility in bulk carrier analytics  \n- Reduced risk of technical profiling\n\n**What it cannot prevent**:\n- Sophisticated individual targeting with time and resources\n- Advanced correlation techniques by capable adversaries\n- Collection via unknown modem vulnerabilities or backdoors\n- Eventual detection if you become a high-value target\n\n**The bet you're making**: *\"Staying invisible is more valuable than maximum protection because my adversaries primarily use bulk collection methods.\"*\n\n#### Hardening mode reality check\n\n**What it actually provides**:\n- Maximum protection against known attack vectors\n- Modem-level blocking of GPS and positioning requests\n- Resistance to downgrade attacks and IMSI catchers\n\n**What it cannot prevent**:\n- Detection as a \"privacy-conscious user\" by carrier analysis\n- Correlation with other red-merle users through behavioral signatures\n- Enhanced surveillance attention due to technical profile\n- Collection via attack vectors not addressed by AT commands\n\n**The bet you're making**: *\"Maximum protection is worth the increased detectability risk because I face sophisticated technical threats.\"*\n\n#### The uncomfortable truth\n\n**Neither mode guarantees safety.** Privacy is a process, not a product. Both approaches can fail:\n\n- **Stealth can fail** when adversaries have time, resources, and individual focus\n- **Hardening can fail** when being identified as \"technical\" creates more risk than protection provides\n- **Both can fail** against adversaries with capabilities beyond documented protocols\n\n#### Risk acceptance framework\n\nRather than asking *\"Which mode is better?\"*, ask:\n\n1. **What am I trying to prevent?** (Mass collection vs targeted attacks vs physical threats)\n2. **Who are my adversaries?** (Automated systems vs human analysts vs state actors) \n3. **What are their likely capabilities?** (Bulk analysis vs individual targeting vs advanced techniques)\n4. **What happens if I'm detected?** (Inconvenience vs investigation vs physical danger)\n5. **What other protections do I have?** (VPN, Tor, burner devices, operational security)\n6. **How sophisticated are my likely adversaries?** (Automated systems vs dedicated analysts vs nation-states)\n7. **Am I worth the cost of advanced techniques?** (Mass target vs high-value individual)\n\n#### The sophistication spectrum\n\n**Different adversaries have different capabilities and cost thresholds**:\n\n**Mass surveillance systems** (low cost per target):\n- Automated carrier analytics and bulk data collection\n- Pattern matching against known privacy tool signatures\n- **Hardening blocks**: Standard GPS/SUPL requests\n- **Hardening doesn't block**: Advanced correlation, unknown collection methods\n\n**Dedicated human analysts** (medium cost per target):\n- Individual behavioral analysis and correlation\n- Time-intensive investigation of specific targets  \n- **Hardening blocks**: Quick technical collection methods\n- **Hardening doesn't block**: Patient correlation analysis, alternative data sources\n\n**Advanced persistent threats** (high cost per target):\n- Zero-day exploits, custom malware, physical operations\n- Sophisticated techniques not in public documentation\n- **Hardening blocks**: Basic documented collection vectors\n- **Hardening doesn't block**: Custom exploits, advanced persistent access\n\n#### Realistic threat assessment\n\n**Ask yourself honestly**:\n- *\"Am I interesting enough for them to deploy expensive, sophisticated techniques?\"*\n- *\"Or will they move on to easier targets if basic collection fails?\"*\n- *\"Does blocking GPS/SUPL actually matter if they can correlate my location through cell tower timing?\"*\n\n#### The human pattern problem\n\n**Fundamental truth**: You are human, and humans create patterns. No technical solution can eliminate this.\n\n**Inevitable pattern sources**:\n- **Temporal**: When you connect, how long sessions last, sleep schedules\n- **Geographic**: Where you connect from, travel routes, location clusters  \n- **Behavioral**: Data usage patterns, website visits, communication timing\n- **Operational**: How you change SIMs, timing of IMEI changes, device reboot patterns\n\n**Both stealth AND hardening modes are vulnerable** to long-term pattern analysis:\n- Stealth mode: Patterns emerge through correlation of \"normal\" behavior\n- Hardening mode: Patterns emerge through correlation of technical signatures + behavior\n\n**The goal is buying time, not permanent invisibility**:\n- Stealth mode: Delays detection by hiding in normal population noise\n- Hardening mode: Reduces specific data collection but creates immediate technical signature\n\n**Minimize patterns where possible**:\n- Vary timing, locations, usage patterns\n- Use operational security practices\n- Change behavior regularly\n- But accept that perfect pattern elimination is impossible\n\n**Reality check**: No matter which mode you choose, a sufficiently motivated adversary with enough time and data will eventually identify patterns that reveal your identity. Technology buys time and increases cost for attackers, but cannot solve the fundamental problem that humans have predictable behaviors.\n\n**The decision is ultimately about risk tolerance, time horizons, and realistic threat assessment - not achieving perfect anonymity.**\n\n### Practical guidance\n\n**Default recommendation**: Start with stealth mode for most users, as mass surveillance affects more people than targeted attacks. However, **you must evaluate your own situation**.\n\n**Dynamic approach**: The optimal choice can change based on circumstances:\n```sh\n# Start with stealth for normal operations\nred-merle-mode-switch stealth\n\n# Escalate during high-risk periods\nred-merle-mode-switch hardening  \n\n# Return to stealth when context changes\nred-merle-mode-switch stealth\n```\n\n**Combined with operational security**: Technology alone is insufficient. The most effective privacy strategy layers multiple protections:\n\n- **Technical**: Device hardening (red-merle) + network protection (VPN/Tor)\n- **Operational**: Change IMEI + change SIM + change physical location\n- **Behavioral**: Vary timing, routes, and communication patterns\n- **Compartmental**: Separate devices/identities for different activities\n\n**Final reality check**: Perfect privacy doesn't exist. The goal is raising the cost of surveillance to a level that exceeds the value of targeting you specifically. Both modes contribute to this goal through different mechanisms, and the choice depends on your personal risk assessment.\n\n## Compatibility\n\nVerified with GL-E750 Mudi firmware version **4.3.26**. Firmware versions 4.x should work but are not tested and will display a warning during installation.\n\n### Dependencies\n\n- `luci-base`\n- `gl-sdk4-mcu`\n- `coreutils-shred`\n- `python3-pyserial`\n\n## Installation\n\n### Online install\n\nThe online install method requires an **active Internet connection** on your Mudi to download dependencies.\n\nDownload the [latest `.ipk` release](https://github.com/franckferman/red-merle/releases/latest) and copy it onto your Mudi (e.g. via `scp`), preferably into `/tmp`. Then install:\n\n```sh\nscp red-merle_*.ipk root@192.168.8.1:/tmp/\nssh root@192.168.8.1\n\nopkg update\nopkg install /tmp/red-merle*.ipk\n```\n\nTo upgrade, download the newest `.ipk` and reinstall:\n\n```sh\nopkg install --force-reinstall /tmp/red-merle*.ipk\n```\n\n### Offline install\n\nThe offline install method does **not need an active Internet connection** on your Mudi.\n\nDownload the [latest offline release package](https://github.com/franckferman/red-merle/releases/latest) (the `_offline_install.zip` file), then:\n\n```sh\n# On your computer (connected to the Mudi via WiFi / LAN)\nunzip red-merle_offline_install.zip\n\n# Copy the offline package to your Mudi\n# -O might be needed due to the SSH daemon used by the Mudi\nscp -O -r red-merle_offline_install root@192.168.8.1:/tmp\n\n# Connect to Mudi via SSH\nssh root@192.168.8.1\n\n# Install dependencies and red-merle\ncd /tmp/red-merle_offline_install\n./install.sh\n```\n\n### Quick build \u0026 install (no SDK)\n\nIf you prefer to build from source:\n\n```sh\ngit clone https://github.com/franckferman/red-merle.git\ncd red-merle\n\n# Build the .ipk locally\n./build.sh\n\n# Deploy to Mudi via SSH (default IP: 192.168.8.1)\n./build.sh install\n\n# Or specify a custom IP\nMUDI_IP=10.0.0.1 ./build.sh install\n```\n\n### SDK build (same as CI)\n\n```sh\n./build.sh sdk-build\n```\n\nThis downloads the OpenWrt 23.05.0 SDK for ath79/nand (~200MB) and builds the package exactly like the CI pipeline does.\n\n## Usage\n\nYou may initiate an IMEI update in three different ways:\n\n1. **CLI**: via SSH on the command line\n2. **Toggle**: using the Mudi's physical toggle switch\n3. **Web**: via the LuCI web interface\n\n### CLI\n\nConnect to the device via SSH, then execute:\n\n```sh\nred-merle\n```\n\nThe command guides you through the process of **changing your SIM card**. It supports three IMEI modes:\n\n- **Random** (`-r`): generates a fully random IMEI\n- **Deterministic** (`-d`): generates a pseudo-random IMEI seeded by the inserted SIM's IMSI (same IMSI always produces the same IMEI, regardless of the device)\n- **Static** (`-s`): sets a user-provided IMEI (validated with Luhn checksum)\n\nWe advise you to **reboot the device** and **change location** after changing the IMEI.\n\n### Toggle\n\nThis is a two-stage process using the Mudi's physical switch.\n\n**Stage 1**: Flip the switch. The modem radio is disabled, a temporary random IMEI is set (preventing your old IMEI from being seen with the new SIM), and the display prompts you to **replace the SIM card**.\n\n**Stage 2**: After swapping the SIM, flip the switch again. The modem reads the new IMSI, a final random IMEI is set, and the device **powers off** automatically. **Change location** before booting again.\n\nA 60-second rate limit prevents accidental rapid toggles.\n\n### Web\n\nOpen the LuCI interface from `System` \u003e `Advanced Settings`. Find the `Red Merle` settings under the `Network` tab. The interface displays the current IMEI and IMSI and provides a **\"SIM swap...\"** button.\n\n**Shutdown the device** once the process is complete, **swap your SIM card** and **change location** before booting again.\n\n## What it does at boot\n\nOn every boot, *red-merle* automatically performs the following (before network comes up):\n\n| Action | Purpose |\n|---|---|\n| Log wipe | Clears syslog, dmesg, shell history and tmp logs left over from the previous session (protects against crash or abrupt shutdown before post-IMEI-change wipe could run) |\n| BSSID randomization | New random MAC for both WiFi interfaces (2.4 + 5 GHz), defeating WiFi geolocation databases (WiGLE, Google, Apple) |\n| WAN MAC randomization | New random MAC for the upstream-facing interface, preventing session correlation across locations |\n| Carrier GPS disable | Sends AT commands to refuse silent LPP/SUPL/RRLP positioning requests from the carrier. Re-applied every boot because the setting is non-persistent on some Quectel firmware versions |\n| Client database volatility | The `/etc/oui-tertf` client database is shredded and replaced with a tmpfs mount. Connected device history is kept in RAM only and lost on reboot |\n\n## Building\n\nThis repository contains a CI workflow (`.github/workflows/ci.yml`) that auto-builds the `.ipk` using the OpenWrt 23.05.0 SDK on every push.\n\nYou can also build locally:\n\n```sh\n# Quick build (no SDK, creates a generic .ipk)\n./build.sh\n\n# Full SDK build (same as CI, creates an architecture-specific .ipk)\n./build.sh sdk-build\n\n# Clean build artifacts\n./build.sh clean\n```\n\nOr set up a full OpenWrt development environment:\n\n```sh\ngit clone https://github.com/openwrt/openwrt\ncd openwrt\ngit clone https://github.com/franckferman/red-merle package/red-merle\n./scripts/feeds update -a \u0026\u0026 ./scripts/feeds install -a\nmake distclean \u0026\u0026 make clean\nmake menuconfig\n    # Target System: Atheros ATH79\n    # Subtarget: Generic Devices with NAND flash\n    # Target Profile: GL.iNet GL-E750\n    # In Utilities, select \u003cM\u003e for red-merle\n    # Save\nmake package/red-merle/compile\n```\n\nThe package will be in `./bin/packages/mips_24kc/base/`.\n\n## Implementation details\n\n### IMEI randomization\n\nAn IMEI (International Mobile Equipment Identity) is a 15-digit identifier structured as:\n\n```\n[TAC: 8 digits][Serial: 6 digits][Luhn check: 1 digit]\n```\n\n- **TAC** (Type Allocation Code): assigned by the GSMA, identifies manufacturer + model + hardware revision. Carriers maintain TAC databases with per-device metadata including supported frequency bands.\n- **Serial**: 6 digits assigned by the manufacturer, typically sequential.\n- **Luhn check digit**: deterministic checksum computed from the first 14 digits using the [Luhn algorithm](https://en.wikipedia.org/wiki/Luhn_algorithm).\n\nThe Mudi router's baseband is a Quectel EP06-E/A (V1) or EM060K-GL (V2) LTE module. The IMEI is changed via the AT command `AT+EGMR=1,7,\"\u003cIMEI\u003e\"` sent over serial (`/dev/ttyUSB3` at 9600 baud).\n\n#### TAC prefix selection and frequency band alignment\n\n**The problem with blue-merle:** blue-merle uses 16 hardcoded TAC prefixes corresponding to consumer phones (Samsung, Apple, etc.) whose LTE band profiles do not match the Mudi's modem. The EP06-E connects on TDD bands B38/B40/B41 that many of those phones do not support. A carrier cross-referencing the IMEI's TAC (which maps to a specific phone model) against the actual bands used for the connection can detect the mismatch.\n\nThis is documented in [blue-merle Issue #1](https://github.com/srlabs/blue-merle/issues/1), open since the project's creation. [PR #71](https://github.com/srlabs/blue-merle/pull/71) attempted to fix this by aligning TACs to the EM05-G module's frequency bands, but was closed without being merged. The issue has remained unresolved for over 4 years.\n\nThis likely happened because blue-merle originated as a security research proof-of-concept by SRLabs (published alongside an academic paper in 2022). The primary goal was to demonstrate that the Mudi's IMEI could be changed via AT commands, not to build a hardened OPSEC tool. The TAC prefixes were chosen to produce Luhn-valid IMEIs accepted by carriers, without verifying frequency band alignment. Band-level fingerprinting resistance is a concern that arises when defending against a real adversary with carrier-level access, not when writing a conference paper.\n\n**red-merle's approach:** TAC prefixes are curated per modem variant. The function `detect_modem_prefixes()` sends `AT+CGMM` to the modem via serial at startup. The modem responds with its model identifier (e.g. \"EP06-E\" or \"EM060K-GL\"), and the script automatically selects the matching TAC list. The user does not need to configure anything.\n\nTwo separate lists are maintained:\n\n- **EP06-E** (Mudi V1, EMEA bands B1/B3/B5/B7/B8/B20/B28/B32/B38/B40/B41): 24 TACs from devices whose band profile is a superset:\n  - 5 MiFi/hotspots (Huawei E5787, E5885, E5788, Netgear Nighthawk M1/M2) - same device class as the Mudi, producing the least suspicious network profile (data-only, no voice/SMS)\n  - 7 Samsung Galaxy A series global variants (A52, A33, A34, A53, A54) - tens of millions of units in circulation on European networks\n  - 3 Samsung Galaxy S series global variants (S21, S22, S23)\n  - 5 iPhones, international models (iPhone 12 through 15, A2xxx model numbers)\n  - 4 Xiaomi global variants (12 Pro, Redmi Note 11/12 Pro, 13)\n\n- **EM060K-GL** (Mudi V2, global bands): 25 TACs. The EM060K-GL's broad band support means most modern flagships qualify. The list includes US-market devices (Samsung US, iPhone US, Google Pixel) whose band profiles are the widest available, plus 5G hotspots (Netgear M5, Inseego M2000) and the same global devices from the EP06-E list.\n\nIf the modem is not recognized, the EP06-E list is used as a safe default.\n\n#### Serial number generation and entropy analysis\n\nAll entropy in a generated IMEI resides in the 6-digit serial portion. The TAC is selected from a fixed list, and the Luhn digit is deterministic. The quality of the serial generation directly determines how distinguishable synthetic IMEIs are from legitimate ones.\n\n**blue-merle uses `random.sample(string.digits, 6)`** - sampling *without replacement* from {0,1,...,9}. Think of it as drawing from a bag of marbles: you pull one out, it is gone from the bag, and you cannot draw it again. This is a partial permutation (arrangement):\n\n```\nA(n,k) = n! / (n-k)! = 10! / 4! = 151,200 possible outputs\n```\n\nThe critical property: every generated serial has **all distinct digits**. \"370591\" is possible; \"373593\" is not, because \"3\" cannot be drawn twice.\n\n**red-merle uses `random.choices(string.digits, k=6)`** - sampling *with replacement*. Think of it as rolling a 10-sided die: each roll is independent, and the same number can come up any number of times. \"373593\" is now possible, just like on real IMEIs.\n\n```\n|Omega| = n^k = 10^6 = 1,000,000 possible outputs\n```\n\nThe entropy difference:\n\n```\nH_old  = log2(151,200) = 17.2 bits\nH_new  = log2(1,000,000) = 19.9 bits\nGain: +2.7 bits (6.6x larger keyspace)\n```\n\n**Why this matters for detection:**\n\nThe probability that a uniformly random 6-digit number has no repeated digits is:\n\n```\nP(no repetition) = A(10,6) / 10^6 = 151,200 / 1,000,000 = 0.1512\n```\n\nIn a legitimate IMEI population, roughly 15% of serials happen to have no repetitions. With blue-merle, **100%** of generated serials have no repetitions.\n\nAn analyst with access to a carrier EIR (Equipment Identity Register) or GSMA IMEI database can apply a simple statistical test:\n\n```\nH0: IMEI is legitimate (serial digits uniformly distributed)\nH1: IMEI is generated by blue-merle (no digit repetition, ever)\n\nP(N out of N without repetition | H0) = 0.1512^N\n```\n\n| Observations (N) | P-value under H0 | Conclusion |\n|---|---|---|\n| 1 | 0.1512 | Inconclusive |\n| 3 | 0.00345 | Suspicious (p \u003c 0.5%) |\n| 5 | 0.0000784 | Detected (p \u003c 0.01%) |\n| 10 | 6.1 x 10^-9 | Certain |\n\nWith just 5 observed IMEIs sharing a blue-merle TAC prefix, the analyst rejects H0 at \u003e99.99% confidence. Combined with other signals (data-only behavior, band mismatch), even a single IMEI becomes highly suspect.\n\nWith `random.choices`, ~85% of red-merle IMEIs contain repeated digits, matching the expected distribution. The repetition-based test no longer discriminates.\n\n**Remaining limitations:** manufacturers assign serials sequentially (counters), not randomly. A truly exhaustive analysis comparing generated serials against known allocation ranges could still detect synthetic IMEIs, but this requires access to the proprietary GSMA TAC/serial database and is not a standard carrier operation.\n\n#### IMEI leak prevention during SIM swap\n\nTo prevent IMEI leakage during SIM swap, the modem radio is disabled (`AT+CFUN=4`) before the SIM is removed, and a temporary random IMEI is set immediately. The final IMEI is only written after the new SIM is inserted and its IMSI is read.\n\n![Figure 1. The router's radio is turned off and the IMEI is randomized between entries 70 and 80.](./IMEI%20randomization.png)\n\n### Carrier GPS tracking protection\n\nThe Quectel modem's AGPS (Assisted GPS) is **enabled by default** out of the factory. The modem does not broadcast GPS continuously on its own, but when the carrier sends a positioning request via LPP (LTE Positioning Protocol), SUPL (Secure User Plane Location), or RRLP (Radio Resource LCS Protocol), the modem **responds automatically** with GPS coordinates. This exchange happens between the carrier and the baseband, with no notification or consent prompt visible to the user.\n\nCarriers use this for:\n- Emergency calls (E911/E112 legal obligations)\n- Law enforcement location requests (lawful interception)\n- Network optimization (subscriber density mapping)\n\nGL.iNet does not disable this because the Mudi is marketed as a consumer router, not a privacy tool. blue-merle does not address it either.\n\n*red-merle* disables assisted positioning at boot and after each IMEI change via AT commands:\n\n```\nAT+QGPSCFG=\"agpsposmode\",0    # Refuse carrier positioning requests\nAT+QGPSCFG=\"gpsnmeatype\",0    # Disable NMEA sentence output\nAT+QGPSCFG=\"suplver\",0        # Disable SUPL protocol\n```\n\nThese settings are non-persistent on some Quectel firmware versions (reset after modem power cycle), which is why *red-merle* re-applies them at every boot.\n\n### Log sanitization\n\nblue-merle writes IMEI changes in cleartext to syslog via `logger`:\n\n```\nred-merle-toggle: Changed IMEI from 352609114567893 to 354553127891234\nred-merle-toggle: Finished with Stage 2\n```\n\nOn OpenWrt, syslog persists in the `logd` ring buffer (readable via `logread`) and on some configurations writes to flash (`/var/log/messages`). A device seizure followed by `logread | grep merle` reveals the full IMEI change history with timestamps.\n\n*red-merle* removes these `logger` calls entirely and performs a full log wipe at three points in the device lifecycle:\n\n**At boot** (clears traces from a previous session that may have survived a crash or abrupt shutdown):\n- Syslog ring buffer (`/etc/init.d/log restart`)\n- Kernel ring buffer (`dmesg -c`)\n- Shell command history (`/root/.ash_history` - contains `red-merle` commands, AT commands typed in SSH)\n- Temporary log files (`/tmp/log/*`)\n\n**After each IMEI change** (same wipe, plus eSIM logs):\n- All of the above\n- eSIM logs (`/root/esim/log.txt`)\n\n**At shutdown** (ensures the device is clean if it never boots again, e.g. seizure while powered off):\n- All of the above\n\n### BSSID randomization\n\nOn each boot, *red-merle* generates a valid unicast MAC address and overrides the current BSSID for both `wlan0` and `wlan1` via OpenWrt UCI commands. WiFi is restarted to apply the change.\n\n### WAN MAC randomization\n\nA random MAC is generated and applied to the upstream WAN interface (`network.@device[1].macaddr`), preventing the Mudi from being tracked by upstream access points across reboots. This may interfere with MAC filtering if enabled on the upstream WiFi AP.\n\n### Client database volatility\n\nThe client database at `/etc/oui-tertf` is securely deleted with `shred` on boot, then a `tmpfs` filesystem is mounted at that location. The `gl_clients` service is restarted so it writes to RAM only. Device seizure or flash memory forensics will not recover previously connected client MAC addresses.\n\n### DNS cache flush\n\nAfter each IMEI change, `dnsmasq` is restarted to clear the DNS cache. Stale DNS entries from a previous session could otherwise be used to correlate identities across IMEI changes.\n\n## File structure\n\n```\nfiles/\n├── etc/\n│   ├── config/red-merle                         Config (UCI)\n│   ├── gl-switch.d/sim.sh                       Toggle switch handler\n│   └── init.d/\n│       ├── red-merle                            Boot: MAC/BSSID randomization\n│       └── volatile-client-macs                 Boot: client DB volatility\n├── lib/red-merle/\n│   ├── functions.sh                             Helper functions\n│   ├── imei_generate.py                         IMEI generation + serial modem\n│   └── luhn.lua                                 Luhn checksum\n├── usr/\n│   ├── bin/\n│   │   ├── red-merle                            CLI SIM swap workflow\n│   │   ├── red-merle-switch-stage1              Toggle stage 1\n│   │   ├── red-merle-switch-stage2              Toggle stage 2\n│   │   └── sim_switch                           State toggler\n│   ├── libexec/red-merle                        RPC endpoint for LuCI\n│   └── share/\n│       ├── luci/menu.d/luci-app-red-merle.json  LuCI menu entry\n│       └── rpcd/acl.d/luci-app-red-merle.json   LuCI permissions\n└── www/luci-static/resources/view/red-merle.js  LuCI web interface\n```\n\n## Differences from blue-merle\n\n*red-merle* is a fork of [blue-merle](https://github.com/srlabs/blue-merle) by SRLabs. Key changes:\n\n### Security fixes\n\n| Issue | blue-merle | red-merle |\n|---|---|---|\n| TAC/band fingerprinting | 16 generic TACs, band mismatch detectable by carriers ([Issue #1](https://github.com/srlabs/blue-merle/issues/1)) | 24+ TACs per modem variant, band-aligned to EP06-E and EM060K-GL |\n| IMEI serial entropy | `random.sample` without replacement: 151,200 combinations (17.2 bits), detectable via repetition analysis | `random.choices` with replacement: 1,000,000 combinations (19.9 bits), statistically indistinguishable |\n| Syslog IMEI leak | Writes old/new IMEI in cleartext to syslog (`logger \"Changed IMEI from X to Y\"`) | All logger calls removed, syslog/dmesg/history wiped after IMEI change |\n| Carrier GPS tracking | Not addressed (LPP/SUPL/RRLP active) | Disabled at boot and after each IMEI change via AT+QGPSCFG |\n| DNS correlation | Not addressed | dnsmasq restarted after IMEI change |\n| IMEI validation | `validate_imei()` checks for 14 digits (incorrect, IMEI is 15 digits) | Fixed to validate 15-digit IMEI |\n\n### Features\n\n- **Modem auto-detection**: `AT+CGMM` identifies EP06/EM060K and selects matching TAC prefix list\n- **Static IMEI mode** (`-s`): set a specific IMEI, validated with Luhn checksum\n- **eSIM path handling**: updates `/root/esim/imei` and shreds eSIM logs\n- **Quick build script** (`build.sh`): build `.ipk` without the full SDK\n- **Automated releases**: CI builds `.ipk` + offline install zip on tag push\n- **Toggle rate limiting**: 60-second minimum between switch actions\n\n## License\n\nBSD 3-Clause License. See [LICENSE.md](LICENSE.md).\n\nOriginal project: [blue-merle](https://github.com/srlabs/blue-merle) by SRLabs (2022).\n\nMaintained by [Franck Ferman](https://github.com/franckferman).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffranckferman%2Fred-merle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffranckferman%2Fred-merle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffranckferman%2Fred-merle/lists"}