Configuring VOIP clients with FusionPBX

This is something like a blog entry – a chronological record of the trials and tribulations encountered whilst setting up a VOIP server and trying to route voice, SMS texts and video calls. What it is not is an instructional “this is exactly what you need to do to accomplish xxx” type guide. There are just too many variables, caveats, dependencies.

The Plan

We wanted better control of our telephone services, which were previously hosted on a Broadsoft cloud based switch platform maintained by Sipcom.

Wish list:

  • To manage a small number of extensions (or softphones) with a central incoming number.
  • PBX hosted on Linux
  • Physical handsets and softphones
  • IVR (Interactive Voice Response – auto attendant)
  • Voicemail
  • Busy lamp support
  • Contact list (phonebook)
  • Integration – unified comms
  • Multi-tenant as an option

Firstly we need a SIP server.

Can buy appliances – PBX in a box.

Or create own.

Commonest is Asterisk (Asterisk 13 + FreePBX 14), but does not support multi-tenant.

FreeSWITCH is an open source softswitch that’s been around for over a decade. The lead designer is Anthony Minessale, who originally worked on the Asterisk project. FusionPBX is a browser based graphical front end (there are many alternatives) for FreeSWITCH that performs many of the same functions that FreePBX® performs for Asterisk.

So here we go

FusionPBX (4.4.3) + FreeSWITCH (1.8.5)

Initial test system using Debian 9.7 running within a VirtualBox guest with 1GB RAM and 1 CPU core.

Added the following extensions:

  • Yealink T26P
  • Polycom Soundpoint IP 501
  • softphones on Ubuntu – Ekiga/Linphone/Twinkle

Gotcha: When the extension tries to register, the server becomes unreachable due to fail2ban blocking repeated registration attempts.
Either service fail2ban stop as a temporary measure, or whitelist IP address(es) of extensions https://docs.fusionpbx.com/en/latest/firewall/fail2ban.html .

Good test: Dialing *9664 should reach Music On Hold

It is hard (virtually impossible with some issues) to succeed without utilising the diagnostic capabilities of a network traffic monitor such as wireshark (Analyze -> Enabled Protocols -> RTP and activate rtp_udp checkbox) and sngrep.  

To get internal extension busy lamps working, Advanced/SIP Profiles/ internal/manage-presence/ true and set up on handsets, e.g. Yealink DSSKey/MemoryKey BLF nnnn Line1 ** (** means remote-pickup)

Auto-provisioning – had a play, but put on back-burner.

Phonebook – had a play, but put on back-burner.

Now to connect to the outside world we need a SIP Trunk provider (but test first with a handset or softphone directly connected to the provider, bypassing FusionPBX).

We chose voipfone.co.uk

As well as any external firewalls, traffic is restricted by FusionPBX:

Advanced/Access Controls
lan: default: allow
domains: default: deny
allow 46.31.231.185/32 VOIPFone

(then Status/SIP Status/ RELOAD ACL)

Dialplan / Outbound Routes . Add a Gateway with a dialplan expression that will route outbound calls, ^(0\d{10})$ # 11 digit nos, eg. 01611234567

Dialplan / Inbound Routes . Add

Dialplan / Destinations . Add
Type: Inbound

Note – if you run FusionPBX on a virtual server and freeze and restart the instance, it can mess up the logging to /var/log/freeswitch/freeswitch.log. A Debian reboot corrects matters.

Inbound routing to extensions, via TimeCondition, IVR menus

After getting this working on an internal server, we moved to an external one. Now firewalling becomes more critical as it’s the Wild West out there. Only allow SIP & RTP from the IP addresses of your extensions and your SIP provider. Use Lets Encrypt Certbot to create an SSL certificate for your server (which should have a proper domain name). Setup email forwarding via postfix.

Check RTP traffic is peer-peer (unless going via POTS termination) – no, it’s routing via FPBX. i.e. FreeSwitch is operating in BTBUA (back-to-back user agent) mode rather than P2P (peer-to-peer). (except when codec transcoding or recording)
Need bypass_media=true in bridge part of dialplan
i.e. Extension (Advanced) – SIP Bypass Media:
But only for endpoints on same LAN (behind NAT)

Make sure the server clock time is correct, otherwise interpreting log files is confusing.
systemctl status ntp
service ntp restart

And had to :
service freeswitch stop
mv /var/log/freeswitch/freeswitch.log /var/log/freeswitch/freeswitch_old.log
service freeswitch start

To get regional public holidays in time conditions, Advanced / Default Settings / Time conditions / Region = england

UK dialout rule for routing 999/112/101 0+10 00+11 via SIP gateway:
^(0\d{9,10})$|^(0\d{7})$|^(1\d{6})$|^(1\d{4})$|^(1\d{2})$|^(999)$|^(00\d{9,17})$

Create:

  • Ring Groups
  • IVR Menus
  • Apps / Time Conditions
  • Whitelists
  • Blacklists (App/Call Block)

We chose not to have multiple external DDIs, rather internal  extensions can be reached via the main number’s voice menu.

Voice menus can be auto text to speech, but the default engine (flite slt) is pretty poor, so we made our own recordings as 16-bit 16kHz WAV files. 

Only need 2 RTP ports per simultaneous call – so 10 should be adequate. But RTP only uses even no.s (RTCP uses odd).
So 20 ports allows 5 simultaneous calls.
/etc/freeswitch/autoload_configs/switch.conf.xml
<param name="rtp-start-port" value="17000"/>
<param name="rtp-end-port" value="17020"/>

