Die Verschlüsselung des WSS-Tunnels endet am TLS-Terminator, nicht in der App
Eine wss://-URL belegt TLS auf einem Sprung. Ob die Nutzlast eine eigene Verschlüsselung hat, hängt davon ab, was der Client hineinlegt und wer dieses TLS beendet.
Ein Tunnel, der in einem sicheren WebSocket befördert wird, hat genau so viel Verschlüsselung, wie der Client hineingelegt hat, nicht mehr. Das wss://-Schema besagt, dass TLS eine Verbindung auf einem Sprung schützt. Es sagt nichts darüber, ob die Bytes innerhalb der WebSocket-Nachrichten getrennt geschützt sind, und genau dieser Unterschied entscheidet, wer Ihren Verkehr lesen kann, wenn etwas in der Mitte das TLS beendet.
Zwei Schichten, die wie eine aussehen
Ein sicherer WebSocket ist TLS, über dem ein WebSocket-Handshake ausgeführt wird, wie RFC 6455 in seinen Abschnitten zu Verbindung und Sicherheit beschreibt. Die TLS-Schicht authentifiziert den Server und verschlüsselt den Strom, dann rahmt die WebSocket-Schicht, was die Anwendung zu senden beschließt.
Das sind zwei unabhängige Entscheidungen, und ein Diagramm, das ein einziges Schloss über den ganzen Weg zeichnet, verbirgt die zweite. Fragen Sie, wer die TLS-Verbindung beendet. Fragen Sie dann, was der Client in jede Nachricht legt. Alles Weitere zum Betrieb folgt aus diesen beiden Antworten.
Entwurf A: der Transport ist die einzige Verschlüsselung
Im einfacheren Entwurf nimmt der Client rohe IP-Pakete und wickelt sie in WebSocket-Nachrichten. Im Inneren ist nichts verschlüsselt, also liest die Komponente, die die TLS-Sitzung hält, Klartext-Nutzlasten. Wenn diese Komponente Ihr eigener Tunnel-Server ist, ist dies der beabsichtigte Endpunkt, und der Entwurf ist stimmig, weil der Server den Verkehr ohnehin sehen würde.
Es wird eine andere Anordnung, wenn ein Inspektionsproxy auf dem Pfad sitzt und das TLS mit einem Zertifikat beendet, dem der Client vertraut. Dieser Proxy hält nun denselben Klartext, den der Server gehalten hätte, und keine Menge an WebSocket-Rahmung ändert das. Der Vertrauensspeicher des Clients hat dieses Ergebnis lange vor dem Öffnen des Tunnels entschieden, weil er sich dafür entschied, dieses Zertifikat für diesen Namen zu akzeptieren. Der Proxy sieht außerdem den angeforderten Host und die Größe jeder Nachricht, was ausreicht, um viele Aktivitäten zu fingerprinten, ohne noch etwas weiter zu entschlüsseln.
Entwurf B: die Nutzlast trägt ihre eigenen Schlüssel
Im zweiten Entwurf verschlüsselt und authentifiziert der Client seine Pakete mit einem VPN-Protokoll, das seine eigene Peer-Identität und seinen eigenen Schlüsselaustausch hat, und befördert dann das Ergebnis in WebSocket-Nachrichten. Das Beenden des äußeren TLS legt hier Chiffretext offen, nicht Verkehr. Der Proxy kann Nachrichtengrößen und Timing sehen, und nichts anderes in der Nutzlast. Das ist eine viel kleinere Exposition, und es sind immer noch Metadaten, die in einer Prüfung benannt werden sollten, statt sie wegzuwischen.
Die eigenen Endpunkte des inneren Protokolls sehen weiterhin Klartext, was der Sinn der Anordnung und zugleich ihre Grenze ist. Wenn eine Komponente am Endpunkt befugt ist, Daten vor der Verschlüsselung oder nach der Entschlüsselung zu lesen, schränkt die zusätzliche Schicht sie nicht ein. Schlüssel und die Software, die sie verwaltet, bleiben die Grenze, auf die es ankommt.
Ein VPN-Etikett, ein vertrautes Client-Symbol oder eine Marketingseite sind kein Beleg dafür, dass dieser Entwurf existiert. Das Nutzlastformat zu lesen ist es.
Verfolgen Sie, wo der Klartext tatsächlich erscheint
Das URL-Schema gibt Ihnen einen einzigen Fakt, holen Sie den Rest aus den Schnittstellen. Führen Sie die folgenden Prüfungen in der Reihenfolge aus, denn jede verengt die nächste:
ss -tnp | grep -E ':(443|8443)\b' ip -br link show type tun openssl s_client -connect vpn.example.net:443 -servername vpn.example.net -brief tcpdump -ni tun0 -c 5 -X
Beginnen Sie mit der äußeren Verbindung. Eine langlebige TCP-Sitzung zum TLS-Port ist das Aussehen eines WebSocket-Trägers, und eine zweite Sitzung zu einem unabhängigen Host verdient eine Erklärung, bevor Sie tiefer schauen. Finden Sie dann die Tunnelschnittstelle auf dem Client, denn ein tun- oder tap-Gerät sagt Ihnen, dass der Client IP-Pakete verarbeitet, statt einen einzelnen Anwendungsstrom zu proxyen.
Der Mitschnitt auf der Tunnelschnittstelle klärt meist die Nutzlastfrage. Lesbare Header dort bedeuten, dass die inneren Pakete nie getrennt verschlüsselt wurden, während Nutzlasten mit hoher Entropie bedeuten, dass sie es wurden. Wiederholen Sie den Mitschnitt auf der äußeren Schnittstelle und vergleichen Sie beide: Wenn beide zufällig aussehen, leistet die innere Schicht Arbeit, die die äußere nicht rückgängig machen kann.
Prüfen Sie das Vertrauen, das Sie tatsächlich gewährt haben
Ein installiertes Unternehmens-Wurzelzertifikat ist ein Fakt über den Vertrauensspeicher des Clients, keine Aussage darüber, was ein Proxy protokolliert oder inspiziert. Stellen Sie die eingesetzte Richtlinie und den tatsächlichen Verbindungsweg fest, statt Verhalten aus der Anwesenheit einer CA abzuleiten.
Fragen Sie bei verwalteten Geräten den Administrator, welche Komponente das TLS beendet, ob der Client ein gepinntes oder ein öffentliches Zertifikat validiert und wie das Nutzlastformat aussieht. Diese drei Antworten ergeben einen Befund, den Sie später verteidigen können.
Schreiben Sie das Ergebnis als Grenze statt als Urteil. "TLS endet am Inspektionsproxy, und die innere Nutzlast ist getrennt mit Schlüsseln verschlüsselt, die nur die Endpunkte haben" ist eine überprüfbare Aussage, die einen Anbieterwechsel übersteht. "WebSockets sind sicher" nicht.