Записи в FreePBX в формате MP3

  • Linux
По умолчанию в mp3 freepbx писать не умеет, поэтому сделал, чтобы записи конвертировались потом, в кроне. Запускаю конвертацию ночью и все что накопилось в wav конвертируется в mp3. Имя файла в базе меняется на mp3
Сначала поставим lame
yum install lame

Можете попровать запустить конвертацию на любом wav файле
lame -h -b 32 test.wav test.mp3

Если все ок, запускайте скрипт
#!/bin/sh
#convert wav to mp3 asterisk recordings
cdrdb="asteriskcdrdb"
user="freepbxuser" #пользователь субд для отчетов
pass="password" #пароль пользователя субд

for i in `find /var/asterisk/spool/monitor -type f -name "*.wav"`
do
 if [ -e "$i" ]; then
    file=`basename "$i" .wav`;
    dir=`dirname "$i"`;
    lame -h -b 32 "$i" "$dir/$file.mp3";
    rm -f "$dir/$file.wav";
    mysql -u $user -p$pass --execute='use asteriskcdrdb;UPDATE cdr SET recordingfile="'$file'.mp3" WHERE recordingfile="'$file'.wav";';
  fi
done

Снять дамп разговора asterisk

Если нужно записать трафик, сделать полный дамп разговора для дальнейшего анализа например в wireshark, самый простой способ это tcpdump
tcpdump -i eth0 udp port 5060 or udp portrange 10000-20000 -s 0 -w shiffer.cap

Если нужен только sip траффик, можно так
tcpdump -i eth0 udp port 5060 -s 0 -w shiffer.cap

FreePBX / Elastix / Asterisk проблема при исходящих звонках

  • Asterisk
Проблема при большом количестве правил в исходящей маршрутизации, больше 100 правил в outbound routes, и появляется ошибка в логах ошибка:
Auto fallthrough, channel 'SIP/300-00000007' status is UNKNOWN
Maximum PBX stack exceeded

По умолчанию AST_PBX_MAX_STACK выставлен в 128, но можно его увеличить и пересобрать asterisk. Находим параметр в файлах:
./include/asterisk/extconf.h
./include/asterisk/pbx.h

Делаем
make
make install

Уведомления о пропущенных вызовах FreePBX 13

  • Asterisk
В интернете есть много примеров как сделать уведомления о пропущенных вызовах, но только для внешних вызовов и только для очередей. Мне же потребовалось сделать это для всех вызовов, только я убрал звонки юзер-юзер, только группы и очереди, внутренние или внешние без разницы. Так же без разницы кто положил трубку.
[macro-hangupcall]
include => macro-hangupcall-custom
exten => s,1(start),NoOp("------------------------")
exten => s,n,Set(chan=${CUT(CHANNEL,/,1)})
exten => s,n,NoOp(${chan})
exten => s,n,GotoIf($["${NODEST}" = ""]?nosip)
exten => s,n,GotoIf($[${chan} != SIP]?nosip)
exten => s,n,ExecIf($["${CDR(disposition)}"="NO ANSWER"]?System(/usr/bin/php -q /var/lib/asterisk/agi-bin/sendemail.php "Пропущен звонок q${NODEST} от ${CALLERID(name)}  Время ${CDR(billsec)}" ))
exten => s,n(nosip),GotoIf($["${USE_CONFIRMATION}"="" | "${RINGGROUP_INDEX}"="" | "${CHANNEL}"!="${UNIQCHAN}"]?theend)

exten => s,n(delrgi),Noop(Deleting: RG/${RINGGROUP_INDEX}/${CHANNEL} ${DB_DELETE(RG/${RINGGROUP_INDEX}/${CHANNEL})})
exten => s,n(theend),ExecIf($["${ONETOUCH_RECFILE}"!="" & "${CDR(recordingfile)}"=""]?Set(CDR(recordingfile)=${ONETOUCH_RECFILE}))
exten => s,n,Hangup
exten => s,n,MacroExit()

Asterisk/FreePBX возврат при переводе вызова

  • Asterisk
Часто требуется функция возврата звонка при переводе, если абонент не взял трубку.

globals_custom.conf:
TRANSFER_CONTEXT = custom-test_transfer

