ADG Оставить заявку
Блог Системное администрирование 5 мин чтения

Asterisk на Debian и SIP-транк к Zadarma: как мы поднимали офисную телефонию

Пошагово: собираем Asterisk 1.4 из исходников на Debian Lenny, заводим SIP-транк к Zadarma, пишем диалплан и чиним односторонний звук из-за NAT. Реальная установка, а не пересказ мануала.

Контекст момента

IP-телефония на открытом Asterisk дешевеет и доходит до малого бизнеса, а SIP-операторы вроде Zadarma дают городской номер без железной АТС

К нам пришёл клиент с типовой задачей: пять менеджеров, один городской номер, и желание, чтобы звонки распределялись по людям, а не по принципу «кто первый добежал до трубки». Ставить коробочную АТС дорого и негибко. Значит, собираем IP-АТС сами на Asterisk, а городской номер и выход в город берём у SIP-оператора.

Сразу оговоримся: телефония - область, где «вроде работает» и «работает» разделяет пропасть. Звонок либо идёт с нормальным звуком, либо нет, и клиент это слышит немедленно. Поэтому здесь мы не спешим и не доверяем автоматике на слово.

Что берём

  • Debian 5.0 Lenny - свежая стабильная ветка. Берём именно stable: пакеты в ней заморожены, прилетают только заплатки безопасности, а не внезапные мажорные обновления посреди рабочего дня.
  • Asterisk из ветки 1.4 - проверенная стабильная линейка. Ставим не из репозитория, а собираем из исходников: так мы держим конкретную версию под контролем и не завязаны на то, что заморожено в пакетах Lenny.
  • Никаких плат расширения и аналоговых линий: связь с городом - только через SIP-транк к оператору, всё по сети.

Собираем Asterisk из исходников

Ставим то, чем собирать (сам Asterisk из пакетов не тянем):

apt-get update
apt-get install build-essential libncurses5-dev libssl-dev libxml2-dev wget

Качаем исходники ветки 1.4, распаковываем и собираем:

cd /usr/src
wget http://downloads.asterisk.org/pub/telephony/asterisk/releases/asterisk-1.4.24.tar.gz
tar xzf asterisk-1.4.24.tar.gz
cd asterisk-1.4.24
./configure
make menuselect
make
make install
make samples
make config

make menuselect - это меню сборки: тут проверяем, что включены нужные кодеки и модуль chan_sip. make samples кладёт в /etc/asterisk конфиги с примерами, make config ставит init-скрипт. Запускаем и заходим в консоль:

/etc/init.d/asterisk start
asterisk -rvvv

Если консоль открылась и не сыплет ошибками - основа живёт. Дефолтные примеры конфигов мы на боевом сервере не оставляем: они щедро открывают то, что открывать не надо, поэтому sip.conf и extensions.conf пишем с нуля под себя.

Заводим SIP-транк к Zadarma

Логин, пароль и адрес SIP-сервера берём в личном кабинете оператора. Общие настройки и регистрацию описываем в sip.conf:

[general]
context=default
bindaddr=0.0.0.0
bindport=5060
disallow=all
allow=alaw
allow=ulaw
nat=yes
externip=НАШ.БЕЛЫЙ.IP
localnet=192.168.10.0/255.255.255.0

register => SIP-ЛОГИН:ПАРОЛЬ@sip.zadarma.com

Дальше - сам транк отдельной секцией:

[zadarma]
type=peer
host=sip.zadarma.com
fromdomain=sip.zadarma.com
username=SIP-ЛОГИН
fromuser=SIP-ЛОГИН
secret=ПАРОЛЬ
insecure=port,invite
context=from-zadarma
qualify=yes
nat=yes
disallow=all
allow=alaw

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

asterisk -rx "sip reload"
asterisk -rx "sip show registry"

В выводе напротив sip.zadarma.com должно стоять Registered. Если висит Request Sent или Auth. Sent - значит, оператор нас не пускает: чаще всего перепутан логин, пароль или наш внешний адрес ещё не прописан у него в кабинете, и мы полчаса смотрим в лог, где английским по чёрному написано 403 Forbidden.

Внутренние телефоны

Каждому менеджеру - свой внутренний номер. В тот же sip.conf:

[1001]
type=friend
host=dynamic
secret=СЛОЖНЫЙ_ПАРОЛЬ
context=office
nat=yes
qualify=yes

[1002]
type=friend
host=dynamic
secret=ДРУГОЙ_ПАРОЛЬ
context=office
nat=yes
qualify=yes

host=dynamic означает, что телефон сам регистрируется на сервере с того адреса, где стоит. Пароли ставим длинные и разные: открытый в интернет SIP-порт сканируют перебором постоянно, и слабый пароль внутреннего номера - это чужие звонки за наш счёт.

Диалплан: кто куда звонит

Логику звонков пишем в extensions.conf. Один контекст для внутренних и исходящих, другой - для входящих с города.

[office]
; внутренние: набрал номер коллеги - позвонил коллеге
exten => 1001,1,Dial(SIP/1001,20)
exten => 1002,1,Dial(SIP/1002,20)

; выход в город: 9 и городской номер
exten => _9.,1,Dial(SIP/zadarma/${EXTEN:1},60)
exten => _9.,n,Hangup()

[from-zadarma]
; входящий с города звонит сразу всем менеджерам
exten => s,1,Dial(SIP/1001&SIP/1002,25)
exten => s,n,Hangup()

Разберём ключевое. Шаблон _9. ловит всё, что начинается с девятки, а ${EXTEN:1} отрезает эту девятку и отдаёт оператору чистый номер. Входящий звонок в контексте from-zadarma через Dial(SIP/1001&SIP/1002,25) звонит на оба телефона сразу - кто снял, тот и говорит. Перечитываем диалплан и проверяем:

asterisk -rx "dialplan reload"
asterisk -rx "sip show peers"
graph LR A[Менеджеры
SIP-телефоны] --> B[Asterisk 1.4
Debian Lenny] B -->|SIP-транк| C[Zadarma] C --> D[Городская
телефонная сеть]

Где встряли на день: односторонний звук

Вечер ушёл на сборку и настройку. День - на одну проблему: звонок соединяется, гудки идут, трубку снимают, а дальше в одну сторону тишина. Один слышит, второй нет. Классика.

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

  1. Явно указать серверу его внешний адрес - это externip и localnet в [general], которые мы уже прописали. Без них Asterisk сообщает оператору внутренний адрес вида 192.168.x.x, и обратный голосовой поток уходит в никуда.
  2. Задать диапазон RTP-портов в rtp.conf (по умолчанию rtpstart=10000, rtpend=20000) и пробросить этот диапазон UDP на шлюзе на машину с Asterisk.
  3. Не надеяться на автоопределение адреса. Ровно из-за этой надежды мы и потеряли полдня: казалось, что сервер сам разберётся, кто он снаружи. Не разберётся.

К вечеру второго дня телефония работала: входящие распределялись по менеджерам, исходящие уходили через оператора, звук был чистым в обе стороны. Отдельно мы свели телефонию с их системой учёта, чтобы карточка клиента открывалась на входящем - такие стыковки разных систем и превращают «телефонию» в рабочий инструмент, а не просто в звонящий ящик.

Вывод без пафоса: поднять Asterisk - это вечер. Заставить голос ходить чисто через NAT - это отдельный навык, который окупается ровно один раз, когда клиент не слышит бульканья в трубке. К слову, привычку сразу фиксировать, за что отвечаем мы, а за что канал и оператор, мы завели ещё на одном сервере в подсобке несколькими годами раньше.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.