Microsoft has just announced a public preview of Direct Routing for Microsoft Teams. This is one of the big steps — in my opinion — of making parity with Skype Online.
Direct Routing effectively allows you to connect up existing PSTN connectivity (e.g. SIP trunks) into a certified SBC and route directly to Teams. This differs from the Skype Online method of doing this, in that you no longer need any hardware (on-premises Skype for Business Server or a CCE) other than an SBC.
In this post, I’ll go over how to do this with an AudioCodes SBC and SIP trunks. I shan’t go into too much detail as the documentation from Microsoft and AudioCodes is pretty good:
Before you begin configuration, you need to make sure you have (or will have) everything needed in place:
- An AudioCodes SBC running at least version v.7.20A.154.007 and the following licenses:
- Microsoft license (MSFT) – Should be on most SBCs.
- SBC sessions – same as any other AudioCodes SBC configuration using SIP-SIP, it will consume SBC sessions.
- (Optional) SILK codec – if you want to use the SILK codec instead of G.711, you will need to license it.
- (Optional) Transcoding – if your SIP carrier doesn’t support a codec Teams uses e.g. SILK – to use SILK for Teams would require transcoding.
- The SBC has “LAN” and “WAN” interface with a public IP address assigned (or NAT’d through) to the “WAN” interface.
- A SIP trunk configured on the SBC – I won’t cover this off as it could be configured in a million different ways.
- An A record created that points to the public IP address of the SBC. This can be part of any domain that is in the Office 365 tenant (except the onmicrosoft.com domain). An example could be sbc.domain.com if domain.com is a verified domain on your tenant.
- A publicly issued certificate with the A record/FQDN of the SBC in the common name or SAN. You can also use a wildcard, but I’ve not tried that. Microsoft does not trust all public CAs, so make sure it is on their list. Examples of trusted CAs are DigiCert, Globalsign, Go Daddy.
- Communication is allowed through any firewalls that the SBC uses. The following ports need to be allowed:
Traffic From To Source Port Destination Port Description SIP/TLS Teams SIP Proxy* SBC 1024-65535 TCP Defined on SBC SIP signalling from Teams to your SBC, the destination port is dependant on what you configure the TLS SIP Interface to be. (Default is 5067 TCP) SIP/TLS SBC Teams SIP Proxy* Defined on SBC 5061 TCP SIP signalling from your SBC to Teams. I would most likely allow all source ports (1024-65535 TCP) to destination port 5061. UDP/SRTP Teams Media Processor** SBC 49152-53247 UDP Defined on SBC Media from Teams to your SBC. The destination port is dependant on what is configured in the media realm on the SBC. UDP/SRTP SBC Teams Media Processor** Defined on SBC 49152-53247 UDP Media from your SBC to Teams. The source port is dependant on what is configured in the media realm on the SBC.
* Teams SIP Proxy IPs are currently: 126.96.36.199 (yes, .0), 188.8.131.52, 184.108.40.206, 220.127.116.11, 18.104.22.168 and 22.214.171.124
** Teams Media Processor IPs are not yet defined other than “currently any IP from the Azure Network Range“. Quite a lot of IP’s, that. In my opinion I would just allow Any IP to test first and once happy, tie it down afterwards.
- Access to the tenant via Skype Online PowerShell.
- Users homed on Skype Online (not on-premises).
- Users are licensed correctly with the following licenses:
- Skype Online (Plan 2) – Part of E3, E5 etc.
- Microsoft Phone System – Can be bought standalone or part of E5.
- Microsoft Teams – Part of E3, E5 etc.
- Microsoft Audio Conferencing – Not techinally required to make and recieve calls, but needed if adding participants to meetings etc. Can be bought standalone or part of E5.
At this stage you should have an SBC:
- Running a supported version.
- Setup the PSTN e.g. SIP trunk to route to Teams.
- Two NICs – one “LAN” side, one “WAN” side with a public IP address.
- Created an A record for the SBC and it should be pointing at the SBC’s public IP address.
First thing to do is setup certificates so Teams and the SBC trust each other and encrypt all traffic. Under Setup > IP Network >Security >TLS Contexts create a new TLS context specifically for Teams. It needs to be given a name and set the TLS version to 1.0, 1.1 and 1.2.
Next, under the new TLS context, go to Change Certificate and create a CSR. As mentioned earlier, the SBC FQDN needs to be in the common name or SAN.
Create the CSR (I had to generate a 2048 bit private key first). Copy this to your CA (making sure its supported as per the list) to get it raised.
Once the certificate is issued, upload it as a device certificate in the same location you generated the CSR:
If you now go back the TLS context, under Certificate Information, you should have the issued certificate:
Now the certificate is installed, you need to install any root or intermediates in the chain. In addition you need to install the root certificate Teams SIP Proxy is using – this can be downloaded here. Still under the TLS context, go to Trusted Root Certificates and import the root and intermediate certificates. In my case I have a Globalsign root and a Alpha SSL intermediate for my certifricate and a Baltimore root so that the Teams SIP Proxy is trusted:
Worth noting – the SBC will only accept certificates in Base64 format, not DER.
Navigate to Setup > Signaling and Media >Core Entities > Media Realms. Make sure you have a Media Realm for your “LAN” and “WAN” interfaces. I’ve created 2 and assigned 100 media session legs to each. Obviously if you are going to have more than 100 media session legs, assign more. Make a note of the “WAN” port range as this is the defined SBC media range for the firewall rules.
Navigate to Setup > Signaling and Media > Core Entities > SIP Interfaces. This is in addition to the SIP Interface used by your SIP carrier. Click New and create a new SIP Interface. You will need to do the following:
- Give it a name e.g. Teams.
- Network Interface to be the “WAN” interface.
- Set UDP and TCP Port to 0. Set the TLS Port to whatever port you want the SBC to listen on externally. Typically, in Skype for Business, this has been 5067. Make a note of this as this makes up the defined SBC signalling port for the firewall rules and you need to specify it in Skype Online PowerShell later.
- Enable TCP Keepalive.
- Media Realm to the one created for the “WAN” interface.
- TLS Context Name to the one created for Teams.
- Enable TLS Mutual Authentication.
- Set the Classification Response to 0 (SBC will not respond to failures, useful in DoS attacks).
Navigate to Setup > Signaling and Media > Core Entities > Proxy Sets. As with SIP Interfaces, you should already have one for your SIP trunk. Let’s add one for Teams by clicking New. Set up as:
- Give it a name e.g. Teams.
- SBC IPv4 SIP Interface as the one you just created.
- TLS Context Name to the Teams one you created.
- Proxy Keepalive to Using OPTIONS.
- Proxy Hot Swap to Enabled.
- Proxy Load Balancing Method to Random Weights.
- DNS Resolve Method to SRV.
Once the Proxy Set is created, you need to click Proxy Addresses at the bottom of the Proxy Set. Add teams.local as the only address and set the transport type to TLS:
(Don’t worry, I know teams.local doesn’t resolve to anything – all will become apparent later).
Navigate to Setup > Signaling and Media > Coders and Profiles > Coder Groups. Here, we need to an define an unused group what codecs will be used when communicating with Teams:
(Note: for SILK, you will need the SILK codec license).
Navigate to Setup > Signaling and Media > Coders and Profiles > IP Profiles. Again, you should already have one for your SIP trunk. Click New and add one like so:
- Give it a name e.g. Teams.
- SBC Media Security Mode to SRTP.
- SBC Media Security Method to SDES. Note: AudioCodes note when Direct Routing reaches GA, it should change to DTLS.
Extension Coders Group to the one you just created.
- MKI Size to 0.
- SBC Enforce MKI Size to Enforce.
- Symmetric MKI to Enable.
Reset SRTP Upon Re-Key to Enable.
- Generate SRTP Keys Mode to Always.
Navigate to Setup > Signaling and Media > Core Entities > IP Group. You guessed it – there should already be one here for your SIP trunk. Now, let’s set one up for Teams. You need to setup like below:
- Give it a name e.g. Teams.
- Proxy Set to the one you created for Teams.
- IP Profile to the one you just created.
- Media Realm to the one assigned to the “WAN” interface.
- SBC Operation Mode to B2BUA.
- Classify By Proxy Set to Disable (as the Proxy Set address is teams.local that would be bad).
- Local Host Name to the SBC FQDN/A record. This is then used in Contact and VIA headers.
- DTLS Context to the Teams one you setup.
Internal SRV Table
Navigate to Setup > IP Network > DNS > Internal SRV. Remember setting teams.local SRV as the proxy address earlier? Well, this is where it comes in to play. Effectively, the SBC has the teams.local SRV record resolve to all 3 Teams SIP Proxy addresses in its own DNS table and has them weighted in order. Set them as below:
Side Note: The three addresses here are the primary and two standby Teams SIP Proxy addresses. It’s quite clever in that dependent where you are in the world each address will resolve to the nearest entry point in order. In the EU for example, sip.pstnhub.microsoft.com would be the EU entry point, sip2.pstnhub.microsoft.com would be the US entry point and sip3.pstnhub.microsoft.com would be the ASIA entry point. In the US and ASIA it would be a different order.
Navigate to Setup > Signaling and Media > Media > Media Security and make sure Media Security is Enabled and the Media Security Behaviour is set to Preferable – Single Media. (Ideally use SRTP when you can).
First, make a note of the Teams SIP Interface ID you created earlier. Then, navigate to Signalling and Media > Message Manipulation > Message Manipulations. In here you need to change the Contact header that is sent to Teams. The default behaviour is to send it’s “WAN” IP address in the Contact instead of an FQDN:
If you now click New and configure as:
- Give it a name e.g. Teams Contact Header.
- Manipulation Set ID to an ID not used by any existing message manipulations.
- Message Type to options.
- Condition to param.message.address.dst.sipinterface==’1′ (Change ‘1’ to whatever ID your Teams SIP Interface is). By specifying it, we’re only affecting Teams and not any other SIP Interfaces you may have.
- Action Subject to header.contact.url.host – This is what is being modified.
- Action Type to Modify.
- Action Value to the FQDN of the SBC in single quotes e.g. ‘sbc.domain.com’
Once set, you will need to log in to https://<SBC>/AdminPage and under ini Parameters run GWOutboundManipulationSet with the value of the Manipulation Set you specified. Running this will enable it.
Now, your Contact header should be showing your SBC FQDN:
Navigate to Signalling and Media > Message Manipulation > Message Conditions. Here you need to create a condition that only accepts SIP messages that contain the Contact header ‘pstnhub.microsoft.com’ – effectively a reverse of the previous step. Click New and give it a Name e.g. Teams Contact Header and the condition should be header.contact.url.host contains ‘pstnhub.microsoft.com’
Navigate to Signalling and Media > SBC > Classification. In here, using the message condition you just created, you need to classify (as the traffic won’t match the ‘teams.local’ set in the Proxy Set) and allow this traffic. Configure as below:
- Give it a name e.g. Teams.
- Source SIP Interface will be the Teams SIP Interface you created.
- Destination Host will be the SBC FQDN (not in single quotes this time).
- Message Condition to the one you just created.
- Action Type to Allow.
- Source IP group to the Teams IP group you created.
Navigate to Setup > Signaling and Media > SBC > Routing > IP-to-IP Routing. Here, you need to create rules to:
- Not forward OPTIONS between IP groups.
- Route calls from your SIP trunk IP group (in my case – Gamma) to your Teams IP group. If you were running co-existence with Skype, you could change the Destination Username to route only a certain DDI/range.
- Route calls from Teams IP group to your SIP trunk IP group (in my case – Gamma).
You should now have 3 routes defined:
Verify Connection to Teams
That’s it – you should now have enough configuration to talk to Teams. If you look at Monitor > VOIP Status > Proxy Set Status it should show as online for all 3 regions:
Configure Office 365
Connect to Skype Online using the Skype Online PowerShell connector.
Add SBC as a PSTN Gateway
Once connected, you should now have some new cmdlets:
Then, run New-CSOnlinePSTNGateway cmdlet:
New-CsOnlinePSTNGateway -Fqdn <SBC FQDN> -SipSignallingPort <SBC TLS Port Defined in SIP Interface> -MaxConcurrentSessions <Amount of SBC sessions you are licensed for> -Enabled $true
You can see there are some extra parameters than can be set:
- CodecPriority – You can set it to prefer G711 before SILK etc.
- FailoverTimeSeconds – How long to wait for the SBC to respond. If it doesn’t respond, failover to another SBC (if there is one).
- SendSipOptions – Teams will send SIP OPTIONS. Disabling this will remove it from alerts and monitoring.
- MediaBypass – Reserved for future use.
- Enabled – Useful if you need to take the SBC from the useable list whilst performing maintenance.
If you check the Syslog of the SBC, you can see incoming requests from the Teams SIP Proxy:
Enable User(s) for Calling
For each user make sure they have the correct licenses assigned e.g. E3 with Phone System. Then, run the following command to enable them for calling:
Set-CsUser -Identity "<User name>" -EnterpriseVoiceEnabled $true -HostedVoiceMail $true -OnPremLineURI tel:<E.164 Tel Number>
Configure Voice Routing
Much like on-premises Skype for Business, you have number normalisation, policies, PSTN usages and routes. Like on-premises, this can get quite complex, but essentially calls are based on permissions (Voice Routing Policies) and the number called (Voice Routes).
To keep things simple, in my scenario I have one Voice Routing Policy, one PSTN usage, one Voice Route and one SBC.
Create a PSTN Usage – Here you add a PSTN Usage to the Global list using Set-CSOnlinePSTNUsage:
In my scenario, I’ve added a PSTN usage for the UK. You could add a PSTN usage for each country or for a particular type of call e.g. International.
Create Voice Route – Now you add a Voice Route. This is effectively a regex pattern to match. If it matches, it sends the call to the defined SBC(s):
In my scenario, I’ve routed all calls via a single SBC. You could list more than one SBC and order them based on preference. Another example route could be:
In this route only calls with a UK (+44) number would use this route. Notice the priority set, if you are using multiple routes it is critical you put the more specific routes higher.
Create Voice Routing Policy – Using the PSTN Usage(s) and their defined Voice Route(s), you can create Voice Routing Policy. It is effectively a list of allowed numbers and routes (and their priority) for a User:
I’ve created a Voice Routing Policy for UK users and have assigned the “UK” PSTN Usage.
Grant Voice Routing Policy for each user – With the newly created, policy – assign it to the users:
When I tried this initially it failed. I came back an hour or so and it was fine – maybe an issue on my end.
Once this is setup the call flow works like this:
- A user makes a call.
- Based on the Voice Routing Policy a list of PSTN Usages is returned.
- In order of priority, the Voice Routes within a PSTN Usage are checked to see if the number matches. If it does, the call is sent to the SBC(s) based on the list they are ordered in.
- If for whatever reason the call cannot be routed via the route (e.g. SBC(s) offline), then the remaining matching routes are used.
- If there are no working routes found and the user has a Calling Plan assigned, this is used as a last resort.
Assign a Teams Interop Policy to each user – Each user will need to have a Teams Interop Policy assigned that uses Teams for calling. Currently, there are 8 policies available:
Some allow client override (user can choose), others do not and the user will have to use what you set. In this case, I’ve assigned DisallowOverrideCallingTeamsChatTeams to force the use of Teams for chat and calling:
Enable the use of Teams for calling
Under the Teams part of Settings and Services and add-ins of Office 365 Admin Centre, make sure Allow Private Calling is Enabled:
And that should be it. It is thankfully fairly straight forward. By the end, you will have a SIP connection established to Teams and be able to route calls to and from Teams.