Teams Turn over TCP

Wenn zwei Team-Teilnehmer sich nicht direkt per IP erreichen können oder eine Konferenz stattfindet, dann kommen Transport-Relays mit öffentlichen IP-Adressen von Microsoft zum Einsatz, welche die Audio/Video/Desktop-Sharing-Daten übertragen. Diese Seite beschreibt die Details zu den TURN-Servern per TCP etwas genauer.

Endpunkte in der Cloud

Idealerweise werden Audio/Video-Daten natürlich über UDP übertragen. Verlorene oder zu spät eintreffende Daten können bei UDP einfach verworfen werden und werden nicht erneut übertragen. Zudem kann dies dann die Applikation erkennen und sich anders verhalten, z.B. die Auflösung bei Video reduzieren um die Datenrate zu senken oder Forward Error Correction (FEC) einsetzen. Aber es gibt auch Daten, die müssen verlustfrei übertragen werden, z.B. Dateien in Skype for Business. Oder eine Firewall blockiert UDP, weil die Firma zwingend auf Proxy-Server u.a. aufsetzt. Dann kann die Applikation nur TCP nutzen. Daher publiziert Microsoft nicht nur die IP-Adressen für UDP-Relays, sondern die gleichen Adressen gelten auch für TCP.


Quelle: https://docs.microsoft.com/de-de/microsoft-365/enterprise/urls-and-ip-address-ranges?view=o365-worldwide#skype-for-business-online-and-microsoft-teams

Sie sehen in Regel 11, dass die UDP-Adressen auf "Optimize Required" geführt werden und auch per "Express Route" bereitgestellt werden. Die Regeln 12 und 13 decken dann die TCP-Ports ab. Im Feb 2021 waren beide Dienste noch mit den gleichen Adressen gelistet. Dass Microsoft für Teams und Skype for Business die gleichen Service im Backend nutzt bestätigt auch ein Artikel aus 2017

As we've shared at Ignite and in other blogs, there is a change underway to Office 365 Skype for Business. With the new IP and Port ranges in use for both Skype for Business and Teams when using Transport Relay there are customers who are having challenges completing media setup using these IPS and ports.
Transport Relay Evaluation - CQD https://techcommunity.microsoft.com/t5/skype-for-business-blog/transport-relay-evaluation-cqd/ba-p/137291

Ich gehe davon aus, dass auch nach der Abschaltung von Skype for Business Online die Services weiter genutzt werden, da auch Office 365 Benutzer ja weiter in Besprechungen teilnehmen müssen, die z.B. von Firmen mit Skype for Business 2019 und höher gehostet werden.

In dem Zuge möchte ich noch mal auf eine klare Aussage Richtung Firewall hinweisen:

...For Teams to function correctly, you must open TCP ports 80 and 443 from the clients to the internet, and UDP ports 3478 through 3481 from the clients to the internet. ...
...Opening these ports is essential for a reliable Teams deployment. Blocking these ports is unsupported and will have an effect on media quality...
...If your organization requires that you specify the exact IP address ranges and domains to which these ports should be opened, you can restrict the target IP ranges and domains for these ports. ...
...In the event of a proxy server being deployed, we recommend that you bypass the proxy server for all Teams services. Although using a proxy might work, it's very likely that quality will be reduced due to media being forced to use TCP instead of UDP ...
https://docs.microsoft.com/en-us/microsoftteams/3-envision-evaluate-my-environment#firewall-and-proxy-requirements

MediaRelay Endpunkte

Wenn Sie sich die Adressen von Teams und Skype for Business Online anschauen, dann finden Sie erst einmal drei mächtig große IP-Adressbereiche mit 262144 + 262144 + 16384 Adressen. Ich vermute mal, dass diese Bereiche die geografischen Gegebenheiten spielen, denn in Europa habe ich im immer nur Gegenstellen aus 52.112.0.0/14 gesehen. Aus verschiedenen Dokumentationen habe ich dann auch einige DNS-Namen ermitteln, die auf diese Bereiche verweisen (Stand Feb 2021)

DNS-Namen IP-Bereich Region
world52.tr.teams.microsoft.com
eu52.tr.teams.microsoft.com
tr.teams.microsoft.com
a-tr-teasc-euwe-08.westeurope.cloudapp.azure.com

