TLS Transport - The certificate is untrusted with Microsoft Teams

Dear Community,

I’ve been struggling trying to re-connect an Asterisk Server with Microsoft Teams,
Re-connect since i already made a two-way connection with SIP OPTIONS and Calls,

Currently, i have the following settings:
Note: ${value} is not shown due privacy purposes.

Endpoint:

  ParameterName                      : ParameterValue
 ===================================================================================================
 100rel                             : yes
 accept_multiple_sdp_answers        : true
 accountcode                        :
 acl                                :
 aggregate_mwi                      : true
 allow                              : (g729|alaw|ulaw)
 allow_overlap                      : true
 allow_subscribe                    : false
 allow_transfer                     : true
 allow_unauthenticated_options      : false
 aors                               : AOR_MSTEAMS1, AOR_MSTEAMS2, AOR_MSTEAMS3
 asymmetric_rtp_codec               : false
 auth                               :
 bind_rtp_to_media_address          : false
 bundle                             : false
 call_group                         :
 callerid                           : <unknown>
 callerid_privacy                   : allowed_passed_screen
 callerid_tag                       :
 codec_prefs_incoming_answer        : prefer:pending, operation:intersect, keep:all, transcode:allow
 codec_prefs_incoming_offer         : prefer:pending, operation:intersect, keep:all, transcode:allow
 codec_prefs_outgoing_answer        : prefer:pending, operation:intersect, keep:all, transcode:allow
 codec_prefs_outgoing_offer         : prefer:pending, operation:union, keep:all, transcode:allow
 connected_line_method              : invite
 contact_acl                        :
 context                            : IN_MSTEAMS
 cos_audio                          : 0
 cos_video                          : 0
 device_state_busy_at               : 0
 direct_media                       : false
 direct_media_glare_mitigation      : none
 direct_media_method                : invite
 disable_direct_media_on_nat        : false
 dtls_auto_generate_cert            : No
 dtls_ca_file                       :
 dtls_ca_path                       :
 dtls_cert_file                     :
 dtls_cipher                        :
 dtls_fingerprint                   : SHA-256
 dtls_private_key                   :
 dtls_rekey                         : 0
 dtls_setup                         : active
 dtls_verify                        : No
 dtmf_mode                          : rfc4733
 fax_detect                         : true
 fax_detect_timeout                 : 0
 follow_early_media_fork            : true
 force_avp                          : false
 force_rport                        : true
 from_domain                        : ${domain}
 from_user                          :
 g726_non_standard                  : false
 geoloc_incoming_call_profile       :
 geoloc_outgoing_call_profile       :
 ice_support                        : false
 identify_by                        : ip,username,header,auth_username
 ignore_183_without_sdp             : true
 inband_progress                    : true
 incoming_call_offer_pref           : local
 incoming_mwi_mailbox               :
 language                           : es
 mailboxes                          :
 max_audio_streams                  : 1
 max_video_streams                  : 1
 media_address                      :
 media_encryption                   : sdes
 media_encryption_optimistic        : false
 media_use_received_transport       : false
 message_context                    :
 moh_passthrough                    : true
 moh_suggest                        : default
 mwi_from_user                      :
 mwi_subscribe_replaces_unsolicited : no
 named_call_group                   :
 named_pickup_group                 :
 notify_early_inuse_ringing         : false
 one_touch_recording                : false
 outbound_auth                      :
 outbound_proxy                     :
 outgoing_call_offer_pref           : remote_merge
 pickup_group                       :
 preferred_codec_only               : false
 record_off_feature                 :
 record_on_feature                  :
 refer_blind_progress               : false
 rewrite_contact                    : false
 rpid_immediate                     : false
 rtcp_mux                           : false
 rtp_engine                         : asterisk
 rtp_ipv6                           : false
 rtp_keepalive                      : 0
 rtp_symmetric                      : false
 rtp_timeout                        : 0
 rtp_timeout_hold                   : 0
 sdp_owner                          : ${owner}
 sdp_session                        : ${session}
 send_connected_line                : yes
 send_diversion                     : true
 send_history_info                  : false
 send_pai                           : false
 send_rpid                          : false
 set_var                            :
 srtp_tag_32                        : false
 stir_shaken                        : off
 stir_shaken_profile                :
 sub_min_expiry                     : 0
 subscribe_context                  :
 suppress_q850_reason_headers       : false
 t38_bind_udptl_to_media_address    : false
 t38_udptl                          : true
 t38_udptl_ec                       : none
 t38_udptl_ipv6                     : false
 t38_udptl_maxdatagram              : 0
 t38_udptl_nat                      : false
 timers                             : yes
 timers_min_se                      : 90
 timers_sess_expires                : 1800
 tone_zone                          : cl
 tos_audio                          : 0
 tos_video                          : 0
 transport                          : transport_tls
 trust_connected_line               : yes
 trust_id_inbound                   : true
 trust_id_outbound                  : true
 use_avpf                           : false
 use_ptime                          : false
 user_eq_phone                      : false
 voicemail_extension                :
 webrtc                             : no

