# ReBreak MDM Profiles

Stand 2026-05-26 — NEFilter-Pivot. iOS-Schutz-Architektur in **2 Schichten**:

| Schicht | Was | Wie deployed | Removable? |
|---|---|---|---|
| **Sideload-Protect** | App-Removal-Lock + DNS-Backstop | AirDrop → Settings → Profil installieren | NEIN (Apple Configurator + USB nötig) |
| **MDM-Supervised** | App-Branch-Signal (NEFilter statt PacketTunnel) | NanoMDM `Settings`-Command (API-Push) | JA (User-Enrollment) |

Sicherheit ergibt sich aus der **Kombination**: wenn der User das MDM-Profile entfernt → App fällt still auf PacketTunnel-Pfad zurück (VPN+FC), App selbst bleibt aber gesperrt (Sideload-Protect-Profile blockt Removal).

## Files

### `rebreak-iphone-protect.mobileconfig` (Sideload, non-removable)

Pure Restrictions + DNS. **Kein MDM-Payload, kein VPN-Payload.**

Payloads:
- `com.apple.applicationaccess` — `allowAppRemoval=false`, `allowEraseContentAndSettings=false`, `allowUIConfigurationProfileInstallation=false`
- `com.apple.dnsSettings.managed` — DoH zu `dns.rebreak.org/dns-query` (Belt+Suspenders falls NEFilter ausfällt)

**Voraussetzung**: iPhone supervised mit Apple Configurator 2.

**Install-Flow**:
1. Datei AirDrop ans iPhone
2. Settings → Allgemein → VPN & Geräteverwaltung → Profil installieren
3. Consent + 6-stelliger Geräte-Code

**Entfernung**: nur via `cfgutil remove-profile` über USB-Kabel (Mac + Apple Configurator). Settings.app zeigt **kein** „Profil entfernen"-Button (PayloadRemovalDisallowed).

### `rebreak-iphone-take-management.json` (NanoMDM, Step 1 von 2)

**MUSS VOR `rebreak-iphone-mdm-supervised.json` gepushed werden** — sonst wird der Settings-Command vom System ignoriert.

JSON-Payload für `InstallApplication` mit `ChangeManagementState: Managed`. Konvertiert eine bereits via TestFlight/AppStore installierte ReBreak-App in den **managed** State. Erst dann liefert iOS ManagedAppConfiguration an die App.

Auf supervised Geräten (Apple Configurator): KEIN User-Dialog, läuft silent durch.

### `rebreak-iphone-mdm-supervised.json` (NanoMDM, Step 2 von 2)

JSON-Payload für `Settings`-Command. Setzt `mdmSupervised=true` in der App-ManagedAppConfiguration (`UserDefaults.standard.dictionary(forKey: "com.apple.configuration.managed")`).

**Wirkung**: App's `isMdmSupervised()`-Helper liest `true` → `activateUrlFilter()` startet `NEFilterDataProvider` statt `NEPacketTunnelProvider`. KEIN VPN-Eintrag in iOS-Settings, kein User-Toggle.

### Vollständiger Push-Flow (NanoMDM)

```bash
# Auf rebreak-mdm (178.105.101.137) als root:
ssh rebreak-mdm

# Device-UDID des Test-iPhones (steht im NanoMDM-DB oder Apple Configurator):
DEVICE_UDID="00008140-001A...   "

# Step 1: Take Management of existing TestFlight-App
curl -u nanomdm:$NANO_MDM_API_KEY \
  -X POST "http://localhost:9000/v1/enqueue/$DEVICE_UDID" \
  -H "Content-Type: application/json" \
  -d @rebreak-iphone-take-management.json

# Warte ~5-30s bis APNs ankommt + iPhone das Command processed
# Verify: iPhone → Settings → Allgemein → VPN & Geräteverwaltung →
#   [MDM-Profil] → 'Verwaltete Apps' → ReBreak listed

# Step 2: Push mdmSupervised=true an die jetzt managed App
curl -u nanomdm:$NANO_MDM_API_KEY \
  -X POST "http://localhost:9000/v1/enqueue/$DEVICE_UDID" \
  -H "Content-Type: application/json" \
  -d @rebreak-iphone-mdm-supervised.json

# Force-Quit ReBreak (App-Switcher → swipe up) und neu starten —
# iOS injiziert ManagedAppConfiguration erst beim nächsten App-Launch.
```

Apple-Doku:
- InstallApplication: https://developer.apple.com/documentation/devicemanagement/installapplicationcommand
- Settings: https://developer.apple.com/documentation/devicemanagement/settings

### Verifikation in der App

Nach Step 2 + Force-Quit-Restart:
1. ReBreak öffnen
2. Beim Aktivieren des Schutzes: System-Dialog sollte „ReBreak möchte Web-Inhalte filtern" zeigen (NEFilter), NICHT „ReBreak möchte einen VPN konfigurieren"
3. Settings → VPN: kein ReBreak-Eintrag
4. Settings → Allgemein → VPN & Geräteverwaltung → Filters → ReBreak Content Filter sichtbar (kein User-Toggle, MDM-managed)

### Reversal

Step 2 rückgängig: gleiches Settings-Command mit leerer Configuration:
```json
{"RequestType": "Settings", "Settings": [{"Item": "ApplicationConfiguration", "Identifier": "org.rebreak.app", "Configuration": {}}]}
```

Step 1 rückgängig (App un-manage): `RequestType: RemoveApplication` mit `Identifier: org.rebreak.app` — **Vorsicht: löscht die App vom Gerät**, je nach `ManagementFlags`. Für nur „un-manage ohne uninstall" gibt's leider keinen sauberen Apple-Pfad — Reinstall via TestFlight reset's auf unmanaged.

## Migration vom alten Profile

Das alte `rebreak-iphone-protection.mobileconfig` (PayloadIdentifier `.20260525`) kann nach erfolgreicher Migration entfernt werden:

```bash
# Auf dem iPhone via cfgutil:
cfgutil --ecid <ECID> remove-profile "org.rebreak.protection.iphone.20260525"

# Dann neues Profile via AirDrop + Settings installieren.
# Plus MDM-Settings-Command pushen für mdmSupervised=true.
```

Die alte `rebreak-iphone-protection.DEV-removable.mobileconfig` bleibt für Dev-Testing erhalten.

## NanoMDM Enrollment Generator (per-device)

Wenn mehrere iPhones enrollt werden, darf das gleiche Identity-Cert nicht wiederverwendet werden.
NanoMDM blockt das sonst mit `cert re-use not permitted` (HTTP 500 beim Check-in).

Nutze dafuer den Generator:

```bash
ssh rebreak-mdm
cd /srv/rebreak/ops/mdm/profiles

python3 generate-mdm-enrollment-profile.py \
  --device-label iphone-olfa \
  --template /opt/nanomdm/enrollment/rebreak-enrollment.mobileconfig \
  --ca-cert /opt/nanomdm/certs/ca.crt \
  --ca-key /opt/nanomdm/certs/ca.key \
  --out-dir /opt/nanomdm/enrollment/generated \
  --keep-artifacts
```

Output:
- Neues `.mobileconfig` mit frischem PKCS12-Identity-Payload
- Neue UUIDs fuer alle Payloads
- `.meta.txt` mit cert-sha256 + p12-Passwort
- optional `.key/.csr/.crt/.p12` (bei `--keep-artifacts`)

Wichtig:
- `.meta.txt`, `.key` und `.p12` enthalten sensitive Daten -> auf Server behalten, Rechte `600`.
- Pro Geraet immer ein eigenes generiertes Enrollment-Profil verwenden.
