Teams VoIP Candidates

Microsoft Teams, Skype for Business, Zoom, WebEx, VoIP-Systeme u.a. nutzen alle RTP in ihrem Dialekt zur Übertragung von Audio/Video. Die Endpunkte bieten sich dazu ihre Kandidaten an und suchen einen Kommunikationskanal. Microsoft Teams arbeitet hier etwas anders bei der Auswahl der lokalen Kandidaten und Bestimmung möglicher Kommunikationswege. Der ICE, Handshake arbeitet wohl etwas anders, wenn ich das richtig beobachtet habe.

Auslöser

Im Rahmen eines Support Tickets mit Teams und VPN ist uns aufgefallen, dass der Teams Client den VPN-Tunnel für interne Gespräche wider erwarten nicht genutzt hat. Das war mit Skype for Business noch anders. Hier haben zwei Clients ein 1:1 Gespräch durch das VPN geführt, wenn Sie eine routbare IP-Verbindung gefunden hat. Teams hingegen scheint das nicht zu machen.

Analyse

Also war mal wieder eine Analyse angesagt, auch wenn man im Teams HTTP-Stream nicht so einfach ermitteln kann, welche Informationen übertragen werden. Aber auch bei Teams müssen sich die beiden Endpunkte auf etwas "einigen" und davor steht nun mal der Austausch der Kandidaten. Der VoIP-Stack, genauer ist es hier wohl WebRTC, muss sich also erst einmal klar, werden, wie der Client erreicht werden kann. Das können eine oder mehrere lokale IP-Adressen sein, die sie z:B. per IPCONFIG oder per Powershell einfach ermitteln können.

PS C> Get-NetIPAddress | ft

ifIndex IPAddress                                       PrefixLength PrefixOrigin SuffixOrigin AddressState PolicyStore
------- ---------                                       ------------ ------------ ------------ ------------ -----------
54      fe80::e569:f4df:70eb:442e%54                              64 WellKnown    Link         Deprecated   ActiveStore
40      fe80::b834:32de:131e:9b44%40                              64 WellKnown    Link         Preferred    ActiveStore
33      fe80::64e6:68d4:1eee:f741%33                              64 WellKnown    Link         Preferred    ActiveStore
63      fe80::44e:4b31:be85:b0c2%63                               64 WellKnown    Link         Preferred    ActiveStore
19      fe80::4c5c:33c0:6691:6d42%19                              64 WellKnown    Link         Deprecated   ActiveStore
41      fe80::60ba:aa7e:e8fe:4bda%41                              64 WellKnown    Link         Deprecated   ActiveStore
51      fe80::1543:e821:a36b:d07a%51                              64 WellKnown    Link         Deprecated   ActiveStore
42      fe80::dc2b:6442:6de1:10b8%42                              64 WellKnown    Link         Deprecated   ActiveStore
32      fe80::810d:a226:87ff:f17%32                               64 WellKnown    Link         Deprecated   ActiveStore
39      fe80::5d5a:de0b:1672:14ff%39                              64 WellKnown    Link         Preferred    ActiveStore
1       ::1                                                      128 WellKnown    WellKnown    Preferred    ActiveStore
54      192.168.178.91                                            24 Dhcp         Dhcp         Deprecated   ActiveStore
40      169.254.155.68                                            16 WellKnown    Link         Preferred    ActiveStore
33      192.168.178.91                                            22 Dhcp         Dhcp         Preferred    ActiveStore
63      172.22.144.1                                              20 Manual       Manual       Preferred    ActiveStore
19      169.254.109.66                                            16 WellKnown    Link         Tentative    ActiveStore
41      169.254.75.218                                            16 WellKnown    Link         Tentative    ActiveStore
51      169.254.208.122                                           16 WellKnown    Link         Tentative    ActiveStore
42      169.254.16.184                                            16 WellKnown    Link         Tentative    ActiveStore
32      169.254.15.23                                             16 WellKnown    Link         Tentative    ActiveStore
39      192.168.10.144                                            22 Dhcp         Dhcp         Preferred    ActiveStore
1       127.0.0.1                                                  8 WellKnown    WellKnown    Preferred    ActiveStore