Transport:

ParameterName              : ParameterValue
 =======================================================================================================================================
 allow_reload               : false
 allow_wildcard_certs       : Yes
 async_operations           : 1
 bind                       : 0.0.0.0:5061
 ca_list_file               : /etc/asterisk/certs/CA.pem
 ca_list_path               :
 cert_file                  : /etc/asterisk/certs/wildcard.crt
 cipher                     : ECDHE-RSA-AES256-GCM-SHA384, ECDHE-RSA-AES128-GCM-SHA256, ECDHE-RSA-AES256-SHA384, ECDHE-RSA-AES128-SHA256
 cos                        : 0
 domain                     :
 external_media_address     : ${domain}
 external_signaling_address : ${domain}
 external_signaling_port    : 5061
 local_net                  : net1/255.255.255.0
 local_net                  : net2/255.255.255.0
 local_net                  : net3/255.255.255.224
 local_net                  : net4/255.255.255.224
 method                     : tlsv1_2
 password                   :
 priv_key_file              : /etc/asterisk/certs/private.key
 protocol                   : tls
 require_client_cert        : No
 symmetric_transport        : false
 tos                        : 0
 verify_client              : No
 verify_server              : No
 websocket_write_timeout    : 100

SIP OPTIONS:

<--- Transmitting SIP request (497 bytes) to TLS:52.114.132.46:5061 --->
OPTIONS sip:sip.pstnhub.microsoft.com SIP/2.0
Via: SIP/2.0/TLS ${domain}:5061;rport;branch=z9hG4bKPj411abb45-1454-44e2-9ee2-9e2859e43395;alias
From: <sip:MSTEAMS@${domain};tag=06872202-7eef-44d1-a40a-27e4fb428e41
To: <sip:sip.pstnhub.microsoft.com>
Contact: <sip:MSTEAMS@${domain}:5061;transport=TLS>
Call-ID: 3f1e2668-7ff1-4bd7-98f7-0f9d04a9c73f
CSeq: 38224 OPTIONS
Max-Forwards: 10
User-Agent: ${user-agent}
Content-Length:  0

Im not sure if the following notification is related to this unreachability:

NOTICE[4674]: res_pjsip/pjsip_transport_events.c:179 verify_log_result: Transport ‘transport_tls’ to remote ‘sip.pstnhub.microsoft.com’ - The certificate is untrusted

My certificate provider is LeaderSSL that works with Sectigo,
wildcard.crt file contains only the “STAR” certificate that provides LeaderSSL
CA.pem contains all intermediate CA values of the wildcard service,

AAACertificateServices.crt
SectigoRSAOrganizationValidationSecureServerCA.crt
USERTrustRSAAAACA.crt

Also,
I have downloaded the CA that MS Teams is using and added it to Centos 9: DigiCert Global Root G2

