ISP`s IT Аутсорсинг
Быстрый переход: Главная блога Главная сайта Форум
Если Вы чего то недопоняли или не нашли - задайте
вопрос на нашем форуме и мы попробуем Вам помочь.
Subnets.ru Регистрация IP и Автономных систем mega-net.ru

Метки статьи: ‘Asterisk’

Добро пожаловать в блог! Надеемся, что Вы еще вернетесь.

Кто то уже знает, кто-то нет и спит спокойно, точнее пока что спит спокойно.

Как давно вы читали логи своего Asterisk сервера ?

Некоторые из вас или уже видели или ещё увидят в логах строчки:

  • Registration from ‘»100″<sip:100@sip.mydomain.ru>’ failed for ‘188.165.215.79’ — No matching peer found
  • Registration from ‘»111″ <sip:111@sip.mydomain.ru>’ failed for ‘188.165.215.79’ — Wrong password

Догадываетесь к чему они ведут ? К тому что вас сканят и пытаются подобрать пароль к вашим SIP аккаунтам.

Большинство пользователей безалаберно относятся к своим паролям, это факт, а раз так то проверте что на ваших SIP номерах не стоят пароли аля 123 или 1234.

Если пароль таки подберут, то вы (или ваш клиент) попадете на деньги, т.к. через вас пустят звонки забугор, например на Кубу или Северную Корею.

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

В сети есть набор утилит sipvicious:

The 4 tools that you should be looking at are:svmapsvwarsvcracksvreportsvcrash

The tools: svmap — this is a sip scanner. When launched against ranges of ip address space, it will identify any SIP servers which it finds on the way. Also has the option to scan hosts on ranges of ports.

svwar — identifies working extension lines on a PBX. A working extension is one that can be registered. Also tells you if the extension line requires authentication or not.

svcrack — a password cracker making use of digest authentication. It is able to crack passwords on both registrar servers and proxy servers. Current cracking modes are either numeric ranges or words from dictionary files.

svreport — able to manage sessions created by the rest of the tools and export to pdf, xml, csv and plain text.

svlearnfp — allows you to generate new fingerprints by simply running the tool against a host. It will attempt to guess most values and allow you to save the information to the local fingerprint db. Then you can choose to upload it to the author so that it can be added to the database.

svcrash — responds to svwar and svcrack SIP messages with a message that causes old versions to crash.

Так вот с их помощью нас и сканят.  Эти же утилиты помогут нам просканить самих себя и  усложнить жизнь уродам жаждущих халявы.

Начнем с того что скачаем этот набор утилит (сохраненная у нас копия).

Распакуйте архив в какую нить папку и можно приступать к скану.

Будет считать что IP-адрес нашего Asterisk сервера это 192.168.1.1  и запустим сканер:

cd /home/virus/sipvicious

./svmap.py -p5060 192.168.1.1 -m INVITE

Получаем результат:

| SIP Device        | User Agent   | Fingerprint |
--------------------------------------------------
| 192.168.1.1:5060 | Asterisk PBX | disabled    |

Идем далее, посканим теперь на аккаунты:

./svwar.py —force -e100-999 192.168.1.1

Ответ может быть таким:

| Extension | Authentication |
------------------------------
| 210       | reqauth        |
| 300       | reqauth        |
| 666       | reqauth        |
| 241       | reqauth        |
| 242       | reqauth        |
| 222       | reqauth        |

Можно ли как то обломать их ? Можно. Для этого отредактируем /usr/local/etc/asterisk/sip.conf и добавим или раскоментируем строчку в секции [general]:

alwaysauthreject = yes

Описание:

When an incoming INVITE or REGISTER is to be rejected, for any reason, always reject with ‘401 Unauthorized’ instead of letting the requester know whether there was a matching user or peer for their request.

Т.е. наш сервер будет всегда при любых ошибках авторизации будет отвечать «401 Unauthorized» и не сообщать подробностей.

После изменения sip.conf зайдите в консоль Asterisk`а:

asterisk -r

и примените изменения:

asterisk*CLI> sip reload

Теперь посканим снова:

./svwar.py —force -e100-999 192.168.1.1

Ответ от сканера изменился и выглядит примерно так:

WARNING:TakeASip:Bad user = SIP/2.0 401  - svwar will probably not work!
WARNING:TakeASip:We got an unknown response
ERROR:TakeASip:Response: 'SIP/2.0 401 Unauthorized\r\n
Via: SIP/2.0/UDP 192.168.1.1:5061;branch=z9hG4bK-3613016185;received=192.168.1.1;rport=5061\r\n
From: "100"; tag=31303001333430333334313736\r\n
To: "100";tag=as47e73e29\r\nCall-ID: 2008271273\r\n
CSeq: 1 REGISTER\r\n
User-Agent: Asterisk PBX\r\n
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO\r\n
Supported: replaces\r\n
WWW-Authenticate: Digest algorithm=MD5, realm="asterisk", nonce="3b652f8d"\r\n
Content-Length: 0\r\n\r\n'

Как видите списка с номерами более не выдается, то что нам и надо.

Что ещё мы можем сделать ?

A. Например закрыть в диал-плане забугорные направления (коды стран), по которым не вы ни ваши пользователи не звонят или вообще перекрыть выход на международку.

Добавим в  /usr/local/etc/asterisk/extensions.conf в секцию где у вас происходит выход в город:

exten => _810X.,1,playback(pbx-invalid)

exten => _810X.,n,Hangup()

B. Так же мы можем скриптом анализировать логи Asterisk сервера и всех уродов, подбирающих пароль, банить фаирволом (ipfw) сервера.

Нашу версию подобного скрипта можно увидеть пройдя по ссылке: http://subnets.ru/files/protect_aster.txt

Инсталляция скрипта:

1. Сохраните код скрипта на своем сервере

2. Переименуйте файл в protect_aster.sh

3. Сделайте скрипт исполняемым:

chmod a+x protect_aster.sh

4. Добавте в ваш firewall ipfw правило:

ipfw add XXX reject ip from «table(56)» to me

где ХХХ это номер правила.

Будьте внимательны размещая данное правило, не забаньте сами себя ! Обеспечьте allow правила для своих IP-адресов выше этого правила, чтобы избежать неожиданностей.

5. Добавте скрипт на исполнение по crontab, отредактируйте /etc/crontab:

*/5    *       *       *       *       root    /full/path/to/script/protect_aster.sh

Забаненый IP-адрес попадает в таблицу ровно на сутки, через сутки он автоматически будет удален из таблицы.

C. В /usr/local/etc/asterisk/sip.conf, описывая секции пользователей (их номера) указывайте:

type=user

Пароли ставте минимум из 6-ти знаков с использованием букв и цифр.

Если известно с каких адресов будет авторизовываться пользователь, то будет совсем не лишним указать ACL с перечислением IP-адресов/подсетей из которых разрешено подключение, например:

[111]
type=user
context=users
disallow=all
allow = alaw
reinvite=no
canreinvite=no
callerid=User 111
language=ru
secret=Xm32rQ
mailbox=111
host=dynamic
deny=0.0.0.0/0
permit=217.172.16.74/30
nat=yes

В данном примере пользователю разрешено подключаться только из подсети 217.172.16.74/30 и запрещено из всех остальных. Не забудьте прописать пароль (secret=Xm32rQ) и в /usr/local/etc/asterisk/users.conf.

D. Измените план набора номеров для исходящих звонков. Добавте к номеру какой нибудь префикс, например 004 и «отрезайте» его (в моем примере это получается 3 цифры) перед тем как отправить своему провайдеру:
exten => _0048X.,1,Dial(SIP/${EXTEN:3}@sip-provider,60,rT)

Т.е. что бы набрать городской номер, пользователь должен набрать 00484951234567, халявщик этого точно знать не может, потому обломится, а мы ему поможем, дописав:
exten => _8X.,1,playback(pbx-invalid)

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

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

З.Ы. При копировании статьи ссылка на источник ОБЯЗАТЕЛЬНА ! Пожалуйста, уважайте чужой труд.

З.Ы.Ы. Ваши комментарии и дополнения к статье приветствуются.

Авторы: Панфилов Алексей (lehis (at) subnets.ru) и Николаев Дмитрий (virus (at) subnets.ru)

Ничего не понялТак себе...Не плохоДовольно интересноОтлично ! То что нужно ! (голосов: 4, среднее: 5,00 из 5)
Загрузка...
Отправить на почту Отправить на почту

Автообзвон

Есть задачи реализация которых возможна через автоматический обзвон. Например ?

Например вы сис.админ, у вас есть локальная сеть и куча оборудования в ней, но вы же не 24/7 на работе, а раз так, то в сети может что то произойти, например событие в системе мониторинга, а вас нет на рабочем месте. Конечно можно отправлять себе SMS, если такая вожможность есть, а имея сервер Asterisk можно и позвонить и самому себе рассказать что же случилось 😉

Или вам необходима система callback, что бы позвонив на номер заведенный на Asterisk, вы могли получить с него обратный звонок и набрать другой номер.

Итак, считаем что у вас у уже есть установленный и настроенный сервер Asterisk, который имеет выход в город.

Что бы совершить автоматический звонок нам потребуется следующие вещи:

  • сформировать call файл
  • иметь в диалплане (dialplan (определяется в /usr/local/etc/asterisk/extensions.conf)) контекст (context) со списком действий

Начнем с call файла, его основной синтаксис:

  • Channel: <channel> — Какой канал использовать для звонка
  • CallerID: «name» <number> — Установить Caller ID, проще сказать тут мы можем выставить АОН (номер с которого мы звоним).
  • MaxRetries: <number> — Максимальное кол-во попыток дозвониться, по умолчанию 0, что является одной попыткой.
  • RetryTime: <number> — Время в секундах между попытками дозвона, по умолчанию 300 (5 минут).
  • WaitTime: <number> — Сколько секунд ожидаем поднятия трубки, по умолчанию 45.
  • Context: <context-name> — Какой контекст используем из extensions.conf
  • Extension: <ext> — Какой экстеншн используем в выбранном контексте (так же в extensions.conf).
  • Priority: <priority> — С какого приоритета начинаем.

Я привел не полный список, полный список доступен тут. Лично я, для каждого номера, создаю свой контекст в extensions.conf.

Соответственно зная синтаксис мы теперь сможем сформировать call файл, на примере звонка через SIP канал:

Channel: SIP/89161112233@sip-provider
Callerid: 9998877
MaxRetries: 2
RetryTime: 20
WaitTime: 60
Context: outgoing_to_89161112233
Extension: s
Priority: 1

Для тех кто в танке 🙂 разберем call файл построчно:

  • позвонить на SIP номер 89161112233 через провайдера sip-provider (имя из /usr/local/etc/asterisk/sip.conf для выхода в город)
  • использовать АОН 9998877
  • Максимальное кол-во попыток дозвона 2
  • Пауза между попытками 20 секунд
  • Ожидать поднятия трубки 60 секунд
  • Использовать контекст (context) с именем outgoing_to_89161112233
  • Начинать с экстеншена (ext) s
  • И начинать с приоритета 1 в экстеншене s

Сформировав call файл, его необходимо положить в папку:  /var/spool/asterisk/outgoing/ сервер Asterisk обнаружив в этой папке файл сразу же попытается отработать его.

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

Сервер Asterisk смотрит на дату создания call файла и если изменить дату создания на дату в будущем, то Asterisk не будет отрабатывать call файл, пока не наступит эта самая дата.

