Child pages
  • FreeSWITCH SIP Trunking Gateway
Skip to end of metadata
Go to start of metadata

Introduction

As of FreeSWITCH version 1.2.3, FreeSWITCH mod_sofia has become mature enough to handle all signalling demands from sipXecs, and can be used as a SIP trunking/call routing platform, amongst other things. sipXecs does not include a version this new, however the FreeSWITCH team now provides a yum repo that makes FreeSWITCH installation trivial. See the FreeSWITCH Installation Guide for more information on installing FreeSWITCH on a standalone server.

System Variable Changes

There are a few system variables we should change to interop with ITSP providers better, and for firewall simplicity. The first of these is the internal and external SIP ports. As we are simply using the internal profile for connecting to sipXecs, we can set the port to 5080, while leaving 5060 for the external profile. To do this, change the following variables in /etc/freeswitch/vars.xml:

/etc/freeswitch/vars.xml
<!-- Internal SIP Profile -->
<X-PRE-PROCESS cmd="set" data="internal_auth_calls=false"/>
<X-PRE-PROCESS cmd="set" data="internal_sip_port=5080"/>
<X-PRE-PROCESS cmd="set" data="internal_tls_port=5081"/>
<X-PRE-PROCESS cmd="set" data="internal_ssl_enable=false"/>
<X-PRE-PROCESS cmd="set" data="internal_ssl_dir=$${base_dir}/conf/ssl"/>
<!-- External SIP Profile -->
<X-PRE-PROCESS cmd="set" data="external_auth_calls=false"/>
<X-PRE-PROCESS cmd="set" data="external_sip_port=5060"/>
<X-PRE-PROCESS cmd="set" data="external_tls_port=5061"/>
<X-PRE-PROCESS cmd="set" data="external_ssl_enable=false"/>
<X-PRE-PROCESS cmd="set" data="external_ssl_dir=$${base_dir}/conf/ssl"/>

We also need to change the RTP port range for firewall simplicity. The default port range is too wide and leaves a lot of open ports. Change the following variables in /etc/freeswitch/autoload_configs/switch.conf.xml:

/etc/freeswitch/autoload_configs/switch.conf.xml
<!-- RTP port range -->
<param name="rtp-start-port" value="30000"/>
<param name="rtp-end-port" value="31000"/>
<param name="rtp-enable-zrtp" value="true"/>

Sofia Profiles and Dialplans

By default, FreeSWITCH store sofia profiles in /etc/freeswitch/sip_profiles and dialplan information is stored in /etc/freeswitch/dialplan

We need to remove or rename the existing xml files in these two locations so that conflicts do not occur with the profiles and dialplans that we will be creating.

Sofia Profiles

Create two sip profiles, internal and external:

/etc/freeswitch/sip_profiles/internal.xml
  <profile name="to-sipx">
  <aliases>
    <!--
    <alias name="outbound"/>
    <alias name="nat"/>
    -->
  </aliases>
  <domains>
    <domain name="all" alias="false" parse="true"/>
  </domains>
  <settings>
    <param name="debug" value="0"/>
    <param name="sip-trace" value="no"/>
    <param name="rfc2833-pt" value="101"/>
    <param name="sip-port" value="$${internal_sip_port}"/>
    <param name="dialplan" value="XML"/>
    <param name="context" value="private"/>
    <param name="dtmf-duration" value="100"/>
    <param name="codec-prefs" value="G722,PCMU@20i,PCMA@20i,speex,L16"/>
    <param name="hold-music" value="$${hold_music}"/>
    <param name="rtp-timer-name" value="soft"/>
    <param name="inbound-late-negotiation" value="true"/>
    <!--<param name="enable-100rel" value="true"/>-->
    <!-- This could be set to "passive" -->
    <param name="local-network-acl" value="localnet.auto"/>
    <param name="manage-presence" value="false"/>
    <!-- used to share presence info across sofia profiles
     manage-presence needs to be set to passive on this profile
     if you want it to behave as if it were the internal profile
     for presence.
    -->
    <!-- Name of the db to use for this profile -->
    <!--<param name="dbname" value="share_presence"/>-->
    <!--<param name="presence-hosts" value="$org.sipfoundry.sipxconfig.domain.Domain@1"/>-->
    <!--<param name="force-register-domain" value="$org.sipfoundry.sipxconfig.domain.Domain@1"/>-->
    <!--all inbound reg will stored in the db using this domain -->
    <!--<param name="force-register-db-domain" value="$org.sipfoundry.sipxconfig.domain.Domain@1"/>-->
    <!-- ************************************************* -->
    <!--<param name="aggressive-nat-detection" value="true"/>-->
    <param name="inbound-codec-negotiation" value="generous"/>
    <param name="nonce-ttl" value="60"/>
    <param name="auth-calls" value="false"/>
    <param name="accept-blind-auth" value="true"/>
    <!--
    DO NOT USE HOSTNAMES, ONLY IP ADDRESSES IN THESE SETTINGS!
    -->
    <param name="rtp-ip" value="$${local_ip_v4}"/>
    <param name="sip-ip" value="$${local_ip_v4}"/>
    <param name="ext-rtp-ip" value="$${local_ip_v4}"/>
    <param name="ext-sip-ip" value="$${local_ip_v4}"/>
    <param name="rtp-timeout-sec" value="300"/>
    <param name="rtp-hold-timeout-sec" value="1800"/>
    <!-- <param name="enable-3pcc" value="true"/> -->
    <!-- TLS: disabled by default, set to "true" to enable -->
    <param name="tls" value="$${external_ssl_enable}"/>
    <!-- additional bind parameters for TLS -->
    <param name="tls-bind-params" value="transport=tls"/>
    <!-- Port to listen on for TLS requests. (5081 will be used if unspecified) -->
    <param name="tls-sip-port" value="$${external_tls_port}"/>
    <!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
    <param name="tls-cert-dir" value="$${external_ssl_dir}"/>
    <!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
    <param name="tls-version" value="$${sip_tls_version}"/>
  </settings>