/etc/pki/ca-trust/source/anchors/${DigiCertCA.pem}

then, I applied the CA changes to the O.S. with:

update-ca-trust

I’m aware that Asterisk is not “supported” by default as a valid SBC for MS Teams, so, i followed this guide and modified what values were out of date, everything was working fine until today with no changes made whatsoever, so i believe that MS Teams is updating something or banned my server directly, my logs shows unavailability at 12:00 UTC in multiple attempts (Available - Unavailable).

Any suggestions are greatly appreciated
Warm Regards

You don’t appear to have the signing certificate for Microsoft.

Dear David,

Do you mean that, i can mention multiple CAs there?

pjsip.conf

`[transport_tls]`
`ca_list_file = /etc/asterisk/certs/CA.pem`

Im not sure how to mention “external” CA’s in the configuration
I’ve tried separating them with comma, but i got a exception handler for the transport

ca_list_file = /etc/asterisk/certs/CA.pem, /etc/asterisk/certs/MSTeamsCA.pem

Warm Regards

Ive tried moving my CA’s to

/etc/asterisk/certs/CA/

With 400 asterisk:asterisk

And mentioning only:

ca_list_path = /etc/asterisk/certs/CA/

[transport_tls]

;ca_list_file = /etc/asterisk/certs/CA.pem
ca_list_path = /etc/asterisk/certs/CA/

But im getting the same message, and the trunks stay unavailable

I have an update,
After installing a Baltimore CA adviced by microsoft the Untrusted message disappeared, instead i receive:

res_pjsip/pjsip_transport_events.c:179 verify_log_result: Transport ‘transport_tls’ to remote ‘sip.pstnhub.microsoft.com’ - OK

Now im raising a case to MS Teams if they have “blocked” my server instance, or to understand what is out of MSTeams standard.

I believe you concatenate the PEM files physically for the file method, and you have to rename them based on a hash, see man 3 openssl-rehash, for the directory one

Dear @david551,
Hope you’re fine,

I have concatenated three CA certificates in the same file,

BEGIN CERTIFICATE
CA 1 (Asterisk Server Domain)
END CERTIFICATE
BEGIN CERTIFICATE
CA 2 (MS Teams - Baltimore)
END CERTIFICATE
BEGIN CERTIFICATE
CA 3 (MS Teams - Digicert)
END CERTIFICATE

MS Teams is replying “properly” as i have seen in the Asterisk CLI

res_pjsip/pjsip_transport_events.c:179 verify_log_result: Transport ‘transport_tls’ to remote ‘sip.pstnhub.microsoft.com’ - OK

But their replies, at network level, aren’t shown like the options packet captured at the start of this thread,
Im using
pjsip set logger on
and
pjsip set logger host sip.pstnhub.microsoft.com

The thing that i see is CLI Prompt when using pjsip logger is:

<— Transmitting SIP request (502 bytes) to TLS:52.114.132.46:5061 —>
OPTIONS sip:sip.pstnhub.microsoft.com:5061 SIP/2.0
Via: SIP/2.0/TLS ${DOMAIN}:5061;rport;branch=z9hG4bKPjf2181e3f-caed-465b-a852-2d8cedcafd44;alias
From: sip:MSTEAMS@{DOMAIN};tag=98d9cc6f-e726-4be1-a833-387583f0a024
To: sip:sip.pstnhub.microsoft.com
Contact: sip:MSTEAMS@${DOMAIN}:5061;transport=TLS>
Call-ID: 7851ceee-2a84-4ab7-9b73-5ed0cbdd0783
CSeq: 30600 OPTIONS
Max-Forwards: 10
User-Agent: ${User Agent}
Content-Length: 0

res_pjsip/pjsip_transport_events.c:179 verify_log_result: Transport ‘transport_tls’ to remote ‘sip.pstnhub.microsoft.com’ - OK

But, I should receive something like:

<— Receiving SIP request (502 bytes) from TLS:52.114.132.46:5061 —>

