Teams und HTTP Proxy Caching

Bandbreite kann man angeblich nie genug haben aber sie ist nicht endlos. Diese Seite beschreibt, wie ein Proxy-Server mit Caching z.B. die Ladezeiten von Teams und Apps optimieren kann. Auch die Bandbreite von Teams LiveEvent und Teams Townhall Meetings kann ein korrekt konfigurierter Proxy optimieren.

Spoiler: Der Einsatz von einem internen HTTP-Proxy zum Cachen von bestimmten Inhalten ist möglich und kann sinnvoll sein. Aber Sie müssen SSL-Inspection für die gewünschten Ziele aktivieren.

Teams Datenströme

In aller Kürze möchte ich noch einmal auf die Teams Media-Steams und Übertragungen eingehen, denn nur ein ganz kleiner Teil ist "Proxy-tauglich".

Workload Protokoll Daten Cache möglich/sinnvoll

Teams Application (HTML, JavaScript, CSS, Bilder, Klingeltöne (.mp3) etc.)

HTTPS

Identisch

Ja/Ja

Teams Daten (Präsenz, Chat, Gruppendiskussionen, OneDrive Zugriffe)

HTTPS

Individuell

Nein/Nein

Teams 1:1 Audio/Video

UDP/TCP/HTTP

Individuell

Nein/Nein

Teams N:M Meeting Audio/Video

UDP/TCP/HTTP

Individuell

Nein/Nein

Teams LiveEvent/Townhall Meeting Producer

UDP/TCP/HTTP

Individuell

Nein/Nein

Teams LiveEvent/Townhall Teilnehmer

HTTPS

Identisch

Ja/Ja

Teams LiveEvent/Townhall eCDN Teilnehmer

Websocket und P2P-UDP

Identisch

Nein/Nein

Es bleiben also nur zwei Datenübertragungen überhaupt im Fokus, da alle anderen Übertragungen entweder individuelle Inhalte sind und im Cache keinen Sinn machen oder als P2P-Traffic sowieso nicht durch einen Proxy laufen würden oder laut Microsoft am besten am Proxy vorbei geroutet werden sollten. Aber auch für die beiden grünen Übertragungen müssen wir noch einmal hinschauen, ob ein Cache hier auch funktionieren kann.

HTTPS und Caching

Damit Datenübertragungen von einem HTTP-Proxy tatsächlich auch gecached werden, müssen einige Voraussetzungen erfüllt sein.

  • Sichtbarkeit und SSL Inspection
    Der Proxy muss natürlich den Request sehen und verstehen. Das funktioniert nur mit HTTP-Verbindungen ohne besondere Vorarbeiten. Da mittlerweile aber die überwiegende Anzahl an Verbindungen auf HTTPS setzt, sieht ein Proxy-Server nur die "CONNECT"-Anforderung und danach nichts mehr. Für ein Caching von HTTPS-Verbindungen ist es zwingend erforderlich, dass der Proxy eine SSL-Inspection für diese URLs umsetzt.
    Microsoft stellt speziell die Updates nicht per HTTP bereit, da TLS nicht nur die Verschlüsselung erlaubt, sondern vor allem sicherstellt, dass Sie den richtigen Server erreicht haben und die Daten bei der Übertragung nicht verändert wurden. Das ist insbesondere für Code wichtig.
  • Cacheable URL
    Wenn mehrere Clients die gleichen Informationen abrufen, dann sollten alle auch die gleiche URL nutzen. Wenn Webseiten dahinter aber Parameter oder sei es nur Tracking-Daten addieren, dann ist das für den Proxy eine andere URL und damit nicht mehr für den Cache relevant.
  • Authentifizierung
    Aber auch eine gleiche URL bedeutet nicht unbedingt, dass auch der gelieferte Inhalt identisch ist. Wenn zwei Nutzer die gleiche URL aber unterschiedlichen vorherigen Anmeldungen aufrufen, dann wäre eine Auslieferung der falschen Daten aus dem Cache natürlich ein Problem. Eine gute Webapplikation sollte solche Daten natürlich mit einem sehr kurzen Timeout oder als "nicht Cachebar versehen.
  • Server Cache Timeout
    Ich habe aber auch schon Webseiten gesehen, die serverseitig einen sehr kurzen Cache oder "NoCache" einstellen, um die Zugriffe mehrerer Personen hinter einem Proxy zählen zu können. Sicher kann ein Proxy einen HEAD-Request absetzen, um die Aktualität seines Cache zu prüfen aber letztlich entscheidet der Webserver, ob er ein "not modified" oder "modified" ausliefert und damit den Cache untauglich macht.
  • Client Cache Request
    Aber auch der Client kann dem Proxy-Server befehlen, dass er die Daten nicht aus dem Cache sondern aus dem Original bekommen möchte.