extensions_custom.conf:
[custom-test_transfer]
exten => _X.,1,NoOp(Entering custom-test_transfer)
exten => _X.,n,Set(timeoutd=25) ; set timeout in seconds
exten => _X.,n,Set(extLeng=${LEN(${EXTEN})})
exten => _X.,n,NoOp(The extenlength is ${extLeng})
exten => _X.,n,Dial(Local/${EXTEN}@from-internal,${timeoutd})
exten => _X.,n,Set(CALLERID(name)=RB:${CALLERID(name)})
exten => _X.,n,Dial(Local/${BLINDTRANSFER:4:${extLeng}}@from-internal)
exten => _X.,n,Hangup()

Адресная книга для телефонов Grandstream из FreePBX 13

Адресная книга удобная опция, которую часто спрашивают заказчики, поэтому разберемся как прописать ее для телефонов Grandstream

Сначала нам нужен скрипт который выгрузит номера и их Caller ID (он же поле «Имя») из настроек внутренних номеров FreePBX. Я делал на версии FreePBX 13, возможно будет работать и на более ранних.
<?php
$config = include("db/config.php");

$db = new PDO($config["db"], $config["username"], $config["password"], $config["options"]);

$sql = "SELECT extension, name from users";   // Делаем выборку записей книги
$q = $db->prepare($sql);
$q->execute();
$rows = $q->fetchAll();

unlink($config["pb_file_gs"]);  // Удалим старый файл

$fp = fopen($config["pb_file_gs"],"w+");
fputs($fp, '<?xml version="1.0" encoding="UTF-8"?><AddressBook>');

