PBX – James Batchelor https://james-batchelor.com Useful I.T & VoIP Ramblings Thu, 28 Dec 2023 15:36:05 +0000 en-US hourly 1 https://wordpress.org/?v=6.8.5 https://james-batchelor.com/wp-content/uploads/2025/05/cropped-cropped-logo-jb-202505-32x32.png PBX – James Batchelor https://james-batchelor.com 32 32 Asterisk Monitoring Over SNMP https://james-batchelor.com/index.php/2023/12/28/asterisk-monitoring-over-snmp/ Thu, 28 Dec 2023 15:36:05 +0000 https://james-batchelor.com/?p=927 Continue reading "Asterisk Monitoring Over SNMP"]]> The aim of deploying Zabbix and adding SNMP to Gentoo was to gain better insight on how an Asterisk PBX was performing.

Last of the hurdles was to get data from Asterisk in order to send to Zabbix, however the traditional way of loading the res_snmp.so module in Asterisk was not available, as while the PBX in question utilises Asterisk, its buried under proprietary licensing and a non-standard api, therefore being unable to either add the SNMP module or to query it.

If you are experiencing a similar situation, here is how to extract some stats from Asterisk 16 using SNMP, but without the SNMP module…

Despite not being able edit Asterisk code directly, SSH access and the Asterisk CLI is available, so can run commands to return a snapshot of PBX activity.

The following commands can be run to output some valuable info:

asterisk -rx ‘pjsip show endpoints’ returns total number and current online endpoints, as well as reported user agent of device.

asterisk -rx ‘core show channels verbose’ gives us a list of active channels and current point in an inbound call flow, along with a counter of completed calls.

asterisk -rx ‘pjsip show channelstats’ is similar to ‘show channels verbose’, but includes the codec in use, helpful to determine if the system is transcoding.

Scripts

To get and output just the info required, a script can be created to parse the command output and list each value on a new line.

Create the three files below and paste the code in.
In this example I saved to /usr/local……

asterisk_chan.sh

command_output=$(asterisk -rx 'core show channels')

active=$(echo "$command_output" | grep -oE '[0-9]+ active channels' | grep -oE '[0-9]+')
processed=$(echo "$command_output" | grep -oE '[0-9]+ calls processed' | grep -oE '[0-9]+')

echo "$active"
echo "$processed"

asterisk_chanstat.sh

command_output=$(asterisk -rx 'pjsip show channelstats')

opus=$(echo "$command_output" | grep 'opus' | (wc -l))
g722=$(echo "$command_output" | grep 'g722' | (wc -l))
alaw=$(echo "$command_output" | grep 'alaw' | (wc -l))
ulaw=$(echo "$command_output" | grep 'ulaw' | (wc -l))
g729=$(echo "$command_output" | grep 'ulaw' | (wc -l))
total=$(echo "$command_output" | grep -oP 'Objects found: \K\d+' || echo 0)

echo "$opus"
echo "$g722"
echo "$alaw"
echo "$ulaw"
echo "$g729"
echo "$total"

asterisk_endpoint.sh

command_output=$(asterisk -rx 'pjsip show endpoints')

avail=$(echo "$command_output" | grep 'Avail' | (wc -l))
total=$(( $(echo "$command_output" | grep -c 'Endpoint') - 1 ))

echo "$avail"
echo "$total"

Saved, they need to be made executable, add the execute flag to each file…

chmod +x /usr/local/asterisk_chan.sh
chmod +x /usr/local/asterisk_chanstat.sh
chmod +x /usr/local/asterisk_endpoint.sh

SNMP extend_sh

SNMP has an extension feature to add and poll your own custom data, to take advantage of this the snmp.d.conf file need to include reference and path to the scripts. At the bottom of snmpd.conf, add the following lines…

extend-sh asterisk_chan /usr/local/share/snmp/rps/asterisk_chan.sh
extend-sh asterisk_chanstat /usr/local/share/snmp/rps/asterisk_chanstat.sh
extend-sh asterisk_endpoint /usr/local/share/snmp/rps/asterisk_endpoint.sh

Restart snmpd to load changes…

Gentoo:

/etc/init.d/snmpd restart

RHEL:

systemctl restart snmpd

Testing

