OpenSIPS as MS Teams SBC

Microsoft Teams

Microsoft Teams is the product which is going to replace Lync and Skype for Business. With MS Teams you can communicate with users on your Office365 tenant. It is straightforward in case you don’t need to talk to people outside of your company. And in case you do need connection to the outside world there are 2 ways:

  • buy phone numbers and outgoing traffic from Microsoft
  • use so called “Direct Routing” to connect over SIP.

How can OpenSIPS help?

Most of companies already have some infrastructure with employee’s phones, external phone numbers, which are known to customers etc. So, MS Teams Direct Routing is the way to connect MS Teams infrastructure and the existing telephony infrastructure of the company. With proper configuration external numbers can be forwarded to MS Teams or left on PBX, and existing outgoing trunks can be used for calling out from MS Teams.

OpenSIPS can process SIP very efficiently, so why not to use it instead of Microsoft certified Session Border Controllers.

MS Teams doesn’t use user/password authentication, that’s why it has some very specific requirements for SIP to authenticate and authorize calls. Let’s start with the very simple case, with just one MS Teams tenant for one company.

MS Teams encrypts all the traffic. SBC should use SIP over TLS and SRTP for media. SRTP processing is the responsibility of a media server or RTPEngine. Of course, our SBC should have a correct FQDN (let’s call it SBC_FQDN) and an SSL certificate for this name. For this article we created a domain “voipgw.ipnordic.dk”. While configuring MS Teams part we should add exactly this domain SBC_FQDN to Office365 tenant and add Direct Routing SBC with Power Shell.

Configuring Direct Routing in MS Teams

Microsoft provides documentation on the setup of Direct Routing for Teams. So, this article describes very basic steps for adding the Direct Routing gateway.

Add domain SBC_FQDN (voipgw.ipnordic.dk) to Office365 tenant:

If you login to administration interface for MS Teams and choose Voice ->Direct Routing, there will be nothing:

Before you add Direct Routing SBC to MS Teams, you should add a user to the new domain “voipgw.ipnordic.dk”:

Now it is possible to add gateway with PowerShell. First connect with our Microsoft credentials:

PS> $userCredential = Get-Credential
PS> $sfbSession = New-CsOnlineSession -Credential $userCredential
PS> Import-PSSession $sfbSession

Then add the Direct Routing gateway:

PS> New-CsOnlinePSTNGateway -Fqdn voipgw.ipnordic.dk -SipSignallingPort 5061 
-MaxConcurrentSessions 10 -ForwardCallHistory $true -Enabled $true

So finally you should get the successful result:

Identity                          : voipgw.ipnordic.dk
Fqdn                              : voipgw.ipnordic.dk 
SipSignallingPort                 : 5061
FailoverTimeSeconds               : 10
ForwardCallHistory                : True
ForwardPai                        : False
SendSipOptions                    : True
MaxConcurrentSessions             : 10
Enabled                           : True
MediaBypass                       : False
GatewaySiteId                     :
GatewaySiteLbrEnabled             : False
FailoverResponseCodes             : 408,503,504
GenerateRingingWhileLocatingUser  : True
PidfLoSupported                   : False
MediaRelayRoutingLocationOverride :
ProxySbc                          :
BypassMode                        : None

Configuring OpenSIPS

Now it’s time to also configure OpenSIPS, to accept the calls from MS Teams and to route it further. First, the simple TLS configuration:

listen=tls:WAN_IP:5061 loadmodule "tls_mgm.so"
modparam("tls_mgm","verify_cert", "1")
modparam("tls_mgm","require_cert", "1")
modparam("tls_mgm","tls_method", "TLSv1_2")
modparam("tls_mgm","certificate", "/etc/tls/dom1/fullchain.pem")
modparam("tls_mgm","private_key", "/etc/tls/dom1/privkey.pem")
modparam("tls_mgm", "ca_list", "/etc/ssl/certs/ca-bundle.crt")

OpenSIPS will verify client TLS certificates, e.g. connections from Microsoft servers. The certificate authorities list depends on the operating system. The path in the example is for CentOS 7.