foreach($rows as $row) {         // Пробежим по всем записям, подготовив XML файл нужного вида
    	fputs($fp, '<Contact>
                        <FirstName>'.$row['name'].'</FirstName>
                        <LastName></LastName>
                        <Phone>
                                   <phonenumber>'.$row['extension'].'</phonenumber>
                                   <accountindex>1</accountindex>
                                   <downloaded>1</downloaded>
                        </Phone>
                        <Groups>
                                   <groupid>4</groupid>
                        </Groups>
            </Contact>
	'); 
}
fputs($fp, '<Group id="4">Server</Group> </AddressBook>');
fclose($fp);
?>


Файл «db/config.php»
<?php
return array(
    "db" => "mysql:host=localhost;dbname=asterisk",
    "pb_file_gs" => "/var/www/html/phonebook/phonebook.xml",
    "username" => "freepbxuser",     //Mysql login
    "password" => "123456", //Mysql password
    "options" => array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8')
);


Потом заходим в телефон «Phonebook -> Phonebook Management»

Enable Phonebook XML Download -> Enabled, HTTP
Phonebook XML Server Path -> http://serverpbx/phonebook/
Phonebook -> Phonebook Management
Phonebook Download Interval -> 60
Remove Manually-edited Entries on Download -> No

В крон прописываем запуск скрипта, который будет выгружать книгу. Для проверки можно посмотреть логи httpd, чтобы удостовериться, что телефон загружает нужный файл. Чтобы не ждать, можно телефон перегрузить, тогда он при загрузке подтянет телефонную книгу.

FreePBX 13 не применяет изменения в конфигурации

FreePBX 13 в Centos 7 выдал ошибку:
Unable to connect to remote asterisk (does /var/run/asterisk/asterisk.ctl exist?)
Exception: Unable to connect to Asterisk through the CLI in file /var/lib/asterisk/bin/retrieve_conf on line 30
Stack trace:
1. Exception->() /var/lib/asterisk/bin/retrieve_conf:30

А дело в том, что изменились права на какой-то папке и нужно обновить права, запустим для этого скрипт
/usr/sbin/fwconsole start

Можете добавить его в запуск при загрузке в файл /etc/rc.d/rc.local

Настройка fail2ban для защиты Elastix от подбора пароля для веб-интерфейса

  • Linux
Мануалов по настройке защиты asterisk много, а защиты самого elastix почему-то не нашел. Вопросы на форумах висят без ответов. Сделал сам, метод работает.
Создадим фильтр
vim /etc/fail2ban/filter.d/elastix-login.conf

[Definition]
#_daemon = asterisk
# Option:  failregex
# Notes.:  regex to match the password failures messages in the logfile. The
#          host must be matched by a group named "host". The tag "" can
#          be used for standard IP/hostname matching and is only an alias for
#          (?:::f{4,6}:)?(?P\S+)
# Values:  TEXT

#[Jul 14 20:47:04] LOGIN asdf: Authentication Failure to Web Interface login. Invalid user asdf from 192.168.0.100.
#[Nov 10 20:56:01] LOGIN admin: Authentication Failure to Web Interface login. Failed password for admin from 37.176.189.82.
#
failregex = LOGIN .*: Authentication Failure to Web Interface login. Invalid user .* from <HOST>.
            LOGIN .*: Authentication Failure to Web Interface login. Failed password for .* from <HOST>.

ignoreregex =

И добавим правило в jail.conf
[elastix]
enabled = true
filter = elastix-login
action = iptables-multiport[name=NoLoginFailures, port="http,https"]
logpath = /var/log/elastix/audit.log
bantime = 3600
maxretry = 3

Asterisk GUI

Начал писать свой веб-интерфейс для asterisk, на php + js + html + ajax
Проект opensource. Пока еще на начальной стадии, но уже кое что умеет.
Из того, чего не видел у других — отображение очередей с статусами агентов и с кем они разговаривают (с привязкой к очереди), видно не отвеченные вызовы и нагрузку на очереди. Да, похожее есть в FOP2, но во-первых платно, во-вторых не совсем так.

Ссылка на github.com

Прошу попинать и высказать фидбек или хотелки, может по разработке подскажете что полезное.

Скриншот

Как добавить в очередь внешнего абонента

  • Asterisk
Нашел на форумах, возможно пригодится:

Вы можете добавить в очередь любой канал, в том числе внешний номер:

member => Local/12345@default

Где [default] наш контекст.

И так же можно использовать такую конструкцию:
member => SIP/12345@yourprovider

Команды AMI

  • Asterisk
Список команд AMI asterisk версии 11, вывод команды manager show commands
AbsoluteTimeout: Set absolute timeout.  (Priv: system,call,all)
AgentLogoff: Sets an agent as no longer logged in.  (Priv: agent,all)
Agents: Lists agents and their status.  (Priv: agent,all)
Atxfer: Attended transfer.  (Priv: call,all)
Bridge: Bridge two channels already in the PBX.  (Priv: call,all)
Challenge: Generate Challenge for MD5 Auth.  (Priv: <none>)
ChangeMonitor: Change monitoring filename of a channel.  (Priv: call,all)
Command: Execute Asterisk CLI Command.  (Priv: command,all)
ConfbridgeKick: Kick a Confbridge user.  (Priv: call,all)
ConfbridgeList: List participants in a conference.  (Priv: reporting,all)
ConfbridgeListRooms: List active conferences.  (Priv: reporting,all)
ConfbridgeLock: Lock a Confbridge conference.  (Priv: call,all)
ConfbridgeMute: Mute a Confbridge user.  (Priv: call,all)
ConfbridgeSetSingleVideoSrc: Set a conference user as the single video source distributed to all other participants.  (Priv: call,all)
ConfbridgeStartRecord: Start recording a Confbridge conference.  (Priv: system,all)
ConfbridgeStopRecord: Stop recording a Confbridge conference.  (Priv: call,all)
ConfbridgeUnlock: Unlock a Confbridge conference.  (Priv: call,all)
ConfbridgeUnmute: Unmute a Confbridge user.  (Priv: call,all)
CoreSettings: Show PBX core settings (version etc).  (Priv: system,reporting,all)
CoreShowChannels: List currently active channels.  (Priv: system,reporting,all)
CoreStatus: Show PBX core status variables.  (Priv: system,reporting,all)
CreateConfig: Creates an empty file in the configuration directory.  (Priv: config,all)
DAHDIDialOffhook: Dial over DAHDI channel while offhook.  (Priv: <none>)
DAHDIDNDoff: Toggle DAHDI channel Do Not Disturb status OFF.  (Priv: <none>)
DAHDIDNDon: Toggle DAHDI channel Do Not Disturb status ON.  (Priv: <none>)
DAHDIHangup: Hangup DAHDI Channel.  (Priv: <none>)
DAHDIRestart: Fully Restart DAHDI channels (terminates calls).  (Priv: <none>)
DAHDIShowChannels: Show status of DAHDI channels.  (Priv: <none>)
DAHDITransfer: Transfer DAHDI Channel.  (Priv: <none>)
DataGet: Retrieve the data api tree.  (Priv: <none>)
DBDel: Delete DB entry.  (Priv: system,all)
DBDelTree: Delete DB Tree.  (Priv: system,all)
DBGet: Get DB Entry.  (Priv: system,reporting,all)
DBPut: Put DB entry.  (Priv: system,all)
Events: Control Event Flow.  (Priv: <none>)
ExtensionState: Check Extension Status.  (Priv: call,reporting,all)
Filter: Dynamically add filters for the current manager session.  (Priv: system,all)
GetConfig: Retrieve configuration.  (Priv: system,config,all)
GetConfigJSON: Retrieve configuration (JSON format).  (Priv: system,config,all)
Getvar: Gets a channel variable or function value.  (Priv: call,reporting,all)
Hangup: Hangup channel.  (Priv: system,call,all)
IAXnetstats: Show IAX Netstats.  (Priv: system,reporting,all)
IAXpeerlist: List IAX Peers.  (Priv: system,reporting,all)
IAXpeers: List IAX peers.  (Priv: system,reporting,all)
IAXregistry: Show IAX registrations.  (Priv: system,reporting,all)
ListCategories: List categories in configuration file.  (Priv: config,all)
ListCommands: List available manager commands.  (Priv: <none>)
LocalOptimizeAway: Optimize away a local channel when possible.  (Priv: system,call,all)
Login: Login Manager.  (Priv: <none>)
Logoff: Logoff Manager.  (Priv: <none>)
MailboxCount: Check Mailbox Message Count.  (Priv: call,reporting,all)
MailboxStatus: Check mailbox.  (Priv: call,reporting,all)
MixMonitor: Record a call and mix the audio during the recording.  Use of StopMixMonitor is required to guarantee the audio file is available for processing during dialplan execution.  (Priv: system,all)
MixMonitorMute: Mute / unMute a Mixmonitor recording.  (Priv: system,call,all)
ModuleCheck: Check if module is loaded.  (Priv: system,all)
ModuleLoad: Module management.  (Priv: system,all)
Monitor: Monitor a channel.  (Priv: call,all)
MuteAudio: Mute an audio stream.  (Priv: system,all)
Originate: Originate a call.  (Priv: originate,all)
Park: Park a channel.  (Priv: call,all)
ParkedCalls: List parked calls.  (Priv: <none>)
Parkinglots: Get a list of parking lots  (Priv: <none>)
PauseMonitor: Pause monitoring of a channel.  (Priv: call,all)
Ping: Keepalive command.  (Priv: <none>)
PlayDTMF: Play DTMF signal on a specific channel.  (Priv: call,all)
PresenceState: Check Presence State  (Priv: call,reporting,all)
QueueAdd: Add interface to queue.  (Priv: agent,all)
QueueLog: Adds custom entry in queue_log.  (Priv: agent,all)
QueueMemberRingInUse: Set the ringinuse value for a queue member.  (Priv: agent,all)
QueuePause: Makes a queue member temporarily unavailable.  (Priv: agent,all)
QueuePenalty: Set the penalty for a queue member.  (Priv: agent,all)
QueueReload: Reload a queue, queues, or any sub-section of a queue or queues.  (Priv: <none>)
QueueRemove: Remove interface from queue.  (Priv: agent,all)
QueueReset: Reset queue statistics.  (Priv: <none>)
QueueRule: Queue Rules.  (Priv: <none>)
Queues: Queues.  (Priv: <none>)
QueueStatus: Show queue status.  (Priv: <none>)
QueueSummary: Show queue summary.  (Priv: <none>)
Redirect: Redirect (transfer) a call.  (Priv: call,all)
Reload: Send a reload event.  (Priv: system,config,all)
SendText: Send text message to channel.  (Priv: call,all)
Setvar: Sets a channel variable or function value.  (Priv: call,all)
ShowDialPlan: Show dialplan contexts and extensions  (Priv: config,reporting,all)
SIPnotify: Send a SIP notify.  (Priv: system,all)
SIPpeers: List SIP peers (text format).  (Priv: system,reporting,all)
SIPpeerstatus: Show the status of one or all of the sip peers.  (Priv: system,all)
SIPqualifypeer: Qualify SIP peers.  (Priv: system,reporting,all)
SIPshowpeer: show SIP peer (text format).  (Priv: system,reporting,all)
SIPshowregistry: Show SIP registrations (text format).  (Priv: system,reporting,all)
Status: List channel status.  (Priv: system,call,reporting,all)
StopMixMonitor: Stop recording a call through MixMonitor, and free the recording's file handle.  (Priv: system,call,all)
StopMonitor: Stop monitoring a channel.  (Priv: call,all)
UnpauseMonitor: Unpause monitoring of a channel.  (Priv: call,all)
UpdateConfig: Update basic configuration.  (Priv: config,all)
UserEvent: Send an arbitrary event.  (Priv: user,all)
VoicemailUsersList: List All Voicemail User Information.  (Priv: call,reporting,all)
WaitEvent: Wait for an event to occur.  (Priv: <none>)