Es ist gut zu sehen, dass ich wohl mehrere Adapter (LAN, WLAN, Bluetooth, VPN etc.) habe. Wenn ich nun einen Teams-Anruf starte, dann sollte ich sehen, welche Verbindungen ein Prozess alles ausgehend aber insbesondere auch eingehend öffnet.

Ein Skype for Business hat quasi immer alle IP-Adressen aller Interfaces als "Candidates" angeboten. Das passiert aber in Teams nicht, denn ich habe immer nur wenig TURN-Anfragen und RTP-Versuche gefunden. Hier ein Mitschnitt von Teams zum Anruf auf ein Festnetz.

Ich sehe nur Verbindungen von einer einzigen IP-Adresse auf Office 365-Systeme. Ich sehe keine direkten Verbindungen zwischen dem Client und dem SBC oder einem Client mit dem anderen Client. Der klassische "ich versuch mal alles"-Ansatz von Skype for Business kommt hier hier wohl nicht mehr zum Einsatz. Es ist eher ein deterministischer Ansatz, bei dem die Endpunkte schon "wissen", wo sie sind und sich damit ausrechnen können, welche Verbindung für RTP genutzt werden soll.

Diese Annahme bestätigt sich auch anhand einiger Problemfälle in Verbindung mit DirectRouting und Local Media Optimization (LMO)

LMO erfordert, dass der Client weiß, ob er intern oder extern ist. Dazu werden die öffentlichen IP-Adressen ihrer Firmenstandorte hinterlegt und das Teams Backend teilt dem Client mit, wenn er damit "intern" ist. Der Client nutzt dann seine private Adresse, um den internen Standort zu ermitteln und sendet diese "ich bin intern"-Meldung auch an den SBC, der dann mit aktiviertem LMO entsprechend die internen Kandidaten ausliefert.

Wenn eine Firewall zwischen internem Client und internen SBC-Kandidaten diese Verbindung nicht erlaubt, dann kommt einfach kein Gespräch zustande. Teams baut dann keinen Umweg über die Cloud oder andere Wege auf.

Das ist das von mir beobachtete Verhalten. Es kann von Microsoft jederzeit geändert werden. Beim WebClient kann Teams aber nicht auf den TCP-Stack zugreifen, sondern muss sich dem WebRTC-Framework bedienen. Hier funktioniert dann z.B. Teams Local Media Optimization nicht.

Tracing in den Logs

Altgediente Skype for Business Administratoren haben natürlich schon immer mit UCCAPI-Logs und Snooper die Probleme auf dem Client oder auf dem Server analysieren können. Eine Analyse auf dem Teams Server ist aber nicht möglich und der Teams Client schreibt keine UCCAPILOGs mehr.

Aber der Teams Client ist ja "nur" eine JavaScript-Software in einem Chromium-Container, den ich per "F12-Debugging" ebenfalls untersuchen kann.

Für einige Informationen müssen Sie die Medialogs aktivieren

 Teams kann aber auch Support-Dateien anlegen. Das geht recht einfach über das Teams-Menü:

Beim Browser ist der Hotkey WIN-CTRL-ALT-1 nutzbar. in Teams sehen Sie die Dateien im Dateibereich unter Downloads

Die Dateien selbst landen in ihrem Download-Ordner. Hier sind nach dem Anruf die beiden folgenden Dateien interessant, die sie einfach in einem Texteditor ihrer Wahl öffnen können.

Ich habe in den verschiedenen Diagnose-Protokollen von Teams noch keinen klassischen SDP-Datensatz und den ICE-Handshake nachvollziehen können. Eine RegEx Suche nach "candidate.*details" sollte aber diese Einträge je nach Debug-Einstellung finden.

Ich werde später noch einmal Logs entsprechend untersuchen.

Candidates

So ganz hat mir das keine Ruhe gelassen und auch auf der Seite Teams Local Media Optimization habe ich schon beschrieben, dass Der SBC bei einem internen Teilnehmer nur genau den einen internen Endpunkt an Teams weiter meldet und damit die Verbindung zwingend über die interne Verbindung hergestellt wird. Kommt diese Verbindung nicht zustande, dann findet kein Fallback statt. Interessanter ist aber die Liste der Kandidaten, die mein Client an den SBC liefert:

a=candidate:3 1 UDP 2130705407 192.168.178.91 50002 typ host
a=candidate:3 2 UDP 2130704894 192.168.178.91 50003 typ host
a=candidate:4 1 tcp-act 2121005054 192.168.178.91 50000 typ host
a=candidate:4 2 tcp-act 2121005054 192.168.178.91 50000 typ host
a=candidate:5 1 UDP 1694496767 80.66.18.142 50002 typ srflx raddr 192.168.178.91 rport 50002
a=candidate:5 2 UDP 1694496254 80.66.18.142 50003 typ srflx raddr 192.168.178.91 rport 50003
a=candidate:6 1 UDP 1258288639 52.114.93.20 52999 typ relay raddr 80.66.18.142 rport 50002
a=candidate:6 2 UDP 1258288126 52.114.93.20 53003 typ relay raddr 80.66.18.142 rport 50003
a=candidate:7 1 tcp-act 1684795902 217.91.247.140 50006 typ srflx raddr 192.168.178.91 rport 50006
a=candidate:7 2 tcp-act 1684795902 217.91.247.140 50006 typ srflx raddr 192.168.178.91 rport 50006
a=candidate:8 1 tcp-pass 1248194558 52.114.93.224 59495 typ relay raddr 217.91.247.140 rport 50006
a=candidate:8 2 tcp-pass 1248194558 52.114.93.224 59495 typ relay raddr 217.91.247.140 rport 50006
a=candidate:9 1 tcp-act 1248587262 52.114.93.224 59495 typ relay raddr 217.91.247.140 rport 50006
a=candidate:9 2 tcp-act 1248587262 52.114.93.224 59495 typ relay raddr 217.91.247.140 rport 50006

Ich sehe hier nur die eine IP-Adresse 192.168.178.91, die Teams an den SBC meldet. Wenn ich auf dem gleichen PC einen Skype for Business-Anruf starte, dann sehe ich:

a=candidate:1 1 UDP 2130706431 172.24.224.1 50006 typ host
a=candidate:1 2 UDP 2130705918 172.24.224.1 50007 typ host
a=candidate:2 1 UDP 2130705919 192.168.178.91 50006 typ host
a=candidate:2 2 UDP 2130705406 192.168.178.91 50007 typ host
a=x-candidate-ipv6:3 1 UDP 2130705407 2a00:6020:b007:3200:71b5:16f8:3134:b2b 50002 typ host
a=x-candidate-ipv6:3 2 UDP 2130704894 2a00:6020:b007:3200:71b5:16f8:3134:b2b 50003 typ host
a=candidate:4 1 TCP-PASS 174455295 52.112.12.165 56979 typ relay raddr 52.112.12.253 rport 50010
a=candidate:5 1 UDP 184547327 52.112.12.149 55835 typ relay raddr 94.31.83.223 rport 50018
a=candidate:5 2 UDP 184546814 52.112.12.149 57329 typ relay raddr 94.31.83.223 rport 50019
a=candidate:6 1 TCP-ACT 174847487 52.112.12.165 56979 typ relay raddr 52.112.12.253 rport 50010
a=x-candidate-ipv6:7 1 TCP-PASS 174453759 2603:1037:0:9b::2c 51450 typ relay raddr 52.112.12.253 rport 50010
a=x-candidate-ipv6:8 1 TCP-ACT 174846463 2603:1037:0:9b::2c 51450 typ relay raddr 52.112.12.253 rport 50010
a=candidate:9 1 TCP-ACT 1684795391 52.112.12.253 50010 typ srflx raddr 192.168.178.91 rport 50010
a=x-candidate-ipv6:10 1 UDP 184544767 2603:1037:0:9b::1c 52091 typ relay raddr 94.31.83.223 rport 50018
a=x-candidate-ipv6:10 2 UDP 184544254 2603:1037:0:9b::1c 58082 typ relay raddr 94.31.83.223 rport 50019
a=candidate:11 1 UDP 1694231551 94.31.83.223 50018 typ srflx raddr 192.168.178.91 rport 50018
a=candidate:11 2 UDP 1694231038 94.31.83.223 50019 typ srflx raddr 192.168.178.91 rport 50019

