Teams Voice Route greift nicht
Regex, Priorität und überdeckte Routen in Direct RoutingTeams Voice Route greift nicht: Regex, Priorität und überdeckte Routen

|
WISSEN Alles zur Teams-Telefonie: Direct Routing, SBC, Wählpläne, Routing, Notruf und Betrieb an einem Ort. |
BERATUNG Deine Routen sind über Jahre gewachsen und keiner weiß mehr, welche gewinnt? Wir räumen sie gemeinsam mit dir auf. |
SCHULUNG Für Admins, die Muster, Prioritäten und Usages selbst bauen und sicher ändern wollen. |
|---|
Du hast eine neue Voice Route angelegt. Das Muster ist sauber, der Regex-Tester im Browser leuchtet grün, der SBC dahinter meldet sich brav. Und die Anrufe gehen trotzdem woanders hin. Oder gar nicht. Willkommen bei einem der hartnäckigsten Fehler in Teams Direct Routing: der Route, die existiert, aber nie gewinnt.
Meistens steckt eine von drei Ursachen dahinter. Entweder schluckt eine allgemeinere Route mit kleinerer Prioritätszahl alles, bevor deine spezielle Route überhaupt drankommt. Oder das Muster passt schlicht nicht auf die Nummer, die an dieser Stelle ankommt, weil sie im Format E.164 mit +49 vorliegt und das Muster etwas anderes erwartet. Oder ein einzelnes fehlendes Zeichen, typischerweise der Backslash vor dem Pluszeichen, macht aus einem guten Muster eines, das nie trifft und dabei nicht einmal eine Fehlermeldung produziert. Regex ist eben die einzige Sprache, in der ein vergessenes Zeichen so höflich schweigt.
In diesem Beitrag zum Thema teams voice route regex gehen wir vom Symptom aus: wie sich der Fehler anfühlt, wie er technisch entsteht, wie du ihn mit lesenden PowerShell-Befehlen findest, wie du ihn mit Rückweg behebst und wie du verhinderst, dass er wiederkommt. Grundlagen zu Direct Routing wiederholen wir nur so weit, wie sie zum Verständnis nötig sind. Den Gesamtüberblick findest du auf der Seite Teams-Telefonie.
|
FAKTEN · Das Beispiel in diesem Beitrag Erfundener Tenant Contoso (contoso.com) mit Standorten in Frankfurt, Köln, Berlin, Hamburg und München. Die Rufnummern folgen dem Muster +49 69 555 0100 (Frankfurt), +49 221 555 0100 (Köln), +49 30 555 0100 (Berlin). Der Haupt-SBC heißt sbc1.contoso.com, der zweite sbc2.contoso.com. Über sbc2 läuft zusätzlich ein eigener Trunk für Servicenummern (0800). Alle Diagnosebefehle sind lesend: Get- und Test-Cmdlets aus dem Modul MicrosoftTeams sowie [regex]::IsMatch() in PowerShell. Geschrieben wird erst im Abschnitt zur Behebung, mit Sicherung und Rückweg. |
|---|
Das Symptom: „Die Route ist doch da!“
Eine Route, die nicht greift, meldet sich selten mit einer klaren Fehlermeldung. Häufiger geht der Anruf einfach über den falschen Weg raus, und das fällt erst auf, wenn jemand die Rechnung, die Rufnummernanzeige oder ein Gesprächsprotokoll anschaut. Im Helpdesk klingt das dann so:
„Die neue 0800-Route ist seit Dienstag drin, aber der Provider sieht keinen einzigen Anruf.“
„Wenn ich nach Köln telefoniere, geht es über den Berliner Trunk. Warum auch immer.“
„Seit der Umstellung kommt bei Anrufen ins Ausland gar nichts mehr an, Inland geht.“
„Der Ersatz-SBC sollte nur einspringen, wenn der erste ausfällt. Jetzt läuft alles über den Ersatz.“
„Ich habe die Route im Teams Admin Center geprüft, das Muster stimmt. Ich habe es sogar getestet!“
Der letzte Satz ist der wichtigste. Er bedeutet fast immer: Das Muster wurde isoliert getestet, gegen eine Nummer, die so nie an der Route ankommt, und ohne Blick auf die anderen Routen, die ebenfalls passen. Eine Voice Route ist nie allein. Ob sie greift, entscheidet sich im Vergleich mit ihren Nachbarn.
|
WICHTIG · Erst prüfen, ob es wirklich die Route ist Wenn ein Anruf gar nicht rausgeht, kann die Ursache auch vor der Route liegen: fehlende Lizenz, keine Voice Routing Policy, ein Wählplan, der die Nummer nicht nach E.164 übersetzt. Den kompletten Rufweg von vorne prüfst du mit Teams-Anruf geht nicht raus: den Rufweg Schritt für Schritt prüfen. Dieser Beitrag beginnt an der Stelle, an der die normalisierte Nummer feststeht und Teams eine passende Route sucht. |
|---|
Wie der Fehler technisch zustande kommt
Wo die Route in der Kette sitzt
Ein abgehender Anruf läuft durch eine feste Kette: Benutzer › Wählplan › Normalisierung › Voice Routing Policy › PSTN Usage › Voice Route › SBC. Für unser Thema zählen zwei Glieder. Die Normalisierung bestimmt, welche Zeichenfolge überhaupt an den Routen ankommt. Und die Policy legt fest, in welcher Reihenfolge die Usages und damit die Routen geprüft werden.

