Beim Einrichten von squid als transparentem Webproxy auf meiner pfSense bin ich auf ein interessantes Problem gestoßen:
Welche der Einstellungen bei SSL Man-in-the-middle-filtering unter „SSL/MITM Mode“ ist die Beste? Welche ist korrekt? Welche macht Sinn und was ist Quatsch? Und warum überhaupt?
SSL heißt TLS
Zuerst einmal sollte hier etwas auf das Wording geschaut werden: SSL (Secure Socket Layer) gibt’s eigentlich gar nicht mehr, denn es wurde 1999 in TLS (Transport Layer Security) umbenannt. Irgendwie hat sich aber die Bezeichnung SSL bis heute gehalten. Seit 2015 wird allerdings empfohlen, SSLv2 und SSLv3 aus Gründen unsicherer Verschlüsselungstechnologien nicht mehr zu verwenden. TLS liegt mittlerweise in der Version 1.2 vor, 1.3 existiert als Entwurf. Eine Erweiterung, die seit 2003 existiert, ist SNI (Server Name Indicator), die auch für Proxys nicht unrelevant ist.
Server Name Indication (SNI)
Der verschlüsselte Verbindungsaufbau zum Server findet bereits statt, bevor die eigentlich angefragte URL übertragen wird. Da mit dem digitalen Zertifikat die Authentizität einer Website sichergestellt werden soll, muss dieses Zertifikat für genau die eine Website ausgestellt sein. Dies würde allerdings bedeuten, dass für jede Subdomain ein eigenes Zertifikat existieren muss und es keine Möglichkeit gäbe, mehrere Domains unter einer IP-Adresse zu nutzen, was vor Allem bei der Knappheit von IPv4-Adressen ein ernsthaftes Problem darstellt.
Um dies zu umgehen, wurde das SNI-Verfahren eingeführt. Hierbei wird dem Server beim Verbindungsaufbau unverschlüsselt der Parameter server_name übermittelt.
Squid: SslBump Peek and Splice
Nutzt man squid mit der Funktion als SSL-MITM-Proxy, so bekommt man der Konfiguration die Frage gestellt, welchen SSL-MITM-Mode man nutzen möchte: Splice All, Splice Whitelist – Bump All, Benutzerdefiniert. Um sich hier entscheiden zu können, was man wählt muss man wissen, was was bedeutet.
Der Verbindunsgaufbau einer SSL/TLS-Verbindung ist in folgender Grafik dargestellt.
Beim Splicing (zu deutsch so viel wie „spleißen, zusammenkleben“) fungiert der Proxy als TCP-Tunnel und leitet den Verkehr einfach zwischen Client und Server hin und her, für beide Kommunikationspartner existiert der Proxy quasi nicht.
Vorteil: Web-Filtering funktioniert weiterhin super, denn (beispielsweise) squid-guard kann seine URL-Listen problemlos mit der angeforderten URL vergleichen und filtern.
Nachteil: es ist kein Content-Filterng (z.B.mit clamAV) möglich, da die gesamte Übertragung über den Proxy (der ja als Tunnel fungiert) verschlüsselt bleibt.
Beim Bumping entschlüsselt der Proxy die Nachrichten mit einem eigens ausgestellten Zertifikat (die CA des Proxy MUSS auf allen Clients installiert sein) und übernimmt die Kommunikation mit dem Server. Dazu baut er zwei Verbindungen auf: eine zwischen sich und dem Server und eine zwischen sich und dem Client.
Vorteil: Deep packet inspection wird ermöglicht (notwendig für beispielsweise clamAV)
Nachteil: Web-Filtering wird unmöglich.
Ablauf
Der squid ssl_bump ist in drei Schritte aufgeteilt:
- Lesen des TCP-Level und der HTTP-CONNECT-Infos
- Lesen der TLSClientHello-Nachricht-Infos.
- Lesen der TLSServerHello-Nachricht-Infos.
Im ersten Schritt wertet der Proxy die TCP Connect Informationen aus. Ist HTTPS Interception aktiviert, baut der proxy die fake-Verbindung zum angeforderten Ziel auf. Daraufhin werden alle ssl_bump-Regeln (festgelegt in der Datei squid.conf) abgearbeitet. Trifft dort eine zu, wird sie ausgeführt. Die Aktionen, die in den Regeln definiert werden können, sind hier zu finden. Lautet hier die Regel bspw.
ssl_bump splice all
so wird der Proxy als TCP-Tunnel fungieren. Bei peek oder stare wird zu Schritt zwei übergegangen. Beide Konfigurationen für HTTPS MITM in der pfSense führen im ersten Schritt „peek“ aus, was dazu führt, dass im zweiten Schritt die TLSClientHello-Nachricht ausgewertet und wenn möglich der SNI extrahiert wird. An dieser Stelle wird in logs (wie auch in lightsquid) nur Ziel-IP und -port auftauchen, da hier noch kein Domainname verfügbar ist.
In Schritt 3 wird dann die Antwort des Servers (TLSServerHello) ausgewertet, das Zertifikat validiert und wiederum alle Regeln überprüft und die passende ausgeführt. Trifft hier eine Splice-Regel zu, so wird squid wiederum nur als HTTP-Tunnel fungieren, bei Bump übernimmt squid die Kommunikation mit dem Server und dem Client getrennt.
Warum nicht „Splice Whitelist, Bump Otherwise“?
Im Mode „Splice Whitelist, Bump Otherwise“ sollte dem Verständnis nach alles was im Tab ACL unter Whitelist eingetragen wird also „gesplices“ und in einem TCP-Tunnel an den Server geschickt werden, alles andere wird „gebump“ und der Proxy redet mit dem Server. Dies ist allerdings ein Trugschluss, denn alle Einträge in der Whitelist werden intern in der squid.conf folgender Regel zugeordnet:
acl whitelist dstdom_regex -i „var/squid/acl/whitelist.acl“
Der Ausdruck dstdom_regex wie auch dstdomain basieren aber auf HTTP-Informationen, die im gesamten ssl_bump-Prozess noch nicht entschlüsselt sind. Daher wird die regel „Splice Whitelist, Bump otherwise“ dazu führen, das alles gebumpt wird. Das wiederum wird vor allem problematisch bei Anwendungen wie WhatsApp-Web und Threema-Web, die die Herkunft und somit den Aussteller der SSL-Zertifikate überprüfen und bei den fake-Zertifikaten von squid einfach den Verbindungsaufbau beenden.
Will man an dieser Stelle squid bumpen lassen, so kommt der anfangs genannte SNI-Parameter server_name inst Spiel. Hierfür hat squid bei den ACLs (ACL = Access Control List) die Parameter ssl::server_name bzw. ssl::server_name_regex zur Verfügung gestellt. Will man also einzelne splicen, damit sie direkt mit dem Server reden, dann muss man benutzerdefinierte Regeln und ssl_bump-Abläufe definieren. Dazu wählt man beim SSL-MITM-Mode „custom“ (bzw. „benutzerdefiniert“), erweitert unten die benutzerdefinierten Optionen und legt bei „Custom options (before auth)“ die ACLs fest. Für WhatsApp und Threema habe ich folgende Eintragung vorgenommen:
acl noSSLInterception ssl::server_name_regex (w[0-9]+|[a-z]+)\.web\.whatsapp\.com
acl noSSLInterception ssl::server_name_regex .whatsapp\.net
acl noSSLInterception ssl::server_name_regex (w[0-9]+|[a-z]+)\.threema\.ch
acl noSSLInterception ssl::server_name_regex .threema\-forum\.de
acl noSSLInterception ssl::server_name_regex .threema\.ch
Unter „custom options (SSL/MITM)“ muss dann noch festgelegt werden, wie ssl_bump vorgehen soll. Hier wird analog zu „Splice whitelist, bump otherwise“ vorgegagngen, nur statt der whitelist die oben erstellte ACL „noSSLInterception“ angegeben. Das Feld „custom options (SSL/MITM)“ sieht somit folgendermaßen aus:
ssl_bump peek step1
ssl_bump splice noSSLInterception
ssl_bump bump all
Nun noch speichern und squid bumped alles außer WhatsApp und Threema Web. ClamAV scannt jetzt ebenfalls jeglichen HTTPS-Traffic (außer WhatsApp und Threema).
Fazit
Wem SquidGuard als Web-Filter wichtig und vor allem ausreichend ist, der wählt „Splice All“ und wird damit froh und zufrieden. Wer mehr will, der muss sich etwas tiefergehender mit SSL/TLS, HTTPS und squid beschäftigen um sein System so zu konfigurieren, wie er es gern hätte.
Viel Spaß beim Ausprobieren.