By the way,

MSTeams is able to send calls to Asterisk and there is audio in both directions.
But from Asterisk to MSTeams, the Endpoint shows as unavailable, i tried sending calls ignoring QUALIFY/OPTIONS,
Should i debug encription related issues?
Or is Asterisk CLI (pjsip logger) unable to capture encripted packets.

If further details are required please let me know.
Warm Regards

Also,
Is there a way to remove the user portion of SIP OPTIONS:
FROM and/or CONTACT headers?

Leaving only the “FQDN”:

i.e.:

From: sip:MSTEAMS@{DOMAIN};tag=98d9cc6f-e726-4be1-a833-387583f0a024
Contact: sip:MSTEAMS@${DOMAIN}:5061;transport=TLS>
From: sip:{DOMAIN};tag=98d9cc6f-e726-4be1-a833-387583f0a024
Contact: sip:${DOMAIN}:5061;transport=TLS>

Any advices are going to be appreciated
Warm Regards

Is it expected to qualify an endpoint as Unavailable after receiving this CLI message?

res_pjsip/pjsip_transport_events.c:179 verify_log_result: Transport ‘transport_tls’ to remote ‘sip.pstnhub.microsoft.com’ - OK

Its like remote side ended connection or i have an internal asterisk problem.

Any ideas or advices will be greatly appreciated
Warm Regards

I would say that message indicates that there was no problem at the point where it was issued.

I think the device state will be UNAVAILABLE until OPTIONS produces a response.

So,
CA’s is “valid” as per CLI reply via TLS,
But no 200 OK is being replied from remote side right?
Thats why Asterisk interprets this behavior as “Unavailable”

There is no requirement that the reply be 200 OK. Even method not implemented should be good enough.

@david551
Maybe i need some TLS Debugging,

I just saw a Teams article, that describes a step by step process of what happens when an SBC (Asterisk) starts a connection to a SIP Proxy (Teams),

The SIP proxy checks the connection request.

  • If the request is not valid, the TLS connection is closed and the SIP proxy does not receive SIP options from the SBC.
  • If the request is valid, the TLS connection is established, and the SBC uses it to send SIP options to the SIP proxy.

Do you know when “TLS Negotiation” is sucessful?
Im seeing many “TLS” packets at network level with

Client Hello to Teams
Server Hello to Asterisk
Certificate, Key Exchange to Teams
Change Cypher Spec to Asterisk

Then 2 TCP Packets,

FIN, ACK Flag to Teams
RST, ACK to Asterisk

Maybe Teams doesn’t like SIP OPTIONS format and is resseting the TLS encription, if so, it could be the user portion of FROM and CONTACT headers,
I couldn’t find a way to remove them from pjsip.conf, 2 days ago i posted a example of what i tried to send in OPTIONS to Teams,
Maybe a source code modification can remove the user portion in OPTIONS method?

Any suggestions are greatly appreciated

To the best of my knowledge (which admittedly is around 2 years old on this
topic now) it is not possible to connect Asterisk directly to MS Teams without
using something like Kamailio in the middle to fiddle certain headers to
Microsoft’s liking.

Basically, MS only supports certain approved systems with MS Teams, and if
whatever you connect to it (in this case Asterisk) doesn’t look sufficiently
like one of those, then Teams won’t play with you.

I’d be very interested to know if anyone thinks it is possible to plug
Asterisk directly into MS Teams, but given Microsoft’s historical attitude to
standards and inter-operability, I suspect what I learned 2 years ago is still
true.

Antony.

I am aware that people have done patches to Asterisk to adjust things accordingly, but noone has ever contributed them to the project.

I will try to modify SIP OPTIONS from source…
Not sure what im into, but i have to give it a try,

If somebody knows what source code files provision OPTIONS method, i surely appreciate the file names,

Also, Thanks for mentioning Kamailio, if i can’t progress with Asterisk itself, ill have to give Kamailio a try,

Warm Regards