Wie Policy, Usage und Route zusammenhängen und warum die Reihenfolge der Usages wichtiger ist als jede Priorität, erklärt Voice Routing Policy, PSTN Usage und Voice Route: Reihenfolge verstehen ausführlich. Hier reicht die Kurzfassung: Teams prüft die Usages der Policy von oben nach unten. In der ersten Usage, in der überhaupt eine Route passt, ist Schluss. Innerhalb dieser Usage gewinnt von allen passenden Routen die mit der kleinsten Prioritätszahl.
Wie Teams ein Muster prüft
Das Feld NumberPattern einer Voice Route ist ein regulärer Ausdruck. Microsoft beschreibt es genau so: Nummern, die auf den Ausdruck passen, werden über diese Route geleitet. Die Syntax entspricht der .NET-Regex, die du in PowerShell mit [regex]::IsMatch() nachstellen kannst. Daraus ergeben sich drei Eigenschaften, die man kennen muss:
Gesucht wird ein Treffer irgendwo in der Nummer. Ein Muster ohne ^ am Anfang und $ am Ende passt, sobald es an irgendeiner Stelle der Nummer vorkommt. Das Muster 221 trifft also nicht nur Köln, sondern jede Nummer, in der irgendwo 221 steht.
Das Pluszeichen ist ein Sonderzeichen. Ein + bedeutet in Regex „ein oder mehrmals das Vorige“. Wer das Pluszeichen der Rufnummer meint, muss \+ schreiben.
Geprüft wird die normalisierte Nummer. Also +49221…, nicht 0221…. Enthält die Nummer eine Durchwahl im Format ;ext=, prüft Teams laut Microsoft das Muster nur gegen den Teil davor.
|
FAKTEN · Was Microsoft zum Routing dokumentiert Die Priorität legt die Reihenfolge fest, wenn mehrere Routen auf eine Nummer passen: die niedrigste Zahl zuerst, dann aufsteigend. Die PSTN Usages einer Voice Routing Policy werden der Reihe nach angewendet. Gibt es in der ersten Usage einen Treffer, werden die weiteren nie ausgewertet. Die SBCs innerhalb einer Route werden in zufälliger Reihenfolge versucht. Sind alle nicht verfügbar, kommt die nächste passende Route dran. Gibt es keine, wird der Anruf abgebrochen. Passt keine Route, scheitert der Anruf. Nur bei Benutzern mit Calling Plan dient der Calling Plan als automatischer letzter Weg. Legst du eine Route ohne Angabe einer Priorität an, vergibt Teams selbst eine. In der Dokumentation landet die neue Route dabei hinter den bestehenden. |
|---|
Ein Detail zum Schmunzeln, oder zum Weinen: In der offiziellen Anleitung verwendet Microsoft für die internationale Route selbst die Muster \d+ und .*. Beides ist für eine Laborumgebung völlig in Ordnung. In einer Usage mit weiteren Routen und einer kleinen Prioritätszahl ist es eine Einladung zur Überdeckung.
Die fünf Fehlerbilder im Überblick
Aus diesen Regeln ergeben sich fünf Fehlerbilder, die in echten Tenants immer wieder auftauchen. Alle Muster in der Tabelle sind mit [regex]::IsMatch() gegen die genannten Nummern geprüft.
|
Fehlerbild |
Beispielmuster |
Was passiert |
Woran du es erkennst |
|---|---|---|---|
|
1 Überdeckte Route |
Prio 1: ^\+49\d+$ |
+498005550100 passt auf beide, Prio 1 gewinnt. Die 0800-Route wird nie benutzt. |
Spezielle Route hat null Anrufe, ihr SBC sieht nichts |
|
2 Muster passt nicht auf E.164 |
^0221\d+$ oder ^\+490221\d+$ |
An der Route kommt +492215550100 an. Das Muster erwartet eine 0, die es nicht mehr gibt. |
Route greift nie, Anruf geht über eine andere Route oder scheitert |
|
3 Fehlendes \+ |
^+49\d+$ |
Gültige Regex, aber + wirkt als Quantor auf ^. Das Muster trifft keine Nummer mit Pluszeichen. |
Keine Fehlermeldung beim Anlegen, trotzdem nie ein Treffer |
|
4 Priorität innerhalb der Usage falsch |
Prio 1: ^\+49\d+$ › sbc2 |
Gleiches Muster, die Ersatzroute hat die kleinere Zahl. Alles läuft über den Ersatz. |
Haupt-SBC ist untätig, Ersatz-SBC voll |
|
5 Fehlende Klammer oder Anker |
^\+49221|30\d+$ |
Gelesen als „beginnt mit +49221“ oder „endet auf 30 und Ziffern“. Trifft auch +49695553000. |
Einzelne Nummern anderer Standorte landen auf der falschen Route |
Fehlerbild 1: die überdeckte Route
Das ist der Klassiker und der Grund, warum der Titel dieses Beitrags so heißt. Die Usage DE-National enthält seit der Einführung eine Route mit ^\+49\d+$ und Priorität 1. Später kommt der Wunsch, 0800-Nummern über einen eigenen Trunk an sbc2 zu führen. Jemand legt die Route DE-0800 mit ^\+49800\d+$ an, hängt sie an dieselbe Usage, und Teams vergibt ihr die nächste freie Priorität. Ab jetzt passen auf jede 0800-Nummer zwei Routen, und die kleinere Zahl gewinnt. Das ist die allgemeine.