Hier erscheint noch ein Kandidat mit der IP-Adresse "172.24.224.1", welcher bei Teams nicht angezeigt wird.

Anders als Skype for Business scheint Teams nicht alle lokalen IP-Adressen als mögliche Kandidaten auszuwählen, sondern nur sinnvolle Werte zu nutzen. Auch sehe ich kein IPv6-Angebot, was aber auch daran liegen könnte, dass es ein SBC-Call war.

Über verschiedene Quellen habe ich noch einige weitere Aussagen zusammengetragen, die sich mit meinen Beobachtungen decken.

Das ist aber keine Garantie, dass die Aussagen auch morgen noch korrekt sind

Also habe ich verschiedene Personen befragt, und folgende Antworten bekommen:

... How we solve the VPN (split-tunnel) problem::
We check for routes to the three well known IP ranges from ID11 on https://aka.ms/O365endpoints) service endpoints. We use the "GetBestRoute" function and will bind to that interface with the best match. RTP-Traffic to the TURN-Services is kept away from the VPN tunnel...

... Customers are strongly encouraged to follow our connectivity guidance on https://aka.ms/PNC. This will ensure, that they get the best end-user experience. The Teams service is evolving all the time, keeping those connectivity principles in mind and optimizing for those...

Clients with no default route also check for routes to the known endpoints from https://aka.ms/O365endpoints and try to reach the transport relays. Teams will only bind to the interface which routes to our service.

Teams media transport can use IPv6, but Teams prefers IPv4 and IPv6 is a fallback to IPv4 at the moment.

Die Funktion kann auch per PowerShell nachgestellt werden.