Как это сделать ? Очень просто, для этого воспользуемся командой touch, которая есть во всех unix системах.

После того как создали сам call файл берем и меняем дату его создания, шаблон даты такой:

ГОДМЕСЯЦДЕНЬЧАСЫМИНУТЫ.СЕКУНДЫ (внимание: перед секундами стоит символ точки, это так и нужно, а не опечатка).

Для примера выставим дату в будущем, скажем это 09.07.2010 19:18:55:

/usr/bin/touch -t 1007091918.55 /path/to/call/file.call

Дата создания call файла изменится и если переместить файл в /var/spool/asterisk/outgoing/, то соответственно Asterisk его не обработает до тех пор пока не наступит выставленная дата.

Совет: генерить call файл лучше в какой то tmp директории, выполнять над ними все необходимые и действия и затем мувить (переносить) в /var/spool/asterisk/outgoing/.

Теперь посмотрим на сам контекст (context), для системы мониторинга он может быть таким:

[outgoing_to_89161112233]
exten => s,1,Answer
exten => s,n,Wait(1)
exten => s,n,Background(/usr/local/share/asterisk/sounds/monitoring/welcome)
exten => s,n,Background(/usr/local/share/asterisk/sounds/monitoring/Down)
exten => s,n,Background(/usr/local/share/asterisk/sounds/monitoring/provider-a)
exten => s,n,Background(/usr/local/share/asterisk/sounds/monitoring/bye)
exten => s,n,hangup

Исходя из данного контекста Asterisk дозвонившись до 89161112233 (человек взял трубку) выполнит следущее:

  • поднимет трубку со своей стороны
  • секунду подождет
  • проиграет записанные вами звуковые файлы (полные пути к файлам указаны)
  • повесит трубку

Как записать голосовые файлы (то что вы будете проигрывать) вы можете узнать из этой статьи.

После того как Asterisk полностью отработает call файл, он его удаляет из директории /var/spool/asterisk/outgoing/.

Специальный экстеншен ‘failed
Если на вызов не ответили, и существует стандартный экстеншен с именем failed и команда с приоритетом 1 в заданном (в .call файле) контексте, управление будет передано этой команде.

exten => failed,1,Set(NumberDialed=${CUT(PassedInfo,,1)})
exten => failed,n,SetCDRUserField(${NumberDialed})

[Добавлено 11.02.2011]

Может появится ещё одна задача, а именно: если при автодозвоне трубку так и не подняли, то сразу набрать другой номер. Пример такой конструкции:

  • сначала набираем внутренний SIP  номер (6003) человека
  • если внутренний SIP номер не отвечает/занят/недоступен — набираем мобильный номер

Кажется, ну что может быть проще, написать:

exten => failed,1,Dial(SIP/89161112233@sip-provider)

А вот тут то и выяснилось, что не все так просто. На такое действо вы в консоле (выставив core set verbose 3) увидите подобное сообщение:

— Executing [failed@dialsip:1] Dial(«OutgoingSpoolFailed», «SIP/6003») in new stack
[Feb 11 16:57:44] WARNING[94371]: channel.c:3441 ast_request: No translator path exists for channel type SIP (native 65535) to 0
[Feb 11 16:57:44] WARNING[94371]: app_dial.c:1296 dial_exec_full: Unable to create channel of type ‘SIP’ (cause 58 — Bearer capability not available)
== Everyone is busy/congested at this time (1:0/0/1)
== Auto fallthrough, channel ‘OutgoingSpoolFailed’ status is ‘CHANUNAVAIL’
[Feb 11 16:57:54] NOTICE[94371]: pbx_spool.c:356 attempt_thread: Call failed to go through, reason (8) Congestion (circuits busy)

Усе… приехали…. Лазая по результатам поиска в гугле я натыкался на сообщения:

Канал получается OutgoingSpoolFailed и именно в него пытается звонить и Dial и играть Playback. Как мне находясь в failed сделать звонок на SIP и проиграть сообщение?

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

Так же как и я народ пытался реализовать подобное через failed c Goto, System и т.п., но результат получался таким же — никаким 🙁

Получается из starndart extention failed сделать набор (Dial) другого номера не получится…..

Я уже было подумал, что не судьба и мне придется ловить DIALSTATUS, передавать его AGI скрипту (который ещё и писать придется) и тот уже будет решать что с этим делать (создавать новый call файл или ещё что то), но тут родился ещё один вариант:

core*CLI> core show channeltypes
Type        Description                              Devicestate  Indications  Transfer
----------  -----------                              -----------  -----------  --------
Skinny      Skinny Client Control Protocol (Skinny)  no           yes          no
SIP         Session Initiation Protocol (SIP)        yes          yes          yes
Console     OSS Console Channel Driver               no           yes          no
MGCP        Media Gateway Control Protocol (MGCP)    yes          yes          no
Local       Local Proxy Channel Driver               yes          yes          no
Zap         DAHDI Telephony Driver w/PRI             no           yes          no
Agent       Call Agent Proxy Channel                 yes          yes          no
----------
7 channel drivers registered

core*CLI> core show channeltype Local
-- Info about channel driver: Local --
Device State: yes
Indication: yes
Transfer : no
Capabilities: -1
Digit Begin: yes
Digit End: yes
Send HTML : yes
Image Support: no
Text Support: yes
core*CLI>

Создаем call-файл уже чуть другого содержания:

Channel: Local/1@autocaller
Callerid: 9998877
Context: outgoing_to_89161112233
Extension: s
Priority: 1

Где autocaller это название контекста, а 1-ца это приоритет в этом контексте. Соответственно делаем в extensions.conf этот контекст:

[autocaller]
exten => 1,1,Macro(call6003user,6003)