Daher müssen wir uns den ein oder anderen Request einfach mal anschauen. Übrigens hat natürlich auch ihr Client eine Cache und speichert statische Inhalte lokal zwischen. Einige Browser laden sogar schon vorsorglich weitere Seiten, damit sie beim Anklicken schneller erscheinen und auch Webseitenbetreiber können z.B. mittels JavaScript weitere Inhalte schon einmal anfordern. Wie immer gibt es zu dem Thema auch eine RFC und viele weitere Seiten:

HTTP-Feld: Cache-Control

Die Steuerung des Cache erfolgt seit HTTP 1.1 über das Feld "Cache-Control", welches mehrere Wert enthalten kann. Das Feld kann sowohl beim Zugriff vom Client zum Server als auch vom Server zum Client gesetzt sein. Hier ein Beispiel von Firefox beim Zugriff auf https://www.msxfaq.de und die Antwort darauf

GET / HTTP/1.1
Host: www.msxfaq.de
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: _ga=GA1.1.2132152683.1629900119; _ga_FMY31V3QXY=GS1.1.1703017660.8.0.1703017670.0.0.0
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
If-Modified-Since: Wed, 06 Dec 2023 23:56:01 GMT
If-None-Match: "57b5-60be017d9e640-gzip"

Hier wird erst einmal kein "Cache-Control" gesetzt aber anscheinend hat Firefox eine ältere Version in seinem Cache und nutzt den Header "If-Modified-Since", um dem Webserver eine passende Antwortmöglichkeit zu geben, z.B. ein "Not modified" zu senden. Die Antwort auf den Request enthält folgende Header:

HTTP/1.1 200 OK
Date: Fri, 29 Dec 2023 19:07:41 GMT
Content-Type: text/html
Content-Length: 6523
Connection: keep-alive
Server: Apache
X-Frame-Options: SAMEORIGIN
Last-Modified: Tue, 26 Dec 2023 02:13:27 GMT
ETag: "595a-60d603a55ffc0-gzip"
Accept-Ranges: bytes
Cache-Control: private, must-revalidate
Expires: Fri, 29 Dec 2023 19:16:01 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
Referrer-Policy: origin-when-cross-origin
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000; includeSubDomains
Permissions-Policy: interest-cohort=()

Sie sehen hier gleich mehrere Felder, die das Caching beeinflussen, z.B. Last-Modified, ETag, Cache-Control und Expires. Das Feld "Cache-Control" enthält hier nur "private, must-revalidate". Es können aber noch weitere Werte gesetzt sein, z.B.:

Feld

Bedeutung

max-age

Anzahl in Sekunden, die eine Antwort genutzt werden darf

s-maxage

Dauer in Sekunden, die der Inhalt in einem Shared Cache vorgehalten werden darf.

must-revalidate.

Der Cache muss die Quelle erneut fragen und die Gültigkeit prüfen

proxy-revalidate

Weist den Proxy separat an, eine Information erneut zu überprüfen

no-transform

Der Inhalt darf nicht verändert werden, z.B. "Content-Encoding" etc.

Beachten Sie, dass diese Header nicht Teil der HTML-Datei auf einem Webserver sind sondern vom Webserver (.htacces) oder einem Script gesetzt werden können.

Neben dem Feld "Cache-Control" gibt es auch weitere native Felder:

Feld

Bedeutung

Expires

Zeitpunkt, ab wann die Information nicht mehr gültig ist

pragma

Alter früherer Eintrag um Caching zu steuern

ETag