Teams fragt nicht, welche Route besser passt. Es gibt kein „spezifischer gewinnt“ wie bei Netzwerkrouten mit längerem Präfix. Es gibt nur die Zahl. Eine überdeckte Route ist deshalb völlig intakt, sie wird nur nie gefragt, solange die allgemeine Route einen verfügbaren SBC hat. Gemein wird es, wenn sbc1 einmal ausfällt: Dann springt plötzlich die 0800-Route für 0800-Nummern ein, und am nächsten Tag ist der Spuk wieder vorbei. Solche Fehler werden gern als „sporadisch“ abgelegt.
Dieselbe Überdeckung gibt es eine Ebene höher über die Usages: Liegt eine Usage mit einer Sammelroute vor der Usage mit der speziellen Route, hilft auch Priorität 1 nichts. Diese Variante behandelt Voice Routing Policy, PSTN Usage und Voice Route: Reihenfolge verstehen.
Fehlerbild 2 und 3: das Muster passt nicht auf E.164
Die Route sieht die Nummer so, wie der Wählplan sie hinterlässt. Bei einem sauberen Wählplan ist das E.164: +49, dann die Ortsvorwahl ohne führende 0, dann die Rufnummer. Muster im nationalen Format (^0221) oder mit der Null nach der Landesvorwahl (^\+490221) treffen dann nie. Umgekehrt gilt: Wenn deine Normalisierung kein + erzeugt, passen die korrekten Muster nicht, und der Fehler liegt im Wählplan. Wie du das unterscheidest, steht in Normalisierungsregeln in Teams: typische Fehler und wie du sie findest.