Microsoft requires that a client SBC sends SIP OPTIONS requests. Otherwise the SBC will be considered as “Inactive” and Microsoft will ignore any traffic coming from the SBC.

OPTIONS request for MS Teams must contain the Contact header of such a format:

Contact: <sip:SBC_FQDN:5061;transport=tls>

In RFC3261 we can find, that Contact header MAY be present in an OPTIONS request, so that Microsoft requirements don’t conflict with the RFC. To send periodic OPTIONS we can use an external script or any of modules with pinging/probing gateways features. For example, let’s take a standard configuration with Dynamic Routing module. Let’s add all three Microsoft entry points as dynamic routing gateways and specify in the database tls sockets for probing.

gwidaddressprobe_modestatesocket
ms1sip.pstnhub.microsoft.com20tls:<SBC_WAN_IP>:5061
ms2sip2.pstnhub.microsoft.com20tls:<SBC_WAN_IP>:5061
ms3sip3.pstnhub.microsoft.com20tls:<SBC_WAN_IP>:5061

Now we can see, that OpenSIPS tries to connect to MS Teams:

INFO:proto_tls:tls_connect: New TLS connection to 52.114.76.76:5061 established
INFO:proto_tls:tls_dump_cert_info: tls_connect: server TLS certificate subject: /CN=sip.pstnhub.microsoft.com,
issuer: /C=US/ST=Washington/L=Redmond/O=Microsoft Corporation/OU=Microsoft IT/CN=Microsoft IT TLS CA 4

But standard modules don’t add the Contact header to OPTIONS, because it is not required by RFC, so we need to add it from the configuration script:

local_route {
  $var(dst) = "pstnhub.microsoft.com";
  if (is_method("OPTIONS") && ($(ru{s.index, $var(dst)}) != NULL))
    append_hf("Contact: <sip:SBC_FQDN:5061;transport=tls>\r\n");
}

Now we get some responses from MS Teams, but with default settings in OpenSIPS there will be different errors during a TLS handshake:

ERROR:core:tcp_connect_blocking_timeout: connect timed out, 99219 us elapsed out of 100000 us
ERROR:proto_tls:tls_sync_connect: tcp_blocking_connect failed
ERROR:proto_tls:proto_tls_send: connect failed ERROR:tm:msg_send: send() to 52.114.148.0:5061 for proto tls/3 failed
ERROR:tm:t_uac: attempt to send to 'sip:sip.pstnhub.microsoft.com' failed

Logs show that the default timeout for connection is too small. We should increase it:

modparam("tls_mgm", "tls_handshake_timeout", 300)

However even after that the same errors are still left in logs. This is because TLS uses tcp for connection, so tcp connection timeout should be increased too, this is a global parameter:

tcp_connect_timeout=300

Now we send correct OPTIONS request to MS Teams. We should process OPTIONS from them. Check IP-addresses of source with the permissions module table:

# Checks from MS Teams
if(is_method("OPTIONS") && is_domain_local("$rd") && check_source_address("2")) {
  xlog("L_INFO", "[MS TEAMS] OPTIONS In");
  send_reply("200", "OK");
  exit;
}

Packets with all certificates are long, so the maximum number of fragments, which can contain SIP message over TLS should be increased

modparam("proto_tls", "tls_max_msg_chunks", 8)

Finally, we can see on the MS Teams admin portal, that the new SBC has the “TLS connectivity status” and the “SIP options status” Active:

Making calls

So, we can call from MS Teams to outside. Just remember to use SRTP for media on your side.

Then we can just route calls with dynamic routing to MS Teams. And can try to call to users of MS Teams, but Microsoft doesn’t allow:

SIP/2.0 403 Forbidden
FROM: "ipnordic"<sip:+4589102030@10.20.0.133>;tag=rcDtpcp16r6Bg
TO: <sip:4583008300@10.20.0.132>
CSEQ: 6526398 INVITE
CALL-ID: fc6c053a-1838-1238-b3ae-1eea2439faf6
VIA: SIP/2.0/UDP 10.20.0.133:5080;received=10.20.0.133;branch=z9hG4bKmj7Zmt2gjtaBm;rport=5080
REASON: Q.850;cause=21;text="e7646e44-e4ef-473e-b0b5-cc8efb416634;Provided Trunk FQDN '185.46.45.202' is not allowed. Connection allows following fqdns: voipgw.ipnordic.dk, voipgw.ipnordic.dk."
CONTENT-LENGTH: 0
ALLOW: INVITE
ALLOW: ACK
ALLOW: OPTIONS
ALLOW: CANCEL
ALLOW: BYE
ALLOW: NOTIFY
SERVER: Microsoft.PSTNHub.SIPProxy v.2019.4.24.4 i.EUNO.3

This is actually the second and the last requirement. It doesn’t matter, what domain names in the “To” and “From” headers are, INVITE must contain Route header with SBC_FQDN, not just IP address. No problem for OpenSIPS:

record_route_preset("SBC_FQDN:5061;transport=tls", "LAN_IP:5060");
add_rr_param(";r2=on");

And that’s it, calls can successfully come to the MS Teams client on the desktop:

UPDATE: Starting from 01.07.2020 Microsoft requires Route headers with SBC_FQDN in SIP replies too. Instead of simple record_route() for SIP request from MS servers OpenSIPS should add FQDN, but in different order:

record_route_preset("LAN_IP:5060", "SBC_FQDN:5061;transport=tls");
add_rr_param(";r2=on");

And an administrator of MS Teams can see stats for SBC:

OpenSIPS is configured as Microsoft Teams Direct Routing SBC. Now there are a lot of possibilities to improve this setup. SBC should be reliable, just put another OpenSIPS and make a cluster.

And OpenSIPS has a feature which doesn’t exist in any commercial SBC for Teams. It can support multiple SIP over TLS connection for MS Teams with different certificates.

So, using OpenSIPS as SBC for MS Teams has unlimited possibilities for further integration.