Wenn eine Information abgelaufen ist, müsste der Client oder Proxy die komplette Seite wieder holen. Der Webserver kann aber eine eindeutige Zahl im Feld "ETAG" hinterlegen. Wenn dann der Client oder Server beim Revalidieren nur den Header holt und sich der ETag nicht geändert hat, dann ist die Information im Cache wieder gültig

Last-Modified

Zeitpunkt der letzten Änderung. Als "max-age", "Expires" etc. noch nicht genutzt wurden, haben einige Clients die Dauer seit der letzten Änderung als Anhaltspunkt für die weitere Gültigkeit missbraucht.

Teams Client im Browser

Ausgestattet mit diesen Informationen können wir nun mal schauen welche Clients für welche Zugriffe ein Caching erlauben oder nutzen würden. Dazu zählt natürlich auch der Teams Client und insbesondere Updates. Zuerst habe ich dazu Microsoft Teams in einem neuen Browser-Fenster gestartet, welches aber früher schon einmal Teams gestartet hatte. Damit erwarte ich dass im Cache schon eine "alte Teams-Version" oder zumindest alte Bestandteile zu finden sind. Da Microsoft Teams als "Moderne App" ja quasi in JavaScript geschrieben ist und das keine große monolithische JS-Datei ist, habe ich jede Menge Requests gesehen:

Auch statische Inhalte wie z.B. die MP3-Dateien der Klingeltöne werden geladen. Wenn Sie die "Size"  anschauen, dann sind das schon einige Kilobyte, die da pro Client zusammen kommen, wenn diese nicht mehr im lokalen Cache vorliegen.

Sie können aber auch gut erkennen, dass Microsoft für die statischen Inhalte extra einen eigenen Hostnamen nutzt:

https://statics.teams.cdn.office.net

Die Daten kommen hier nicht von https://teams.microsoft.com, sondern einem eigenen Content Delivery-Netzwerk für statische Inhalte. Damit entlastet Microsoft natürlich die eigentlichen Teams-Services, die dann nur noch die individuellen Daten liefern müssen und die CDN-Server können näher bei dem Kunden stehen. Die DNS-Anfrage zeigt auch auf Dienste von Akamai:

C:\>nslookup statics.teams.cdn.office.net

Name: a1813.dscd.akamai.net
Addresses: 2a00:6020:100:800::b916:8c10
2a00:6020:100:800::b916:8c11
185.22.140.17
185.22.140.16
Aliases: statics.teams.cdn.office.net
teams-staticscdn.trafficmanager.net
statics.teams.cdn.office.net-c.edgesuite.net
statics.teams.cdn.office.net-c.edgesuite.net.globalredir.akadns.net

Die Bereitstellung erfolgt (Stand Dez 2023) per Geo-DNS und nicht über Anycast-Routing. Abhängig vom jeweils gefragten DNS-Server kommen andere Adressen zurück. Sie sollten auf jeden Fall sicherstellen, dass ihr Namensauflösung immer entlang des IP-Routings verläuft.

Die Klingeltöne sind natürlich dankbare Dateien, die sich nicht ändern, anonym erreichbar sind und cachebar sind. Ein Request vom Client zum Server war:

Die Antwort liefert die 304353 Bytes MP3-Datei aber auch die Information, dass diese Datei "public" und 365 Tage gepuffert werden darf!

Zudem liefert der Server ein eindeutiges "Etag"-Feld mit, so dass ein Proxy oder Client auch später noch einmal nachfragen kann, ob er die Datei neu laden muss. Haben Sie auch das Feld "Last-Modified" gesehen? Die Datei ist tatsächlich schon einige Monate unverändert. Wer sie sich anhören möchte. Hier ist der Link:

Ein Download ist auch nicht schwer:

Invoke-WebRequest `
   -Uri https://statics.teams.cdn.office.net/hashed/audio/ring-fb90357.mp3 `
   -OutFile ring- fb90357.mp3

Es ist der 8 Sekunden lange "Klingelton", wenn Sie mit Teams einen anderen Teilnehmer anrufen.