Fehlerbild 3 ist das tückischste, weil es keinen Lärm macht. Das Muster +49\d+ ohne Anker lässt sich gar nicht anlegen, die Regex ist ungültig und das fällt sofort auf. Das Muster ^+49\d+$ dagegen ist gültige .NET-Regex: Das + quantifiziert den Anker ^, und danach muss die Nummer mit 49 weitergehen. Weil an der Route aber +49… ankommt, trifft das Muster nie. Kein Fehler, kein Treffer, keine Spur. Wir haben es mit [regex]::IsMatch("+49695550100", "^+49\d+$") nachgeprüft: Das Ergebnis ist False.
|
WARNUNG · 110 und 112 sind keine E.164-Nummern Ein korrekter deutscher Wählplan lässt 110 und 112 unverändert. Eine nationale Route wie ^\+49\d+$ trifft sie deshalb nicht, und das ist auch richtig so. Gibt es aber keine Route mit einem Muster wie ^(110|112)$ in einer Usage der Policy, findet der Notruf keinen Weg. Umgekehrt fängt eine unverankerte Sammelroute wie \d+ oder .* den Notruf mit ein, im Zweifel über den falschen SBC. Ist einem Netzwerkstandort eine Notruf-Richtlinie mit eigener PSTN Usage zugeordnet, kann der Notruf außerdem einen eigenen Weg nehmen. Wie Notruf insgesamt aufgebaut ist, steht in Notruf in Microsoft Teams konfigurieren. Und bitte: Teste neue Notrufrouten nicht, indem du 112 wählst. Wie es richtig geht, zeigt Notruf in Teams testen, ohne die Leitstelle zu verärgern. |
|---|
Fehlerbild 4: Priorität innerhalb der Usage
Microsoft empfiehlt für Ersatzwege zwei Routen mit demselben Muster in derselben Usage: die Hauptroute mit der kleineren Prioritätszahl, die Ersatzroute mit der größeren. Vertauscht man die Zahlen, funktioniert technisch alles. Nur eben andersherum. Der Ersatz-SBC trägt die Last, der Haupt-SBC langweilt sich, und das Monitoring ist zufrieden, weil ja alle Anrufe durchgehen. Bis jemand die Leitungskosten oder die Kanalauslastung anschaut.
Zwei Eigenheiten verschärfen das. Erstens ist die Priorität eine Eigenschaft der Route, nicht der Verbindung zur Usage. Hängt eine Route an mehreren Usages, hat sie überall dieselbe Zahl. Zweitens ist die Priorität ein Rangplatz in einer gemeinsamen Liste aller Routen. Wenn du eine Route verschiebst, können sich die Plätze anderer Routen ändern. Sieh dir deshalb nach jeder Änderung die komplette Liste an. Mehr zur Ersatzlogik steht in SBC-Failover in Teams funktioniert nicht.
Fehlerbild 5: Klammer und Anker
Der Oder-Strich | hat in Regex die niedrigste Rangfolge. Das Muster ^\+49221|30\d+$ liest die Engine deshalb nicht als „+49, dann 221 oder 30“, sondern als zwei getrennte Alternativen: „beginnt mit +49221“ oder „endet auf 30 und mindestens eine weitere Ziffer“. Berliner Nummern wie +49305550100 treffen trotzdem, weil auch sie irgendwo 30 enthalten. Deshalb fällt der Fehler im Test nicht auf. Er fällt erst auf, wenn eine Frankfurter Nummer wie +49695553000 plötzlich über die Route für Köln und Berlin geht. Richtig ist ^\+49(221|30)\d+$.
|
AUS DER PRAXIS · Ein Maschinenbauer mit zwölf Standorten Bei einem Maschinenbauer mit zwölf Standorten liefen Anrufe zu einzelnen Kunden über den SBC eines anderen Werks. Nicht alle, nur manche, und niemand sah ein Muster. Die Ursache war eine Route für zwei Ortsnetze mit genau diesem Fehler: Alternative ohne Klammer. Getroffen wurden alle Nummern, die zufällig auf eine bestimmte Ziffernfolge endeten. Gefunden haben wir es nicht durch Anstarren des Musters, sondern mit einer Liste von Prüfnummern pro Standort und einem kleinen Skript, das für jede Nummer die gewinnende Route ausgibt. Das Skript findest du im nächsten Abschnitt. |
|---|
Diagnose Schritt für Schritt
Für die Diagnose brauchst du das Modul MicrosoftTeams und eine Rolle, die Telefonie-Einstellungen lesen darf. Alle Befehle in diesem Abschnitt ändern nichts. Du kannst sie also auch kurz vor Feierabend ausführen, ohne dass jemand in der Leitstelle nervös wird.

