Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 124, АПРЕЛЬ 2009 г.

Звездное попурри. Фокусничаем с IP-PBX Asterisk

Sergey Jaremchuk feat. Andrey Matveev




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

Система видеонаблюдения с оповещением

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

  1. Call-файл – обычный текстовый файл, имеющий определенную структуру.
  2. API – подключившись к порту управления (по умолчанию 5038) при помощи telnet, можно задать все необходимые команды.
  3. CLI (command line interface) команда – управление сервером в консоли (вызывается при помощи «asterisk -r»).
  4. Использование настроек переадресации на другой номер – FollowMe.

Наиболее удобен в работе вариант с использованием файла с расширением .call. Достаточно такому файлу появиться в каталоге /var/spool/asterisk/outgoing (настраивается в asterisk.conf при помощи astspooldir), как сервер выполнит заданные в нем команды. Call-файл можно сгенерировать налету и затем просто скопировать в данный каталог. Asterisk проверяет время создания файла, если оно «в будущем», то команда выполнится, когда системное время и время модификации совпадут. Это также можно использовать для отложенного запуска команд в Call-файле. Единственное условие - активация параметра «autoload=yes» (так сделано по умолчанию) в modules.conf. В файле используются инструкции из extensions.conf, но у него несколько другая структура и количество возможных команд в нем ограничено.

Чтобы было понятнее, о чем речь, рассмотрим совместную работу Asterisk и системы видеонаблюдения Motion (www.lavrsen.dk/twiki/bin/view/Motion/WebHome), способной выполнять заданную программу или скрипт при обнаружении движения. Такой тандем может понадобиться для контроля над некоторым объектом, скажем, сервером. Роль Asterisk здесь – главная: с его помощью при возникновении события мы будем звонить админу на SIP-телефон (можно на городской или сотовый).
Полностью установку Motion и настройки в /etc/motion/motion.conf рассматривать не будем, за подробностями обращайся к статье «Сумеречный дозор», опубликованной в мартовском номере ][ за 2008 год. Остановимся только на самых важных моментах:

$ sudo nano /etc/motion/motion.conf

# Включаем встроенный веб-сервер, разрешаем к нему удаленный доступ
webcam_port 8000
webcam_motion on
webcam_localhost off
webcam_quality 30
webcam_maxrate 6
control_authentication username:password
# При обнаружении движения запускаем скрипт, который будет поднимать тревогу, вместо директивы on_motion_detected можно использовать on_event_start
on_motion_detected /usr/bin/webcam_event.sh

Смотрим отладочную информацию, запустив Motion с флагом '–n':

$ motion –n
Thread is from /etc/motion/motion.conf

Если все в порядке, стартуем программу в обычном режиме и переходим к написанию скрипта webcam_event.sh:

$ sudo nano /usr/bin/webcam_event.sh

#!/bin/sh
cat << EOF > /tmp/alarm.call
# Устанавливаем параметры канала и CallerID
Channel: SIP/admin
Callerid: 11111111
# Количество повторных попыток вызова в случае неудачи, не включая первую (т.е. в нашем случае при возникновении проблем будет сделано 3 попытки вызова абонента)
MaxRetries: 2
# Время до повторной попытки набора (по умолчанию 300 сек)
RetryTime: 30
# Время ожидания ответа (по умолчанию 45 сек)
WaitTime: 30
# Контекст из extensions.conf и приоритет вызова
Context: alarm
Extension: s
Priority: 1
EOF
# Задаем нужные права для созданного файла и переносим его в нужную папку
chown asterisk:asterisk /tmp/alarm.call
mv /tmp/alarm.call /var/spool/asterisk/outgoing/

Вот практически и все параметры, возможные в Call-файле. Опционально для установки времени можно использовать timestamp:

Set: timestamp=20091023104500

Теперь добавляем описание в extension.conf:

$ sudo nano /etc/asterisk/extension.conf

[alarm]
exten => s,1,Answer()
exten => s,n,Wait(2)
exten => s,n,Playback(activated)
exten => s,n,Wait(1)
exten => s,n,Hangup()

После внесения изменений не забываем перечитать план набора командой «dialplan reload». Теперь, обнаружив движение, Motion запустит выполняться скрипт webcam_event.sh, который создаст /tmp/alarm.call и скопирует его в /var/spool/asterisk/outgoing. После чего Call-файл будет обработан Asterisk, и на номер admin, описанный в sip.conf, поступит звонок с CallerID «11111111». Немного допилив этот скрипт, можно заставить Asterisk выполнять и другие операции, например, отправлять e-mail или SMS. Как ты понимаешь, вместо Motion подойдет любая другая программа, умеющая создавать или копировать файлы при возникновении определенного события.

Усложняя конфигурацию, упрощаем управление

Рассмотрим еще одну возможность выполнения команд в Asterisk, а заодно – немного дополним нашу схему. Например, в рабочее время в использовании Motion особого смысла нет, поэтому его можно смело отключать. Это можно сделать из консоли или при помощи планировщика cron, но удобнее для включения/отключения просто позвонить по определенному номеру. Создадим небольшой скрипт, при помощи которого будем управлять демоном Motion:

$ sudo nano /usr/bin/motion.sh

#!/bin/sh
case $1 in
start)
/usr/bin/motion
;;
stop)
PID=`pidof motion`
kill $PID
killall webcam_event.sh
rm -f /var/spool/asterisk/outgoing/alarm.call
;;
esac