Ich frage mich schon, ob ein Freizeichen wirklich mit 48kHz, Stereo und 32Bit bei 320kB/s gesampelt werden muss, wenn die meisten MP3-Songs mit 128kBit oder 196kBit und 8-Bit Stereo codiert sind. Das weiß aber wohl nur Microsoft, warum 8 Sekunden 297kByte groß sein müssen, wo doch auch 120kbyte reichen würden.

Wir haben also durchaus Potential durch ein Caching hier Bandbreite zu sparen. Da diese Dateien sogar von einem eigenen Hostnamen kommen, könnten Sie über eine "proxy.pac"-Datei gezielt diese Zugriffe über einen Proxy leiten.

Leider habe ich keine Daten einer produktiven Cache-Instanz, die das Einsparungspotential aufzeigen könnte.

In dem Zuge habe ich mal schauen wollen, was denn auf meinem Client im Cache liegt. Ich musste feststellen, dass es mit modernen Browsern gar nicht mehr so einfach ist, über das Dateisystem den Cache anzuschauen. Im Browser selbst wird nur noch die Größe angezeigt und das Löschen angeboten. In den Verzeichnissen liegen nur scheinbar zufällig benannte Dateien.

%LOCALAPPDATA%\Google\Chrome\User Data\Default\Cache\Cache_Data
%LOCALAPPDATA%\Microsoft\Edge\User Data\Profile 1\Cache\Cache_Data

Aber es gibt Dritthersteller wie z.B. Nirsoft, die einen Einblick erlauben:

Ich kann hier jede Datei einzeln anschauen und vor allem die Cache-Control-Werte sehen. Hier am Beispiele eines Benutzerfotos.

Diese Information wird also bis zu 5184000 Sekunden (=60 Tage) gehalten. Folgende Cache-Zeiten habe ich gefunden:

Information Cache-Control

 

 

Teams Benutzerfoto
https://teams.microsoft.com/api/mt/emea/beta/users/8:orgid:<guid>/profilepicturev2?displayname=<name>&size=HR64x64
private, max-age=5184000, stale-while-revalidate=5184000

 

 

Teams Klingelton
https://teams.microsoft.com/assets/audio/ring.mp3
public,max-age=31536000

 

 

Teams JavaScript
https://teams.microsoft.com/ ... /Serviceworker.js
no-transform, max-age=5400, private

 

 

Teams JavaScript
https://statics.teams.cdn.office.net/ ... teams_enterprise_m24.js
public, max-age=604800

 

 

Sharepoint
https://static2.sharepointonline.com/files/fabric/assets/icons/fabricmdl2icons.woff2?2.21
public, max-age=23318415

 

 

Auch viele anderen Firmen, z.B. Facebook etc. nutzen JavaScript-Dateien, die einen "hashwert" als Dateinamen haben und im Cache durchaus 365 liegen können. Das ist auch nicht sonderlich schlimm, wenn sie als Betreiber der Webseite eine neue Version ihres JavaScript mit dem geänderten Hashwert Bereitstellung und verlinken.

Durch die Technik die Datei mit einem Hashwerte zu bekennen erlaubt es dem Cache die Dateien lange vorhalten. Er muss auch nicht regelmäßig deren Aktualität prüfen. Sie ändern sich nämlich nie aber werden irgendwann einfach nicht mehr verwendet.

Das macht es aber natürlich interessant, diese Dateien auch entsprechend zu cachen.

Teams 2.1 Client Update

Deutlich kniffliger ist die Analyse des Teams Update. Der vollwertige Teams-Client lädt die Updates ja im Hintergrund herunter und startet dann einfach durch. Auf der Seite Teams Client Update habe ich für den "classic Client" den Prozess auseinander genommen. Der New Teams Client / Teams 2.1 nutzt allerdings eine andere Technik. Mittels "Get-AppxPackage" kann ich einen installierten Teams Clients ermitteln aber es gibt kein "Update-AppxPackage" um eine Aktualisierung zu starten.

PS C:\> Get-AppxPackage -Name MSTeams