Тем самым мы как бы набираем уже не номер, а конкретный exten  в контексте и в нем передаем вызов в макро, создаем и макро, которое используется в этом контексте:

[macro-call6003user]
exten => s,1,Dial(SIP/${ARG1},15,t)
exten => s,n,Goto(s-${DIALSTATUS},1)
exten => s-NOANSWER,1,Dial(SIP/89161112233@sip-provider)
exten => s-NOANSWER,n,VoiceMail(${ARG1},u)
exten => s-NOANSWER,n,Hangup()
exten => s-BUSY,1,VoiceMail(${ARG1},b)
exten => s-BUSY,n,Hangup()
exten => _s-.,1,Goto(s-NOANSWER,1)

Собственно этот макро дает нам возможность уже управлять куда и в каком случае пойдет вызов. Пример конечно «грубый», но главное ведь принцип, а дальше уже ваше творчество 😉

И вот таким образом мы получаем искомый результат.

[Конец добавленного 11.02.2011]

Callback

Он работает по тому же принципу, что и описанный выше автообзвон, за некоторыми исключениеми:

  • генерация call файла происходит при звонке человека на номер выделенный под callback.
  • в контексте (context) мы не просто проигрываем звуковые, а предлагаем пользователю ввести номер, на который он хочет позвонить

Что нам потребуется в этом случае:

  • выделить номер для callback и создать контекст (context) под него в  extensions.conf.
  • «передать»  звонок в AGI скрипт, который проверит АОН звонящего на предмет разрешен ли этому номеру callback
  • если  callback разрешен, то сформирует call файл.

AGI — это Asterisk Gateway Interface.
Asterisk Gateway Interface это возможность расширить функционал Asterisk`а с помощью использования скриптов на многих языках программирования. Например Perl, PHP, C, Pascal, Bourne Shell.

Начнем с номера, допустим это будет гор. номер 84955556677. Добавим в extensions.conf в контекст (context) куда поступают все входящие звонки:

exten => 84955556677,1,AGI(sms-callback.php)
exten => 84955556677,n,Hangup()

Т.е. звонок на экстеншн (ext) 84955556677 будет передан AGI скрипту callback.php, а затем звонок будет сразу же завершен.

AGI скрипты для Asterisk располагаются в директории  /usr/local/share/asterisk/agi-bin/.

Почему скрипт на PHP ? PHP был выбран для AGI, т.к. callback является неотъемлимой частью проекта написанного на PHP + MySQL, потому решили и AGI пусть на PHP будет.
Сам скрипт: http://subnets.ru/files/callback.php.txt

Что происходит с скрипте ?

  • определяем необходимые переменные
  • получаем данные от Asterisk`а.
  • логи, куда же без них. В лог мы поместим все то, то получил AGI скрипт от Asterisk`а, это для дебага, потом можно выключить логирование.
  • проверяем номер (АОН) звонящего на доступ к callback
  • смотрим нет ли уже call файла для  данного номера, если нет, то создаем его

В переменной $agivar[‘agi_callerid’] и содержится АОН (телефонный номер) звонящего переданного нам Asterisk`ом, что в других передаваемых переменных вы сможете увидеть в log файле.
Если установить $debug в ноль, то тем самым выключите логирование.
В массиве  $permit_num содержатся номера для которых разрешен callback.

Ну и осталось дело за малым, а именно что бы был контекст (context) под звонящий номер в extensions.conf.

Допустим наш callback номер 84955556677 набрали с мобильного 89105647899 и ему разрешен callback (номер84955556677 указан в массиве  $permit_num в скрипте), то его контекст может выглядеть вот так:

[outgoing_to_89105647899]
exten => s,1,Set(CallbackNumTries=0)
exten => s,n,Set(CALLERID(num)="9998877")
exten => s,n(start),Background(vo-vvedite-ton-num-abonent)
exten => s,n,WaitExten(10)
exten => 100,1,Dial(SIP/8495${EXTEN}@sip-provider,120)
exten => _XXXXXXX,1,Dial(SIP/8495${EXTEN}@sip-provider,120)
exten => _8X.,1,Dial(SIP/${EXTEN}@sip-provider,120)
exten => i,1,Set(CallbackNumTries=$[${CallbackNumTries} + 1])
exten => i,n,Playback(vo-nomer-nabran-ne-verno)
exten => i,n,GotoIf($["${CallbackNumTries}" < "3"]?s|start)
exten => i,n,Playback(vo-dosvidaniya)
exten => t,1,Set(CallbackNumTries=$[${CallbackNumTries} + 1])
exten => t,n,GotoIf($["${CallbackNumTries}" < "3"]?s|start)
exten => t,n,Playback(vo-dosvidaniya)
exten => t,n,Hangup()
  • устанавливаем число попыток в ноль
  • выставляем АОН (под исх. звонок)
  • проигрываем записанный текст: «переведите ваш телефон в тональный набор…. бла… бла.. бла…»
  • 10 сек. ждем от человека набора номера
  • указываем возможный набор номеров: 100 (узнать время ;)), 7-ми значный номер, 8-рка и далее сколько угодно цифр
  • даем человеку три попытки на набор номера, если истек таймаут набора номера или номер был набран не верно, то человеку это озвучивается и кол-во попыток увеличивается на 1-цу и наше мини голосовое меню начинается сначала (возврат к метке start)
  • если кол-во попыток исчерпано, то Asterisk вешает трубку

З.Ы. При копировании статьи ссылка на источник ОБЯЗАТЕЛЬНА !

Автор: Николаев Дмитрий (virus (at) subnets.ru)

Ничего не понялТак себе...Не плохоДовольно интересноОтлично ! То что нужно ! (голосов: 19, среднее: 4,95 из 5)
Загрузка...
Отправить на почту Отправить на почту

