MDM-VPN-Pivot (Phase F.2 done): - ops/mdm/profiles/rebreak-iphone-protection.mobileconfig auf v5 mit com.apple.vpn.managed Payload + OnDemandUserOverrideDisabled. iPhone-User kann ReBreak-VPN-Profile nicht entfernen und "Bedarf verbinden"-Toggle ist disabled. allowEnablingRestrictions empirisch widerlegt für FC-Toggle- Lock — out. - DEV-removable Variante als Test-Profile dazu. - Bootstrap-Tool (rebreak-supervise.sh) + Supervision-Identity-Setup-Doc. - PHASES.md updated mit empirischen Befunden. App-side MDM-Detect (Pfad-a Banner-Logic): - modules/rebreak-protection: getDeviceState() returnt mdmManaged via Heuristik NETunnelProviderManager.count > 1 (App selbst kann nur einen eigenen erstellen, MDM-Push fügt einen zweiten hinzu). - DeviceLayers.mdmManaged?: boolean Type. - blocker.tsx: lockedIn-Bedingung erweitert um mdmManaged. Bei MDM-managed iPhones wird der App-Lock-Card (FC-Authorization-Toggle UI) ausgeblendet weil der per-App FC-Toggle nicht lockbar ist und durch den MDM-VPN-Layer redundant. Layer-2-Country-Curated-Pivot: - backend: vip-swap.post.ts raus, suggest.post.ts rein. Curated-domains durch admin (separate Tabelle/Pfad), getrennt von User-Custom-Domains. - Admin-APIs für curated-domain Pflege (index.get + [id].patch). - seed-country-blocklists Script für initiale Curated-Domain-Liste. - protection/webcontent-domains.get refactored für Country-Curated-Pfad. - Migration drop_vip_swap_fields.sql + schema.prisma adjusted. - docs/concepts/layer2-country-pivot.md mit Architektur + Decision-Trail. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
233 lines
12 KiB
XML
233 lines
12 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
<!--
|
|
ReBreak iPhone Protection Profile
|
|
---------------------------------
|
|
Scope (2026-05-25, Phase F.2 — NEFilter+MDM-Pivot):
|
|
1. Rebreak (und andere Apps) nicht entfernbar → Restrictions.allowAppRemoval=false
|
|
2. Profil selbst nicht entfernbar → PayloadRemovalDisallowed=true
|
|
3. System-DNS auf dns.rebreak.org locken → com.apple.dnsSettings.managed (DoH)
|
|
4. Anti-Tampering → allowEraseContentAndSettings=false,
|
|
allowUIConfigurationProfileInstallation=false
|
|
5. ReBreak-VPN als Managed-VPN pushed → com.apple.vpn.managed
|
|
→ ProviderBundleIdentifier =
|
|
org.rebreak.app.PacketTunnelExtension
|
|
→ Profile non-removable durch MDM
|
|
→ User kann VPN-Toggle in Settings nicht aus
|
|
|
|
Architektur (Pivot 2026-05-25):
|
|
Der Per-App-Family-Controls-Authorization-Toggle ist via Standard-Apple-MDM nicht
|
|
lockbar (dokumentierte security gap). Statt diesen Arms-Race zu spielen pushen wir
|
|
ReBreak-VPN selbst via MDM — damit ist das VPN-Profile non-removable und der User
|
|
kann den Filter nicht abschalten. App-seitig wird MDM-Präsenz detected und der
|
|
Protection-Layer dynamisch gewählt:
|
|
- MDM präsent: PacketTunnel (NEFilter-Path) bleibt always-on via Managed-VPN
|
|
- kein MDM: bisheriger VPN-DNS-Filter wie gehabt (user-toggleable)
|
|
Bypass-Vektor: 3rd-Party-VPN (ExpressVPN) bleibt installierbar, akzeptiert für DiGA-Pilot.
|
|
|
|
Voraussetzungen am Gerät:
|
|
- Supervised-Mode aktiv (sonst greifen allowAppRemoval / PayloadRemovalDisallowed NICHT)
|
|
- iOS 14+ (DNS-Settings-Payload erfordert iOS 14)
|
|
- ReBreak-App mit PacketTunnel-Extension installed BEVOR Profile-Install
|
|
(sonst kann iOS den ProviderBundleIdentifier nicht auflösen)
|
|
|
|
Apple-Referenzen:
|
|
- Restrictions: https://developer.apple.com/documentation/devicemanagement/restrictions
|
|
- DNS Settings: https://developer.apple.com/documentation/devicemanagement/dnssettings
|
|
- VPN-Managed: https://github.com/apple/device-management/blob/release/mdm/profiles/com.apple.vpn.managed.yaml
|
|
- Profile Format: https://developer.apple.com/documentation/devicemanagement/toplevel
|
|
|
|
Stand: 2026-05-25, Profile-Version 2 (VPN-Managed-Payload hinzugefügt)
|
|
-->
|
|
<plist version="1.0">
|
|
<dict>
|
|
<key>PayloadType</key>
|
|
<string>Configuration</string>
|
|
<key>PayloadVersion</key>
|
|
<integer>1</integer>
|
|
<key>PayloadIdentifier</key>
|
|
<string>org.rebreak.protection.iphone.20260525</string>
|
|
<key>PayloadUUID</key>
|
|
<string>A1B2C3D8-E5F6-4789-ABCD-EF1234567894</string>
|
|
<key>PayloadDisplayName</key>
|
|
<string>ReBreak Schutz</string>
|
|
<key>PayloadDescription</key>
|
|
<string>Schützt dich vor Glücksspiel-Rückfall: Rebreak nicht entfernbar, DNS-Filter auf dns.rebreak.org gelocked, VPN-Toggle deaktiviert. Profil kann nicht selbst entfernt werden — Notfall-Entfernung via deinem Trustee.</string>
|
|
<key>PayloadOrganization</key>
|
|
<string>ReBreak</string>
|
|
<key>PayloadRemovalDisallowed</key>
|
|
<true/>
|
|
<key>ConsentText</key>
|
|
<dict>
|
|
<key>default</key>
|
|
<string>Du installierst hiermit das ReBreak-Schutz-Profil. Dieses Profil bindet dich freiwillig an folgende Einschränkungen:
|
|
|
|
• Apps können während des Schutzes nicht über Long-Press gelöscht werden
|
|
• Das ReBreak-VPN kann nicht in den iPhone-Einstellungen deaktiviert werden
|
|
• System-DNS-Anfragen laufen über dns.rebreak.org (verschlüsselt via DoH)
|
|
• Du kannst dieses Profil nicht selbst entfernen
|
|
|
|
Das ist gewollt. Der Schutz wirkt, weil er gegen deine impulsive Selbst-Override-Tendenz steht. Die Entfernung läuft über deinen Trustee oder deinen 7-Tage-Cooldown in der App.
|
|
|
|
Bei Verlust deines iPhones: das Profil verschwindet mit Factory-Reset, das ist normal.</string>
|
|
</dict>
|
|
|
|
<key>PayloadContent</key>
|
|
<array>
|
|
|
|
<!-- ===================================================================
|
|
1) RESTRICTIONS-PAYLOAD
|
|
Supervised-only Restrictions: blockt App-Removal + VPN-User-Eingriffe
|
|
=================================================================== -->
|
|
<dict>
|
|
<key>PayloadType</key>
|
|
<string>com.apple.applicationaccess</string>
|
|
<key>PayloadVersion</key>
|
|
<integer>1</integer>
|
|
<key>PayloadIdentifier</key>
|
|
<string>org.rebreak.protection.iphone.restrictions</string>
|
|
<key>PayloadUUID</key>
|
|
<string>B3234567-ABCD-4F01-9345-67890ABCDEF6</string>
|
|
<key>PayloadDisplayName</key>
|
|
<string>ReBreak Restrictions</string>
|
|
<key>PayloadDescription</key>
|
|
<string>Verhindert App-Löschung und VPN-Eingriffe.</string>
|
|
|
|
<!-- App-Removal komplett blocken (supervised only)
|
|
Per-Bundle-ID-Lock wäre chirurgischer, erfordert aber MDM-managed-Convert
|
|
via separatem InstallApplication-Command. Akzeptierter Trade-off für Prototype:
|
|
alle Apps sind während Schutz nicht löschbar. Für Self-Binding gewünscht.
|
|
User-Verhalten-Test 2026-05-24: zeigt "Vom Home-Screen entfernen" statt
|
|
"App löschen" — User kann App in Mediathek verschieben, nicht deinstallieren. -->
|
|
<key>allowAppRemoval</key>
|
|
<false/>
|
|
|
|
<!-- Verhindert dass User per Erase-All-Content-and-Settings entkommt
|
|
(supervised only). Bewusst gesetzt: Wipe ist Trustee-/Cooldown-Pfad. -->
|
|
<key>allowEraseContentAndSettings</key>
|
|
<false/>
|
|
|
|
<!-- Schutz vor Profil-Install-Bypass: User kann keine konkurrierenden
|
|
Konfigurationsprofile installieren die unsere Restrictions overriden -->
|
|
<key>allowUIConfigurationProfileInstallation</key>
|
|
<false/>
|
|
|
|
<!-- 2026-05-25 empirisch getestet: allowEnablingRestrictions=false
|
|
deaktiviert zwar die Bildschirmzeit-Setup-Page komplett, hat
|
|
aber KEINEN Effekt auf den per-App "Apps mit Zugriff auf
|
|
Bildschirmzeit"-Toggle (FC-Authorization). Apple unterscheidet
|
|
die beiden Permission-Systeme.
|
|
→ Rollback, FC-Toggle wird via App-Code-Bypass (MDM-Detect)
|
|
geregelt statt via MDM-Restriction.
|
|
→ ManagedSettings-API bleibt damit für die App weiter verfügbar. -->
|
|
</dict>
|
|
|
|
<!-- ===================================================================
|
|
2) DNS-SETTINGS-PAYLOAD
|
|
Lockt System-DNS auf unseren DoH-Endpoint
|
|
Belt+Suspenders zur VPN-Schicht: greift auch wenn VPN aus irgend-
|
|
einem Grund nicht aktiv ist
|
|
=================================================================== -->
|
|
<dict>
|
|
<key>PayloadType</key>
|
|
<string>com.apple.dnsSettings.managed</string>
|
|
<key>PayloadVersion</key>
|
|
<integer>1</integer>
|
|
<key>PayloadIdentifier</key>
|
|
<string>org.rebreak.protection.iphone.dns</string>
|
|
<key>PayloadUUID</key>
|
|
<string>C1234567-ABCD-4F01-9345-67890ABCDEF2</string>
|
|
<key>PayloadDisplayName</key>
|
|
<string>ReBreak DNS-Filter</string>
|
|
<key>PayloadDescription</key>
|
|
<string>Leitet alle DNS-Anfragen verschlüsselt über dns.rebreak.org. Glücksspiel-Domains werden blockiert.</string>
|
|
|
|
<key>DNSSettings</key>
|
|
<dict>
|
|
<key>DNSProtocol</key>
|
|
<string>HTTPS</string>
|
|
<key>ServerURL</key>
|
|
<string>https://dns.rebreak.org/dns-query</string>
|
|
</dict>
|
|
</dict>
|
|
|
|
<!-- ===================================================================
|
|
3) VPN-MANAGED-PAYLOAD (Phase F.2 — NEFilter+MDM-Pivot 2026-05-25)
|
|
Pushed ReBreak's eigenen NEPacketTunnelProvider als MDM-Managed-VPN.
|
|
Effekt: VPN-Profile non-removable via Settings → User kann den
|
|
Filter nicht abschalten. ReBreak-App's eigene NEVPNManager-Aufrufe
|
|
überschreiben diese Config nicht (MDM-managed wins).
|
|
Voraussetzung: ReBreak-App MIT PacketTunnel-Extension muss installed
|
|
sein BEVOR dieses Profile gepushed wird (sonst kann iOS den
|
|
ProviderBundleIdentifier nicht auflösen → InstallProfile-Fail).
|
|
=================================================================== -->
|
|
<dict>
|
|
<key>PayloadType</key>
|
|
<string>com.apple.vpn.managed</string>
|
|
<key>PayloadVersion</key>
|
|
<integer>1</integer>
|
|
<key>PayloadIdentifier</key>
|
|
<string>org.rebreak.protection.iphone.vpn</string>
|
|
<key>PayloadUUID</key>
|
|
<string>D2234567-ABCD-4F01-9345-67890ABCDEF4</string>
|
|
<key>PayloadDisplayName</key>
|
|
<string>ReBreak Schutz-VPN</string>
|
|
<key>PayloadDescription</key>
|
|
<string>Aktiviert den ReBreak-DNS-Filter als nicht-abschaltbaren VPN. Verhindert dass du dich impulsiv selbst aussperrst-vom-Schutz.</string>
|
|
|
|
<key>UserDefinedName</key>
|
|
<string>ReBreak Schutz</string>
|
|
<key>VPNType</key>
|
|
<string>VPN</string>
|
|
<!-- VPNSubType + VPN.ProviderBundleIdentifier referenzieren die
|
|
Extension im ReBreak-App-Bundle. iOS findet den Provider via
|
|
diesem Bundle-ID und ruft den ReBreak-PacketTunnel auf. -->
|
|
<key>VPNSubType</key>
|
|
<string>org.rebreak.app.PacketTunnelExtension</string>
|
|
|
|
<key>VPN</key>
|
|
<dict>
|
|
<!-- RemoteAddress ist Pflichtfeld, hat aber bei lokal-only
|
|
PacketTunnel keine echte Funktion. Muss mit App-Code
|
|
übereinstimmen (RebreakProtectionModule.swift:1225). -->
|
|
<key>RemoteAddress</key>
|
|
<string>ReBreak DNS-Filter (lokal)</string>
|
|
<key>AuthenticationMethod</key>
|
|
<string>Password</string>
|
|
<key>ProviderBundleIdentifier</key>
|
|
<string>org.rebreak.app.PacketTunnelExtension</string>
|
|
<key>ProviderType</key>
|
|
<string>packet-tunnel</string>
|
|
<key>DisconnectOnIdle</key>
|
|
<integer>0</integer>
|
|
<!-- OnDemand-User-Override blocken: "Bedarf verbinden"-Toggle in
|
|
Settings → VPN → ReBreak Schutz wird disabled (grau).
|
|
Apple-Schema-Doku: "If 1, the Connect On Demand toggle in
|
|
Settings is disabled for this configuration." iOS 14+ -->
|
|
<key>OnDemandUserOverrideDisabled</key>
|
|
<true/>
|
|
</dict>
|
|
|
|
<!-- Empty VendorConfig — Apple-Schema erlaubt das, ReBreak-Extension
|
|
liest providerConfiguration nicht (Blocklist kommt aus AppGroup). -->
|
|
<key>VendorConfig</key>
|
|
<dict/>
|
|
|
|
<!-- On-Demand: VPN startet automatisch bei jedem Netzwerk-Connect.
|
|
Kombiniert mit MDM-non-removable + OnDemandUserOverrideDisabled
|
|
= always-on Schutz, User kann nicht abschalten. -->
|
|
<key>OnDemandEnabled</key>
|
|
<integer>1</integer>
|
|
<key>OnDemandRules</key>
|
|
<array>
|
|
<dict>
|
|
<key>Action</key>
|
|
<string>Connect</string>
|
|
</dict>
|
|
</array>
|
|
</dict>
|
|
|
|
</array>
|
|
</dict>
|
|
</plist>
|