RunspaceId             : 1bdabcb3-53dd-4979-871d-58256d82bed7
Name                   : MSTeams
Publisher              : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
PublisherId            : 8wekyb3d8bbwe
Architecture           : X64
ResourceId             :
Version                : 23320.3021.2567.4799
PackageFamilyName      : MSTeams_8wekyb3d8bbwe
PackageFullName        : MSTeams_23320.3021.2567.4799_x64__8wekyb3d8bbwe
InstallLocation        : C:\Program Files\WindowsApps\MSTeams_23320.3021.2567.4799_x64__8wekyb3d8bbwe
IsFramework            : False
PackageUserInformation : {}
IsResourcePackage      : False
IsBundle               : False
IsDevelopmentMode      : False
NonRemovable           : False
Dependencies           : {}
IsPartiallyStaged      : False
SignatureKind          : Developer
Status                 : Ok

Im Installationsverzeichnis findet sich auch eine "AppxManifest.xml" mit dem Hinweis auf die im gleichen Verzeichnis liegenden "ms-teamsupdate.exe". Das Programm hat aber weder eine Hilfe noch reagiert es auf Parameter. Also musste ich eine alte VM reaktivieren, auf der ein alter neuer Teams Client installiert war und mit Fiddler betrachten, welche Daten Teams nachlädt. Wie erwartet werden jede Menge JavaScript-Dateien vom Task "msedgewebview2" geladen.

Fast alle Dateien haben die Cache-Control-Eintrag auf "public" und "max-age: 31556926" erlaubt ein Caching für etwas mehr als 365 Tage. Es gibt keinen "Authentication Header", d.h. der Abruf ist anonym möglich, was ich per PowerShell auch einfach verifizieren konnte.

Das bedeutet aber hier, dass ein HTTP-Proxy mit SSL-Decryption und Cache für die URL "statics.teams.cdn.office.net" ziemlich viel Bandbreite sparen kann, insbesondere wenn viele Clients an einem Standort sind.

Sie können zwar aus den Zugriffsprotokollen im Proxy dann sogar sehen, welche Client-IP sich schon die Updates gezogen hat, aber zur Inventarisierung gibt es bessere Ansätze, z.B. "Get-AppxPackage -Name MSTeams".

Teams A/V-HTTPProxy Caching

Bislang haben wir uns um die relativ statischen Installationsquellen gekümmert. Der neue Teams Client hat einen Umfang von ca. 130MByte (Dez 2023) und wenn 1000 Clients an einem Standort eine neue Version beziehen, dann kann ein Caching hier 130 Gigabyte Transfervolumen sparen. Das kling viel aber ist nichts im Gegensatz zu einem Meeting.

Schon am Anfang habe ich beschrieben, dass die klassischen Teams 1:1-Verbindungen und Teams Konferenzen gar nicht über HTTPS laufen sondern sinnvollweise ihre Bilder und Töne über UDP übertragen. Selbst wenn Sie Teams zu HTTPS zwingen, wird ein Proxy mit Caching nicht bringen, da jeder Teilstream individuell verschlüsselt ist.

Wenn es aber um sehr große Teams-Meetings geht, die als LiveEvent/Townhall-Meeting übertragen werden, dann kommt wieder HTTPS zum Einsatz und hier ist kann ein geeigneter Proxy Bandbreite sparen. Hier macht es auch Sinn, wenn eine Teilnahme an einem Townhall-Meeting mit Audio und Video generiert auch gerne mal 1-2 Megabit/Sekunde. 8 Sekunden sind dann schon mindestens 1 Megabyte und nach 17 Minuten haben wir schon die gleiche Datenmenge übertragen, die ansonsten durch die Installation verbraucht wurde.

Die benötigte Bandbreite ist dabei im Zeichen von "Flatrates" weniger ein Kostenproblem sondern einfach eine Kapazitätsfrage. Dabei müssen Sie den kompletten Pfad von dem Client bis zum ausliefernden Service betrachten, d.h. ihr LAN, ihre Firewall und ihr Internetanschluss aber genauso gut auch die Kapazitäten beim Provider und sein Peering zu Microsoft oder seinem Upstream-Provider.

Live Events und Teams Townhall Meetings sind natürlich nicht so zeitkritisch wie ein klassisches Meeting und alle Teilnehmer sehen exakt die gleiche Information. Da stellt sich dann schon die Frage, ob der Request und die Daten durch einen HTTP-Proxy als Cache optimiert ausgeliefert werden können. Bei Microsoft finde ich dazu:


Quelle: https://learn.microsoft.com/en-us/microsoftteams/teams-stream-troubleshooting#preparing-your-network-for-many-concurrent-viewers

Das klingt doch schon einmal vielversprechend. Allerdings ist da ein "Aber" mit im Bild, denn ein HTTP-Proxy kann nur cachen, was er "sieht". Aber selbst dies zumindest beschrieben aber bestätigt damit auch, dass es funktionieren kann:


https://learn.microsoft.com/en-us/microsoftteams/proxy-servers-for-skype-for-business-online#if-you-need-to-use-a-proxy-server 

Allerdings hält diese Seite noch eine weitere Aussage bereit, die explizit auf die SSL-Inspektion eingeht und zwei Domains nennt, die man bitteschön von der SSL-Inspektion ausnehmen und idealerweise sogar als Bypass durchlassen sollte:


https://learn.microsoft.com/en-us/microsoftteams/proxy-servers-for-skype-for-business-online#additional-recommendations-for-teams-live-events-and-teams-view-only-meetings 

Beide Adressen sind auch in den Office 365 IP-Adressen aufgeführt. Allerdings ist "bmc.cdn.office.net" nur unter "*.office.net" einzuordnen. Der "*" bedeutet also auch weitere Subdomains.


https://learn.microsoft.com/de-de/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide

Eine weitere Fundstelle ist:


https://learn.microsoft.com/en-us/microsoftteams/view-only-meeting-experience#networking-considerations

Das ist nun gerade nicht, was ich erhofft habe.

Ich hätte mir gewünscht, dass die HTTP-GET-Requests auf die Media-Blöcke unverschlüsselt erfolgen würden und die Payload mit einem für alle Teilnehmer kleinen Meetingkey verschlüsselt ist und damit HTTP-Proxy-Server ganz ohne SSL-aufbrechen ein Caching durchführen können.

Ich habe dann ein LiveEvent/Townhall-Meeting gestartet und auf zwei PCs als Teilnehmer die Pakete mit Fiddler mitgeschnitten.


Fiddler-Ausschnitt Live Event Teilnehmern

Ca. alle 2 Sekunden wird ein Audio-Ausschnitt und ein Video-Ausschnitt per HTTPS von Microsoft heruntergeladen. mit 20kByte Audio/Sekunde kommen wir auf 10KBytet/Sek oder ca. 100kbit. Die Datenmenge bei Video ist natürlich deutlich höher, die 12 Abschnitte über eine Zeit von ca. 20 Sekunden haben ca. 2,2MByte was auf ca. 1100kBit/Sek auf einen 720p-Stream hinweist. Hier ein exemplarischer Request und die Antwort:

Im Request gibt es keinerlei Hinweis auf eine Art "Authentication", d.h. weder Cookies, noch "Authentication"-Header oder Formularfelder oder Individualisierung für den Teilnehmer . Ein Abruf per Invoke-Webrequest funktioniert tatsächlich und liefert die Datei.

Interessant sind hier auch die Header im Bezug auf Caching, die Fiddler sehr schön auseinandernimmt.

HTTP/200 responses are cacheable by default, unless Expires, Pragma, or Cache-Control headers are present and forbid caching.
HTTP/1.0 Expires Header is present: Tue, 02 Jan 2024 02:43:25 GMT

Legacy Pragma Header is present: IISMS/6.0,IIS Media Services Premium by Microsoft
!! WARNING: IE supports only an EXACT match of "Pragma: no-cache". IE will ignore the Pragma header if any other values are present.

HTTP/1.1 Cache-Control Header is present: max-age=259200
	max-age: This resource will expire in 72 hours. [259200 sec]

HTTP/1.1 ETAG Header is present: "Ny8xNS8yMDEz"

Die Daten könnten also bis zu 72 Stunden im Cache gehalten werden. Das Feld "X-Cache" im Header gibt gut Auskunft, ob die Daten aus dem Cache des Content Delivery Netzwerk (CDN) oder erst vom Ursprungsserver geholt werden mussten.


Quelle: https://learn.microsoft.com/de-de/azure/cdn/cdn-msft-http-debug-headers#response-header-format