Статья: Asterisk: автообзвон (auto-dial out) и обратный звонок (callback) с использованием AGI

Проблема

При организации функции callback на Asterisk`е, когда Asterisk перезванивает и ты пытаешься ввести тоном номер, то нажатые тобой цифры начинают задваиваться, а то и затраиваться.

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

Так же после многочисленных тестов стало точно понятно, что когда идет звонок из «города» на Asterisk, то подобных проблем не возникает, только если сам Asterisk звонит в «город».

VoIP соединение идет так:

E1 <—> Cisco AS5350 (c5350-js-mz.124-15.T11.bin) <—> Asterisk (версия 1.4.29_2)

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

Начали разбор полетов

Для того что бы выявить проблему стало понятно, что нужно подебажить DTMF на самом Asterisk. Как это сделать ?

Пока опыт работы с Asterisk не такой большой как хотелось бы, посему прибегнули к помощи гугла, через минут пять выяснили:

Открываем файл  logger.conf и там ищем строчку:

console => notice,warning,error

В нее дописывем dtmf, получаем:

console => notice,warning,error,dtmf

Сохраняем файл, входим в консоль Asterisk`а:

asterisk -r

И в консоле даем команду:

asterisk*CLI> logger reload

После чего, в той же консоле, задаем уровень дебага, я делал так:

asterisk*CLI> core set debug 3

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

[dtmf_test]
exten => s,1,Answer()
exten => s,n,Wait(1)
exten => s,n(collect),Read(digito,,11)
exten => s,n,SayDigits(${digito})
exten => s,n,GoTo(collect)
exten => s,n,Hangup

Т.е. поднимаем трубку, ждем ввода 11-ти цифр, а затем проговариваем все что набрали, собственно в этот контекст я перенаправил callback вызовы.

Подготовились, значит можно начинать.

Делаю callback на свою мобилку, начинаю давить цифири на мобиле, в консоле Астериска вижу:

[ДАТА] DTMF[5031]: channel.c:2351 __ast_read: DTMF begin '9' received on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2355 __ast_read: DTMF begin ignored '9' on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2283 __ast_read: DTMF end '9' received on SIP/gt-00000015, duration 352 ms
[ДАТА] DTMF[5031]: channel.c:2336 __ast_read: DTMF end passthrough '9' on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2351 __ast_read: DTMF begin '8' received on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2355 __ast_read: DTMF begin ignored '8' on SIP/gt-00000015
[ДАТА] DTMF[5031]: channel.c:2283 __ast_read: DTMF end '8' received on SIP/gt-00000015, duration 376 ms
[ДАТА] DTMF[5031]: channel.c:2336 __ast_read: DTMF end passthrough '8' on SIP/gt-00000015

и т.д. Во, то что надо, дебаг нажатия кнопок есть.

На одно нажатие в дебаге 4-ре строки. Чем дальше я смотрел в дебаг тем больше понимал, что я нажимаю цифирь один раз, а в дебаге она могла появиться и 2 и 3 раза (т.к. после одного нажатия появлялось более 4-х строк).

Смотрим что вообще мы можем «потрогать» в Астериске на тему DTMF.

Открываем файл sip.conf:

relaxdtmf=yes ; Relax dtmf handling
dtmfmode = rfc2833 ; Set default dtmfmode for sending DTMF. Default: rfc2833
 ; Other options:
 ; info : SIP INFO messages
 ; inband : Inband audio (requires 64 kbit codec -alaw, ulaw)
 ; auto : Use rfc2833 if offered, inband otherwise

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

Меняли режимы, ситуация не изменялась. Как работало через раз, так и продолжало работать.

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

Смотрим что же у нас указано в dial-peer:

dial-peer voice 23 voip
 description 4_outgoing_asterisk
 translation-profile incoming fake_aon
 answer-address 0010.....
 session protocol sipv2
 voice-class codec 20
 dtmf-relay rtp-nte  h245-signal h245-alphanumeric
 no vad

В voice-class перечислены кодеки:

voice class codec 20
 codec preference 1 g723r53
 codec preference 2 g723ar53
 codec preference 3 g723r63
 codec preference 4 g723ar63
 codec preference 5 g729r8
 codec preference 6 g729br8
 codec preference 7 gsmfr
 codec preference 8 g726r16
 codec preference 9 g726r24
 codec preference 10 g726r32
 codec preference 11 g711alaw
 codec preference 12 g711ulaw

Решили ужать выбор кодеков до alaw и ulaw, т.к. тот же режим inband работет только с этими кодеками.

