Extending this further, I recently learned that Twilio does not verify SSL remote certs over SIP trunks: SIP Security Best Practices | Twilio. This means they accept self-signed certs, and you don’t need to buy a cert to encrypt your SIP traffic. As such, there really isn’t any reason not to encrypt your traffic with Twilio. So let’s do it!
Asterisk/PJSIP’s SSL listener is a basic TCP TLS implementation. (Not UDP DTLS.) So if you’re familiar with TLS for web servers all the same rules apply. There are two main gotchas I found:
- The CA cert is required, so the basic openssl one-liner to create a self-signed key/cert pair doesn’t work. However, Asterisk comes with a script to generate a self-signed SSL cert with a CA cert in the repo contrib/ directory, so we can use that.
- Media encryption defaults to off and must be manually enabled, as Twilio requires media encryption when enabling encryption. If you miss this the error is
res_pjsip_session.c:937 handle_incoming_sdp: Twilio: Couldn't negotiate stream 0:audio-0:audio:sendrecv (nothing)
The steps from here assume you already have the previously posted config working.
First, run the contrib script to make a self-signed cert and store it in a path accessible to Asterisk. Note that by default this script drops CA and config files into the working directory, so I recommend running it in a work directory and copying the CA cert, server cert, and server key into the final location. Script source: asterisk/contrib/scripts/ast_tls_cert at master · asterisk/asterisk · GitHub
Then set up the SSL transport in pjsip.conf. This is net-new:
[ssltrans]
type=transport
protocol=tls
bind=0.0.0.0:5061
allow_reload=no
tos=cs3
cos=3
local_net=[Local network CIDR]
external_media_address=[Asterisk Public IP]
external_signaling_address=[Asterisk Public IP]
ca_list_file=[CA cert file path]
cert_file=[Server cert file path]
priv_key_file=[Server key file path]
method=tlsv1
; Disable verify_client as we're not doing mutual TLS
verify_client=no
; Asterisk doesn't like Twilio's wildcard certs.
verify_server=no
If you reload your config at this point TCP/5061 should be open and using the self-signed cert. This can be checked with openssl:
echo | openssl s_client -connect 127.0.0.1:5061
Then update the twilio
endpoint to use the ssltrans
transport and encrypt media. This is a diff:
[Twilio]
type=endpoint
-transport=simpletrans
context=Twilio ;Which dialplan to use for incoming calls
disallow=all
allow=ulaw
outbound_auth=Twilio-auth
aors=Twilio
; NOTE: direct_media is not in the original config guide, but I needed it to prevent NAT issues.
direct_media=no
+media_encryption=sdes
+media_use_received_transport=yes
+transport=ssltrans
With this config setting Secure Trunking
to Enabled
in your Twilio Elastic SIP Trunking settings in Twilio’s portal should work. If Twilio is the only SIP connection incoming from the internet you should be able to close port 5060 TCP & UDP internet access.
I found the following very helpful when working through these settings: res_pjsip: SIP Resource using PJProject - Asterisk Documentation
And if you don’t use module autoloading make sure res_srtp.so
and res_crypto.so
are loaded.
Finally, a complete config:
[global]
type=global
[simpletrans]
type=transport
protocol=udp
bind=0.0.0.0:5060
allow_reload=no
tos=cs3
cos=3
local_net=[Local network CIDR]
external_media_address=[Asterisk Public IP]
external_signaling_address=[Asterisk Public IP]
[ssltrans]
type=transport
protocol=tls
bind=0.0.0.0:5061
allow_reload=no
tos=cs3
cos=3
local_net=[Local network CIDR]
external_media_address=[Asterisk Public IP]
external_signaling_address=[Asterisk Public IP]
ca_list_file=[CA cert file path]
cert_file=[Server cert file path]
priv_key_file=[Server key file path]
method=tlsv1
; Disable verify_client as we're not doing mutual TLS
verify_client=no
; Asterisk doesn't like Twilio's wildcard certs.
verify_server=no
[Twilio]
type=endpoint
context=Twilio ;Which dialplan to use for incoming calls
disallow=all
allow=ulaw
outbound_auth=Twilio-auth
aors=Twilio
direct_media=no
media_encryption=sdes
media_use_received_transport=yes
transport=ssltrans
;===============Inbound calls
[Twilio-auth]
type=auth
auth_type=userpass
username=[username]
password=[password]
[Twilio]
type=identify
endpoint=Twilio
; Twilio Signalling 54.172.60.0/30
match=54.172.60.0
match=54.172.60.1
match=54.172.60.2
match=54.172.60.3
; Twilio Signalling 54.244.51.0/30
match=54.244.51.0
match=54.244.51.1
match=54.244.51.2
match=54.244.51.3
; Twilio Signalling 54.171.127.192/30
match=54.171.127.192
match=54.171.127.193
match=54.171.127.194
match=54.171.127.195
; Twilio Signalling 35.156.191.128/30
match=35.156.191.128
match=35.156.191.129
match=35.156.191.130
match=35.156.191.131
; Twilio Signalling 54.65.63.192/30
match=54.65.63.192
match=54.65.63.193
match=54.65.63.194
match=54.65.63.195
; Twilio Signalling 54.169.127.128/30
match=54.169.127.128
match=54.169.127.129
match=54.169.127.130
match=54.169.127.131
; Twilio Signalling 54.252.254.64/30
match=54.252.254.64
match=54.252.254.65
match=54.252.254.66
match=54.252.254.67
; Twilio Signalling 177.71.206.192/30
match=177.71.206.192
match=177.71.206.193
match=177.71.206.194
match=177.71.206.195
;===============Outbound calls
[Twilio]
type=aor
contact=sip:[SIP trunk Termination SIP URI in Twilio]