====== Сервис Asterisk ======
* [[http://asterisk.ru/knowledgebase|База знаний Астериск]]
* [[http://asterisk-pbx.ru/wiki/asterisk/cf|Файлы конфигурации Asterisk]]
* [[http://xgu.ru/wiki/Asterisk|xgu.ru wiki Asterisk]]
* [[http://www.asteriskguru.com/|Учебник по Asterisk на asteriskguru.com]]
* [[https://wapo-spb.livejournal.com/|Интересный блог сисадмина из СПб]]
===== Установка =====
* [[https://community.asterisk.org/t/install-asterisk-via-apt-or-from-source/99713|Install Asterisk via apt or from source?]]
==== Debian/Ubuntu ====
root@server:~# apt update
root@server:~# apt install asterisk
===== Удаление =====
# apt purge asterisk-config asterisk
# apt autoremove
===== Настройка базового функционала IP PBX =====
==== Настройка CHAN_SIP каналов ====
* [[https://asterisk-pbx.ru/wiki/asterisk/cf/chan_sip|Настройка SIP в Asterisk - sip.conf]]
* [[http://www.voip-info.org/wiki/view/Asterisk+config+sip.conf|Asterisk config sip.conf]]
* [[http://www.voip-info.org/wiki/view/Asterisk+sip+type|Matching incoming calls to users and peers]]
* [[http://asterisk-support.ru/question/15221/username-i-auth-username-chto-to-izmenilos/|username и auth username - что-то изменилось?]]
* [[http://voip.rus.net/tiki-index.php?page=Asterisk+SIP+channels|Модуль SIP канала Asterisk]]
* [[http://irockasterisk.blogspot.ru/2012/03/how-to-set-concurrent-calls-limit-on.html|How to set the concurrent calls limit on SIP trunk in Asterisk?]]
* [[http://asterisk-support.ru/question/38301/call-limit/|call limit]]
server# cat /etc/asterisk/sip.conf
[general]
;udpbindaddr=0.0.0.0:6050
transport=udp
disallow=all
allow=alaw
directmedia=no ; for webinar
nat=force_rport,comedia ; for webinar
qualify=yes ; for webinar
;context=default
;allowguest=no ;Allow unknown access
;alwaysauthreject=yes ;Always auth rejects
;autocreatepeer=no ;AutoCreate Peer
;localnet=192.168.X.0/255.255.255.0
;;;externip=172.16.1.X
;externaddr = 172.16.1.X
;externaddr = 172.16.1.X:6050
;defaultexpiry=60
[401]
secret=tpassword401
type=friend
host=dynamic
[402]
secret=tpassword402
type=friend
host=dynamic
;allowsubscribe=no
;setvar=MY-USER-ID=user2@corpX.un ;in channel type=user
;callerid=Петр Петров<402>
;cid_number=402
;fullname=Петр Петров
;disallow=all
;allow=gsm
;call-limit=1
;deny=0.0.0.0/0.0.0.0
;permit=172.16.1.0/255.255.255.0
;directmedia=no
;nat=force_rport,comedia
;qualify=yes
;[user2]
;secret=password2
;...
;[corpY]
;type=peer
;context=default
;host=server.corpY.un
;directmedia=no ;need for video?
==== Использование шаблонов в именах CHAN_SIP каналов ====
server# cat /etc/asterisk/sip.conf
...
[office](!)
type=friend
host=dynamic
deny=0.0.0.0/0.0.0.0
permit=192.168.X.0/255.255.255.0
[internet](!)
type=friend
host=dynamic
permit=0.0.0.0/0.0.0.0
nat=force_rport,comedia
qualify=yes
directmedia=no
;call-limit=1
[401](office)
secret=tpassword401
[402](internet)
secret=tpassword402
[403](office)
secret=tpassword403
[404](office)
secret=tpassword404
...
==== Настройка RES_PJSIP каналов ====
* [[https://wiki.asterisk.org/wiki/display/AST/Migrating+from+chan_sip+to+res_pjsip|Migrating from chan_sip to res_pjsip]]
* [[https://asterisk-pbx.ru/wiki/asterisk/pjsip|Описание параметров настройки pjsip в Asterisk]]
* [[http://voiplab.by/wiki/asterisk/60-novyj-kanalnyj-drajver-chan-pjsip-v-asterisk-13|НОВЫЙ КАНАЛЬНЫЙ ДРАЙВЕР CHAN_PJSIP В ASTERISK 13]]
* Переменные канала: [[https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+Function_PJSIP_ENDPOINT|function 'PJSIP_ENDPOINT']]
* [[https://zadarma.com/ru/support/instructions/asteriskpjsip/|Пример настройки подключения Asterisk PJSIP к Zadarma]]
=== Настройка PJSIP транспорта ===
# cat /etc/asterisk/sip.conf
[general]
udpbindaddr=0.0.0.0:5061
# cat /etc/asterisk/pjsip.conf
[udp-transport-1]
type=transport
protocol=udp
bind=0.0.0.0:5060
=== Настройка PJSIP точки подключения телефона ===
Базовый вариант
# cat /etc/asterisk/pjsip.conf
...
[401]
type=endpoint
transport=udp-transport-1
context=default
disallow=all
allow=alaw
aors=401
auth=401
;callerid=Иван Иванов<401>
;set_var=MY-USER-ID=user1@corpX.un
;set_var=MY-PSTN-CALLER-ID=8495123456X
;force_rport=yes
;rewrite_contact=yes
;rtp_symmetric=yes
;direct_media=no
[401]
type=aor
max_contacts=1
remove_existing=yes
;qualify_frequency=60
[401]
type=auth
auth_type=userpass
password=tpassword401
username=401
...
Wizard вариант
!!! Изменение отдельных параметров требует либо удаление/reload/добавление/reload всего описания точки подключения, либо перезапуска asterisk
# cat /etc/asterisk/pjsip_wizard.conf
[402]
type=wizard
accepts_auth=yes
accepts_registrations=yes
transport=udp-transport-1
inbound_auth/username=402
inbound_auth/password=tpassword402
endpoint/allow=alaw
endpoint/context=default
;endpoint/set_var=MY-USER-ID=user2@corp13.un
;endpoint/callerid=Petr P. Petrov<402>
aor/max_contacts=1
aor/remove_existing=yes
=== Настройка PJSIP точки подключения к другому офису ===
[corp]
type=endpoint
transport=udp-transport-1
context=default
disallow=all
allow=alaw
aors=corp
;force_rport=yes
;rewrite_contact=yes
;rtp_symmetric=yes
;direct_media=no
[corp]
type=aor
contact=sip:server.corp.un:5060
;qualify_frequency=60
[corp]
type=identify
endpoint=corp
match=server.corp.un
=== Настройка PJSIP точки подключения к VoIP провайдеру ===
# cat /etc/asterisk/pjsip.conf
...
; voip1.un и server.corp.un (курс CGP) одна и та же система
; приходится подключаться к ней с разных портов :)
[udp-transport-2]
type=transport
protocol=udp
bind=0.0.0.0:5062
;local_net=192.168.1.0/255.255.255.0
;local_net=192.168.X.0/255.255.255.0
;external_media_address=172.16.1.X
;external_signaling_address=172.16.1.X
[voip1_00000X]
type=endpoint
transport=udp-transport-2
context=default
disallow=all
allow=alaw
outbound_auth=voip1_00000X
aors=voip1_00000X
from_user=00000X
from_domain=voip1.un
;direct_media=no
;rtp_symmetric=yes
;;;force_rport=yes
;;;rewrite_contact=yes
[voip1_00000X]
type=auth
auth_type=userpass
password=spasswordX
username=00000X
[voip1_00000X]
type=aor
contact=sip:voip1.un:5060
;qualify_frequency=60
[voip1_00000X]
type=registration
transport=udp-transport-2
outbound_auth=voip1_00000X
server_uri=sip:voip1.un
client_uri=sip:00000X@voip1.un
;;;retry_interval=10
;;;expiration=10
contact_user=voip1_00000X
[voip1_00000X]
type=identify
endpoint=voip1_00000X
match=voip1.un
==== Настройка базового плана нумерации ====
* [[http://www.voip-info.org/wiki/view/Asterisk+variables|Using Variables in Asterisk Dialplans]]
* [[https://asterisk-pbx.ru/wiki/asterisk/app/dial|Команда диалплана Asterisk "Dial"]]
* [[https://wiki.asterisk.org/wiki/display/AST/Dialing+PJSIP+Channels|Dialing PJSIP Channels]]
* [[https://wiki.asterisk.org/wiki/display/AST/The+Verbose+and+NoOp+Applications|The Verbose and NoOp Applications]]
server# cat /etc/asterisk/extensions.conf
;[general]
;[globals]
[default]
exten => 301,1,Answer()
exten => 301,n,Playback(hello-world)
exten => 301,n,SayNumber(X)
exten => 301,n,Hangup()
exten => 311,1,Answer()
same => n,Echo()
;exten => 401,1,Dial(SIP/401)
;exten => 402,1,Dial(SIP/402)
exten => _4XX,1,Dial(SIP/${EXTEN})
;exten => _4XX,1,Dial(PJSIP/${EXTEN})
==== Командный интерфейс Asterisk ====
server# asterisk -r
server*CLI> sip reload
server*CLI> sip show settings
server*CLI> sip show users
server*CLI> sip show user 401
server*CLI> sip show peers
server*CLI> sip show peer 401
server*CLI> sip unregister 401
server*CLI> pjsip reload
server*CLI> pjsip show endpoints
server*CLI> dialplan reload
server*CLI> dialplan show default
server*CLI> core reload
server*CLI> core restart gracefully
server*CLI> exit
server# asterisk -x 'sip show peers'
==== Видеозвонки ====
* [[http://www.voip-info.org/wiki/view/Asterisk+video]]
server# cat /etc/asterisk/sip.conf
[general]
...
disallow=all
allow=alaw
...
allow=h263
allow=h264
videosupport=yes
avpf=yes
...
==== Отладка работы Asterisk ====
* [[https://community.asterisk.org/t/help-new-installation-full-of-errors/46614|HELP - New Installation Full of Errors]]
=== Сервисные сообщения ===
server# asterisk -rvvv
server*CLI> core set verbose 1
server# cat /etc/asterisk/logger.conf
...
[logfiles]
...
console => warning,error,dtmf
messages => notice,warning,error,verbose(3)
...
# tail -f /var/log/asterisk/messages
=== Отладка SIP ===
* [[https://habrahabr.ru/post/274919/|Asterisk: ngrep, sipgrep, sngrep, protocol diagram]]
server*CLI> sip set debug peer 401
server*CLI> sip set debug ip 172.16.1.Z
server*CLI> sip set debug off
=== Отладка RTP ===
server*CLI> rtp set debug on
===== Управление контекстами =====
==== TimeBased контексты ====
* [[https://wiki.asterisk.org/wiki/display/AST/Contexts%2C+Extensions%2C+and+Priorities#Contexts,Extensions,andPriorities-Dialplansearchorder|Dialplan search order]]
* [[https://www.voip-info.org/asterisk-tips-openhours/|How to include contexts based on time and date]]
* [[http://voip.rus.net/tiki-index.php?page=Asterisk+tips+openhours|Использование различных контекстов в зависимости от времени суток]]
server# cat /etc/asterisk/extensions.conf
[default]
...
;[incoming]
include=>incoming_work_time,10:00-16:59,mon-fri,*,*
include=>incoming_work_time,10:00-13:59,sat,*,*
include=>incoming_not_work_time,17:00-9:59,mon-fri,*,*
include=>incoming_not_work_time,14:00-9:59,sat,*,*
include=>incoming_not_work_time,*,sun,*,*
[incoming_work_time]
exten => voip1_00000X,1,Dial(SIP/403,10,t)
exten => voip1_00000X,n,Dial(SIP/401&SIP/402)
[incoming_not_work_time]
exten => voip1_00000X,1,Dial(SIP/voip1_00000X/89161234567)
===== Подключение Asterisk к VoIP провайдеру по протоколу SIP =====
* [[Материалы по VoIP#Настройка Asterisk для связи с VoIP провайдерами]]
==== Шаблон конфигурации для осуществления исходящих вызовов ====
server# cat /etc/asterisk/sip.conf
...
[voip1_00000X]
type=peer
defaultuser=00000X
secret=spasswordX
host=voip1.un
fromuser=00000X
fromdomain=voip1.un
server# cat /etc/asterisk/extensions.conf
...
exten => _8XXXXXXXXXX,1,Dial(SIP/voip1_00000X/${EXTEN})
;exten => _8XXXXXXXXXX,1,Dial(SIP/${EXTEN}@voip1_00000X) ;SIP можно так
;exten => _8XXXXXXXXXX,1,Dial(PJSIP/${EXTEN}@voip1_00000X) ;PJSIP только так
;exten => _[+789]XXXXXXXXXX!,1,GoSub(sub-monitor,s,1)
;exten => _[+789]XXXXXXXXXX!,n,Dial(SIP/voip1_00000X/8${EXTEN:-10})
==== Шаблон конфигурации для обработки входящих вызовов ====
server# cat /etc/asterisk/sip.conf
[general]
...
;register => 00000X:spasswordX@voip1.un/voip1_00000X
...
[voip1_00000X]
type=peer
defaultuser=00000X
secret=spasswordX
host=voip1.un
fromuser=00000X
fromdomain=voip1.un
;context=incoming
insecure=invite
callbackextension=voip1_00000X
server# cat /etc/asterisk/extensions.conf
[globals]
;MY-RING-GROUP => SIP/401&SIP/402&SIP/403&SIP/404
;MY-RING-GROUP-84951234567 => SIP/401&SIP/402
;MY-RING-GROUP-84957654321 => SIP/403&SIP/404
[default]
...
;[incoming]
exten => voip1_00000X,1,Dial(SIP/401&SIP/402&SIP/403&SIP/404)
;exten => voip1_00000X,1,Dial(${MY-RING-GROUP})
;exten => 8495XXXXXXX,1,Dial(${MY-RING-GROUP-${EXTEN}})
server*CLI> sip show registry
server*CLI> pjsip show registrations
==== Использование asterisk в качестве телефона ====
* [[https://sourceforge.net/p/raspbx/discussion/general/thread/6d319f48/|ALSA Asterisk Console on RasPBX]]
phone2# cat /etc/asterisk/extensions.conf
[default]
exten => 301,1,Answer()
exten => 301,n,Playback(hello-world)
exten => 301,n,Hangup()
debian# cat /etc/asterisk/modules.conf
...
load => chan_alsa.so
noload => chan_oss.so
...
rasberry# cat alsa.conf
...
input_device=hw:1,0
output_device=hw:0,0
...
phone2*CLI> module show like alsa
phone2*CLI> channel originate Console/dsp extension 301
phone2*CLI> console answer
phone2*CLI> console hangup
phone2# cat /etc/asterisk/sip.conf
[general]
transport=udp
disallow=all
allow=alaw
[sipproxy]
type=peer
defaultuser=402
secret=tpassword402
host=gate.corpX.un
insecure=invite
callbackextension=sipproxy
phone2# cat /etc/asterisk/extensions.conf
...
exten => _4XX,1,Dial(SIP/sipproxy/${EXTEN})
exten => sipproxy,1,Dial(Console/dsp)
===== Подключение Asterisk к Asterisk по протоколу SIP =====
==== Настройка серверов филиалов ====
* [[#Подключение Asterisk к VoIP провайдеру по протоколу SIP]]
==== Настройка центрального сервера ====
root@voip1.un:~# cat sip.conf
...
[000001]
type=user
;type=friend
secret=spassword1
host=dynamic
context=from-sip-trunk
...
[000006]
type=user
;type=friend
secret=spassword6
host=dynamic
context=from-sip-trunk
root@voip1.un:~# cat extensions.conf
...
[from-sip-trunk]
exten => _8XXXXXXXXXX,1,Dial(SIP/sipnet_00000X/${EXTEN})
===== Подключение Asterisk к Asterisk по протоколу IAX =====
==== Настройка IAX каналов ====
server.corpX.un# cat /etc/asterisk/iax.conf
[general]
;bindport=4569
;bindaddr=0.0.0.0
disallow=all
allow=alaw
[corp]
type=user
;context=default
host=dynamic
secret=apassword
auth=md5
[corp]
type=peer
host=server.corp.un
username=corpX
secret=apasswordX
auth=md5
;[corpY]
;type=friend
;context=default
;host=server.corpY.un
==== Настройка плана нумерации ====
* CallerID ([[Сервис Asterisk#Настройка CHAN_SIP каналов]])
server.corpX.un# cat /etc/asterisk/extensions.conf
[default]
...
exten => _000XXX,1,Set(CALLERID(num)=00X${CALLERID(num)})
exten => _000XXX,n,Dial(IAX2/corp/${EXTEN:3})
;exten => _000XXX,n,Dial(PJSIP/${EXTEN:3}@corp)
;exten => _00Y[34]XX,1,Set(CALLERID(num)=00X${CALLERID(num)})
;exten => _00Y[34]XX,n,Dial(IAX2/corpY/${EXTEN:3})
* Сервис Ansible [[Сервис Ansible#Использование шаблонов]]
;;пример универсального шаблона для звонков в офисы
;;с 1-го по 9-й и c 10-го по 13-й
exten => _00X[34]XX,1,Set(CALLERID(num)=00X${CALLERID(num)})
exten => _00X[34]XX,n,Dial(IAX2/corp${EXTEN:2:1}/${EXTEN:3})
exten => _01[0-3][34]XX,1,Set(CALLERID(num)=00X${CALLERID(num)})
exten => _01[0-3][34]XX,n,Dial(IAX2/corp${EXTEN:1:2}/${EXTEN:3})
server*CLI> iax2 reload
server*CLI> dialplan reload
===== Детализация разговоров =====
==== Просмотр текущих звонков ====
server*CLI> sip show channels
server*CLI> cdr show active
server*CLI> channel request hangup SIP/
# watch -d "asterisk -x 'cdr show active'"
# curl -v -X GET "http://localhost:8088/ari/channels?api_key=asterisk:asterisk"
=== Настройка местного времени ===
server# cat /etc/asterisk/cdr.conf
...
[csv]
usegmtime=no
...
==== Добавление IP адреса ====
* [[https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+Function_CHANNEL|Asterisk 13 Function_CHANNEL]]
...
same => n,Set(CDR(userfield)=${CHANNEL(recvip)}) ;SIP
...
same => n,Set(CDR(userfield)=${CHANNEL(pjsip,remote_addr)}) ;PJSIP
...
==== Использование файлов для хранения CDR ====
=== Просмотр ===
server# tail -f /var/log/asterisk/cdr-csv/Master.csv
=== Построение отчетов ===
* [[http://www.voip-info.org/wiki/view/Asterisk+CDR+csv+handling2]]
=== Ротация с использованием SYSLOG ===
* [[Сервис SYSLOG]]
* [[Планирование выполнения заданий в Linux]]
* [[Планирование выполнения заданий в FreeBSD]]
server# :> /etc/asterisk/cdr.conf
server# cat /etc/asterisk/cdr_syslog.conf
[general]
facility=local0
[cdr-simple]
template = "${CDR(clid)}","${CDR(src)}","${CDR(dst)}","${CDR(dcontext)}","${CDR(channel)}","${CDR(dstchannel)}","${CDR(lastapp)}","${CDR(lastdata)}","${CDR(start)}","${CDR(answer)}","${CDR(end)}","${CDR(duration)}","${CDR(billsec)}","${CDR(disposition)}","${CDR(amaflags)}","${CDR(accountcode)}","${CDR(uniqueid)}","${CDR(userfield)}"
server# asterisk -x 'core restart gracefully'
server# asterisk -x 'cdr show status'
...
Mode: Simple
...
* Registered Backends
-------------------
cdr-syslog
...
server# tail -f /var/log/syslog
==== Использование СУБД для хранения CDR ====
=== Создание базы данных ===
* [[https://wiki.asterisk.org/wiki/display/AST/MySQL+CDR+Backend|MySQL CDR Backend]]
# cat cdr.sql
CREATE DATABASE asterisk;
GRANT ALL ON asterisk.* TO asterisk@localhost IDENTIFIED BY 'asterisk';
USE asterisk;
CREATE TABLE `cdr` (
`calldate` datetime NOT NULL default CURRENT_TIMESTAMP,
`clid` varchar(80) NOT NULL default '',
`src` varchar(80) NOT NULL default '',
`dst` varchar(80) NOT NULL default '',
`dcontext` varchar(80) NOT NULL default '',
`channel` varchar(80) NOT NULL default '',
`dstchannel` varchar(80) NOT NULL default '',
`lastapp` varchar(80) NOT NULL default '',
`lastdata` varchar(80) NOT NULL default '',
`duration` int(11) NOT NULL default '0',
`billsec` int(11) NOT NULL default '0',
`disposition` varchar(45) NOT NULL default '',
`amaflags` int(11) NOT NULL default '0',
`accountcode` varchar(20) NOT NULL default '',
`userfield` varchar(255) NOT NULL default '',
`uniqueid` VARCHAR(32) NOT NULL default '',
`linkedid` VARCHAR(32) NOT NULL default '',
`sequence` VARCHAR(32) NOT NULL default '',
`peeraccount` VARCHAR(32) NOT NULL default ''
);
ALTER TABLE `cdr` ADD INDEX ( `calldate` );
ALTER TABLE `cdr` ADD INDEX ( `dst` );
ALTER TABLE `cdr` ADD INDEX ( `accountcode` );
# mysql < cdr.sql
=== Настройка записи в БД ===
* [[#Asterisk ODBC CDR]]
=== Просмотра статистики CDR и прослушивание записей ===
# cat /etc/asterisk/extensions.conf
...
;exten => _4XX,1,Macro(monitor)
exten => _4XX,1,GoSub(sub-monitor,s,1)
exten => _4XX,n,Dial(SIP/${EXTEN})
...
;[macro-monitor]
[sub-monitor]
exten => s,1,Set(MONITOR_FILE=/var/spool/asterisk/monitor/${UNIQUEID})
exten => s,n,MixMonitor(${MONITOR_FILE}.wav,b)
exten => s,n,Return()
* [[https://code.google.com/p/asterisk-cdr-viewer/wiki/ReadMe]]
* [[http://prog-it.github.io/Asterisk-CDR-Viewer-Mod/|Значительно переработанная версия Web-интерфейса для просмотра и прослушивания записей звонков Asterisk]]
* [[https://asterisk-pbx.ru/wiki/artikle/cdr_viewer|Прекрасное приложение, для просмотра статистики и прослушивания записей]]
* [[Сервис HTTP#Установка и запуск сервера Apache]]
* [[Сервис HTTP#Модуль php]]
* [[Язык программирования PHP#Модуль php mysql]]
# cd /var/www/html
# wget http://val.bmstu.ru/unix/voip/asterisk-cdr-viewer-latest.tgz
# tar -xzvf asterisk-cdr-viewer-*.tgz
# cat /var/www/html/asterisk-cdr-viewer/include/config.inc.php
...
$db_user = 'asterisk';
$db_pass = 'asterisk';
$db_name = 'asterisk';
...
$system_auth_require = 0;
...
# usermod -G asterisk www-data
# service apache2 restart
http://172.16.1.X/asterisk-cdr-viewer/
* Спасибо Комлеву Александру Павловичу!
Чтобы запись разговора воспроизводилась прямо на странице CDR Viewer, нужно в файле
/var/www/html/asterisk-cdr-viewer/include/functions.inc.php
заменить строку:
echo " | \n";
на такую:
echo " | \n";
===== Asterisk realtime =====
==== PJSIP ====
* [[https://asterisk-pbx.ru/wiki/asterisk/realtime-pjsip|Asterisk PJSIP Realtime (asterisk-pbx.ru)]]
* [[https://wiki.asterisk.org/wiki/display/AST/Setting+up+PJSIP+Realtime|Setting up PJSIP Realtime (wiki.asterisk.org)]]
CREATE TABLE `ps_aors` (
`id` varchar(40) NOT NULL,
`contact` varchar(255) DEFAULT NULL,
`default_expiration` int(11) DEFAULT NULL,
`mailboxes` varchar(80) DEFAULT NULL,
`max_contacts` int(11) DEFAULT NULL,
`minimum_expiration` int(11) DEFAULT NULL,
`remove_existing` enum('yes','no') DEFAULT NULL,
`qualify_frequency` int(11) DEFAULT NULL,
`authenticate_qualify` enum('yes','no') DEFAULT NULL,
`maximum_expiration` int(11) DEFAULT NULL,
`outbound_proxy` varchar(40) DEFAULT NULL,
`support_path` enum('yes','no') DEFAULT NULL,
`qualify_timeout` float DEFAULT NULL,
`voicemail_extension` varchar(40) DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_aors_id` (`id`),
KEY `ps_aors_qualifyfreq_contact` (`qualify_frequency`,`contact`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_auths` (
`id` varchar(40) NOT NULL,
`auth_type` enum('md5','userpass') DEFAULT NULL,
`nonce_lifetime` int(11) DEFAULT NULL,
`md5_cred` varchar(40) DEFAULT NULL,
`password` varchar(80) DEFAULT NULL,
`realm` varchar(40) DEFAULT NULL,
`username` varchar(40) DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_auths_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_contacts` (
`id` varchar(255) DEFAULT NULL,
`uri` varchar(255) DEFAULT NULL,
`expiration_time` bigint(20) DEFAULT NULL,
`qualify_frequency` int(11) DEFAULT NULL,
`outbound_proxy` varchar(40) DEFAULT NULL,
`path` text,
`user_agent` varchar(255) DEFAULT NULL,
`qualify_timeout` float DEFAULT NULL,
`reg_server` varchar(20) DEFAULT NULL,
`authenticate_qualify` enum('yes','no') DEFAULT NULL,
`via_addr` varchar(40) DEFAULT NULL,
`via_port` int(11) DEFAULT NULL,
`call_id` varchar(255) DEFAULT NULL,
`endpoint` varchar(40) DEFAULT NULL,
`prune_on_boot` enum('yes','no') DEFAULT NULL,
UNIQUE KEY `id` (`id`),
UNIQUE KEY `ps_contacts_uq` (`id`,`reg_server`),
KEY `ps_contacts_id` (`id`),
KEY `ps_contacts_qualifyfreq_exp` (`qualify_frequency`,`expiration_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_domain_aliases` (
`id` varchar(40) NOT NULL,
`domain` varchar(80) DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_domain_aliases_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_endpoint_id_ips` (
`id` varchar(40) NOT NULL,
`endpoint` varchar(40) DEFAULT NULL,
`match` varchar(80) DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_endpoint_id_ips_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_endpoints` (
`id` varchar(40) NOT NULL,
`transport` varchar(40) DEFAULT NULL,
`aors` varchar(200) DEFAULT NULL,
`auth` varchar(40) DEFAULT NULL,
`context` varchar(40) DEFAULT NULL,
`disallow` varchar(200) DEFAULT NULL,
`allow` varchar(200) DEFAULT NULL,
`direct_media` enum('yes','no') DEFAULT NULL,
`connected_line_method` enum('invite','reinvite','update') DEFAULT NULL,
`direct_media_method` enum('invite','reinvite','update') DEFAULT NULL,
`direct_media_glare_mitigation` enum('none','outgoing','incoming') DEFAULT NULL,
`disable_direct_media_on_nat` enum('yes','no') DEFAULT NULL,
`dtmf_mode` enum('rfc4733','inband','info','auto') DEFAULT NULL,
`external_media_address` varchar(40) DEFAULT NULL,
`force_rport` enum('yes','no') DEFAULT NULL,
`ice_support` enum('yes','no') DEFAULT NULL,
`identify_by` enum('username','auth_username') DEFAULT NULL,
`mailboxes` varchar(40) DEFAULT NULL,
`moh_suggest` varchar(40) DEFAULT NULL,
`outbound_auth` varchar(40) DEFAULT NULL,
`outbound_proxy` varchar(40) DEFAULT NULL,
`rewrite_contact` enum('yes','no') DEFAULT NULL,
`rtp_ipv6` enum('yes','no') DEFAULT NULL,
`rtp_symmetric` enum('yes','no') DEFAULT NULL,
`send_diversion` enum('yes','no') DEFAULT NULL,
`send_pai` enum('yes','no') DEFAULT NULL,
`send_rpid` enum('yes','no') DEFAULT NULL,
`timers_min_se` int(11) DEFAULT NULL,
`timers` enum('forced','no','required','yes') DEFAULT NULL,
`timers_sess_expires` int(11) DEFAULT NULL,
`callerid` varchar(40) DEFAULT NULL,
`callerid_privacy` enum('allowed_not_screened','allowed_passed_screened','allowed_failed_screened','allowed','prohib_not_screened','prohib_passed_screened','prohib_failed_screened','prohib','unavailable') DEFAULT NULL,
`callerid_tag` varchar(40) DEFAULT NULL,
`100rel` enum('no','required','yes') DEFAULT NULL,
`aggregate_mwi` enum('yes','no') DEFAULT NULL,
`trust_id_inbound` enum('yes','no') DEFAULT NULL,
`trust_id_outbound` enum('yes','no') DEFAULT NULL,
`use_ptime` enum('yes','no') DEFAULT NULL,
`use_avpf` enum('yes','no') DEFAULT NULL,
`media_encryption` enum('no','sdes','dtls') DEFAULT NULL,
`inband_progress` enum('yes','no') DEFAULT NULL,
`call_group` varchar(40) DEFAULT NULL,
`pickup_group` varchar(40) DEFAULT NULL,
`named_call_group` varchar(40) DEFAULT NULL,
`named_pickup_group` varchar(40) DEFAULT NULL,
`device_state_busy_at` int(11) DEFAULT NULL,
`fax_detect` enum('yes','no') DEFAULT NULL,
`t38_udptl` enum('yes','no') DEFAULT NULL,
`t38_udptl_ec` enum('none','fec','redundancy') DEFAULT NULL,
`t38_udptl_maxdatagram` int(11) DEFAULT NULL,
`t38_udptl_nat` enum('yes','no') DEFAULT NULL,
`t38_udptl_ipv6` enum('yes','no') DEFAULT NULL,
`tone_zone` varchar(40) DEFAULT NULL,
`language` varchar(40) DEFAULT NULL,
`one_touch_recording` enum('yes','no') DEFAULT NULL,
`record_on_feature` varchar(40) DEFAULT NULL,
`record_off_feature` varchar(40) DEFAULT NULL,
`rtp_engine` varchar(40) DEFAULT NULL,
`allow_transfer` enum('yes','no') DEFAULT NULL,
`allow_subscribe` enum('yes','no') DEFAULT NULL,
`sdp_owner` varchar(40) DEFAULT NULL,
`sdp_session` varchar(40) DEFAULT NULL,
`tos_audio` varchar(10) DEFAULT NULL,
`tos_video` varchar(10) DEFAULT NULL,
`sub_min_expiry` int(11) DEFAULT NULL,
`from_domain` varchar(40) DEFAULT NULL,
`from_user` varchar(40) DEFAULT NULL,
`mwi_from_user` varchar(40) DEFAULT NULL,
`dtls_verify` varchar(40) DEFAULT NULL,
`dtls_rekey` varchar(40) DEFAULT NULL,
`dtls_cert_file` varchar(200) DEFAULT NULL,
`dtls_private_key` varchar(200) DEFAULT NULL,
`dtls_cipher` varchar(200) DEFAULT NULL,
`dtls_ca_file` varchar(200) DEFAULT NULL,
`dtls_ca_path` varchar(200) DEFAULT NULL,
`dtls_setup` enum('active','passive','actpass') DEFAULT NULL,
`srtp_tag_32` enum('yes','no') DEFAULT NULL,
`media_address` varchar(40) DEFAULT NULL,
`redirect_method` enum('user','uri_core','uri_pjsip') DEFAULT NULL,
`set_var` text,
`cos_audio` int(11) DEFAULT NULL,
`cos_video` int(11) DEFAULT NULL,
`message_context` varchar(40) DEFAULT NULL,
`force_avp` enum('yes','no') DEFAULT NULL,
`media_use_received_transport` enum('yes','no') DEFAULT NULL,
`accountcode` varchar(80) DEFAULT NULL,
`user_eq_phone` enum('yes','no') DEFAULT NULL,
`moh_passthrough` enum('yes','no') DEFAULT NULL,
`media_encryption_optimistic` enum('yes','no') DEFAULT NULL,
`rpid_immediate` enum('yes','no') DEFAULT NULL,
`g726_non_standard` enum('yes','no') DEFAULT NULL,
`rtp_keepalive` int(11) DEFAULT NULL,
`rtp_timeout` int(11) DEFAULT NULL,
`rtp_timeout_hold` int(11) DEFAULT NULL,
`bind_rtp_to_media_address` enum('yes','no') DEFAULT NULL,
`voicemail_extension` varchar(40) DEFAULT NULL,
`mwi_subscribe_replaces_unsolicited` int(11) DEFAULT NULL,
`deny` varchar(95) DEFAULT NULL,
`permit` varchar(95) DEFAULT NULL,
`acl` varchar(40) DEFAULT NULL,
`contact_deny` varchar(95) DEFAULT NULL,
`contact_permit` varchar(95) DEFAULT NULL,
`contact_acl` varchar(40) DEFAULT NULL,
`subscribe_context` varchar(40) DEFAULT NULL,
`fax_detect_timeout` int(11) DEFAULT NULL,
`contact_user` varchar(80) DEFAULT NULL,
`asymmetric_rtp_codec` enum('yes','no') DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_endpoints_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_globals` (
`id` varchar(40) NOT NULL,
`max_forwards` int(11) DEFAULT NULL,
`user_agent` varchar(255) DEFAULT NULL,
`default_outbound_endpoint` varchar(40) DEFAULT NULL,
`debug` varchar(40) DEFAULT NULL,
`endpoint_identifier_order` varchar(40) DEFAULT NULL,
`max_initial_qualify_time` int(11) DEFAULT NULL,
`default_from_user` varchar(80) DEFAULT NULL,
`keep_alive_interval` int(11) DEFAULT NULL,
`regcontext` varchar(80) DEFAULT NULL,
`contact_expiration_check_interval` int(11) DEFAULT NULL,
`default_voicemail_extension` varchar(40) DEFAULT NULL,
`disable_multi_domain` enum('yes','no') DEFAULT NULL,
`unidentified_request_count` int(11) DEFAULT NULL,
`unidentified_request_period` int(11) DEFAULT NULL,
`unidentified_request_prune_interval` int(11) DEFAULT NULL,
`default_realm` varchar(40) DEFAULT NULL,
`mwi_tps_queue_high` int(11) DEFAULT NULL,
`mwi_tps_queue_low` int(11) DEFAULT NULL,
`mwi_disable_initial_unsolicited` enum('yes','no') DEFAULT NULL,
`ignore_uri_user_options` enum('yes','no') DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_globals_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_registrations` (
`id` varchar(40) NOT NULL,
`auth_rejection_permanent` enum('yes','no') DEFAULT NULL,
`client_uri` varchar(255) DEFAULT NULL,
`contact_user` varchar(40) DEFAULT NULL,
`expiration` int(11) DEFAULT NULL,
`max_retries` int(11) DEFAULT NULL,
`outbound_auth` varchar(40) DEFAULT NULL,
`outbound_proxy` varchar(40) DEFAULT NULL,
`retry_interval` int(11) DEFAULT NULL,
`forbidden_retry_interval` int(11) DEFAULT NULL,
`server_uri` varchar(255) DEFAULT NULL,
`transport` varchar(40) DEFAULT NULL,
`support_path` enum('yes','no') DEFAULT NULL,
`fatal_retry_interval` int(11) DEFAULT NULL,
`line` enum('yes','no') DEFAULT NULL,
`endpoint` varchar(40) DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_registrations_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_subscription_persistence` (
`id` varchar(40) NOT NULL,
`packet` varchar(2048) DEFAULT NULL,
`src_name` varchar(128) DEFAULT NULL,
`src_port` int(11) DEFAULT NULL,
`transport_key` varchar(64) DEFAULT NULL,
`local_name` varchar(128) DEFAULT NULL,
`local_port` int(11) DEFAULT NULL,
`cseq` int(11) DEFAULT NULL,
`tag` varchar(128) DEFAULT NULL,
`endpoint` varchar(40) DEFAULT NULL,
`expires` int(11) DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_subscription_persistence_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_systems` (
`id` varchar(40) NOT NULL,
`timer_t1` int(11) DEFAULT NULL,
`timer_b` int(11) DEFAULT NULL,
`compact_headers` enum('yes','no') DEFAULT NULL,
`threadpool_initial_size` int(11) DEFAULT NULL,
`threadpool_auto_increment` int(11) DEFAULT NULL,
`threadpool_idle_timeout` int(11) DEFAULT NULL,
`threadpool_max_size` int(11) DEFAULT NULL,
`disable_tcp_switch` enum('yes','no') DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_systems_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ps_transports` (
`id` varchar(40) NOT NULL,
`async_operations` int(11) DEFAULT NULL,
`bind` varchar(40) DEFAULT NULL,
`ca_list_file` varchar(200) DEFAULT NULL,
`cert_file` varchar(200) DEFAULT NULL,
`cipher` varchar(200) DEFAULT NULL,
`domain` varchar(40) DEFAULT NULL,
`external_media_address` varchar(40) DEFAULT NULL,
`external_signaling_address` varchar(40) DEFAULT NULL,
`external_signaling_port` int(11) DEFAULT NULL,
`method` enum('default','unspecified','tlsv1','sslv2','sslv3','sslv23') DEFAULT NULL,
`local_net` varchar(40) DEFAULT NULL,
`password` varchar(40) DEFAULT NULL,
`priv_key_file` varchar(200) DEFAULT NULL,
`protocol` enum('udp','tcp','tls','ws','wss') DEFAULT NULL,
`require_client_cert` enum('yes','no') DEFAULT NULL,
`verify_client` enum('yes','no') DEFAULT NULL,
`verify_server` enum('yes','no') DEFAULT NULL,
`tos` varchar(10) DEFAULT NULL,
`cos` int(11) DEFAULT NULL,
`allow_reload` enum('yes','no') DEFAULT NULL,
UNIQUE KEY `id` (`id`),
KEY `ps_transports_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# cat /etc/asterisk/sorcery.conf
[res_pjsip]
endpoint=realtime,ps_endpoints
auth=realtime,ps_auths
aor=realtime,ps_aors
domain_alias=realtime,ps_domain_aliases
contact=realtime,ps_contacts
[res_pjsip_endpoint_identifier_ip]
identify=realtime,ps_endpoint_id_ips
insert into ps_aors (id, max_contacts) values (403, 1);
insert into ps_aors (id, max_contacts) values (404, 1);
insert into ps_auths (id, auth_type, password, username) values (403, 'userpass', 'tpassword403', 403);
insert into ps_auths (id, auth_type, password, username) values (404, 'userpass', 'tpassword404', 404);
insert into ps_endpoints (id, transport, aors, auth, context, disallow, allow, direct_media) values (403, 'udp-transport-1', '403', '403', 'default', 'all', 'alaw', 'no');
insert into ps_endpoints (id, transport, aors, auth, context, disallow, allow, direct_media) values (404, 'udp-transport-1', '404', '404', 'default', 'all', 'alaw', 'no');
==== CHAN SIP ====
* [[http://asterisk-support.ru/question/58839/sipconf-perenesti-polzovatelei-v-realtime-mysql/|sip.conf перенести пользователей в realtime mysql]]
* [[http://middev.blogspot.ru/2012/05/asterisk-realtime.html|Что нам стоит “Asterisk realtime” построить]]
* [[http://voip.rus.net/tiki-index.php?page=Asterisk+Realtime+Sip|Asterisk RealTime SIP]]
* [[https://wiki.asterisk.org/wiki/display/AST/SIP+Realtime%2C+MySQL+table+structure|SIP Realtime, MySQL table structure]]
# cat chan_sip_realtime.sql
CREATE TABLE IF NOT EXISTS `sipfriends` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(10) NOT NULL,
`ipaddr` varchar(15) DEFAULT NULL,
`port` int(5) DEFAULT NULL,
`regseconds` int(11) DEFAULT NULL,
`defaultuser` varchar(10) DEFAULT NULL,
`fullcontact` varchar(35) DEFAULT NULL,
`regserver` varchar(20) DEFAULT NULL,
`useragent` varchar(20) DEFAULT NULL,
`lastms` int(11) DEFAULT NULL,
`host` varchar(40) DEFAULT NULL,
`type` enum('friend','user','peer') DEFAULT NULL,
`context` varchar(40) DEFAULT NULL,
`permit` varchar(40) DEFAULT NULL,
`deny` varchar(40) DEFAULT NULL,
`secret` varchar(40) DEFAULT NULL,
`md5secret` varchar(40) DEFAULT NULL,
`remotesecret` varchar(40) DEFAULT NULL,
`transport` enum('udp','tcp','udp,tcp','tcp,udp') DEFAULT NULL,
`dtmfmode` enum('rfc2833','info','shortinfo','inband','auto') DEFAULT NULL,
`directmedia` enum('yes','no','nonat','update') DEFAULT NULL,
`nat` enum('yes','no','never','route') DEFAULT NULL,
`callgroup` varchar(40) DEFAULT NULL,
`pickupgroup` varchar(40) DEFAULT NULL,
`language` varchar(40) DEFAULT NULL,
`allow` varchar(40) DEFAULT NULL,
`disallow` varchar(40) DEFAULT NULL,
`insecure` varchar(40) DEFAULT NULL,
`trustrpid` enum('yes','no') DEFAULT NULL,
`progressinband` enum('yes','no','never') DEFAULT NULL,
`promiscredir` enum('yes','no') DEFAULT NULL,
`useclientcode` enum('yes','no') DEFAULT NULL,
`accountcode` varchar(40) DEFAULT NULL,
`setvar` varchar(40) DEFAULT NULL,
`callerid` varchar(40) DEFAULT NULL,
`amaflags` varchar(40) DEFAULT NULL,
`callcounter` enum('yes','no') DEFAULT NULL,
`busylevel` int(11) DEFAULT NULL,
`allowoverlap` enum('yes','no') DEFAULT NULL,
`allowsubscribe` enum('yes','no') DEFAULT NULL,
`videosupport` enum('yes','no') DEFAULT NULL,
`maxcallbitrate` int(11) DEFAULT NULL,
`rfc2833compensate` enum('yes','no') DEFAULT NULL,
`mailbox` varchar(40) DEFAULT NULL,
`session-timers` enum('accept','refuse','originate') DEFAULT NULL,
`session-expires` int(11) DEFAULT NULL,
`session-minse` int(11) DEFAULT NULL,
`session-refresher` enum('uac','uas') DEFAULT NULL,
`t38pt_usertpsource` varchar(40) DEFAULT NULL,
`regexten` varchar(40) DEFAULT NULL,
`fromdomain` varchar(40) DEFAULT NULL,
`fromuser` varchar(40) DEFAULT NULL,
`qualify` varchar(40) DEFAULT NULL,
`defaultip` varchar(40) DEFAULT NULL,
`rtptimeout` int(11) DEFAULT NULL,
`rtpholdtimeout` int(11) DEFAULT NULL,
`sendrpid` enum('yes','no') DEFAULT NULL,
`outboundproxy` varchar(40) DEFAULT NULL,
`callbackextension` varchar(40) DEFAULT NULL,
`registertrying` enum('yes','no') DEFAULT NULL,
`timert1` int(11) DEFAULT NULL,
`timerb` int(11) DEFAULT NULL,
`qualifyfreq` int(11) DEFAULT NULL,
`constantssrc` enum('yes','no') DEFAULT NULL,
`contactpermit` varchar(40) DEFAULT NULL,
`contactdeny` varchar(40) DEFAULT NULL,
`usereqphone` enum('yes','no') DEFAULT NULL,
`textsupport` enum('yes','no') DEFAULT NULL,
`faxdetect` enum('yes','no') DEFAULT NULL,
`buggymwi` enum('yes','no') DEFAULT NULL,
`auth` varchar(40) DEFAULT NULL,
`fullname` varchar(40) DEFAULT NULL,
`trunkname` varchar(40) DEFAULT NULL,
`cid_number` varchar(40) DEFAULT NULL,
`callingpres` enum('allowed_not_screened','allowed_passed_screen','allowed_failed_screen','allowed','prohib_not_screened','prohib_passed_screen','prohib_failed_screen','prohib') DEFAULT NULL,
`mohinterpret` varchar(40) DEFAULT NULL,
`mohsuggest` varchar(40) DEFAULT NULL,
`parkinglot` varchar(40) DEFAULT NULL,
`hasvoicemail` enum('yes','no') DEFAULT NULL,
`subscribemwi` enum('yes','no') DEFAULT NULL,
`vmexten` varchar(40) DEFAULT NULL,
`autoframing` enum('yes','no') DEFAULT NULL,
`rtpkeepalive` int(11) DEFAULT NULL,
`call-limit` int(11) DEFAULT NULL,
`g726nonstandard` enum('yes','no') DEFAULT NULL,
`ignoresdpversion` enum('yes','no') DEFAULT NULL,
`allowtransfer` enum('yes','no') DEFAULT NULL,
`dynamic` enum('yes','no') DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
KEY `ipaddr` (`ipaddr`,`port`),
KEY `host` (`host`,`port`)
) ENGINE=MyISAM;
# mysql asterisk < chan_sip_realtime.sql
# mysql asterisk
MariaDB [asterisk]> delete from sipfriends;
insert into sipfriends(name, secret, host, type) values ('403', 'tpassword403', 'dynamic', 'friend');
insert into sipfriends(name, secret, host, type) values ('404', 'tpassword404', 'dynamic', 'friend');
* [[#Asterisk ODBC realtime]]
# cat /etc/asterisk/sip.conf
[general]
...
rtcachefriends=yes
rtcache=yes
...
# cat /etc/asterisk/extensions.conf
...
exten => _5XX,1,Answer()
exten => _5XX,n,Set(row="${REALTIME(sippeers,name,4${EXTEN:1})}")
exten => _5XX,n,NoOp(ROW is ${row})
exten => _5XX,n,Set(col_name_pair=${CUT(row,",",1)})
exten => _5XX,n,NoOp(${col_name_pair})
exten => _5XX,n,Hangup()
...
===== Asterisk MySQL =====
==== Установка asterisk-mysql ====
debian# apt install asterisk-mysql
debian# service asterisk restart
# asterisk -x 'module show' | grep mysql
==== Asterisk MySQL CDR ====
# cat cdr_mysql.conf
[global]
hostname=localhost
user=asterisk
password=asterisk
dbname=asterisk
table=cdr
[columns]
alias start => calldate
# service asterisk restart
server*CLI> cdr show status
...
* Registered Backends
-------------------
mysql
...
server*CLI> cdr mysql status
...
Wrote NNN records ...
==== Asterisk MySQL realtime ====
# cat /etc/asterisk/res_config_mysql.conf
[general]
dbhost = 127.0.0.1
dbname = asterisk
dbuser = asterisk
dbpass = asterisk
# cat /etc/asterisk/extconfig.conf
[settings]
sippeers => mysql,general,sipfriends
server*CLI> core reload
server*CLI> realtime mysql status
general connected to asterisk@127.0.0.1, port 3306 with username asterisk for 12 seconds.
==== Asterisk MySQL dialplan ====
# apt install asterisk-mysql
# cat extensions.conf
...
exten => 312,1,Answer()
same => n,MYSQL(Connect connid localhost asterisk asterisk asterisk)
; same => n,MYSQL(Query resultid ${connid} SET NAMES 'utf8')
same => n,MYSQL(Query resultid ${connid} SELECT name, fullname FROM sipfriends)
same => n(loop),MYSQL(Fetch fetchid ${resultid} NM FN)
same => n,GotoIf($[${fetchid} = 0]?clear)
same => n,NoOp(fetchid ${fetchid} ${FN} ${NM})
same => n,SayDigits(${NM})
; same => n,Festival(${FN})
same => n,Goto(312,loop)
same => n(clear),MYSQL(Clear ${resultid})
same => n,MYSQL(Disconnect ${connid})
same => n,Hangup()
...
exten => _6XX,1,MYSQL(Connect connid localhost asterisk asterisk asterisk)
; same => n,MYSQL(Query resultid ${connid} SET NAMES 'utf8')
same => n,MYSQL(Query resultid ${connid} SELECT fullname FROM sipfriends where name="4${EXTEN:1}")
same => n,MYSQL(Fetch fetchid ${resultid} FN)
same => n,NoOp(fullname ${FN})
; same => n,Festival(${FN})
same => n,MYSQL(Clear ${resultid})
same => n,MYSQL(Disconnect ${connid})
same => n,Hangup()
...
===== Asterisk ODBC =====
* [[Сервис ODBC]]
==== Подключение Asterisk ODBC ====
* !!! Не совместим с пакетом asterisk-mysql
# asterisk -x 'module show' | grep odbc
# cat /etc/asterisk/res_odbc.conf
[asterisk]
enabled => yes
dsn => asterisk
pre-connect => yes
server*CLI> core reload
server*CLI> odbc show all
ODBC DSN Settings
-----------------
Name: asterisk
DSN: asterisk
Number of active connections: 1 (out of 1)
==== Asterisk ODBC CDR ====
# cat /etc/asterisk/cdr_adaptive_odbc.conf
[default]
connection=asterisk
table=cdr
# service asterisk restart
server*CLI> cdr show status !!! Ничего не изменилось, поискать другую команду
==== Asterisk ODBC realtime ====
# cat /etc/asterisk/modules.conf
...
;noload => res_config_odbc.so
...
# cat /etc/asterisk/extconfig.conf
[settings]
sippeers => odbc,asterisk,sipfriends
ps_endpoints => odbc,asterisk
ps_auths => odbc,asterisk
ps_aors => odbc,asterisk
ps_domain_aliases => odbc,asterisk
ps_endpoint_id_ips => odbc,asterisk
ps_contacts => odbc,asterisk
==== Asterisk ODBC функции ====
# cat /etc/asterisk/func_odbc.conf
...
[LAST_DSTCHANNEL_BY_CALLERID]
dsn=asterisk
readsql=SELECT dstchannel FROM cdr WHERE src='${ARG1}' AND disposition='ANSWERED' ORDER BY calldate DESC LIMIT 1;
# cat /etc/asterisk/extensions.conf
...
exten => voip1_00000X,1,Set(MY-DST-CHAN=${ODBC_LAST_DSTCHANNEL_BY_CALLERID(${CALLERID(num)})})
exten => voip1_00000X,n,Set(MY-DST-CHAN=${CUT(MY-DST-CHAN,"-",1)})
exten => voip1_00000X,n,ExecIf($[${LEN(${MY-DST-CHAN})} = 0]?Set(MY-DST-CHAN=SIP/401&SIP/402&SIP/403&SIP/404))
exten => voip1_00000X,n,Dial(${MY-DST-CHAN},10)
exten => voip1_00000X,n,Dial(SIP/401&SIP/402&SIP/403&SIP/404)
...
===== Аутентификация и учет звонков в RADIUS =====
* [[Сервис FreeRADIUS]]
# cat /usr/share/auth.sh
#!/bin/sh
CALL_FROM=$1
# chown asterisk /tmp/auth.log
if echo "User-Name=${CALL_FROM},User-Password=${CALL_FROM},NAS-IP-Address=127.0.0.1" | radclient localhost auth testing123 >>/tmp/auth.log
then
echo -n YES
else
echo -n NO
fi
exit 0
# cat /usr/share/acct-start.sh
#!/bin/sh
CALL_ID=$1
CALL_FROM=$2
CALL_TO=$3
echo "User-Name=${CALL_FROM},Acct-Session-Id=${CALL_ID},Called-Station-Id=${CALL_TO},Calling-Station-Id=${CALL_FROM},Acct-Status-Type=Start,NAS-IP-Address=127.0.0.1,NAS-Port=${CALL_FROM}${CALL_TO}"| radclient localhost acct testing123
exit 0
# cat /usr/share/acct-stop.sh
#!/bin/sh
CALL_ID=$1
CALL_FROM=$2
CALL_TO=$3
echo "User-Name=${CALL_FROM},Acct-Session-Id=${CALL_ID},Acct-Status-Type=Stop,NAS-IP-Address=127.0.0.1,NAS-Port=${CALL_FROM}${CALL_TO}"| radclient localhost acct testing123
exit 0
Примечания:
* Помещаем абонента, звонки которого надо тарифицировать, в контекст billing
* Переводим все тарифицируемые вызовы в контекст aaa-call (что-бы отследить событие окончания разговора через контекст "h")
* В случае MYAUTH!=NO разрешаем абоненту совершить звонок. С помощью макроса "U" программируем вызов кода в момент снятия трубки для начала тарификации. По какой то причине переменные ${CALLERID(num)} ${CALLERID(dnid)} не передаются, а ${UNIQUEID} меняет значение в этом коде, поэтому занчения передаются через аргументы.
* В контексте "h" проверяем факт наличия разговора и только в этом случае тарифицируем его окончание
# cat /etc/asterisk/extensions.conf
...
[billing]
...
exten => _4XX,1,Goto(aaa-call,s,1)
...
[aaa-call]
exten => s,1,Verbose(AUTH CALL_ID=${UNIQUEID} CALL_FROM=${CALLERID(num)} CALL_TO=${CALLERID(dnid)})
exten => s,n,Set(MYAUTH=${SHELL(/usr/share/auth.sh ${CALLERID(num)})});
exten => s,n,GotoIf($["${MYAUTH}" = "NO"]?end_call)
exten => s,n,Dial(SIP/${CALLERID(dnid)},,U(aaa-call-beg-acct,${UNIQUEID},${CALLERID(num)},${CALLERID(dnid)}));
exten => s,n(end_call),Hangup()
exten => h,1,GotoIf($["${DIALSTATUS}" != "ANSWER"]?no-answer)
exten => h,n,Verbose(END ACCT DIALSTATUS=${DIALSTATUS} CALL_ID=${UNIQUEID} CALL_FROM=${CALLERID(num)} CALL_TO=${CALLERID(dnid)})
exten => h,n,System(/usr/share/acct-stop.sh ${UNIQUEID} ${CALLERID(num)} ${CALLERID(dnid)})
exten => h,n(no-answer),NoOp()
[aaa-call-beg-acct]
exten => s,1,Verbose(BEGIN ACCT CALL_ID=${ARG1} CALL_FROM=${ARG2} CALL_TO=${ARG3})
exten => s,n,System(/usr/share/acct-start.sh ${ARG1} ${ARG2} ${ARG3})
exten => s,n,return
...
===== Настройка дополнительных видов обслуживания =====
==== Базовая конфигурация ====
Настройка прохождения трафика и сигнализации через asterisk и режима тонального набора для всех каналов
server# cat /etc/asterisk/sip.conf
[general]
...
;canreinvite=no
directmedia=no
dtmfmode=rfc2833
...
==== Перевод вызова на другого абонента ====
* С сопровождение и слепой
* Клавиша "flash" аналогового телефона
* Кнопка "transfer" ip телефона
* Программируемая комбинация DTMF
server# cat /etc/asterisk/features.conf
[general]
...
featuredigittimeout = 3000
...
[featuremap]
...
blindxfer => *21
atxfer => *22
...
server# cat /etc/asterisk/extensions.conf
...
exten => _4XX,1,Dial(SIP/${EXTEN},,Tt)
...
exten => voip1_00000X,1,Dial(SIP/401,10,t)
exten => voip1_00000X,n,Dial(SIP/401&SIP/402&SIP/403,,t)
server*CLI> core reload
server*CLI> features show
==== Мониторинг текущего состояния абонента (BLF) ====
=== Настройка asterisk ===
* [[http://bos-info.com/asterisk/hints.html|My IT-blog hints(Дополнено)]]
* [[http://voip.rus.net/tiki-index.php?page=Asterisk+standard+extensions&highlight=hint|Стандартные расширения]]
* [[https://wiki.asterisk.org/wiki/display/AST/Configuring+chan_sip+for+Presence+Subscriptions|Configuring chan_sip for Presence Subscriptions]]
# cat /etc/asterisk/sip.conf
[general]
...
allowsubscribe=yes
notifyhold=yes
callcounter=yes
notifyringing=yes
limitonpeers=yes
subscribecontext=default
...
[4NN]
...
;allowsubscribe=no
...
# cat /etc/asterisk/extensions.conf
[default]
...
exten => _4XX,hint,SIP/${EXTEN}
...
=== Настройка телефонов ===
* [[DrayTek SIP Softphone]]
* [[SIP Phone Panasonic KX-HDVXXX]]
=== Мониторинг ===
server*CLI> sip show subscriptions
server*CLI> core show hints
==== Перехват вызова ====
* [[https://wiki.asterisk.org/wiki/display/AST/Call+Pickup|Call Pickup]]
server# cat /etc/asterisk/sip.conf
...
[401]
callgroup=1
pickupgroup=1
;namedcallgroup=gr1,gr2,gr3
;namedpickupgroup=gr2,gr3,gr4
...
[403]
callgroup=1
pickupgroup=1
server# cat /etc/asterisk/features.conf
...
[general]
...
pickupexten = *88
...
server*CLI> features show
==== Парковка разговора ====
Сценарий:
снимаем трубку чужого, звонящего телефона, просим подождать, набираем *21700, слушаем номер слота, кладем трубку. Со своего телефона набираем номер слота и продолжаем разговор.
asterisk11# less /etc/asterisk/features.conf
asterisk13# less /etc/asterisk/res_parking.conf
...
[default]
parkext => 700
parkpos => 701-720
...
context => parkedcalls
...
server# cat /etc/asterisk/extensions.conf
[default]
include => parkedcalls
...
exten => _8XXXXXXXXXX,1,Dial(SIP/voip1_00000X/${EXTEN},,T)
...
exten => voip1_00000X,1,Dial(SIP/401,,t)
...
===== Локализация сообщений Asterisk =====
==== Кодеки ====
*CLI> core show codecs
*CLI> core show translation
==== Установка из пакетов ====
root@server:~# apt install asterisk-core-sounds-ru-wav
root@server:~# find /usr/share/asterisk/sounds/ru/
==== Установка с сайта ====
server# cd /usr/share/asterisk/sounds
server# mkdir ru; cd ru/
server# wget http://downloads.asterisk.org/pub/telephony/sounds/asterisk-core-sounds-ru-alaw-current.tar.gz
server# tar -xvf asterisk-core-sounds-ru-alaw-current.tar.gz
==== Настройка локализации ====
server# cat /etc/asterisk/asterisk.conf
...
[options]
...
defaultlanguage = ru
...
# service asterisk restart
server# cat /etc/asterisk/sip.conf
[general]
language=ru
...
[401]
language=ru
...
server# cat /etc/asterisk/extensions.conf
...
exten => 301,1,Answer()
exten => 301,n,Playback(hello-world)
exten => 301,n,Set(CHANNEL(language)=en)
exten => 301,n,Playback(hello-world)
exten => 301,n,Hangup()
...
===== Голосовая почта =====
server# cat /etc/asterisk/voicemail.conf
[general]
...
;;;For IMAP/SMTP
;charset=UTF-8
;locale=ru_RU.UTF-8
;emailsubject=Голосовое сообщение от абонента ${VM_CALLERID}
;emailbody=Здравствуйте ${VM_NAME}\n\n${VM_DATE} получено голосовое сообщение от абонента ${VM_CALLERID}
;emaildateformat=%A, %B %d, %Y в %r
...
;;;For IMAP
;;;debian# apt install asterisk-voicemail-imapstorage
;;;debian# cp /etc/dovecot/private/dovecot.pem /usr/local/share/ca-certificates/dovecot.crt
;;;debian# update-ca-certificates
;;;debian# service asterisk restart
;imapserver=server.corpX.un
;imapfolder=INBOX
;;;For SMTP
;debian# apt install postfix mailutils
...
[corpX]
;401 => ,,
;402 => 2222,,
;403 => ,Ваше Имя Отчество Фамилия,user3@corpX.un,,attache=yes|delete=yes
;404 => 4444,Ваше Имя Отчество Фамилия,,,imapuser=student|imappassword=password
server*CLI> voicemail reload
server# cat /etc/asterisk/extensions.conf
[default]
...
exten => 390,1,VoiceMailMain(@corpX)
;exten => 391,1,VoiceMailMain(${CALLERID(num)}@corpX)
;exten => asterisk,1,VoiceMailMain(${CALLERID(num)}@corpX)
...
exten => _4XX,1,Dial(SIP/${EXTEN},10,Tt)
exten => _4XX,n,VoiceMail(${EXTEN}@corpX)
exten => _4XX,n,Hangup()
...
Альтернативный dialplan для прослушивания голосовой почты (звонок на номер своего телефона)
exten => _4XX,1,GotoIf($["${CALLERID(num)}" = "${EXTEN}"]?MAIL)
exten => _4XX,n,Dial(SIP/${EXTEN},10)
exten => _4XX,n,VoiceMail(${EXTEN}@corpX)
exten => _4XX,n,Hangup()
exten => _4XX,n(MAIL),VoiceMailMain(${EXTEN}@corpX)
exten => _4XX,n,Hangup()
server# cat /etc/asterisk/sip.conf
...
[401]
;allowsubscribe=no
mailbox=401@corpX
...
[402]
mailbox=402@corpX
...
[403]
mailbox=403@corpX
...
[404]
mailbox=404@corpX
...
server# ls /var/spool/asterisk/voicemail/corpX/
server# ls -l /var/mail/
===== Конференц связь =====
* [[http://voip.rus.net/tiki-index.php?page=Asterisk+ConfBridge|Приложение ConfBridge]]
* [[https://asterisk-pbx.ru/wiki/asterisk/app/originate|Asterisk app: Originate]]
==== Настройка ====
* Сценарий 1: все желающие участвовать в конференции звонят на заранее обговоренный номер 6NN
* Сценарий 2: ответственный за проведение конференции обзванивает участников и переводит вызовы в конференцию набирая *216NN
* Сценарий 3: ответственный звонит на номер 389, у участников 401 и 403 звонят телефоны и ответственный тоже становится участником конференции.
server# cat /etc/asterisk/extensions.conf
[default]
...
exten => 389/402,1,Originate(SIP/401,exten,default,601,1)
exten => 389/402,n,Originate(SIP/403,exten,default,601,1)
exten => 389/402,n,ConfBridge(601)
exten => _6XX,1,ConfBridge(${EXTEN})
...
==== Отладка ====
server# asterisk -x "confbridge list 601"
...
===== Организация обратных вызовов =====
==== Из командной строки ====
* [[http://asterisk-support.ru/forum/topics/7351|Проблемы с CallerID]]
# asterisk -x "channel originate SIP/401 extension 601@default"
# asterisk -x "channel originate SIP/402 extension 601@default"
# asterisk -x "channel originate SIP/403 extension 601@default"
; сначала вызов телефона оператора, затем вызов абонента
server*CLI> channel originate SIP/403 extension 89161234567@default
; Сначала вызов абонента, затем обработчика (например - IVR)
server*CLI> channel originate SIP/voip1_00000X/89161234567 extension voip1_00000X@default
server*CLI> channel originate PJSIP/89161234567@voip1_00000X extension voip1_00000X@default
; сначала вызов обработчика (например - все телефоны в офисе или оператор/агент из членов очереди), затем вызов абонента
server*CLI> channel originate Local/voip1_00000X@default extension 89161234567@default
# cat /usr/share/originate_cli.sh
#!/bin/sh
asterisk -x "channel originate SIP/$1 extension $2@default"
# /usr/share/originate_cli.sh 403 601
==== С использованием Call файлов ====
* [[https://docs.asterisk.org/Configuration/Interfaces/Asterisk-Call-Files/|Asterisk Call Files]]
* [[Сервис atrun]]
# cat call.txt
Channel: Local/voip1_00000X@default
Extension: 89161234567
Context: default
CallerId: CorpX<84992636363>
server# grep astspooldir /etc/asterisk/asterisk.conf
server# cp call.txt /var/spool/asterisk/outgoing/
server# ls /var/spool/asterisk/outgoing_done
# cat /usr/share/originate_call_file.sh
#!/bin/sh
cat </var/spool/asterisk/outgoing/$1$2$3
Channel: SIP/$1
Extension: $2
Context: default
CallerId: $2<$3>
EOF
# chmod +x /usr/share/originate_call_file.sh
# /usr/share/originate_call_file.sh 401 601 Conferencia
# /usr/share/originate_call_file.sh 402 601 Conferencia
# /usr/share/originate_call_file.sh 401 601 Conferencia
==== Пример с использованием Asterisk AMI ====
* [[#Asterisk AMI]]
==== Пример с использованием Asterisk ARI ====
* [[#Asterisk ARI]]
# curl -v -X POST "http://localhost:8088/ari/channels?endpoint=SIP%2F403&extension=301&context=default&callerId=301&api_key=asterisk:asterisk"
или
# curl -v -u asterisk:asterisk -X POST "http://localhost:8088/ari/channels?endpoint=SIP%2F403&extension=301&context=default&callerId=301"
===== Запись звукового файла =====
sever# cat /etc/asterisk/extensions.conf
...
exten => 302,1,Authenticate(1234)
exten => 302,n,Playback(vm-intro)
exten => 302,n,Record(recordings/speech.alaw,,,xk)
exten => 302,n,Hangup()
exten => 303,1,Answer()
exten => 303,n,Playback(beep)
exten => 303,n,Playback(recordings/speech)
exten => 303,n,Playback(beep)
exten => 303,n,Hangup()
...
# ls -lh /usr/share/asterisk/sounds/recordings/
===== Интерактивное голосовое меню IVR =====
* [[https://www.voip-info.org/wiki/view/Asterisk+standard+extensions|Asterisk standard extensions]]
==== Реализация с использованием стандартного языка описания диалплана ====
sever# cat /etc/asterisk/extensions.conf
...
exten => 304,1,Goto(menu,s,1) ; for debug
...
exten => voip1_00000X,1,Goto(menu,s,1)
...
[menu]
exten => s,1,Background(recordings/speech)
exten => s,n,Goto(s,1)
; exten => 1,1,Dial(SIP/401)
; exten => 2,1,Dial(SIP/402)
; exten => 3,1,Dial(SIP/403)
; exten => _X,1,Dial(SIP/40${EXTEN})
exten => _X,1,Goto(default,40${EXTEN},1)
exten => _4XX,1,Goto(default,${EXTEN},1)
;exten => 0,1,Goto(menu2,s,1)
;exten => 0,1,DISA(no-password,default)
;exten => _[34]XX,1,Goto(default,${EXTEN},1)
;exten => _[43]XX,1,Dial(Local/{EXTEN}@default)
;[menu2]
;exten => s,1,Background(silence/8)
;exten => s,n,WaitExten(8) ; работает только после Answer или Background
;exten => _4XX,1,Goto(default,${EXTEN},1)
;exten => t,1,Goto(menu,s,1) ; timeout exceeded, работает только с WaitExten
;exten => i,1,Goto(menu,s,1) ; error extensions
==== Реализация с использованием AEL ====
* [[http://voip.rus.net/tiki-index.php?page=Asterisk+AEL|The Asterisk Extension Language (Язык Расширения Астериска)]]
sever# cat /etc/asterisk/extensions.conf
[default]
...
include => ivr
...
;[incoming]
exten => voip1_00000X,1,Goto(menu,s,1)
sever# cat /etc/asterisk/extensions.ael
context ivr {
302 => {
Answer();
Record(recordings/speech:alaw);
Hangup();
}
303 => {
Answer();
Playback(beep);
Playback(recordings/speech);
Playback(beep);
Hangup();
}
304 => {
goto menu|s|begin;
}
}
context menu {
s => {
begin:
Background(recordings/speech);
goto begin;
}
_X => {
goto default|40${EXTEN}|1;
}
}
===== Прослушивание разговоров =====
* [[https://wiki.merionet.ru/ip-telephoniya/34/modul-chanspy-v-asterisk/|МОДУЛЬ CHANSPY В ASTERISK]]
server# cat /etc/asterisk/extensions.conf
[default]
...
exten => _5XX/402,1,ChanSpy(SIP/4${EXTEN:1},qw)
...
===== Запись разговоров =====
==== Запись по желанию абонента ====
* Если создается два файла - in и out, то ([[http://asterisk.ru/knowledgebase/Asterisk+config+features.conf|можно смикшировать в один, используя утилиту sox]])
* [[http://asterisk-support.ru/question/59823/touch-mix-monitor-prefiks/|touch mix monitor префикс]]
server# cat /etc/asterisk/features.conf
...
[featuremap]
...
automon => *11
...
server# cat /etc/asterisk/extensions.conf
...
exten => _4XX,n,Set(TOUCH_MONITOR=${STRFTIME(${EPOCH},,%Y.%m.%d-%H.%M)}_${CALLERID(number)}_${EXTEN})
exten => _4XX,n,Dial(SIP/${EXTEN},,wW)
...
exten => _8XXXXXXXXXX,1,Set(TOUCH_MONITOR=${STRFTIME(${EPOCH},,%Y.%m.%d-%H.%M)}_${CALLERID(number)}_${EXTEN})
exten => _8XXXXXXXXXX,n,Dial(SIP/voip1_00000X/${EXTEN},,W)
..
server*CLI> core reload
server# ls /var/spool/asterisk/monitor/
==== Автоматическая запись средствами Asterisk ====
server# cat /etc/asterisk/extensions.conf
...
[menu]
...
exten => _X,1,Set(MY-FILE-NAME=${STRFTIME(${EPOCH},,%Y.%m.%d-%H.%M)}_${CALLERID(number)}_40${EXTEN}.wav)
exten => _X,n,MixMonitor(${MY-FILE-NAME},b)
exten => _X,n,Goto(default,40${EXTEN},1)
...
server*CLI> dialplan reload
server# ls /var/spool/asterisk/monitor/
==== Автоматическая запись путем анализа трафика ====
* [[http://oreka.sourceforge.net/|The Open Source Enterprise Telephony Recording and Retrieval System]]
===== MOH =====
==== Добавление своих звуковых файлов ====
* [[https://www.voip-info.org/wiki/view/Convert+WAV+audio+files+for+use+in+Asterisk|Convert WAV audio files for use in Asterisk]]
* Перекодировка mp3 в raw формат для asterisk ([[Перекодировка звука]])
root@server:~# rm /usr/share/asterisk/moh/*
root@server:~# cp Knockin_on_Heavens_Door.raw /usr/share/asterisk/moh/
server*CLI> moh reload
server*CLI> moh show files
server# cat /etc/asterisk/extensions.conf
...
exten => 305,1,Answer()
exten => 305,n,MusicOnHold()
exten => 305,n,MusicOnHold(busy)
...
==== Добавление своих классов ====
server# mkdir /usr/share/asterisk/incoming
server# cp -v /usr/share/asterisk/sounds/recordings/speech.alaw /usr/share/asterisk/incoming/
server# mkdir /usr/share/asterisk/busy/
server# cp -v /usr/share/asterisk/sounds/ru/tt-allbusy.* /usr/share/asterisk/busy/
server# mkdir /usr/share/asterisk/silence/
server# cp -v /usr/share/asterisk/sounds/en/silence/10.* /usr/share/asterisk/silence/
server# cat /etc/asterisk/musiconhold.conf
...
[incoming]
mode=files
directory=incoming
[busy]
mode=files
directory=busy
[silence]
mode=files
directory=silence
server# cat /etc/asterisk/extensions.conf
...
exten => voip1_00000X,1,Dial(SIP/4NN,,m(incoming)t)
===== Синтез речи с использованием пакета Festival =====
* [[Сервис Festival]]
# asterisk -x 'module show' | grep fest
server# cat /etc/asterisk/extensions.conf
...
exten => 324,1,Answer()
;exten => 324,n,Festival(Hello World)
;exten => 324,n,Festival(Привет Мир)
exten => 324,n,Hangup()
;Плохо воспроизводит длинный текст
;exten => 325,1,Answer()
;exten => 325,n,Set(ZABBIX-MESSAGE=${FILE(/tmp/zabbix.txt)})
;exten => 325,n,Festival(${ZABBIX-MESSAGE})
;exten => 325,n,Hangup()
;exten => 326,1,Answer()
;exten => 326,n,Wait(3)
;exten => 326,n,Playback(/tmp/zabbix)
;exten => 326,n,Playback(/tmp/zabbix)
;exten => 326,n,Playback(/tmp/zabbix)
;exten => 326,n,Hangup()
;exten => 327,1,Answer()
;exten => 327,n,Set(TOP-CPU=${SHELL(ps ax -o pcpu,command --sort pcpu | cut -d' ' -f3 | tail -n5 | xargs -I CMD basename CMD)})
;exten => 327,n,Festival(${TOP-CPU})
;exten => 327,n,Hangup()
...
exten => _4XX,1,Dial(SIP/${EXTEN},10)
;exten => _4XX,n,Set(MY-CALLED-USER-NAME=${ODBC_SIPFRIENDS_BY_NAME(${EXTEN})})
exten => _4XX,n,Set(MY-CALLED-USER-NAME=${SIPPEER(${EXTEN},callerid_name)})
;exten => _4XX,n,Set(MY-CALLED-USER-NAME=${PJSIP_ENDPOINT(${EXTEN},callerid)})
exten => _4XX,n,Festival(${MY-CALLED-USER-NAME} не может ответить)
===== Переадресация вызовов на внешний номер =====
==== Использование FollowMe ====
server# cat /etc/asterisk/followme.conf
[101+X]
;number=>401,30
;number=>89162323232,30
context=>default
;context=>to-pstn
[401]
number=>89162323232,30
;number=>89163434345,30
context=>default
;context=>to-pstn
server# cat /etc/asterisk/extensions.conf
;...
exten => _4XX,1,Dial(SIP/${EXTEN},10,t)
exten => _4XX,n,FollowMe(${EXTEN})
=== Использование MySQL ===
* [[https://habrahabr.ru/post/262439/|Оптимизируем листинг диалплана Asterisk при помощи MySQL]]
=== Использование AstDB ===
* [[#Перенаправление звонков]]
===== AstDB =====
server*CLI> database show
==== Использование AstDB для связи номеров и учетных записей ====
server*CLI> database put num2login 401 user1
server*CLI> database put num2login 402 user2
server*CLI> database put num2login 403 user3
server*CLI> database show num2login
# cat /etc/asterisk/extensions.conf
;exten => _[a-z].,1,Dial(SIP/${EXTEN})
exten => _4XX,1,Set(MY-LOGIN=${DB(num2login/${EXTEN})})
exten => _4XX,n,ExecIf($[ "${MY-LOGIN}" = "" ]?Set(MY-LOGIN=${EXTEN}))
exten => _4XX,n,Verbose(1,variable MY-LOGIN set to ${MY-LOGIN})
exten => _4XX,n,Dial(SIP/${MY-LOGIN})
==== Использование AstDB для перенаправления вызовов ====
server*CLI> database put redirect 403 89166071103
server*CLI> database get redirect 403
server*CLI> database show redirect
server*CLI> database del redirect 403
server# cat /etc/asterisk/extensions.conf
...
[default]
...
exten => 308,1,Answer()
exten => 308,n,Goto(setredirect,s,1)
exten => 309,1,Answer()
exten => 309,n,Playback(beep)
exten => 309,n,NoOp(${DB_DELETE(redirect/${CALLERID(num)})})
exten => 309,n,Hangup()
...
exten => _4XX,1,Dial(SIP/${EXTEN},10,t)
exten => _4XX,n,Set(MY-REDIRNUM=${DB(redirect/${EXTEN})})
exten => _4XX,n,GotoIf(${MY-REDIRNUM}?CALLMOBILE)
...
exten => _4XX,n(CALLMOBILE),Goto(default,${MY-REDIRNUM},1)
...
[setredirect]
exten => s,1,Playback(beep)
exten => s,n,WaitExten()
exten => _8XXXXXXXXXX,1,Set(DB(redirect/${CALLERID(num)})=${EXTEN})
exten => _8XXXXXXXXXX,n,Playback(beep)
exten => _8XXXXXXXXXX,n,SayDigits(${EXTEN})
exten => _8XXXXXXXXXX,n,Playback(beep)
exten => _8XXXXXXXXXX,n,Hangup()
===== Подсчет количества одновременных вызовов абонента =====
==== С использованием функции SIPPEER ====
* [[http://asterisk.ru/knowledgebase/Asterisk+func+sippeer|Функция SIPPEER()]]
* !!! curcalls работает только если для канала установлено ограничение на число одновременных вызовов (call-limit)
server*CLI> core show function SIPPEER
exten => _4XX,1,Set(MY-CALLS-COUNT=${SIPPEER(${EXTEN},curcalls)})
exten => _4XX,n,Verbose(2,*** MY-CALLS-COUNT = ${MY-CALLS-COUNT} ***)
exten => _4XX,n,ExecIf($[ ${MY-CALLS-COUNT} > 0 ]?Set(MY-CLASS-MOH=busy))
exten => _4XX,n,Dial(SIP/${EXTEN},,tTm(${MY-CLASS-MOH}))
==== С использованием GROUP_COUNT ====
* [[https://forum.nag.ru/index.php?/topic/88711-resheno-asterisk-call-limit/|Asterisk call-limit]]
* [[https://habr.com/post/180445/|Asterisk в примерах: балансировка каналов]]
exten => _4XX,1,Set(GROUP(MYCALLTO)=${EXTEN})
exten => _4XX,n,Set(MYCALLS=${GROUP_COUNT(${GROUP(MYCALLTO)})})
exten => _4XX,n,Verbose(2,*** ${MYCALLS} ***)
exten => _4XX,n,ExecIf($[ ${MYCALLS} > 1 ]?Set(MYCLASSMOH=busy))
exten => _4XX,n,Verbose(2,(*** ${MYCLASSMOH} ***)
exten => _4XX,n,Dial(SIP/${EXTEN},10,Ttm(${MYCLASSMOH}))
===== Обработка статуса вызова =====
* [[http://voip.rus.net/tiki-index.php?page=Asterisk+variable+DIALSTATUS|Переменная канала в Asterisk: DIALSTATUS]]
[default]
exten => _X!,1,Goto(pbx-invalid,s,1)
...
exten => _4XX,1,Dial(SIP/${EXTEN},,Tt)
exten => _4XX,n,Verbose(1,Значение DIALSTATUS равно ${DIALSTATUS})
exten => _4XX,n,GotoIf($["${DIALSTATUS}" = "CHANUNAVAIL"]?pbx-invalid,s,1)
...
[pbx-invalid]
exten => s,1,Playback(pbx-invalid)
Абдирахимов Мансур представил решение "Vip звонок" - определенный номер при звонке на офисный телефон соединялся с определенным номером даже если последний разговаривает.
[office]
...
exten => s,n,Gotoif($["${CALLERID(num)}"="9259280996"]?delta,s,1)
...
[delta];Звонок от Директора
exten => s,1,Playback(priv-trying)
exten => s,n,ExecIf($["${DIALSTATUS}"="${BUSY}"]?Bridge(SIP/854))
exten => s,n,Dial(SIP/854)
Кузьмин Алексей предложил решение, если требуется только уведомить звонящего
exten => _X.,1,Dial(PJSIP/${EXTEN},60)
exten => _X.,n,Goto(s-${DIALSTATUS},1) ; Jump based on status (NOANSWER, BUSY, CHANUNAVAIL, CONGESTION, ANSWER)
exten => s-BUSY,1,Playback(ru/custom/busy_ru)
exten => s-BUSY,n,Hangup()
exten => s-NOANSWER,1,Playback(ru/custom/noanswer_ru)
exten => s-NOANSWER,n,Hangup()
exten => s-CHANUNAVAIL,1,Playback(ru/custom/invalid_ru)
exten => s-CHANUNAVAIL,n,Hangup()
===== Организация Call центра =====
==== Автоматизация распределения вызовов ACD ====
=== Организация очередей ===
* [[https://asterisk-pbx.ru/wiki/asterisk/cf/queues.conf|Asterisk настройка очереди - queues.conf]]
* [[https://asterisk-pbx.ru/wiki/asterisk/app/queue|Команда Asterisk: Queue]]
server# cat /etc/asterisk/queues.conf
[general]
persistentmembers = yes
[queue1]
;timeout=10
;для демонстрации на многоканальном телефоне установить call-limit=1
;member => SIP/403 ; (можно занять звонком на 311)
;member => SIP/user1@mailcgp
;member => SIP/user2@mailcgp
;member => SIP/user3@mailcgp
sever# cat /etc/asterisk/extensions.conf
...
;[incoming]
exten => voip1_00000X,1,Answer()
exten => voip1_00000X,n,Queue(queue1)
...
=== Регистрация агентов ===
* [[http://zarubochki.ru/asterisk_agents_conf|Asterisk. Конфигурационный файл agents.conf]]
asterisk# /etc/asterisk/agents.conf
[general]
[my-agents](!)
;musiconhold=silence
[801](my-agents)
fullname=Ivan Ivanovitch Ivanov
[802](my-agents)
fullname=Petr Petrovitch Petrov
[803](my-agents)
fullname=Your name
asterisk# cat /etc/asterisk/extensions.conf
[default]
...
exten => _8XX,1,AgentLogin(${EXTEN})
...
[agents]
exten => _8XX,1,AgentRequest(${EXTEN})
same => n,Hangup()
=== Использование агентов в очередях ===
asterisk# cat /etc/asterisk/queues.conf
[general]
persistentmembers = yes
[queue1]
strategy = rrmemory
musicclass = default
announce = queue-markq
announce-frequency = 30
announce-position = yes
announce-position-limit = 1
member => Local/801@agents
member => Local/802@agents
member => Local/803@agents
server*CLI> queue show queue1
server*CLI> agent show online
===== Интерфейсы взаимодействия с внешними программами =====
==== Приложение System ====
* [[https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+Application_System|Asterisk Application_System]]
* [[https://www.voip-info.org/wiki/view/Asterisk+cmd+System|Asterisk cmd System]]
* [[http://www.itp-redial.com/class/weekly-notes/week4-notes/system-and-shell|System and SHELL]]
* [[Пакет sudo]]
server# cat /etc/asterisk/extensions.conf
[default]
...
exten => 398,1,Authenticate(1234)
exten => 398,n,System(/usr/bin/sudo /sbin/init 6)
...
==== Функция SHELL ====
* !!! Название функции только ЗАГЛАВНЫМИ буквами
* [[https://www.voip-info.org/wiki/view/Asterisk+func+shell|Asterisk func shell]]
* Сервис HTTP [[Сервис HTTP#Управление кодировкой]]
* http://172.16.1.X/asterisk/addrbook.txt
# mkdir /var/www/html/asterisk/
# cat /var/www/html/asterisk/addrbook.txt
Вячеслав Лохтуров<+74951234569>
Вячеслав Лохтуров<+74951234560>
Ваше ФИО<+7ВАШМОБИЛЬНЫЙ>
# cat /usr/local/bin/get-customer-callerid-all.sh
#!/bin/sh
PHONE=$1
ADDR_BOOK=/var/www/html/asterisk/addrbook.txt
grep $PHONE $ADDR_BOOK || echo $PHONE
# chmod +x /usr/local/bin/get-customer-callerid-all.sh
# cat /etc/asterisk/extensions.conf
...
exten => _4XX,n,ExecIf($["${CALLERID(name)}"=""]?Set(CALLERID(all)=${SHELL(/usr/local/bin/get-customer-callerid-all.sh ${CALLERID(num)})}))
...
exten => voip1_00000X,1,Set(CALLERID(all)=${SHELL(/usr/local/bin/get-customer-callerid-all.sh ${CALLERID(num)})})
exten => voip1_00000X,n,Dial(SIP/401&SIP/402&SIP/403&SIP/404)
...
==== Asterisk AGI ====
* [[http://www.voip-info.org/wiki/view/Asterisk+AGI|Asterisk Gateway Interface (AGI)]]
* [[http://www.it4ru.ru/index.php/ru/2-uncategorised/17-prostoj-primer-agi.html|Простой пример AGI на PHP]]
* [[https://habrahabr.ru/post/133869/|Синтез и распознавание речи от Google для Asterisk]]
=== Пример на SHELL ===
# cat /usr/share/asterisk/agi-bin/multi_playback.sh
#!/bin/sh
LOG=/tmp/multi_playback.log
SAMPLE_COUNT=0
:>$LOG
while read ARG && [ "$ARG" ]
do
echo $ARG >> $LOG
if echo $ARG | grep -q 'agi_arg_'
then
SAMPLE_NAME=`echo $ARG | sed -E 's/.*: (.*)$/\1/'`
echo EXEC Playback $SAMPLE_NAME
SAMPLE_COUNT=$(($SAMPLE_COUNT+1))
fi
done
echo SET VARIABLE SAMPLE-COUNT $SAMPLE_COUNT
exit 0
# chmod +x /usr/share/asterisk/agi-bin/multi_playback.sh
# Демонстрировать лучше построчно
# /usr/share/asterisk/agi-bin/multi_playback.sh
agi_request: multi_playback.sh
agi_escho_kucha_parametrov: ...
agi_arg_1: beep
agi_arg_2: hello-world
agi_arg_3: beep
# rm /tmp/multi_playback.log
# cat /etc/asterisk/extensions.conf
...
exten => 313,1,AGI(multi_playback.sh,beep,hello-world,beep)
exten => 313,n,Verbose(1,SAMPLE-COUNT ${SAMPLE-COUNT})
exten => 313,n,Hangup()
...
Решение от Кузьмина Алексея, скрипты взаимоисключающие, один только переводит полное ФИО в фамилию + инициалы, второй еще транслитирует
Место хранения /var/lib/asterisk/agi-bin
Сделать исполняемыми chmod +x
exten => _X.,1,AGI(shortname.sh,${CALLERID(name)},${CALLERID(num)})
exten => _X.,1,AGI(translite.sh,${CALLERID(name)},${CALLERID(num)})
shortname.sh
#!/bin/bash
fio=""
words=($1)
num=$2
m=${#words[@]}
for ((i=0;i<=m-1;i++)); do
word=${words[$i]}
if [ $i -gt 0 ]; then
word=${word:0:1}.
fi
if [ $i -eq 0 ]; then
fio="${word} "
else
fio="${fio}${word}"
fi
done
echo "SET CALLERID \"$fio\"<$num>"
translite.sh
#!/bin/bash
fio=""
words=($1)
num=$2
m=${#words[@]}
for ((i=0;i<=m-1;i++)); do
word=${words[$i]}
if [ $i -gt 0 ]; then
word=${word:0:1}.
fi
str=`echo $word | sed "y/абвгдеёзийклмнопрстуфыэ/abvgdeeziyklmnoprstufye/"`
str=`echo $str | sed "y/АБВГДЕЁЗИЙКЛМНОПРСТУФЫЭ/ABVGDEEZIYKLMNOPRSTUFYE/"`
str=${str//ж/zh} str=${str//Ж/Zh};
str=${str//х/kh} str=${str//Х/Kh};
str=${str//ц/ts} str=${str//Ц/Ts};
str=${str//ч/ch} str=${str//Ч/Ch};
str=${str//ш/sh} str=${str//Ш/Sh};
str=${str//щ/sch} str=${str//Щ/Sch};
str=${str//ъ/} str=${str//Ъ/};
str=${str//ь/} str=${str//Ь/};
str=${str//ю/yu} str=${str//Ю/Yu};
str=${str//я/ya} str=${str//Я/Ya};
if [ $i -eq 0 ]; then
fio="${str} "
else
fio="${fio}${str}"
fi
done
echo "SET CALLERID \"$fio\"<$num>"
=== Пример на PHP ===
* [[http://phpagi.sourceforge.net/]]
# cd /usr/local/
# wget http://val.bmstu.ru/unix/voip/phpagi-2.20.tgz
# tar -xvf phpagi-2.20.tgz
# cat /usr/share/asterisk/agi-bin/example.php
#!/usr/bin/php
answer();
$agi->stream_file("hello-world");
$agi->hangup();
?>
==== Asterisk AMI ====
* [[http://www.pbxware.ru/wiki/asterisk_managment_interface_ami/|Asterisk Managment Interface (AMI)]]
* [[http://www.jcgonzalez.com/test-asterisk-ami-telnet|Log in, Log out from Asterisk AMI with Telnet]]
* [[http://habrahabr.ru/company/centosadmin/blog/161521/|Asterisk: обратный вызов с использованием AMI и PHP]]
* Программирование диалогов expect [[Программирование диалогов expect#Asterisk AMI]]
# less /etc/asterisk/manager.conf
[general]
enabled = yes
port = 5038
bindaddr = 127.0.0.1
;bindaddr = 0.0.0.0
#include "manager.d/*.conf"
# cat /etc/asterisk/manager.d/admin.conf
[admin]
secret = admin
read = all
write = all
# asterisk -rx "module reload manager"
# asterisk -rx "manager show connected"
# asterisk -rx "manager show commands"
# telnet 127.0.0.1 5038
Action: Login
ActionID: 1
Username: admin
Secret: admin
Action: Originate
Channel: SIP/403
Context: default
Exten: 301
Callerid: HelloWorld<301>
Priority: 1
Action: Logoff
==== Asterisk ARI ====
* [[https://wiki.asterisk.org/wiki/display/AST/Getting+Started+with+ARI|Getting Started with ARI]]
* [[https://wiki.asterisk.org/wiki/display/AST/Asterisk+12+ARI|Complete reference of the API]]
* [[http://subnets.ru/blog/?p=5416|В Asterisk появился REST Interface (ARI)]]
=== Настройка доступа к ARI ===
# cat /etc/asterisk/http.conf
[general]
enabled=yes
;bindaddr=127.0.0.1
;bindaddr=0.0.0.0
bindport=8088
# cat /etc/asterisk/ari.conf
[general]
enabled = yes
pretty = yes
allowed_origins = *
[asterisk]
type = user
read_only = no
password = asterisk
=== Управление Asterisk через ARI ===
* [[http://ari.asterisk.org/|Asterisk REST API Browser]]
# curl http://localhost:8088/ari/endpoints?api_key=asterisk:asterisk
=== Мониторинг Asterisk через ARI ===
* [[https://stackoverflow.com/questions/28064526/how-to-get-all-dialer-events-from-asterisk-rest-api-ari|How to get all dialer events from Asterisk REST API (ARI)?]]
debian9# curl -sL https://deb.nodesource.com/setup_9.x | sudo -E bash -
# apt install -y nodejs npm
# npm install -g wscat
# wscat -c "ws://localhost:8088/ari/events?api_key=asterisk:asterisk&app=my-first-app"
*CLI> ari show apps
# curl -v -u asterisk:asterisk -X POST "http://localhost:8088/ari/applications/my-first-app/subscription?eventSource=endpoint%3ASIP"
*CLI> ari show app my-first-app
=== ARI Stasis ===
exten => 314,1,Answer()
exten => 314,n,Stasis(my-first-app)
exten => 314,n,Hangup()
# curl -v -u asterisk:asterisk -X GET "http://localhost:8088/ari/channels"
...
"id": "1513594816.47",
...
# ID=1513594816.47
# curl -v -u asterisk:asterisk -X POST "http://localhost:8088/ari/channels/$ID/play?media=sound:hello-world"
# curl -v -u asterisk:asterisk -X POST "http://localhost:8088/ari/channels/$ID/redirect?endpoint=SIP%2F403"
==== XMPP ====
!!! При использовании GSSAPI надо добавить метод PALIN
* [[http://www.asteriskdocs.org/en/3rd_Edition/asterisk-book-html-chunk/ExternalServices_id286789.html|Using XMPP (Jabber) with Asterisk]]
* Сервис OpenFire [[Сервис OpenFire#Управление контактами]]
# asterisk -x 'module show' | grep xmpp
# cat /etc/asterisk/xmpp.conf
[general]
debug=no
[aster]
type=client
serverhost=server.corpX.un
;username=administrator@corpX.un
;username=admin@corpX.un
secret=Pa$$w0rd
port=5222
;usetls=yes
;usetls=no
*CLI> module reload res_xmpp
*CLI> xmpp show connections
*CLI> xmpp show buddies
# cat /etc/asterisk/extensions.conf
[default]
...
exten => 307,1,Answer()
exten => 307,n,JabberSend(aster,userN@corpX.un,Hello World)
exten => 307,n,Hangup()
...
exten => _4XX,1,Set(MY-CALLED-USER-ID=${SIPPEER(${EXTEN},chanvar[MY-USER-ID])})
;exten => _4XX,1,Set(MY-CALLED-USER-ID=${PJSIP_ENDPOINT(${EXTEN},MY-USER-ID)})
exten => _4XX,n,Set(MY-CALLED-USER-STATUS=${JABBER_STATUS(aster,${MY-CALLED-USER-ID})})
exten => _4XX,n,GotoIf($[${MY-CALLED-USER-STATUS} > 2]?busy)
exten => _4XX,n,JabberSend(aster,${MY-CALLED-USER-ID},Вам звонит ${CALLERID(all)})
exten => _4XX,n,Dial(SIP/${EXTEN})
;exten => _4XX,n,Dial(PJSIP/${EXTEN})
exten => _4XX,n,Hangup()
exten => _4XX,n(busy),JabberSend(aster,${MY-CALLED-USER-ID},Вам звонил ${CALLERID(all)})
exten => _4XX,n,Playback(tt-allbusy)
exten => _4XX,n,Hangup()
...
===== Интеграция с Microsoft AD и LDAP =====
* [[https://habrahabr.ru/post/125359/|Скрипт на perl формирующий users.conf и extensions.conf]]
* [[https://habrahabr.ru/post/137124/|Связываем Active Directory, Asterisk и OpenFire]]
* [[http://free.oxymium.net/Asterisk/|Asterisk LDAP Realtime driver]]
* [[https://wiki.asterisk.org/wiki/display/AST/LDAP+Realtime+Driver|Asterisk Realtime Lightweight Directory Access Protocol (LDAP) Driver]]
* [[http://blog.sepa.spb.ru/2012/04/asterisk-sync-with-active-directory.html|Asterisk sync with Active Directory]]
* Заполняем атрибут Telephone number и переименовываем пользователя указав Full name на русском языке
* Видео урок: [[Открытое решение IM и Presence в инфраструктуре Microsoft AD]]
==== Выгружаем данные из Microsoft AD через LDAP ====
# apt install ldap-utils
# cat /root/create_exten_mail_cidname_table.sh
#!/bin/sh
IFS=' '
ldapsearch -x -D "cn=Administrator,cn=Users,dc=corp,dc=un" -w 'Pa$$w0rd' -H ldap://ad.corp.un -b "dc=corp,dc=un" "(telephoneNumber=4*)" cn telephoneNumber mail \
| perl -p00e 's/\r?\n //g' |
while read s
do
echo $s | grep -vq '^dn:' && continue
read fn cn
echo $fn | grep -q '::' && cn=`echo $cn | base64 -d`
read fn tn
read fn email
echo $tn $email $cn
done
# chmod +x /root/create_exten_mail_cidname_table.sh
# /root/create_exten_mail_cidname_table.sh | tee exten_mail_cidname_table.txt
401 user1@corp.un Иван Иванович Иванов
402 user2@corp.un Петр Петрович Петров
403 user3@corp.un Сидор Сидорович Сидоров
404 user4@corp.un Василий Муркович Кошкин
==== Добавляем исходные данные для Provisioning ====
* [[Сервис Asterisk#Provisioning]]
==== Создаем файл конфигурации CHAN SIP ====
# cat /root/create_ast_users_conf.sh
#!/bin/sh
IFS=' '
cat $1|
while read exten mail name
do
echo "[$exten]"
echo "type=friend"
echo "fullname=$name"
echo "setvar=MY-USER-ID=$mail"
secret=`cat $2 | grep "^$exten" | cut -d' ' -f2`
echo "secret=$secret"
echo "host=dynamic"
echo mailbox=${exten}'@'$(echo $mail | cut -d '@' -f2 | cut -d'.' -f1)
echo
done
# chmod +x /root/create_ast_users_conf.sh
# /root/create_ast_users_conf.sh exten_mail_cidname_table.txt exten_secret_proxy_mac_model_table.txt | tee /etc/asterisk/users.conf
# cat /etc/asterisk/users.conf
[401]
type=friend
fullname=Иван Иванович Иванов
setvar=MY-USER-ID=user1@corpX.un
secret=tpassword401
host=dynamic
mailbox=401@corpX
...
# cat /etc/asterisk/sip.conf
[general]
...
#include "/etc/asterisk/users.conf"
...
==== Создаем файл конфигурации PJSIP ====
# cat create_ast_pjsip_wizard.sh
#!/bin/sh
IFS=' '
cat $1|
while read exten mail name
do
password=`cat $2 | grep "^$exten" | cut -d' ' -f2`
echo "[$exten]"
echo "type=wizard"
echo "accepts_auth=yes"
echo "accepts_registrations=yes"
echo "transport=udp-transport-1"
echo "inbound_auth/username=$exten"
echo "inbound_auth/password=$password"
echo "endpoint/allow=alaw"
echo "endpoint/context=default"
echo "endpoint/set_var=MY-USER-ID=$mail"
echo "endpoint/callerid=${name}<${exten}>"
echo "aor/max_contacts=1"
echo "aor/remove_existing=yes"
echo
done
# /root/create_ast_pjsip_wizard.sh exten_mail_cidname_table.txt exten_secret_proxy_mac_model_table.txt | tee /etc/asterisk/pjsip_wizard.conf
# service asterisk restart
==== Использование sourceforge asterisk AD perl scripts ====
* [[https://sourceforge.net/p/asteriskadperl/code/HEAD/tree/users.pl|asterisk + AD perl scripts]]
* из AD берутся номера телефонов и ФИО
* secret для SIP телефонов задается ст статически в sip.conf
# apt install libnet-ldap-perl
# cat users.pl
...
$ADcontroller="ad.corp.un";
$ADDC="DC=corp,DC=un";
$ADuser="Administrator";
$ADpass='Pa$$w0rd';
$dialplan="default";
...
# /root/users.pl > /etc/asterisk/users.conf
# cat /etc/asterisk/users.conf
[401]
cid_number = 401
fullname = Ivan I. Ivanov
type = peer
[402]
...
# cat /etc/asterisk/sip.conf
[general]
...
#include "/etc/asterisk/users.conf"
[401]
secret=tpassword401
type=user
host=dynamic
[402]
...
===== Provisioning =====
# cat exten_secret_proxy_mac_model_table.txt
401 tpassword401 server.corpX.un 000000000000 Softphone
402 tpassword402 server.corpX.un 000000000000 Softphone
403 tpassword403 server.corpX.un 000E08C190C2 SPA3102
404 tpassword404 server.corpX.un BCC34221709A KX-HDVXXX
405 tpassword405 server.corpX.un 080023F67118 KX-HDVXXX
...
403 tpassword403 server.corp1.un 000E08C190A8 SPA3102
403 tpassword403 server.corp2.un BCC34221709A KX-HDVXXX
403 tpassword403 server.corp3.un 080023F67118 KX-HDVXXX
403 tpassword403 server.corp4.un 000E08C38F1D SPA3102
403 tpassword403 server.corp5.un 000E08C190A2 SPA3102
403 tpassword403 server.corp5.un 000E08C190C2 SPA3102
403 tpassword403 server.corp6.un BCC3422170AA KX-HDVXXX
403 tpassword403 server.corp7.un 080023E421CD KX-HDVXXX
403 tpassword403 server.corp8.un 000E08C190B6 SPA3102
403 tpassword403 server.corp9.un 000E08C190BB SPA3102
403 tpassword403 server.corp10.un 080023BF61CD KX-HDVXXX
403 tpassword403 server.corp11.un 000E08C389BF SPA3102
403 tpassword403 server.corp12.un 080023BF61CC KX-HDVXXX
# cat create_prov_phones_conf.sh
#!/bin/sh
wwwdir=/var/www/html/
while read pn secret sipproxy mac model
do
if [ "$model" = KX-HDVXXX ]
then
# echo $pn $secret $mac $model
cat > ${wwwdir}kx-hdv-$mac.cfg < ${wwwdir}spa-$mac.cfg <
$sipproxy
$pn
$secret
( xxx | 8xxxxxxxxxx | 0xxxxx | *xx )
FIN
fi
done
# /root/create_prov_phones_conf.sh < exten_secret_proxy_mac_model_table.txt
# ls /var/www/html/
===== Интеграция с CRM =====
* [[http://habrahabr.ru/post/174637/|Интеграция Asterisk и SugarCRM]]
* [[Сервис SugarCRM]]
* [[Сервис SalesPlatform Vtiger CRM Russian]]
===== Безопасность Asterisk =====
==== Поддерживаемые версии ====
* [[http://www.asterisk.org/downloads/asterisk/all-asterisk-versions|All Asterisk Versions]]
==== Список проблем безопасности ====
* [[http://www.asterisk.org/downloads/security-advisories|Security Advisories]]
==== Использование TLS ====
* [[http://www.voip-info.org/wiki/view/SIP+TLS]]
* [[http://www.sipring.ru/overview/asterisk-pbx-ready/99-asterisk-sip-tls.html]]
* [[https://wiki.asterisk.org/wiki/display/AST/Secure+Calling+Tutorial]]
* [[https://wiki.asterisk.org/wiki/display/AST/SIP+TLS+Transport]]
* Можно использовать самоподписанные серитфикаты или CA
* Cертификат сервера или СА необходимо импортировать на телефоны/компьютеры с софтфонами
server# cat server.crt server.key > /etc/asterisk/server.crtkey
server# cat /etc/asterisk/sip.conf
[general]
...
tlsenable=yes
;tlsbindaddr=0.0.0.0:5061
tlscertfile=/etc/asterisk/server.crtkey
; tlscafile=/var/www/html/ca.crt ;need if use clietns certs
tlscipher=ALL
tlsclientmethod=tlsv1
tlsdontverifyserver=no
...
[402]
...
transport=tls
encryption=yes
...
# service asterisk restart
==== Сокрытие версии ====
# cat /etc/asterisk/sip.conf
[general]
...
useragent=Microsoft Lync
...
==== Использование хешей паролей для каналов типа user ====
* [[http://www.voip-info.org/wiki/view/Asterisk+sip+md5secret]]
* [[http://asterisk-support.ru/forum/topics/3032/|SIP авторизация и MD5]]
server# echo -n "402:corp:tpassword402" | md5sum
server# cat /etc/asterisk/sip.conf
[general]
...
realm=corp
...
[402]
;secret=tpassword402
md5secret=a77b8ed36b4be2c14c2d7e4dfad34b46
...
==== Зашита от несанкционированного использования ====
* [[http://subnets.ru/blog/?p=1552|Защита Asterisk или несколько способов как защититься от подбора пароля к SIP аккаунту]]
* [[http://tamkovich.com/2009/04/asterisk-sip-security/|Asterisk: SIP и безопасность]]
* [[http://voipapplication.blogspot.com/2009/01/120000-phone-bill-voip-hacked-small.html|"Voip hackers runs up a phone bill worth $120,000".]]
===== WebRTC =====
* [[http://vinogradov.iptel.od.ua/ustanovka-webrtc-klienta-na-asterisk-na-primere-sipml5/|Установка WebRTC клиента на Asterisk на примере SipML5]]
* [[https://github.com/paneru-rajan/asterisk-sipml5|Sipml5 with Asterisk]]
* [[https://habr.com/post/144293/|SIPML5 — SIP клиент для браузера на базе WebRTC]]
* [[https://habr.com/post/236291/|Установка и настройка Asterisk для работы с WebRTC]]
* [[https://wiki.asterisk.org/wiki/display/AST/WebRTC+tutorial+using+SIPML5]]
* [[https://voxlink.ru/kb/asterisk-configuration/nastrojka-webrtc-v-asterisk-13/|Настройка WebRTC в Asterisk 13]]
* !!! Заработало в Firefox
==== Настройка сервера ====
* [[Пакет OpenSSL#Создание само подписанного сертификата]] для системы server.corpX.un
# cat server.crt server.key > /etc/asterisk/server.crtkey
# cat /etc/asterisk/http.conf
[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088
tlsenable=yes
tlsbindaddr=0.0.0.0:8089
tlscertfile=/etc/asterisk/server.crtkey
# cat /etc/asterisk/sip.conf
[general]
transport=udp,wss
...
[webrtc](!)
avpf = yes
force_avp = yes
icesupport = yes
encryption = yes
dtlsenable = yes
dtlsverify = no
dtlssetup = actpass
dtlscertfile = /etc/asterisk/server.crtkey
[401](webrtc)
...
!!! Проверить и принять сертификат
https://server.corpX.un:8089/ws
==== Настройка клиента sipml5 ====
* [[https://github.com/DoubangoTelecom/sipml5|DoubangoTelecom/sipml5]]
Display Name: 401
Private Identity*: 401
Public Identity*: sip:401@server.corpX.un
Password: tpassword401
Realm*: server.corpX.un
WebSocket Server URL: wss://server.corpX.un:8089/ws
ICE Servers: []
==== Установка клиента sipml5 ====
* [[Пакет OpenSSL#Создание самоподписанного сертификата]] для системы server.corpX.un
* [[Сервис HTTP#Поддержка протокола HTTPS]]
# cd /var/www/html/
# wget http://val.bmstu.ru/unix/voip/sipml5-master.zip
# unzip sipml5-master.zip
https://server.corpX.un/sipml5-master/call.htm
===== Дополнительные материалы =====
==== Распознавание речи в Asterisk с использованием Yandex SpeechKit HTTP API ====
* [[https://habr.com/post/225179/|Распознавание речи в Asterisk с использованием Yandex SpeechKit HTTP API]]
* [[Голосовые сервисы помогут голосовой почте]]
==== Сотрудник звонит на внешний номер, внешний номер перезванивает ====
Сотрудник звонит на внешний номер, номер не отвечает или занят.
Внешний номер перезванивает на внешний номер организации (с которого у него пропущенный), где по умолчанию его должен встретить IVR.
Если в течении последних Х минут в cdr есть запись звонка на этот внешний номер с состоянием номер не отвечает или занят, то соединить с внутренним номер с которого ему звонили.
ДОП.: Если при этом в cdr есть запись что с этим внешним номером звонок состоялся(по времени после не отвеченного, направление не важно, внешний номер сам перезвонил и дозвонился или до него дозвонились со второго раза), то переключить на IVR.
Решение собственное, если есть что улучшить буду рад.
Адаптировано под вашу методичку, но лучше проверить.
/etc/asterisk/func_odbc.conf
[NOTANSWERED_BY_CALLERID]
dsn=asterisk
readsql=SELECT cnum FROM cdr WHERE dst='${ARG1}' AND disposition<>'ANSWERED' AND (calldate >= (SELECT COALESCE(MAX(calldate), now() - interval ${ARG2} minute) AS calldate FROM cdr WHERE (dst='${ARG1}' OR src='${ARG1}') AND disposition='ANSWERED' AND (calldate >= now() - interval ${ARG2} minute) ORDER BY calldate DESC LIMIT 1)) ORDER BY calldate DESC LIMIT 1;
/etc/asterisk/extensions.conf
exten => voip1_00000X,1,Set(NOTANSWERED=${ODBC_NOTANSWERED_BY_CALLERID(${CALLERID(num)},5)}) ; External number, # minutes to search not answered call
same => n,GotoIf($[${LEN(${NOTANSWERED})} != 0]?recall)
same => n,Goto(ivr,s,1)
same => n(recall),Set(CALLERID(name)=RECALL ${CALLERID(name)})
same => n,Dial(PJSIP/${NOTANSWERED},60)
Вызывается функция ODBC с передачей ей номера звонящего и количества минут за которые искать записи.
В SQL запросе вначале выполняется поиск за указанный интервал в минутах отвеченных звонков с участием внешнего номера и возвращается дата самого последнего звонка, если он есть, либо дата начала указанного интервала поиска (now() – 5 минут, например) и после этого выполняется поиск не отвеченных звонков на указанный внешний номер за указанный интервал.
После этого к CALLERID(name) звонящего добавляется RECALL, чтобы уведомить сотрудника, что ему перезванивают, и осуществляется соединение с номером сотрудника от которого был последний не отвеченный звонок, или переключение на IVR, если не отвеченных звонков не было.
Алексей Михайлович Кузьмин
==== Принудительный провижининг ====
#add to sip_notify.conf
[spa-resync]
Event=>resync
Content-Length=>0
[spa-report]
Event=>report
Content-Length=>0
[spa-reboot]
Event=>reboot
Content-Length=>0
[spa-restart]
Event=>restart
Content-Length=>0
restart asterisk
# service asterisk restart
run sip notify against the extension and see the result
# asterisk -r
asterisk1*CLI> sip debug peer 401
asterisk1*CLI> sip notify spa-resync 401
==== HUDlite ====
http://yum.trixbox.org/centos/5/RPMS/repodata/repoview/__nogroup__.group.html
Убедитесь что trixbox repository выбран.
yum search hud
yum install hudlite-server.i386
yum install tbm-hudadmin
Создайте директорию /etc/asterisk/hud
Создайте пустой файл user.xml в этой директории: cat > user.xml
Выйдите из директории hud и модифицируйте права chmod –R 766 hud
HUDlite Admin программа будет исследовать ваши настройки и автоматически создавать учетные записи и пароли для ваших пользователей. Вы можете по желанию сменить пароли созданные автоматически и добавить мобильные номера телефонов и адрес электронной почты ваших пользователей.
Конфигурация HUDLite клиента.
[Download HUDlite client here]
Приинсталляции выберите автозапуск при HUDlite клиента. Примите пользовательскую лицензию. Далее Вам нужно ввести HUDимя пользователя и пароль. Вы можете получить имя пользователя в HUDlite административной панели. Если ваше имя пользователя 200 ваше имя пользователя будет sip200. Ваш пароль будет восемь случайных символов. Вы можете изменить пароли по желанию в HUDliteadmin.
Далее введите имя сервера, пароль для обращения к серверу password (общий для всех), и серверный порт.
Имя сервера IPaddressвашего trixbox.
Сервер пароль 'password'
Сервер порт 6600
Если вы пользуетесь MicrosoftOutlookвыберите инсталяцию с разрешением HUDliteиспользовать Ваш список контактов для callerIDи для установки функции ClicktoDialв Outlook. После этого выберите инсталяцию TAPIдрайвера. Это позволит вам выполнять функцию clicktodialиспользуя любую TAPIиспользуемую приложениями.
HUDliteтеперь инсталирован. Вы должны видеть все доступные номера в HUDокне.
==== Чистка регистрации в AstDB ====
asterisk*CLI> sip show peers
Name/username Host Dyn Nat ACL Port Status
...
00000X/voip1 172.16.1.X D N 1024 Unmonitored
asterisk*CLI> database show
asterisk*CLI> database showkey SIP/Registry/00000X
asterisk*CLI> database deltree SIP/Registry/00000X
server# /etc/init.d/asterisk restart
==== Сборка asterisk из исходных текстов ====
* [[https://www.tecmint.com/install-asterisk-on-centos-7/|How to Install Asterisk on CentOS 7]]
* [[Управление ПО в Linux#Работа с исходными текстами]]
=== Версия 16 ===
* [[https://wiki.asterisk.org/wiki/display/AST/Installing+Asterisk+From+Source|Installing Asterisk From Source]]
# apt install libedit-dev uuid-dev libxml2-dev libsqlite3-dev
# wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-16-current.tar.gz
# cd /usr/local/src
# tar -xvzf /root/asterisk-16-current.tar.gz
# cd asterisk-16.3.0/
# ./configure --with-jansson-bundled
# cd contrib/scripts
# ./install_prereq install
# ./install_prereq install-unpackaged
# cd -
# make menuselect
# make
# make install
# make samples
# asterisk
# asterisk -rvvv
=== Версия 1.8 ===
**Задача: Добавление поддержки imap хранилища голосовой почты**
* [[http://blogs.reucon.com/srt/2007/02/20/1171932900000.html]]
* [[http://www.asteriskdocs.org/html/ch14s05.html]]
* [[http://etel.wiki.oreilly.com/wiki/index.php/Storing_Voicemail_on_an_IMAP_server]]
**Ubuntu**
root@server:~# apt-get install libncurses5-dev libssl-dev libxml2-dev
root@server:~# cd /usr/src
root@server:/usr/src# wget ftp://ftp.cac.washington.edu/mail/imap.tar.Z
root@server:/usr/src# wget http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-1.6.2.19.tar.gz
**FreeBSD**
[server:~] # pkg install perl5 bison m4 gmake gcc libtool libltdl libxml2 speex unixODBC gsm
[server:~] # cd /usr/src/
[server:/usr/src] # fetch ftp://ftp.cac.washington.edu/mail/imap.tar.Z
[server:/usr/src] # fetch http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-1.6.2.19.tar.gz
**Ubuntu/FreeBSD**
server:/usr/src# gunzip imap.tar.Z
server:/usr/src# tar -xvf imap.tar
server:/usr/src# tar -xvf asterisk-1.6.2.19.tar.gz
server:/usr/src# cd imap-2007f/
root@server:/usr/src/imap-2007f# make slx EXTRACFLAGS="-I/usr/include/openssl"
или
[server:/usr/src/imap-2007f] # make bsf EXTRACFLAGS="-I/usr/include/openssl"
server:/usr/src/imap-2007f# cd ../asterisk-1.6.2.19
server:/usr/src/asterisk-1.6.2.19# ./configure --with-imap=/usr/src/imap-2007f/ --prefix=/usr/local/asterisk/ --disable-xmldoc
server:/usr/src/asterisk-1.6.2.19# make menuconfig
server:/usr/src/asterisk-1.6.2.19# make
server:/usr/src/asterisk-1.6.2.19# make install clean
server:/usr/src/asterisk-1.6.2.19# make samples
server:~# mkdir -p /usr/local/asterisk/var/db/asterisk/
server:~# /usr/local/asterisk/sbin/asterisk
server:~# /usr/local/asterisk/sbin/asterisk -rvvvvvv