В extension.conf заносим описания номеров, которые будут использованы для запуска скрипта с разными параметрами:

$ sudo nano /etc/asterisk/extension.conf

exten => *001,1,Answer()
exten => *001,n,Playback(activated)
exten => *001,n,System(/usr/bin/motion.sh start)
exten => *001,n,Hangup()
exten => *002,1,Answer()
exten => *002,n,System(/usr/bin/motion.sh stop)
exten => *002,n,Playback(de-activated)
exten => *002,n,Hangup()

Теперь, чтобы запустить Motion, достаточно набрать номер *001, а чтобы остановить – *002.

Будильник на Asterisk

Реализовать будильник в *nix можно далеко не единственным способом (самый простой, наверное: «sleep 20m && mpg123 ~/bell.mp3»), но хочется чего-то красивого и нестандартного. Поиск в интернете по запросу «asterisk wakeup» выдаст несколько решений, написанных с использованием разных языков программирования и немного отличающихся как процессом установки, так и возможностями. Самое популярное из них - PHP скрипт wakeup.php, автором которого стал Анди Высоцки (www.voip-info.org/liberty/view/file/2388). Скачиваем по ссылке tar-архив, распаковываем php-файл в каталог с AGI скриптами (Asterisk Gateway Interface - шлюзовой интерфейс, посредством которого внешние программы могут управлять диалпланом Asterisk) и делаем его исполняемым: «chmod a+x /var/lib/asterisk/agi-bin/wakeup.php» (нужный каталог можно узнать, просмотрев значение переменной astagidir в конфиге asterisk.conf).

Скрипт wakeup.php содержит ряд переменных, которые необходимо подправить с учетом настроек системы:

; Расположение интерпретатора PHP в разных *nix-системах может отличаться
#!/usr/bin/php -q
; Журнал из /tmp лучше убрать
$parm_error_log = '/var/log/asterisk/wakeup.log';
; По умолчанию скрипт создает временные файлы в /tmp, но если этот каталог находится на отдельном разделе, то wakeup.php откажется работать, поэтому:
$parm_temp_dir = '/var/spool/asterisk/tmp';

Принцип запуска скрипта аналогичен примеру с Motion - просто заносим в extensions.conf информацию о новом номере:

exten => *97,1,Answer()
exten => *97,n,AGI(wakeup.php)
exten => *97,n,Hangup()

Теперь достаточно позвонить на номер *97 и по запросу ввести время, когда система должна произвести обратный звонок. Например, чтобы завести будильник на 17:55 (сегодня финал кубка английской лиги :)), набираем «0555», а затем «2» (1 - до полудня, 2 - после полудня).