Тоже самое сделали и на Asterisk, запретив использование всех кодеков кроме этих двух, для этого в sip.conf, в настройках peer`а, который смотрит на Cisco, указали:

disallow=all
allow = alaw
allow = ulaw

Снова стали менять режимы в sip.conf, пробовать звонить, пофиг, все как было так и осталось.

Полезли на Cisco.com -> Configuring SIP DTMF Features, в частности интересовали предлагаемый самой циской debug:

Verifying SIP DTMF Support

To verify SIP DTMF support, perform the following steps as appropriate (commands are listed in alphabetical order).

SUMMARY STEPS

1. show running-config
2. show sip-ua retry
3. show sip-ua statistics
4. show sip-ua status
5. show sip-ua timers
6. show voip rtp connections
7. show sip-ua calls

Благодаря команде show sip-ua calls видно какой режим DTMF выбран в данный момент:

Call 1
SIP Call ID                : 12abb76a79d610df282e2b237177bfe5@XX.XXX.XXX.XXX
   State of the call       : STATE_SENT_ALERTING (14)
   Substate of the call    : SUBSTATE_NONE (0)
   Calling Number          : 001000119
   Called Number           : 8916XXXXXXX
   Bit Flags               : 0xC0001C 0x100 0x404
   CC Call ID              : 22371
   Source IP Address (Sig ): XXX.XXX.XXX.XXX
   Destn SIP Req Addr:Port : XXX.XXX.XXX.XXX:5060
   Destn SIP Resp Addr:Port: XXX.XXX.XXX.XXX:5060
   Destination Name        : XXX.XXX.XXX.XXX
   Number of Media Streams : 1
   Number of Active Streams: 0
   RTP Fork Object         : 0x0
   Media Mode              : flow-through
   Media Stream 1
     State of the stream      : STREAM_ADDING
     Stream Call ID           : -1
     Stream Type              : voice+dtmf (1)
     Negotiated Codec         : g711alaw (160 bytes)
     Codec Payload Type       : 8
     Negotiated Dtmf-relay    : rtp-nte
     Dtmf-relay Payload Type  : 101
     Media Source IP Addr:Port: XXX.XXX.XXX.XXX:18936
     Media Dest IP Addr:Port  : XXX.XXX.XXX.XXX:14328
     Orig Media Dest IP Addr:Port : 0.0.0.0:0

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

В Инете (в частности на www.voip-info.org/wiki/view/Asterisk+DTMF) иногда народ советовал прям в dialplan указывать режим DTMF перед набором чего-либо, сделать это можно командой SIPdtmfmode:

SIPDtmfMode(inband|info|rfc2833)

Но это как то тоже не очень спасало. После многочасовых разборок решили глянуть, а что у Asterisk`а на тему vad есть.

Решение

В файле codecs.conf:

; voice activity detection [true / false]
; reduces bitrate when no voice detected, used only for CBR
; (implicit in VBR/ABR)
vad => true

Таксссс.. опять же народ в Инете, при разборках с DTMF, советует с первую очередь гасить vad к чертям, делаем это:

vad => false

Далее была обнаружена вот эта статья «Changing DTMF tone frequency in Asterisk«:

Changing the DTMF tones
The Asterisk module dsp.c contains the definitions for DTMF tones. Just look for a part of the source code that says:

static float dtmf_row[] =
{
    697.0,  770.0,  852.0,  941.0
};
static float dtmf_col[] =
{
    1209.0, 1336.0, 1477.0, 1633.0
};

And change that to:

static float dtmf_row[] =
{
        732.0,  809.0,  894.0, 988.0
        /* 697.0,  770.0,  852.0,  941.0 */
};
static float dtmf_col[] =
{
        1270.0, 1404.0, 1551.0, 1715.0
        /* 1209.0, 1336.0, 1477.0, 1633.0 */
};

This will raise all detected DTMF codes by some 40Hz, enough for Asterisk to become completely tone-blind to existing DTMF codes.


Once you made the change, you must recompile Asterisk by:

  • 1. Stopping Asterisk
  • 2. Go to your Asterisk source directory
  • 3. Enter make clean
  • 4. Enter make
  • 5. Enter make install

Note that you still can send Asterisk DTMF codes to transfer the call, start monitoring or what else — as long as you use the new DTMF tone matrix you just input. This is pretty easy to do with most industrial-grade call handling equipment.

«Ну что ж, не грех попробовать»  — сказали мы и выполнили как написано.

Диалпир на циске был приведен к виду:

dial-peer voice 23 voip
 description 4_outgoing_asterisk
 translation-profile incoming fake_aon
 answer-address 0010.....
 session protocol sipv2
 codec g711alaw
 dtmf-relay rtp-nte
 no vad

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

Я решил написать все это для того, что бы если кто-то тоже заморочится с этой темой и не будет знать как к этому подступиться, ну и если я вернусь к этому вопросу позднее, чтобы не вспоминать что уже было сделано :).

З.Ы. При копировании статьи ссылка на источник ОБЯЗАТЕЛЬНА ! Пожалуйста, уважайте чужой труд.

Авторы:  Панфилов Алексей (lehis (at) subnets.ru), Николаев Дмитрий (virus (at) subnets.ru)

Ничего не понялТак себе...Не плохоДовольно интересноОтлично ! То что нужно ! (голосов: 6, среднее: 5,00 из 5)
Загрузка...
Отправить на почту Отправить на почту

Появилась задача, организовать конференции в Asterisk.

Все кажется просто, поправить два конфига и вуаля, но на деле все оказалось не просто.

Читаем инструкцию Asterisk cmd MeetMe. Пробуем, получаем облом. Не работает. Почему ? Расскажу как было у меня:

посмотрим, что у нас в подгруженных в Asterisk модулях, для этого зайдем в его CLI:

/usr/local/sbin/asterisk -r

и выполним команду show modules:

Asterisk 1.4.23.1, Copyright (C) 1999 — 2008 Digium, Inc. and others.
Created by Mark Spencer <markster@digium.com>
Asterisk comes with ABSOLUTELY NO WARRANTY; type ‘core show warranty’ for details.
This is free software, with components licensed under the GNU General Public
License version 2 and other licenses; you are welcome to redistribute it under
certain conditions. Type ‘core show license’ for details.
=========================================================================
Connected to Asterisk 1.4.23.1 currently running on core (pid = 13061)

aster*CLI> show modules

у себя я обнаружил, что модуля app_meetme.so в списке нету….

можно выполнить и более предметную команду:

aster*CLI> module show like app_meetme

а в логах честно об этом написано:

pbx_extension_helper: No application ‘MeetMe’

Начинаем гуглить и копать. Выясняется, что для того, чтобы был этот модуль нужно собрать zaptel

