VoIP, Linux, Security & much more fun
If you need any help regarding these subjects do not hesitate about sending me a text

Twilio is one complete VoIP carriers these days. Among its SMS capabilities, it provides sip trunks as well. The good or bad thing about Twilio is that its SIP trunk only works with SSL/TLS. This will help you to warrant your confidentiality but it needs more work from you to make it work. I will talk how I did it.

Preparing the System Variables

By default, FusionPBX has SSL/TLS disabled. It is easy to turn it on. Go to Advanced->Variables menu, you will find a variable called external_ssl_enable; turn this variable to true. Take note of the value in the variable external_ssl_dir, by default has the value $${conf_dir}/ssl. Depending on how you installed your FreeSWITCH, you will know what value it has. For example, if you are using my RPMs for FreeSWITCH from OKay RPM Repository, that variable is pointing to /etc.

Those variables will affect the external sip profile. external_ssl_enable will apply on the tls parameter and external_ssl_dir will apply on tls-cert-dir parameter. There is no need to change the other parameters from the profile, they work out of the box; only if you want to customize something.

If you want to learn how FreeSWITCH gets all this info, you can read the file vars.xml and you can turn on the xml_string debugging in FusionPBX to see the XML that it outputs.

Setting Up the Certificates

I will assume you already have your certificate. Lucky us, FreeSWITCH works with self-signed certificates, and so far I haven't found any carrier or IP Phone that does not work with them. HTTP/HTTPS is different, I am just talking about SIPs or SRTP. FreeSWITCH needs the following files inside the external_ssl_dir directory: agent.pem, cafile.pem, tls.pem, wss.pem, dtls-srtp. Names are almost self-explained. I will put some comments about them:

  • The cafile.pem file needs to have the public part of your trust chain. This file is usually given from any SSL Vendor when you get a commercial certificate.
  • The agent.pem, tls.pem, wss.pem and dtls-srtp.pem are used for different things but they must contain the same keys. Inside each file, you will put the public and private key.

Setting Up the Gateway for Outbound Calls

Twilio configuration as almost as any gateway. The only difference is that you need to go into the advanced settings of the gateway and switch to TLS transport mode. This will make FusionPBX XML Handler deliver the following parameters to FreeSWITCH:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="freeswitch/xml">
     <section name="configuration">
           <configuration name="sofia.conf" description="sofia Endpoint">
                 <global_settings>
                       <param name="log-level" value="0"/>
                        <param name="debug-presence" value="0"/>
                 </global_settings>
                 <profiles>
                        <profile name="external">
                              <aliases>
                              </aliases>
                              <gateways>
                                   <gateway name="4569e34e-97e4-4ad4-a249-b00cfebcdd0b">
                                         <param name="username" value="any_username"/>
                                         <param name="password" value="any_password"/>
                                         <param name="realm" value="sip.twilio.com"/>
                                         <param name="from-domain" value="nextrueit.pstn.twilio.com"/>
                                         <param name="proxy" value="nextrueit.pstn.twilio.com"/>
                                         <param name="expire-seconds" value="800"/>
                                         <param name="register" value="false"/>
                                         <param name="register-transport" value="tls"/>
                                         <param name="contact-params" value="transport=tls"/>
                                         <param name="retry-seconds" value="30"/>
                                         <param name="context" value="public"/>
                                         <variables>
                                         </variables>
                                   </gateway>
                              </gateways>
                              <domains>
<!-- indicator to parse the directory for domains with parse="true" to get gateways-->
<!--<domain name="$${domain}" parse="true"/>-->
<!-- indicator to parse the directory for domains with parse="true" to get gateways and alias every domain to this profile -->
                                <!--<domain name="all" alias="true" parse="true"/>-->
                                <domain name="all" alias="false" parse="false""/>
                              </domains>
                              <settings>
                                <param name="rtp-ip" value="1.1.1.1"/>
                                <param name="sip-ip" value="1.1.1.1"/>
                                <param name="ext-rtp-ip" value="1.1.1.1"/>
                                <param name="ext-sip-ip" value="1.1.1.1"/>
                                <param name="rtp-timeout-sec" value="300"/>
                                <param name="rtp-hold-timeout-sec" value="1800"/>
                                <param name="tls" value="true"/>
                                <param name="tls-bind-params" value="transport=tls"/>
                                <param name="tls-sip-port" value="5081"/>
                                <param name="tls-cert-dir" value="/etc//ssl"/>
                                <param name="tls-verify-date" value="false"/>
                                <param name="tls-only" value="false"/>
                                <param name="tls-passphrase" value=""/>
                                <param name="tls-version" value="tlsv1"/>
                                <param name="user-agent-string" value="FreeSWITCH"/>
                                <param name="sip-trace" value="no"/>
                                <param name="sip-capture" value="no"/>
                                <param name="rfc2833-pt" value="101"/>
                                <param name="dialplan" value="XML"/>
                                <param name="context" value="public"/>
                                <param name="dtmf-type" value="rfc2833"/>
                                <param name="tls-verify-policy" value="none"/>
                                <param name="dtmf-duration" value="2000"/>
                                <param name="inbound-codec-prefs" value="G7221@32000h,G7221@16000h,G722,PCMU,PCMA,GSM"/>
                                <param name="outbound-codec-prefs" value="PCMU,PCMA,GSM"/>
                                <param name="debug" value="0"/>
                                <param name="hold-music" value="local_stream://default"/>
                                <param name="zrtp-passthru" value="true"/>
                                <param name="rtp-timer-name" value="soft"/>
                                <param name="local-network-acl" value="localnet.auto"/>
                                <param name="manage-presence" value="false"/>
                                <param name="inbound-codec-negotiation" value="generous"/>
                                <param name="nonce-ttl" value="60"/>
                                <param name="auth-calls" value="false"/>
                                <param name="sip-port" value="5080"/>
                                <param name="tls-verify-depth" value="2"/>
                                <param name="tls-verify-in-subjects" value=""/>
                              </settings>
                        </profile>
                        <profile name="internal">
                              <aliases>
                              </aliases>
                              <gateways>
                              </gateways>
                              <domains>