Das AzureCDN ist quasi auch "nur" ein Proxy mit Cache, der hier aber nun in Gegenrichtung konfiguriert ist, d.h. als Reverse Proxy. Da ich das Meeting einige Wochen nicht genutzt habe, liegen die Informationen dann nur noch auf dem Heimserver und der Reverse Proxy kann sie Sie nicht aus seinem Cache liefern. Daher finde ich ein Feld "X-Cache:TCP_MISS" im Header.

(Invoke-Webrequest `
 -URI ("http://endpoint1-s00prddencompsvc.prd.bmc.cdn.office.net/" `
      +"b1080223-6624-401c-816d-c79e9cbcc912" `
      +"/9fe43086-dcaf-4e4d-bdbb-0bcdcb7598f7.ism" `
      +"/QualityLevels(96000)/Fragments(audio=10848337280,format=mpd-time-csf)")).headers."X-Cache"

Wenn ich mir die URL zweimal hole und den Header "X-Cache" anschaue, dann sehen sie beim ersten Aufruf auch den "TCP_MISS" und dem Folgeaufruf den "TCP_HIT".

Sobald mehrere Clients bei Microsoft über den gleichen Cache-Server die Daten abrufen würden, könnte Microsoft die Daten aus dem Cache ausliefern und im Header ein "X-Cache: TCP_HIT" setzen. Ich habe auch den Wert "TCP_REMOTE_HIT" gefunden. Anscheinend meldet das dann eine Proxy, der die TLS-Verbindung aufgebrochen hat. In dem Fall war es das Azure CDN, welches als Reverse Proxy den Zugriff von Extern aus dem Cache bedient.

Das wirft nun natürlich wieder Fragen auf, wie Microsoft z.B. mehrere Clients aus der gleichen Region zum gleichen Cache weiterleiten. Bei ausgehenden Proxy-Servern kenne ich das Verfahren den Hostnamen zu einem numerischen Hashwert zu konvertieren und durch die Anzahl der Proxy-Server zu teilen. So sollten alle Clients beim Zugriff auf das gleiche Ziel immer den gleichen Proxy nutzen, was die Cache-Trefferrate erhöht.

HTTP statt HTTPS

Ich habe aktuell keinen Test dahingehend gemacht, die Verbindung per HTTPS zu "*.cdn.office.net" zu verbieten und darauf zu hoffen, dass der Client vielleicht auf HTTP umschwenkt und damit ein HTTP-Proxy auch ohne TLS-Inspection. Aber die URLs sind auch ohne HTTPS erreichbar.

Theoretisch könnte ein Townhall Meeting Client die Daten auch ohne HTTPS herunterladen und entsprechen ein Proxy ohne SSL-Inspection ein Caching vornehmen. Wenn ich dies mit meinem lokalen Squid Proxy probiere, dann sehe ich im Header X-Cache sogar beide Einträge:

Allein die Tatsache, dass die Verbindung auch unterschlüsselt per HTTP möglich ist, ist keine Zusicherung, dass dieser Weg auch genutzt würde. Theoretisch könnte ich auf einem Proxy Server  den HTTPS-Zugriff auf die verschiedenen Streams-Endpunkte von Microsoft unterbinden und darauf hoffen, dass der Townhall Client vielleicht auf HTTP schwenkt und mir damit das Caching vereinfacht. Ich habe dies aber nicht ausprobiert, da Microsoft, der Proxy und der Client dann ja nicht mehr sicher sein könnten, dass sie wirklich den richtigen Stream betrachten. HTTPS ist ja nicht nur eine Frage der Verschlüsselung sondern auch der Überprüfbarkeit der Gegenstelle anhand des Zertifikats und quasi einer Signatur. In Zeiten von SEO-Marketing, Suchmaschinen, Let's Encrypt und der starken Verbreitung von TLS gehe ich auch nicht davon aus, dass der Townhall-Client auf HTTP umsteigen würde.

Auch die Pflege der per HTTPS zu unterbindenden Gegenstellen wäre eine aufwändige und sicher nicht 100% zuverlässige Tätigkeit. Sie können ja auch nicht pauschal den Zugriff auf "*.office.net" oder "*.cnd.office.net" unterbinden. Ein CDN kann ja auch Code, z.B. Updates, JavaScript etc., bereitstellen, bei denen die Authentizität sichergestellt sein muss.