52.112.0.0/14

Ich habe diese Adressen für europäische Teams-Kandidaten gesehen.

?

52.120.0.0/14

Ich vermute mal, dass dieser große Bereich für USA, Canada u.a. genutzt wird

world.tr.teams.microsoft.com

2620:1ec:40::2
13.107.64.2

Auch wenn hier "eu" erscheint, könnte ich mir vorstellen, dass hier die asiatischen Regionen abgebildet werden oder die Adressen per "Anycast" überall verwendet werden.

eu.tr.teams.microsoft.com

13.107.65.5 2620:1ec:41::5

Diese Mediarelay soll von den europäischen Kunten genutzt werden, damit die Audiodaten auch wirklich in Europa bleiben und nicht doch mal ein Relay aus einer anderen Region genutzt wird. Das ist z.B. in Randbereichen ein Team

mediaedge1E.online.lync.com  (SfB Online EU)

52.112.0.0/14

Skype for Business Online Edge EMEA
Liegt im gleichen Bereich wie Teams TR  und nimmt Verbindungen auf Port 443 an aber macht keinen klassischen TLS-Handshake

edge.live.com (Skype Consumer?)

13.107.3.128

Reagiert auf TCP/443 mit TLS-Handshake und Zertifikat für "CN=Outlook.live.com"

edge.skype.com (Skype Consumer?)

13.107.3.128

Reagiert auf TCP/443 mit TLS-Handshake und Zertifikat für "CN=edge.skype.com"

global.tr.skype.com

13.107.8.2

Zertifikat ist aber tr.teams.microsoft.com

Anscheinend gibt es noch viel mehr Namen, die unter der Adresse *.relay.teams.microsoft.com und *.tr.teams.microsoft.com erscheinen.

TCP-Tests

Auf der Seite End2End-UDP3478 habe ich ein PowerShell-Script, welches sich als UC-Client ausgibt und kontinuierlich eine UDP-Verbindung zum TURN/UDP-Server prüft. So kann sich sehr schnell kurze Aussetzer in einer Verbindung erkennen. Der gleiche Test kann nur sehr viel aufwändiger mit TCP erfolgen, denn da reicht kein einfaches Paket. Wer nicht selbst per RAW-Sockets sich einen TCP-Stack programmieren will, kann nur einen TCP-Socket aufbauen und die komplette Abwicklung des Handshake übernimmt Windows. Als Applikation haben Sie keinen direkten Zugriff auf die darunterliegenden Parameter und können vor allem keine Paketverluste o.ä. selbst messen.

Dennoch kann es hilfreich sein, regelmäßig eine TCP-Verbindung zu starten und sogar einen TLS-Handshake zu starten, das Zertifikat zu lesen und die Zeiten zu messen. Darauf gehe auf End2End-TCP noch weiter ein. Hier beschränke ich mich auf die Erkenntnisse einer solchen Serie. Ich habe dazu am 1. Feb 2021 über eine Dauer von 10h immer wieder TCP-Connections zu "tr.teams.microsoft.com" aufgebaut und dabei mehrere Daten erfasst. Hier die Ausgabe einer einzelnen Verbindung:

datetime                       : 2021-02-12 13:46:01Z
remotehost                     : tr.teams.microsoft.com
remotename                     : a-tr-teams-frcn-08.francecentral.cloudapp.azure.com
remoteip                       : 52.112.173.78
Port                           : 443
Status                         : OK
SslProtocol                    : Tls12
CipherAlgorithm                : Aes256
HashAlgorithm                  : Sha384
KeyExchangeAlgorithm           : 44550
CN                             : CN=tr.teams.microsoft.com
Subject                        : CN=tr.teams.microsoft.com
NotAfter                       : 26.11.2021 16:52:50
NotBefore                      : 26.11.2020 16:52:50
Issuer                         : CN=Microsoft RSA TLS CA 01, O=Microsoft Corporation, C=US
Thumbprint                     : 3A6E1AFFB01B4E092E4027DCF2FA874FA4D302A0
SerialNumber                   : 6B000364481F8F4E4869832568000000036448
SignatureAlgorithmFriendlyName : sha256RSA
dnstimems                      : 28
connecttimems                  : 22
tlstimems                      : 59
totaltimems                    : 120