Schritt 1: Welche Nummer kommt an der Route an?
|
Connect-MicrosoftTeams $upn = "anna.berger@contoso.com" Test-CsEffectiveTenantDialPlan -Identity $upn -DialedNumber "08005550100" Test-CsEffectiveTenantDialPlan -Identity $upn -DialedNumber "112" |
|---|
Das Feld TranslatedNumber ist die Zeichenfolge, gegen die die Muster geprüft werden. Steht dort +498005550100, ist der Wählplan in Ordnung. Steht dort etwas ohne Pluszeichen oder mit einer Null nach +49, hast du das Problem eine Ebene früher gefunden. Wer intern mit Amtsholung wählt, prüft die Nummer mit vorangestellter 0. Wie das sauber gebaut wird, steht in Wählplan mit Amtsholung 0 in Teams richtig bauen.
Schritt 2: Policy und Usages des Benutzers
|
$vrp = (Get-CsOnlineUser -Identity $upn).OnlineVoiceRoutingPolicy $vrpId = if ([string]::IsNullOrEmpty("$vrp")) { "Global" } else { "Tag:$vrp" } $usages = (Get-CsOnlineVoiceRoutingPolicy -Identity $vrpId).OnlinePstnUsages $vrpId; $usages |
|---|
Ist OnlineVoiceRoutingPolicy leer, greift die globale Policy. Das ist selten Absicht und erklärt so manche Route, die „bei mir geht und bei dir nicht“. Hintergründe stehen in Teams-Benutzer fällt auf die globale Richtlinie zurück.
Schritt 3: Alle passenden Routen mit Priorität
Jetzt der entscheidende Blick: Welche Routen der Usages passen auf die Nummer, und welche davon gewinnt? Ein lesendes Cmdlet, das den kompletten Weg für Teams online simuliert, gibt es im Modul MicrosoftTeams nicht. Mit ein paar Zeilen PowerShell und der .NET-Regex-Engine baust du es nach:
|
$nummer = "+498005550100" # TranslatedNumber aus Schritt 1 $routen = Get-CsOnlineVoiceRoute | Sort-Object Priority foreach ($u in $usages) { $treffer = @($routen | Where-Object { $_.OnlinePstnUsages -contains $u -and [regex]::IsMatch($nummer, $_.NumberPattern) }) if ($treffer.Count -eq 0) { "Usage '$u': kein Treffer"; continue } "Usage '$u' gewinnt, weitere Usages werden nicht geprüft:" $i = 0 foreach ($r in $treffer) { $rolle = if ($i -eq 0) { "GEWINNT" } else { "Ersatz oder überdeckt" } " {0,-4} {1,-14} {2,-22} {3} ({4})" -f $r.Priority, $r.Identity, $r.NumberPattern, ($r.OnlinePstnGatewayList -join ", "), $rolle $i++ } break } |
|---|
Im Beispiel aus Fehlerbild 1 lautet die Ausgabe sinngemäß: Usage DE-National gewinnt, Priorität 1 DE-National mit ^\+49\d+$ über sbc1 GEWINNT, Priorität 2 DE-0800 mit ^\+49800\d+$ über sbc2 „Ersatz oder überdeckt“. Damit ist die Diskussion beendet, ob die Route „doch da ist“. Sie ist da. Sie steht nur auf Platz zwei.
Schritt 4: Überdeckungen im ganzen Bestand finden
Schritt 3 beantwortet die Frage für eine Nummer. Um alle überdeckten Routen zu finden, brauchst du für jede Route einen Prüffall: eine Nummer, die genau diese Route treffen soll. Das Skript prüft dann, ob in derselben Usage eine andere Route mit kleinerer Zahl ebenfalls passt:
|
$prueffaelle = @{ "DE-0800" = "+498005550100" "Köln-Berlin" = "+492215550100" "Notruf" = "112" } $routen = Get-CsOnlineVoiceRoute | Sort-Object Priority foreach ($name in $prueffaelle.Keys) { $nr = $prueffaelle[$name] $ziel = $routen | Where-Object Identity -eq $name if (-not [regex]::IsMatch($nr, $ziel.NumberPattern)) { "${name}: Muster passt nicht auf den eigenen Prüffall $nr"; continue } foreach ($u in $ziel.OnlinePstnUsages) { $vorher = $routen | Where-Object { $_.Identity -ne $name -and $_.Priority -lt $ziel.Priority -and $_.OnlinePstnUsages -contains $u -and [regex]::IsMatch($nr, $_.NumberPattern) } foreach ($v in $vorher) { "$name ist in Usage '$u' überdeckt von $($v.Identity) (Prio $($v.Priority))" } } } |
|---|
Die Identitäten in der Prüfliste müssen exakt den Namen deiner Routen entsprechen. Das Skript deckt zwei Fehlerbilder auf einmal ab: Passt das Muster nicht einmal auf den eigenen Prüffall, hast du Fehlerbild 2, 3 oder 5. Taucht eine Route mit kleinerer Zahl auf, hast du Fehlerbild 1 oder 4. Überdeckungen über die Usage-Reihenfolge erkennst du zusätzlich mit dem Skript aus Schritt 3.
Schritt 5: Sind die Gateways der Gewinner-Route verfügbar?
|
Get-CsOnlinePSTNGateway | Format-Table Identity, Enabled, SendSipOptions -AutoSize |
|---|
Steht in der Gewinner-Route nur ein deaktiviertes Gateway, nimmt Teams die nächste passende Route, und schon sieht es so aus, als wäre die falsche Route aktiv. Wenn der Anruf zwar den richtigen SBC erreicht, dort aber mit einem SIP-Fehler endet, liegt das Problem hinter der Route. Dann hilft SIP-Fehlercodes in Teams Direct Routing verstehen.
Im Teams Admin Center
Wer lieber klickt: Unter Voice › Direct Routing findest du auf dem Reiter Voice routes alle Routen mit Priorität und Muster, unter Voice › Voice routing policies die Policies mit ihren Usages in Reihenfolge. Die deutsche Oberfläche benennt die Menüs sinngemäß übersetzt. Für einzelne Routen reicht das. Für die Frage „Welche Route überdeckt welche?“ musst du aber alle Muster im Kopf gegen eine Nummer prüfen, und das kann PowerShell zuverlässiger als jedes menschliche Gehirn am Freitagnachmittag.
|
WERKZEUG · So findet es der Teams-Telefonie Diagnostiker Der Diagnostiker meldet eine überdeckte Route als Befund mit Prüffall: Er nennt die Route, die nie gewinnen kann, die Route, die sie überdeckt, und eine Beispielnummer, an der du das Verhalten nachvollziehen kannst. Der Befund erscheint in der Ampel im Bereich SBC/Routing. Mit dem Rufweg-Simulator spielst du die Beispielnummer für einen bestimmten Benutzer durch Wählplan, Normalisierung, Policy, Usage und Route bis zum Gateway. Die Routing-Landkarte zeigt Policies, Usages, Routen und Gateways im Zusammenhang. Der Assistent für Routing weist beim Anlegen neuer Routen auf Konflikte mit bestehenden Mustern hin und zeigt vorab, was entsteht. Der Teams-Telefonie Diagnostiker lässt sich 15 Tage kostenlos testen. |
|---|