Wenn nach einigen Monaten der Inhalt aber verfallen ist, dann kommt folgender Fehler:

Invoke-Webrequest : 41025007Asset streaming locator has expired. 
Please try changing the access policy on the locator.9b34e212-c6be-408a-b2d5-53d4ed3f8ff20f4496cd-4476-4e25-872d-823163c127cf

Wenn Sie A/V-Streams von Townhall-Meetings durch einen HTTPS-Proxy cachen wollen, dann funktioniert das nach meiner Einschätzung nur, wenn der Proxy die TLS-Verbindung aufbricht und so die Requests und Antworten im Klartext sieht.

Verifikation

Bislang waren alle Ausführungen nur Ergebnisse meiner Analysen und Textumgebung aber basieren nicht auf realen Messwerten bei Kunden. Es ist schon etwas aufwändiger, in einer kleinen Labor-Umgebung mehrere Clients bereitzustellen und einen Proxy-Server mit Cache SSL Inspection und Logging zu betreiben. Zudem wären aufgrund der kleinen Stichprobe die Ergebnisse mit Vorsicht zu betrachten.

Hier wäre ich dann doch mal auf Rückmeldungen aus der Leserschaft angewiesen, die Daten bereitstellen würden wie:

Anzahl Clients

Verwendeter Proxy

SSL Inspection Aktiv

Cache-Größe

Teams Code Total/Cache

LiveEvents/Townhall Total/Cache

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Die Frage bleibt nun aber, ob ein HTTP-Proxy, der die Verbindung per TLS-Inspection aufbricht, die Inhalte vernünftig cachen kann. Dazu müsste ich einen HTTP-Proxy mit TLS Inspection für die fraglichen URLs UND Caching konfigurieren. Oder vielleicht würde Teams auch ohne SSL ein Rückfall auf HTTP machen?. Alles noch offene Fragen.

Das klingt alles interessant, aber dürfte mehrere Tage Aufwand bedeuten, die ich aktuell noch nicht aufgewendet habe. Vielleicht ist ein Kunde ja bereit, mit mir so ein Setup komplett durchzuspielen.
Und das ist sicher ein Thema für eine eigene Seite auf der MSXFAQ

Fiddler wäre ein schnell aufzusetzender SSL-Inspection Proxy, der aber leider keinen Cache bereitstellt. Basierend auf meinen Vorarbeiten von Squid-Proxy auf WSL mit Kerberos würde ich eher Squid einsetzen. Squid dürfte auch der Unterbau auf vielen Appliances und Firmen sein.

eCDN und Websockets-Caching

Wer eine eCDN-Lizenz für all seine Anwender kauft, kann natürlich auch anstatt des HTTP-Proxy-Servers auf die interne Verteilung von Client zu Client setzt. Dazu laden sich wenige Clients die A/V-Daten von Microsoft und verteilen diese intern weiter. Interessanterweise nutzt Microsoft dazu nicht HTTPS-Download von 2 Sekunden langen Blöcken, sondern die Clients verbinden sich über Websockets mit dem Server.

Ein Proxy-Server kann die Nutzung von Websockets unterbinden oder zulassen. Allerdings ist das Kommunikationsverhalten dabei komplett unterschiedliche. Bei der Nutzung von Websockets wird ein HTTP/HTTPS-Request an den Server gemacht, der aber ein "Upgrade" der Verbindung zu Websockets anfordert und danach einen bidirektionalen Kanal überträgt.

Nach meiner Einschätzung kann ein Proxy-Server solche Daten nicht wirklich cachen, da es keine sich wiederholenden HTTP-Requests gibt, deren Antworten beim ersten Mal von extern geladen und dann aus dem Cache bedient werden können.

Insofern würde ich eher prüfen, ob sie Townhall-Meetings über einen HTTP-Proxy mit SSL-Inspection cachen können.

Weitere Links

Auf den den folgenden Seiten habe ich die Kommunikation per HTTP und eines HTTP-Proxy etwas weiter beschrieben.