Direct Routing for Teams

Configure Direct Routing for Teams

Microsoft Teams provides the functionality to replace your PBX (private branch exchange). To be able to call with a landline, you need access to the PSTN (public switched telephone network). One way to get this is with a Microsoft calling plan. The other way is to configure Direct Routing. If you have a supported SBC (Session Border Controller), you can create a SIP trunk to the Microsoft phone system.

If you don’t have the expertise to configure an SBC or better yet, a pair of SBC’s you can try to find a provider to host and maintain the SBC’s. Here in Belgium a provider that does exactly that is Destiny.

This article is a compilation of my actions to set this up and perform a migration from a Skype For Business on premise environment to Microsoft Teams.

In this article the domain name of the customer is customer.com, the name of a user is [email protected].

Licensing in Office 365

To be able to use the SIP trunk provided by Destiny we need to make sure the user has the necessary Phone System license. More info on the license here.

  • Assign a license to the users who need to make calls.

Add a domain for the SBC in Office 365

To connect the sbc to the Office 365, it is mandatory to provide a valid certificate. Add the domains provided by Destiny to the Office 365 tenant. These domains will probably look like customera.teams.destiny.be and customerb.teams.destiny.be. To complete the validation send the TXT record to your Destiny contact.

After the creation of the TXT record, you can complete the setup of the domains in Office 365, by verifying the record.

Setup direct routing connection to the SBC

Microsoft documentation on the subject can be found here.

Install prerequisites

# Import the module
Import-Module SkypeOnlineConnector
# Install the MicrosoftTeams Module with version at least 0.9.5
Install-Module -name MicrosoftTeams -RequiredVersion 0.9.5

Create a session to SFB Online

First we need a session to SFB Online.

$Session = New-CsOnlineSession -UserName [email protected]
Import-PSSession $Session -AllowClobber

Next we can test if the cmdlets of the imported modules are available.

# Get the online PSTN gateway commands, just to see if they are available
get-command *OnlinePSTNGateway*

The output should show a list of availlable commands.

Setup the PSTN gateway

We need to add the PSTN gateways customera.teams.destiny.be and customerb.teams.destiny.be to our tenant. To be able to add these gateways, the domains must be listed in DomainUrlMap field from the command.

Get-CsTenant | select DomainUrlMap

Otherwise, you might get the error New-CsOnlinePSTNGateway returns "Can not use the domain as it was not configured for this tenant"

The easiest way to get the domain in the list is to make a dummy user in Office 365 for the domains customera.teams.destiny.be and customerb.teams.destiny.be. After the users are created, login to https://teams.microsoft.com with these users. Once the domains are listed in the DomainUrlMap, continue adding the gateways.

# Create the PSTN gateway
New-CsOnlinePSTNGateway -Fqdn customera.teams.destiny.be -SipSignalingPort 6061 -MaxConcurrentSessions 100 -Enabled $true
New-CsOnlinePSTNGateway -Fqdn customerb.teams.destiny.be -SipSignalingPort 6061 -MaxConcurrentSessions 100 -Enabled $true

# Verify creation
Get-CsOnlinePSTNGateway

Identity                           : customera.teams.destiny.eu
InboundTeamsNumberTranslationRules : {}
InboundPstnNumberTranslationRules  : {}
OutbundTeamsNumberTranslationRules : {}
OutboundPstnNumberTranslationRules : {}
Fqdn                               : customera.teams.destiny.eu
SipSignalingPort                   : 6061
FailoverTimeSeconds                : 10
ForwardCallHistory                 : False
ForwardPai                         : False
SendSipOptions                     : True
MaxConcurrentSessions              : 100
Enabled                            : True
MediaBypass                        : False
GatewaySiteId                      : 
GatewaySiteLbrEnabled              : False
FailoverResponseCodes              : 408,503,504
GenerateRingingWhileLocatingUser   : True
PidfLoSupported                    : False
MediaRelayRoutingLocationOverride  : 
ProxySbc                           : 
BypassMode                         : None

Identity                           : customerb.teams.destiny.eu
InboundTeamsNumberTranslationRules : {}
InboundPstnNumberTranslationRules  : {}
OutbundTeamsNumberTranslationRules : {}
OutboundPstnNumberTranslationRules : {}
Fqdn                               : customerb.teams.destiny.eu
SipSignalingPort                   : 6061
FailoverTimeSeconds                : 10
ForwardCallHistory                 : False
ForwardPai                         : False
SendSipOptions                     : True
MaxConcurrentSessions              : 100
Enabled                            : True
MediaBypass                        : False
GatewaySiteId                      : 
GatewaySiteLbrEnabled              : False
FailoverResponseCodes              : 408,503,504
GenerateRingingWhileLocatingUser   : True
PidfLoSupported                    : False
MediaRelayRoutingLocationOverride  : 
ProxySbc                           : 
BypassMode                         : None

Remove the dummy users from the Office 365 tenant.

Setup policies

