Asterisk - SIP АТС для офиса, пошаговая инструкция по настройке с нуля

Одним из рабочих инструментов офиса, несмотря на стремительные изменения последних десятилетий, по-прежнему является телефон. Мы займемся пошаговой настройкой с нуля АТС asterisk - современного инструмента для организации телефонии в офисе на основе протокола SIP. Я подробно с примерами и описанием проведу вас по основным параметрам, необходимым для базового функционала.

Онлайн-курс по устройству компьютерных сетей

На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Данная статья является частью единого цикла статьей про сервер Centos.

Введение

Не буду останавливаться на описании сервера asterisk, в интернете много информации на эту тему. Да и сам я кратко рассказывал в своих предыдущих статьях про установку. Материал будет объемный, поэтому сразу перейдем к сути.

Статья планируется учебная, поэтому использовать будем голый asterisk без каких-либо web панелей для управления. Выполнять настройку asterisk будем с нуля, то есть с самой начальной установки самого сервера телефонии и всех зависимостей. Если вы разберетесь и освоите этот материал, то потом без проблем сможете настроить и поддерживать любую конфигурацию на основе астериска.

Я хочу подробно рассказать о настройке asterisk на конкретном примере, где будет собран в одном месте расширенный функционал, отвечающий практически на все запросы среднестатистического офиса.

Сразу хочу обратить внимание на очень важный момент. Я не являюсь профессионалом в настройке asterisk. Данный материал является калькуляцией всех моих знаний на текущий момент, которые я методично шаг за шагом собирал из доступных в интернете источников. По этой статье вы получите рабочий, многофункциональный сервер телефонии, работу которого я проверял на практике. Но это не означает, что все, что здесь настроено, сделано наилучшим образом. Я постоянно учусь и совершенствую свои знания. Если вы увидите ошибки, недочеты, варианты более правильной и удобной настройки, прошу об этом сообщить в комментариях, я проверю и обновлю статью.

Для примера опишем наш воображаемый офис:

  • Работает 30 сотрудников. Номера будут трехзначные, от 100 до 130.
  • У нас будут 3 отдела - менеджеры, техподдержка, руководство и все остальные.
  • Номер секретаря 100, менеджеры 101-110, техподдержка 111-120, руководство 121-130.
  • Мы будем использовать одного SIP провайдера для звонков.

Кратко получается такая картина. Я не пишу в самом начале о техническом задании, которое буду реализовывать. Каждый момент буду описывать и раскрывать в соответствующем разделе.

Для настройки я буду использовать учетную запись сервиса zadarma.com (отделились в РФ и работают под брендом Новофон). Неплохой оператор voip связи. Беру его для примера, потому что удобно использовать для тестирования конфигурации. Сразу после регистрации вам дают аккаунт, пример настроек для asterisk. Вы можете позвонить на прямой городской номер, ввести добавочный и совершить звонок на свой аккаунт. Это полностью эмулируер работу sip подключения от какого-нибудь провайдера.

В качестве операционной системы у меня выступает CentOS 8. Но для данной статьи это не имеет принципиального значения. Конфигурация астериск кроссплатформенная, без проблем переносится между системами.

Приступаем к нашей работе по настройке сервера телефонии.

Быстрая установка из репозитория

Centos 7

У asterisk не существует официального репозитория пакетов, поэтому предпочтительным способом установки свежей версии является сборка из исходников. Но если вы хотите быстро установить и потестить систему, то можно использовать один из сторонних репозиториев asterisk. К примеру - Tuncy. Я не знаю, кто ведет этот репозиторий, как часто он обновляется и насколько там актуальные версии. На момент актуализации этой статьи (март 2020 года) в репозитории не было свежих пакетов для Centos 8, только для 7-й.

Добавляем репозиторий астериск в систему. Для этого создаем файл /etc/yum.repos.d/tuncy-asterisk-16.repo следующего содержания.

[asterisk-common]
name=Asterisk Common Requirement Packages @ tucny.com
baseurl=https://ast.tucny.com/repo/asterisk-common/el\$releasever/\$basearch/
enabled=1
gpgcheck=1
gpgkey=https://ast.tucny.com/repo/RPM-GPG-KEY-dtucny

[asterisk-16]
name=Asterisk 16 Packages @ tucny.com 
baseurl=https://ast.tucny.com/repo/asterisk-16/el\$releasever/\$basearch/
enabled=1
gpgcheck=1
gpgkey=https://ast.tucny.com/repo/RPM-GPG-KEY-dtucny

Обновляем информацию о репозиториях и устанавливаем астериск.

# yum install asterisk

Установка asterisk из репозитория

Установка из исходников

Centos 8

Вопроса установки asterisk я уже касался ранее в одной из прошлых статей. Но там я использовал связку с панелью управления freepbx. Здесь же мы будем использовать голый астериск, без обвязок. Более того, я не буду использовать никаких дополнительных плат расширения и модемов. Будет только софтовая АТС, которая легко переносится с одного сервера на другой при желании. Считаю, что такой подход наиболее эффективен и к нему стоит стремиться. Настроив виртуальную машину, вы навсегда будете отвязаны от конкретного железа и спокойно можете переносить свой сервер куда угодно, заменив только сетевые настройки.

Таким образом, нам нужно установить непосредственно asterisk и pjproject с jansson. На первоначальном этапе этого достаточно. Если вы предпочитаете сервер debian, то воспользуйтесь отдельной инструкцией по установке asterisk 16 на debian 10. После этого можете сразу же переходить на следующий этап настройки. Приступим.

Первым делом обновляем систему и отключаем SELinux, как рассказано в статье про настройку centos. Установим теперь пакеты, которые нам понадобятся для сборки. В первую очередь подключим репозиторий epel.

# dnf install epel-release

Дальше идет мета пакет Development Tools со всем необходимым для сборки из исходников.

# dnf groupinstall "Development Tools"

Установка Development tools И еще некоторые зависимости, которые будут нужны.

# dnf install git wget net-tools sqlite-devel psmisc ncurses-devel libtermcap-devel newt-devel libxml2-devel libtiff-devel gtk2-devel libtool libuuid-devel subversion kernel-devel kernel-devel-$(uname -r) crontabs cronie-anacron mariadb mariadb-server

Установка зависимостей asterisk 16 Настройте mysql сервер, задав пароль для root.

# systemctl start mariadb
# systemctl enable mariadb
# /usr/bin/mysql_secure_installation

На этом подготовка закончена. Устанавливаем Jansson и pjsip.

# cd ~
# git clone https://github.com/akheron/jansson.git
# cd jansson
# autoreconf -i
# ./configure --prefix=/usr/
# make && make install

Установка Jansson

# cd ~
# git clone https://github.com/pjsip/pjproject.git
# cd pjproject
# ./configure CFLAGS="-DNDEBUG -DPJ_HAS_IPV6=1" --prefix=/usr --libdir=/usr/lib64 --enable-shared --disable-video --disable-sound --disable-opencore-amr
# make dep && make && make install
# ldconfig

Установка pjsip Все готово к установке непосредственно Astersik

Я буду устанавливать LTS версию Asterisk 16. Советую для долгосрочного использования всегда использовать LTS версии. Они в целом стабильнее и дольше срок поддержки. Идем на страницу https://www.asterisk.org/downloads/asterisk/all-asterisk-versions и копируем ссылку на нужную версию. Загружаем ее на сервер.

# cd ~
# wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-16-current.tar.gz
# tar xfz asterisk-16-current.tar.gz
# cd asterisk-16*/
# contrib/scripts/install_prereq install
# contrib/scripts/get_mp3_source.sh

Устанавливаем на centos 8 пакет libedit-devel.

# dnf config-manager --set-enabled powertools
# dnf install libedit-devel

Собираем asterisk.

# ./configure --libdir=/usr/lib64
# make menuselect

Установка Asterisk 16 на Centos 8 Выбирайте необходимые модули и звуки, в зависимости от того, что вам нужно. Я в общем случае указываю:

  • Add-ons: format_mp3, res_config_mysql.
  • Core Sound Packages: русские звуки RU-WAV.
  • Music On Hold File Packages: звук WAV.
  • Extras Sound Packages: английский EN-WAV, русского к сожалению нет.

Все остальные настройки оставляем по-умолчанию. Ставится много модулей. Все они не нужны, но мало ли, пригодится что-то в будущем. Неиспользуемые модули можно будет потом отключить в конфигурации.

Продолжаем установку:

# make && make install && make samples && make config
# ldconfig

По-умолчанию, asterisk установлен от root и будет запускаться от него же. Я предлагаю для этого создать отдельного пользователя и запускать астериск от него. Для этого создаем пользователя и добавляем его в некоторые группы.

# groupadd asterisk
# useradd -r -d /var/lib/asterisk -g asterisk asterisk
# usermod -aG audio,dialout asterisk
# chown -R asterisk.asterisk /etc/asterisk /var/{lib,log,spool}/asterisk /usr/lib64/asterisk

Настраиваем Asterisk на запуск под этим пользователем. Для этого добавляем в конфиг /etc/sysconfig/asterisk параметры:

AST_USER="asterisk"
AST_GROUP="asterisk"

Теперь добавим примерно то же самое в сам конфиг астера /etc/asterisk/asterisk.conf.

runuser = asterisk
rungroup = asterisk

Пробуем запустить asterisk:

# systemctl start asterisk

Если нет сообщений об ошибке, скорее всего все в порядке. Проверяем статус службы.

# systemctl status asterisk

Запуск asterisk Asterisk запустился, но есть небольшие ошибки.

radcli: rc_read_config: rc_read_config: can't open /etc/radiusclient-ng/radiusclient.conf: No such file or directory

Связаны с тем, что в конфигах неверно указан путь к radiusclient. Сейчас исправим это.

# sed -i 's";\[radius\]"\[radius\]"g' /etc/asterisk/cdr.conf
# sed -i 's";radiuscfg => /usr/local/etc/radiusclient-ng/radiusclient.conf"radiuscfg => /etc/radcli/radiusclient.conf"g' /etc/asterisk/cdr.conf
# sed -i 's";radiuscfg => /usr/local/etc/radiusclient-ng/radiusclient.conf"radiuscfg => /etc/radcli/radiusclient.conf"g' /etc/asterisk/cel.conf

Перезапускаем asterisk и убеждаемся, что ошибок нет. Проверим, все ли в порядке, зайдя в консоль:

# asterisk -r

Проверка работы Если получили такой же вывод команды, значит все в порядке, астериск 16 установлен. Добавим его теперь в автозагрузку.

# systemctl enable asterisk

Для тех, у кого что-то не получается или не понятно, как сделать, записал видео по приведенной инструкции. Видео подтверждает, что материал актуален и если делать по нему, то все получится. https://youtu.be/9q9RGqBVQbA

Centos 7

Если вы хотите использовать для настройки Asterisk предыдущую версию системы, то смотрите мою статью по установке Asterisk 16 на Centos 7. Там нет принципиальных отличий, но имейте ввиду, что все дальнейшие действия были проделаны и проверены на 8-й вверсии Центос, так что я не ручаюсь, что это так же заработает и на 7-й. Полную проверку и адаптацию материала я сделал для CentOS 8.

Настройка iptables, asterisk за NAT, проброс портов

Сразу же уделим внимание настройке iptables для работы астериск. У нас может быть 2 ситуации, которые требуют двух принципиально различных настроек:

  1. Сервер телефонии имеет свой внешний ip адрес и напрямую смотрит через него в интернет.
  2. Сервер стоит за шлюзом, не имеет своего внешнего адреса, доступ в интернет с помощью NAT.

В первом случае нам нужно открыть на iptables необходимые порты для работы, все остальное закрыть. Подробно вопрос настройки iptables я рассматривал в отдельной статье. Там есть примеры и пояснения, рассказан мой подход к настройке.

Я не могу привести универсальные настройки для всех случаев. У каждого будут свои нюансы. Кто-то, к примеру, будет пользоваться phpmyadmin для настройки базы mysql для хранения статистики звонков. Потом эту же статистику будет просматривать через cdr viewer, установленный на веб сервере. Доступ к этому веб серверу можно открыть через внешний IP адрес, а можно только через локальную сеть. Настройки iptables в данном случае будут разные.

В моем примере сервер будет находиться в локальной сети офиса за nat. Доступ в интернет осуществляется через офисный шлюз, на котором установлены iptables. На нем будет сделан проброс необходимых портов для работы внешних телефонных аппаратов. В случае, если у вас все телефоны будут находиться в локальной сети офиса вместе с сервером телефонии, пробрасывать ничего не нужно. С сервисом zadarma все будет работать без проброса портов. Пиры зарегистрируются на внешнем сервере провайдера и этого будет достаточно для приема и совершения звонков.

С другими провайдерами этого может быть не достаточно. В общем случае для настройки asterisk за nat нужно будет на шлюзе пробросить порт 5060 и диапазон 10000:20000. По-умолчанию астериск использует UDP порты. Если вы не будете менять эти настройки, то пробрасывать нужно именно UDP.

В моем случае получается следующая картина. На шлюзе сделан проброс необходимых портов:

iptables -t nat -A PREROUTING -p udp --dst $WAN_IP --dport 5060 -j DNAT --to 192.168.1.25:5060
iptables -t nat -A PREROUTING -p udp --dst $WAN_IP --dport 10000:20000 -j DNAT --to 192.168.1.25
$WAN_IP Внешний IP адрес на шлюзе
192.168.1.25 Локальный адрес сервера астериск

Настройкой фаервола на самом астериске я не хочу сейчас заниматься, статья и так масштабная получается. С этим без проблем можно разобраться с помощью моей статьи по iptables, ссылку на которую я привел в начале раздела. Нужно просто открыть указанные выше порты, и любые другие, которые будут использоваться на сервере.

Если вы делаете тестовую установку и настройку asterisk, можете совсем отключить firewalld:

# systemctl stop firewalld
# systemctl disable firewalld
# dnf remove firewalld

Подключение абонентов и проверка внутренних звонков

Астериск у нас установлен, firewall настроен. Можно попробовать подключиться и протестировать работу АТС. Я для отладки использую бесплатную софтовую звонилку 3CXPhone 6-й версии. Не знаю, где ее сейчас найти в интернете. У самого производителя давно уже вышли более новые и платные версии, которые работают только с его АТС. А эта версия универсальная. В ней отличный функционал, удобные настройки, есть дебаг режим с подробным логированием. Пользоваться программой удобно и приятно. Скачиваем ее у меня и устанавливаем.

Теперь нам нужно сделать некоторые общие настройки и добавить пользователей. Работать будем с файлом конфигурации /etc/asterisk/sip.conf. Файлы настроек астера хорошо закомментированы, но мне это мешает с ними работать. Они слишком большие и громоздкие, неудобно прокручивать вверх и вниз, поэтому я их полностью чищу и вношу только те настройки, которые мне нужны. Так удобнее и нагляднее получается. Сохраните на всякий случай куда-нибудь оригинальный файл sip.conf и начинайте новую настройку. Вот мой пример конфига для нашего случая:

[general]
;Внешний ip адрес
externaddr=212.78.136.18:5060
;Указываем использовать русскую озвучку
language=ru
context=default
allowoverlap=no
udpbindaddr=0.0.0.0
tcpenable=no
tcpbindaddr=0.0.0.0
transport=udp
srvlookup=yes
allowguest=no
limitonpeers=yes

[authentication]

;Создаем шаблон для телефонов менеджеров
[managers-phones](!)
type=friend
context=call-out
secret=123
host=dynamic
nat=no
qualify=yes
canreinvite=no
callgroup=1
pickupgroup=1
call-limit=1
dtmfmode=auto
disallow=all
allow=alaw
allow=ulaw
allow=g729
allow=g723
allow=g722

;Создаем пользователей менеджеров
[100](managers-phones)
callerid="Number 100" <100>
[101](managers-phones)
callerid="Number 101" <101>
[102](managers-phones)
callerid="Number 102" <102>
[103](managers-phones)
callerid="Number 103" <103>
[104](managers-phones)
callerid="Number 104" <104>
[105](managers-phones)
callerid="Number 105" <105>
[106](managers-phones)
callerid="Number 106" <106>
[107](managers-phones)
callerid="Number 107" <107>
[108](managers-phones)
callerid="Number 108" <108>
[109](managers-phones)
callerid="Number 109" <109>
[110](managers-phones)
callerid="Number 110" <110>

;Создаем шаблон для телефонов поддержки
[support-phones](!)
type=friend
context=call-out
secret=456
host=dynamic
nat=no
qualify=yes
canreinvite=no
callgroup=2
pickupgroup=2
call-limit=1
dtmfmode=auto
disallow=all
allow=alaw
allow=ulaw
allow=g729
allow=g723
allow=g722

