- ChatBubble: useActionSheet replaces custom Modal (native iOS popup, Android bottom sheet) - DM mode (isDM prop): hides like-count, shows Insta-style heart badge under bubble when liked - Group chat unchanged - Cleanup: remove unused Modal/Platform imports, sheet styles, actionsOpen state - deploy.sh: auto-detect ANDROID_HOME + auto-create local.properties for local Gradle - NEXT_RELEASE.md: DM reactions release note - Includes other staged work across binder-mac, marketing, ops/mdm, ios/
138 lines
6.0 KiB
Markdown
138 lines
6.0 KiB
Markdown
# 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.
|