Set CSOnlinePstnUsage. This modifies a set of strings that identify the allowed online public switched telephone network (PSTN) usages. This cmdlet can be used to add usages to the list of online PSTN usages or remove usages from the list.

# Create PSTN usage
Set-CsOnlinePstnUsage -Identity global -Usage @{Add="Peoplefone"}

# Verify creation
Get-CsOnlinePstnUsage

Identity : Global
Usage    : {Peoplefone}

New-CsOnlineVoiceRoute. Creates a new online voice route. Online voice routes contain instructions that tell Skype for Business Online how to route calls from Office 365 users to phone numbers on the public switched telephone network (PSTN) or a private branch exchange (PBX), based on the destination.

# Show the available PSTN gateways
Get-CsOnlinePSTNGateway | select identity

# Create the route based on the destination prefix
New-CsOnlineVoiceRoute -Identity "International" -NumberPattern "\d+" -OnlinePstnGatewayList customera.teams.destiny.eu, customerb.teams.destiny.eu -Priority 2 -OnlinePstnUsages "Peoplefone" # Number pattern "\d+" = route any number

# Verify creation
Get-CsOnlineVoiceRoute

Identity              : LocalRoute
Priority              : 0
Description           : 
NumberPattern         : ^(\+1[0-9]{10})$
OnlinePstnUsages      : {}
OnlinePstnGatewayList : {}
Name                  : LocalRoute

Identity              : International
Priority              : 1
Description           : 
NumberPattern         : \d+
OnlinePstnUsages      : {Peoplefone}
OnlinePstnGatewayList : {customera.teams.destiny.eu, customerb.teams.destiny.eu}
Name                  : International

New-CsOnlineVoiceRoutingPolicy. Creates a new online voice routing policy. Online voice routing policies manage online PSTN usages for Phone System users.

# Create a voice routing policy. This policy needs to be assign to a user later on. To find the availabel OnlinePstnUsage use Get-CsOnlinePstnUsage
New-CsOnlineVoiceRoutingPolicy "Peoplefone" -OnlinePstnUsages "Peoplefone"

# Verify creation
Get-CsOnlineVoiceRoutingPolicy

Identity         : Global
OnlinePstnUsages : {}
Description      : 
RouteType        : BYOT

Identity         : Tag:Peoplefone
OnlinePstnUsages : {Peoplefone}
Description      : 
RouteType        : BYOT

Grant-CsOnlineVoiceRoutingPolicy. Assigns a per-user online voice routing policy to one or more users. Online voice routing policies manage online PSTN usages for Phone System users.

Grant-CsOnlineVoiceRoutingPolicy -Identity [email protected] -PolicyName "Peoplefone"
# Verify
Get-CsOnlineUser -Identity [email protected] | select UserPrincipalName, OnlineVoiceRoutingPolicy

UserPrincipalName OnlineVoiceRoutingPolicy
----------------- ------------------------
[email protected]  Peoplefone        

Assign the Teams calling policy

This can be set by user or global. Depending on your environment choose below by user or global.

By user

Grant-CsTeamsCallingPolicy. Cmdlet to assign a specific Teams Calling Policy to a user.

Grant-CsTeamsCallingPolicy -PolicyName AllowCalling -Identity [email protected]
# Verify user Teams calling policy
Get-CsOnlineUser -Identity [email protected] | select Teams*

TeamsVoiceRoute                    : False
TeamsMeetingPolicy                 : 
TeamsCallingPolicy                 : 
TeamsInteropPolicy                 : 
TeamsMessagingPolicy               : 
TeamsUpgradeEffectiveMode          : TeamsOnly
TeamsUpgradeNotificationsEnabled   : False
TeamsUpgradePolicyIsReadOnly       : None
TeamsUpgradePolicy                 : UpgradeToTeams
TeamsCortanaPolicy                 : 
TeamsOwnersPolicy                  : 
TeamsMeetingBroadcastPolicy        : 
TeamsAppPermissionPolicy           : 
TeamsAppSetupPolicy                : 
TeamsCallParkPolicy                : 
TeamsEducationAssignmentsAppPolicy : 
TeamsUpdateManagementPolicy        : 
TeamsNotificationAndFeedsPolicy    : 
TeamsChannelsPolicy                : 
TeamsSyntheticAutomatedCallPolicy  : 
TeamsTargetingPolicy               : 
TeamsVerticalPackagePolicy         : 
TeamsComplianceRecordingPolicy     : 
TeamsMobilityPolicy                : 
TeamsTasksPolicy                   : 
TeamsIPPhonePolicy                 : 
TeamsEmergencyCallRoutingPolicy    : 
TeamsEmergencyCallingPolicy        : 
TeamsShiftsAppPolicy               : 
TeamsShiftsPolicy                  : 
TeamsUpgradeOverridePolicy         : 
TeamsVideoInteropServicePolicy     : 
TeamsWorkLoadPolicy                : 
TeamsFeedbackPolicy                :

Global

Set-CsTeamsCallingPolicy. Use this cmdlet to update values in existing Teams Calling Policies.

# Set the calling policy
Set-CsTeamsCallingPolicy -Identity global -AllowPrivateCalling $true

