{"id":969,"date":"2020-05-08T15:50:39","date_gmt":"2020-05-08T08:50:39","guid":{"rendered":"https:\/\/www.otakudang.org\/?p=969"},"modified":"2021-03-22T03:37:35","modified_gmt":"2021-03-21T20:37:35","slug":"microsoft-teams-direct-routing-with-issabel-asterisk","status":"publish","type":"post","link":"https:\/\/www.otakudang.org\/?p=969","title":{"rendered":"Microsoft Teams Direct Routing with Issabel (Asterisk)"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2021\/03\/image-16.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2021\/03\/image-16.png\" alt=\"\" class=\"wp-image-1079\" width=\"336\" height=\"375\" srcset=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2021\/03\/image-16.png 736w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2021\/03\/image-16-268x300.png 268w\" sizes=\"auto, (max-width: 336px) 100vw, 336px\" \/><\/a><\/figure><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Why?<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Inspired by a post &#8220;<a href=\"https:\/\/www.kamailio.org\/w\/2019\/10\/using-kamailio-as-sbc-for-microsoft-teams\/\">Using Kamailio as SBC for Microsoft Teams<\/a>&#8221; written by <a href=\"https:\/\/www.linkedin.com\/in\/henning-westerholt\/\">Henning Westerholt<\/a>. <\/li><li>While preparing Ribbon Communication certification, I found out what it takes to connect to Microsoft Teams Phone System.<\/li><li>I play with <a href=\"https:\/\/www.issabel.org\/\">Issabel <\/a>(Asterisk) quite a lot.<\/li><li>Boredom during WFH is killing me.  <\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">FYI<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Should have Issabel server properly installed with ip public and . The server firewall should be hardened by only allowing Carrier and Microsoft cloud ip address blocks (52.112.0.0\/14). Even better if the only maintenance can only be accessed by VPN. Dont open your Issabel webGUI, SSH, SIP &amp; RTP ports to public internet whenever possible.<\/li><li>My Issbel (Asterisk) server is already connected to <a href=\"https:\/\/www.ofon.co.id\">Ofon<\/a> as the PSTN Carrier, and already has a DID assigned. <\/li><li>Requires to edit <em>chan_sip.c <\/em>to comply with Microsoft Teams Phone System that demands SIP <em>From<\/em> and <em>Contact<\/em> header host part to be FQDN. <em>From <\/em>header is easy, just add <em>fromdomain<\/em> at the Asterisk trunk config and you&#8217;re good. The <em>Contact <\/em>header is the tricky one, based on this screenshot clue (stolen from thread <a href=\"https:\/\/community.asterisk.org\/t\/fqdn-in-the-contact-header\/77625\">https:\/\/community.asterisk.org\/t\/fqdn-in-the-contact-header\/77625<\/a>):<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"956\" height=\"127\" src=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image.png\" alt=\"\" class=\"wp-image-970\" srcset=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image.png 956w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-300x40.png 300w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-768x102.png 768w\" sizes=\"auto, (max-width: 956px) 100vw, 956px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li>By half-assed editing the <em>chan_sip.c <\/em>, I expect there will be repercussion somewhere else in the system (plus I am no good at C,  should find a better way to insert the change with more elegant solution), so dont share the PBX with something else for production, and use this as POC only. <\/li><li>Dont ever think to commercialize this without Microsoft approval, nor use this for officials. You may not be able to open tickets if you encounter problems with this installation although you are a legit Office 365 tenant with Phone System license. The certified SBC list can be found <a href=\"https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-border-controllers\">here<\/a>. <\/li><li>Should have access to DNS server to add TXT type record for domain authentication. <\/li><li>Should have global admin account to make changes in O365 portal. <\/li><li>In this example, I have two E1 O365 + Phone System licenses. One to be assigned to my account and one to  be assigned to SIP trunk domain dummy user. <\/li><li>You cant do multi tenant with this installation. Asterisk itself is a single realm (CMIIW). <\/li><li>Still cant find how to modify <em>Contact<\/em> <em> <\/em>header in OPTIONS, hence you&#8217;ll find <em>tlsdontverifyserver=yes<\/em> in Issabel general config.<\/li><li>Will periodically update this post with something new whenever I find improvement. So forgive me if you find something different when you read back the post later. <\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Microsoft Teams Phone System Side Config<\/h2>\n\n\n\n<p>In this stage you will need to add an SSL&#8217;ed domain to Office 365 portal. Microsoft-recommended CA list can be found <a href=\"https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-plan#public-trusted-certificate-for-the-sbc\">here<\/a>. I myself use GeoTrust. <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Microsoft has a very detailed documentation that can be found at <a href=\"https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-plan\">https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-plan<\/a> . I wont rewrite the details here. <\/li><li>Using global admin to add domain (mine is <strong>ast.ofon.biz<\/strong>), to O365 admin portal. <\/li><li>Add a dummy user for that domain and assign O365 + Phone System license for that dummy user. For example, my dummy user for the newly added domain is <strong>sip@ast.ofon.biz<\/strong>. If successfully added, I will find the user in <strong>Active users <\/strong>table like this:<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"62\" src=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-1-1024x62.png\" alt=\"\" class=\"wp-image-973\" srcset=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-1-1024x62.png 1024w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-1-300x18.png 300w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-1-768x47.png 768w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-1.png 1149w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li>that is how Microsoft Teams will recognize the SIP trunk to our Issabel (Asterisk) server and assign license to the trunk.<\/li><li>Login<em> <\/em>using <em>powershell <\/em>to your account using global admin user. Again, the powershell preparation wont be repeated here since the detailed documentation can be found at <a href=\"https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-configure\">https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-configure<\/a>. Next steps will require us to import <a href=\"https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=39366\">Sfbonline<\/a> module to powershell.<\/li><li>Start the session (you will be asked for password on a popped up windows) :<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">$sfb = New-CsOnlineSession -Username \"admin@ofonio.onmicrosoft.com\"\nImport-PSSession $sfb -AllowClobber<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>Add the Issabel (Asterisk server) as PSTN Gateway:<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">New-CsOnlinePSTNGateway -Fqdn ast.ofon.biz -SipSignalingPort 5061 -ForwardCallHistory $true -Enabled $true -ForwardPai $true -MaxConcurrentSessions 5<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>See if the server is properly added with <em>Get-CsOnlinePstnGateway<\/em> :<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"> Get-CsOnlinePSTNGateway\n\n\nIdentity                            : ast.ofon.biz\nInboundTeamsNumberTranslationRules  : {}\nInboundPstnNumberTranslationRules   : {}\nOutboundTeamsNumberTranslationRules : {}\nOutboundPstnNumberTranslationRules  : {}\nFqdn                                : ast.ofon.biz\nSipSignalingPort                    : 5061\nFailoverTimeSeconds                 : 10\nForwardCallHistory                  : True\nForwardPai                          : True\nSendSipOptions                      : True\nMaxConcurrentSessions               : 5\nEnabled                             : True\nMediaBypass                         : False\nGatewaySiteId                       :\nGatewaySiteLbrEnabled               : False\nFailoverResponseCodes               : 408,503,504\nGenerateRingingWhileLocatingUser    : True\nPidfLoSupported                     : False\nMediaRelayRoutingLocationOverride   :\nProxySbc                            :\nBypassMode                          : None<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>Create a routing and routing policy that will utilize the Issabel (Asterisk) server:<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"powershell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Set-CsOnlinePstnUsage -Identity Global -Usage @{Add=\"Default\"}\n\nNew-CsOnlineVoiceRoute -Identity \"CatchAll\" -NumberPattern \".*\" -OnlinePstnGatewayList ast.ofon.biz -Priority 1 -OnlinePstnUsages \"Default\"\n\nNew-CsOnlineVoiceRoutingPolicy -Identity \"DefaultVoicePolicy\" -OnlinePstnUsages \"Default\"<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>Assign DID &amp; VoiceRoutingPolicy to my account. <\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Issabel (Asterisk) Side Config<\/h2>\n\n\n\n<p>We will have two SIP connection configs for Microsoft Teams Phone System and two SIP connection configs for Carrier. Each connection will have different contexts. One SIP connection for Microsoft Teams will be <em>from-internal<\/em>, so call from Microsoft Teams will be treated as call from <em>extension<\/em>. And the other SIP connection will be treated as outbound trunk with <em>from-trunk <\/em>context. Same deal with the two SIP connections toward Carrier. <\/p>\n\n\n\n<p>Microsoft provides 3 hosts to connect a SIP trunk with: <\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>sip.pstnhub.microsoft.com<\/li><li>sip2.pstnhub.microsoft.com<\/li><li>sip3.pstnhub.microsoft.com <\/li><\/ul>\n\n\n\n<p>This example will only test the first one (sip.pstnhub.microsoft.com).<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Adding Trunk to Microsoft Teams from <strong>PBX -&gt; PBX Configuration -&gt; Trunks. <\/strong>Add SIP Trunk and fill these parameters :<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">Trunk Name: MSTeams-Outbound\nPEER Details:\ndisallow=all\nhost=sip.pstnhub.microsoft.com\ntype=peer\ntransport=tls\nport=5061\nallow=all&amp;amp;ulaw\nqualify=yes\ndtmfmode=rfc2833\ncontext=from-trunk\ninsecure=port,invite\nnat=force_rport,comedia\nfromdomain=ast.ofon.biz\nencryption=yes<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>And as &#8220;extension&#8221; add the following configs to <strong>sip_custom.conf <\/strong>using <strong>PBX -&gt; Tools -&gt; Asterisk File Editor <\/strong>:<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">[MSTeams-Inbound]\ndisallow=all\nhost=sip.pstnhub.microsoft.com\ntype=friend\ntransport=tls\nport=5061\nallow=all\nallow=ulaw\nqualify=yes\ndtmfmode=rfc2833\ncontext=from-internal\ninsecure=port,invite\nnat=force_rport,comedia\nfromdomain=ast.ofon.biz<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>To refer to certifcate files, go to <strong>PBX -&gt; PBX Configuration -&gt; Unembedded IssabelPBX. <\/strong>At the following page, go to <strong>Settings -&gt; Asterisk SIP Settings<\/strong> and then <strong>Add field <\/strong>at the <strong>Other SIP Settings <\/strong> with these:<\/li><\/ul>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">realm=ast.ofon.biz\ntlsenable=yes\ntlsbindaddr=0.0.0.0:5061\ntlsprivatekey=\/etc\/asterisk\/keys\/star_ofon_biz.key\ntlscertfile=\/etc\/asterisk\/keys\/star_ofon_biz.pem\ntlscafile=\/etc\/asterisk\/keys\/star_ofon_biz.crt\ntlscipher=ALL\ntlsclientmethod=tlsv1\ntlsdontverifyserver=yes<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>Save and reload the config.<\/li><li>Add the Outbound Routes to Microsoft Teams and Carrier (Microsoft Teams outbound should be aboive the Carrier). Since my carrier mostly sends with prefix 0,  I have to convert it to E.164. Please modify these according to your apporpriate settings:<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"688\" height=\"479\" src=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-2.png\" alt=\"\" class=\"wp-image-974\" srcset=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-2.png 688w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-2-300x209.png 300w\" sizes=\"auto, (max-width: 688px) 100vw, 688px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"666\" height=\"473\" src=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-3.png\" alt=\"\" class=\"wp-image-975\" srcset=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-3.png 666w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-3-300x213.png 300w\" sizes=\"auto, (max-width: 666px) 100vw, 666px\" \/><\/figure>\n\n\n\n<p>At this point, you should be able to call outbound from Microsoft Teams account but not the other way (inbound). As mentioned before, Microsoft Teams Phone System require us to send <em>From <\/em>and <em>Contact <\/em>header host as FQDN. The trunk settings in Asterisk wont change <em>Contact<\/em> header host to FQDN hence we&#8217;ll receive this message:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">INVITE sip:+622430000062@sip.pstnhub.microsoft.com:5061 SIP\/2.0\nVia: SIP\/2.0\/TLS xxx.xxx.xxx.xxx:5061;branch=z9hG4bK4e781f8a;rport\nMax-Forwards: 70\nFrom: \"02139700001\" &amp;lt;sip:02139700001@ast.ofon.biz&amp;gt;;tag=as36acd9d9\nTo: &amp;lt;sip:+622430000062@sip.pstnhub.microsoft.com:5061&amp;gt;\nContact: &amp;lt;sip:02139700001@xxx.xxx.xxx.xxx:5061;transport=tls&amp;gt;\nCall-ID: 2239ff467456d8f03c4348826168d7a6@ast.ofon.biz\nCSeq: 102 INVITE\nUser-Agent: Asterisk 16.7.0\nDate: Fri, 08 May 2020 04:45:38 GMT\nAllow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE\nSupported: replaces, timer\nContent-Type: application\/sdp\nContent-Length: 1324\n\n...\n...\n...\nSIP\/2.0 403 Forbidden\nFROM: \"02139700001\"&amp;lt;sip:02139700001@ast.ofon.biz&amp;gt;;tag=as36acd9d9\nTO: &amp;lt;sip:+622430000062@sip.pstnhub.microsoft.com:5061&amp;gt;\nCSEQ: 102 INVITE\nCALL-ID: 2239ff467456d8f03c4348826168d7a6@ast.ofon.biz\nVIA: SIP\/2.0\/TLS xxx.xxx.xxx.xxx:5061;branch=z9hG4bK4e781f8a;rport\nREASON: Q.850;cause=63;text=\"735a16a2-5f83-4cb0-bdec-9cb64edff551;Provided Trunk FQDN 'xxx.xxx.xxx.xxx' is not allowed. Connection allows following fqdns: *.ofon.biz, ofon.biz, *.ofon.biz.\"\nCONTENT-LENGTH: 0\nALLOW: INVITE,ACK,OPTIONS,CANCEL,BYE,NOTIFY\nSERVER: Microsoft.PSTNHub.SIPProxy v.2020.5.6.2 i.ASEA.2<\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">chan_sip.c<\/h2>\n\n\n\n<p>There is no Asterisk source in Issabel distro so we have to get it ourself. From  Issabel linux console, git clone the Asterisk github and checkout for 16.7.0 (since this is my Issabel&#8217;s Asterisk version).:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">cd \/usr\/src\ngit clone https:\/\/github.com\/asterisk\/asterisk.git\ncd asterisk\ngit checkout 16.7.0<\/pre>\n\n\n\n<p>Edit file <strong>\/usr\/src\/asterisk\/channel\/chan_sip.c<\/strong>. Look at <em>build_contact() <\/em>we will find these lines:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">static void build_contact(struct sip_pvt *p, struct sip_request *req, int incoming)\n{\n        char tmp[SIPBUFSIZE];\n        char *user = ast_uri_encode(p-&amp;gt;exten, tmp, sizeof(tmp), ast_uri_sip_user);\n        int use_sips;\n        char *transport = ast_strdupa(sip_get_transport(p-&amp;gt;socket.type));\n\n        if (incoming) {\n                use_sips = uas_sips_contact(req);\n        } else {\n                use_sips = uac_sips_contact(req);\n        }\n\n        if (p-&amp;gt;socket.type == AST_TRANSPORT_UDP) {\n                ast_string_field_build(p, our_contact, \"&amp;lt;%s:%s%s%s&amp;gt;\", use_sips ? \"sips\" : \"sip\",\n                        user, ast_strlen_zero(user) ? \"\" : \"@\",\n                        ast_sockaddr_stringify_remote(&amp;amp;p-&amp;gt;ourip));\n        } else {\n                ast_string_field_build(p, our_contact, \"&amp;lt;%s:%s%s%s;transport=%s&amp;gt;\",\n                        use_sips ? \"sips\" : \"sip\", user, ast_strlen_zero(user) ? \"\" : \"@\",\n                        ast_sockaddr_stringify_remote(&amp;amp;p-&amp;gt;ourip), ast_str_to_lower(transport));\n        }\n}<\/pre>\n\n\n\n<p>The last conditional lines are where the Contact header gets value from. Since we only need to modify for TCP transport, edit the line:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"> else {\n                ast_string_field_build(p, our_contact, \"&amp;lt;%s:%s%s%s;transport=%s&amp;gt;\",\n                        use_sips ? \"sips\" : \"sip\", user, ast_strlen_zero(user) ? \"\" : \"@\",\n                        ast_sockaddr_stringify_remote(&amp;amp;p-&amp;gt;ourip), ast_str_to_lower(transport));\n        }<\/pre>\n\n\n\n<p>to become :<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"> else {\n                ast_string_field_build(p, our_contact, \"&amp;lt;%s:%s%s%s;transport=%s&amp;gt;\",\n                        use_sips ? \"sips\" : \"sip\", user, ast_strlen_zero(user) ? \"\" : \"@\",\n                        p-&amp;gt;fromdomain, ast_str_to_lower(transport));\n        }<\/pre>\n\n\n\n<p><em>p-&gt;fromdomain<\/em> will follow whatever <em>&#8220;fromdomain=<\/em>&#8221; value in the SIP trunk config. <\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"><em>Update:\nGot input from Igo Cunha that the call from MSteams to PSTN will be disconnected after 6 sec. I can confirm I got random disconnect call at about 6 sec from the same direction. Try replace:<\/em>\n<em> <\/em>\n<em>ast_sockaddr_stringify_remote(&amp;p-&gt;ourip) <\/em>\n\n<em>with your Asterisk's FQDN string (e.g \"ast.ofon.biz\" in my case) instead of p-&gt;fromdomain.\n\nThanks Igo!<\/em><\/pre>\n\n\n\n<p>I understand this is not elegant way, but that should do it. Compile the source and we will have brand new <em>chan_sip.so<\/em>. Backup the original one and replace it after:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">copy \/usr\/lib64\/asterisk\/modules\/chan_sip.so \/usr\/local\/src\/chan_sip.so.original\ncopy \/usr\/src\/asterisk\/channels\/chan_sip.so \/usr\/lib64\/asterisk\/modules\/chan_sip.so<\/pre>\n\n\n\n<p>then reload the module from Asterisk console:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">asterisk -vr\n\nast*CLI&amp;gt; module reload chan_sip.so\nModule 'chan_sip.so' reloaded successfully.\n Reloading SIP\n<\/pre>\n\n\n\n<p>Now test call to inbound, we should have correct SIP Contact header requirement as follows:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">INVITE sip:+622430000062@sip.pstnhub.microsoft.com:5061 SIP\/2.0\nVia: SIP\/2.0\/TLS 103.135.74.15:5061;branch=z9hG4bK394b6483;rport\nMax-Forwards: 70\nFrom: \"02139700001\" &amp;lt;sip:02139700001@ast.ofon.biz&amp;gt;;tag=as20858906\nTo: &amp;lt;sip:+622430000062@sip.pstnhub.microsoft.com:5061&amp;gt;\nContact: &amp;lt;sip:02139700001@ast.ofon.biz;transport=tls&amp;gt;\nCall-ID: 1a5d05f10eadb0036683f88a6177f80f@ast.ofon.biz\nCSeq: 102 INVITE\nUser-Agent: Asterisk 16.7.0\nDate: Fri, 08 May 2020 04:54:36 GMT\nAllow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE\nSupported: replaces, timer\nContent-Type: application\/sdp\nContent-Length: 1324<\/pre>\n\n\n\n<p>and the call went through:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"792\" src=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-4-1024x792.png\" alt=\"\" class=\"wp-image-976\" srcset=\"https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-4-1024x792.png 1024w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-4-300x232.png 300w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-4-768x594.png 768w, https:\/\/www.otakudang.org\/wp-content\/uploads\/2020\/05\/image-4.png 1178w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Remarks<\/h2>\n\n\n\n<p>Although it is possible to connect Direct Routing with Asterisk, still easier using Kamailio (and OpenSIPS) since they&#8217;re built solely for SIP packet engineering. Until some of them become certified with Microsoft, I guess I will be using the already ceritfied ones, like Sonus or AudioCodes, or just connect to a hosted Direct Routing Provider in Indonesia, like <a href=\"https:\/\/ofon.co.id\/enterprise\/clouddirectrouting\">Ofon<\/a>. Alternatively, there are Kamailo based products start providing hosted DR, like <a href=\"https:\/\/gilawa.com\/en\/products\">Gilawa<\/a> and <a href=\"https:\/\/dsiprouter.org\/msteams\">dSIPRouter<\/a>. Check them out. <\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Complete Configs<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.otakudang.org\/?p=990\">https:\/\/www.otakudang.org\/?p=990<\/a><\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Links:<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/www.kamailio.org\/w\/2019\/10\/using-kamailio-as-sbc-for-microsoft-teams\/\">https:\/\/www.kamailio.org\/w\/2019\/10\/using-kamailio-as-sbc-for-microsoft-teams\/<\/a><\/li><li><a href=\"https:\/\/www.issabel.org\/\">https:\/\/www.issabel.org\/<\/a><\/li><li>https:\/\/ofon.co.id\/enterprise\/clouddirectrouting<\/li><li><a href=\"https:\/\/gilawa.com\/en\/products\">https:\/\/gilawa.com\/en\/products<\/a><\/li><li><a href=\"https:\/\/dsiprouter.org\/msteams\">https:\/\/dsiprouter.org\/msteams<\/a><\/li><li><a href=\"https:\/\/community.asterisk.org\/t\/fqdn-in-the-contact-header\/77625\">https:\/\/community.asterisk.org\/t\/fqdn-in-the-contact-header\/77625<\/a><\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-plan\">https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-plan<\/a><\/li><li><a href=\"https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-configure\">https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/direct-routing-configure<\/a><\/li><li><a href=\"https:\/\/support.sonus.net\/display\/IOT\/Ribbon+Configuration+With+Microsoft+Teams+for+Carrier+Trunk+and+CAC+-+ERE+and+PSX?desktop=true&amp;macroName=style\">https:\/\/support.sonus.net\/display\/IOT\/Ribbon+Configuration+With+Microsoft+Teams+for+Carrier+Trunk+and+CAC+-+ERE+and+PSX?desktop=true&amp;macroName=style<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Why? Inspired by a post &#8220;Using Kamailio as SBC for Microsoft Teams&#8221; written by Henning Westerholt. While preparing Ribbon Communication certification, I found out what it takes to connect to Microsoft Teams Phone System. I play with Issabel (Asterisk) quite a lot. Boredom during WFH is killing me. FYI Should have Issabel server properly installed &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.otakudang.org\/?p=969\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Microsoft Teams Direct Routing with Issabel (Asterisk)&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,16],"tags":[],"class_list":["post-969","post","type-post","status-publish","format-standard","hentry","category-asterisk","category-msteams","entry"],"_links":{"self":[{"href":"https:\/\/www.otakudang.org\/index.php?rest_route=\/wp\/v2\/posts\/969","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.otakudang.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.otakudang.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.otakudang.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.otakudang.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=969"}],"version-history":[{"count":18,"href":"https:\/\/www.otakudang.org\/index.php?rest_route=\/wp\/v2\/posts\/969\/revisions"}],"predecessor-version":[{"id":1082,"href":"https:\/\/www.otakudang.org\/index.php?rest_route=\/wp\/v2\/posts\/969\/revisions\/1082"}],"wp:attachment":[{"href":"https:\/\/www.otakudang.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=969"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.otakudang.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=969"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.otakudang.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=969"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}