Behebung: Route reparieren, ohne neue Löcher zu reißen
Vorher sichern
Bevor du an Mustern oder Prioritäten drehst, sicherst du den Ist-Zustand. Das kostet zehn Sekunden und ist dein Rückweg:
|
$stamp = Get-Date -Format "yyyyMMdd-HHmm" Get-CsOnlineVoiceRoute | Export-Clixml ".\routes-$stamp.xml" Get-CsOnlineVoiceRoutingPolicy | Export-Clixml ".\vrp-$stamp.xml" |
|---|
Überdeckung auflösen: zwei Wege
Für eine überdeckte Route gibt es zwei saubere Lösungen. Welche besser ist, hängt davon ab, wie viele Routen sich überschneiden.
|
Weg |
Was du tust |
Vorteil |
Nachteil |
|---|---|---|---|
|
A Priorität ändern |
Die spezielle Route bekommt eine kleinere Zahl als die allgemeine |
Schnell, ein Befehl, Muster bleiben unverändert |
Hängt an der Reihenfolge. Die nächste neue Route kann es wieder kaputt machen |
|
B Muster schärfen |
Das allgemeine Muster schließt das Spezielle aus, etwa ^\+49(?!800)\d+$ |
Kein Überlapp mehr, Reihenfolge wird egal |
Muster wird länger. Jede neue Ausnahme muss ergänzt werden |
Weg A, Priorität ändern:
|
Set-CsOnlineVoiceRoute -Identity "DE-0800" -Priority 1 Get-CsOnlineVoiceRoute | Sort-Object Priority | Format-Table Identity, Priority, NumberPattern |
|---|
Weg B, Muster schärfen. Prüfe das neue Muster vorher gegen deine Prüffälle, und zwar positiv und negativ:
|
$neu = '^\+49(?!800)\d+$' [regex]::IsMatch('+49695550100', $neu) # True: Frankfurt bleibt national [regex]::IsMatch('+498005550100', $neu) # False: 0800 geht an DE-0800 [regex]::IsMatch('112', $neu) # False: Notruf hat seine eigene Route Set-CsOnlineVoiceRoute -Identity "DE-National" -NumberPattern $neu |
|---|
Das Konstrukt (?!800) ist ein negativer Lookahead: An dieser Stelle darf nicht 800 folgen. Die einfachen Anführungszeichen in PowerShell sorgen dafür, dass das $ am Ende nicht als Variable interpretiert wird. Bei doppelten Anführungszeichen gilt das nur, solange nach dem $ nichts folgt, was PowerShell als Variablennamen lesen könnte. Einfache Anführungszeichen ersparen dir das Nachdenken.
Muster und Prioritäten korrigieren
Fehlerbild 2: Muster auf E.164 umstellen, also ^\+49221\d+$ statt ^0221\d+$. Liefert der Wählplan kein E.164, korrigierst du zuerst den Wählplan, nicht die Route.
Fehlerbild 3: Backslash ergänzen. Aus ^+49\d+$ wird ^\+49\d+$.
Fehlerbild 4: Prioritäten tauschen, sodass die Route mit dem Haupt-SBC die kleinere Zahl hat. Danach die komplette Liste kontrollieren.
Fehlerbild 5: Alternativen klammern und verankern: ^\+49(221|30)\d+$.
|
TIPP · Erst im Kleinen, dann für alle Statt eine produktive Route umzubauen, legst du eine neue Route mit korrigiertem Muster an einer eigenen Usage an, steckst diese Usage an den Anfang einer Kopie der Policy und weist die Kopie zwei, drei Testbenutzern zu. Passt alles, übernimmst du die Korrektur in die produktive Route. Der Rückweg ist dann eine einzige Zuweisung zurück auf die alte Policy. |
|---|
Wirksamkeit prüfen und Rollback
Änderungen an Routing-Objekten sind nicht in derselben Sekunde überall wirksam. Plane etwas Wartezeit ein und prüfe dann mit dem Skript aus Schritt 3 und einem echten Anruf auf eine unkritische Nummer. Geht etwas schief, holst du den alten Stand aus der Sicherung zurück:
|
$alt = Import-Clixml ".\routes-$stamp.xml" | Where-Object Identity -eq "DE-National" Set-CsOnlineVoiceRoute -Identity "DE-National" -NumberPattern $alt.NumberPattern ` -Priority $alt.Priority |
|---|
Wenn du mehrere Prioritäten geändert hast, stellst du sie in derselben Reihenfolge zurück, in der sie vorher standen, beginnend mit der kleinsten Zahl. Kontrolliere anschließend wieder die komplette Liste.
|
AUS DER PRAXIS · Ulis eigener anynode-SBC In meinem eigenen Tenant läuft Direct Routing über einen anynode-SBC. Als ich dort einen zweiten Trunk für Testnummern ergänzt habe, habe ich genau Fehlerbild 1 produziert: neue Route, schönes Muster, angehängt an die bestehende Usage, Priorität von Teams vergeben. Ergebnis: Kein einziger Testanruf erreichte den neuen Trunk, weil die alte Route mit ^\+49\d+$ auf Platz eins stand. Seitdem gilt bei mir: Jede neue Route bekommt beim Anlegen ausdrücklich eine Priorität, und vor dem Speichern läuft das Prüffall-Skript. Das ist weniger elegant als Vertrauen, aber deutlich kürzer als die Fehlersuche. |
|---|
Vorbeugung: damit deine Routen auch morgen noch greifen
Jedes Muster verankert. Immer ^ am Anfang und $ am Ende. Ein Muster ohne Anker ist eine Überdeckung, die nur auf ihre Gelegenheit wartet.
Immer \+ statt +. Und immer E.164: +49, Ortsvorwahl ohne führende 0.
Alternativen in Klammern. (221|30), nie 221|30 ohne Klammer.
Vom Speziellen zum Allgemeinen. In jeder Usage bekommen spezielle Muster die kleineren Zahlen, Sammelmuster die größten. Oder du schärfst das Sammelmuster so, dass es sich nicht überschneidet.
Priorität ausdrücklich setzen. Beim Anlegen einer Route nie Teams die Zahl vergeben lassen, wenn sich das Muster mit bestehenden überschneidet.
Notruf eigens behandeln. Eine Route für ^(110|112)$ in der ersten Usage jeder Policy, keine unverankerten Sammelmuster davor.
Prüffälle pflegen. Zu jeder Route gehört mindestens eine Nummer, die sie treffen muss, und eine, die sie nicht treffen darf. Nach jeder Änderung läuft das Skript aus Schritt 4.
Soll-Zustand dokumentieren. Muster und Prioritäten aller Routen gehören in die Betriebsdokumentation und werden regelmäßig mit dem Ist-Zustand verglichen.
Zum letzten Punkt passen zwei Vertiefungen: Konfigurationsdrift in der Teams-Telefonie erkennen zeigt, wie du ungeplante Änderungen erkennst, und Microsoft Teams Telefonie-Governance regelt, wer überhaupt an Routen schrauben darf. Wenn dein Routing über Jahre und Standorte gewachsen ist und du es grundsätzlich neu ordnen willst, ist das ein gutes Thema für ein Festpreispaket Grobkonzept Teams-Telefonie oder eine Beratung zur Teams-Telefonie. Wer Regex für Routen und Normalisierungsregeln lieber einmal in Ruhe lernt als im Störungsfall, ist in der Schulung Teams-Telefonie richtig.
FAQ
Warum greift meine Voice Route nicht, obwohl das Muster passt?
Weil in derselben Usage eine andere Route mit kleinerer Prioritätszahl ebenfalls passt, oder weil eine frühere Usage der Policy schon einen Treffer liefert. Teams nimmt nicht die passendste, sondern die erste passende Route. Prüfe mit dem Skript aus Schritt 3, welche Route gewinnt.
Gewinnt in Teams die spezifischere Route?
Nein. Es gibt kein Prinzip „längster Präfix gewinnt“. Entscheidend sind die Reihenfolge der Usages in der Policy und innerhalb der Usage die Prioritätszahl, die kleinste zuerst.
Muss ich das Pluszeichen im Muster maskieren?
Ja. Ein + ist in Regex ein Quantor. Das Muster ^+49\d+$ ist gültig, trifft aber keine Nummer, die mit + beginnt. Richtig ist ^\+49\d+$.
Gegen welche Nummer prüft Teams das Muster?
Gegen die Nummer nach der Normalisierung durch den Wählplan, im Idealfall E.164 wie +49695550100. Eine Durchwahl im Format ;ext= wird laut Microsoft dabei nicht berücksichtigt. Die tatsächliche Nummer siehst du mit Test-CsEffectiveTenantDialPlan im Feld TranslatedNumber.
Welche Regex-Syntax gilt für Voice Routes?
Die Muster sind reguläre Ausdrücke in der Syntax, die du aus .NET und PowerShell kennst. Deshalb eignet sich [regex]::IsMatch() in PowerShell gut, um ein Muster vor dem Anlegen zu prüfen. Online-Tester mit anderer Regex-Variante können sich in Details anders verhalten.
Wie schließe ich 0800 oder 0900 aus einer nationalen Route aus?
Mit einem negativen Lookahead, zum Beispiel ^\+49(?!800|900)\d+$. Achte darauf, dass keine Sammelroute in einer anderen Usage der Policy die ausgeschlossenen Nummern doch wieder auffängt.
Was passiert, wenn zwei Routen dieselbe Priorität haben sollen?
Die Priorität ist ein Rangplatz. Wenn du zwei SBCs gleichwertig nutzen willst, trägst du beide in dieselbe Route ein. Teams versucht die SBCs einer Route laut Microsoft in zufälliger Reihenfolge.
Warum geht der Notruf nicht über meine Notrufroute?
Entweder fängt eine Sammelroute wie \d+ oder .* in einer früheren Usage oder mit kleinerer Zahl die 112 ab, oder eine Notruf-Richtlinie mit eigener PSTN Usage greift. Prüfe beides, und teste ohne echten Notruf.
Fazit: Nicht die passendste Route gewinnt, sondern die erste
Eine Voice Route, die nicht greift, ist fast nie kaputt. Sie steht an der falschen Stelle, erwartet eine Nummer, die so nie ankommt, oder hat ein Zeichen zu wenig. Die fünf Fehlerbilder lassen sich auf drei Fragen eindampfen: Welche Nummer kommt wirklich an? Welche Routen passen in der gewinnenden Usage? Und welche davon hat die kleinste Zahl?
Wer diese Fragen mit lesenden Befehlen beantwortet, statt Muster im Admin Center anzustarren, findet überdeckte Routen in Minuten. Verankere jedes Muster, maskiere das Pluszeichen, klammere Alternativen, setze Prioritäten bewusst und pflege zu jeder Route einen Prüffall. Dann landet die 0800-Nummer auf dem 0800-Trunk, der Haupt-SBC macht wieder seine Arbeit, und die Route, die „doch da ist“, ist auch an der richtigen Stelle.
Dieses Consulting-Dokument steht als PDF zum Download bereit: https://www.boddenberg.de/ArtikelPdf/deine-neue-teams.pdf — © Ulrich B. Boddenberg · boddenberg.de