Если при запуске скрипта возникли проблемы, доустанови пакеты php5-cli и asterisk-sound-extra и используй утилиту fromdos, чтобы привести wakeup.php к Unix-стандартам.

Виртуальный диктофон

Дистрибутивный комплект Asterisk и пакет дополнений asterisk-sounds содержат около 1000 голосовых сообщений на английском языке (голос принадлежит дамочке по имени Allison Smith). В качестве альтернативы можно записать мессаджи на русском/украинском/суахили самостоятельно, но для этого необязательно прибегать к аудиоредактору типа Audacity. Нижеследующее дополнение в диалплан обеспечит возможность звонить на номер *98 и записывать сообщения в папку /tmp под именами myrecordНОМЕР.wav. После завершения записи (осуществляется нажатием #) звуковой файл будет воспроизведен, и соединение разорвется. Примечание: чтобы уровень громкости был постоянным, а «белый» шум, создаваемый системами отопления/охлаждения/кондиционирования, сведен к минимуму, для записи лучше воспользоваться аппаратным VoIP-телефоном.

exten => *98,1,Answer()
exten => *98,n,Wait(2)
exten => *98,n,Record(/tmp/myrecord%d:wav)
exten => *98,n,Wait(1)
exten => *98,n,Playback(${RECORDED_FILE})
exten => *98,n,Wait(1)
exten => *98,n,Hangup()

Не забудь скопировать/перенести полученный файл из временной директории в папку для звуковых файлов Asterisk и наделить его каким-нибудь осмысленным именем, вроде privetstvie.wav. Кстати, голосовые сообщения лучше не конвертировать в gsm/mp3/ogg, чтобы на проц не легла дополнительная нагрузка по преобразованию.

Телефонный справочник

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

exten => *99,1,Directory(default,internal)

Создаем почтовый ящик в файле voicemail.conf:

[default]
401 => 1234,Andrey Matveev,andrushock@real.xakep.ru

На клавиатуре софтофона набираем *99, затем первые три буквы фамилии пользователя, номер которого мы хотим узнать (в данном случае – «mat»). Allison Smith начнет по буквам «зачитывать» из voicemail.conf имя и фамилию найденного абонента: «a-n-d-r-e-y m-a-t-v-e-e-v». Подтверждаем правильность выбора нажатием «1». Виртуальный оператор проговорит добавочный номер 401 (если в диалплане используется конструкция вида «exten => _XXX,1,SayDigits(${EXTEN})») и произведет соединение. Очень удобно!

Который час?

Оказывается, служба точного времени - невероятно популярный сервис: судя по материалу из Википедии, ежедневно по номеру 100 звонят около миллиона москвичей. Может быть, пойдем навстречу МГТС (или твоей городской телефонной станции) и чуточку разгрузим их оборудование за счет создания своих «говорящих часов»? В этом нам поможет приложение SayUnixTime(), проговаривающее указанное время в определенном формате:

exten => *100,1,Answer()
exten => *100,n,SayUnixTime(,,QdhAR)
exten => *100,n,WaitMusicOnHold(10)
exten => *100,n,Goto(*100,1)

Набираем *100, Allison Smith приветливо сообщает о том, что сейчас 1 марта, воскресенье, 14 часов и 50 минут. Затем воспроизводится 10-секундная музыкальная пауза (путь к папке с музоном задается параметром directory в файле musiconhold.conf), и вызов номера повторяется (на тот случай, если мы что-то не расслышали).

Будущее телефонии за видеозвонками

Изначально вопрос о поддержке видеосвязи перед разработчиками не ставился, однако сегодня необходимость в такой функциональности очевидна. Кроме того, вычислительные мощности многократно возросли, трафик подешевел, а пропускная способность каналов позволяет гонять видеопоток хорошего качества. Так или иначе, но поддержка видео в Asterisk 1.4 находится в зачаточном состоянии (плохое согласование кодеков, не распознаются расширенные атрибуты для видеопотоков, не поддерживаются популярные видеоформаты, нет возможности перекодировки и т.д.). Часть перечисленного, вероятно, так никогда и не появится в Asterisk, в том числе, из-за возможных проблем с лицензированием. Например, разработчики не могут использовать библиотеку ffmpeg, хотя сегодня уже доступно приложение app_transcoder (sip.fontventa.com/content/view/30/57), работающее с ffmpeg и имеющее ограниченные функции, связанные с перекодированием. В новой версии 1.6 планировались некоторые подвижки в этом направлении, в частности, полная перестройка поддержки видео в каналах (так называются соединения в Asterisk), но пока дальше идей дело не пошло.

Из всего множества каналов передача видео реализована только в двух - SIP и IAX2. Некоторые популярные реализации (chan_h323, chan_oh323, chan_ooh323) старого доброго H.323 не обеспечивают такой возможности, хотя в самом стандарте H.323 это предусмотрено. Так, чтобы разрешить совершать вызовы с поддержкой видео, достаточно добавить в файл sip.conf параметр:

[general]
videosupport=yes

В IAX эта возможность заложена изначально, поэтому параметр videosupport в файле iax.conf не поддерживается.Список видеокодеков, умеющих работать с видео, невелик: H.261 (только транзит), H.263, H.263p и H.264 (последние два с Asterisk версии 1.4). Но так как Asterisk 1.4 имеет проблемы с согласованием кодеков, активировать их все одновременно не следует. Лучше подобрать наиболее оптимальный для конкретной ситуации, отключив остальные при помощи «disallow=all». Но не забывай, что выбранный кодек должен поддерживаться и клиентом.

disallow=all
allow=alaw
allow=gsm
allow=speex
allow=ilbc
allow=h264
allow=h261

По умолчанию максимальный битрейт для видео установлен в 384 Кб/с, – его можно изменить при помощи директивы maxcallbitrate.Нельзя не отметить, что Asterisk умеет задавать биты TOS (Type of Service) в заголовке IP-пакета, чтобы ускорить передачу потока данных через маршрутизаторы, которые учитывают биты TOS при определении маршрутов. В sip.conf директивы tos_sip, tos_audio и tos_video управляют TOS-битами для SIP-сообщений, аудио- и видеоданных соответственно.

tos_video=af41

В iax.conf все поля TOS устанавливаются при помощи одного параметра:

tos=0x18

В настоящее время передачу видео поддерживает огромное количество софт-клиентов: Ekiga, Bria, X-lite, Linphone, Milliphone, WengoPhone, Windows Messenger и некоторые другие.

Вместо заключения

Что еще можно сделать с помощью Asterisk? Например, расширить функции устаревшей коммутируемой АТС, создать интерактивный автоответчик (это может быть прогноз погоды для любой точки земного шара, обучающая программа или аудиоигра - ответы можно вводить посредством номеронабирателя телефона), организовывать аудиоконференц-залы, читать электронную почту вслух, когда ты, например, в дороге или принимаешь ванну (связка Asterisk + Festival), управлять системой сигнализации, контролировать няню и детей (допустим, мать и отец, сидя на работе, подключаются VPN-клиентом к домашнему серверу, звонят в контекст добавочного номера, защищенного паролем, после успешной аутентификации устанавливается аудиосвязь со всеми IP-телефонами в квартире - это позволит родителям слышать, что происходит в каждой комнате, - своеобразные VoIP-жучки). Прояви творческие способности, замути что-нибудь экстраординарное и напиши нам :).