Using snmpget command locally or on your collector machine, test that its working..

snmpget -c }your-community} -v 2c {ip-address} 'NET-SNMP-EXTEND-MIB::nsExtendOutLine."asterisk_chan".1'

Where “asterisk_chan” is the name of the extend_sh created in snmpd.conf file, and .1 on the end collates to the line of script output, .2 returns the second line and so on.

Add to monitoring

When adding to your monitoring system, in this example Zabbix, use the command listed in the testing phase to grab the values…

Logging and monitoring is now enabled for the Asterisk service…

]]>
Yealink OpenVPN to Draytek Router https://james-batchelor.com/index.php/2022/11/13/yealink-openvpn-to-draytek-router/ Sun, 13 Nov 2022 17:12:20 +0000 https://james-batchelor.com/?p=839 Continue reading "Yealink OpenVPN to Draytek Router"]]> The firewalls in front of our PBX’s are configured to only allow SIP traffic from UK IP addresses, this reduces the attack surface and is usually not an issue as almost all legitimate traffic is from the UK.

As we expand there is greater need for international connections, this is fine if they have a static WAN IP or FQDN, but the more recent requirements are for “home” users with phones on their residential connections where dynamic IPs are the standard.

Changing the whitelisted IP every time their IP changes is not only tedious, but gives poor service, plus due to recent events (here and here) I’m not prepared to open access to another country for a single extension.

In my case, these internationals are satellites of a UK based office, so the idea is having the overseas phone route all voice traffic through the UK office where its free to connect to the PBX…

For this setup, a Yealink T46S will connect to a Draytek 2927 via OpenVPN and crucially, route all traffic destined for the PBX via the VPN to get around the GeoIP block.

This guide should also be compatible with the Draytek 2865, and Yealink T4xS and T4xU series phones.

Notepad++ and 7zip are required.

Draytek Setup

Original Guide: https://www.draytek.com/support/knowledge-base/7462

First create a user for the Yealink, at the router GUI navigate to: VPN and Remote Access >> Remote Dial-in User.

Click an Index number and make the following changes:

  • Enable this account: On
  • Allowed Dail-In Type: OpenVPN Tunnel: On
  • Username: Enter a username
  • Password: Enter a password

It should look like this:

Next is to setup the Draytek to accept OpenVPN connections.

Navigate to VPN and Remote Access >> Remote Access Control. And check OpenVPN is enabled.

Then navigate to VPN and Remote Access >> OpenVPN >> OpenVPN Server Setup.

In the General Certificates section, select Router Generated Certificates, and then press generate.

After some time, the generated certificates appear in this section:

OpenVPN Setup

The Draytek has the ability to create an OpenVPN config file for clients. However, what the Draytek generates and what the Yealink requires is not compatible. Therefore, we’ll need to manipulate the file to file to get what we want.

Extracting Certificates

On the Draytek, navigate to Remote Access >> OpenVPN >> Client Config.

Leaving defaults in place, enter a filename and click the Export button to download the config file.

Open the file in Notepad++.

You’ll see the protocol config at start of file, followed by each of the certificates in the following order:

  1. CA
  2. Client
  3. Private Key

The Yealink requires the certificates in their own file so they need to be extracted.

Copy the text from —–BEGIN CERTIFICATE—– to —–END CERTIFICATE—– of the first certificate and paste into a new Notepad++ file.

Save this file as ca.crt (remove the txt file extension)

Repeat this for the second certificate, naming this one client.crt

Now it’s the private key, copy text from —–BEGIN RSA PRIVATE KEY—– to —–END RSA PRIVATE KEY—– to a new file and save as client.key

Config files

For the next file, you’ll need to add the Draytek VPN user details as a file to allow the Yealink to authenticate.

In a new text file, enter the username and password on separate lines as below:

Save the file as auth.txt

You’ll now have the following files:

With the supporting files ready, it’s time to reference them together with the OpenVPN config file.

In a new text file, enter the following info:

client
dev tun
proto udp
remote nnn.nnn.nnn.nnn 1194                  # IP address of Draytek
auth sha256
cipher aes-256-cbc
resolv-retry infinite                        # Reconnect if dropped
nobind

ca /config/openvpn/keys/ca.crt
cert /config/openvpn/keys/client.crt
key /config/openvpn/keys/client.key