So gut Powershell die Verbindungszeiten messen kann, hat es ca. 35ms gedauert, bis die TCP-Verbindung gestanden hat und nach 124ms seit Start hatte ich schon das TLS-Zertifikat. Der komplette Durchlauf dauerte gerade mal 129ms. Die kann man auch schön mit WireShark nachvollziehen.

Insgesamt gehen bei der Aktion 5179 Daten "Nutzlast" über die Leitung. Im "Server Hello" stecken auch noch weitere DNS-Namen.

Ich habe nun aber nicht getestet, welche Namen sich hinter "*" noch verbergen können. Allerdings bedeutet TLS nicht automatisch auch HTTPS. Ein Test mit "Invoke-Webrequest" hat das schnell gezeigt:

Es sieht auch für eine Firewall erst einmal nur wie eine TLS-Verbindung auf Port 443 aus. Aber es keine HTTPS-Verbindung. das macht es für Proxy-Server natürlich auch einfach, diese Verbindung umzusetzen, wenn Sie auch noch "reinschauen" wollen. Natürlich habe ich auch die TLS-Version vorgegeben und am 12. Feb 2021 hat das Teams Media Relay nur TLS 1.2 angenommen.

TLSLevel SSL TLS 1.0 TLS 1.1 TLS 1.2 TLS 1.3

Verbindung (Feb 2021)

Keine

Keine

Keine

Cipher: AES256 mit Hash:SHA384

Keine

Hier hat Microsoft schon ein TLS 1.2 Enforcement umgesetzt. Ältere Verfahren werden nicht mehr angeboten. Aber TLS 1.3 ist auch noch nicht erlaubt.

TURN over TCP

Leider ist die Verbindung zum TURN-Server über 443 per TLS verschlüsselt und der passenden privaten Key ist bei Microsoft. Ich kann also nicht direkt dort reinschauen, wenn ich keinen TCP-Proxy mit TLS-Proxy aufsetze. Aber ich habe von meinem Skript End2End-UDP3478 noch den TURN-Buffer über UDP. Also habe ich einfach mal diese Byte-Sequenz an die Gegenstelle gesendet. Meine Hoffnung war, dass ich wie bei TURN/UDP eine Antwort bekomme.

Leider ist das nicht der Fall. Zumindest die Teams Transport Relays sind einfach "stumm" geblieben. es kam kein Byte zurück.

Vielleicht lese ich hier irgendwann noch mal die WebRTC-Dokumente, auf deren auch Teams aufbaut

Auswertung mit PS

Diese Werte habe ich in eine CSV-Datei geschrieben und dann etwas in den Daten gestöbert. Die Zeilen in der Datei habe ich umgebrochen.

"datetime","Computername","remotename","remoteip","Port","Status","CN","Subject","NotAfter","NotBefore","Issuer","Thumbprint","SerialNumber",
   "SignatureAlgorithmFriendlyName","connecttimems","tlstimems","totaltimems"
"2021-02-01 00:22:51Z","tr..","b-tr-teasc-euno-05.northeurope.cloudapp.azure.com","52.114.251.80","443","OK","CN=tr.teams.microsoft.com",
   "CN=tr.teams.microsoft.com","26.11.2021 16:52:50","26.11.2020 16:52:50","CN=Mi..","xx","x","sha256RSA","33","112","126"
"2021-02-01 00:22:52Z","tr..","b-tr-teasc-euno-16.northeurope.cloudapp.azure.com","52.114.248.34","443","OK","CN=tr.teams.microsoft.com",
   "CN=tr.teams.microsoft.com","26.11.2021 16:52:50","26.11.2020 16:52:50","CN=Mi..","xx","xx","sha256RSA","30","106","119"



"2021-02-01 09:03:44Z","tr..","b-tr-teasc-ukwe-08.ukwest.cloudapp.azure.com","52.114.93.230","443","OK","CN=tr.teams.microsoft.com",
   "CN=tr.teams.microsoft.com","26.11.2021 16:52:50","26.11.2020 16:52:50","CN=Mi..","xx","xx","sha256RSA","29","108","112"

