Поднимает телефонию с нуля: Asterisk, FreePBX, GSM-шлюз на Huawei E173 в Debian



Сначала маленькая предыстория. Не так давно наша фирма практически лишилась городской связи, один телефонный оператор, что-то не поделил с другим и в результате между ними перестали проходить звонки. Было принято решение, раз уж так произошло полностью отказаться от обычной телефонной связи и полностью перейти на ip-телефонию.
Постановка задачи:
1) Организовать телефонную связь;
2) Запись разговоров;
3) Очередь звонков;
4) Голосовое меню;
5) GSM-шлюз, так-как должны обрабатываться и звонки с мобильных операторов.
6) Минимальная стоимость решения, так как ситуация форс-мажорная и бюджет выделен не был.

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


Выбор платформы.

Первым делом решил посмотреть готовые сборки, указанные на сайте asterisk.ru, были скачаны готовые образы AsteriskNOW, FreePBX, Elastix, про остальные просто прочитана документация. TrixBox был сразу откинут из-за своей платности, так как противоречил 6 пункту. AsteriskNOW показался сыроватым и не доработанным, FreePBX, Elastix понравились оба, логичные и удобные сборки, но не захотели дружить с имеющимся в наличии модемом Huawei E173, а также были собраны на CentOS с достаточно старым ядром и не вписывались в общий парк серверов на Debian. Принял решение собирать все с нуля, тем самым получив бесценный опыт.

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

Итак имеем свежеустановленный Debian 6 Squeeze, минимальная установка.
Добавляем необходимые в дальнейшем репозитории в
 /etc/apt/sources.list

deb http://backports.debian.org/debian-backports squeeze-backports main contrib non-free
deb http://www.deb-multimedia.org stable main non-free
deb http://packages.dotdeb.org squeeze all
deb-src http://packages.dotdeb.org squeeze all
deb http://repos.zend.com/zend-server/deb server non-free

Устанавливаем ключи
apt-get update && apt-get install deb-multimedia-keyring
wget http://www.dotdeb.org/dotdeb.gpg -O- |apt-key add -
wget http://repos.zend.com/zend.key -O- |apt-key add -

Обнобляемся.
apt-get update && apt-get upgrade

Из бэкпортов ставим свежее ядро, которое необходимо для корректной работы GSM модема
apt-get install -t squeeze-backports linux-image-3.2.0-0.bpo.3-amd64
apt-get install -t squeeze-backports linux-headers-3.2.0-0.bpo.3-amd64

Перезагружаемся
reboot

Ставим web сервер.

Так как нагрузка на веб сервер планируется разовая и небольшая, было лень ставить отдельно apache + php + нужные модули, решил воспользоваться неплохой, на мой взгляд, сборкой Zend Server CE.
Ставить будем все и сразу.
aptitude install zend-server-ce-php-5.3 php-5.3-source-zend-server control-panel-zend-server bison libaudiofile-dev libssl-dev checkinstall mpg123 libmpg123-0 libmpg123-dev xmms2-plugin-mpg123 mysql-server libmysqlclient15-dev php-db php-pear sox curl g++ libncurses-dev libxml2-dev subversion libspandsp-dev lame libmp3lame-dev

Настройка веб-сервера Zend
echo "PATH=$PATH:/usr/local/zend/bin" >> /etc/profile
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/zend/lib" >> /etc/profile
source /etc/profile
chown zend:adm -R /var/log/apache2/
mkdir /var/www/freepbx/
adduser asterisk --disabled-password --gecos "Asterisk PBX"

Изменяем пользователя из под которого работает апач, на asterisk.
sed -i "s/\(^User *\)\(.*\)/\1asterisk/" /etc/apache2/apache2.conf
sed -i "s/\(^Group *\)\(.*\)/\1asterisk/" /etc/apache2/apache2.conf