service freeswitch restart

After restarting freeswitch, ext Yealink handset won’t receive calls.
Tried changing Account/SipServer1/Expires from 3600 -> 120 – This fixed it.
Tip: If after making freeswitch changes your extensions play-up, reboot ’em (before wasting too much time trying to diagnose an issue that a reboot may fix).

But when trying to dial out, FusionPBX tries to dial number@sipcom.com, but sipcom does not forward to POTS
(like Linphone behaviour, unlike twinkle?)
604 Does Not Exist Anywhere
Generic problem that occurs when someone sends “Remote Party ID” to a VoIP Provider that doesn’t want/need it. On gateway/advanced, need to set:
Sip CID Type = none

caller hangs-up, receiving extension does not clear – BYE signal not being passed to receiver? Switched Yealink handsets from TCP to UDP and it hung-up correctly.

Now for Video calling.

Important first step: Make sure audio (microphone and speakers) and webcam work – especially on Linux clients. We had to fight alsamixer, pavucontrol. Had best results with Linphone 4.1.1 installed from flatpak.

Check extension SIP Bypass Media:
Blank Default: media flows through FS  (transcoded if clients do not share a common codec)
Bypass Media RTP routes peer-2-peer 
Bypass Media after Bridge
Proxy Media Transparent Proxy – RTP passes unaltered via FS (no transcoding)

Bypass media is incompatible with NAT unless you’re using STUN/TURN/ICE in your clients

Need to go back to default media mode and work out why FS is not keeping VP8 in Invite
Does FS recognise VP8 codec?

FS should be able to transcode VP8/H264
(note WebRTC client bundles only Opus,iSAC,iLBC audio and VP8,VP9 video)

Red Herring:
<!– Codecs –> section of /etc/freeswitch/autoload_configs/modules.conf.xml does not have a VP8 entry
VP8 & VP9 was replaced by mod_vpx in a later version which is now automatically loaded as part of the core

fs_cli
show codec
does give VP8 Videoenable

Advanced -> Variables and add OPUS,H264,VP8 to the list of supported codecs in both outbound_codec_prefs and global_codec_prefs
Then on SIP Status page Flush cache and Rescan ‘sofia status profile internal’
Check with fs_cli: sofia status profile internal

Video call from a browser

webrtc on freeswitch: http://nerdvittles.com/?p=26750
cd /usr/src
git clone https://github.com/fusionpbx/fusionpbx-apps
cd fusionpbx-apps
cp -R sipjs/ /var/www/fusionpbx/app/
chown -R www-data:www-data /var/www/fusionpbx/

Advanced -> Variables; SIP Profile: Internal & External; internal/external_ssl_enable to true
Status -> SIP Status and click FLUSH CACHE
service freeswitch restart
Advanced -> SIP Profiles -> Internal and set wss-binding to true (port 7443 TCP – firewall)
service freeswitch restart
Status -> SIP Status, click FLUSH CACHE and then REFRESH

/etc/freeswitch/vars.xml (using XML editor) – Add (Opus,H264 &) VP8 to global_codec_prefs and outbound_codec_prefs have gone missing…
Advanced -> Variables and add H264 to the list of supported codecs in both outbound_codec_prefs and global_codec_prefs
SAVE. Navigate to Status -> SIP Status and click FLUSH CACHE then RESCAN internal profile
Advanced -> Upgrade -> Menu Defaults and EXECUTE
Add Admin user to an Extension; then log out/in
Apps -> SIPjs dial *9664

FS inbuilt SIPJS WebRTC client appears to fall foul of “unable to acquire streams” Javascript issue in Chrome, but works in Firefox.

video call from FS/sipjs on firefox to Linphone

Now try local SIPJS WebRTC browser client via our FusionPBX server with code based on https://sipjs.com/ 

openssl s_client -dtls1 -connect oursipserver.co.uk:7443
gives CONNECTED, showing traversal through the firewall is OK.

Needed to specify
wsUri: “wss://oursipserver.co.uk:**7443**”,
in sip-0.13.7.js otherwise it attempts 443 (shown by Network tab in browser Developer Tools)

https://webrtc.github.io/samples/src/content/devices/input-output/ can help as a test

WebRTC https://hpbn.co/webrtc/ https://sipjs.com/

So, current issues:

  • delay in audio/video whilst routing via FPBX
  • Peer-Peer RTP routing and NAT/STUN/TURN/ICE etc.
  • Browser support for WebRTC is patchy…

May 2022 Update

The FreeSWITCH project (now at version 1.10.7) has been moved to GitHub: https://github.com/signalwire/freeswitch.

The  repositories use to be hosted at http://files.freeswitch.org/repo/deb/freeswitch-1.8/ , however they are now hosted at https://freeswitch.signalwire.com/repo/deb/debian-release/ , which requires a (free) SignalWire Personal Access Token (PAT) to access FreeSWITCH install packages. See https://freeswitch.org/confluence/display/FREESWITCH/HOWTO+Create+a+SignalWire+Personal+Access+Token

Once we’d sorted out the FreeSWITCH package locations, upgrading our Debian host VM from 9.13 stretch → 10.12 buster → 11.3 bullseye went without a hitch.

FusionPBX v5.0.1 has recently been released, but an upgrade attempt (following https://docs.fusionpbx.com/en/latest/advanced/version_upgrade.html) left us with all sorts of problems, so we’ve reverted to FusionPBX v4.4.3 (running on FreeSWITCH 1.10.7).