<!-- indicator to parse the directory for domains with parse="true" to get gateways-->
<!--<domain name="$${domain}" parse="true"/>-->
<!-- indicator to parse the directory for domains with parse="true" to get gateways and alias every domain to this profile -->
                                <!--<domain name="all" alias="true" parse="true"/>-->
                                <domain name="all" alias="false" parse="false""/>
                              </domains>
                              <settings>
                                <param name="tls-cert-dir" value="/etc/ssl"/>
                                <param name="tls-passphrase" value=""/>
                                <param name="tls-verify-date" value="true"/>
                                <param name="tls-verify-depth" value="2"/>
                                <param name="tls-verify-in-subjects" value=""/>
                                <param name="tls-version" value="tlsv1"/>
                                <param name="nonce-ttl" value="60"/>
                                <param name="inbound-reg-force-matching-username" value="true"/>
                                <param name="auth-all-packets" value="false"/>
                                <param name="ext-rtp-ip" value="1.1.1.1"/>
                                <param name="ext-sip-ip" value="1.1.1.1"/>
                                <param name="rtp-timeout-sec" value="300"/>
                                <param name="rtp-hold-timeout-sec" value="1800"/>
                                <param name="NDLB-force-rport" value="safe"/>
                                <param name="challenge-realm" value="auto_to"/>
                                <param name="auth-calls" value="true"/>
                                <param name="user-agent-string" value="FreeSWITCH"/>
                                <param name="debug" value="0"/>
                                <param name="sip-trace" value="no"/>
                                <param name="sip-capture" value="no"/>
                                <param name="watchdog-enabled" value="no"/>
                                <param name="watchdog-step-timeout" value="30000"/>
                                <param name="watchdog-event-timeout" value="30000"/>
                                <param name="log-auth-failures" value="true"/>
                                <param name="forward-unsolicited-mwi-notify" value="false"/>
                                <param name="context" value="public"/>
                                <param name="rfc2833-pt" value="101"/>
                                <param name="sip-port" value="5060"/>
                                <param name="dialplan" value="XML"/>
                                <param name="dtmf-type" value="rfc2833"/>
                                <param name="dtmf-duration" value="2000"/>
                                <param name="inbound-codec-prefs" value="G7221@32000h,G7221@16000h,G722,PCMU,PCMA,GSM"/>
                                <param name="outbound-codec-prefs" value="G7221@32000h,G7221@16000h,G722,PCMU,PCMA,GSM"/>
                                <param name="rtp-timer-name" value="soft"/>
                                <param name="rtp-ip" value="1.1.1.1"/>
                                <param name="sip-ip" value="1.1.1.1"/>
                                <param name="hold-music" value="local_stream://default"/>
                                <param name="apply-nat-acl" value="nat.auto"/>
                                <param name="aggressive-nat-detection" value="true"/>
                                <param name="apply-inbound-acl" value="domains"/>
                                <param name="local-network-acl" value="localnet.auto"/>
                                <param name="record-path" value="/var/lib/freeswitch/recordings"/>
                                <param name="record-template" value="${domain_name}/archive/${strftime(%Y)}/${strftime(%b)}/${strftime(%d)}/${uuid}.${record_ext}"/>
                                <param name="manage-presence" value="true"/>
                                <param name="presence-probe-on-register" value="true"/>
                                <param name="manage-shared-appearance" value="true"/>
                                <param name="presence-privacy" value="$${presence_privacy}"/>
                                <param name="inbound-codec-negotiation" value="generous"/>
                                <param name="tls" value="true"/>
                                <param name="tls-only" value="false"/>
                                <param name="tls-bind-params" value="transport=tls"/>
                                <param name="tls-sip-port" value="5061"/>
                              </settings>
                        </profile>
                 </profiles>
           </configuration>
     </section>
</document>

Setting Up the Dialplan

Dialplan should be set up as usual. After you are done, add the following variables:

  • export nolocal:rtp_secure_media = true:AES_CM_128_HMAC_SHA1_80

Optionally, you can put:

  • set proxy_media = false
  • set bypass_media = false
  • export zrtp_secure_media = false

At the end, your dial-plan should look somehow like this:

twilio dialplan in fusionpbx

Setting up Inbound Calls

There is not too much to add here. From the Twilio web console, make sure you forward calls to port 5081 which it is the default port for incoming calls with TLS enabled.

You are done. Good luck!

blog comments powered by Disqus
If you need more help than the free one provided here...