Teams Direct Routing with an AudioCodes SBC

Introduction

Microsoft has released 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:

Plan Direct Routing

Configure Direct Routing

AudioCodes Documentation

Pre-requisites

Before you begin configuration, you need to make sure you have (or will have) everything needed in place:

AudioCodes SBC:

  • 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: 52.114.148.0 (yes, .0), 52.114.132.46, 52.114.75.24, 52.114.76.76, 52.114.7.24 and 52.114.14.70
    ** Teams Media Processor IPs are currently defined as 52.112.0.0/14

    For latest IP addresses in use, check here: https://docs.microsoft.com/en-us/microsoftteams/direct-routing-plan#sip-signaling-fqdns-and-firewall-ports

Office 365:

  • 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.

Configure SBC

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.

Certificates

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.

Media Realms

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.

SIP Interface

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).

Proxy Set

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).

Coder Group

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).

IP Profile

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 it will support DTLS at a later date.
  • 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.

 

IP Group

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 set as teams.local, so that wouldn’t match the acutal addresses).
  • 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.

SRTP

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).

Message Manipulation

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, which is incorrect here:

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:

Condition Rule

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’. 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’

Classification Rule

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.

IP-to-IP Routing

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:

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:

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 with “Policy <name> is not a user policy”. I came back an hour or so and it was fine.

Once this is setup the call flow works like this:

  1. A user makes a call.
  2. Based on the Voice Routing Policy a list of PSTN Usages is returned.
  3. The Voice Routes tied to the PSTN Usages are checked to see if the number matches. If it does, the call is sent to the SBC(s) in the route with the highest priority.
  4. If for whatever reason the call cannot be routed via the route (e.g. SBC(s) offline), then the remaining matching routes are used.
  5. 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:

Wrap up

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.

