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
- Download and install the SFB Online Connector from https://www.microsoft.com/en-us/download/details.aspx?id=39366
- Import the SFB Online Connector module in PowerShell
# 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