Sie sehen, das der Test von 00:22 bis 9:03 genau 8h41min gelaufen ist. Insgesamt also ca. 521 Minuten. In der Zeit wurden 229748 Datensätze mit 91.514.627 Bytes geschrieben. Das Skript also ca. 440 Messungen/Minute durchgeführt, also ca. 7,3 Messungen/Sek. Dabei wird bei jeder Messung eine neue TCP-Verbindung geöffnet. Darauf müssen Sie achten, damit Sie nicht ihre Firewall (NAT Limits) überlasten.

Achtung: Solche exzessiven Tests können von Firewalls auch als "Angriff" bzw. DoS-Attacke interpretiert werden. Genau genommen ist es das ja auch, da ich die Verbindung ja nicht nutze.

Verteilung der IP-Adressen

Zuerst habe ich einfach geschaut, wie viele IP-Adressen ich denn zurück bekommen habe und wie "gleichverteilt" das war.

PS C:\> Import-Csv .\test.csv | group remoteip -NoElement

Count Name
----- ----
 2001 52.112.168.208
 1919 52.112.168.209
 1939 52.112.168.210
 1967 52.112.168.211
 1937 52.112.168.212
 1978 52.112.168.213
...

In meinem Fall waren es 119 unterschiedliche IP-Adressen, die recht gleichverteilt um die 2000 Verbindungen erhalten haben. Allerdings sind alle Adressen im Bereich 52.112.0.0/14 und keine der anderen Adressen.

Ich interpretiere das so, dass dieser Adressbereich wohl für Europa genutzt wird.

Anzahl der Server und Bandbreite

Die Gruppierung nach IP-Adressen liefert natürlich auch die Information, mit wie vielen unterschiedlichen Servern ich gesprochen habe.

PS C:\> (Import-Csv .\end2end-tcpturn.csv | group remoteip -NoElement).count
119

119 Server finde ich nun aber nicht so viel. Da hätte ich mehr erwartet. Mit 229.717 Verbindungen haben ich jeden Server ca. 1900mal kontaktiert. Das ist aber keine qualifizierte Aussage über die Gesamtanzahl an Servern, denn es können ja die Server sein, die für meinen Internet-Provider "naheliegend" sind. Ein besseres Bild würde man hier nur erhalten, wenn man von vielen Orten mit unterschiedlichen Providern und Peerings den Namen "tr.teams.microsoft.com" auflöst und die Namen einsammelt.

Da die TURN-Server nur Pakete 1:1 weiterreichen und keine Anforderungen an Transkodierung oder Disk-IO haben, könnte ich mir aber schon vorstellen, dass die Anzahl passt. Wenn ich diese Server mit 10GBit Netzwerkkarten ausstatte, die zu 50% ausgelastet sein dürfen, dann kommen wir auf etwas über 500 Gigabit Netzwerkdurchsatz. Das wären (bei 1 Megabit/Video) ca. 500.000 Video-Teilnehmer. Da aber nicht alle Video nutzen, sondern vielleicht nur 20% ihre Kamera angeschaltet haben, kommen wir auf 100kBit/Audio + 200kBit Anteilig Video. Das könnte dann 1,5 Millionen gleichzeitige Teilnehmer in allen Teams-Meetings oder Telefonaten sein. Der Engpass ist hier vermutlich weniger das Transport-Relay sondern die Konferenzunit im Hintergrund, die ich hier nicht ermitteln kann.

Das sind natürlich alles nur nette Zahlenspielereien ohne Anspruch auf eine qualifizierte Aussage.

Aber mit den Zahlen lassen sich durchaus weitere Auswertungen anstellen.

Zeitliche Abfolge

Dann hat mich interessiert, ob ich wirklich mit jedem Request eine neue IP-Adresse bekomme. Und dem ist tatsächlich so:

PS C:\> Import-Csv .\end2end-tcpturn.csv | select datetime,remotename,remoteip,connecttimems -First 10