INFO

Существует патч от разработчика с ником IVeS (смотри на нашем диске файл videocodec_nego_fix_ast-1.4.13.patch.gz), в котором проблема согласования кодеков устранена, но сама заплатка до сих пор не принята Digium.

VIDEO

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

WWW

  • Все возможности по инициированию исходящего звонка в Asterisk ты найдешь в документе «Asterisk auto-dial out» - www.voip-info.org/wiki-Asterisk+auto-dial+out.
  • Описание всех известных проблем, связанных с передачей видео, можно найти в списке рассылки Asterisk-Video (lists.digium.com/pipermail/asterisk-video).
Содержание
загрузка...
Журнал Хакер #151Журнал Хакер #150Журнал Хакер #149Журнал Хакер #148Журнал Хакер #147Журнал Хакер #146Журнал Хакер #145Журнал Хакер #144Журнал Хакер #143Журнал Хакер #142Журнал Хакер #141Журнал Хакер #140Журнал Хакер #139Журнал Хакер #138Журнал Хакер #137Журнал Хакер #136Журнал Хакер #135Журнал Хакер #134Журнал Хакер #133Журнал Хакер #132Журнал Хакер #131Журнал Хакер #130Журнал Хакер #129Журнал Хакер #128Журнал Хакер #127Журнал Хакер #126Журнал Хакер #125Журнал Хакер #124Журнал Хакер #123Журнал Хакер #122Журнал Хакер #121Журнал Хакер #120Журнал Хакер #119Журнал Хакер #118Журнал Хакер #117Журнал Хакер #116Журнал Хакер #115Журнал Хакер #114Журнал Хакер #113Журнал Хакер #112Журнал Хакер #111Журнал Хакер #110Журнал Хакер #109Журнал Хакер #108Журнал Хакер #107Журнал Хакер #106Журнал Хакер #105Журнал Хакер #104Журнал Хакер #103Журнал Хакер #102Журнал Хакер #101Журнал Хакер #100Журнал Хакер #099Журнал Хакер #098Журнал Хакер #097Журнал Хакер #096Журнал Хакер #095Журнал Хакер #094Журнал Хакер #093Журнал Хакер #092Журнал Хакер #091Журнал Хакер #090Журнал Хакер #089Журнал Хакер #088Журнал Хакер #087Журнал Хакер #086Журнал Хакер #085Журнал Хакер #084Журнал Хакер #083Журнал Хакер #082Журнал Хакер #081Журнал Хакер #080Журнал Хакер #079Журнал Хакер #078Журнал Хакер #077Журнал Хакер #076Журнал Хакер #075Журнал Хакер #074Журнал Хакер #073Журнал Хакер #072Журнал Хакер #071Журнал Хакер #070Журнал Хакер #069Журнал Хакер #068Журнал Хакер #067Журнал Хакер #066Журнал Хакер #065Журнал Хакер #064Журнал Хакер #063Журнал Хакер #062Журнал Хакер #061Журнал Хакер #060Журнал Хакер #059Журнал Хакер #058Журнал Хакер #057Журнал Хакер #056Журнал Хакер #055Журнал Хакер #054Журнал Хакер #053Журнал Хакер #052Журнал Хакер #051Журнал Хакер #050Журнал Хакер #049Журнал Хакер #048Журнал Хакер #047Журнал Хакер #046Журнал Хакер #045Журнал Хакер #044Журнал Хакер #043Журнал Хакер #042Журнал Хакер #041Журнал Хакер #040Журнал Хакер #039Журнал Хакер #038Журнал Хакер #037Журнал Хакер #036Журнал Хакер #035Журнал Хакер #034Журнал Хакер #033Журнал Хакер #032Журнал Хакер #031Журнал Хакер #030Журнал Хакер #029Журнал Хакер #028Журнал Хакер #027Журнал Хакер #026Журнал Хакер #025Журнал Хакер #024Журнал Хакер #023Журнал Хакер #022Журнал Хакер #021Журнал Хакер #020Журнал Хакер #019Журнал Хакер #018Журнал Хакер #017Журнал Хакер #016Журнал Хакер #015Журнал Хакер #014Журнал Хакер #013Журнал Хакер #012Журнал Хакер #011Журнал Хакер #010Журнал Хакер #009Журнал Хакер #008Журнал Хакер #007Журнал Хакер #006Журнал Хакер #005Журнал Хакер #004Журнал Хакер #003Журнал Хакер #002Журнал Хакер #001