Android-VPN pro App: Eine App auszuschliessen blockiert sie nicht
Die Liste pro App auf dem Bildschirm gehört einem einzigen Tunnel-Eigentümer, und eine App auszuschliessen leitet sie um diesen Tunnel herum statt aus dem Netz. Dort beginnt die Suche.
Zwei Personen stellen dieselbe Frage und erhalten unvereinbare Antworten, weil sie an verschiedenen Stellen stehen. Die eine hat die VPN-Einstellungen des Systems offen und bearbeitet eine Liste von Anwendungen. Die andere schreibt VpnService.Builder.addDisallowedApplication() in einem Editor. Beide nennen es einen VPN-Filter pro App. Nur eine von ihnen besitzt die Kontrolle, die sie beschreibt, und keine von ihnen blockiert irgendetwas.
Beginne bei dem Bildschirm, den der Nutzer sieht
Öffne die Einstellungen, suche den VPN-Eintrag und schau dir die Verbindung an, die tatsächlich aktiv ist. Bietet der Client eine Liste pro App, gehört diese Liste zum eigenen Tunnel des Clients. Die Plattform veröffentlicht keine allgemeine API, über die eine fremde Anwendung die App-Auswahl eines anderen VPN lesen oder ändern könnte, also kann eine zweite App diese Liste für den Nutzer nicht reparieren.
Hier ist die erste Gabelung des Rundgangs. Hat das installierte VPN keine solche Einstellung, gibt es nichts, worum man herum programmieren müsste: Das Merkmal fehlt in dem Produkt, das den Tunnel besitzt. Hat es eine, liegt die richtige Korrektur in diesem Bildschirm und wird von der Person gemacht, die ihn oeffnen kann.
Folge dem Paket in einen Tunnel
Wenn deine eigene App einen Tunnel aufbaut, erzeugt sie eine TUN-Schnittstelle und erklärt, welcher Anwendungen Verkehr hineinfließt. Die Mitgliedschaftsaufrufe geschehen, bevor die Schnittstelle aufgebaut wird, und danach steht der Regelsatz für diese Sitzung fest:
val builder = VpnService.Builder()
builder.addAddress("10.8.0.2", 32)
builder.addRoute("0.0.0.0", 0)
builder.addDisallowedApplication("com.example.bypass")
val tun = builder.establish() // membership decided hereDiese Aufrufe gelten für den Tunnel, den deine App gerade erzeugt hat, und für nichts sonst. Sie sind keine geräteweite Richtlinie, sie bleiben nicht für andere Clients bestehen, und sie können nicht in das VPN von jemand anderem hineingreifen. Wenn ein Aufruf des Builders fehlschlägt, weil das Paket nicht aufgelöst werden kann, wird die Schnittstelle nie aufgebaut, was ein sauberes Scheitern statt eines stillen ist.
Warum der Ausschluss wie eine Sperre aussah
Eine ausgeschlossene Anwendung wird um deinen Tunnel herum auf das darunterliegende Netz geleitet. Das ist das Gegenteil einer Sperre: Der Verkehr verlässt das Gerät weiterhin, nur außerhalb der Schnittstelle, die du kontrollierst. Eine App im Firewall-Stil macht das Umgekehrte. Sie lässt den Verkehr der Anwendung in ihren Tunnel und verwirft dann die Pakete oder weigert sich, sie weiterzuleiten, sodass die Schnittstelle dieselbe ist und die Richtung der Richtlinie umgekehrt wird.
Die Arbeit hinter dieser Umkehrung ist kein Konfigurationsschalter. Du liest IP-Pakete aus dem Tunnel-Deskriptor, entscheidest pro Fluss und leitest sie entweder durch einen geschützten Socket weiter oder verwirfst sie. Alles, was du nicht behandelst, bleibt einfach stehen, weshalb ein halbfertiger Tunnel wie ein kaputtes Netz aussieht statt wie ein funktionierender Filter. Wenn dein Ziel eine Sperre ist, plane Paketverarbeitung, einen Vordergrunddienst und eine schriftliche Richtlinie für Verkehr ein, den du nicht einordnen kannst.
Was bricht, wenn du es selbst baust
Android erlaubt im Allgemeinen nur ein aktives VPN zur Zeit, also konkurrieren dein Filter-Tunnel und ein Privatsphäre-Tunnel um denselben Platz, sofern die Produkte keine Verkettung unterstützen. Always-on-VPN mit Verbindungsblockade ändert die Art des Scheiterns auf eine Weise, die hier zaehlt: Verkehr, der nicht in den Tunnel gelangen kann, wird verworfen statt direkt gesendet, was ein Design zur Leckvermeidung will und eine Debug-Sitzung selten erwartet.
Paketsichtbarkeit ist die zweite Falle. Das Aufloesen des Paketnamens einer Anwendung kann mit NameNotFoundException scheitern, und auf neueren Android-Versionen hängt die Menge der Pakete, die du sehen kannst, von den von dir deklarierten Abfragen ab. Behandle die Ausnahme, statt anzunehmen, dass jeder Name aufgelöst wird, und lies die Liste neu ein, wenn Anwendungen installiert oder entfernt werden, statt sie für immer zwischenzuspeichern.
Verwaltete Geräte bringen einen dritten Eigentümer. Eine Richtlinie für Unternehmensmobilitaet kann ein VPN pro App oder ein Always-on-Profil setzen, und eine gewöhnliche Anwendung kann das nicht überschreiben. Prüfe, ob das Gerät verwaltet wird, bevor du deinen eigenen Code debugst, denn in diesem Fall ist die Liste, die du ändern willst, möglicherweise für niemanden, der das Telefon haelt, bearbeitbar.
Teste es mit einer App, die du kontrollierst
Teste nicht mit der App, die du filtern willst. Nutze eine zweite Anwendung, deren Netzverhalten du beobachten kannst, und pruefe, ob ihr Verkehr durch deinen Tunnel geht, während der des Ziels es nicht tut. Bleiben beide drinnen, funktioniert die Richtlinie und das Ziel ist ausgeschlossen; geht keiner hinaus, ist der Tunnel selbst falsch und die App-Liste nicht das Problem.
Dann entscheide, welches von drei Dingen du eigentlich baust. Ein Tunnel pro App ist die Builder-API, mit der Liste als Teil deines Profils. Eine Geräte-Firewall ist Paketverarbeitung plus ein Lebenszyklus, den du verteidigen kannst. Das VPN von jemand anderem zu ändern ist überhaupt kein unterstützter Weg, und die ehrliche Antwort dort ist, dass die Einstellung zu jenem Produkt gehört.