Find-NetRoute -RemoteIPAddress (resolve-dnsname worldaz.tr.teams.microsoft.com -Type a).ip4address  `
| select IPAddress, InterfaceIndex, InterfaceAlias, State, DestinationPrefix, NextHop

Die IP-Adresse ist dabei eines der Teams Transportrelay-Server hinter worldaz.tr.teams.microsoft.com.

Wenn ich diese Aussage als korrekt annehme, dann komme ich auf die gleichen Ergebnisse, die ich auch per Wireshark gesehen habe: Bei einer SplitVPN-Konfiguration ist das Default Gateway weiterhin die lokale Netzwerkkarte und nicht der VPN-Adapter. Damit wird der Client dann auch keine RTP-Daten durch das VPN schleusen. Ich habe dann bei mir meinen PC mit zwei Netzwerkkarten versorgt, von denen jedes auch ein Gateway geliefert hat.

Wenn ich einen Call gestartet habe und mit Wireshark die Verbindungsversuche untersucht habe, dann habe ich auch nur ausgehende Verbindungen von diesem Interface gesehen. Das kann natürlich auch mit den IP-Leitwegen zu tun haben aber bei Skype for Business wurden immer alle lokalen IP-Adressen mit Kandidaten angeboten und von der Gegenseite auch versucht zu erreichen.

Tracing auf dem SBC

Wer den Vorteil eines eigenen SBCs hat, auf dem er sich entsprechende Logs ziehen kann, findet weitere interessante Kandidaten. Sobald z.B. Teams Local Media Optimization aktiviert ist und der Client als "Intern" angesehen wird, dann sendet Teams per SIP eine ganze Menge an Kandidaten an den SBC. Hier ein Auszug:

a=candidate:3 1 UDP 2130705407 192.168.178.91 50002 typ host
a=candidate:3 2 UDP 2130704894 192.168.178.91 50003 typ host
a=candidate:4 1 tcp-act 2121005054 192.168.178.91 50000 typ host
a=candidate:4 2 tcp-act 2121005054 192.168.178.91 50000 typ host
a=candidate:5 1 UDP 1694496767 80.66.18.142 50002 typ srflx raddr 192.168.178.91 rport 50002
a=candidate:5 2 UDP 1694496254 80.66.18.142 50003 typ srflx raddr 192.168.178.91 rport 50003
a=candidate:6 1 UDP 1258288639 52.114.93.20 52999 typ relay raddr 80.66.18.142 rport 50002
a=candidate:6 2 UDP 1258288126 52.114.93.20 53003 typ relay raddr 80.66.18.142 rport 50003
a=candidate:7 1 tcp-act 1684795902 217.91.247.140 50006 typ srflx raddr 192.168.178.91 rport 50006
a=candidate:7 2 tcp-act 1684795902 217.91.247.140 50006 typ srflx raddr 192.168.178.91 rport 50006
a=candidate:8 1 tcp-pass 1248194558 52.114.93.224 59495 typ relay raddr 217.91.247.140 rport 50006
a=candidate:8 2 tcp-pass 1248194558 52.114.93.224 59495 typ relay raddr 217.91.247.140 rport 50006
a=candidate:9 1 tcp-act 1248587262 52.114.93.224 59495 typ relay raddr 217.91.247.140 rport 50006
a=candidate:9 2 tcp-act 1248587262 52.114.93.224 59495 typ relay raddr 217.91.247.140 rport 50006

Ich habe die Sortierung nach der Priorität geändert, da Teams zuerst den TURN-Kandidaten 6 an erster Stelle hat. Sie sehen aber die private IP-Adresse 192.168.178.91, die ich zu dem Zeitpunkt hatte. Die Kandidaten alleine helfen dem SBC natürlich noch nicht. Er muss schon noch die Informationen im Header auswerten

X-MS-UserLocation: internal 
X-MS-MediaPath: sbc.netatwork.de 
X-MS-UserSite: Paderborn

Aber dann sehe ich im RINGING, welches der SBC zu Teams sendet, nur noch die internen Kandidaten.

SIP/2.0 180 Ringing
a=ice-lite
a=ptime:20
a=sendrecv
a=ice-ufrag:xxxxx
a=ice-pwd:xxxxxx
a=candidate:1630614871 1 udp 2130706431 192.168.10.12 8130 typ host
a=candidate:1630614871 2 udp 2130706430 192.168.10.12 8131 typ host
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15,16
a=rtpmap:13 CN/8000
a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:xxxxxxxxx/xxxxx|2^31

Diese Daten werden so aber nur auf dem SIP-Signalisierungsweg zwischen dem SBC und dem Microsoft PSTNHUB genutzt. Was durch das Gateway dann zum Teams-Client gesendet wird, ist hier nicht zu sehen. Allerdings muss zumindest der Windows Teams Client die kompletten Kandidaten ermittelt und gemeldet haben, die vom Teams Backend dann zum SBC weiter gegeben werden.

Teams Local Media Optimization funktioniert (aktuell) nicht mit Teams als Browser App, da WebRTC keinen Zugriff auf den Netzwerkstack erlaubt und diese Optimierung nicht genutzt werden kann.

Szenarien

Damit ergeben sich nun einige Szenarien, die Sie kennen sollten. Immer vorausgesetzt, dass Teams sein verhalten nicht ändert und immer nur die IP-Adresse der Netzwerkkarte nutzt, die er nach der oben genannten Logik ermittelt.

  • Single NIC
    Computer mit genau einer aktiven Netzwerkkarte brauchen wir nicht weiter zu betrachten. Hier gibt es nur nur ein Interface, welches Teams nutzen wird.
  • Keine Route
    Dieser seltene Fall kommt aber im "sicheren Umgebungen" vor, wenn Clients zwingend einen Proxy oder Application Gateway nutzen sollten. Teils haben die Clients keine externe DNS-Auflösung können die Transportrelay-Server gar nicht auflösen. Manchmal haben die Systeme nicht einmal ein Default Gateway, weil alle Zugriffe zwingend über Proxy-Server geleitet werden.

Hier habe ich noch nicht analysiert, was Teams genau macht. Ich vermute aber, dass er ein Fallback auf HTTPS macht und damit den HTTP-Proxy nutzt.

Interessant wird es mit Clients, die zwei oder sogar mehr Netzwerkkarten haben. Das kann ein LAN + WLAN sein oder eine GSM-Verbindung. Hier gibt es aber IP-Routen und Kosten. Ein häufiger Fall seit COVID19 ist aber das HomeOffice mit VPN-Verbindung. Die meisten VPN-Produkte haben einen VPN-Netzwerkadapter, der bei einer aktiven Verbindung dann die Leitwege ins Firmennetzwerk (oft private Adressen) bereitstellt.

  • SplitVPN
    Das Default-Gateway bleibt auf der lokalen Netzwerkkarte und der VPN-Adapter routet nur die Subnetze der Firma durch den Tunnel. Teams bekommt beim "GetBestRoute" natürlich die reale Netzwerkkarte und holt sich hier seine Kandidaten. Die IP-Adressen des VPN-Adapters werden nicht als Kandidat genutzt. Damit ist auch klar, warum dieser Homeoffice-Client nicht durch das VPN mit anderen Client in der Firma kommuniziert. Ist ist eine Abweichung zu Skype for Business.
  • TunnelVPN
    Wenn das VPN
    The VPN ensures, that all packets are routet though the tunnel. So even the connection to the relay is going through the tunnel.
    1:1 to an company client will use the tunnel ans also any other VoIP will use the ineffective tunnel. Right ?
  • Sonderfall IPv6 Bypass
    Eine besondere Variante des SplitVPN ist die Betrachtung on IPv4 und IPv6. Selbst wenn ihr VPN einen "Tunnel" eingerichtet hat aber IPv6 dabei überseht, öffnet sich für IPv6-taugliche Clients ein Seitenausgang. Auch Microsoft Teams nutzt IPv6 für die Kommunikation zu anderen IPv6-Clients aber aktuell noch nicht zu den TURN-Servern in der Cloud.

Es gibt also schon einige Varianten, auf die sich ihr PC und Microsoft Teams einstimmen muss.

Einschätzung

Zuerst habe ich mich gewundert, warum Microsoft hier anders arbeitet und von dem bewährten SIP/ICE-Standards abweicht. Schließlich werden diese weltweit von sehr vielen Systemen, also auch Cisco, Avaya, Unify, Asterisk, Snom und anderen SIP-Systemen genutzt. Die vielen Kandidaten führen aber auch dazu, dass es bei der Aushandlung sehr viele "Verbindungsversuche" gibt, die vielleicht etwas die Logs in der Firewall füllen aber vor allem Zeit kosten. Insbesondere wenn die Verbindung unterbrochen und neu aufgebaut werden muss.

In den meisten Fällen ist die Annahme ja korrekt, dass die IP-Adresse mit der Verbindung zu Office 365 auch die "beste Adresse" für die generelle Erreichbarkeit ist. Vor allem ist die Verbindung dann auch sehr gut "vorhersagbar".

Wer ein richtiges TunnelVPN für IPv4 und IPv6 hat, bei dem wird der Aufruf von "GetBestRoute" auch den Tunneladapter liefern und alles ist sicher. Wer allerdings nur ein "halbes" VPN hat, weil er IPv6 nicht durch den Tunnel zwingt oder gleich mit Split-VPN arbeitet, der wird bemerken, dass Teams den STUN/TURN-Server in der Cloud als Media-Relay bevorzugt und nicht den VPN-Tunnel zum Firmennetzwerk, selbst wenn der Weg dorthin auf dem Papier kürzer wäre. Das ist aber nur ein Irrglaube, denn auch vom Homeoffice mit Provider1 zur Firma mit Provider 2 gibt es einige "Peerings" zu überwinden. Da ist es meist sogar besser, wenn das Relay bei Microsoft genutzt wird.

Sobald eine Teams-Konferenz gestartet wird, müssen die Daten eh in die Cloud und dann wäre der Umweg über das VPN die schlechteste Verbindung.

Insofern: Alles richtig gemacht auch wenn die SIP-Fachleute etwas umlernen müssen, wenn Teams zwar im LAN noch direkte 1:1 Verbindungen aufbaue aber mit zwei Netzwerkkarten (LAN/WLAN/VPN/UMTS) immer nur die Netzwerkkarte nutzt, die aus Sicht von Teams die beste Verbindung zur Cloud hat.

Weitere Links