;Создаем пользователей техподдержки
[111](support-phones)
callerid="Number 111" <111>
[112](support-phones)
callerid="Number 112" <112>
[113](support-phones)
callerid="Number 113" <113>
[114](support-phones)
callerid="Number 114" <114>
[115](support-phones)
callerid="Number 115" <115>
[116](support-phones)
callerid="Number 116" <116>
[117](support-phones)
callerid="Number 117" <117>
[118](support-phones)
callerid="Number 118" <118>
[119](support-phones)
callerid="Number 119" <119>
[120](support-phones)
callerid="Number 120" <120>

;Создаем шаблон для телефонов топов
[top-phones](!)
type=friend
context=call-out
secret=789
host=dynamic
nat=no
qualify=yes
canreinvite=no
callgroup=3
pickupgroup=3
call-limit=1
dtmfmode=auto
disallow=all
allow=alaw
allow=ulaw
allow=g729
allow=g723
allow=g722

;Создаем пользователей топов
[121](top-phones)
callerid="Number 111" <121>
[122](top-phones)
callerid="Number 122" <122>
[123](top-phones)
callerid="Number 123" <123>
[124](top-phones)
callerid="Number 124" <124>
[125](top-phones)
callerid="Number 125" <125>
[126](top-phones)
callerid="Number 126" <126>
[127](top-phones)
callerid="Number 127" <127>
[128](top-phones)
callerid="Number 128" <128>
[129](top-phones)
callerid="Number 129" <129>
[130](top-phones)
callerid="Number 130" <130>

Я немного пояснил комментариями отдельные моменты. Чтобы сократить размер sip.conf, я использую шаблоны групп номеров, где задаю общие настройки для группы. Затем просто создаю пользователей и указываю их принадлежность к группе. Они берут все настройки этой группы. Если вам необходимо будет задать отдельные настройки для какого-то пользователя, как у меня, к примеру, callerid, то вы просто в его разделе указываете эти настройки.

У меня стоит один и тот же пароль для всей группы. Это удобно, если все телефоны стационарные и стоят в офисе, настраивают их только сисадмины. Делать каждому персональный пароль особого смысла нет. Если вам это не нужно, то указывайте персональный пароль для каждого пользователя. Я просто привожу примеры использования тех или иных настроек, но не призываю делать так же, как я. Во многих случаях так делать нельзя. Уточню еще некоторые нюансы.

  • Параметры callgroup и pickupgroup задают группы перехвата звонков. Люди из одной группы могут перехватывать звонки друг друга. Удобно заводить в одну группу людей, сидящих в одной комнате. Так они видят, что человека нет на месте и перехватывают его звонок. Эти параметры можно индивидуально задать для каждого пользователя в отдельности, если разбивка по шаблонам настроек не соответствует реальной рассадке людей в офисе.
  • Параметр callerid можно задать кириллицей, но могут возникнуть проблемы с некоторыми телефонами и точно возникнут проблемы, когда вы будете вести статистику звонков в mysql. Я не смог победить эту проблему с кодировками, поэтому использую только латиницу в этом параметре. Туда можно писать либо должность, либо ФИО человека.
  • call-limit=1 задает количество одновременных соединений на линию. Если у вас один человек = один телефонный аппарат, то разрешать больше одной линии на пользователя нет смысла. Ему будет идти новый звонок в тот момент, как он разговаривает. Конечно, если есть необходимость переключаться между разговорами и ставить кого-то на удержание, то можно делать и больше линий. Но мне кажется, это неудобно. Если ты разговариваешь, пусть звонящий лучше услышит занято и перезвонит.
  • Я всех добавляю в один context. В данном примере у нас будет только один номер телефона на всех. Если у вас их будет несколько, то контекстами можно будет разводить звонки на разные номера. Эту ситуацию я рассмотрю в отдельной статье.

Сохраняем sip.conf. Теперь нам нужно добавить план звонков, для того, чтобы можно было совершать вызовы. Для этого как и с предыдущим конфигурационным файлом, очищаем файл extensions.conf и записываем туда следующую информацию:

[general]
static=yes
writeprotect=no
[globals]
[default]

;Вешаем трубку
[handup-sip]
exten => _X!,1,HangUp()

;Исходящие звонки
[call-out]
;Звонок на внутренний номер
exten => _XXX,1,Dial(SIP/${EXTEN})
include => handup-sip

Мы просто добавили один план звонков на трехзначные номера. Я сразу добавляю комментарии с заделом на дальнейшее расширение этого файла, чтобы потом было проще разбираться. Сохраняем файл.

У нас все готово для внутренних звонков через asterisk. Заходим в консоль и перезагружаем его:

# asterisk -r
CLI> reload

Вы увидите некоторые предупреждения и ошибки. Это не страшно, так и должно быть, так как мы многое еще не настроили. Загружаются модули, которым не хватает настроек. Проверим список созданных пользователей с помощью команды в консоли:

CLI> sip show users

sip show users

Видим всех наших пользователей, их пароли и контекст. Список отсортирован не по порядку, не пугайтесь, если не заметите какой-то номер.

Дальше устанавливайте любую софтовую звонилку на компьютер или можете сразу использовать телефон, если он у вас под рукой. С телефонами удобнее, но не всегда они есть. В 3CXPhone задаем следующие настройки подключения к нашей ip атс:

Пример подключения телефона к asterisk Я сразу открываю дебаг окно для отладки. Корректное подключение к серверу будет выглядеть вот так: Подключение 3CXPhone к астериск Проверим на сервере список подключенных пиров с помощью команды:

CLI> sip show peers

Должна быть строка с подключенным пиром:

100/100                   192.168.1.100                            D  No         No             59891    OK (104 ms)

Если у вас так же, то все в порядке. Чтобы протестировать звонки, нам нужно подключить двух абонентов. Настраивайте еще один телефон или софтофон. Проверяйте в списке подключенных пиров чтобы было 2 подключения и попробуйте позвонить друг другу. Если вы все сделали правильно, то локальные звонки должны работать. Я обычно для тестирования второго клиента настраиваю на мобильном телефоне. Так можно проверить работу звонков через смартфоны.

После звонка в файле /var/log/asterisk/cdr-csv/Master.csv появится запись о совершенном звонке:

"","101","100","call-out","""Number 101"" <101>","SIP/101-00000000","SIP/100-00000001","Dial","SIP/100","2020-02-27 12:38:35","2020-02-27 12:38:45","2020-02-27 12:38:47",12,2,"ANSWERED","DOCUMENTATION","1582807115.0",""

В этом файле будет накапливаться статистика звонков. Позже мы перенесем ее в mysql. Я позвонил с номера 101 на номер 100, там мне ответили. В файле отражены все основные данные этого звонка.

Один небольшой шажок по настройке voip атс asterisk мы сделали. Будем двигаться дальше.

Настройка sip trunk (транка) и добавление номера

Регистрируемся у какого-нибудь sip провайдера и получаем настройки транков для подключения. Как я говорил выше, я буду использовать провайдера zadarma. После регистрации в личном кабинете в разделе Настройки -> Подключение по SIP я вижу свой логин, пароль для подключения и адрес сервера. Там же можно узнать пример настройки подключения для астериска и номера для тестовых звонков:

  • Номер для эхо-теста: 4444.
  • Информация про остаток на счету: 1111
  • Прямой звонок: Москва +7 (495) 777-66-75 и внутренний номер клиента (логин)

Нам этого будет достаточно для полноценного тестирования конфигурации астериска. Добавляем необходимые настройки sip транка, чтобы выполнить его регистрацию. Редактируем sip.conf, добавляем в самый конец нового пира в соответствии с инструкцией провайдера:

[397945]
host=sip.zadarma.com
insecure=invite,port
type=friend
fromdomain=sip.zadarma.com
disallow=all
allow=alaw
dtmfmode=auto
secret=password
defaultuser=397945
trunkname=397945
fromuser=397945
callbackextension=397945
context=call-in
qualify=400
directmedia=no
nat=force_rport,comedia

В данном случае 397945 мой внутренний номер в сервисе, password - пароль. Сохраняем файл и даем команду астеру перечиать его:

CLI> sip reload

Тут же в консоли, если все в порядке, вы получите сообщение:

chan_sip.c:24403 handle_response_peerpoke: Peer '397945' is now Reachable. (55ms / 400ms)

Это означает, что наш пир успешно зарегистрировался у провайдера. Проверить это можно с помощью уже известной команды:

CLI> sip show peers
397945/397945             185.45.152.161                              Auto (No)  No             5060     OK (54 ms)

Все, транк настроили, по сути подключили номер. Но этого не достаточно, чтобы совершать и принимать звонки. Надо отредактировать dialplan.

Dial-plan - пример маршрутизации звонков

Начало построения диалплана для маршрутизации звонков мы уже положили, когда настраивали внутренние звонки. Теперь нужно дополнить dial-plan для совершения исходящих и приема входящих звонков. Редактируем extensions.conf и приводим его к следующему виду:

[general]
static=yes
writeprotect=no
[globals]
[default]

;Вешаем трубку
[handup-sip]
exten => _X!,1,HangUp()

;Исходящие звонки
[call-out]
;Звонок на внутренний номер
exten => _XXX,1,Dial(SIP/${EXTEN})
;Звонок на внешний номер
exten => _XXX.,1,Dial(SIP/${EXTEN}@397945)

include => handup-sip

;Входящие звонки
[call-in]
exten => 397945,1,Dial(SIP/100)

Я выложил полную версию файла, а не только то, что добавил. Добавленные строки выделил цветом.

В нашем примере в контекст исходящих звонков мы добавили правило набора любого номера длиннее трех символов через транк 397954. Если в локальных звонках маска экстеншена задается тремя любыми символами, то тут мы в конец добавили точку, которая означает любое количество символов.

С таким диалпланом при наборе трехзначного номера вы позвоните на локальный номер, а при наборе любого городского номера сможете позвонить на него без каких-либо добавочных цифр. Сразу набираете номер с 8 и так далее.

Контекст [call-in] описывает поведение при входящем звонке. В нашем случае все входящие звонки с транка 397945 будут направляться на номер секретаря 100. К этому контексту мы еще вернемся позже, когда будем настраивать голосовое меню.

Сохраняем dial-plan и перезагружаем астериск единой командой reload, либо отдельно перезагружаем sip и dialplan командами:

CLI> sip reload
CLI> dialplan reload

Теперь можно попробовать позвонить, к примеру, на тестовый номер zadarma - 4444 для эхотеста. Если все получилось, значит вы правильно настроили исходящие звонки. Для проверки входящего звонка, позвоните в Москве на номер +7 (495) 777-66-75 и введите свой добавочный номер в виде логина. Звонок должен переключиться на номер 100. Чтобы это произошло, необходимо, чтобы peer с номером 100 был подключен к астериску.

Я проверил, без проблем дозвонился и по исходящему номеру, и по входящему. В файле Master.csv появилась информация о совершенных звонках:

"","100","4444","call-out","""Number 100"" <100>","SIP/100-00000002","SIP/397945-00000003","Dial","SIP/4444@397945","2020-02-27 14:13:18","2020-02-27 14:13:20","2020-02-27 14:13:25",6,5,"ANSWERED","DOCUMENTATION","1582812798.3",""
"","79689056505","397945","call-in","""79689056505"" <79689056505>","SIP/397945-00000004","SIP/100-00000005","Dial","SIP/100","2020-02-27 14:14:11",,"2020-02-27 14:14:16",4,0,"BUSY","DOCUMENTATION","1582812851.6",""

После звонков в консоли астера и в логе /var/log/asterisk/messages вы увидите множество ошибок:

res_hep.c: Unable to send packet: Address Family mismatch between source/destination

Чтобы их не было, вам нужно на сервере отключить протокол ipv6.

В таком виде АТС уже вполне работоспособна, можно пользоваться, но есть ряд неудобств. Например, если позвонить на трехзначный номер, которого не существует, или на номер, который не зарегистрирован в данный момент на устройстве, вы просто получите сброс звонка и не поймете, в чем проблема. Для этих событий нужна отдельная обработка. Чтобы не загружать сразу файл конфигурации длинными и непонятными конструкциями, я рассмотрю этот момент ниже, когда буду рассказывать про голосовую почту. Это не критичная настройка, в таком виде все будет замечательно работать, но не так удобно, как могло бы.

Приветствие и голосовое меню (ivr)

Основной функционал asterisk реализован. Будем его расширять. Практически на всех АТС присутствует голосовое меню, которое встречает звонящего. Я рассмотрю настройку самого простого варианта голосового меню, как его еще называют ivr. Позвонив, человек услышит какое-то приветствие, далее ему будет предложено ввести внутренний номер абонента, если он его знает, либо дождаться ответа секретаря.

Для простоты настройки и отладки, поделюсь способом, который использую я. У проекта zadarma есть клиент под андроид - Zadarma SIP. Скачиваете его на телефон и регистрируете еще одну учетную запись в проекте. Логинитесь под ней в телефоне и можете звонить на свой астериск, просто набирая 6-ти значный номер аккаунта, который используете на сервере. Таким образом вы быстро, удобно и бесплатно эмулируете входящие звонки с внешних линий на свой сервер.

Начнем настройку с того, что создадим возможность для записи приветствия. Вы можете записать его где угодно и потом скопировать на сервер astersik. Но можно поступить удобнее - записать прямо с телефонного аппарата приветствие и использовать его в голосовом меню. Чтобы это сделать, необходимо добавить в dialplan в контекст исходящих звонков, в моем примере это [call-out], в самое начало следующую конструкцию:

;Номер для записи звуков, окончание записи #
exten => _35X, 1, NoOp()
exten => _35X, n, Wait(2)
exten => _35X, n, Playback(beep)
exten => _35X, n, Record(/tmp/music${EXTEN:2}:wav)
exten => _35X, n, Wait(1)
exten => _35X, n, Playback(/tmp/music${EXTEN:2})
exten => _35X, n, Wait(2)
exten => _35X, n, Hangup()

Перезагружаем dialplan:

CLI> dialplan reload

Теперь при звонке на любой из номеров 350-359 вы услышите бип, после которого начнется запись всего, что сказано в трубку. Чтобы завершить запись, нажмите #. После этого вы прослушаете то, что было записано. Файл с записью будет сохранен в папку /temp. Если вы позвоните на номер 351, то файл будет иметь имя music1.wav, если на 355, то music5.wav. Можно записать до 10-ти разных вариантов и потом из них выбирать.

Сохраните подходящую запись с именем ivr-main.wav и разместите его в какой-нибудь папке. Я положил в папку /etc/asterisk/ivr. Добавим пример голосового меню в нашу конфигурацию asterisk. Для этого снова открываем extensions.conf и добавляем в него новый контекст [ivr-main] следующего содержания:

[ivr-main]
exten => s,1,Answer()
;Проигрываем приветствие
exten => s,2,Background(/etc/asterisk/ivr/ivr-main)
;Ждем 5 секунд ввода добавочного номера
exten => s,3,WaitExten(5)
;Звоним по введенному добавочному
exten => _XXX,1,Dial(SIP/${EXTEN})
;Если введен не существующий номер, то говорим об этом и отправляем в начало приветствия
exten => _XXX,2,Playback(privacy-incorrect)
exten => _XXX,3,Goto(ivr-main,s,1)
;Если звонящий ничего не вводит, то звоним секретарю
exten => t,1,Dial(SIP/100)

В комментариях я сделал все пояснения. Мы создали контекст для ivr. Теперь его надо добавить в контекст входящих звонков. Для этого изменяем существующий контекст [call-in], заменяя в нем единственную строку на новую:

exten => 397945,1,Goto(ivr-main,s,1)

Перезапускаем диал план и звоним снаружи на внешний номер. Вы должны услышать голосовое приветствие ivr, которое мы только что настроили. После этого этапа ваш файл extensions.conf должен выглядеть примерно так (комментарии вырезал):

[general]
static=yes
writeprotect=no
[globals]
[default]

[handup-sip]
exten => _X!,1,HangUp()

[call-out]
exten => _35X, 1, NoOp()
exten => _35X, n, Wait(2)
exten => _35X, n, Playback(beep)
exten => _35X, n, Record(/tmp/music${EXTEN:2}:wav)
exten => _35X, n, Wait(1)
exten => _35X, n, Playback(/tmp/music${EXTEN:2})
exten => _35X, n, Wait(2)
exten => _35X, n, Hangup()
exten => _XXX,1,Dial(SIP/${EXTEN})
exten => _XXX.,1,Dial(SIP/${EXTEN}@397945)
include => handup-sip

[call-in]
exten => 397945,1,Goto(ivr-main,s,1)

[ivr-main]
exten => s,1,Answer()
exten => s,2,Background(/etc/asterisk/ivr/ivr-main)
exten => s,3,WaitExten(5)
exten => _XXX,1,Dial(SIP/${EXTEN})
exten => _XXX,2,Playback(privacy-incorrect)
exten => _XXX,3,Goto(ivr-main,s,1)
exten => t,1,Dial(SIP/100)

Включаем голосовую почту

Продолжаем наращивать функционал voip атс. В данном разделе опишу настройку голосовой почты в asterisk. Для начала пару слов о том, что это такое. Если адресат звонка долго не отвечает, мы можем предложить звонящему оставить для него голосовое сообщение. Когда получатель вернется на место, он сможет прослушать оставленные ему сообщения. При этом, после записи голосового сообщения, будет отправлено письмо с записью этого сообщения на почтовый адрес получателя.

На практике я не видел, чтобы голосовую почту активно использовали. Но для полноты картины расскажу про нее, возможно вам она пригодится. Открываем файл voicemail.conf на редактирование. Я не трогал настройки по-умолчанию, просто добавляем в секцию [default] ящики голосовой почты для нужных нам сотрудников в следующем виде:

130 => 1234,Number 130,user130@mail.ru
100 => 1234,Number 100,user100@mail.ru
130 внутренний номер абонента
1234 пароль доступа к ящику голосовой почты
user130@mail.ru почтовый адрес, куда будет отправлено записанное голосовое сообщение

Для корректной отправки почтовых сообщений сразу на внешние почтовые ящики необходимо правильно настроить локальный почтовый сервер, либо использовать внешний. Я рекомендую использовать отдельный сервер, наверняка он есть в организации, либо на локальном использовать какой-то публичный с авторизацией по smtp. Пример такой настройки - отправка почты с авторизацией по smtp в linux.

В консоли перезапускаем модуль голосовой почты и проверяем пользователей:

CLI> voicemail reload
Reloading voicemail configuration...
asterisk*CLI> voicemail show users
Context Mbox User Zone NewMsg
default 130 Number 121 0
default 100 Number 100 0
other 1234 Company2 User 0
3 voicemail users configured.

Наши два добавленных пользователя и один тестовый остался из дефолтной конфигурации. Его можно удалить. Их вообще два должно быть. Одного я уже удалил, второго забыл.

Это пол дела. Теперь нам нужно добавить голосовую почту в dialplan. Причем в 2 разных места. Я буду использовать номер 500 для звонка в панель управления голосовой почтой. Позвонив на этот номер, пользователь введет свой пароль и сможет управлять голосовыми сообщениями (слушать, удалять, менять настройки). Добавим в контекст для исходящих звонков звонок на этот номер. Добавлять следует сразу за номерами для записи, которые мы ранее создали и перед правилом набора трехзначных номеров.

[call-out]
;Номер для записи звуков, окончание записи #
exten => _35X, 1, NoOp()
exten => _35X, n, Wait(2)
exten => _35X, n, Playback(beep)
exten => _35X, n, Record(/tmp/music${EXTEN:2}:wav)
exten => _35X, n, Wait(1)
exten => _35X, n, Playback(/tmp/music${EXTEN:2})
exten => _35X, n, Wait(2)
exten => _35X, n, Hangup()
;Управление голосовой почтой
exten => 500,1,VoiceMailMain()
;Звонок на внутренний номер
exten => _XXX,1,Dial(SIP/${EXTEN},15)
;Звонок на внешний номер
exten => _XXX.,1,Dial(SIP/${EXTEN}@397945)

Добавленные данные выделил цветом. Обращаю внимание на цифру 15. Ранее этой настройки не было, сейчас я добавил. Она будет означать, что звонок будет длиться 15 секунд. Если за это время никто не ответит, он будет сброшен. До использования голосовой почты, можно было не устанавливать этот параметр, оставить его значение по-умолчанию, оно очень большое, не помню точно сколько по времени. Но сейчас нам нужно при неснятии трубки дольше 15-ти секунд, включать запись голосового сообщения.

Конкретно в контексте внутренних звонков этот параметр не принципиален, так как я не добавляю голосовую почту для звонков внутри организации, хотя можно это сделать. Не вижу в этом смысла. Я добавил сюда этот параметр, чтобы время ожидания ответа было одинаково во всех звонках. В следующих изменениях это уже будет играть принципиальное значение.

Пока мы просто добавили номер, куда можно позвонить для управления голосовой почтой. Теперь добавим непосредственно возможность записи голосовых сообщений по событиям. Остановимся на этом пункте поподробнее. Для начала уясним, в каких состояниях может пребывать номер:

  1. Номера вообще не существует на сервере. В нашем случае, к примеру, это любой номер не из диапазона 100-130.
  2. Номер существует, но он не зарегистрирован на АТС, то есть аппарат с этим номером не подключен.
  3. Номер существует, зарегистрирован, но при звонке на него никто не отвечает.
  4. Номер существует, зарегистрирован, но в данный момент занят.

Каждое из этих четырех состояний обрабатывается отдельно. Я считаю, что голосовую почту уместно будет включать по событию номер 3. Но это не обязательно, можно и на занято повесить возможность оставить сообщение. Тут на ваше усмотрение. Я покажу пример, как это делается, а вы сможете настроить так, как вам нужно.

Обработка этих событий не такая простая, как кажется на первый взгляд. Я сразу же столкнулся с трудностью следующего характера. С параметром call-limit=1 при звонке на номер, который занят в данный момент, астериск возвращает статус CHANUNAVAIL, что может означать, к примеру, что канал недоступен. На статус занято BUSY это совсем не похоже. Для разрешения этой ситуации я воспользуюсь функцией ChanIsAvail, которая проверяет не статус пира, а статус канала и возвращает значение 2 или 3, когда он занят.

Для различения несуществующих и не подключенных пиров я буду использовать функцию SIPPEER. Если она ничего не возвращает, значит номера не существует, если значение UNKNOWN, значит номер не подключен. С отсутствием ответа какое-то время проще всего. Если пир возвращает статус NOANSWER, включаем голосовую почту. Собираем все статусы в одно место и добавляем голосовую почту. Для этого в контекст [ivr-main] добавляем новые параметры и приводим его к следующему виду:

[ivr-main]
exten => s,1,Answer()
exten => s,2,Background(/etc/asterisk/ivr/ivr-main)
exten => s,3,WaitExten(5)
exten => _XXX,1,Dial(SIP/${EXTEN},15)
;Задаем переменную для передачи в голосовую почту
exten => _XXX,n,Set(dstNUM=${EXTEN})
;Проверяем статус пира, существует или нет
exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status)}" = ""]?num-not-exist,1)
;Проверяем статус пира, подключен или нет
exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status):0:2}" = "UN"]?num-not-connected,1)
;Проверяем канал на занятость
exten => _XXX,n,ChanIsAvail(SIP/${EXTEN},s)
;Выводим в лог значение функции ChanIsAvail, нужно только для отладки, можно удалить строку
exten => _XXX,n,NoOp(=========== ChanIsAvail STATUS: ${AVAILSTATUS} ===========)
;Если функция возвращает 2 или 3, значит абонент занят
exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 2]?num-BUSY,1)
exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 3]?num-BUSY,1)
;Обрабатываем остальные статусы
exten => _XXX,n,Goto(num-${DIALSTATUS},1)
;Если номера не существует говорим "Ошибочный номер, попробуйте еще раз"
exten => num-not-exist,1,Wait(2)
exten => num-not-exist,n,Playback(invalid)
;Если номер не подключен, говорим "Набранный вами номер отключен, проверьте номер и повторите попытку
exten => num-not-connected,1,Wait(2)
exten => num-not-connected,n,Playback(ss-noservice)
;Если номер занят, говорим "Занято"
exten => num-BUSY,1,Wait(2)
exten => num-BUSY,n,Playback(vm-isonphone)
;Если номер не отвечает, включаем голосовую почту
exten => num-NOANSWER,1,Wait(2)
exten => num-NOANSWER,n,Voicemail(${dstNUM},u)
;Если еще по какой-то причине будет статус CHANUNAVAIL, говорим, что номер не доступен в данный момент
exten => num-CHANUNAVAIL,1,Wait(2)
exten => num-CHANUNAVAIL,n,Playback(vm-isunavail)
;Если в голосовом меню не выбрали внутренний номер, адресуем звонок секретарю
exten => t,1,Dial(SIP/100,15)

Если вам нужна обработка статусов номеров для внутренних звонков, то скопируйте обработку состояний в контекст [call-out], за исключением последней строки, которая отвечает за звонок секретарю. Полностью контекст внутренних звонков будет выглядеть вот так:

[call-out]
;Номер для записи звуков, окончание записи #
exten => _35X, 1, NoOp()
exten => _35X, n, Wait(2)
exten => _35X, n, Playback(beep)
exten => _35X, n, Record(/tmp/music${EXTEN:2}:wav)
exten => _35X, n, Wait(1)
exten => _35X, n, Playback(/tmp/music${EXTEN:2})
exten => _35X, n, Wait(2)
exten => _35X, n, Hangup()
;Управление голосовой почтой
exten => 500,1,VoiceMailMain()
;Звонок на внутренний номер
exten => _XXX,1,Dial(SIP/${EXTEN},15)
exten => _XXX,n,Set(dstNUM=${EXTEN})
exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status)}" = ""]?num-not-exist,1)
exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status):0:2}" = "UN"]?num-not-connected,1)
exten => _XXX,n,ChanIsAvail(SIP/${EXTEN},s)
exten => _XXX,n,NoOp(=========== ChanIsAvail STATUS: ${AVAILSTATUS} ===========)
exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 2]?num-BUSY,1)
exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 3]?num-BUSY,1)
exten => _XXX,n,Goto(num-${DIALSTATUS},1)
exten => num-not-exist,1,Wait(2)
exten => num-not-exist,n,Playback(invalid)
exten => num-not-connected,1,Wait(2)
exten => num-not-connected,n,Playback(ss-noservice)
exten => num-BUSY,1,Wait(2)
exten => num-BUSY,n,Playback(vm-isonphone)
exten => num-NOANSWER,1,Wait(2)
exten => num-NOANSWER,n,Voicemail(${dstNUM},u)
exten => num-CHANUNAVAIL,1,Wait(2)
exten => num-CHANUNAVAIL,n,Playback(vm-isunavail)
;Звонок на внешний номер
exten => _XXX.,1,Dial(SIP/${EXTEN}@397945)
include => handup-sip

Я во всех звонках установил время ожидания ответа 15 секунд. Если вы считаете, что нужно больше, измените этот параметр.

Обращаю ваше внимание, что в контексте голосового меню я не сделал обработку статусов состояния телефона секретаря, хотя это может быть нужно, если у вас будет один секретарь принимать звонки. Ему и голосовая почта может пригодиться. В следующем пункте я расскажу про случай, когда в офисе работают 2 секретаря и обработкой звонков будет заниматься очередь (queue), поэтому статусы в том виде, как они реализованы здесь будут не нужны. Вы можете использовать любую конфигурацию, которая вам подойдет. Например, использовать очередь, но с одним секретарем в ней. Настраивайте по аналогии, я даю базовый функционал. Все возможные случаи разобрать невозможно.

Перечитывайте диалплан и тестируйте конфигурацию. При звонке абоненту и его неответе, звонящий услышит в трубке сообщение о том, что номер не отвечает и предложение оставить голосовую почту. Если звонивший оставит сообщение, то получатель получит это сообщение по email и сможет его прослушать там, либо позвонить на номер 500, ввести свой номер и пароль, заданные в voicemail.conf и послушать сообщение по телефону.

Я сталкивался с ошибкой, когда у пользователя в настройках отключена голосовая почта, но он все равно получал сообщения. У него мигало оповещение на телефонном аппарате. Нужно было оперативно удалить все оставленные сообщения без прослушивания. Как удалить голосовую почту в астериск я написал в отдельной заметке.

На этом настройка голосовой почты окончена. Можно пользоваться, не забывая добавлять новых пользователей в voicemail.conf и перечитывая конфигурацию голосовой почты.

Очереди (queues) входящих звонков

С помощью очередей в астериске можно управлять потоком входящих звонков, перераспределяя их по определенным правилам. В нашей конфигурации asterisk мы настроим очередь (queue) для направления звонка двум секретарям одновременно. Кто первый ответит, тот и будет разговаривать со звонящим. Если один секретарь уже разговаривает, новый звонок поступит к другому. Если оба секретаря будут заняты, звонящий будет слушать мелодию и ожидать, пока кто-нибудь не освободится. Как только один из секретарей освободится, звонящего из очереди направит на освободившийся номер.

Номер первого секретаря - 100, второго - 130. Я настраиваю простейшую конфигурацию очереди в астериск для понимания принципа работы. Более сложный вариант настройки это сделать 3 очереди для каждого отдела и в голосовом меню-приветствии сделать возможность позвонить в конкретный отдел. Эту конфигурацию я рассмотрю в отдельной статье, хотя в нем и нет ничего сложного. Делается по аналогии с приведенным примером.

Открываем файл queues.conf и добавляем в самый конец:

[secretary]
strategy = ringall
member => SIP/100
member => SIP/130

Все остальные настройки оставляю по-умолчанию. Параметр strategy может принимать следующие значения:

ringall вызываются все доступные участники до тех пор, пока кто-то из них не ответит на вызов (по умолчанию).
leastrecent Вызывается первый свободный участник, который меньше всего вызывался из этой очереди.
fewestcalls Вызывается первый свободный участник, который обработал наименьшее количество вызовов из данной очереди.
random случайным образом вызывается не занятый участник, обрабатывающий очередь.
rrmemory циклическое распределение с памятью, запоминается последний участник, ответивший на вызов.

Вы можете выбрать наиболее подходящую вам стратегию распределения звонков в очереди. Дальше нужно добавить в extensions.conf в созданный нами ранее контекст с голосовым меню отправку звонка в очередь с секретарями. Для этого меняем строку в [ivr-main]:

exten => t,1,Dial(SIP/100,15)

на новую:

exten => t,1,Queue(secretary,t)

Если раньше при звонке на внешний номер, звонящий не набирал внутренний номер абонента, то через 5 секунд он перенаправлялся к секретарю с номером 100. Теперь он будет отправляться в очередь secretary, в которую мы завели 2 номера - 100 и 130. Можно добавить и больше номеров, если есть необходимость.

Перечитываем полностью конфигурацию asterisk:

CLI> reload

Состояние созданной очереди:

CLI> queue show secretary
secretary has 0 calls (max unlimited) in 'ringall' strategy (0s holdtime, 0s talktime), W:0, C:0, A:0, SL:0.0% within 0s
Members:
SIP/100 (ringinuse enabled) (Not in use) has taken no calls yet
SIP/130 (ringinuse enabled) (Not in use) has taken no calls yet
No Callers

Теперь можете позвонить на внешний номер и дождаться перенаправления на секретаря. Зазвонят оба аппарата. Если оба заняты, звонок будет висеть в очереди и ждать освобождения. После звонка статистика очереди изменится:

CLI> queue show secretary
secretary has 0 calls (max unlimited) in 'ringall' strategy (0s holdtime, 2s talktime), W:0, C:1, A:1, SL:0.0% within 0s
Members:
SIP/100 (ringinuse enabled) (Not in use) has taken 1 calls (last was 63 secs ago)
SIP/130 (ringinuse enabled) (Not in use) has taken no calls yet
No Callers

Вот так легко организовать простую queue (очередь) в asterisk. Более сложные примеры я буду рассматривать в отдельных статьях.

Учет и просмотр статистики звонков (cdr viewer)

Важной и нужной возможностью современной АТС на базе asterisk является сбор и просмотр статистики звонков. По умолчанию, астериск ведет статистику в файле /var/log/asterisk/cdr-csv/Master.csv. Разобрать этот файл и передать куда-то в обработку не очень сложно, если у вас есть что-то или кто-то, кто способен написать на каком-нибудь языке программирования обработку.

Мы будем использовать готовые бесплатные инструменты для просмотра статистики звонков. Все необходимое для этого мы установили в самом начале. Перенесем сбор статистики в mysql базу. Для этого запускаем mariadb сервер, добавляем в автозагрузку и устанавливаем пароль администратора:

# systemctl start mariadb
# systemctl enable mariadb.service
# /usr/bin/mysql_secure_installation

Подключаемся к mysql и создаем пользователя и базу данных:

# mysql -uroot -p
MariaDB [(none)]> create database asterisk;
MariaDB [(none)]> use asterisk;
MariaDB [asterisk]> CREATE TABLE `cdr` (   `id` int(9) unsigned NOT NULL auto_increment,   `calldate` datetime NOT NULL default '0000-00-00 00:00:00',   `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 '',   `uniqueid` varchar(32) NOT NULL default '',   `userfield` varchar(255) NOT NULL default '',   PRIMARY KEY  (`id`),   KEY `calldate` (`calldate`),   KEY `accountcode` (`accountcode`),   KEY `uniqueid` (`uniqueid`),   KEY `dst` (`dst`),   KEY `src` (`src`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
MariaDB [asterisk]> grant all on asterisk.* to 'asterisk_user'@'localhost' identified by '12345678';
asterisk имя базы данных
asterisk_user пользователь базы данных
12345678 пароль пользователя бд

Теперь нам надо установить odbc коннектор для mysql - mysql-connector-odbc. С этим в Centos 8 есть некоторые трудности, так как нужных пакетов нет в базовых репозиториях. Я в итоге его взял из официальной репы mysql. Для этого скачиваем и подключаем их репозиторий.

# wget https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm
# dnf localinstall mysql80-community-release-el8-1.noarch.rpm
# dnf makecache

Тут я получил ошибку:

Failed to download metadata for repo 'mysql-tools-community'
Error: Failed to download metadata for repo 'mysql-tools-community'

Не стал разбираться, почему этот репозиторий недоступен, так как он мне не нужен. Просто зашел в /etc/yum.repos.d/mysql-community.repo и закомментировал строки с этим репозиторием.

#[mysql-tools-community]
#name=MySQL Tools Community
#baseurl=http://repo.mysql.com/yum/mysql-tools-community/el/8/$basearch/
#enabled=1
#gpgcheck=1
#gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql

После этого благополучно обновил кэш пакетов и установил mysql-connector-odbc на centos 8.

# dnf install mysql-connector-odbc

Теперь редактируем файлы конфигурации. Добавляем в самый конец /etc/asterisk/res_odbc.conf:

[asterisk]
enabled => yes
dsn => MySQL-asterisk
username => asterisk_user
password => 12345678

В конец файла /etc/asterisk/cdr_adaptive_odbc.conf:

[cdr_adaptive_connection]
connection=asterisk
table=cdr
alias start => calldate

Создаем файл /etc/odbc.ini следующего содержания:

[MySQL-asterisk]
Description = MySQL Asterisk database
Driver = MySQL
Server = localhost
User = asterisk_user
Password = 12345678
Socket = /var/lib/mysql/mysql.sock
Database = asterisk

Редактируем файл /etc/odbcinst.ini. Я его не трогал, оставил по-умолчанию, только в самый конец секции [MySQL] добавил две недостающие строки. Я не разбирался нужны они или нет, просто подсмотрел в другой инструкции. Вот как этот файл выглядит у меня:

[MySQL]
Description = ODBC for MySQL
Driver = /usr/lib/libmyodbc8.so
Setup = /usr/lib/libodbcmyS.so
Driver64 = /usr/lib64/libmyodbc8a.so
Setup64 = /usr/lib64/libodbcmyS.so
FileUsage = 1
CPTimeout =
CPReuse =

В последнем конфиге проверьте все пути. Имена файлов могут немного отличаться в зависимости от установленной версии коннектора. Актуализируйте пути и имена файлов. После этого проверьте работу odbc connector. Для этого запустите в консоли команду:

# odbcinst -q -d

Вы должны увидеть список всех настроенных коннекторов, в том числе [Mysql]. Настроим использование нашего часового пояса в записях cdr. По-умолчанию там стоит часовой пояс GTM. Для этого в файле /etc/asterisk/cdr.conf указываем параметр:

usegmtime=no

После этого перезапускаем астериск:

# systemctl restart asterisk

Заходим в консоль и проверяем подключение по odbc.

> odbc show all

Настройка odbc в asterisk

Совершаем звонок и проверяем таблицу mysql. У меня добавилась информация о звонке с номера 100 на 101, когда он был не подключен. Если сделать экспорт, то получится вот такая запись:

INSERT INTO `cdr` (`id`, `calldate`, `clid`, `src`, `dst`, `dcontext`, `channel`, `dstchannel`, `lastapp`, `lastdata`, `duration`, `billsec`, `disposition`, `amaflags`, `accountcode`, `uniqueid`, `userfield`) VALUES
(1, '2020-02-27 19:08:17', '\"Number 100\" <100>', '100', 'num-not-connected', 'call-out', 'SIP/100-0000000e', '', 'Dial', 'SIP/101,15', 6, 4, 'ANSWERED', 3, '', '1582819697.14', '');

Для удобства дальнейшей работы, я настроил web сервер на базе apache. Не буду на этом подробно останавливаться. Чтобы двигаться дальше нам нужен классический web сервер на базе php. Для удобства рекомендую сразу настроить phpmyadmin или любой другой клиент к mysql. Если привыкли работать с mysql через консоль, можете обойтись без него.

Дальше нам надо настроить какую-нибудь web панель для просмотра этой статистики. Я решил сразу установить панель, которая позволяет не только смотреть статистику, но прослушивать записанные разговоры. Поэтому дальнейшая настройка панели просмотра статистики переходит в следующий раздел, в котором я расскажу, как записывать звонки.

Запись (record) разговоров

Запись разговоров в asterisk настраивается относительно не сложно. Буквально нужно добавить несколько строк в dialplan. Но мы сразу сделаем более расширенную настройку. Мы будем не просто записывать все разговоры, но станем хранить информацию о звонках в mysql, чтобы их можно было прослушивать через удобную web панель просмотра статистики.

Хранить записи будем в mp3, потому нам понадобится утилита lame, для конвертации файлов из формата wav в mp3. Скачаем ее и установим.

# cd ~
# wget http://sourceforge.net/projects/lame/files/lame/3.100/lame-3.100.tar.gz
# tar zxvf lame-3.*
# cd lame-3.*
# ./configure
# make && make install

В качестве web панели я буду использовать Asterisk-CDR-Viewer-Mod. Очень простая и функциональная штука. Настраивается легко, пользоваться удобно. Скачиваем исходники с github:

# cd ~
# git clone https://github.com/prog-it/Asterisk-CDR-Viewer-Mod

Копируем содержимое репозитория в директорию cdr web сервера.

# mkdir /var/www/html/cdr
# cp -R ~/Asterisk-CDR-Viewer-Mod/* /var/www/html/cdr
# chown -R apache. /var/www/html/cdr

В папке docs подробная инструкция по настройке. Все дальнейшие действия делаются в соответствии с ней. Исправляются только некоторые особенности данной версии системы. Нам необходимо добавить дополнительное поле в таблицу cdr для хранения имени файла. Для этого либо в консоли mysql, либо через phpmyadmin выполните код:

alter table  `cdr` add column `filename` varchar(120) DEFAULT 'none' after `userfield`;

Редактируем файл /etc/asterisk/cdr_mysql.conf, добавляя в самый конец 2 строки:

alias realdst => realdst
alias filename => filename

Дальше редактируем диалплан. Открываем /etc/asterisk/extensions.conf и добавляем в секцию globals переменную, соответствующую папке, где будут храниться записи разговоров.

[globals]
DIR_RECORDS=/mnt/calls/

Добавляем макрос для записи перед контекстами звонков:

[recording]
exten => s,1,Set(fname=${UNIQUEID}-${STRFTIME(${EPOCH},,%Y-%m-%d-%H_%M)}-${ARG1}-${ARG2})
exten => s,n,Set(monopt=nice -n 19 /usr/local/bin/lame -b 32 --silent "${DIR_RECORDS}${fname}.wav" "${DIR_RECORDS}${fname}.mp3" && rm -f "${DIR_RECORDS}${fname}.wav" && chmod o+r "${DIR_RECORDS}${fname}.mp3")
exten => s,n,Set(CDR(filename)=${fname}.mp3)
exten => s,n,Set(CDR(realdst)=${ARG2})
exten => s,n,MixMonitor(${DIR_RECORDS}${fname}.wav,b,${monopt})
exten => s,n(no),Verbose(Exit record)
exten => s,n,Return()

И редактируем контексты входящих и исходящих разговоров, добавляя туда макрос на запись. Он идет самым первым, перед набором номера. Вот так у меня выглядит контекст локальных звонков и входящих через ivr меню с учетом всех сделанных ранее настроек:

[call-out]
;Номер для записи звуков, окончание записи #
exten => _35X, 1, NoOp()
exten => _35X, n, Wait(2)
exten => _35X, n, Playback(beep)
exten => _35X, n, Record(/tmp/music${EXTEN:2}:wav)
exten => _35X, n, Wait(1)
exten => _35X, n, Playback(/tmp/music${EXTEN:2})
exten => _35X, n, Wait(2)
exten => _35X, n, Hangup()
;Управление голосовой почтой
exten => 500,1,VoiceMailMain()
;Звонок на внутренний номер
exten => _XXX,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
exten => _XXX,n,Dial(SIP/${EXTEN},10)
exten => _XXX,n,Set(dstNUM=${EXTEN})
exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status)}" = ""]?num-not-exist,1)
exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status):0:2}" = "UN"]?num-not-connected,1)
exten => _XXX,n,ChanIsAvail(SIP/${EXTEN},s)
exten => _XXX,n,NoOp(=========== ChanIsAvail STATUS: ${AVAILSTATUS} ===========)
exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 2]?num-BUSY,1)
exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 3]?num-BUSY,1)
exten => _XXX,n,Goto(num-${DIALSTATUS},1)
exten => num-not-exist,1,Wait(2)
exten => num-not-exist,n,Playback(invalid)
exten => num-not-connected,1,Wait(2)
exten => num-not-connected,n,Playback(ss-noservice)
exten => num-BUSY,1,Wait(2)
exten => num-BUSY,n,Playback(vm-isonphone)
exten => num-NOANSWER,1,Wait(2)
exten => num-NOANSWER,n,Voicemail(${dstNUM},u)
exten => num-CHANUNAVAIL,1,Wait(2)
exten => num-CHANUNAVAIL,n,Playback(vm-isunavail)
;Звонок на внешний номер
exten => _XXX.,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
exten => _XXX.,n,Dial(SIP/${EXTEN}@397945)
include => handup-sip

[ivr-main]
exten => s,1,Answer()
exten => s,2,Background(/etc/asterisk/ivr/ivr-main)
exten => s,3,WaitExten(5)
exten => _XXX,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
exten => _XXX,n,Dial(SIP/${EXTEN},10)
exten => _XXX,n,Set(dstNUM=${EXTEN})
exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status)}" = ""]?num-not-exist,1)
exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status):0:2}" = "UN"]?num-not-connected,1)
exten => _XXX,n,ChanIsAvail(SIP/${EXTEN},s)
exten => _XXX,n,NoOp(=========== ChanIsAvail STATUS: ${AVAILSTATUS} ===========)
exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 2]?num-BUSY,1)
exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 3]?num-BUSY,1)
exten => _XXX,n,Goto(num-${DIALSTATUS},1)
exten => num-not-exist,1,Wait(2)
exten => num-not-exist,n,Playback(invalid)
exten => num-not-connected,1,Wait(2)
exten => num-not-connected,n,Playback(ss-noservice)
exten => num-BUSY,1,Wait(2)
exten => num-BUSY,n,Playback(vm-isonphone)
exten => num-NOANSWER,1,Wait(2)
exten => num-NOANSWER,n,Voicemail(${dstNUM},u)
exten => num-CHANUNAVAIL,1,Wait(2)
exten => num-CHANUNAVAIL,n,Playback(vm-isunavail)
exten => t,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
exten => t,n,Queue(secretary,t)

Создаем директорию для записи разговор и назначаем ей права.

# mkdir /mnt/calls
# chown -R asterisk. /mnt/calls

Перезапускаем астериск для применения всех настроек:

# systemctl restart asterisk

Осталось только указать настройки подключения к базе данных cdr viewer. Эти настройки находятся в файле inc/config.php. Для начала создадим его.

# cp /var/www/html/cdr/inc/config/config.php.sample /var/www/html/cdr/inc/config/config.php

Задаем там следующие параметры:

Mysql
$db_type = 'mysql';
$db_host = 'localhost';
$db_port = '3306';
$db_user = 'asterisk_user';
$db_pass = '12345678';
$db_name = 'asterisk';
$db_table_name = 'cdr';

$system_storage_format = 5;
$system_monitor_dir = '/mnt/calls';

Остальные параметры я оставил без изменений. Можно звонить и тестировать запись разговоров, просмотр статистики через Asterisk CDR Viewer Mod. Все записанные файлы складываются в одну папку /mnt/calls. В readme.txt описан пример, как настроить сортировку записей по папкам с датами. Если вам это нужно, сделайте, ничего сложного нет, все рассказано подробно. В web панель можно зайти просто набрав в браузере http://ip/cdr/.

Просмотр статистики и записей звонков

Музыка на ожидании (on hold)

Вы можете назначить любую мелодию для проигрывания во время нахождения звонка в очереди.  Можете крутить мелодию вместо длинных гудков во время вызова, хотя считаю это лишним. Уместней всего мелодию пускать, как я уже сказал, во время ожидания в очереди и во время удержания звонка по какой-то причине. По-умолчанию в эти моменты проигрывается дефолтная мелодия.

За конфигурацию music on hold отвечает соответствующий файл настроек - /etc/asterisk/musiconhold.conf. Изначально он выглядит так:

[general]
[default]
mode=files
directory=moh

Директория указана как moh, полный ее путь /var/lib/asterisk/moh, мелодии проигрываются отсюда. Я не буду менять настройки по-умолчанию. Добавим еще один класс музыки и укажем его в свойствах очереди, где будем ее проигрывать.

Я привожу пример использования. Если у вас везде будет одна и та же мелодия, то отредактируйте канал default. Так вам не придется каждый раз указывать добавленный канал.

Копируем любым способом mp3 файл на сервер в домашнюю директорию root. Создаем директорию /var/lib/asterisk/mohmp3 и кодируем в нее мелодию из mp3 в wav:

# mkdir  /var/lib/asterisk/mohmp3
# lame --decode /root/music.mp3 /var/lib/asterisk/mohmp3/music.wav

Добавляем новый класс в musiconhold.conf в самый конец:

[mp3]
mode=files
directory=mohmp3

Теперь добавим эту мелодию в свойства очереди. Для этого в описание очереди добавьте новый параметр:

[secretary]
music = mp3
strategy = ringall
member => SIP/100
member => SIP/130

Теперь нужно перечитать настройки очереди и мелодии. Проще перезапустить сам астериск:

# systemctl restart asterisk

Можно звонить на внешний номер и ждать попадания в очередь. Вы должны услышать добавленную мелодию во время ожидания.

Чтобы добавить эту мелодию вместо длинного гудка, необходимо отредактировать dialplan, добавив новый параметр в правило набора. Если добавляете свой класс музыки, то указываете его в свойствах:

exten => _XXX,1,Dial(SIP/${EXTEN},15,m(mp3))

Если используете музыку по-умолчанию, то достаточно написать вот так:

exten => _XXX,1,Dial(SIP/${EXTEN},15,m)

Для отладки музыки на ожидании, я рекомендую добавить в dialplan в контекст локальных звонков такую конструкцию:

exten => 336,1,Answer
exten => 336,2,MusicOnHold()

336 - любой не занятый реальным пиром номер. При звонке на этот номер, вы услышите заданную дефолтную мелодию в соответствии с настройками в файле musiconhold.conf. Для проигрывания не дефолтного класса, укажите его имя в скобках. Так вы можете прослушать как звучат ваши мелодии, протестировать порядок проигрывания и т.д.

Не забывайте перезагружать диалплан после редактирования. На этом настройка music on hold закончена. Можете добавлять разные мелодии и использовать в необходимых местах диалплана или очередях.

Настройка конференций

Полезным и востребованным функционалом офисной телефонной станции является создание конференций для одновременного разговора нескольких человек. В asterisk конференция настраивается следующим образом. В специальном файле конфигурации задаются параметры комнаты для конференций. В диалплане назначается отдельный номер для комнаты с конференцией.

Создаем конфигурацию конференции. Для этого в файл confbridge.conf добавляем в самый конец:

[confer]
type=bridge
max_members=20
mixing_interval=10
internal_sample_rate=auto
record_conference=yes

В контекст исходящих звонков [call-out] добавляем в самое начало:

exten => 999,1,Answer()
exten => 999,n,ConfBridge(1,confer)

Перезапускаем астериск. Теперь при звонке на номер 999 человек попадает в комнату для конференций. Следующим участникам конференции необходимо будет так же позвонить на номер 999 для участия в совместной конференции. Если вы с кем-то уже разговариваете, хотите создать конференцию и добавить туда еще участников, то необходимо вашего собеседника переадресовать на номер конференции, затем позвонить новому абоненту и его направить туда же. После этого звоните сами на номер конференции и сможете общаться с тремя абонентами одновременно.

Как выполнять переводы и переадресации звонков я расскажу ниже.

Перевод, перехват, переадресация звонка

Рассмотрим несколько необходимых функций и возможностей телефонной станции asterisk. Начнем с перевода звонка. Как перевести звонок на другого абонента? По-умолчанию в астериске для трансфера звонка предусмотрена клавиша #. Посмотреть, так ли это в вашей конфигурации, введите в консоли астера команду:

CLI> features show
Builtin Feature               Default Current
---------------               ------- -------
Pickup                           *8     *8
Blind Transfer                    #      #
Attended Transfer
One Touch Monitor
Disconnect Call                   *      *
Park Call

Во время разговора нужно нажать # и набрать номер, куда вы хотите перевести звонок. Для того, чтобы трансфер состоялся, он должен быть разрешен в диалплане в команде Dial следующим образом:

exten => _XXX,n,Dial(SIP/${EXTEN},15,Tt)
T дать возможность звонящему (вызывающему) абоненту совершать перевод звонка на другой номер.
t дать возможность вызываемому абоненту сделать перевод звонка на другой номер

В предыдущих примерах я не указывал этот параметр. Сейчас пришло время рассказать о нем и добавить во все участки диалплана, если вам необходимо осуществлять перевод звонков в asterisk.

Перевод звонка можно сделать с помощью функции самого телефона. Мне еще не попадалось ни одного телефона, который бы не умел переводить звонок. Обычно для этих целей предназначена отдельная клавиша или функция в меню телефона. Для уточнения информации о переводе нужно воспользоваться инструкцией самого телефона. В софтфоне, которым я пользуюсь, есть отдельная клавиша для перевода звонка:

Кнопка перевода звонка

С включенным по-умолчанию Blind Transfer есть проблемы. Например, вы перенаправляете звонок на другой номер, а он не ответил или у него занято. Входящий вызов сбрасывается. В астериске есть другой режим перевода звонка, он называется Attended Transfer, по-умолчанию он выключен. Работает он более изящно. Сначала вы звоните тому, куда хотите перевести номер, разговариваете с ним, убеждаетесь, что он доступен и готов принять звонок. Только после этого переводите звонок на этого абонента. Чтобы включить такое перенаправление вызова, нужно раскомментировать в features.conf строку:

atxfer => *2

Горячую клавишу можно переназначить на любую другую. На этом о переводе звонка в астериске все.

Теперь поговорим о перехвате звонка. Хотя говорить тут особо нечего. В asteerisk перехват работает из коробки и не требует никаких настроек. Для того, чтобы перехватить звонок, нужно снять трубку и нажать комбинацию *8. Комбинация задается в том же файле, что и перехват - features.conf. Перехватывать звонки могут только абоненты в одной группе. Это задается в свойствах пользователя, я об этом рассказывал в самом начале, когда мы создавали sip аккаунты. Напомню, что речь идет о параметрах callgroup и pickupgroup.

Разберем теперь переадресацию звонка на какой-то внешний номер, например, мобильный телефон. Многие телефоны имеют встроенный функционал по перенаправлению звонка. Читаете инструкцию к телефону, смотрите, можно ли на нем установить переадресацию и как, и делаете. Работает это только если ваш телефон подключен к АТС. Он принимает звонок и сам его переадресовывает на указанный номер. Это самый простой и быстрый вариант автоматической переадресации звонка на внешний номер.

Рассмотрим другой случай переадресации на мобильный телефон. Допустим, у нас есть номер 115, который вообще отсутствует в офисе, у него нет стационарного телефона. Нам нужно, чтобы при звонке на этот номер, вызов переадресовывался на внешний номер, а конкретно на мобильный сотрудника. Для этого в dialplan нужно добавить следующую строку:

exten => 115,n,Dial(SIP/89151234567@397945)

Если вы хотите, чтобы переадресация работала только при звонках с внутренних номеров офиса, то добавить эту строку нужно в контекст [call-out] перед общим правилом набора на внутренние номера:

exten => 115,n,Dial(SIP/89151234567@397945)
exten => _XXX,n,Dial(SIP/${EXTEN},15,Tt)

Для того, чтобы переадресация на внешний номер работала и для звонков из вне, правило перенаправления на мобильный нужно поставить в контекст с голосовым приветствием [ivr-main]. Ставим туда же, перед строкой набора на внутренние номера:

exten => 115,n,Dial(SIP/89151234567@397945)
exten => _XXX,n,Dial(SIP/${EXTEN},15,Tt)

Вы можете поменять внешний номер для разных контекстов. К примеру, для сотрудников офиса сделать перенаправление на один мобильный, а для звонков клиентов на другой.

Защита asterisk с помощью fail2ban

Если ваш астериск имеет внешний ip адрес, либо на него сделан проброс портов с внешнего ip, то необходимо обеспечить защиту от перебора учеток и прочих множественных подключений. Организуем защиту с помощью известного и популярного средства fail2ban. Сделать это не сложно, fail2ban поддерживает astersik из коробки. Достаточно просто установить его и активировать некоторые настройки.

Устанавливаем fail2ban на сервер с астериском:

# dnf install fail2ban

Включаем запись в лог файл событий типа security. Для этого открываем файл /etc/asterisk/logger.conf и раскомментируем строку:

security => security

Перечитываем настройки хранения логов:

# asterisk -x "logger reload"

В папке /var/log/asterisk появился новый файл security. Его записи мы будем передавать в fail2ban для анализа. Открываем файл /etc/fail2ban/jail.conf, ищем там секцию [asterisk] и меняем путь к логфайлу и добавляем строку активации джейла:

logpath  = /var/log/asterisk/security
enabled  = true

Запускаем fail2ban и добавляем в автозапуск:

# systemctl start fail2ban
# systemctl enable fail2ban

Чтобы fail2ban работал, у вас должен быть запущен и настроен iptables. Отмечу также, что по-умолчанию fail2ban в centos использует команды firewalld. Если вы его отключили и используете голые iptables, то вам необходимо удалить файл /etc/fail2ban/jail.d/00-firewalld.conf и перезапустить fail2ban. Если этого не сделать, работать он не будет.

На этом подробная и многофункциональная настройка asterisk закончена. Я рассказал все, что запланировал, выделив наиболее востребованные функции.

Заключение

Не понравилась статья и хочешь научить меня администрировать? Пожалуйста, я люблю учиться. Комментарии в твоем распоряжении. Расскажи, как сделать правильно!

Время подвести итог проделанной работы. На всякий случай приведу полный конфиг основного файла, с которым мы работали - extensions.conf. Я писал статью почти 2 месяца, что-то добавляя, проверяя, редактируя. Она актуальна полностью на момент написания. Можно простым копипастом переносить конфигурацию и все заработает. Я проверил перед публикацией. Со временем что-то может измениться, но не думаю, что сильно. Синтаксис конфигурационных файлов почти не меняется в разных версиях астера, это позволяет без проблем переносить настройки между версиями, и тем более между операционными системами.

Я планирую раскрыть более широко затронутую тему. У меня есть примеры интересных и полезных конфигураций. По мере возможности буду писать новые статьи по серверу телефонии. На сегодня у меня все, хороших вам настроек  :-)

Напоминаю, что данная статья является частью единого цикла статьей про сервер Centos.

Другие материалы по asterisk:

Углубленный онлайн-курс по MikroTik.

Научиться настраивать MikroTik с нуля или систематизировать уже имеющиеся знания можно на углубленном онлайн-курcе по администрированию MikroTik. Автор курcа – сертифицированный тренер MikroTik Дмитрий Скоромнов. Более 40 лабораторных работ по которым дается обратная связь. В три раза больше информации, чем в MTCNA.

Помогла статья? Подписывайся на telegram канал автора

Анонсы всех статей, плюс много другой полезной и интересной информации, которая не попадает на сайт.

Автор Zerox

Владимир, системный администратор, автор сайта. Люблю настраивать сервера, изучать что-то новое, делиться знаниями, писать интересные и полезные статьи. Открыт к диалогу и сотрудничеству. Если вам интересно узнать обо мне побольше, то можете послушать интервью. Запись на моем канале - https://t.me/srv_admin/425 или на сайте в контактах.

554 комментария

  1. У вас в инструкции в Mixmonitor стоит ключ b, но записи всё равно сохраняются, даже если трубку не сняли.

  2. Татьяна

    Ошибка загрузки конфигурации в телефон уже больше 2-х месяцев мучает нас....несколько телефонов asterisk не загружается по сети - unknown
    Из N-го колличества (примерно 220 аппаратов) штук 15 пишут - unspecified , ip выдает dhcp.
    Можете подсказать где искать проблему? или посоветовать специалиста, что поможет решить вопрос. Спасибо

  3. Анатолий

    Использовал наработки из этой статьи и предыдущих для установки Asterisk на Ubuntu. Но при установке выбрал дистрибутив самого последнего Asterisk, версии 20 и самую последнюю Ubuntu. Следуя инструкции автора настроил sip.conf потом extension.conf дошел до пункта проверка пользователей CLI> sip show users и тут приехали..... Система вообще не знает команд начинающихся на слово sip. Начал гуглить и почти на всех форумах пишут ( -- не стоит использовать chan_sip в 2020 году на новых установках. Пора приучать людей к pjsip, так как chan_sip устаревший и в ближайших выпусках от него откажутся окончательно --) Похоже пришло время обновлять инструкцию под новые версии Asterisk.

    • От chan_sip уже лет 10 отказываются, ещё когда я только начал изучать Asterisk от него уже отказывались. Думаю, ещё столько же будут отказываться. Объективно, с ним нет никаких проблем для типового применения, которое описано в статье.

  4. Андрей

    Доброго
    Не подскажете , используя chan_pjsip возможно настроить на один номер два аппарата, с одновременной возможностью и звонить на этот номер, и с этих аппаратов этим номером?

  5. Веталь

    Огоромное спасибо автору за толковую статью с понятными обьяснениями.
    Прошу помощи, проблема заключается в следующем:
    На астере добавил несколько транков, создал группу внутренних номеров и очередь.
    Звонки из внутренних номеров по исходящему маршруту идут в транки все ок.
    Дальше поставил модуль коллцентр (issabel) и имею проблемку...
    когда колцентр дозванивает абонентов и закидівает их в очередь я не могу совершать звонки наружу из внутренних номеров(хотя изредка пробивает раза с 30го) можно ли как-то віставить приоритет доступа к транкам для внутренних номеров перед автодиалером?

    • Я так сходу не могу продумать решение, тем более с таким модулем никогда не работал. Для абонентов можно устанавливать call-limit, который ограничивает количество возможных линий. Возможно в эту сторону нужно смотреть. Ну и учитывать, что dialplan читается по порядку, сверху вниз. Абонентов с наименьшим приоритетом надо выделять в отдельные маски и ставить в самый низ.

      • Веталь

        Не совсем понимаю, (так как не имею ни знаний ни опыта, поднял все методом научного тыка) на многих ресурсах писалось, что расположение элементов в файлах конфигурации не играет роли... и что такое маски? и вниз чего ставить абонентов???

        У меня есть пару идей, может подскажете что нужно изменить чтобы при дозвоне после перебора транков астер не озвучивал мне что все линии заняты, а заново перебирал транки, что-бы получился вроди цикл до того пока не получится выскочить на линию?

        Спасибо за внимание!

        • Решение этой задачи требует определённых навыков и понимания работы Asterisk. Я не помогу решить эту задачу в рамках ответов на комментарии. С учётом того, что решение я тоже не знаю, его надо придумать и отладить.

  6. Подскажите, пожалуйста, деревянному, как привязать один внешний номер и 3 внутренних. И как настроить сценарий когда звонят на внешний, то звонок на Линии 1, после на 5 сек переадресация на Линию 2 и Линию 3?

    Зарание благодарен!

  7. Евгений

    Добрый день! Кто нибудь ставил на Debian11? Проблема odbc коннектором, asterisk не подключается к базе

  8. Василий Васильевич

    Сложно. А на Бейсике можно перепрограммировать астерикс?

  9. Здравствуйте, столкнулся с проблемой! У меня развернута телефония на базе FreePBX. Каждый день падает внешний телефон, то есть звонки из вне не могут пройти в организацию, идут короткие гудки. А внутренние звонки, просто тишина в трубке. После перезагрузки всё работает в штатном режиме. Подскажите в чём может быть проблема?

    • Логи надо смотреть. Как можно заочно сказать, в чём проблема? Возможно транки отваливаются, может ещё что-нибудь, какие-то сетевые проблемы и т.д.

      • Подскажите какой лог смотреть? В веб версии с самом FreePBX, ни каких ошибок не наблюдал!

        • Имеет смысл вот эти посмотреть:
          /var/log/asterisk/full
          /var/log/asterisk/freepbx.log
          /var/log/messages
          Сопоставить события там с временем, когда падает внешняя связь.

  10. Алексей

    Здравствуйте.
    Разворачиваю на Proxmox VE 7.2-3 с Версия ядра Linux 5.15.30-2-pve #1 SMP PVE 5.15.30-3 (Fri, 22 Apr 2022 18:08:27 +0200) контейнер LXC для установки: АТС asterisk. На Debian GNU/Linux 11 \n \l.

    root@proxmox:/etc# dpkg --get-selections | grep ^pve-kernel
    pve-kernel-5.15 install
    pve-kernel-5.15.30-2-pve install
    pve-kernel-helper install

    Возникла проблема с установкой dahdi:
    cd /usr/src/dahdi-linux-complete-2.10*/
    root@asteriks:/usr/src/dahdi-linux-complete-2.10.2+2.10.2# make all && make install && make config
    make -C linux all
    make[1]: Entering directory '/usr/src/dahdi-linux-complete-2.10.2+2.10.2/linux'
    make -C drivers/dahdi/firmware firmware-loaders
    make[2]: Entering directory '/usr/src/dahdi-linux-complete-2.10.2+2.10.2/linux/drivers/dahdi/firmware'
    make[2]: Leaving directory '/usr/src/dahdi-linux-complete-2.10.2+2.10.2/linux/drivers/dahdi/firmware'

    You do not appear to have the sources for the 5.15.30-2-pve kernel installed.

    make[1]: *** [Makefile:72: modules] Error 1

    make[1]: Leaving directory '/usr/src/dahdi-linux-complete-2.10.2+2.10.2/linux'

    make: *** [Makefile:9: all] Error 2

    пробовал и так apt install linux-headers*
    Failed to restart dahdi.service: Unit dahdi.service not found.

    Смотрел версию ядра, точно такая как на proxmox.

    Делал обновление на контейнере и на proxmox: sudo apt update && sudo apt dist-upgrade
    результата нет.

    Пробовал установить последнюю версию dahdi-linux-complete-3.2.0+3.2.0 тоже нет результата:

    wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-complete-3.2.0+3.2.0.tar.gz
    root@asteriks:/usr/src/dahdi-linux-complete-3.2.0+3.2.0# systemctl restart dahdi
    Failed to restart dahdi.service: Unit dahdi.service not found.
    root@asteriks:/usr/src/dahdi-linux-complete-3.2.0+3.2.0# make all && make install && make config
    make -C linux all
    make[1]: Entering directory '/usr/src/dahdi-linux-complete-3.2.0+3.2.0/linux'
    make -C drivers/dahdi/firmware firmware-loaders
    make[2]: Entering directory '/usr/src/dahdi-linux-complete-3.2.0+3.2.0/linux/drivers/dahdi/firmware'
    make[2]: Leaving directory '/usr/src/dahdi-linux-complete-3.2.0+3.2.0/linux/drivers/dahdi/firmware'
    You do not appear to have the sources for the 5.15.30-2-pve kernel installed.
    make[1]: *** [Makefile:72: modules] Error 1
    make[1]: Leaving directory '/usr/src/dahdi-linux-complete-3.2.0+3.2.0/linux'
    make: *** [Makefile:9: all] Error 2

    Подскажите пожалуйста в чем ошибка? Есть предположение, что проблема в proxmox. Но куда копать не знаю.

  11. Добрый день. Интересно, как решаете вопрос постепенного заполнения выделенного каталога под записи входящих/исходящих звонков. В сети много инструкций и примеров. Может какой-то свой способ или подход к этой теме порекомендуете?

  12. Александр

    Добрый день!
    Пробовали ли интегрировать сервисы YANDEX.SPEECHKIT? Ari или Agi пробовали использовать?

  13. Михаил

    Добрый день, Владимир
    Спасибо большое за подробно описанную статью по настройке.
    Есть такая проблема при звонке, иногда возникает редко. не знаю куда дальше копать, везде перерыл все и не нашел ответа на свой вопрос
    При исходящих звонках периодически выскакивает в дебаге астерикса следующая ошибка, автоответчик сообщает "На данный момент все линии заняты, перезвоните позже"
    ЛОГ ошибки;
    [2022-08-17 12:02:01] WARNING[3009][C-00001213] chan_sip.c: Received response: "Forbidden" from ';tag=as1514e78c'
    Подскажите пожалуйста, где копать информация по истреблении данной проблемы?

    • Это скорее всего ограничение вашего провайдера. Он выдаёт ответ вашему серверу:
      Received response: "Forbidden" from ';tag=as1514e78c'
      Напишите им в поддержку, точно ответят их ли это проблема.

  14. у вас в настройке cdr viewer ошибка, в экстеншене [recording]:
    exten => s,n,Set(CDR(filename)=${fname}.mp3) нужно изменить на .wav, т.к. он в базу данных сохраняет неверный формат, из-за чего на веб-морде не подтягиваются аудиозаписи.
    За статью спасибо.

    • Александр

      Добрый день. Прочитал вашу инструкцию в возможности решения своей проблемы, но не нашел, хотя бы намека, где искать.
      подскажите куда копать, проблема с отображением номера звонившего мне на АТС.
      прописано два номера один пусть 74953000001, второй 88001001001
      так вот при звонке на номер 8800, номер звонившего отображается как 9204404040
      при звонке на 7495, отображается 79204404040, 7 перед номером.
      но если позвонить на 7495 из-за заграницы, пусть будет Польша или Казахстан, то номер будет без 7 впереди, то есть 9204404040. и привяжет звонок к 8800.
      номера арендованы у двух разных провайдеров.
      Это особенность самого астериска или нужно где то искать в консоле, в ГУИ все пересмотрел, не нашел.

      • По умолчанию Астериск ничего не обрезает и не добавляет к номерам, если вы сами специально это не настроите. Я подозреваю, что разный формат отображения номера звонящего это особенности провайдеров. Напишите в тех. поддержку об этом и точно узнаете. Возможно они смогут под вас подправить это, если вам это критично. Если они ничего не сделают, то это можно исправить и на самом Астериск, но нужно немного разбираться в нём.

  15. Николай

    Добрый день.
    Подскажите пожалуйста, выявилась одна любопытная проблема. При звонке от нас на внешний городской номер, когда трубку поднимает один человек, а потом хочет меня перевести на другого, то меня выкидывает в моё голосовое меню. Именно в моё, на мой астериск. Не подскажите куда копать?

    • Чего-то в диалплане напутали явно. Так трудно сказать, в чём проблема. Можно включить debug лог и посмотреть, что там в момент перенаправления в ivr. Должны быть какие-то записи по теме.

  16. Здраствуйте Zerox можете подсказать у меня установлено астериск мод изабел у меня на данном моменте работает 4 сип транка с одного оператора но еще дополнительно хочу купить из другого провайдера 4 номера но как с исходяшем звонком быт ? Я данный момент исползую перхикс для каждого номера если в астериск такой функции при каждом исходном вызове астериск помещал номера для исходящего звонка ? Например 1 оператор 100 звонит на номеру +5985611641 и 2 оператор в тот же момент звонит с 200 на +55998514231 но при это 1ый оператор выходить из +592000000 а 2ой оператор выходить из +592001111

  17. Аноним

    подскажите, что за ошибка, при записи в базу данных, и соответственно дата и время не записываются, показывает нули
    WARNING[9317]: cdr_adaptive_odbc.c:731 odbc_log: Column type 9 (field 'asterisk:cdr:calldate') is unsupported at this time.

    • Хм, это на какой версии Asterisk? Я недавно по статье настраивал Aterisk 18, всё гладко прошло. Такой ошибки не получал.

    • Владимир

      Добрый день! Вы решили проблему? Сейчас столкнулся с такойже проблемой. Пытаюсь гуглить, пока ничего вразумительного не нашел. Дайте пожалуйста ответ в случае если найдете решение или хотябы путь в сторону решения) Спасибо)

      • Аноним

        /etc/asterisk/cdr_odbc.conf

        [asterisk]
        enabled => yes
        dsn => asterisk-connector
        username => asteriskcdr
        password => b!2^qWq12Z
        pre-connect => yes

        /etc/asterisk/res_odbc.conf

        [asterisk]
        enabled => yes
        dsn => asterisk-connector
        username => asteriskcdr
        password => b!2^qWq12Z
        pooling => no
        limit => 99999
        pre-connect => yes

        /etc/asterisk/cdr_mysql.conf:

        ​[global]
        hostname=localhost;    - ip адрес где располагается сервер MySQL
        dbname=asteriskcdrdb;  – название базы данных где будут храниться cdr
        table=cdr;             - название таблицы
        password=b!2^qWq12Z;   - пароль для пользователя asteriskuser
        user=asteriskcdr;      - имя пользователя для базы данных
        port=3306
        sock=/var/run/mysqld/mysqld.sock
        ;timezone=UTC ; Previously called usegmtime

        с такими настройками удалось запустить, /etc/asterisk/cdr_adaptive_odbc.conf дефолтный

  18. Не проигрывает ivr. Я уже весь гугл перерыл, ничего не могу найти.
    Executing [s@ivr-main:2] BackGround("SIP/rtk-00000005", "/etc/asterisk/ivr/music") in new stack
    [Mar 1 13:39:52] WARNING[6176][C-00000004]: file.c:804 ast_openstream_full: File /etc/asterisk/ivr/music does not exist in any format
    [Mar 1 13:39:52] WARNING[6176][C-00000004]: file.c:1277 ast_streamfile: Unable to open /etc/asterisk/ivr/music (format (alaw)): No such file or directory
    [Mar 1 13:39:52] WARNING[6176][C-00000004]: pbx_builtins.c:1239 pbx_builtin_background: ast_streamfile failed on SIP/rtk-00000005 for /etc/asterisk/ivr/music

    Как-будто ругается на формат, но и на любой другой звук в папке /var/lib/asterisk/sound/{en,ru} он выдаёт такую же ошибку.

  19. Доброго времени суток. Для Debian 11 есть такие статьи ? или можно истользовать Вашу для Debian 10 и там все идентично ?

    • Есть некоторые отличия. Я недавно настраивал на Debian 11, пришлось повозиться только с настройкой odbc для хранения статистики в mysql. А так всё остальное в статье актуально и для 18-й версии Asterisk + Debian 11.

    • Richard Faraday

      Я не советую использовать для Астериска Debian дистрибутывы, я сталкивался уже, были проблемы с отсутствием дополнительных модулей, особенно при использовании freePBX. Чем больше примочек добавляешь, тем больше проблем и костылей. Centos лучше всего подходит...

      • С базовым Asterisk никаких проблем в Debian нет. Вы советуете Centos Stream? Обычной Centos больше нет.

        • Richard Faraday

          Ну да. Я в принципе разворачивал базовый Астериск на Дебиан, соглашусь в вами, вполне всё отлично. Но когда ставил вручную freePBX вдруг бросил, потому что всё требовало RHEL, и я просто скачал freePBX Distro и это видимо было правильно. Подкорректирую свой коммент - для базового Астериска Дебиан норм.

          • Всё правильно. FreePBX создан на базе Centos, поэтому именно там он и работает без проблем. Вручную ставить его нет большого смысла, тем более на Debian. Надо действительно брать готовый FreePBX Distro и разворачивать из него.

  20. Алексей

    Продолжаем разбираться

    Создаем директорию для записи разговор и назначаем ей права.

    # mkdir /mnt/calls
    # chown -R asterisk. /mnt/calls

    что за пользователь "asterisk."?
    не понятно откуда он взялся...

  21. Алексей

    Статья крутая! Работа проделана большая. Большое спасибо!
    Но к сожалению много "белых" пятен и частично информация устарела.
    Особенно "запнулся" на моменте настройке сервера apache+php - проблема в том что следуя инструкции не запускается php
    Далее настройка cdr так же не без танцев с бубном.

  22. Интересно, кто-нибудь пытался установить и настроить данный сервер на CentOS Stream?
    Мой CentOS 8 после 1.01.22 перестал иметь доступ к репозитариям, dnf или yum update пустота...

  23. Здравствуйте.
    asterisk сбрасывает входящий вызов после 30 секунд
    как решить проблему?
    Спасибо!!!

  24. Здравствуйте Zerox! Спасибо за подробное руководство. Единственный вопрос, по голосовой почте. Как сделать так, чтобы по почте ничего не отправлять (нет желания настраивать сервер пересылки). Т.е запись разговора хранились только в Asterisk, без отправки куда-либо. Заранее спасибо, уважением= Олег-

  25. Виктор

    Спасибо за статьи, это наверное самые подробные и полные описания установок и настроек, что мне попались.
    По крайней мере установить, настроить CentOS и Asterisk получилось не обращаясь к другим ресурсам.
    Только с Asterisk не совсем сладил :) , уперся вот в какой момент.
    После установки и первичной настройки Астериска.
    Установил софтфон скачанный по Вашей ссылке и установил на iPhone - SessionTalk SIP Softphone.
    Соединение с Астериском есть
    Name/username Host Dyn Forcerport Comedia ACL Port Status Description
    100/100 192.168.41.240 D No No 53380 OK (124 ms)
    101 (Unspecified) D No No 0 UNKNOWN
    111/111 192.168.41.209 D No No 34872 OK (49 ms)
    при наборе с софтфона звонок на iPhone проходит, но при ответе на телефоне соединения не происходит.
    при обратном звонке телефон-софтфон соединение происходит, но речи по ним - нет, то есть алокаешь что в микрофон компьютера, что в смартфон , этого алло не слышно.
    и в терминале такие сообщения
    [Nov 30 16:56:47] NOTICE[1298]: chan_sip.c:25001 handle_response_peerpoke: Peer '111' is now Reachable. (48ms / 2000ms)
    [Nov 30 18:00:11] NOTICE[1298]: chan_sip.c:30537 sip_poke_noanswer: Peer '111' is now UNREACHABLE! Last qualify: 371

    Подскажите куда рыть?

    • Обычно, когда кого-то не слышно, это сетевые проблемы, особенно если asterisk за nat. Для голоса открывается отдельное соединение и возможно оно по какой-то причине не работает. А из лога видно, что пир сначала подключился, потом отключился.

  26. Александр

    Доброго дня
    при переходе с sip на pjsip, при звонке на старую (неизвестную) модель телефона (всё что про него известно - это "АБВ-телефон") вылетает ошибка, при следующих звонках на него идет только звонок

    [Oct 26 14:28:40] ERROR[45805]: pjproject: : sip_transport.c Error processing 361 bytes packet from UDP 192.168.2.16:5060 : PJSIP syntax error exception when parsing 'Event' header on line 7 col 11:
    SIP/2.0 487 Request Terminated
    Via: SIP/2.0/UDP 192.168.3.150:5060;rport;branch=z9hG4bKPj426c6d50-b90a-48ff-846e-690acaef151e
    From: 1001 ;tag=0754a29f-4d3e-4b31-8766-e45a641a3fda
    To: ;tag=323742653
    Call-ID: 97d3c60d-cc4b-41e8-9886-5bcb0650d9de
    CSeq: 20476 INVITE
    Event: Mic=0,Speaker=0
    Content-Length: 0

  27. Александр

    Возник вопрос по Asterisk CDR Viewer Mod: как правильно сделать запись в файле подсчёта расхода денежных средств (my_callrates.csv) по такому ТП: Столицы, первые 100 минут бесплатно, потом 1.98 руб с посекундной тарификацией? Пробовал написать так: 7495,0.00,Столицы,6000s+s,1.98
    Ну или так: 7495,0.00,Столицы,100m+s,1.98
    Не работает! Считает деньги (расход) сразу с первой секунды. В чём ошибка?, как написать правильно?

  28. Алексей

    Думаю в будущем были бы полезны статьи с описанием перехода на pjsip и апгрейда астериска на 17/18/19

  29. Алексей

    Владимир, огромное спасибо за статью. Очень помогла, с ее помощью запустил полноценную телефонию.
    Спасибо и удачи!

  30. У меня не появляются записи звонков в папке /mnt/calls

  31. Добрый день!
    Пробовали установку на rocky linux?

  32. Кирилл

    Подскажите, пожалуйста, как в веб-морде Asterisk CDR Viewer Mod v2.6.4, корректно отображался пункт "Кто звонил"
    Т.к. сейчас там всегда отображается только мой собственный номер, и на какой номер он звонил, а не реальный номер звонящего

  33. Кирилл

    Статья по-прежнему улет!
    Но есть небольшой у меня затык и непонятки.
    Как правильно в блок ниже натыкать запись звонков строчкой
    exten => t,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))

    Сам блок:

    [ivr-main]
    exten => s,1,Answer()
    exten => s,2,Background(/etc/asterisk/ownsounds/hello)
    exten => s,3,WaitExten(15)
    exten => 1,1,Goto(priem,s,1)
    exten => 2,1,Dial(SIP/219)
    exten => 3,1,Dial(SIP/224)
    exten => 4,1,Dial(SIP/216)
    exten => 0,1,Queue(reception,t)
    exten => _XXX,1,Dial(SIP/${EXTEN})
    exten => _XXX,2,Playback(privacy-incorrect)
    exten => _XXX,3,Goto(ivr-main,s,1)
    exten => t,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
    exten => t,n,Queue(reception,t)

    • Кирилл

      Когда отправил, вариант натыкивания пришел в голову такой:

      exten => s,1,Answer()
      exten => s,2,Background(/etc/asterisk/ownsounds/hello)
      exten => s,3,WaitExten(15)
      exten => 1,1,Goto(priem,s,1)
      exten => 2,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
      exten => 2,2,Dial(SIP/219)
      exten => 3,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
      exten => 3,2,Dial(SIP/224)
      exten => 4,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
      exten => 4,2,Dial(SIP/216)
      exten => 0,1,Queue(reception,t)
      exten => _XXX,1,Dial(SIP/${EXTEN})
      exten => _XXX,2,Playback(privacy-incorrect)
      exten => _XXX,3,Goto(ivr-main,s,1)
      exten => t,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
      exten => t,n,Queue(reception,t)

      Есть ли у него минусы?

  34. Здравствуйте, интересует вопрос - можно ли настроить Voicemail для отправки с разной темой письма и тела?
    Задача вообще такова: сотрудник звонит в службу поддержки, оставляя голос.сообщение -- голосовое сообщение пересылается на почту -- обработчик в Jira из письма создает задачу в проекте.

    Делали с помощью модуля RecordEmail (в нем можно и тему и тело указать для разных типов задач) - все хорошо создается, но вложение НЕ прикрепляется, с помощью модуля VoiceMail - тоже задача создается и вложение прикрепляется! Что смогли выяснить - отличие писем в "" - если глянуть оригинал письма от VoiceMail - то имя файла заключено в "", а при RecordEmail (хоть " и прописаны в модуле) - в оригинале письма отсутствуют. То ли команда System (exten => submodule,n,System(echo "Content-Disposition: attachment\; filename=\"recording-6689bb50ebba833b431922090425679c.wav\"" >> /tmp/email-${UNIQUEID})) не так обрабатывает, то ли ...

    Буду благодарен за любую помощь!
    Заранее спасибо!

  35. Здравствуйте! Спасибо вам за вашу статью!!!
    После этого этапа пытаюсь записать приветствие с 3схphone6, например с номера 355, после происходит 5 сек и он сбрасывается, в чём может быть проблема?
    лог: "," "100", "355", "call-out", "Number 100" "", "SIP/100-0000006", "Hangup", "","2021-05-29 05:05:52", "2021-05-29 05:05:29 05:05:58",5,3, "ANSWERED","DOCUMENTATION","1622264752.10",""

    • С консоли , пишет, что нет такой директории с консоли при вызове на номер 355
      > 0x7f5c200352d0 -- Strict RTP learning after remote address set to: 192.168.56.1:40024 -- Executing [355@call-out:1] NoOp("SIP/100-00000006", "") in new stack
      -- Executing [355@call-out:2] Wait("SIP/100-00000006", "2") in new stack
      -- Executing [355@call-out:3] Playback("SIP/100-00000006", "beep") in new stack
      > 0x7f5c200352d0 -- Strict RTP switching to RTP target address 192.168.56.1:40024 as source
      -- Playing 'beep.alaw' (language 'ru')
      -- Executing [355@call-out:4] Record("SIP/100-00000006", "/tmp/musicEXTEN:2:wav") in new stack
      -- Playing 'beep.alaw' (language 'ru')
      [May 29 22:23:09] WARNING[1651][C-00000004]: file.c:1504 ast_writefile: No such format '2:wav'[May 29 22:23:09] WARNING[1651][C-00000004]: app_record.c:396 record_exec: Could not create file /tmp/musicEXTEN
      -- Executing [355@call-out:5] Wait("SIP/100-00000006", "1") in new stack
      -- Executing [355@call-out:6] Playback("SIP/100-00000006", "/tmp/musicEXTEN:2") in new stack
      [May 29 22:23:10] WARNING[1651][C-00000004]: file.c:789 ast_openstream_full: File /tmp/musicEXTEN:2 does not exist in any format[May 29 22:23:10] WARNING[1651][C-00000004]: file.c:1262 ast_streamfile: Unable to open /tmp/musicEXTEN:2 (format (alaw)): No such file or directory
      [May 29 22:23:10] WARNING[1651][C-00000004]: app_playback.c:497 playback_exec: Playback failed on SIP/100-00000006 for /tmp/musicEXTEN:2
      -- Executing [355@call-out:7] Wait("SIP/100-00000006", "2") in new stack
      > 0x7f5c200352d0 -- Strict RTP learning complete - Locking on source address 192.168.56.1:40024
      -- Executing [355@call-out:8] Hangup("SIP/100-00000006", "") in new stack
      == Spawn extension (call-out, 355, 8) exited non-zero on 'SIP/100-00000006'
      pc-call*CLI>

      • Вы явно в конфиге что-то напутали. У вас создается файл с таким именем - /tmp/musicEXTEN:2. Где-то какой-то символ потеряли и у вас EXTEN не переводится в реальный номер.

  36. Настроил запись и статистику звонков, но появилась проблема, собеседники перестали слышать друг друга. Если прослушать запись звонка, то слышно как они "алекают" друг другу. Диалплан был самый простой, звонки внутри сети, исх. звонок на внешний номер, до добавления макроса на запись звонилось на ура.

    • Вообще странно. Запись звонков обычно никак не влияет на сами звонки, а идет параллельно, как организационно в диалплане, так и технически. Ни разу не сталкивался с проблемой связи при записи.

      • Аноним

        По идее, если в записи звонка слышно голоса, то он нормально проходит. Есть сомнения в софтовой звонилке 3CX. Завтра попробую телефон украсть у кого-нибудь.

        • Виновата оказалась софтовая звонилка, после ее удаления и выковыривания остатков из реестра все заработало.
          И еще, чтобы удалить из CDR Viewer ненужные записи их нужно удалить из VariaDB?

  37. Кирилл

    Большое спасибо за статью, очень хорошая. Подскажите, пожалуйста, столкнулся с следующим затыком и гуглежка по другим сайтам не помогла.

    Подключал транк без регистрации
    [2000000]
    type=friend
    host=10.16.150.20
    registersip=no
    trunkname=2000000
    fromuser=8122000000
    callerid=812000000
    callbackextension=2000000
    disallow=all
    allow=alaw
    contex=call-in
    insecure=invite
    relaxdtmf=yes
    dtmfmode=RFC2833 ; без relaxdtmf не помогает
    canreinvite=no
    port=5060

    Прописал extentions.conf
    [general]
    static=yes
    writeprotect=no
    [globals]
    [default]

    ;Вешаем трубку
    [handup-sip]
    exten => _X!,1,HangUp()

    ;Исходящие звонки
    [call-out]
    ;Звонок на внутренний номер
    exten => _XXX,1,Dial(SIP/${EXTEN})
    ;Звонок на внешний номер
    exten => _XXX.,1,Dial(SIP/${EXTEN}@2000000)

    include => handup-sip

    ;Входящие звонки
    [call-in]
    exten => 2000000,1,Dial(SIP/100)

    Наружу звонки идут, при попытке набрать номер, получаю ошибку на астере:
    [May 6 23:29:16] NOTICE[1902][C-00000023]: chan_sip.c:26793 handle_request_invite: Call from '2000000' (10.16.150.20:5060) to extension '2000000' rejected because extension not found in context 'default'.

    Не очень понимаю, как он ее не находит, ведь мы его прописывали нижней строчкой. Подскажите. на что он может ругатся?

    • Кирилл

      АААА, опечатка в слове context... на contex.....
      Вот пример, почему надо отдыхать, спасибо, Зерокс)

  38. Алексей

    Добрый день! Подскажите пожалуйста, после ввода команды "sip show users" выдает "No such command 'sip show users' " В чем может быть проблема

  39. Доброго времени суток! Вот пытаюсь разобраться в написанном поподробнее и возник вопрос:

    callbackextension - я так понимаю, что эта настройка в sip.conf говорит о том, что данный peer может совершать исходящие звонки?

    Поискал в сети описание данной настройки и конкретного ответа - прав я или нет, так и не нашел.
    Зарание прошу прощения, если вопрос глупый.

    • Александр

      Здравствуйте! Можно пример как сделать исходящий звонок с любого свободного транка если их 4 и больше?

      • Перечислите их по очереди в рамках одного контекста и маски. Он и так их будет перебирать по очереди, если с первого звонок не получится.

    • Нет, callbackextension с входящими звонками не связан. За это отвечает настройка dialplan и context, в который помещен peer.

  40. В общем у меня активных коннекторов показывает 0 из 1. Делал всё по статье...

  41. А почему коннектор MySQL, когда у нас ставится MariaDB...?!?

    • Друг как я тебя понимаю мы просто купаемся в этом океане обсурда и ничего поделать не можем !!!
      мария это тоже sql

      • Это не просто sql. Так то postgresql тоже sql. MariaDB форк Mysql с полной обратной совместимостью. Как и другой известный форк - percona.

  42. Подскажите а как обработать события после dial когда кто-то из сторон положил трубку, нужно отправить curl в софт, но все команды после соединения в диал не обрабатываются, только в случаи не удачи соединится?

    • Разобрался как обработать поднял трубку вызываемый опция U(), отклонил вызов вызываемый опция g, но не могу обработать сброс вызова звонящим может кто подскажет. Знаю про exten => h , но не совсем подходит может есть другой способ? не разобрался еще с опцией F() не пойму как работает

  43. Дмитрий

    Добрый день.
    Такая же ошибка, как и одного из комментаторов и никак дальше не продвинуться
    [Mar 26 16:31:34] NOTICE[3024][C-00000005]: chan_sip.c:26805 handle_request_invite: Call from '101' (192.168.0.130:62506) to extension '100' rejected because extension not found in context 'call-out'.

    Проверил и extensions.conf и sip.conf - все как в статье
    Перезапускал сервис.
    Все безрезультатно. Клиенты подключаются, в системе видятся, но позвонить друг другу не могут.
    Что еще можно проверить?

    • В тексте ошибки точно указано, в чем проблема. Кроме как внимательно проверять конфиг, не знаю, что посоветовать. Обычно это все же ошибки в конфигурации. Я сам бывало так же ошибался и получал эту ошибку.

    • Дмитрий

      Все перепроверил, все конфиги.
      Не работает. Та же ошибка.
      Софтофоны конектятся:

      Asterisk*CLI> sip show peers
      Name/username             Host                                    Dyn Forcerport Comedia    ACL Port     Status      Description
      100/100                   192.168.1.121                            D  No         No             51387    OK (104 ms)
      101/101                   192.168.0.130                            D  No         No             58926    OK (110 ms)

      Сократил оба конфига до минимума:
      sip.conf:

      [100]
      type=friend
      regexten=100
      secret=123
      context=outcalling
      host=dynamic
      callerid="100"
      disallow=all
      allow=alaw
      language=ru
      callgroup=1
      pickupgroup=1
      qualify=yes
      canreinvite=yes
      call-limit=4
      nat=no
      
      [101]
      type=friend
      regexten=101
      secret=123
      context=outcalling
      host=dynamic
      callerid="101"
      disallow=all
      allow=alaw
      language=ru
      callgroup=1
      pickupgroup=1
      qualify=yes
      canreinvite=yes
      call-limit=4
      nat=no

      extentions.conf:

      [outcalling]
      exten => _XXX,1,Dial(SIP/${EXTEN},,m)

      Проще уже некуда,
      и все равно ошибки при попытке звонка в обе стороны:

      [Mar 30 12:07:59] NOTICE[1224][C-00000009]: chan_sip.c:26805 handle_request_invite: Call from '101' (192.168.0.130:58926) to extension '100' rejected because extension not found in context 'outcalling'.
      [Mar 30 12:08:14] NOTICE[1224][C-0000000a]: chan_sip.c:26805 handle_request_invite: Call from '100' (192.168.1.121:51387) to extension '101' rejected because extension not found in context 'outcalling'.

      Asterisk 16.16.2, CentOS Linux release 8.3.2011

      • Странная история. Попробуйте на всякий случай название контекста outcalling везде написать с клавиатуры. Возможно при копировании какие-то проблемы возникает. Сталкивался с таким.

        Далее попробуйте в контексте явно прописать номера, без масок:
        exten => 100,1,Dial(SIP/100)
        exten => 101,1,Dial(SIP/101)

        Возможно где-то что-то еще меняли в конфигах и удалили что-то нужное. Я ни разу не сталкивался с описываемой проблемой.

        • Дмитрий

          Добрый день.
          Спасибо, что уделили мне столько времени.
          Это я болван!!! Создал файл с неправильным именем "extentions.conf".
          Исправил, перезапустил - все работает.
          Ошибку нашел, когда начал проверять права на файлы.
          Два дня бился, даже разные клиенты X-Lite пробовал - оказалось все просто...
          Еще раз спасибо!!!

      • И еще dialplan show покажите, когда все сделаете.

  44. Дмитрий

    Я только начинаю разбираться в командах Linux и перепроверяю все, что написано в статье.
    Такой вопрос. В команде chown вы намеренно поставили точку между пользователем и группой?
    # chown -R asterisk.asterisk /etc/asterisk /var/{lib,log,spool}/asterisk /usr/lib64/asterisk
    В синтаксисе команды они должны разделяться двоиточием.
    Как-то так
    # chown -R asterisk:asterisk /etc/asterisk /var/{lib,log,spool}/asterisk /usr/lib64/asterisk
    Я ввел именно свой вариант. Ошибок не было.
    Спасибо.

    • Насколько я понимаю, разницы нет. Я обычно использую либо двоеточие asterisk:asterisk, либо для краткости точку - asterisk. Это то же самое, что предыдущая запись. Подходит, когда имя пользователя и группы совпадают. Не нужно писать группу.

  45. Дмитрий

    Добрый день.
    На CentOS 8 команда
    # dnf config-manager --set-enabled PowerTools
    Выдала ошибку
    Error: No matching repo to modify: PowerTools.
    Решение оказалось - убрать заглавные буквы. Правильное написание команды:
    # dnf config-manager --set-enabled powertools

    • Все верно. Это недавно изменилось, не понятно только, зачем. Мне и в других статьях на это указали.

  46. Алексей

    Простите!
    Придерусь с первых строк. Номера от 100 до 130 это 31 сотрудник.
    Ничего страшного конечно нет. Но глаз "режет" )
    А в целом статья на пятерочку!

  47. Дмитрий

    Владимир, а не могли бы Вы дополнить статью разделом по настройке с использованием PJSIP?

  48. Александр

    Здравствуйте.

    1. Входящий звонок приходит на один внутренний номер.
    2. Входящий звонок приходит на пару внутренних номеров
    (queues.conf :

    [secretary]
    strategy = ringall / randov
    member => SIP/100
    member => SIP/130)

    Если абонент не взял трубку в течении пары секунд/гудков - переадресовать входящий на сотовый.
    Подскажите пожалуйста реализацию данных схемы.

    • Первый случай простой. Делается примерно так:
      exten => 150,1,Dial(SIP/${EXTEN},2,Tt)
      exten => 150,n,Dial(SIP/89151234567@397945)

      Второй сходу не скажу, давно не настраивал подобное, надо думать и тестировать.

  49. Добрый подскажите подключаю yeastar tg как VoIP-канал как правильно прописать конфиги то все примеры под Freepbx а я не пойму куда прописывать входящею и исходящею маршрутизацию (Out/Incoming Route)

    • Voip шлюз yeastar подключается как обычный пир и дальше через него настраивается маршрутизация в dialplan. В чем конкретно проблема? Я настраивал yeastar, не было никаких проблем и нюансов.

  50. александр

    Здравствуйте! Как запретить межгород и звонки на мобильные для определенной группы

    • В формате комментария трудно ответить. Общий смысл такой. Формируете номера по группам, в одной те, кому можно звонить по межгороду, во второй те, кому нельзя. Разные группы привязываете к разным контекстам. В контексте, где разрешен межгород и мобильные, разрешаете все звонки по маске _X. А в группе, где не разрешены, делаете более узкие маски так, чтобы они не включали в себя номера на _810. и _89ХХ. То есть будет разрешено только _8495XXXXXXX и _8499XXXXXXX. Это городские московские номера. Они звонить смогут только по ним. Примерно так.

  51. александр

    asterisk при определении номера срезает первую цифру 8. Как сделать чтобы правильно работал определитель номера?

    • Не понял, что значит срезает? Он по умолчанию ничего не срезает, если это не настроить в диалплане. При каких звонках это происходит? Может провайдер так передает входящий номер?

      • Аноним

        номер приходит в виде 93700000 не хватает или +7 или 8

        • Так это ваш астериск восьмерку отрезает или от провайдера такой номер приходит? От этого зависит исправление. Просто добавить 8 к номеру не проблема. Нужно callerid поправить. Вот тут пример, как это делать - https://serveradmin.ru/vyivod-tranka-vmeste-s-nomerom-zvonyashhego/ Только там я название транка добавляю, а вам надо цифру 8 добавить. Хотя я не очень понимаю, зачем это делать. И так понятно, какой номер звонил.

          • Аноним

            добавил во входящие "exten => _XXXXXXXXXX,1,Set(CALLERID(number)=8${CALLERID(number)}) exten => _XXXXXXXXXX,n,goto(ext-did,${EXTEN},1)". А нужно это чтобы из не принятых набрать абоненту который звонил

  52. Евгений

    Здравствуйте. А что за ошибка после запуска asterisk.service: Can't open PID file /var/run/asterisk/asterisk.pid (yet?) after start: No such file or directory

    Она тоже у вас есть на скрине.

    • Да это не ошибка. Если я правильно понимаю смысл, то при запуске идет проверка наличия pid файла. Его там нет, так как он появляется после запуска службы asterisk. Зачем проверять его наличие при запуске и выводить предупреждение, не очень понятно. Возможно так реализована проверка активности службы. Но в такой ситуации, по идее, никакое предупреждение в логе не должно быть.

  53. DenisNIkolaich

    Доброго времени суток уважаемый Zerox! Прежде всего хочу выразить огромную благодарность за Ваш труд, так как с Asterisk имею дело первый раз, а Ваша статья очень помогает разобраться. Но есть вопрос, не могли бы Вы подсказать, как переадресовывать вызов на голосовую почту, если выключены телефоны секретарей, которые находятся в queue? Или же если это не возможно, то подскажите пожалуйста по этому ("Обращаю ваше внимание, что в контексте голосового меню я не сделал обработку статусов состояния телефона секретаря, хотя это может быть нужно, если у вас будет один секретарь принимать звонки."), желательно пример))) Заранее премного благодарен.

    • По таким нюансам уже не подскажу. Давно не погружался в voip тему. Подзабыл многое.

  54. Сергей

    Доброго времени суток! Наверное начну с того, что данная инструкция одна из лучших среди тех, которые я смотрел и изучал.

    С Linux я знаком мало, как-то не было нужды изучать, но тут обстоятельства так сложились, что я стал изучать Linux из-за необходимости поднять сервер Asterisk'a. Все шло по инструкции до момента сборки Asterisk'a, а именно возникла трудность с Jannson:

    checking for JANSSON... no
    checking for json_sprintf in -ljansson... no
    configure: *** Asterisk requires libjansson >= 2.11 and no system copy was found.
    configure: *** Please install the 'libjansson' development package or
    configure: *** use './configure --with-jansson-bundled'

    Покопавшись в сети я так и не нашел ответа как обновить Jannson до версии 2.11. Я подозреваю, что Jannson 2.11 необходим из-за того, что я взял Asterisk 18, а не как указано 16. Сервер CentOS 7.
    Может быть вы подскажете как мне все таки обновить или установить Jannson 2.11? Заранее благодарен за ответ и весьма подробную, понятную инструкцию.

    • Я бегло погуглил и не нашел простого решения. Готового пакета с Jannson 2.11 для Centos 7, как я понял, не существует. Надо либо от других версий пробовать rpm пакеты ставить, но могут быть проблемы с зависимостями. Либо собирать самому из исходников, но тоже не факт, что получится. С учетом того, что в линуксе вы новичок, я бы вам не советовал тратить на это время. Это может оказаться непосильной задачей.

      Советую остановиться пока на 16-й версии и сделать все по моей статье. У этой версии поддержка еще 3 года будет. Вам хватит, чтобы освоиться и войти в тему. Потом без проблем перенесете все на 18-ю или какую-то другую версию. Там еще и на pjsip переходить надо будет. Так что переезда не избежать. А моя статья все равно использует старый sip, так что 16-я версия тут лучше всего смотрится.

      • Сергей

        Ну я пробовал собрать из исходников Jannson 2.11 и 2.13.1 - в системе остается Jannson 2.10, смотрел через № rpm -qa. Я так понимаю, что на CentOS 7 они просто не встают. Хотя я может и ошибаюсь. Большое спасибо за ответ, пойду щупать Asterisk 16. ;)

      • Сергей

        Уважаемый Zerox, вот тут, как говориться "Либо я дурак, либо лыжи не едут..." Дело в том, что при попытке установить Asterisk 16.15.0 на моменте сборки Asteriska вылазит та же самая чертовщина с Jannson и вот тут я совсем запутался... У вас есть какие-то мысли по таком№у рзавитию событий? Ну как у более опытного пользователя.

        • Не зная всех подробностей, не могу что-то сказать конкретное. Когда последний раз проверял статью, все работало. Попробуйте все начать с нуля на чистом сервере.

  55. Виталий

    Все конечно хорошо и красиво вот только pjsip тут установлен а настройка проходит через sip.conf. Как понимать сие чудо?

  56. Здравствуйте, я в линухах поный ноль , но очень хочется самому ручками все настроить
    подскажите пожалуйста, в чем может быть проблема, все сделал по вашей инструкции до момента усановки Asterisk-CDR-Viewer-Mod все получалось.
    Тут же проблема в том, что если все делать точно по инструкции , то после настройки, при попытке перехода по http://ваш ip/cdr/.

    браузер ругается

    Not Found
    The requested URL /cdr/ was not found on this server.

    если смотреть по аналогии настройку z.serveradmin.ru ( ваша статья по установке апача и php), то в директорию /etc/httpd/conf.d/ кладется файл конфигурации z.serveradmin.ru.conf
    и апач понимает, где живет z.serveradmin.ru и что с ним надо делать.

    В случае же с установкой Asterisk-CDR-Viewer-Mod
    по инструкции никаких файлов в /etc/httpd/conf.d/ класть не надо
    Но оно не работает в таком случае, либо же настройки лежат где то в другом месте, если да , то где ?

    В общем подскажите куда копать

    • В данном случае в статье подразумевается, что используется дефолтная настройка web сервера, который доступен по ip адресу и отдает исходные файлы из директории /var/www/html/, тогда в случае создания там папки cdr, можно обращаться к ней напрямую через http://ваш ip/cdr/.

      Если вы все делали по статье, то по идее, у вас все должно получиться. Убедитесь, что исходники панели реально лежат в /var/www/html/cdr, а директория /var/www/html/ это корень веб сервера.

      Это азы настройки веб сервера, мне трудно пояснить подробнее. Никакие файлы z.serveradmin.ru.conf вам не нужны и не могут быть примером, так как там речь идет о виртуальных серверах, а тут все это не используется.

      • Да, исходники точно лежат по адресу /var/www/html/cdr
        А еще, у меня по адресу "мойIP" открывается не дефолтная страница , а страница виртуального хоста PhpMyAdmin, который я настроил опять же для asteriska и живет он в директории web/sites/pma.aster.ru/

        в папке /etc/httpd/conf.d соответственно лежит конфиг pma.aster.ru.conf
        больше никаких хостов нет

        Что мне нужно настроить, чтоб он увидел панель ?

      • В итоге создал файл конфигурации в папке /etc/httpd/conf.d следующего содержания
        Alias /cdr/ "/var/www/html/cdr/"

        #
        # AuthName "Asterisk-CDR-Stat"
        # AuthType Basic
        # AuthUserFile /var/www/asterisk-cdr-viewer/.htpasswd
        # AuthGroupFile /dev/null
        # require valid-user
        #

        - заработало
        авторизацию правда не настраивал еще, но уже радует))

  57. Спасибо за статью, по данному описанию собрал рабочую сеть внутри сети.
    Но дело дошло до zadrama и пошли тормоза.
    Выходит ошибка: WARNING[1542]: chan_sip.c:16217 transmit_register: Probably a DNS error for registration to 843987@sip.zadarma.com, trying REGISTER again (after 20 seconds)
    Сделал telnet, проверил открыт у меня порт или нет, порт открыть. попытался ввести
    sip.zadarma.com ввиде IP адреса, тоже не выходит.
    nc -vnzu 185.45.152.174 5060 все работает, но эта ошибка не уходит.

    Связался с техподдержкой, там меня попросили сменить внешний порт на TCP 5065.....
    Тут пошли еще больше проблемы....где его сменить....меняю в sip.conf но он не меняется...
    sip show peers показывает что используется 5060 порт.

    Как решить эту проблему?

    • Провайдер не может блокировать sip трафик? Я много раз с подобным сталкивался.

      • а это каким образом проверить можно?

      • Дело в том что порт открыт, я проверял.

        Неужели они трафик режут?

        • Да, могут мешать именно нормальному хождению трафика. Порт при этом будет открыт. Я с таким сталкивался, приходилось по vpn подключаться sip телефонию. Провайдер просто продавал сам услуги voip, поэтому другим не давал пользоваться чем-то со стороны. Проверить легко - попробуйте подключиться к какому-то другому voip провайдеру. Например, через софтовый клиент на своем компьютере.

  58. Спасибо за статью - реально помогла решить проблему: сервер телефонии - за NAT (сеть офиса) на входе - программный шлюз, телефон в другой локальной сети (офис2) - , тоже за NAT (шлюз на pfsense)! Между сетями поднят OPENVPN - клиенты друг друга видят, все прекрасно. Внешний офис не единственный (уже был ранее настроен доступ из туннеля "офис3 - офис1", но.. В механизм не сработал... Телефон на сервере регистрируется, SIP (5060) проходит из одной локальной сети в другую через канал замечательно, а RTP от сервера идет напрямую через туннель в офис2, а обратно - сигнал хоть тресни отправляется на внешний адрес, указанный в настройках телефонии Х.Х.Х.Х Как итог: в офисе2 звук слышен, от сервера (офис1) приходит, а в офисе1 - в трубке полная тишина...
    И ведь было написано правило прероутинга... Все отличие, что вместо --dst X.X.X.X. стояло -i ensYY - WAN и порты прописаны все одним правилом как -m multiport --dport 5060,10000:20000 НЕ РАБОТАЛО! стоило переписать правила - голос пошел в обе стороны!

    • Круто, что это помогло. Я бы так сходу и не догадался поменять правила. Не очевидно, что ваше не будет работать.

      • nkudrich@gmail.com

        Вот и мне было не очевидно целых две недели))). До правила по SIP, TCPDUMP показывал прохождение пакетов чисто между локальными интерфейсами: офис2_lan:5060 - офис1_lan: 5060. Rtp было асинхронным. Теперь все идёт так: офис2_lan - офис1_wan. (5060, и rtp). И все работает.

  59. Здравствуйте! Изучаю по Вашей инструкции asterisk, за что огромное спасибо! У меня возник вопрос: я записываю(через Record()) сообщения, которое оставляет клиент (тот, кто позвонил нам) и хочу распознать через google cloud stt записанный файл формата wav, но столкнулся с проблемой плохого качества записи (8000 Hz, 1 channels, s16, 128 kb/s) и последующих проблем с распознаванием. Попытался записать в формате mp3, но астер мне сказал, что он умеет только "читать" mp3, но не записывать. Можно ли как то улучшить качество записываемого файла? Или записывать не через Record, а что-нибудь другое, которое записывает в лучшем качестве. Спасибо.

    • Я не решал никогда подобную задачу, поэтому не знаю, что посоветовать для гарантированного улучшения качества записи. Попробуйте записывать разговоры через MixMonitor, как я в статье это делаю. Но мне кажется, там то же самое будет. Качество разговора зависит не только от принимающей стороны, но и от передающей, а ею управлять не получится.

    • Да сейчас столо проще держать переговоры в текстовых файлах!
      Залейте на ютуб и проверьте там распознаваемость.

      кстате попробуйте реализовать отправку в телеграм аудио у кого получиться прокоментируйте пож-та!!!!

      ;exten => s,n,system(curl -X POST "https://api.telegram.org/bot0000000000:hkjhUIYIUHJK_hkjhUIYIUHJK_gCrOfBU/SendMessage" -d "chat_id=98789798&text=(С Номера: ${DIAL_ID}} дата: ${STRFTIME(${EPOCH},,%d.%m.%Y)} время)
      ;exten => s,n,system(curl -X POST "https://api.telegram.org/bot0000000000:hkjhUIYIUHJK_hkjhUIYIUHJK_gCrOfBU/SendAudio" -F "chat_id=98789798" -F "audio=@/home/record/${fname}" --insecure)

  60. Я не пойму, нужно или нет загружать в mysql /var/www/html/cdr/docs/mysql_cdr.sql?
    Я дошел до "В папке docs подробная инструкция по настройке. Все дальнейшие действия делаются в соответствии с ней." и не пойму, что делать дальше?
    Вроде по данной статье , мы создали таблицу cdr и колонки.

  61. Аноним

    Здравствуйте,
    При звонке с alcatel на asterisk (v16 + freepbx v15), на экране телефона alcatel отображается "SIP", а при поднятии трубку на asteriske, на телефоне alcatel отображется "вызываемый номер" и "SIP". Скажите пожалуйста, в чем может проблема.

    • Сам alcatel куда подключен? К этому же asterisk? Вообще, за информацию на дисплее аппаратов отвечает CALLERID. Надо копать в эту сторону.

      • Аноним

        Да, asterisk подключен к alcatel по sip транку

      • Zerox, здравствуйте,

        Спасибо большое за подсказку, нашли решение.

        Возник другой момент, при внутреннем звонке из астериска на alcatel, на аппарате алкателя звонок поступает на "isdn", вместо "внутренней линии". Нужно чтобы внутренние звонки поступали по внутренней линии. Скажите пожалуйста где в астериске можно настроить это? Есть ли какой-нибудь параметр в астериске, отвечающий за данный процесс?

  62. Василий

    Добрый день. Установил астериск 13 и при перезагрузке диалплана не вижу ошибок. всегда пишет pbx_config successfully loaded 33 contexts. Причем я намеренно сделал синтаксическую ошибку, чтобы увидеть в консоле как он про нее пишет. С астром 11 такого не было. Что нужно включить, чтобы он выводил в консоле ошибки в диалпланах?

  63. Здравствуйте.
    Вроде нашёл небольшой недочёт в инструкции.
    Нужно добавить каталог "run" в команду chown -R asterisk.asterisk /etc/asterisk /var/{lib,log,spool,run}/asterisk /usr/lib64/asterisk
    В 17ой версии Asterisk на CentOS8 после этого проблем нету, стартует без ошибок.
    Спасибо.

    • В инструкции всё хорошо, просто я не отключал SELinux.
      Для тех кому интересно как его настроить, ниже напишу команды.
      Не знаю на счёт "правильности", зато работает.
      semanage fcontext -a -t asterisk_var_run_t '/var/{lib,log,spool,run}/asterisk(/.*)?'
      restorecon -Rv '/var/{lib,log,spool,run}/asterisk'

      • При старте сервиса вот это сообщение "asterisk.service: Can't open PID file /var/run/asterisk/asterisk.pid (yet?) after start: No such file or directory" никуда не делось, просто asterisk работает и так.

  64. Здравствуйте Zerox.

    Наблюдаю "интересную" ситуацию с подменой статуса внутреннего номера после звонка. Не могу понять что не правильно.

    Как уже писала, по Вашей статье всё работает. На просторах нашла вкл/выкл безусловной переадресации с использованием актБД. Использовать по назначению не интересно. Интересно интегрировать в Ваш код таким образом, что бы отрабатывалась переадресация по определенным правилам, например если не снимают трубку. В остальных случаях вступают другие правила.

    После обработки этой строки:
    exten => _XXX,n,GotoIf($[${ISNULL(${REDIRECTNUM})}]?redirect)
    сигнал BUSY, NOANSWER меняется на CHANUNAVAIL. И как следствие, ситуационное ветвление не отрабатывается.
    Возможно и другие сигналы тоже меняются на CHANUNAVAIL, не проверяла.

    Подскажите пожалуйста что не правильно.
    Спасибо.

    Привожу код диалплана:

    [call-out]
    ; Установить с телефона переадресацию *21
    exten => *21,1,Playback(hello)
    same => n,Playback(vm-enter-num-to-call)
    same => n,Read(cfwd)
    same => n,Playback(beep)
    same => n,Set(DB(REDIRECT/${CALLERID(num)})=${cfwd})
    same => n,Set(DB(REDIRTIMER/TIMER)=5)
    same => n,Playback(you-entered)
    same => n,SayDigits(${DB(REDIRECT/${CALLERID(num))}})
    same => n,Playback(enabled)

    ; Отменить переадресацию с телефона *22
    exten => *22,1,Set(NOREDIRNUM=${DB_DELETE(REDIRECT/${CALLERID(num)})=${cfwd}})
    ;exten => *22,1,Set(NOREDIRNUM=${DB_DELETE(REDIRECT/${CALLERID(num)})})
    same => n,Playback(disabled)

    ;Звонок на внутренний номер
    exten => _XXX,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
    exten => _XXX,n,Dial(SIP/${EXTEN},5,m,Tt)
    exten => _XXX,n,Set(dstNUM=${EXTEN})
    exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status)}" = ""]?num-not-exist,1)
    exten => _XXX,n,GotoIf($["${SIPPEER(${EXTEN},status):0:2}" = "UN"]?num-not-connected,1)
    exten => _XXX,n,ChanIsAvail(SIP/${EXTEN},s)
    exten => _XXX,n,NoOp(=========== ChanIsAvail STATUS: ${AVAILSTATUS} ===========)
    ; Если установлена переадресация *21
    exten => _XXX,n,Set(REDIRECTNUM=${DB(REDIRECT/${EXTEN})})
    exten => _XXX,n,GotoIf($[${ISNULL(${REDIRECTNUM})}]?redirect)
    exten => _XXX,n(redirect),Dial(SIP/12345678/${REDIRECTNUM})
    ;end
    exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 2]?num-BUSY,1)
    exten => _XXX,n,GoToIf($[${AVAILSTATUS} = 3]?num-BUSY,1)
    exten => _XXX,n,Goto(num-${DIALSTATUS},1)

    ; Номер не существует
    exten => num-not-exist,1,Playback(vm-dialout) ;пожалуйста подождите происходит соединение
    exten => num-not-exist,n,Wait(1)
    exten => num-not-exist,n,Queue(secretary,t)
    exten => num-not-connected,1,Wait(2)
    ; номер отключен
    exten => num-not-connected,n,Playback(vm-nobodyavail) ;в данный момент никто не может принять Ваш звонок
    exten => num-not-connected,n,Wait(2)
    exten => num-not-connected,n,Voicemail(${dstNUM},u)
    exten => num-BUSY,1,Wait(2)
    exten => num-BUSY,n,Playback(telephone-number) ;телефонный номер
    exten => num-BUSY,n,Playback(vm-isonphone) ;занят
    exten => num-BUSY,n,Playback(pls-try-call-later) ;попробуйте позвонить познее
    exten => num-BUSY,n,Wait(1)
    exten => num-NOANSWER,1,Voicemail(${dstNUM},u)
    exten => num-CHANUNAVAIL,1,Wait(2)
    exten => num-CHANUNAVAIL,n,Playback(vm-isunavail)

    ;Звонок на внешний номер
    exten => _XXX.,1,GoSub(recording,s,1,(${CALLERID(num)},${EXTEN}))
    exten => _XXX.,n,Dial(SIP/${EXTEN}@12345678)

    include => handup-sip

    • Я так понимаю решения нет?

      • Наверняка есть, но у меня нет возможности в этом разбираться и решать вопрос.

        • Да, есть, спасибо, нашла ответ в Вашей статье "Оповещение о занятости второй линии в asterisk". Увеличила кол-во линий на 2 и всё заработало). Вы в ней как раз про этот нюанс рассказываете.
          Ещё раз Спасибо за Ваш труд!

  65. Исправление: Добрый день, как я могу с уважением поменять язык на испанский или английский с ASTCDR?

    • Не очень понял, о каком языке идет речь? В web панели со статистикой звонков?

      • Да, веб-панель «Asterisk CDR Viewer Mod».
        Я из Латинской Америки, все устанавливаю хорошо, но панель на русском.
        Как я могу изменить его на испанский? Спасибо.

        • Эта панель русскоязычная. У нее нет перевода на другие языки. Так что только вручную переводить. Тут не так много текста, не трудно сделать самому.

          • Спасибо за ваш вклад, я надеюсь, вы настроите биллинг A2 со звездочкой 16 и freepbx. Ура!

  66. Добрый день, как я могу изменить язык на испанский или английский, с уважением.