31 thoughts on “OpenSIPS as MS Teams SBC

  1. Thank you so much for writing such a straight to the point article.
    Just a quick question, you might be able to help me. I have 3 different domains like mysip1.mytestdomain.com mysip2.mytestdomain.com and mysip3.mytestdomain.com

    I am using attr in the dispatcher to send these FQDN in the contact header. so OPTION going to sip:sip.pstnhub.microsoft.com:5061;transport:tls have contact header so that is all good. The socket is always tls:myip:5061
    Now the problem is with different domains certificate. is there any way i can use wildcard domain like *.mytestdomain.com and use that in the certificate? This way i do not have to create 3 letsencrypt certificate 😉

    So i am after a parameter which will let me use wildcard domain.

    As i have not added mysipx.xx domain i always get an error ERROR:proto_tls:proto_tls_conn_init: no TLS client domain found

    Like

    1. Hi, you can use wildcard domain certificate without problems. You just need to create client domain, containing this wildcard certificate. OpenSIPS error exactly saying, that you are missing client tls domain in your config.

      Like

    1. No, you do not need to buy anything – simply install OpenSIPS and adjust its config according to the tutorial and MSTeams integration will work just fine.

      Like

  2. After i added all three Microsoft sip gateways at Dynamic Routing i receive the error when trying to reload on server via CP:
    Sending to json:127.0.0.1:8888/json : Error code 500 (Command not found)

    In opensips.log the message is:
    Jun 10 17:17:54 opensips /sbin/opensips[1264]: ERROR:mi_json:mi_json_answer_to_connection: unable to find mi command [dr_reload]

    If i try to reload it manually, i got this message:
    root@opensips:~# opensipsctl dr reload
    500 command ‘dr_reload’ not available

    Any idea what i’m doing wrong?

    Like

  3. Hello,

    can you please tell me why do you instruct to add voipgw.ipnordic.dk into domains? MS says in their documentation to add a new domain, the different one than the default *.onmicrosoft.com. They clearly explain in example: Using *.onmicrosoft.com domain names is not supported for the SBC FQDN name. For example, if you have two domain names, contoso.com and contoso.onmicrosoft.com, you can use sbc.contoso.con for the SBC name. I don’t understand why you add FQDN of SBC to the list of registered domain. If MS directions are followed then your SBC should be named sbc.voipgw.ipnordic.dk because voipgw.ipnordic.dk is your domain suffix.

    I am asking this in relation to the issue I am facing. I am not able to get SIP Options from Warning status to the Active status.

    Like

      1. Because it is illogical as you wrote it or we two speak about different things. If you add voipgw.ipnordic.dk into O365 domains, that SBC cannot be named the same. It would have to be .voipgw.ipnordic.dk.

        If voipgw.ipnordic.dk is used at domains, it is a domain.
        If voipgw.ipnordic.dk is used at New-CsOnlinePSTNGateway then it represents SBC with hostname voipgw and domain suffix ipnordic.dk.

        …at least in my view….

        Like

  4. Hello

    Thanks a lot for sharing!

    I follow the instructon. But got some issues.

    TLS part is configured correctly. I also got OPTIONS pings working. That is very good.

    But… There is issues with outbound calls from MS teams.

    MS side send INVITE, we responds with 180 and 200 OK, but looks like MS ignores us. I know that I probably should use record_route_preset function here to modify Record-Route headers to satisfy MS wishes. But nothing helps. I also tried to modify contact header in 200 OK like it was done for OPTIONS – no luck.
    Can you please to share working example of opensips conf files for MS team ?
    Or at least sucessful pcap with them.
    I can be wrong but looks like MS doesn’t respect RFC at all.

    Like

    1. Hi, you don’t need to use record_route_preset, just record_route() on incoming call from MS Teams. And you should not modify Contact. You can share your SIP-traces and configuration on OpenSIPS users mailing list, if you still have questions.

      Like

  5. Hi Alexey,
    Thanks for the greate article. I got everything setup as per this article.
    But SBC status on MS Direct Routing console still shows as inactive for me.
    I can see sending sip OPTIONS, but I’m not seeing any reply from microsoft side. anyidea
    what could be the issue ? I’m not seeing OPTIONS coming from microsoft side as well.
    No firewall is in place. my test sbc is hosted in aws.

    Like

    1. Hi Pasan. Please check, that you have the same FQDN_SBC in 1) MS Teams Direct Routing gateway 2) OpenSIPS SSL certificate CN 3) your OPTIONS Contact header. And if they are the same, please post your OPTIONS and logs to OpenSIPS Users Mail List.

      Liked by 1 person

      1. yup, as you indicate, my domain setup for SBC FQDN was incorrect. Once its fixed ms start to reply to SIP OPTIONS 🙂

        Like

  6. Hi Alexei,
    thanks for article. It really helped me.

    Have a question on tls config:
    modparam(“tls_mgm”,”certificate”, “/etc/tls/dom1/fullchain.pem”)
    modparam(“tls_mgm”,”private_key”, “/etc/tls/dom1/privkey.pem”)
    modparam(“tls_mgm”, “ca_list”, “/etc/ssl/certs/ca-bundle.crt”)
    Where did you get ca-bundle.crt from?

    I generated certificates with letsencrypt and cant find this file.

    I am new to this tls configs.

    Thanks.

    Vitalie Bugaian

    Like

    1. Hi. Answer actually in the article: “The certificate authorities list depends on the operating system. The path in the example is for CentOS 7” Package ca-certificates. For another operating systems the package and the path can be different.

      Like

  7. Hi all
    is there a way to get help from somewhere with the setup of a config? We do have a lot of little issues and cannot find the proper way to do it.
    Thanks for your help

    Like

  8. Thanks for this great article. I have one question. We have a shortel phonesystem. I am hoping to get a few sip trunks and connect to opensips as well as MS Teams. I also need the opensips server to connect to Shortel proprietary system. Is this possible?

    Like

    1. Sure, it should be possible, as long as the Shortel system is compliant with the SIP (RFC 3261). You just need to figure out what are the system’s requirements, and have OpenSIPS configured to handle them.

      Like

Leave a comment