auth-user-pass /config/openvpn/keys/auth.txt

persist-key
persist-tun

route nnn.nnn.nnn.nnn 255.nnn.nnn.nnn nnn.nnn.nnn.nnn  # Static route:
                                                       # PBX IP
                                                       # IP Subnet
                                                       # Draytek LAN Gateway
verb 5

Save this as vpn.cnf

Preparing Yealink File

Original Guide: https://support.yealink.com/forward2download?path=ZIjHOJbWuW/DFrGTLnGypjZRKhDplusSymbolXJQ4JaUSvKXmAoZw0rMev5uUPSPDoclfqojerLoiDU/Ol0NW5DZdXcWplusSymbolZDNbde0dvqwZjDVChAjsaqHDjPW14991UaBvXhQ10P6Rm4u3tO4pNBqXRzzyvj9PbA==

The OpenVPN configuration is uploaded to the Yealink via a specifically arranged tar file, so the directory structure needs to be prepared.

On your desktop, create a new folder (named anything you like) and within this folder create another named “keys”

Move vpn.cnf to the upper folder, and move auth.txt, ca.crt, client.crt and client.key to keys directory.

Open 7-Zip and navigate to the newly created folder:

Highlight vpn.cnf and keys, right click and choose 7-Zip >> add to archive.

Ensure the following is set:

  • Archive format: tar
  • Compression level: Store

Click OK to create the file. The tar file is created in the directory and it’s ready to be uploaded to the Yealink

Yealink Setup

On the phone, press the OK key to discover it’s IP address, then navigate to it’s Web interface via a browser on your computer.

Login, then move to Network >> Advanced and scroll down to the VPN section.

Set Active to Enabled and set Mode to OpenVPN

Click browse next to Upload VPN Config and choose the created tar file.

Click Upload, the page will refresh and now Upload VPN Config is populated with vpn.cnf

Click Save at the bottom of the page.

OpenVPN will be set back to Disabled, scroll down and Enable it again, then click Save.

As there’s a network change pending, you’ll need to click apply at the warning message:

It’ll now connect to the VPN.

Note: If you are configuring a phone remotely, the web page will stop responding as traffic is now passing through the VPN. To get back to the interface, check the Draytek for the VPN connection (VPN and Remote Access >> Connection Management) to discover it’s local IP:

The phone is now connected and routing traffic via the VPN.

]]>
Testing a New PBX https://james-batchelor.com/index.php/2020/02/22/testing-a-new-pbx/ Sat, 22 Feb 2020 21:32:52 +0000 http://james-batchelor.com/?p=648 Continue reading "Testing a New PBX"]]> Recently I’ve had the opportunity to deploy and test a call centre PBX product to gauge if its viable to offer as a product and how it will sit within our infrastructure.

Installing and poking around the GUI is all well and good but to really find out how a PBX behaves it needs some traffic, to find outs its performance in regards to resources but also to find out what a vendor’s interpretation of an advertised feature actually is.

To generate sample calls, instead of registering handsets/softphones and dialling manually it would be better to automate this, and SIPp is the perfect tool for this.

SIPp is an open source SIP testing tool for stress testing PBX’s, but it can also be used more modestly so it can generate more real-world scenarios to simulate typical calls. This can also be beneficial when testing and reviewing complex call flows through a system before deploying.

Environment

In this example I would be using a local CentOS 7 Virtual Machine to host the SIPp application, with the PBX sitting remotely and network access via VPN for the testing period.

The PBX will also have a trunk set to allow calls in from the CentOS box and a DDI assigned.

Installation

Installation on CentOS is easiest via yum and the EPEL repositories.

From a clean install run:

yum update
yum install epel-release
yum install sipp

Operation

Once installed its as easy to run as running the program from the command line, but getting the results you are looking for requires a lot of switches and a scenario file.

SIPp in action

The simplest way to look at this is the switches take care of the targeting and rate of the calls, where the scenario file simulates the calling person, and can be set to imitate speech (RTP streams), dtmf inputs and even introduce packet loss to measure quality of calls. Essentially a profile of a call is contained within the scenario file.

As an example, this is a typical command I use for testing a very modest call load:

sipp -sf file.xml -trace_err -trace_msg -i 10.20.30.40 -r 1 -rp 10000 -l 100 -m 50 -s 12345678901 10.100.100.100

To break down this command and make it more understandable:

  • -sf {FILENAME} – Scenario file.
  • -trace_err – Print errors to file, for troubleshooting.
  • -trace_msg – Print verbose log to file, for troubleshooting.
  • -i {IPADDRESS} – RTP stream (Audio) source.
  • -r {NUMBER} – Call Rate – Rate that calls are attempted.
  • -rp {NUMBER} – Rate Period – Number defined in Call Rate are spread over the Rate Period.
  • -l {NUMBER} – Max number of concurrent calls.
  • -m {NUMBER} – Total number of calls to attempt.
  • -s {NUMBER}- SIP number to dial and server.
  • “10.100.100.100” – PBX server IP

Scenario File

As mentioned, the scenario file contains the simulation of a call from a calling party.

SIPp has a number of template scenario files in XML format available on their Sourceforge page, these can be download and modified as needed.

For example, below is my modification of the uac_pcap.xml template, this is a simple file that connects and plays an RTP stream (from a pcap file) for two minutes before hanging up:

  <scenario name="UAC with media">
<!-- CALL SETUP         -->
  <send retrans="500">
    <![CDATA[
 
      INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
      From: 01234567890 <sip:01234567890@[local_ip]:[local_port]>;tag=[call_number]
      To: sut <sip:[service]@[remote_ip]:[remote_port]>
      Call-ID: [call_id]
      CSeq: 1 INVITE
      Contact: sip:sipp@[local_ip]:[local_port]
      Max-Forwards: 70
      Subject: Performance Test
      Content-Type: application/sdp
      Content-Length: [len]
 
      v=0
      o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
      s=-
      c=IN IP[local_ip_type] [local_ip]
      t=0 0
      m=audio [auto_media_port] RTP/AVP 8
      a=rtpmap:8 PCMA/8000
      a=rtpmap:101 telephone-event/8000
      a=fmtp:101 0-11,16
 
    ]]>
  </send>
 
  <recv response="100" optional="true">
  </recv>
 
  <recv response="180" optional="true">
  </recv>
 
  <send>
    <![CDATA[
 
      ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
      From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
      To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
      Call-ID: [call_id]
      CSeq: 1 ACK
      Contact: sip:sipp@[local_ip]:[local_port]
      Max-Forwards: 70
      Subject: Performance Test
      Content-Length: 0
 
    ]]>
  </send>
  <!-- PLAY RTP STREAM         -->
  <nop>
    <action>
        <exec play_pcap_audio="pcap/g711a_600.pcap"/>
    </action>
  </nop>
 
  <!-- SET CALL LENGTH                                                        -->
  <pause milliseconds="120000"/>
 
  <send retrans="500">
    <![CDATA[
 
      BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
      From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
      To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
      Call-ID: [call_id]
      CSeq: 2 BYE
      Contact: sip:sipp@[local_ip]:[local_port]
      Max-Forwards: 70
      Subject: Performance Test
      Content-Length: 0
 
    ]]>
  </send>
 
  <recv response="200" crlf="true">
  </recv>
 
  <!-- definition of the response time repartition table (unit is ms)   -->
  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
 
  <!-- definition of the call length repartition table (unit is ms)     -->
  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
 
</scenario>

Personal Observations

This is a great tool for automation in the testing phase of a new platform deployment, and you can easily generate calls in numbers considered unfeasible when using traditional desk and soft phones, plus this method allows all phones in the test bed to become call recipients, increasing the user base to more accurately test a platform.

In addition to the PBX this tool also tests the network that provides connectivity to the phone system, this was highlighted to me when testing with traffic going over a VPN, and discovered that the VPN gateway could not cope with more than 10 concurrent calls despite having enough bandwidth available.

As a final note I recommend to start a test with minimal call volume ad scale from there. Whilst SIPPp can simulate calls, these aren’t as organic as the real world. I managed to knock a live system offline with as little as 100 generated calls, due in part to 100 SIP invites being sent within one second.

Oh, and don’t introduce a load of test calls to a flow where the final destination is a voicemail, I found that out the hard way!

]]>