datetime             remotename                                          remoteip       connecttimems
--------             ----------                                          --------       -------------
2021-02-01 00:22:51Z b-tr-teasc-euno-05.northeurope.cloudapp.azure.com   52.114.251.80  33
2021-02-01 00:22:52Z b-tr-teasc-euno-16.northeurope.cloudapp.azure.com   52.114.248.34  30
2021-02-01 00:22:52Z a-tr-teasc-euwe-03.westeurope.cloudapp.azure.com    52.114.253.252 20
2021-02-01 00:22:52Z b-tr-teasc-euno-17.northeurope.cloudapp.azure.com   52.114.249.29  31
2021-02-01 00:22:52Z a-tr-teasc-frcn-07.francecentral.cloudapp.azure.com 52.112.172.109 25
2021-02-01 00:22:52Z a-tr-teasc-ukwe-05.ukwest.cloudapp.azure.com        52.114.93.14   25
2021-02-01 00:22:52Z a-tr-teasc-euwe-08.westeurope.cloudapp.azure.com    52.114.242.2   16
2021-02-01 00:22:53Z b-tr-teasc-frcn-02.francecentral.cloudapp.azure.com 52.112.172.255 26
2021-02-01 00:22:53Z b-tr-teasc-euno-10.northeurope.cloudapp.azure.com   52.114.231.0   34
2021-02-01 00:22:53Z b-tr-teasc-ukwe-16.ukwest.cloudapp.azure.com        52.112.168.215 26

Auch die Verteilung ist interessant, denn mein Client bekommt Adressen aus ganz unterschiedlichen Regionen. Dazu passt auch, dass die "ConnecttimeMS", d.h. die Zeit für den 3-Wege-HAndshake unterschiedlich schnell ist. Das muss ich mir gleich noch mal genauer anschauen.

DNS-TTL

Mein Skript fragt eigentlich jedes mal den Namen an. mit einem DNS-Cache sollte ich auf dem gleichen Server landen. Das ist hier aber nicht so. Eine DNS-Anfrage liefert mit jedem Query eine andere IP-Adresse. Der TTL des A-Records ist zwar 10Sek aber der Weg dorthin ist durch einige CNAMEs gepflastert, die einen TTL =0 Sek haben.

PS C:\> Resolve-DnsName tr.teams.microsoft.com

Name                           Type   TTL   Section    NameHost
----                           ----   ---   -------    --------
tr.teams.microsoft.com         CNAME  0     Answer     worldaz.tr.teams.microsoft.com
worldaz.tr.teams.microsoft.com CNAME  0     Answer     worldaz.tr.teams.trafficmanager.net
worldaz.tr.teams.trafficmanage CNAME  0     Answer     a-tr-teasc-euwe-04.westeurope.cloudapp.azure.com
r.net

Name       : a-tr-teasc-euwe-11.westeurope.cloudapp.azure.com
QueryType  : A
TTL        : 10
Section    : Answer
IP4Address : 52.114.242.1


Name                   : westeurope.cloudapp.azure.com
QueryType              : SOA
TTL                    : 36
Section                : Authority
NameAdministrator      : msnhst.microsoft.com
SerialNumber           : 10001
TimeToZoneRefresh      : 900
TimeToZoneFailureRetry : 300
TimeToExpiration       : 604800
DefaultTTL             : 60

Das bedeutet aber auch, dass zu jeder Verbindung weitere DNS-Anfragen dazu kommen, die in der Zeit hier nicht erfasst sind. Ich habe die Namensauflösung vor dem Start der "Stoppuhr" gemacht.

Genutzte Zertifikate

Mit jeder Verbindung bekomme ich den Thumbprint und die Seriennummer des TLS-Zertifikats mit. Da hat es mich zuerst mal interessiert, ob denn alle Server das gleiche Zertifikat nutzen.

PS C:\> Import-Csv .\end2end-tcpturn.csv | group Thumbprint -NoElement | ft -autosize

 Count Name
 ----- ----
    31
229717 3A6E1AFFB01B4E092E4027DCF2FA874FA4D302A0

Anscheinend haben alle Server immer das gleiche Zertifikat. Das nenne ich mal "Sharing" eines Zertifikats. Ich hätte eigentlich erwartet, dass jeder Server ein eigenes lokales Zertifikat durch eine Intermediate-CA bekommt und nicht, dass der private Key auf vielen Servern erneut genutzt wird.

Die OCS/Lync/Skype for Business Administratoren kennen das Verhalten aber vom OnPremises Edge-Server, bei dem alle Server das gleiche Zertifkat für den Media Relay Authentication Service (MRAS) genutzt haben. Warum bewährte Methoden verändern?

Gruppierung nach Region als dem RemoteName

