Deine Pakete gehen niemanden außer dir was an.
Wi-Fi ist ein geteiltes Medium. Cafés, Hotels, Wohnheime, LAN-Partys. Jeder im selben Netzwerk kann deinen Traffic sehen. Dish wurde mit diesem Wissen gebaut.
Threat Model
Dish ist so gebaut, dass es auch in Netzwerken sicher bleibt, denen du nicht vollständig vertraust:
- Ein Mitbewohner oder Nachbar im selben Wi-Fi sollte keine Controller-Inputs in dein Spiel injizieren können.
- Jemand, der
tcpdumpauf dem Router laufen lässt, sollte nicht sehen, was du spielst oder wie du es spielst. - Ein eingefangenes Paket sollte eine Stunde später nicht erneut abspielbar sein.
- Pairing sollte fail closed sein. Niemals ein stilles Zurückfallen auf Klartext.
- Die Konfigurations-Surface sollte nicht aus dem LAN erreichbar sein. Nur der verschlüsselte Gamepad-Pfad ist es.
Pairing
Wenn du Dish zum ersten Mal mit Satellite verbindest, wirft Satellite eine vierstellige PIN auf deinen Gaming-PC. Die PIN lebt fünf Minuten, dann läuft sie ab. Du tippst sie in Dish auf deinem Smartphone, Laptop oder anderen Client-Gerät ein.
Pairing läuft über HTTPS auf Port 9443, auf einem selbstsignierten Zertifikat, das Satellite lokal erzeugt. Der Transport schützt gegen passive Lauscher; die PIN schützt gegen jeden, der Satellite dazu bringen will, ihm zu vertrauen. Der Client sendet einen 32-byte X25519-Public-Key, Satellite berechnet das Shared Secret mit crypto_scalarmult, und von da an halten beide Seiten einen 256-bit-symmetrischen Schlüssel, der nie über die Leitung geschickt wurde. Die PIN selbst wird zerstört, sobald das Pairing abgeschlossen ist.
Der Shared Key wird lokal auf beiden Seiten gespeichert und für die Authentifizierung jedes folgenden Reconnects verwendet. Auf der Satellite-Seite lebt er im Per-User-Config-Verzeichnis deiner Plattform, modus-geschützt auf dein Konto (Windows DPAPI in V1); auf der Android-Client-Seite lebt er in den privaten SharedPreferences der App, von Android in die Dish-App sandboxed und aus Cloud-Backup und Device-Transfer ausgeschlossen. Kein Schlüssel verlässt jemals eines der beiden Geräte.
Pro-Paket-AEAD
Jedes Controller-Paket – Gamepad-Input, Heartbeat, Controller-Add, Rumble, Motion, Akku, Touchpad, Lightbar – wird mit ChaCha20-Poly1305 (IETF) versiegelt, demselben AEAD, das TLS 1.3, WireGuard und SSH benutzen. ChaCha20 ist schnell und constant-time auf jeder CPU, die uns wichtig ist, einschließlich Androids ARMv8 und Apple Silicon.
Das Wire-Format ist klein und starr: 4-byte Session-Token, 4-byte Zähler, Ciphertext, 16-byte Poly1305-Authentication-Tag. Der Token dient zugleich als Additional Authenticated Data (AAD), sodass ihn in ein Replay-Paket zu tauschen Verifizierung scheitern lässt. Die Nonce ist der Zähler, auf 12 Bytes mit Nullen aufgefüllt – Nonce-Wiederverwendung ist ohne Session-Roll unmöglich.
Replay-Schutz
Satellite speichert den höchsten Zähler, den es auf jeder Verbindung akzeptiert hat. Jedes Paket, dessen Zähler kleiner oder gleich diesem High-Water-Mark ist, wird verworfen, bevor es jemals das Gamepad-Backend erreicht. Eingefangener Ciphertext aus der gestrigen Session – oder selbst von vor einer Sekunde – lässt sich nicht erneut abspielen, um einen Tastendruck auszulösen.
Worüber du dir keine Sorgen machen musst
- Lauschangriff. Niemand im LAN erfährt, welche Tasten du gedrückt hast.
- Spoofing. Ohne den Session-Key kann kein Angreifer einen „B-Tasten"-Druck injizieren, selbst wenn er deine IP kennt.
- Replay. Das gestrige „Feuer"-Paket wird heute nicht feuern. Genauso wenig wie der gestrige Heartbeat oder das gestrige Pairing-Paket.
- Downgrade. Kein Klartext-Fallback. Falls die Krypto-Verifizierung scheitert, stirbt das Paket still.
- Remote-Config-Manipulation. Die Admin-API (
localhost:9877) bindet sich nur an127.0.0.1. Die LAN-gewandte HTTPS-API auf 9443 exponiert nur Pair- und Session-Endpunkte, alle gated durch eine gekoppelte Device-ID.
Null Analytics, null Werbung
Dish und Satellite sammeln keine Nutzungsdaten, keine Identifier, keine Analytics, keine Werbe-IDs. Der einzige ausgehende TinkerNorth-berührte Fluss bei Dish for Android ist opt-out Firebase Crashlytics für Crash- und ANR-Reports – Stack Trace, Gerätemodell, Install-UUID, mehr nicht. Niemals Gamepad-Input, niemals Satellite-IPs, niemals Wi-Fi-SSIDs. Es gibt einen Ein-Tipp-Opt-out in den App-Einstellungen unter Diagnose, der vor jedem möglichen Upload beim nächsten Start respektiert wird. Satellite selbst kommt mit überhaupt keinem Crash-Reporting-SDK. Der volle Umfang steht in der Datenschutzerklärung von Dish for Android.
Wir betreiben kein Account-System. Es gibt keine Cloud. Nichts, was kompromittiert werden könnte, weil nichts auf einem Server liegt, das leaken könnte.
Auditierbare Supply-Chain
Jedes getaggte Release wird mit folgendem ausgeliefert:
- Eine SHA-256-Prüfsummendatei für jedes Artefakt, keyless signiert via
cosignund der OIDC-Identität des GitHub-Actions-Release-Workflows. - Eine SLSA Level 3 Provenance-Attestation, die belegt, dass das Artefakt aus dem getaggten Commit in der CI gebaut wurde.
- Eine Software Bill of Materials in den Formaten SPDX und CycloneDX, sodass du jede transitive Abhängigkeit auditieren kannst.
Das verify-blob-Rezept lebt in der SECURITY.md im Satellite-Repo. Wenn ein Download nicht zur veröffentlichten Prüfsumme passt, installiere es nicht.
Open Source und auditierbar
Jede Zeile crypto-berührenden Codes lebt in einem öffentlichen Repo. Satellite nutzt libsodium; Dish for Android nutzt libsodium-stable, via NDK gebaut, und Androids Standard-Conscrypt für den HTTPS-Pairing-Transport. Keine selbstgebraute Krypto. Kein „wir haben unser eigenes ChaCha geschrieben".
Vertrieben unter der GNU Lesser General Public License v3.0 or later. Etwas Komisches gefunden? Die SECURITY.md im Satellite-Repo enthält unsere Disclosure-Policy.