# Verify global Teams calling policy
Get-CsTeamsCallingPolicy -Identity global

Identity                   : Global
Description                : 
AllowPrivateCalling        : True
AllowWebPSTNCalling        : True
AllowVoicemail             : UserOverride
AllowCallGroups            : True
AllowDelegation            : True
AllowCallForwardingToUser  : True
AllowCallForwardingToPhone : True
PreventTollBypass          : False
BusyOnBusyEnabledType      : Disabled
MusicOnHoldEnabledType     : Enabled

Migrate users to SFB Online

First make sure the users have a telephone number and are Enterprise voice enabled.

# Set phone number & enterprise voice enabled
Set-CsUser -Identity [email protected] -EnterpriseVoiceEnabled $true -HostedVoiceMail $true -OnPremLineURI tel:+32xxxxxxxx

# Show user properties
Get-CsUser -Identity [email protected] | select DisplayName, EnterpriseVoiceEnabled, HostedVoiceMail, LineURI

DisplayName  EnterpriseVoiceEnabled HostedVoiceMail LineURI        
-----------  ---------------------- --------------- -------        
Urszula Such                   True                 tel:+32xxxxxxxx

Migrate users from SFB Online to Teams

Grant-CsTeamsUpgradePolicy. TeamsUpgradePolicy allows administrators to manage the transition from Skype for Business to Teams.

# Grant TeamsOnly mode to user already in SFB Online
Grant-CsTeamsUpgradePolicy -Identity [email protected] -PolicyName UpgradeToTeams

Move users from SFB on prem to Teams directly

# Move the user to SFB Online
Move-CsUser -Identity [email protected] -Target sipfed.online.lync.com -MoveToTeams #-WhatIf

Finish the migration

We can now set the Coexistence mode to Teams only. Set this in the Teams admin portal in Org-wide settings, Teams upgrade.

To finish the migration, publish an empty topology in SFB and run the local installer on each host, to remove any remaining roles from the servers. After that you can decommision the servers as usual.

Troubleshooting

This article provided some valuble insight during troubleshooting.

$User = <UPN of the user>
Get-CsOnlineUser $User | Format-List UserPrincipalName, DisplayName, SipAddress, Enabled, TeamsUpgradeEffectiveMode, EnterpriseVoiceEnabled, HostedVoiceMail, City, UsageLocation, DialPlan, TenantDialPlan, OnlineVoiceRoutingPolicy, LineURI, OnPremLineURI, OnlineDialinConferencingPolicy, TeamsVideoInteropServicePolicy, TeamsCallingPolicy, HostingProvider, InterpretedUserType, VoicePolicy 

UserPrincipalName              : [email protected]
DisplayName                    : Urszula Such
SipAddress                     : sip:[email protected]
Enabled                        : True
TeamsUpgradeEffectiveMode      : TeamsOnly
EnterpriseVoiceEnabled         : True
HostedVoiceMail                : True
City                           : 
UsageLocation                  : BE
DialPlan                       : BE
TenantDialPlan                 : 
OnlineVoiceRoutingPolicy       : Peoplefone
LineURI                        : tel:+32xxxxxxxx
OnPremLineURI                  : tel:+32xxxxxxxx
OnlineDialinConferencingPolicy : 
TeamsVideoInteropServicePolicy : 
TeamsCallingPolicy             : 
HostingProvider                : sipfed.online.lync.com
InterpretedUserType            : HybridOnlineSfBUser
VoicePolicy                    : HybridVoice
  • TeamsUpgradeEffectiveMode – Should be set to TeamsOnly, if not, try to change it again and look at the error message
  • UsageLocation, DialPlan, and TenantDialPlan – When using enterprise voice together with Microsoft Teams, UsageLocation is important. It decides the number you get as part of AudioConferencing and your DialPlan. The default DialPlan just adds a plus and country code to whatever you type in Teams and is rarely good enough. You should supplement with TenantDialplans, don’t crate them yourself, use https://www.ucdialplans.com/ by MVP Ken Lasko. UsageLocation is set using the MSol PowerShell module.
  • LineURI, OnPremLineURI, and VoicePolicy – if your VoicePolicy is set to BusinessVoice you have a Calling Plan assigned, if it is set to HybridVoice, you are using Direct Routing. This is good to know if you are troubleshooting why LineURI is not updated by OnPremLineURI for Direct Routing. You should also know that if you are not able to set OnPremLineURI using Set-CsUser using online PowerShell, then you have msRTCSIP-LineURI populated in local Active Directory. If you clear this attribute, you get write access to the OnPremLineURI online.
  • InterpretedUserType – is a great source of information. It tells you the status of the user. If you have any attributes in local Active Directory it will be set to HybridOnpremSfBUser. If for some reason the user is disabled it will show in this attribute as something with disabled such as DirSyncDisabledSfBUser. Read this useful blog article that goes into this in more detail
Avatar
Sven de Windt
Systems Administrator

Systems engineer with an intrest in automation

comments powered by Disqus