Установка Asterisk IP-PBX в качестве домашней АТС для начинающих.
Опубликовал: Andrey [rtty] Shidakov
Введение.
Решил я построить дома собственную АТС. Выбор пал на программную АТС Asterisk —
свободное решение компьютерной телефонии с открытым исходным кодом от компании Digium. Приложение работает на операционных системах GNU/Linux, FreeBSD и Solaris. В качестве ОС была выбрана уже установленная на home-server FreeBSD 8.1.
Информации достаточно много по этому вопросу, тут я попытался собрать все необходимое для настройки простенькой домашней АТС. Статья расчитана на новичков, поэтому экспертам врядли будет интересна.
Итак, что же умеет Asterisk?
Asterisk, в комплексе с необходимым оборудованием, обладает всеми возможностями классической АТС, поддерживает множество VoIP протоколов и предоставляет функции голосовой почты, конференций, интерактивного голосового меню (IVR), центра обработки вызовов (постановка звонков в очередь и распределение их по агентам используя различные алгоритмы), запись CDR и прочие функции. Для создания собственной функциональности можно воспользоваться собственным языком Asterisk для написания диалплана, написав модуль на языке C, либо воспользовавшись AGI, который является гибким и универсальным интерфейсом для интеграции с внешними системами обработки данных, выполняемое через AGI может быть написано на любом языке программирования.
Проектируем будущую АТС.
Для начала накидаем схему будущей телефонной сети и определимся что и как будет работать:
И так, ядро системы Asterisk, VOIP шлюз Linksys SPA3102 для подключения к VoIP городской телефонной линии и обычного телефонного аппарата, GSM шлюз (в качестве его используется 3G модем Huawey E1550), различные IP телефоны (программные, например X-Lite, PhonerLite и различные аппаратные).
Итак, задачи:
— При поступлении входящего вызова на городскую линию/gsm/voip в дневное время звонят все телефоны, если в течении минуты ответа нет — включается голосовая почта. В ночное время включается голосовое меню, которое позволяет либо оставить сообщение либо ввести пин-код (известный тем людям, кому можно звонить в ночное время) и сделать вызов.
— Возможность переводить вызов (во время разговора нажатием #(внутренний номер абонента)#).
— Внутренняя связь по коротким 2-х значным номерам (у меня 10-19)
— Прием факсов и отправка на email. (в процессе)
— Отправка голосовой почти на email. (в процессе)
Оборудование:
Сам Asterisk я установил на домашний сервер на базе Intel Atom, ОС FreeBSD 8.1. В качестве VoIP шлюза был выбран Linksys SPA3102 (у нас в Тамбове его можно приобрести в http://torg68.ru/ , я покупал за 2824 руб, доставка около недели, самовывоз с Чичканова 7) . К его настройкам мы вернемся чуть позже. Для связи с сотовой сетью был установлен Huawei E1550 (стоимостью 590 рулей на момент написания статьи). IP телефоны — любые, обычный телефон — любой с тональным набором, АОН должен поддерживать стандарт FSK-CallerID, «Русский-АОН» не подойдет.
Устанавливаем Asterisk
Установку производим из портов:
cd /usr/ports/net/asterisk16 make install clean echo 'asterisk_enable="YES"' >> /etc/rc.conf /usr/local/etc/rc.d/asterisk start
Для подключения к консоли: astrisk -rvvvvvv (количество ‘v’ повышает уровень вывода)
Далее приведу свои конфигурационные файлы:
/usr/local/etc/asterisk/sip.conf
[general] ; нужно, чтобы принимать входящие вызовы через SIPNET register=>имя_пользователя:пароль@sipnet.ru/идентификатор [HOME-USERS](!) type=friend ; может как принимать, так и совершать звонки host=dynamic nat=no canreinvite=no context=from-home disallow=all ; разрешить только определенные кодэки allow=ulaw ; данная конфигурация лучше подходит allow=alaw ; для локальной сети - без сжатия. monitor=yes language=ru ; язык dtmfmode=rfc2833 [spa3102] ; для входящих с городской линии через шлюз Linksys spa3102 type=friend host=dynamic secret=пароль context=from-gw [10](HOME-USERS) ; Linksys spa3102 username=linksys secret=пароль [SIPNET] ; для sipnet.ru (для приема входящих директива register в начале файла) secret = пароль defaultuser = имя_пользователя trunkname = sipnet callerid = hasexten = no hassip = yes hasiax = no host = sipnet.ru context = from-sipnet ; контекст с таким именем должен существовать в dialplan’е insecure = invite fromuser = 0012345678 ; ваш id в SIPNET fromdomain = sipnet.ru type = peer disallow = all allow = alaw allow = ulaw allow = g729 nat = yes canreinvite = no dtmfmode = auto [11](HOME-USERS) ; IP - телефон, например программа X-Lite username=user1 secret=pass1 callerid="user1" <11> [12](HOME-USERS) ; Другой IP - Телефон username=user2 secret=pass2 callerid="user2" <12>
/usr/local/etc/asterisk/extensions.ael:
// Описываем конетксты согласно своей схеме. В моем случае схема такая: // 1. from-home - исходящие звонки с домашних телефонов, которые подразделяются на более точные контексты // 1.1 local-users - домашние номера 2-х значные (пользователи моей АТС) // 1.2 city-numbers - городские 6-ти значные номера (через шлюз gw (в моем случае Linksys SPA3102-EU)) // 1.3 mobile-numbers - 11 значные мобильные (Тамбов) (через шлюз gsm (в моем случаем 3G модем Huaway)) // 1.4 mezhgorod-numbers - междугородние (через sipnet (сеть интернет-телефонии)) // 2. from-gw входящие звонки на gw // 3. datacard-incoming входящие звонки на gsm // 4. from-sipnet входящие звонки на sipnet globals { ALL=SIP/10&SIP/11&SIP/12; } context from-home { includes { local-users; mobile-numbers; mezhgorod-numbers; city-numbers; }; }; // Пользователи моей АТС с 2-х значными номерами context local-users { _500 => { // Чтобы записывать голосовые файлы для меню Wait(2); Record(/tmp/ast:gsm); Wait(2); Playback(/tmp/ast); Wait(2); Hangup; }; _20 => VoiceMailMain(${CALLERID(NUM)}); // Набрав 20 - попадаем в голосовую почту _XX => Dial(SIP/${EXTEN},60,tT); // Для внутренних звонков }; // Звонки на городские номера будут адресоваться по обычной телефонной линии через Linksys context city-numbers { _XXXXXX => Dial(SIP/${EXTEN}@spa3102,,T); }; // Звонки на мобильные номера будут адресоваться через gsm шлюз context mobile-numbers { _89XXXXXXXXX => Dial(Datacard/datacard0/${EXTEN},,T); }; // Звоник на межгород через sipnet context mezhgorod-numbers { _849XXXXXXXX => Dial(SIP/${EXTEN}@SIPNET,,T); }; // Входящие с SIPNET context from-sipnet { s => { GotoIfTime(8:00-22:00|*|*|*?inc-day,s,1); // В дневное время inc-day Goto(inc-night,s,1); // В ночное время inc-night; }; } // Входящие с GSM-GW context datacard-incoming { s => { GotoIfTime(8:00-22:00|*|*|*?inc-day,s,1); // В дневное время inc-day Goto(inc-night,s,1); // В ночное время inc-night; }; } // Входящие с телефонной линии через Linksys context from-gw { 10 => { NoOp(CALLERID=${CALLERID(all)}); // Используется для отладки и вывода в консоль // GotoIfTime(8:00-22:00|*|*|*?inc-day,s,1); // В дневное время inc-day // Goto(inc-night,s,1); Goto(inc-day,s,1); // В ночное время inc-night; }; } context inc-day { s => { SET(CHANNEL(language)=ru); Dial(${ALL},60,t); // Звоним на телефоны (ALL обозначено в начале файла в секции GLOBAL) if ("${DIALSTATUS}" = "CHANUNAVAIL") { // Если абонент не доступен Wait(2); // Ждем 2 секунды Voicemail(20,u); // Включаем голосовую почту с сообщением "Не доступен" Hangup; // Вешаем трубку }; if ("${DIALSTATUS}" = "BUSY") { // Если занято Hangup; // Вешаем трубку }; if ("${DIALSTATUS}" = "NOANSWER") { // Если никто не ответит в течение 60 секунд (задается вторым параметром в Dial Wait(2); Voicemail(20); }; }; } context inc-night { // Вызывается ночью s => { Set(TIMEOUT(digit)=5); Set(TIMEOUT(response)=15); Answer(); Background(/usr/local/share/asterisk/voice/night-hi); // Голос: Что нибудь типа этого - К сожалению в ночное время входящие //вызовы запрещены, нажмите 1 чтобы оставить сообщение, или 2 чтобы ввести пароль для совершения вызова. vvod: WaitExten; // Ждем ввод }; _1 => Voicemail(20); // Нажато 1 - вызываем почту _2 => Goto(pass,s,1); // Нажато 2 - переходим в контекст проверки пин кода _i => { // Не правильный ввод Background(/usr/local/share/asterisk/voice/never); // Проигрываем запись о неверном вводе goto s|vvod; //Не правильный ввод } # => Hangup; // # - повесить трубку } context pass { s => { Background(/usr/local/share/asterisk/voice/pass); // Голос: Введите пароль vvod: WaitExten; // Ждем ввода }; _321* => Dial(${ALL},60,t); // 321* - Пароль. Если пароль верный, пропускаем вызов. * => { Background(/usr/local/share/asterisk/voice/never); // Неправильный ввод goto s|vvod; // Не правильный ввод }; i => { // Неверный ввод goto s|vvod; }; }
/usr/local/etc/asterisk/features.conf:
В секции [featuremap] должны быть следующие строки (это нужно для возможности перевода звонка):
blindxfer => * ; Blind transfer (default is #) disconnect => 00 ; Disconnect (default is *) atxfer => # ; Attended transfer
Чтобы работал перевод звонка, в диалплане у команды Dial есть специальные опции — tT:
T — разрешает звонящему пользователю перевести звонок (нажатием #внутренний_номер#)
t — разрешает принимающему звонок пользователю перевести звонок
В /usr/local/etc/asterisk/voicemail.conf в секции [default] дописываем пользователей:
10 => pass, User, [email protected] ; ID - 10, пароль - pass, мыло - [email protected] (отправляется уведомление)
/usr/local/etc/asterisk/datacard.conf — описан ниже в разделе по настройке GSM-шлюза.
Остальные конфиги оставляем без изменений.
Настраиваем GSM-шлюз:
В качестве GSM шлюза подойдут Huawei K3715, Huawei E169 / K3520, Huawei E1550. Следующие модемы НЕ будут работать: Huawei E160 / K3565. Был куплен Huawei E1550 за 550 руб (МТС). Голосовые функции были активны. Модем был залочен на оператора. Чтобы разлочить модем, заходим на сайт http://a-zgsm.com/huawei.php вводим в поле IMEI своего модема (обычно написан на корпусе) и получаем два кода — unlock и flash коды. У Huawei e1550 достаточно вставить другую симку и в самой программе ввести unlock код, если планируете использовать в будущем модем по назначению, то желательно прошить универсальным Dashboard с поддержкой всех операторов. Flash код нужен для разлочки некоторых других модемов, например e160g, в него сначала зашивается Dashboard, затем прошивка, при прошивке будет запрошен Falsh код. Более подробно по вопросу разлочки, а также скачать Dashboardы и прошивки можно тут и тут.
Подключаем и настраиваем модем на FreeBSD:
Для того чтобы модем определился, нужно собрать и установить модуль u3g (прим. проверенно в FreeBSD 8.1, в более ранних версиях были проблемы).
cd /sys/modules/usb/u3g make && make install && make clean
Подключаем модем и наблюдаем:
ugen0.2: at usbus0 u3g0: on usbus0 u3g0: Found 3 ports.
Видим, появились порты:
[[email protected] ~]$ ls /dev | grep cua cuaU0.0 cuaU0.0 .init cuaU0.0.lock cuaU0.1 cuaU0.1.init cuaU0.1.lock cuaU0.2 cuaU0.2.init cuaU0.2.lock
UPD (спс. Fantom & Евгений):
Чтобы небыло проблем с доступом к устройству модема, добавим юзера asterisk в группу dialer
pw groupmod dialer -m asterisk
Для отправки команд модему можно использовать утилиту cu:
cu -l /dev/cuaU0.0 -s 9600
Для выхода из терминала можно нажать тильда-точка-enter «~.».
Модем разлочен, голосовые функции активированы, определяется в системе, настроим его в качестве GSM-шлюза:
Качаем исходники, собираем модуль chan_datacard (у меня собрался только с Asterisk 1.6, при установленном 1.4 сборка вываливается с ошибкой)
cd ~ svn co http://www.makhutov.org/svn/chan_datacard/trunk/ chan_datacard cd ~/chan_datacard/ ./configure make install cp ~/chan_datacard/etc/datacard.conf /usr/local/etc/asterisk
Вот мой datacard.conf:
[general] interval=15 [datacard0] context=datacard-incoming ; Контекст для входящих с GSM шлюза, понадобится в extensions.ael audio=/dev/cuaU0.1 ; Порт для голосовых функций data=/dev/cuaU0.2 ; Порт для AT команд group=1 ; Группа звонка rxgain=2 ; Увеличение входящей громкости txgain=2 ; Увеличение исходящей громкости autodeletesms=yes ; Автоматически удалять входящие смс resetdatacard=yes ; Сбросить модем во время инициализации u2diag=0 ; Установить U2DIAG параметр (0 = отключить все кроме функций модема) usecallingpres=yes ; Предоставлять информацию о CallerID или нет callingpres=allowed_passed_screen ; Установить СallerID presentation disablesms=yes ; chan_datacard в данный момент глючит с приемом SMS. Когда SMS приходит во время звонка ; модем может упасть. Включите эту опцию чтобы отключить прием SMS. ; Default = no
Перегружаем Asterisk из консоли (подключение к консоли: asterisk -r) командой core restart now
Смотрим, загрузился ли модуль (module show like chan_datacard):
nixadm*CLI> module show like chan_datacard Module Description Use Count chan_datacard.so Datacard Channel Driver 0 1 modules loaded nixadm*CLI>
Проверяем подключился ли модем (datacard show devices):
nixadm*CLI> datacard show devices ID Group State RSSI Mode Submode Provider Name Model Firmware IMEI IMSI Number datacard0 1 Free 12 5 4 MTS RUS E1550 11.608.12.00.143 352************ 250************ Unknown
Теперь можно вписать наш GSM шлюз в диалплан. Вот так примерно это делается в extensions.ael (это пример, рабочая версия позже):
// Исходящие через GSM-GW context mobile-numbers { _89XXXXXXXXX => Dial(Datacard/datacard0/${EXTEN},,T); }; // Входящие с GSM-GW context datacard-incoming { s =>. { Dial(SIP/10&SIP/11&SIP/12,60,t); // При звонке на модем, звонят телефоны с внутренними // номерами 10,11,12, тайм аут 60, t - указывает что вызов может быть переведен }; }
Настраиваем GSM-Шлюз Linksys SPA3102
О настройке Linksys SPA3102 отдельная заметка, читать тут.
Настраиваем фаервол:
SIP:
Так как SIP является RTP протоколом, то кроме порта сигнализации (по умолчанию 5060 TCP или UDP), нужно также открыть порты для медиа-трафика (UDP). Их диапазон настраивается в файле конфигурации Asterisk rtp.conf, вот часть конфига, которая отвечает за это:
rtpstart=10000 ; Начальный порт rtpend=20000 ; Конечный порт
IAX2:
Тут проще: сигнализация и данные идут в одном потоке — нужно открыть один UDP порт (по умолчанию 4569).
Да, очень познавательная статья!Спасибо все по ней и настроил!
ТОлько вот не могу понять на счет перевода звонка, у меня номер 6011 и 6017, я с 6017 звоню на 6011 и набираю во время разговора *; Attended transfer! и вот что выводит консоль:
== Using SIP RTP CoS mark 5
— Called 6011
— SIP/6011-00000014 is ringing
— SIP/6011-00000014 answered SIP/6017-00000013
— Started music on hold, class ‘default’, on SIP/6017-00000013
— Playing ‘pbx-transfer.gsm’ (language ‘ru’)
[2011-11-09 14:41:38] WARNING[4304]: features.c:1615 builtin_atxfer: Extension ‘6’ does not exist in context »
— Playing ‘pbx-invalid.alaw’ (language ‘ru’)
— Stopped music on hold on SIP/6017-00000013
== Spawn extension (macro-stdexten-followme, s, 3) exited non-zero on ‘SIP/6017-00000013’ in macro ‘stdexten-followme’
== Spawn extension (macro-stdexten, s, 6) exited non-zero on ‘SIP/6017-00000013’ in macro ‘stdexten’
== Spawn extension (default, 6011, 1) exited non-zero on ‘SIP/6017-00000013’
и звонок возращается обратно 6011
Dial поставил Tt, и все равно не работает…
НО еще проблема в том, что у меня только не переводят звонки эти номера, остальные работаю нормально…Помогите пожалуйста, всю голову уже сломал никак не выходит(((
Спасибо за автору за статью! и одна маленькая просьба — выложить рабочие конфиги куда-нибудь в виде архива. здесь в тексте они неправильно отображаются … заранее спасибо!
Тоже присоединяюсь к предыдущему посту о не читаемости конфигов, из-за наличия хтмл тегов в статье. Прошу помочь с данной проблемой. Спасибо
@Сергей Занковецкий
@dimia
Была проблемка с плагином, вроде сейчас все верно. У меня сейчас не осталось уже Asterisk, поэтому конфиги выложить не могу.
Да, теперь — порядок, спасибо.
Здравствуйте.
Уже выражал автору огромную благодарность за статью.
Теперь хотел бы задать вопрос.
Решаема ли проблема с непрохождением dtmf при звонке на gsm-шлюз?
Поставил у себя Huawei E1550 от мегафона. Модем разлочен, голос активирован. Все работает (хотя качество голоса можно было бы и получше) кроме dtmf.
Как побороть? Или я один такой?
Помогите пожалуйста. DTMF очень нужен.