</profile>
/etc/freeswitch/sip_profiles/external.xml
 <profile name="external">
  <!-- http://wiki.freeswitch.org/wiki/Sofia_Configuration_Files -->
  <!-- This profile is only for outbound registrations to providers -->
  <gateways>
    <X-PRE-PROCESS cmd="include" data="external/*.xml"/>
  </gateways>
 
  <aliases>
    <!--
        <alias name="outbound"/>
        <alias name="nat"/>
    -->
  </aliases>
 
  <domains>
    <domain name="all" alias="false" parse="true"/>
  </domains>
 
  <settings>
    <param name="debug" value="1"/>
    <!-- If you want FreeSWITCH to shutdown if this profile fails to load, uncomment the next line. -->
    <!-- <param name="shutdown-on-fail" value="true"/> -->
    <param name="sip-trace" value="no"/>
    <param name="sip-capture" value="no"/>
    <param name="rfc2833-pt" value="101"/>
    <!-- RFC 5626 : Send reg-id and sip.instance -->
    <!--<param name="enable-rfc-5626" value="true"/> -->
    <param name="sip-port" value="$${external_sip_port}"/>
    <param name="dialplan" value="XML"/>
    <param name="context" value="public"/>
    <param name="dtmf-duration" value="2000"/>
    <param name="inbound-codec-prefs" value="$${global_codec_prefs}"/>
    <param name="outbound-codec-prefs" value="$${outbound_codec_prefs}"/>
    <param name="hold-music" value="$${hold_music}"/>
    <param name="rtp-timer-name" value="soft"/>
    <!--<param name="enable-100rel" value="true"/>-->
    <!--<param name="disable-srv503" value="true"/>-->
    <!-- This could be set to "passive" -->
    <param name="local-network-acl" value="localnet.auto"/>
    <param name="manage-presence" value="false"/>
 
    <!-- used to share presence info across sofia profiles
         manage-presence needs to be set to passive on this profile
         if you want it to behave as if it were the internal profile
         for presence.
    -->
    <!-- Name of the db to use for this profile -->
    <!--<param name="dbname" value="share_presence"/>-->
    <!--<param name="presence-hosts" value="$${domain}"/>-->
    <!--<param name="force-register-domain" value="$${domain}"/>-->
    <!--all inbound reg will stored in the db using this domain -->
    <!--<param name="force-register-db-domain" value="$${domain}"/>-->
    <!-- ************************************************* -->
 
    <param name="aggressive-nat-detection" value="true"/>
    <param name="inbound-codec-negotiation" value="generous"/>
    <param name="nonce-ttl" value="60"/>
    <param name="auth-calls" value="false"/>
    <param name="inbound-late-negotiation" value="true"/>
    <param name="inbound-zrtp-passthru" value="true"/> <!-- (also enables late negotiation) -->
    <!--
        DO NOT USE HOSTNAMES, ONLY IP ADDRESSES IN THESE SETTINGS!
    -->
    <param name="rtp-ip" value="$${local_ip_v4}"/>
    <param name="sip-ip" value="$${local_ip_v4}"/>
    <param name="ext-sip-ip" value="auto-nat"/>
    <param name="ext-rtp-ip" value="auto-nat"/>
    <param name="rtp-timeout-sec" value="300"/>
    <param name="rtp-hold-timeout-sec" value="1800"/>
    <!--<param name="enable-3pcc" value="true"/>-->
 
    <!-- TLS: disabled by default, set to "true" to enable -->
    <param name="tls" value="$${external_ssl_enable}"/>
    <!-- Set to true to not bind on the normal sip-port but only on the TLS port -->
    <param name="tls-only" value="false"/>
    <!-- additional bind parameters for TLS -->
    <param name="tls-bind-params" value="transport=tls"/>
    <!-- Port to listen on for TLS requests. (5081 will be used if unspecified) -->
    <param name="tls-sip-port" value="$${external_tls_port}"/>
    <!-- Location of the agent.pem and cafile.pem ssl certificates (needed for TLS server) -->
    <param name="tls-cert-dir" value="$${external_ssl_dir}"/>
    <!-- Optionally set the passphrase password used by openSSL to encrypt/decrypt TLS private key files -->
    <param name="tls-passphrase" value=""/>
    <!-- Verify the date on TLS certificates -->
    <param name="tls-verify-date" value="true"/>
    <!-- TLS verify policy, when registering/inviting gateways with other servers (outbound) or handling inbound registration/invite requests how should we verify their certificate -->
    <!-- set to 'in' to only verify incoming connections, 'out' to only verify outgoing connections, 'all' to verify all connections, also 'in_subjects', 'out_subjects' and 'all_subjects' for subject validation. Multiple policies can be split with a '|' pipe -->
    <param name="tls-verify-policy" value="none"/>
    <!-- Certificate max verify depth to use for validating peer TLS certificates when the verify policy is not none -->
    <param name="tls-verify-depth" value="2"/>
    <!-- If the tls-verify-policy is set to subjects_all or subjects_in this sets which subjects are allowed, multiple subjects can be split with a '|' pipe -->
    <param name="tls-verify-in-subjects" value=""/>
    <!-- TLS version ("sslv23" (default), "tlsv1"). NOTE: Phones may not work with TLSv1 -->
    <param name="tls-version" value="$${sip_tls_version}"/>
  </settings>
</profile>

 

We also need to define our SIP trunking gateway. In this case, we will use voip.ms:

/etc/freeswitch/sip_profiles/external/voipms.xml
 <include>
  <gateway name="voip.ms">
  <!--/// account username *required* ///-->
  <param name="username" value="voipmsuser"/>
  <!--/// auth realm: *optional* same as gateway name, if blank ///-->
  <!--<param name="realm" value="asterlink.com"/>-->
  <!--/// username to use in from: *optional* same as  username, if blank ///-->
  <!--<param name="from-user" value="cluecon"/>-->
  <!--/// domain to use in from: *optional* same as  realm, if blank ///-->
  <!--<param name="from-domain" value="asterlink.com"/>-->
  <!--/// account password *required* ///-->
  <param name="password" value="voipmspassword"/>
  <!--/// extension for inbound calls: *optional* same as username, if blank ///-->
  <!--<param name="extension" value="cluecon"/>-->
  <!--/// proxy host: *optional* same as realm, if blank ///-->
  <param name="proxy" value="dallas.voip.ms"/>
  <!--/// send register to this proxy: *optional* same as proxy, if blank ///-->
  <!--<param name="register-proxy" value="mysbc.com"/>-->
  <!--/// expire in seconds: *optional* 3600, if blank ///-->
  <param name="expire-seconds" value="300"/>
  <!--/// do not register ///-->
  <param name="register" value="true"/>
  <!-- which transport to use for register -->
  <param name="register-transport" value="udp"/>
  <!--How many seconds before a retry when a failure or timeout occurs -->
  <param name="retry-seconds" value="30"/>
  <!--Use the callerid of an inbound call in the from field on outbound calls via this gateway -->
  <param name="caller-id-in-from" value="true"/>
  <!--extra sip params to send in the contact-->
  <!--<param name="contact-params" value="tport=tcp"/>-->
  <!--send an options ping every x seconds, failure will unregister and/or mark it down-->
  <param name="ping" value="25"/>
  </gateway>
  <!--rfc5626 : Abilitazione rfc5626 ///-->
  <!--<param name="rfc-5626" value="true"/>-->
  <!--rfc5626 : extra sip params to send in the contact-->
  <!--<param name="reg-id" value="1"/>-->
</include>

Dialplans

We now need to tell FreeSWITCH how to route calls. For this example we will use a very basic dialplan that routes calls from the ITSP to the sipXecs system, and vice versa, with no number manipulations etc.

/etc/freeswitch/dialplan/default.xml
 <include>
<context name="private">
    <extension name="going-out">
        <condition field="destination_number" expression="^(\d{7,20})$">
            <action application="set" data="transfer_ringback=$${us-ring}"/>
            <!--Set this for a generic Caller ID -->
            <action application="set" data="effective_caller_id_number=5553211234"/>
            <action application="bridge" data="sofia/gateway/voip.ms/$1"/>
            <action application="answer"/>
            <anti-action application="set" data="transfer_ringback=$${us-ring}"/>
            <anti-action application="bridge" data="sofia/to-sipx/${destination_number}@sip.corp.ezuce.com"/>
            <anti-action application="answer"/>
        </condition>
    </extension>
</context>
</include>

 

This dialplan takes any number with 7-20 digits and routes it verbatim to the voip.ms gateway. Note the "catch-all" anti-action statements. This is because FreeSWITCH evaluates blind transfers against the dialplan, and blind transfers will fail if there is not a way to route them back to the sipXecs system. It is possible, however unlikely, that a looping scenario may occur.

/etc/freeswitch/dialplan/public.xml
 <include>
<context name="public">
    <extension name="going-in">
        <condition>
            <action application="set" data="transfer_ringback=$${us-ring}"/>
            <action application="bridge" data="{ignore_early_media=true}sofia/to-sipx/${destination_number}@sip.corp.ezuce.com"/>
            <action application="answer"/>
        </condition>
    </extension>
</context>
</include>

 

 

Notice how there is no condition matching. This simply allows anything coming into this profile to be routed to the sipXecs server.

 

Note: 

To allow for simultaneous call forwarding (ringing multiple endpoints for a user including extension and cell phone at the same time for example)- we need to add {ignore_early_media=true} in the public.xml configuration.

Without this freeswitch will use the first contact from a 183 progress with SDP message and if a user picks up a call on their extension there will be no audio. Ignore early media will force Freeswitch to use the contact for the endpoint that answers.

  • No labels