Изменяем параметры php (можно через специальную админку сервера, доступную по ссылке _https://IP:10082/ZendServer или _http://IP:10081/ZendServer.).
post_max_size = 32M
max_execution_time = 60
max_input_time = 60
memory_limit = 256M
upload_max_filesize = 16M
date.timezone = "Europe/Kiev"


Скачиваем необходимые исходники

cd /tmp
wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-1.8.15.1.tar.gz
tar xvzf asterisk-1.8.15.1.tar.gz
wget http://mirror.freepbx.org/freepbx-2.9.0.tar.gz
tar xvzf freepbx-2.9.0.tar.gz
wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-1.4.12.tar.gz
tar xvzf libpri-1.4.12.tar.gz
wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-complete-2.6.1+2.6.1.tar.gz
tar xvzf dahdi-linux-complete-2.6.1+2.6.1.tar.gz


Собираем их для удобства дальнейшего обновления сразу в пакеты.
cd libpri-1.4.12/
make
checkinstall -D

cd /tmp/dahdi-linux-complete-2.6.1+2.6.1/
make all
mkdir /etc/hotplug
mkdir /etc/hotplug/usb/
mkdir /etc/dahdi
checkinstall -D
make config

Отключаем ненужные модули, вообще мне dahdi был не нужен, но на форумах и в документации советуют все равно собирать с ним.
nano /etc/dahdi/modules
/etc/init.d/dahdi start

cd /tmp/asterisk-1.8.15.1/

если планируем включить mp3 выполняем
./contrib/scripts/get_mp3_source.sh

если нет, сразу
./configure
make menuselect

Включаем в menuconfig следующие опции;
app_mysql, app_saycountpl, cdr_mysql, format_mp3, res_config_mysql, EXTRAS-SOUNDS-EN-GSM EXTRAS-SOUNDS-RU-GSM (нужные кодеки и языки) ну и другие нужные опции.

make
checkinstall -D
make config
make samples

Если получили ошибку не существующей директории
mkdir /var/lib/asterisk/phoneprov

и снова
make samples


Создаем и заполняем базу данных необходимую для FreePBX
cd /tmp/freepbx-2.9.0
mysqladmin -uroot create asterisk -p'Password'
mysqladmin -uroot create asteriskcdrdb -p'Password'
mysql -uroot -p'Password' asterisk < SQL/newinstall.sql
mysql -uroot -p'Password' asteriskcdrdb < SQL/cdr_mysql_table.sql

mysql -uroot -pPassword # Password - Ваш пароль для рутового пользователя MySQL

GRANT ALL PRIVILEGES ON asteriskcdrdb.* TO asteriskuser@localhost IDENTIFIED BY 'amp109'; # amp109 - Ваш пароль для пользователя asteriskuser в MySQL
GRANT ALL PRIVILEGES ON asterisk.* TO asteriskuser@localhost IDENTIFIED BY 'amp109'; # amp109 - Ваш пароль для пользователя asteriskuser в MySQL
flush privileges;
quit;

Запускаем Астериск перед установкой FreePBX
/etc/init.d/asterisk start


Конфигурируем FreePBX для работы с Asterisk:
cd /tmp/freepbx-2.9.0
pear install DB
./install_amp

Используем все параметры по умолчанию только путь задаем /var/www/freepbx/, который мы создали ранее.

Теперь небольшое отступление, на сайте FreePBX доступна версия freepbx-2.10.0, но ее инсталятор под Debian вел себя очень странно, пришлось наложить несколько патчей из багрепортов, но дальнейшее его поведение также не понравилось и было принято решение использовать freepbx-2.9.0 для установки, а потом обновиться. После успешной установки заходим на веб интерфейс по адресу _http://IP-сервера/freepbx и обновляем систему, процесс обновления хорошо описан в самом интерфейсе и вынесена отдельная ссылка, так что подробно останавливаться на этом не буду, обновление проходит быстро и гладко и через 10 минут имеем у себя последнюю версию системы.

Прикручиваем модем huaway E173

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

Для определения вменяемого имени модема

apt-get install -t squeeze-backports usb-modeswitch usb-modeswitch-data

Вставляем модем и выполняем
 dmesg | tail

Получаем вывод похожий на
[  303.594149] usb 1-7: New USB device found, idVendor=12d1, idProduct=1001
[  303.594155] usb 1-7: New USB device strings: Mfr=3, Product=2, SerialNumber=0
[  303.594158] usb 1-7: Product: HUAWEI Mobile
[  303.594161] usb 1-7: Manufacturer: HUAWEI Technology
[  303.596731] option 1-7:1.0: GSM modem(1-port) converter detected
[  303.596968] usb 1-7: GSM modem (1-port) converter now attached to ttyUSB0
[  303.597241] option 1-7:1.1: GSM modem (1-port) converter detected
[  303.597373] usb 1-7: GSM modem (1-port) converter now attached to ttyUSB1
[  303.597584] option 1-7:1.2: GSM modem (1-port) converter detected
[  303.597716] usb 1-7: GSM modem (1-port) converter now attached to ttyUSB2


Если не заработало, выясняем идентификатор устройства:
 lsusb

  Bus 002 Device 050: ID 12d1:140c Huawei Technologies Co., Ltd.


Проверяем наличие файла «12d1:*» в /etc/usb_modeswitch.d, в одном из файлов
должно быть упоминание продукта «1446». Например:

# Huawei E270+  (HSPA+ modem)
   DefaultVendor= 0x12d1
   DefaultProduct=0x1446

   TargetVendor=  0x12d1
   TargetProductList="1001,1406,140c,14ac"

   CheckSuccess=20

   MessageContent="55534243123456780000000000000011060000000000000000000000000000"


Если файла нет, то его можно создать по вышеприведенному примеру, просто изменив DefaultProduct на:
DefaultProduct= 0x140c

Перегружаемся, после чего модем имеет вменяемое имя, продолжаем связывать его с Asterisk

svn co https://www.makhutov.org/svn/chan_datacard/trunk/ /tmp/chan_datacard
cd /tmp/chan_datacard
automake
./configure
cp etc/datacard.conf /etc/asterisk/


Настраиваем параметры модуля под наш модем:
nano /etc/asterisk/datacard.conf


в самом низу конфигурационного файла удаляем все данные (Ctrl+k) после последней черты и вставляем данный конфиг
[000101]
context=from-gsm ; context для входящих звонков
audio=/dev/ttyUSB1 ; tty порт для аудио подключения
data=/dev/ttyUSB2 ; tty порт для управляющих AT комманд модема
group=1 ; Группа вызова
rxgain=10 ; Изменение громкости динамика
txgain=-5 ; Изменение громкости микрофона
autodeletesms=yes ; auto delete incoming sms
resetdatacard=yes ; reset datacard during initialization
u2diag=256 ; set U2DIAG parameter (256 = включить модем и кард ридер)
usecallingpres=yes ; use the caller ID presentation or not
callingpres=allowed_passed_screen ; set caller ID presentation

записываем изменения Ctrl+O и выходим из редактора nano Ctrl+X

Создаем контент в диалплане (Не забываем выключить пинкод на SIM):
nano /etc/asterisk/extensions_custom.conf

[from-gsm]
exten => s,1,Set(CALLERID(all)=${CALLERID(num)})
exten => s,n,Set(CALLERID(num)=8${CALLERID(num):2})
exten => s,n,goto(from-trunk,${IMEI},1)

Перезапускаем Asterisk
service asterisk restart

Проверка состояния модема:
asterisk -r

datacard show devices

cam*CLI> datacard show devices
ID           Group State      RSSI Mode Submode Provider Name  Model      Firmware          IMEI             IMSI             Number        
000101       1     Free       23   0    0       DJUICE         E173       11.126.16.04.174  867767ХХХХХХХ  255030580735317  +38097ХХХХХХХ 

Теперь в админке FreePBX добавляем маршруты для этого модема.

Исходящий маршрут:
В веб интерфейсе (FreePBX 2.10) — Connectivity — > Trunks -> Add Custom Trunk
Trunk name — Пишем имя чтоб не забыть например GSM-modem
Последний пункт — Custom dial string — указать
datacard/i:00000000000000/$OUTNUM$

где 0000000000000 — IMEI модема (виден в предыдущем пункте).

В веб интерфейсе (FreePBX 2.10) — Connectivity -> Outbound routes -> ADD route
Назвать например Outbound (Исходящий)
match patern ->. (ставим точку в это поле),
в Trunk Sequence for Matched Routes выбираем наш транк.

Входящий маршрут:
В веб интерфейсе (FreePBX 2.10) — Connectivity -> Inbound routes -> ADD Incoming route
Назвать например Inbound (Входящий)
Номер DID -> 0000000000000 (IMEI модема)
в 'Set destination' выбрать получателя звонков, поступающих на модем.

Включаем русскоязычную озвучку для протоколов, например для SIP, через WEB-интерфейс
Settings -> Asterisk SIP Settings -> language -> ru

Создаем скрипт автозапуска FreePBX: /etc/init.d/amportal-startup
#!/bin/sh
# /etc/init.d/amportal-startup
#
### BEGIN INIT INFO
# Provides:          Asterisk
# Required-Start:    $remote_fs $syslog $all
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start Asterisk at boot time
# Description:       Enable Asterisk.
### END INIT INFO
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
export PATH
case "$1" in
  start)
        amportal start
    ;;
  stop)
        amportal stop
    ;;
  *)
    echo "Usage: /etc/init.d/amportal-startup {start|stop}"
    exit 1
    ;;