Ну чтож… идем в порт asterisk`а, делаем:

  1. cd /usr/ports/net/asterisk
  2. make rmconfig
  3. make

выбираем в списке zaptel и после мейка делаем:

make install

в /usr/local/etc/rc.d появляется файл zaptel:

/usr/local/etc/rc.d/zaptel

дописываем в /etc/rc.conf:

zaptel_enable=»YES»

запускаем:

/usr/local/etc/rc.d/zaptel start

после этого проверяем наличие загруженных модулей zaptel.ko и ztdummy.ko:

/sbin/kldstat

Id Refs Address Size Name
………………
3    5 0xc4fb9000 32000    zaptel.ko
…………………
14 1 0xc62a2000 2000 ztdummy.ko

если не подгрузилось, то они лежат тут: /usr/local/lib/zaptel, подгрузите их руками.

проверяем, что в /usr/local/lib/asterisk/modules появился app_meetme.so.

открываем файл /usr/local/etc/asterisk/modules.conf и добавляем:

load => app_meetme.so

открываем /usr/local/etc/asterisk/meetme.conf и добавляем конференцию:

conf => 501

открываем /usr/local/etc/asterisk/extensions.conf и добавляем экстенш для того, что бы попадать в эту конференцию:

exten => 501,1,MeetMe(501)

т.е. при звонке на внутренний номер 501 мы должны попадать в конференцию с номером 501.

да, замечу, что номер exten и номер конференции могут не совпадать.

Ну чтож, вроде все хорошо и здорово, перезапускаем asterisk:

/usr/local/etc/rc.d/asterisk restart

звоним на номер 501 и слышим: «В настоящий момент вы единственный в этой конференции» и трубка вешается (происходит Hangup)

как говориться «приехали»…..

смотрим в логи и видим:

app_meetme.c:800 build_conf: Unable to open pseudo device

начинаем гуглить и толком ничего не находим. Кто-то так и не смог решить проблему, кто-то ремил куски кода в исходках.

Что бы мы не делали, тока менялись ошибки:

app_meetme.c:1022 conf_run: Unable to set flags: Inappropriate ioctl for device

или

app_meetme.c:1756 conf_run: Unable to set buffering information: Bad file descriptor

или

app_meetme.c:1777 conf_run: Error getting conference

или

app_meetme.c: Unable to set flags: Inappropriate ioctl for device

Вот последнее что удалось добиться:

WARNING[4670] app_meetme.c: Unable to set flags: Inappropriate ioctl for device
WARNING[4670] app_meetme.c: Unable to set buffering information: Bad file descriptor
WARNING[4670] app_meetme.c: Unable to set linear mode: Bad file descriptor
WARNING[4670] app_meetme.c: Error getting conference
WARNING[4670] app_meetme.c: Error setting conference
WARNING[4670] app_meetme.c: Error flushing channel
WARNING[4670] app_meetme.c: Failed to read frame: Bad file descriptor

конференция так и не заработала…

Изрядно подустав от этого дела, мы обнаружили что существует альтернатива для app_meetme.so и это app_conference.so.

Читаем Asterisk cmd Conference

Приступаем к инсталлу:

  1. cd /usr/ports/net/asterisk
  2. make extract
  3. cd work/asterisk-1.4.23.1
  4. fetch http://dfn.dl.sourceforge.net/sourceforge/appconference/appconference-2.0.1.tar.gz
  5. tar -zxf appconference-2.0.1.tar.gz
  6. cd appconference-2.0.1
  7. Правим файл Makefile, вот diff:
    --- Makefile    2008-02-26 19:05:57.000000000 +0300
    +++ Makefile.new        2009-02-10 21:03:09.000000000 +0300
    @@ -18,9 +18,9 @@
    #
    
    INSTALL_PREFIX :=
    -INSTALL_MODULES_DIR := $(INSTALL_PREFIX)/usr/lib/asterisk/modules
    +INSTALL_MODULES_DIR := $(INSTALL_PREFIX)/usr/local/lib/asterisk/modules
    
    -ASTERISK_INCLUDE_DIR ?= ../asterisk/include
    +ASTERISK_INCLUDE_DIR ?= /usr/local/include
    
    REVISION = $(shell svnversion -n .)
  8. gmake
  9. gmake install

убеждаемся что файл app_conference.so появился в /usr/local/lib/asterisk/modules/

открываем файл /usr/local/etc/asterisk/modules.conf и добавляем:

load => app_conference

открываем /usr/local/etc/asterisk/extensions.conf и добавляем экстенш для того, что бы попадать в конференцию:

exten => 502,1,Conference(502)

перегружаем asterisk и убеждаемся что модуль подгружен:

aster*CLI> module show like app_conference

Module                         Description                              Use Count
app_conference.so              Channel Independent Conference Applicati 0
1 modules loaded

Основное отличие app_meetme.so и это app_conference.so в том что app_conference.so создает конференцию налету (on the fly) и не требует наличия zaptel.

Экстеншеном 502 мы попадаем в автоматом созданную конференцию 502.

И все РАБОТАЕТ !

Но app_conference.so не полный аналог app_meetme.so. Например не поставить PIN на вход или так же просто записать разговор в конференции. Эти вопросы можно решить с помощью самого asterisk 😉

о PIN: Asterisk cmd Conference в разделе » Setting up conferences».

запись разговора в конференции: Asterisk cmd Monitor

пример записи конференции, extensions.conf :

exten => 502,1,Answer
exten => 502,2,Wait(1)
exten => 502,3,Monitor(wav,myfilename)
exten => 502,4,Conference(502,ps)

Записанные файлы myfilename-in.wav и myfilename-out.wav будут лежать в /var/spool/asterisk/monitor/

Удачных вам конференций !

З.Ы. При копировании статьи ссылка на источник ОБЯЗАТЕЛЬНА !

Авторы: Николаев Дмитрий (virus (at) subnets.ru) и Панфилов Алексей (lehis (at) subnets.ru)
Ничего не понялТак себе...Не плохоДовольно интересноОтлично ! То что нужно ! (голосов: 6, среднее: 4,50 из 5)
Загрузка...
Отправить на почту Отправить на почту

В качестве примера возьмем вариант с приветствием, 2-мя подменю (отдел продаж и тех. поддержки) и 3-мя попытками выбора.

При входящем звонке из города:

  1. Поднимаем трубку
  2. говорим приветствие
  3. нажмите 4-ре — отдел продаж
  4. нажмите 5 — отдел тех.поддержки

Выдержка из файла /usr/local/etc/asterisk/extensions.conf

[fromcity]
exten => s,1,Answer() ;Поднимаем трубку
exten => s,n,Background(hello) ;Запускаем приветствие
exten => s,n,Set(numTries=0) ;Выставляем кол-во попыток
exten => s,n(naberite),Background(naberite) ;Рассказываем о возможности набрать цифры 4 и 5
exten => s,n,WaitExten() ;Ждем ввода от пользователя
exten => 4,1,Goto(otdel-prodaj,s,1) ; Нажали 4-ре переходим на голосовое меню отдела продаж
exten => 5,1,Goto(supports,s,1) ;Нажали 5-ть — переходим на голосовое меню тех.подов
exten => i,1,Playback(pbx-invalid) ;Нажали не 4-ре и не 5-ть — говорим что ввод не верный
exten => i,n,Goto(s,naberite) ; Возвращаемся и повторяем сообщение о том какие кнопки можно нажимать
exten => t,1,Set(numTries=$[${numTries} + 1]) ; Увеличивает кол-во попыток на 1-цу при таймауте набора
exten => t,n,GotoIf($[«${numTries}» < «3»]?s|naberite) ;Пока кол-во потыток меньше 3-х повторяем сообщение о том какие кнопки можно нажимать
exten => t,n,Playback(bay) ;Кол-во попыток на таймаут израсходовано, прощаемся
exten => t,n,Hangup() ; Вешаем трубку

[otdel-prodaj]
exten => s,1,Playback(vi_nahodites_v_menu)
exten => s,n,Playback(otdela_prodag)
exten => s,n,Background(glavnoe_menu_nazmite_zvezdochka)
exten => s,n,Background(dlya_zaversheniya_nazmite_reshetka)
exten => s,n,WaitExten()
exten => *,1,Goto(fromcity,s,naberite)
;Нажали звездочку, выходим в главное меню
exten => #,1,Hangup() ;Нажали решетку — вешаем трубку
exten => i,1,Playback(pbx-invalid)
exten => i,n,Goto(s,1)
exten => t,1,Playback(bay)
exten => t,n,Hangup()

[supports]
exten => s,1,Playback(vi_nahodites_v_menu)
exten => s,n,Playback(otdela_supportov)
exten => s,n,Background(glavnoe_menu_nazmite_zvezdochka)
exten => s,n,Background(dlya_zaversheniya_nazmite_reshetka)
exten => s,n,WaitExten()
exten => *,1,Goto(fromcity,s,naberite)
exten => #,1,Hangup()
exten => i,1,Playback(pbx-invalid)
exten => i,n,Goto(s,1)
exten => t,1,Playback(bay)
exten => t,n,Hangup()

Вот так это работает. Вы можете создать ещё саб-менюхи.
В саб-менюхах (в примере это otdel-prodaj и supports) вы можете описывать новые саб-меню по нажаитию кнопок и т.д.

Главное чтобы саб-меню выступали как отдельные экстеншены.

Немаловажно помнить о том, что при проигрывании сообщения с помощью функции Playback нажатие каких либо клавиш игнорируются, «прослушка» нажатия клавиши от пользователя ТОЛЬКО при использовании функции Background.

Как записать сами голосовые файлы ?

Вариантов как минимум два:

  1. С помощью самого сервера Asterisk c помощью функции Record, сделать экстеншн (exten) под это дело.
    Пример:

    exten => 1111,1,Set(TIME="${STRFTIME(${EPOCH},,%C%y-%m-%d_%H-%M-%S)}")
    exten => 1111,n,Playback(beep)
    exten => 1111,n,Record(/usr/local/share/asterisk/sounds/record%d_${TIME}.gsm)
    exten => 1111,n,Playback(${RECORDED_FILE})
    exten => 1111,n,Hangup()

    записанный файл будет сохранен в директории /usr/local/share/asterisk/sounds/ и иметь название формата record_НОМЕР_ВРЕМЯ.gsm
    (или ещё вариант: такая возможность реализована в веб-интерфейсе asterisk-gui -> в FreeBSD /usr/ports/www/asterisk-gui -> сайт http://www.asterisknow.org/)

  2. Записать с помощью Windows recorder («Пуск»-«Программы»-«Стандартные» — «Развлечения и звукозапись»), выбираем параметры записи: Формат PCM, Mono, 8bit

Если вы записали файлы вторым способом, то для того чтобы Asterisk «понял» их необходимо перекодировать в формат gsm.

Это можно сделать утилитой sox (в FreeBSD /usr/ports/audio/sox)

sox input.wav -r 8000 -c 1 output.gsm resample -ql

если версия sox 14.3.0:

sox input.wav -r 8k -c 1 -e gsm output.gsm

где input.wav — записанный вами в Windows файл

output.gsm — файл для Asterisk на выходе, его потом нужно разместить в /usr/local/share/asterisk/sounds/

«Нарезать» wav файлы удобно с помощью программы Audacity

При копировании статьи ссылка на источник ОБЯЗАТЕЛЬНА !

Автор: Николаев Дмитрий (virus (at) subnets.ru)
Ничего не понялТак себе...Не плохоДовольно интересноОтлично ! То что нужно ! (голосов: 12, среднее: 4,67 из 5)
Загрузка...
Отправить на почту Отправить на почту