Over the last few weeks and possibly going on for a few more Gamma Telecom are migrating users from their MSX SBCs to their ‘new’ SWe SBCs, and as side effect of this change is that they now do not support non-symetrical nat translation of RTP traffic
Their previous SBCs and like many other carriers do not have an issue with this and in the words of Twilio’s notes below they support both methods
** When Symmetric RTP is enabled Twilio will detect where the remote RTP stream is coming from and start sending RTP to that destination instead of the one negotiated in the SDP. Please note that this setting is more vulnerable to RTP attacks.
When Symmetric RTP is disabled, Twilio will send RTP to the destination negotiated in the SDP. This setting is considered to be more secure and therefore recommended.
On making support calls to Gamma initially they just seem to tell users that the RTP is being sent from a port that isn’t specified in the SDP, and yes that is correct, But Gamma being Gamma and even though they will have had numerous calls they don’t go any further
It seems the problem is with the customer firewalls in particular pfSense:
By default, pfSense software rewrites the source port on all outgoing connections except for UDP port 500. Some operating systems do a poor job of source port randomization, if they do it at all. This makes IP address spoofing easier and makes it possible to fingerprint hosts behind the firewall from their outbound traffic. Rewriting the source port eliminates these potential (but unlikely) security vulnerabilities. Outbound NAT rules, including the automatic rules, will show in the Static Port column on rules set to randomize the source port.
Source port randomization breaks some rare applications. The default Automatic Outbound NAT ruleset disables source port randomization for UDP 500 because it will almost always be broken by rewriting the source port. Outbound NAT rules which preserve the original source port are called Static Port rules and have on the rule in the Static Port column. All other traffic has the source port rewritten by default.
To add a rule for a device which requires static source ports:
Navigate to Firewall > NAT, Outbound tab
Select Hybrid Outbound NAT rule generation
Click Save
Click to add a new NAT rule to the top of the list
Configure the rule to match the traffic that requires static port, such as a source address of a PBX.
Check Static Port in the Translation section of the page
Click Save
Click Apply Changes
After making that change, the source port on outgoing traffic matching the rule will be preserved. **The best practice is to use strict rules when utilizing static port to avoid any potential conflict if two local hosts use the same source port to talk to the same remote server and port using the same external IP address.**
Personally I would just make this change for the UDP port range and not all UDP ports as this could cause problem with traffic such a port 5060 when multiple servers or phones are on a site.
We have also been made aware of another issue with respect to call diversion to external numbers. By deafault Asterisk and many other IP PBXs set a diversion header in the 181 message giving the device that diverted the call and reason. in most cases this will be the extension number so the header will look like:
This seems to cause issues at Gamma and they reject the call as it seems they are setting the callerid from this info.
To overcome this issue for chan_sip set ‘send_diversion = no’ in the general setting of sip.conf or in the “Other SIP Settings” fields in the Advanced sip setting menu. For PJSIP add it to the pjsip.endpoint_custom_post.conf file as below.
To be honest we have only seen the problem with Gamma trunks and having tested with other suppliers and found they are not affected.
Gammas reson for this is as follows: “After reviewing the divert packet, I can see in the message header that the Diversion header is set to divert to “477”. I would recommend to change this to the full CLI you wish to forward the call to as I believe the system is trying to call “477” which wouldn’t be classed as a valid number. The 603 error you are seeing from your side would be in relation to OFCOMS national number length violation.”
See the Packet below
Session Initiation Protocol (181)
Status-Line: SIP/2.0 181 Call is being forwarded
Status-Code: 181
[Resent Packet: False]
[Request Frame: 22149]
[Response Time (ms): 187]
Message Header
Via: SIP/2.0/UDP xxx.yyy.aaa.zzz:5060;branch=z9hG4bK04B82da620259a59a1a;received=xxx.yyy.aaa.zzz;rport=5060
Transport: UDP
Sent-by Address: xxx.yyy.aaa.zzz
Sent-by port: 5060
Branch: z9hG4bK04B82da620259a59a1a
Received: xxx.yyy.aaa.zzz
RPort: 5060
From: <sip:01234567890@xxx.yyy.aaa.zzz>;tag=gK0441ee4f
SIP from address: sip:01234567890@xxx.yyy.aaa.zzz
SIP from tag: gK0441ee4f
To: <sip:07890123456@aaa.bbb.ccc.ddd>;tag=as24643c1b
SIP to address: sip:07890123456@aaa.bbb.ccc.ddd
SIP to tag: as24643c1b
Call-ID: 71571273_130153708@xxx.yyy.aaa.zzz
[Generated Call-ID: 71571273_130153708@xxx.yyy.aaa.zzz]
CSeq: 321899 INVITE
Sequence Number: 321899
Method: INVITE
Server: FPBX-16.0.40.7(18.9)
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Session-Expires: 1800;refresher=uas
Contact: <sip:07890123456@aaa.bbb.ccc.ddd:5060>
Contact URI: sip:07890123456@aaa.bbb.ccc.ddd:5060
Contact URI User Part: 07890123456
Contact URI Host Part: aaa.bbb.ccc.ddd
Contact URI Host Port: 5060
Diversion: <sip:477@aaa.bbb.ccc.ddd>;reason=unconditional
Content-Length: 0
Now the RFC says :
“When a diversion occurs, a Diversion header SHOULD be added to the forwarded request or forwarded 3xx response. The Diversion header MUST contain the Request-URI of the request prior to the diversion. The Diversion header SHOULD contain a reason that the diversion occurred.”
Which is what happens, Gamma seem to have confused what the diversion header does as they seem to assume its setting the diversion destination or outbound caller ID, Neither of which are the uses for the Diversion header.
‘I will add updates here as and when they become available.’
Before diving into the installation and configuration, it’s better to know some terms used in LDAP.
Attribute
An attribute is a characteristic of an object. For example, an email of an account.
Object Class
An object class defines what attributes that object can have. For example, we define an object class, InetOrgPerson, it may contain displayName and mail attributes. Depends on the definition of object class, the attributes specified can be mandatory or optional.
Distinguished Name (DN)
Distinguished Name lets us uniquely identify the object. It is similar to the file path in a reverse order. For example, uid=JohnDoe,OU=People,DC=abc,DC=local is a DN
Entry
An entry is just an object. You define what object class this entry belongs to & each object class defines what attributes this object has. Each entry can belong to multiple object classes and need to have all mandatory attributes specified in all object classes it belongs to.
Schema
A schema contains the definitions of various attributes and object classes.
Domain Component (DC) & Organizational Unit (OU)
They are containers, contains object & let you manage objects in a hierarchy manner. People use them commonly.
OpenLDAP Installation
Install OpenLDAP related packages
sudo yum install openldap* -y
sudo systemctl start slapd
sudo systemctl enable slapd
sudo systemctl status slapd # Check service is started & enabled
● slapd.service - OpenLDAP Server Daemon
Loaded: loaded (/usr/lib/systemd/system/slapd.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2023-10-17 11:20:41 BST; 1 weeks 0 days ago
Docs: man:slapd
man:slapd-config
man:slapd-hdb
man:slapd-mdb
file:///usr/share/doc/openldap-servers/guide.html
Main PID: 1922 (slapd)
CGroup: /system.slice/slapd.service
└─1922 /usr/sbin/slapd -u ldap -h ldapi:/// ldap:///
Oct 24 16:46:06 testsystem.myserver.co.uk slapd[1922]: conn=1604 fd=22 ACCEPT from IP=192.168.1.202:45777 (IP=0.0.0.0:389)
Oct 24 16:46:06 testsystem.myserver.co.uk slapd[1922]: conn=1604 op=0 BIND dn="" method=128
Oct 24 16:46:06 testsystem.myserver.co.uk slapd[1922]: conn=1604 op=0 RESULT tag=97 err=0 text=
Oct 24 16:46:06 testsystem.myserver.co.uk slapd[1922]: conn=1604 op=1 SRCH base="dc=abc,dc=local" scope=2 deref=0 filter="(|(cn=*)(sn=*))"
Oct 24 16:46:06 testsystem.myserver.co.uk slapd[1922]: conn=1604 op=1 SEARCH RESULT tag=101 err=0 nentries=13 text=
Oct 24 16:46:06 testsystem.myserver.co.uk slapd[1922]: conn=1604 op=2 UNBIND
Oct 24 16:46:06 testsystem.myserver.co.uk slapd[1922]: conn=1604 fd=22 closed
Oct 24 16:46:49 testsystem.myserver.co.uk slapd[1922]: conn=1530 op=21 SRCH base="dc=abc,dc=local" scope=2 deref=0 filter="(cn=*)"
Oct 24 16:46:49 testsystem.myserver.co.uk slapd[1922]: conn=1530 op=21 SRCH attr=givenName title wWWHomePage telephoneNumber
Oct 24 16:46:49 testsystem.myserver.co.uk slapd[1922]: conn=1530 op=21 SEARCH RESULT tag=101 err=0 nentries=13 text=
OpenLDAP Configuration
Generate OpenLDAP password and save it
sudo slappasswd
Then, we will use ldapmodify to update /etc/openldap/slapd.d/cn=config/olcDatabase={2}hdb.ldif, which is our database config fileWe will create a file & customize and paste content below
vi db.ldif
Content you should paste: You should replace with your customized values
olcSuffix (should be replaced by your domain, e.g. example.com -> dc=example,dc=com)
olcRootDN (should be replaced by your domain admin name, can be any name you prefer, e.g. admin -> cn=admin,dc=abc,dc=local)
olcRootPW (should be the password you generate above)
Apply some commonly used schema. The 2nd & 3rd schema allow us to create an object with InetOrgPerson & ShadowAccount which we will use to create an user
Now the code. I accept no responsibility for it, Its a mess but it does what it says. There is bound to be a better way but with the timescale I had i needed something quick and as such its dirty. each section is distinct so shouldnt be hard to clean up.
The file fpbxldap.sh
#!/bin/bash
#Script file to add delete and modify ladp database for freeepbx contact manager
#Copyright (C) 2023 Ian Plain Cyber-cottage.co.uk
#
#This program is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public License
#as published by the Free Software Foundation; either version 2
#of the License, or (at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
source fldapconfig.sh
# LDAP Entry Details
#BASE_DN="dc=abc,dc=local"
#BASE_OU="ou=People"
# Search for the LDAP entries ad file them
CURRENT_TELEPHONE_NUMBER=$(ldapsearch -x -D "$LDAP_BINDDN" -w "$LDAP_BINDPW" -H "$LDAP_SERVER" -b "$BASE_OU,$BASE_DN" telephoneNumber | awk -F ',|=|: ' '/dn:/ {print $3}')
echo "$CURRENT_TELEPHONE_NUMBER" |grep -w -v "People" > /tmp/ldapdb.txt
# Query to execute
QUERY="SELECT asterisk.contactmanager_entry_numbers.number as 'telephoneNumber', asterisk.contactmanager_group_entries.displayname as 'cn', asterisk.contactmanager_group_entries.fname as 'givenName', COALESCE(NULLIF(asterisk.contactmanager_group_entries.lname, ''), '-') AS 'sn', asterisk.contactmanager_entry_numbers.type as 'o', asterisk.contactmanager_groups.name as 'dir'
FROM asterisk.contactmanager_entry_numbers
INNER JOIN asterisk.contactmanager_group_entries ON asterisk.contactmanager_entry_numbers.entryid=asterisk.contactmanager_group_entries.id
INNER JOIN asterisk.contactmanager_groups ON asterisk.contactmanager_groups.id=asterisk.contactmanager_group_entries.groupid
WHERE asterisk.contactmanager_entry_numbers.number REGEXP '^[0-9]*$' AND asterisk.contactmanager_group_entries.displayname REGEXP '[:alpha:]'
;"
# Output file
OUTPUT_FILE="/tmp/fpbxdb.txt"
# Run the MySQL query and save the result to the output file
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" -N -e "$QUERY" | sed 's/\t/,/g' > "$OUTPUT_FILE"
#Split out just the names
cat /tmp/fpbxdb.txt |awk -F ',' '{print $2" - "$5}' > /tmp/fpxname.txt
cat /tmp/fpbxdb.txt |awk -F ',' '{print $2" - "$5","$1}' > /tmp/fpxnumna.txt
# Assign filenames to variables
listB_file="/tmp/ldapdb.txt"
listA_file="/tmp/fpxname.txt"
# Check if the files exist
if [ ! -f "$listA_file" ]; then
echo "File $listA_file does not exist."
exit 1
fi
if [ ! -f "$listB_file" ]; then
echo "File $listB_file does not exist."
exit 1
fi
#Bit of a hack here that adds an entry to empty file, as AWK doesnt like empty files.. Thsi was quick a fix
if [ -s "$listA_file" ]; then
echo "The file is not empty."
else
echo "foobar" > /tmp/fpxname.txt
fi
if [ -s "$listB_file" ]; then
echo "The file is not empty."
else
echo "barfoo" > /tmp/ldapdb.txt
fi
# Compare the two files and echo names in List A but not in List B
awk 'NR==FNR{a[$0]++; next} !a[$0]' "$listB_file" "$listA_file" > /tmp/add.txt
awk 'NR==FNR{a[$0]++; next} !a[$0]' "$listA_file" "$listB_file" > /tmp/rem.txt
#lets delete the entries
# Loop through each line in the input file and run the command
while IFS= read -r REM_FILTER; do
# Run the specified command on each line
echo "$REM_FILTER deleted from Ldap" >> /tmp/remlog.txt
ldapdelete -x -D "$LDAP_BINDDN" -w "$LDAP_BINDPW" -H "$LDAP_SERVER" "cn=$REM_FILTER,$BASE_OU,$BASE_DN"
done < "$rem_file"
echo "Done-------" >> /tmp/remlog.txt
#delete the previous ldif files
rm -f /tmp/adding.ldif
rm -f /tmp/modify.ldif
#lets add the entries
# Loop through each line in the input file and run the command
while IFS= read -r ADD_FILTER; do
# Run the specified command on each line
# echo $ADD_FILTER |awk -F ' - ' '{print $1; print $2}'
ms_cn="$(echo $ADD_FILTER |awk -F ' - ' '{print $1}')"
ms_o="$(echo $ADD_FILTER |awk -F ' - ' '{print $2}')"
# Query to execute
QUERY="SELECT asterisk.contactmanager_entry_numbers.number as 'telephoneNumber', COALESCE(NULLIF(asterisk.contactmanager_group_entries.lname, ''), '-') AS 'sn'
FROM asterisk.contactmanager_entry_numbers
INNER JOIN asterisk.contactmanager_group_entries ON asterisk.contactmanager_entry_numbers.entryid=asterisk.contactmanager_group_entries.id
INNER JOIN asterisk.contactmanager_groups ON asterisk.contactmanager_groups.id=asterisk.contactmanager_group_entries.groupid
WHERE asterisk.contactmanager_entry_numbers.type = '$ms_o' AND asterisk.contactmanager_group_entries.displayname = '$ms_cn'
;"
# Run the MySQL query and save the result to the output file
ms_query=$(mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" -N -e "$QUERY")
ms_telephoneNumber=$(echo $ms_query | awk '{print $1}')
ms_sn=$(echo $ms_query | awk '{print $2}')
echo "dn: cn=$ms_cn - $ms_o,ou=People,dc=abc,dc=local" >> /tmp/adding.ldif
echo "cn: $ms_cn - $ms_o" >> /tmp/adding.ldif
echo "givenName: $ms_cn - $ms_o" >> /tmp/adding.ldif
echo "sn: $ms_sn" >> /tmp/adding.ldif
echo "telephonenumber: $ms_telephoneNumber" >> /tmp/adding.ldif
echo "objectclass: inetOrgPerson" >> /tmp/adding.ldif
echo "objectclass: top" >> /tmp/adding.ldif
echo "" >> /tmp/adding.ldif
echo "cn: $ms_cn - $ms_o , $ms_telephoneNumber added to Ldap" >> /tmp/addlog.txt
done < "$add_file"
#Lets run the ldif command
ldapadd -x -D "$LDAP_BINDDN" -w "$LDAP_BINDPW" -H "$LDAP_SERVER" -f /tmp/adding.ldif >> /tmp/addlog.txt
echo "Done-------" >> /tmp/addlog.txt
#OK now we are going to compare freepbx and ldap entries and update as required.
#lets get the current ldap names and numbers
ldapsearch -x -D "cn=admin,dc=abc,dc=local" -w "r1v3rp1g5" -b "ou=People,dc=abc,dc=local" | awk -v OFS=',' '{split($0,a,": ")} /^cn:/{cn=a[2]} /^telephoneNumber:/{telephoneNumber=a[2]; print cn,telephoneNumber}' > /tmp/ldapcsv.txt
awk 'NR==FNR{a[$0]++; next} !a[$0]' /tmp/ldapcsv.txt /tmp/fpxnumna.txt > /tmp/chg.txt
chg_file="/tmp/chg.txt"
# Loop through each line in the input file and run the command
while IFS= read -r CHG_FILTER; do
# Run the specified command on each line
# echo $CHG_FILTER |awk -F ',' '{print $1; print $2}'
ms_cn="$(echo $CHG_FILTER |awk -F ',' '{print $1}')"
ms_telephoneNumber="$(echo $CHG_FILTER |awk -F ',' '{print $2}')"
echo "Changing telephoneNumber to $ms_telephoneNumber"
echo "dn: cn=$ms_cn,$BASE_OU,$BASE_DN" >> /tmp/modify.ldif
echo "changetype: modify" >> /tmp/modify.ldif
echo "replace: telephoneNumber" >> /tmp/modify.ldif
echo "telephoneNumber: $ms_telephoneNumber" >> /tmp/modify.ldif
echo "" >> /tmp/modify.ldif
echo "$CHG_FILTER changed in Ldap" >> /tmp/chglog.txt
done < "$chg_file"
ldapmodify -x -D "$LDAP_BINDDN" -w "$LDAP_BINDPW" -H "$LDAP_SERVER" -f /tmp/modify.ldif >> /tmp/modify.ldif
echo "Done-------" >> /tmp/chglog.txt
Example phone configurations for Sangoma S series and Gigaset.
Gigaset example
Sangoma S Series example
Im sure this will work with other systems that support Ldap directories
UK regulators have implemented changes to help reduce smishing and SMS fraud incidents.
As a reminder, effective immediately, application-to-person (A2P) SMS messages sent to the UK from Alphanumeric Sender IDs that contain special characters will be blocked.
The following characters are allowed:
A to Z (upper and lowercase)
0 to 9
– (dash)
_ (underscore)
‘ ‘ (space)
& (ampersand)
Any special characters outside of the list above will be blocked (example: “+” or “@”).
Effective October 31, 2023, application-to-person (A2P) SMS messages sent to the UK from the following list of generic Alphanumeric Sender IDs will be blocked.
Note: Combinations of these generic Alphanumeric Sender IDs are allowed (for example, “Smith Bank” or “Border Control” are both allowed.
1TimePin
2FA
Accept
Access
Account
Active
Admin
Advise
Alert
Allow
Allowance
App
Appointment
Approve
Approved
Auth
AuthMSG
Authorise
AuthSMS
Aware
Bank
Banking
Bill
Billing
Call
Card
Caution
Certify
Check
CloudOTP
Code
Collect
Collection
Confirm
Contact
Control
Courier
Delay
Deliver
Delivery
Discount
Energy
Fraud
Help
Info
InfoSMS
ISA
Key
Loan
Login
Logistics
LogMeIn
Logon
Malware
Message
Mobile
Mortgage
MSG
MsgAuth
Network
NoReply
Notify
OneTimePin
Order
OTP
OTPSMS
Package
Parcel
Pay
Payment
Pin
PinCode
Post
Protocol
Purchase
Ratify
Rebate
Receipt
Refund
Reminder
Repayment
Reply
Respond
Save
Saving
Savings
Scam
Schedule
Secure
Security
Service
Shipping
Sign
Signin
Signon
SMS
SMSAuth
SMSCode
SMSInfo
SMSOTP
SMSVerify
Support
System
Text
Trace
Track
Tracking
Trust
TXT
Update
Updates
Validate
Verify
VerifySMS
VerifyMe
Virus
Warn
Warning
Winner
What do you need to do?
Avoid using special characters in your Alphanumeric Sender IDs and use a non-generic Alphanumeric Sender ID to send messages in the UK to avoid message disruption following the steps below:
If you’re using a Messaging Service, update your generic Alphanumeric Sender ID by reviewing your suppliers guide on Using Alphanumeric Sender ID with Messaging Services.
If you’re specifying your Alphanumeric Sender ID directly in your API request, update the “From” parameter in your application code with a non-generic Alphanumeric Sender ID.
What if you don’t take action?
There’s no action for you to take. SMS messages sent to the UK from generic Alphanumeric Sender IDs or Sender IDs that contain special characters will be blocked and return an error code.
For this project we are going to use the Amazon AWS Transcribe service, AWS Transcribe is a cloud-based speech recognition service that converts audio recordings into accurate text transcripts. It uses advanced machine learning algorithms to identify different speakers and punctuation, while also supporting a variety of audio formats and languages. AWS Transcribe can transcribe audio from sources such as phone calls, video recordings, and live streams, making it a versatile tool thats idealy suited for voicemail transcription, The service is highly scalable and cost-effective.
We will say that we used to use Google’s Text to speech engine for thsi but over time I would have expected quality of transcription to have improved, But with Google this is not the case, and I expect this is because they possibly use “predictive” text to speech and not sample all the words as this example below shows, This is the same audio fed to Google and AWS
Amazon AWS Transcribe
Um, this is Ian. I’d like to order some pizza for tomorrow, please. We would like to order a pepperoni pizza and a mozzarella pizza that’s for tomorrow at five PM. Thank you.
Google Speech to Text
like to order some pizza for tomorrow please would like to order a pepperoni pizza and a mozzarella Pizza Hut for tomorrow at 5 a.m. thank you
As can be seen google misses words and adds others, As you can imagine this isnt what you want with speech transcription.
So we have switched out old script to use AWS.
For this project on Freepbx you need a few extra applications added and a amazon aws account, setting this up is not covered here as you should already have knowledge of this if you are here.
The extra apps are , aws , jq , sox
to get aws :
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip -qq awscliv2.zip
./aws/install
Then you need to configure as 'root' and as 'asterisk', so:
aws configure
fill out your aws key and token as well as the region your bucket is in
Then repeat as 'asterisk' so
su asteriskaws configure
and fill out same details.
for jq and sox, just yum install xxx as you would for any other program.
Next you need the asterisk dialplan added to the extensions_custom.conf
as can be seen this dialplan records a file and then runs the vmailprox.sh script. This script collects the variables and passes them over to the main script and exits after doing so, this is so channels aren’t held while transcription takes place. (Thats the plan anyway)
#!/bin/sh
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
S3_BUCKET="YOURS3BUCKET"
DIRPATH=/var/spool/asterisk/voicemail/default/
#callerchan=$1
#callerid=$2
#origdate=$3
#origtime=$4
#origmailbox=$5
#origdir=$6
#duration=$7
counter=1
sleep 4
FILENUM=$(/bin/ls ${DIRPATH}${origmailbox}/INBOX |/bin/grep txt | /usr/bin/wc -l)
##Added to allow 999 messages
if (( $FILENUM <= 9 ));
then
FILENAME=msg000${FILENUM}
elif (( $FILENUM <= 99 ));
then
FILENAME=msg00${FILENUM}
else
FILENAME=msg0${FILENUM}
fi
IN=$(/bin/grep "${origmailbox}=" /etc/asterisk/voicemail.conf)
set -- "$IN"
IFS=","; declare -a Array=($*)
email=${Array[2]}
/bin/echo "[message]" >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo origmailbox=${origmailbox} >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "context=demo" >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "macrocontext=" >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "exten=s" >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "priority=11" >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo callerchan=${callerchan} >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo callerid=${callerid} >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo origdate=${origdate} >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo origtime=${origtime} >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo msg_id=${origtime}-00000001 >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "flag=" >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "category=" >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/echo "duration=${duration}" >> ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.txt
/bin/nice /usr/bin/lame -b 16 -m m -q 9-resample /var/lib/asterisk/sounds/catline/${origdir}.wav /tmp/${origdir}.mp3
# Create a string based on the current date and time
current_date_time="$(date +%Y-%m-%d_%H-%M-%S)"
# Upload to the S3 Bucket
aws --debug --profile default s3 cp /tmp/${origdir}.mp3 s3://$S3_BUCKET/$current_date_time
# Start the transcription job
output=$(aws --profile default transcribe start-transcription-job \
--transcription-job-name $current_date_time \
--language-code en-GB \
--media-format mp3 \
--media MediaFileUri=s3://$S3_BUCKET/$current_date_time \
--output-bucket-name $S3_BUCKET)
# Wait for the transcription to finish
JOB_COMPLETED=false
while [ "$JOB_COMPLETED" = false ]; do
JOB_STATUS=$(aws --profile default transcribe get-transcription-job \
--transcription-job-name $current_date_time \
--query 'TranscriptionJob.TranscriptionJobStatus' \
--output text)
if [ "$JOB_STATUS" = "FAILED" ]; then
JOB_COMPLETED=true
SHORT_CALL=yes
/bin/echo "$JOB_STATUS" >> /tmp/logfile.txt
break
fi
if [ "$JOB_STATUS" = "COMPLETED" ]; then
/bin/echo "$JOB_STATUS" >> /tmp/logfile.txt
JOB_COMPLETED=true
else
((counter++))
sleep 5
echo $counter >> /tmp/logfile.txt
/bin/echo "$JOB_STATUS" >> /tmp/logfile.txt
if [ "$counter" -eq "15" ]; then
JOB_STAUS=COMPLETED
JOB_COMPLETED=true
SHORT_CALL=yes
break
fi
fi
done
# Get the transcription result
aws s3 --profile default cp s3://$S3_BUCKET/$current_date_time.json /tmp/$current_date_time.json
# Get the transcription result
FILTERED=$(jq -r '.results.transcripts[].transcript' /tmp/$current_date_time.json)
# append result of transcription
if [ -z "$FILTERED" ]
then
echo "(AWS was unable to recognize any speech in audio data.)" >> /tmp/${origdir}.txt
else
echo "$FILTERED" >> /tmp/${origdir}.txt
sed -i 's/ Um,/ /gI' /tmp/${origdir}.txt
fi
voicemailbody=$(cat "/tmp/${origdir}.txt")
# echo "body ${voicemailbody}"
/bin/cp /var/lib/asterisk/sounds/catline/${origdir}.wav ${DIRPATH}${origmailbox}/INBOX/${FILENAME}.wav
echo -e "You have a new voicemail from ${callerid} it was left on ${origdate} and is ${duration} seconds long,\nThe message left,\n\n${voicemailbody}\n\nTranscribed by the Amazon AWS Transcribe service\n" | /bin/mail -s "A new voicemail has arrived from ${callerid}" -a "/tmp/${origdir}.mp3" "$email"
/bin/rm -f /tmp/${origdir}.mp3
/bin/rm -f /tmp/${origdir}.txt
aws --profile default transcribe delete-transcription-job --transcription-job-name $current_date_time
Then to pass calls to this and not normal voicemail, In Freepbx create a Custom Destination as “vmail2text,s,1” and if you require certain queues to go to specific mailboxes for example 2000 one like “vmail2text,2000,1” so calls will be sent to mailbox 2000 and teh transcriptions will be sent to the email address linked to that extension
Then in extensions that want to use transcription set the “Optional Destinations” in the advanced tab to the custom destination.
Users also can listen to voicemail normally from their handset or the ucp.
These scripts arent only useful for voicemail then can be used fro questionnaire lines and booking lines, anywhere you want to speed up the handling of voice messages. We will soon be looking at ways of integrating this with Whatsapp so transcriptions can be sent to your mobile.
Since this post was originally written things have advanced, FreePBX has an integrated firewall with intrusion detection using Fail2Ban, and this should always be enabled even if system is on premise.
Another major step forward in protection is APIBAN this is a client program that helps prevent unwanted SIP traffic by identifying addresses of known bad actors before they attack your system. Bad bots are collected through globally deployed honeypots. To use APIBAN you will need a key these are obtained from here . More details on API ban are here if you are interested in using it in different situations.
To simplify installation on Freepbx based systems I have simple script that downloads and install it, this can be downloaded here or from the command line of the server as follows:
wget https://freeaccesspublic.s3.eu-west-2.amazonaws.com/apiban.sh
Make it an executable : chmod +x apiban.sh
then run the script : ./apiban.sh your_api_key
If you dont add your APIKEY on the command line vi will open and you can add it manually. The script will then initially run the client which will take a few seconds to download the initial set of bots, then it will add a line to the crontab file and restart the cron daemon. the timing of the cronjob is randomised to be between every 4 and 22 minutes.
We have seen many Bots attacking Asterisk servers, Interestingly its not always good old sipvicious anymore but a Windows program called sipcli and originating mainly from the US and Germany.
Normally our iptables firewalls are updated but for some reason these keep getting through, So we have now based rules on the User-Agent in iptables as well
Here are a few examples to get rid of many of the favourites
-A INPUT -p udp -m udp --dport 5060 -m string --string "User-Agent: friendly-scanner" --algo bm --to 65535 -j DROP
-A INPUT -p udp -m udp --dport 5060 -m string --string "User-Agent: sipcli" --algo bm --to 65535 -j DROP
-A INPUT -p udp -m udp --dport 5060 -m string --string "User-Agent: sipvicious" --algo bm --to 65535 -j DROP
-A INPUT -p udp -m udp --dport 5060 -m string --string "User-Agent: VaxSIPUserAgent" --algo bm --to 65535 -j DROP
For Freepbx format add following to the Firewalls custom rules
-A fpbxreject -p udp --dport 5060:5261 -m string --string "REGISTER sip:server.domain.co.uk" --algo bm -j ACCEPT
-A fpbxreject -p udp --dport 5060:5261 -m string --string "REGISTER sip:" --algo bm -j DROP
-A fpbxreject -p tcp --dport 5060:5261 -m string --string "REGISTER sip:server.domain.co.uk" --algo bm -j ACCEPT
-A fpbxreject -p tcp --dport 5060:5261 -m string --string "REGISTER sip:" --algo bm -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "sip:a'or'3=3--@" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: PolycomSoundPointIP SPIP_550 UA 3.3.2.0413" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: Avaya IP Phone 1120E" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: Cisco-SIPGateway/IOS-15.2.4.M5" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: PolycomVVX-VVX_401-UA5.4.1.18405" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: eyeBeam release 3006o stamp 17551" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: owenee" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: owenee" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: Custom" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: Custom" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: SIP" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: SIP" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: gazllove" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: gazllove" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: pplsip" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: pplsip" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: sipcli" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: sipcli" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: sipvicious" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: sipvicious" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: sip-scan" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: sip-scan" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: sipsak" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: sipsak" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: sundayddr" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: sundayddr" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: friendly-scanner" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: friendly-scanner" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: iWar" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: iWar" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: CSipSimple" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: CSipSimple" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: SIVuS" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: SIVuS" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: Gulp" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: Gulp" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: sipv" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: sipv" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: smap" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: smap" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: friendly-request" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: friendly-request" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: VaxIPUserAgent" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: VaxIPUserAgent" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: VaxSIPUserAgent" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: VaxSIPUserAgent" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: siparmyknife" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: siparmyknife" --algo bm --to 65535 -j DROP
-A fpbxreject -p udp -m udp --dport 5060:5261 -m string --string "User-Agent: Test" --algo bm --to 65535 -j DROP
-A fpbxreject -p tcp -m tcp --dport 5060:5261 -m string --string "User-Agent: Test" --algo bm --to 65535 -j DROP
Also its worth adding these ranges as little good will ever come from them
# Ponytelecom ranges
-A INPUT -s 62.210.0.0/16 -j DROP
-A INPUT -s 195.154.0.0/16 -j DROP
-A INPUT -s 212.129.0.0/18 -j DROP
-A INPUT -s 62.4.0.0/19 -j DROP
-A INPUT -s 212.83.128.0/19 -j DROP
-A INPUT -s 212.83.160.0/19 -j DROP
-A INPUT -s 212.47.224.0/19 -j DROP
-A INPUT -s 163.172.0.0/16 -j DROP
-A INPUT -s 51.15.0.0/16 -j DROP
-A INPUT -s 151.115.0.0/16 -j DROP
# VITOX TELECOM
-A INPUT -s 77.247.109.0/255.255.255.0 -p udp -j DROP
-A INPUT -s 185.53.88.0/24 -p udp -j DROP
-A INPUT -s 185.53.89.0/24 -p udp -j DROP
-A INPUT -s 37.49.224.0/24 -p udp -j DROP
-A INPUT -s 37.49.230.0/24 -p udp -j DROP
-A INPUT -s 37.49.231.0/24 -p udp -j DROP
-A INPUT -s 77.247.110.0/255.255.255.0 -p udp -j DROP
fwconsole ma list |grep restapps
Anything older than 15.0.20
fwconsole ma downloadinstall restapps --tag 15.0.20
fwconsole ma list |grep restapps
fwconsole chown
fwconsole r
and
In the userman reversion note that you need to install again after the downloadinstall , This removes the offending line from crontab
fwconsole ma list |grep userman
crontab -l -uasterisk |grep userman
The above checks the cron jobs for the offending line then if older than 15.0.67 then update as below
fwconsole ma downloadinstall userman --tag 15.0.67
fwconsole ma install userman
fwconsole chown
fwconsole r
At Gradwell, they send internet traffic from different addresses (known as IP addresses) to allow their telephony systems to work smoothly. Below is the list of IP addresses where their VoIP (Voice over IP) traffic will come from. It’s important that your firewall allows traffic from these addresses however they recommend you don’t set it to allow only from these, just that they are included.
The reason they say don’t allow only these addresses is that there network is dynamic and may shift or new items added and we don’t want this to affect your service.
There are a couple of things you should do to ensure you get the most from the Gradwell Voice services:
Check your firewall filtering – is there anything being excluded?
If yes – Allow the IP range traffic – this will most likely be in your firewall settings or tools (they all differ so they can’t exactly point you there)
If no – you’re good to go
If you use UDP traffic then you’ll need to allow Media ports (known as RTP) with the numbers 1024 to 65535
Current ranges as of summer 2021
109.224.232.0/22 109.224.232.0 to 109.224.235.255 109.224.240.0/22 109.224.240.0 to 109.224.243.255 109.239.96.132/31 109.239.96.132 to 109.239.96.133 141.170.24.21/31 141.170.24.21 to 141.170.24.22 141.170.24.5/31 141.170.24.5 to 141.170.24.6 141.170.50.16/28 141.170.50.16 to 141.170.50.31 185.47.148.0/24 185.47.148.0 to 185.47.148.255 194.145.188.224/27 194.145.188.224 to 194.145.188.255 194.145.189.52/31 194.145.189.52 to 194.145.189.53 194.145.190.128/26 194.145.190.128 to 194.145.190.191 194.145.191.128/27 194.145.191.128 to 194.145.191.159 195.74.60.0/23 195.74.60.0 to 195.74.61.255 213.166.3.128/26 213.166.3.129 - 213.166.3.190 213.166.4.128/26 213.166.4.129 - 213.166.4.190 213.166.5.0/24 213.166.5.0 to 213.166.5.255 78.40.243.192/27 78.40.243.192 to 78.40.243.223 87.238.72.128/26 87.238.72.128 to 87.238.72.191 87.238.73.128/26 87.238.73.128 to 87.238.73.191 87.238.74.128/26 87.238.74.128 to 87.238.74.191 87.238.77.128/26 87.238.77.128 to 87.238.77.191
To simplify things a bit listed below are the ranges in common formats.
Some years ago we wrote a post on running macros on queue answer here. this was very useful for integration with backends, At the time we raised a feature request to get it added to Freepbx, But this never happened.
Now the variable QGOSUB is in the dialplan for freepbx queues, But still there is no way of setting this in a default freepbx installation and it requires a snip-it of custom dialplan that is called from freepbx by a ‘custom destination’ . For example at its simplest the dialplan to set it could be :-
This allows simple or more complicated routines to be run. For example sending an email on answer which was a request we had that caused us to revisit this.
[ians_routine]
exten = s,1,Set(origtime=${EPOCH})
exten = s,n,Noop(${CHANNEL})
exten = s,n,Set(Agent11=${CUT(CHANNEL,@,1)})
exten = s,n,Set(Agent12=${CUT(Agent11,/,2)})
exten = s,n,Noop(${Agent11} , ${Agent12} )
exten = s,n,Set(fulltime=${STRFTIME(${EPOCH},,%d%m%Y-%H:%M:%S)})
exten = s,n,system(echo "There has been a call , Callers Details: ${CALLERID(number)} , ${CRM_SOURCE} , Date and Time: ${fulltime} , Agent: ${Agent12} ,Timestamp: ${origtime} , Queue Number: ${QUEUENUM} " | mail -s "failed recall at ${fulltime}" email@address.com)
same = n,Return()
Step By step instructions for call transfer when using the Aastra 6753i with firmware 3.x.x and above.
Phone Idle screen.
Once a call is answered their number will show and an icon of a ‘off hook phone’ will also show
To transfer the call press your ‘Transfer key’. Another ‘line’ will show numbered 2 with a ‘ > ’ next to it.
Enter the number you want to dial and press ‘>‘ dial if the call isn’t immediately dialed.
To ‘Blind’ transfer the call press the Transfer Button again or put the Handset down. NOTE if you do this you will not be able to get the call back.
After pressing dial the Phone Icon will show ‘ringing’
To get the call back while it is ringing press the ‘ < ‘ button shown on the display next to ‘Cancel’. Then L1 in this example will flash and ‘call held’ will show on the display as below, you need to get the call back by pressing the Flashing Line Key.
If the call goes to Voicemail or the caller answers the display will show the ‘off hook’ icon against 2
If the Caller wants the call then Press the ‘Transfer key’ the Red ‘Hangup key’ or put the handset down and the call will be transferred to them. Do not press the ‘>‘ Drop button.
If they don’t want the call or it goes to voicemail and you want to get the caller back, Press the ‘ > ‘ Drop Button and that call will be dropped and as before ‘call held’ will show on the screen and you press the L1 button to get the caller Back
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.AcceptRejectRead More
Privacy & Cookies Policy
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.