esac
 
exit 0


Даем ему права на выполнение
chmod +x /etc/init.d/amportal-startup

Добавляем в автозагрузку.
insserv amportal-startup


FreePBX частично переведен на русский язык, но его включение у меня изначально не работало, чтоб его починить проделываем следующие манипуляции.
Исправляем файлик /usr/share/locale/locale.alias

Удаляем строку с кодировкой для russian и добавляем 3 строки вместо нее:
russian         ru
ru              ru_RU
ru_RU           ru_RU.UTF-8

затем перегенерируем локаль
locale-gen ru_RU.utf8


и все начинает работать.

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

Для настройки использовал документацию с сайтов FreePBX, asterisk-pbx, blog.911.in.ua, официальная документация проектов и поисковые системы.

UPD. Продолжение от моего коллеги.
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 26

    0
    а что на картинке такое прикольно? =)
      0
      На картинке стимпанк мобильного телефона.
      0
      Что же сказать? Это «зачет»! Спасибо.
        0
        а чем обусловлен выбор datacard вместо chan_dongle?
          0
          Ничем, скачал оба варианта, с первым же заработало без нареканий и сразу, а в чем преимущество chan_dongle читал, что произошел от datacard, но выраженных плюсов не увидел.
            0
            Огромнейший плюс — disovery. Можно вместо пачки ttyUSB* (а они ведь и местами поменяться могут, и поменяются) вписать imsi и/или imei, dongle сам найдет, где какой модем.
              0
              В следующий раз буду иметь в виду, я и не лазил на тот сервер больше с момента поднятия, работает нормально, если что отвалится — попробую для интереса disovery, а пока просто лень.
          –1
          хм отлично!
          • НЛО прилетело и опубликовало эту надпись здесь
              0
              Укажите — исправлю.
              • НЛО прилетело и опубликовало эту надпись здесь
                  +1
                  Проверка орфографии включена в браузере, к сожалению грамотная письменная речь не мой конек, практики мало. В дальнейшем постараюсь исправиться.
              0
              Я немного не в теме, поэтому вопрос слегка ламерский. Правильно ли я понимаю, что USB-модем — это выход во внешний мир? Т.е. вызовы на городские и мобильные номера пойдут через него?
                0
                Ну вообще в статье описан вариант создания дешевого GSM шлюза. Через него можно пустить и городские и сотовые без проблем.

                З.Ы. Вот уж не знаю почему ТС выбрал chan datacard — но определенно по стабильности работы больше понравился именно chan_dongle.
                  0
                  Городские номера получили через sip-транк, там ничего примечательного в настройке нет, заполнить 5 строк, выданных sip провайдером и готово. Про настройку остальных полезных функций, таких как очереди звонков, голосовое меню, запись и т.п напишу отдельно, как будет устоявшийся вариант. Сейчас эти настройки постоянно меняются, пытаюсь подобрать оптимальные.
                  0
                  Большое спасибо за подробное описание, давно уже руки чесались разобраться с Asterisk!

                  С нетерпением жду продолжения (плюсонуть статью не могу ввиду низкой кармы).

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

                  Если будете использовать в будущем распределение исходящего трафика на разные модемы (для экономии на звонках, с Life на Life, с Djuce на Djuce и т.д.) будет также интересно посмотреть на правила Asterisk.
                    0
                    Ничего сложного нету. Просто в диалплане можно использовать нечто схожее с:

                    [outgoing_calls_mobile]
                    exten => _050XXXXXXX,1,Dial(${GSM_MTS}/${EXTEN},60,tT)		; МТС
                    exten => _050XXXXXXX,n,Hangup()
                    exten => _066XXXXXXX,1,Dial(${GSM_MTS}/${EXTEN},60,tT)		; МТС
                    exten => _066XXXXXXX,n,Hangup()
                    exten => _095XXXXXXX,1,Dial(${GSM_MTS}/${EXTEN},60,tT)		; МТС
                    exten => _095XXXXXXX,n,Hangup()
                    exten => _099XXXXXXX,1,Dial(${GSM_MTS}/${EXTEN},60,tT)		; МТС
                    exten => _099XXXXXXX,n,Hangup()
                    exten => _067XXXXXXX,1,Dial(${GSM_KS}/${EXTEN},60,tT)		; Киевстар
                    exten => _067XXXXXXX,n,Hangup()
                    exten => _068XXXXXXX,1,Dial(${GSM_KS}/${EXTEN},60,tT)		; Киевстар
                    exten => _068XXXXXXX,n,Hangup()
                    exten => _096XXXXXXX,1,Dial(${GSM_KS}/${EXTEN},60,tT)		; Киевстар
                    exten => _096XXXXXXX,n,Hangup()
                    exten => _097XXXXXXX,1,Dial(${GSM_KS}/${EXTEN},60,tT)		; Киевстар
                    exten => _097XXXXXXX,n,Hangup()
                    exten => _098XXXXXXX,1,Dial(${GSM_KS}/${EXTEN},60,tT)		; Киевстар
                    exten => _098XXXXXXX,n,Hangup()
                    


                    Ну и так далее в том же духе.

                    Ну а сами глобальные переменные GSM_MTS, GSM_KS указываем в [globals] как:
                    [globals]
                    GSM_KS = DAHDI/1
                    GSM_MTS = DAHDI/2
                    

                    Это, конечно, при условии правки конфигов напрямую.
                      0
                      О!!! Супер! Огромное спасибо за оперативность. Осталось только узнать как оно под нагрузкой будет и про железо подробнее.
                        0
                        Относительно нагрузки — это уже зависит от необходимого количества одновременных вызовов и еще нескольких факторов. Подробнее можете почитать тут.
                        0
                        У меня похоже, но немного не так:
                        [macro-gsm-out]
                        exten => s,1,ChanIsAvail(Dongle/${ARG2},j)
                        exten => s,2,Dial(Dongle/${ARG2}/${ARG1},,T)
                        exten => s,3,Hangup()
                        
                        [outer-call]
                        exten => _068XXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_bl)
                        
                        exten => _050XXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_mt)
                        exten => _066XXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_mt)
                        exten => _095XXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_mt)
                        exten => _099XXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_mt)
                        
                        exten => _067XXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_ks)
                        exten => _096XXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_ks)
                        exten => _097XXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_ks)
                        exten => _098XXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_ks)
                        
                        exten => _0XXXXXXXXX,1,Macro(gsm-out,${EXTEN:-10},gsm_ks)
                        
                        exten => _+380XXXXXXXXX,1,Goto(${EXTEN:-10},1)
                        exten => _380XXXXXXXXX,1,Goto(${EXTEN:-10},1)
                        exten => _80XXXXXXXXX,1,Goto(${EXTEN:-10},1)
                        exten => _XXXXXXXXX,1,Goto(0${EXTEN:-9},1)
                        
                        


                        Сейчас ищу, как ставить исходящие звонки в очередь, если Dongle занят.
                      0
                      Для Drupal недавно появился модуль VoIP Drupal обещают много вкусностей. В совокупности с другими модулями drupal(CRM, LDAP) можно сделать неплохую платформу.
                        0
                        У самого стоит подобная задача, после беглого чтения статьи, да и вообще изучения темы на просторах инета сразу возникает вопрос: зачем собирать из сырцов (тут хоть деб пакеты через чекинсталл сделаны), если в репах есть готовые пакеты, которые считаются стабильными для текущей версии ОС? Плюс не понятен момент с апачем, который работает от астериска…
                          0
                          Из сырцов собирают по 3м причинам:
                          1) Хочется текущую версию, вот прямо сейчас.
                          2) Нужны некоторые опции сборки, которые отсутствуют в версиях из репозиториев.
                          3) Несовместимость некоторых компонентов между собой в версиях из репов. (Как пример попробуйте одновременно поставить percona и ZendServer используя только версии из репозиториев).
                          А в чем собственно проблема? Я много собираю из репов и перекладываю в свой реп, для личного пользования. Чем это хуже чем подключать чужие и угадывать при какой фазе луны и с какими опциями собирался нужный пакет. При общей стабильности системы, стабильность некоторых компонентов не настолько критична, как появившийся функционал.
                          Апач работает от asterisk для того, чтобы FreePBX мог полностью управлять астером. Можно использовать apache2-mpm-itk, можно дать пользователю www-data права на asterisk, можно запилить отдельный пул для nginx — тут кому что роднее.
                          0
                          adduser asterisk --disabled-password --gecos «Asterisk PBX

                          Вы в этой строчке кавычку забыли. Исправьте пожалуйста.
                            0
                            Подправил спасибо, хотя не уверен что статья еще актуальна, год прошел, возможно все поменялось уже. Хотя телефония, на основе которой писалась статья, все еще работает.
                            0
                            Актуальна, собрал по ней астериска без особых трудностей.

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

                            Самое читаемое