31 thoughts on “Teams Direct Routing with an AudioCodes SBC

  • 21st June 2018 at 3:45 PM
    Permalink

    Nice write up. Quite a bit of work, but nothing like it used to be. Was pointed here by Audiocodes and we’re (SureVoIP) looking at these SBC’s

    Reply
  • 21st June 2018 at 3:52 PM
    Permalink

    They should be smart. I’ll mention it. Also looking at Ribbon solutions.

    Reply
    • 21st June 2018 at 4:55 PM
      Permalink

      Not seen much of the Ribbon offering. For Direct Routing they seem fairly similar. One person did tell me that the AudioCodes SBC can support multiple 365 tenants but the Ribbon cannot – I haven’t confirmed this, mind.

      Reply
      • 24th July 2018 at 6:28 PM
        Permalink

        The Ribbon Core SBC can support multiple tenants today.

        Reply
  • 21st June 2018 at 4:51 PM
    Permalink

    Thanks Gavin. Yeah back in the bad old days configuring an SBC or GW a big task. With the SBC config wizard you can configure quite easily. If AudioCodes are smart they will add support for Teams using the wizard.

    Reply
    • 21st June 2018 at 4:02 PM
      Permalink

      Coming soon 🙂

      Reply
      • 21st June 2018 at 8:53 PM
        Permalink

        Awesome. Keep me posted – keen to try that out!

        Reply
  • 26th June 2018 at 10:52 AM
    Permalink

    When i try and assign the voice policy in office 365 i get the message “Policy “UK_POLICY” is not a user policy. You can assign only a user policy to a specific user.” Any idea what this could be, gone back through this guide and the one Microsoft themselves posted and still the same.

    Reply
    • 26th June 2018 at 9:05 PM
      Permalink

      Hi Joel,

      I had the same myself. I left it for an hour or so – re run the same command and it worked. Could you try that?

      Thanks,
      Lee

      Reply
  • 1st July 2018 at 7:38 PM
    Permalink

    Hi Matt,

    That’s great – thanks for pointing it out. Looks like now it’s GA they moved it from SfB docs to Teams docs.

    Thanks again,
    Lee

    Reply
  • 16th July 2018 at 4:30 PM
    Permalink

    Configured this all but not getting the “Calls” button on Teams! Anyone experienced the same?

    Reply
    • 17th July 2018 at 10:41 AM
      Permalink

      Hi Mario,

      Can’t say I have – just checking if the Grant-CsOnlineVoiceRoutingPolicy completed without errors. On this command, it errored initially for me. Went back a few hours later and re-ran it and all was well that time.

      I’m guessing you also assigned an Interop Policy to allow calling within Teams?

      Thanks,
      Lee

      Reply
  • 24th July 2018 at 9:35 AM
    Permalink

    Hi Lee,
    Thank you for this significant amount of work here. Seems like a basic question – but in the details above you have assumed in a few areas that we have already entered SIp trunk details.
    Given this might be a new interface for a few users, and the SIp trunk formats differing between providers – is there any documentation you can reference regarding the setup of a basic sip trunk into the SBC?
    Many thanks,
    R

    Reply
    • 25th July 2018 at 9:32 AM
      Permalink

      Thanks Ryan,

      AudioCodes do write guides for specific SIP trunk providers. Do you have a specific one in mind? If not, let me see what I can find on a generic SIP trunk.

      Reply
      • 25th July 2018 at 9:38 AM
        Permalink

        Thanks Lee – I doubt that AudiCodes will have written a guide for this provider, it is a niche ISP in New Zealand. Yes, a generic SIP trunk guide would be great!

        The basic details I have from the ISP are:
        Realm: sipserver.host.co.nz
        username: username
        password: password
        DDI Assigned: +6498884444 (not a real number)

        Is there any additional info that I need?

        Reply
  • 25th July 2018 at 10:41 AM
    Permalink

    The easiest way of setting up an AudioCodes SBC is to use the ‘SBC Wizard’. This is a small application or part of the SBC web GUI that has built-in templates for all of the SIP Trunk providers and PBXs that have been tested with the SBC. The wizard asks a few questions about your setup, PBX type, SIP Trunk provider, IP addresses, etc then builds the configuration for you. You can then easily adapt this by adding a connection to Teams following Lee’s information above.

    Reply
  • 25th July 2018 at 11:20 AM
    Permalink

    Thanks John. Appreciate the input – I just thought I would make clear for anyone reading this that the Wizard will overwite all configuration, so perhaps try it before following the instructions above, not after…

    Reply
    • 25th July 2018 at 11:24 AM
      Permalink

      very good point 🙂

      Reply
  • 2nd August 2018 at 4:35 PM
    Permalink

    How’s AudioCodes support multi tenant?
    Does direct routing hosting mode is for support multi tenant ?
    How about single tenant multi domain? Does it all add domain with SAN and change the contact header?

    Reply
  • Pingback:Direct Routing in Azure using AudioCodes Mediant SBC Azure Edition – Part 2 – Lee Ford's Blog

  • 10th August 2018 at 12:20 PM
    Permalink

    Hi Lee,
    Thank you for your reply. I have follow your step to setup with Public IP is success.
    But We I set it on behind NAT with DMZ IP, it doesn’t work.

    I go to NAT translation and add a rules for WAN interface and Target IP Address is “Public IP”, Port start and stop leave it empty.

    Gateway General Settings- > NAT IP Address ” Public IP”

    I’ve trace the Firewall is 1 : 1 mapping and I’ve tested on another SBC working fine for same rules.

    Any advise?

    Reply
    • 10th August 2018 at 1:58 PM
      Permalink

      Hi John,

      You shouldn’t need the Gateway NAT address, so I would remove that first.

      Failing that, I would on up Syslog trace from SBC and make sure the public IP address is being used e.g. CONTACT header?

      Thanks,
      Lee

      Reply
      • 10th August 2018 at 4:09 PM
        Permalink

        OK, I deleted the Gateway NAT Address, I can see the outgoing SIP Contact header have Public IP.
        Contact:
        SIPAppMngr::GetControlIPAddress – Near NAT translation found for SIP Interface 1. Translated IP Address Public IP:5068

        sometime the call can’t be made, but once the call can established the call will drop after 30 seconds, Firewall rules inbound and outbound are running normal on Souns direct routing with behind NAT. so the firewall rules should be correct.

        It’s look like media firewall issue?
        recv

        Reply
        • 10th August 2018 at 4:50 PM
          Permalink

          When the call ends who sends the BYE? Is it Teams or the Audiocodes? What is the termination reason?

          Reply
          • 12th August 2018 at 1:28 PM
            Permalink

            Local send bye to Teams.
            Reason: SIP ;cause=400 ;text=”local, RTP Broken Connection”

            Thanks.

          • 13th August 2018 at 9:11 PM
            Permalink

            Hmmm sounds like the RTP stream isn’t being established. If you want to blank out the sensitive details of a call on the syslog, I can have a quick look for you. Email is lee at lee-ford dot co dot uk.

  • Pingback:Direct Routing in Azure using AudioCodes Mediant SBC Azure Edition – Part 1 – Lee Ford's Blog

  • 17th September 2018 at 4:13 AM
    Permalink

    Is the AWS Mediant SE with it’s trial license capable of testing SIP/Teams? I’m trying to get this working with 1x Twilio SIP trunk and Direct Routing/Teams. I can get SBC > Twilio test dials OK, and SBC > Teams test dials OK. But I can’t get Twilio to route to Teams or visa versa.

    My trial license says; should this be enough for an end-to-end test?

    Key features:
    Board Type: Mediant SW
    Max SW Ver: 9.80
    Channel Type: DspCh=0
    HA
    Security: IPSEC MediaEncryption StrongEncryption EncryptControlProtocol
    DSP Voice features:
    DATA features:
    Coders: G723 G729 G728 NETCODER GSM-FR GSM-EFR AMR EVRC-QCELP G727 ILBC EVRC-B AMR-WB G722 EG711 MS_RTA_NB MS_RTA_WB SILK_NB SILK_WB SPEEX_NB SPEEX_WB OPUS_NB OPUS_WB
    Control Protocols: MGCP SIP SBC=3 MSFT
    Default features:
    Coders: G711 G726

    Reply
    • 17th September 2018 at 2:33 PM
      Permalink

      Hi Michael,

      Licenses look ok. Can you see anything in a syslog trace at all?

      Thanks

      Reply

Leave a Reply