Wie sie sicher gesehen haben, enthält der reale Name des Turn-Servers auch einen Hinweis auf die Region.

PC C:\> Import-Csv .\end2end-tcpturn.csv | Select-Object -Property @{label='region';expression={@($_.remotename.split(".")[1])}} | group region -NoElement

Count Name
----- ----
8
31104 francecentral
66278 northeurope
66191 ukwest
66167 westeurope

Mein Client scheint sich ziemlich gleich häufig mit drei Regionen zu verbrinden aber nur halb so oft mit Frankreich.

Verbindungszeit nach Region

Eine Auswertung zu den Verbindungszeiten ist auch noch per PowerShell als Einzeiler möglich. ich schreibe es dennoch in mehreren Zeilen, um es lesbarer zu machen und bedenken Sie, dass die Daten temporär im RAM gehalten werden.

Import-Csv .\end2end-tcpturn.csv `
   | Select-Object -Property @{label='region';expression={@($_.remotename.split(".")[1])}},connecttimems `
   | group region `
   | %{$name=$_.name; `
       $_.group `
          | measure-object -Property connecttimems -AllStats `
          | select *,@{label='region';expression={$name}} `
       } `
   | ft region,count,Minimum,average,maximum,StandardDeviation

region        Count Minimum          Average Maximum StandardDeviation
------        ----- -------          ------- ------- -----------------
                  8       1            2,125       4  0,83452296039628
francecentral 31104      19  25,409850823045    1008  14,3146974253767
northeurope   66278      26  33,149913998611    1016  18,0287646362301
ukwest        66191      22  28,525751235062    1009   9,7683316396355
westeurope    66167      13  18,614807985854    1004   6,3067076292667

"northeurope" und "ukwest" sind im Vergleich zu "westeurope" selbst beim Mittelwert ca. 10-16ms langsamer. Auch spricht die Standardabweichung (6) deutlich für "westeuropa". "northeuropa" ist von meinem Anschluss nicht nur am weitesten Weg sondern auch mit der größten Streuung (Standardabweichung = 18). Das Maximum von etwas über 1000ms ist der Tatsache geschuldet, dass ich den TCP-Timeout zu heruntergeschraubt habe und ist eher ein Zeichen, dass die Verbindung wohl nicht zustande gekommen ist.

Anzahl >1000

Durch die Beschränkung des TCP-Timeout auf 1000ms interessiert mich nun natürlich die Anzahl der Einträge, die darüber sind. Gibt es hier Unterschiede nach Standort?

Import-Csv .\end2end-tcpturn.csv `
   | Select-Object -Property @{label='region';expression={@($_.remotename.split(".")[1])}},connecttimems `
   | group region `
   | %{$_.group} `
   | where {([long]($_.connecttimems)) -gt 1000} `
   | group region -NoElement

Count Name
----- ----
    5 francecentral
   14 northeurope
    2 ukwest
    2 westeurope

Bei 229717 Verbindungen sind 21 Fehler gerade mal 0,01%.

PowerBI oder Excel

Grafiken sind natürlich nicht so einfach mit PowerShell möglich. Aber dafür gibt es ja dann Excel oder PowerBI. Excel könnte allerdings mit 229717 Zeilen in 91 Megabyte nicht mehr das optimale Werkzeug sein. Eine Anzeige der Verbindungszeit in Millisekunden nach den vier Standorten zeigt noch deutlicher die Entfernung meines Internetzugangs zu den Servern in den unterschiedlichen Datacentern

Sie finden aber auch keine Ausreißer, was ein Hinweis auf Störungen sein könnte. Allerdings wurde die Messung nur über eine Dauer von ca. 10 Stunden in der Nacht ausgeführt. Eine dauerhafte Überwachung und eine Relation zum Zeitpunkt als auch dem Zugangsprovider wäre interessant.

Spätestens dann kommen wir aber mit CSV-Dateien nicht mehr weiter, sondern sollten diese Daten aggregiert in Datenbanken ablegen und auswerten. Es macht dann auch keinen Sinn jede einzelne Messung zu protokollieren, sondern schon auf der Probe die Ergebnisse zu bündeln und Teilergebnisse zu speichern. Das wird dann ein Thema der Seite End2End-TCP.

Weitere Links