Основы IP-телефонии: Практическое руководство по Asterisk на Ubuntu 22.04

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

Основы VoIP и протоколы SIP с PJSIP

Традиционная телефония десятилетиями опиралась на выделенные медные линии. Когда вы звонили в другой город, телефонная станция физически замыкала цепь между вашим аппаратом и аппаратом собеседника. Эта технология надежна, но крайне неэффективна: пока вы молчите, линия все равно занята, а прокладка кабелей стоит огромных денег.

IP-телефония (или VoIP — Voice over Internet Protocol) решает эту проблему, превращая человеческий голос в цифровые данные. Вместо удержания выделенной линии, голос сжимается, нарезается на мелкие кусочки (пакеты) и отправляется через интернет точно так же, как электронные письма или веб-страницы.

Представьте, что вы отправляете книгу по почте. В традиционной телефонии вам пришлось бы арендовать целый поезд, чтобы отвезти одну книгу. В IP-телефонии вы разрываете книгу на страницы, кладете каждую в отдельный конверт и отправляете обычной почтой. На стороне получателя страницы снова собираются в книгу. Если пара конвертов придет с задержкой, получатель все равно поймет смысл.

Такой подход кардинально снижает стоимость связи. Для расчета объема передаваемых данных в VoIP используется простая формула:

V=R×tV = R \times t

Где VV — итоговый объем данных в килобайтах, RR — скорость потока данных выбранного кодека (например, около 10 килобайт в секунду для стандартного кодека G.711), а tt — время разговора в секундах.

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

Разделение труда: протоколы SIP и RTP

Чтобы два устройства могли поговорить через интернет, им нужно договориться о правилах. В VoIP эти правила разделены на две независимые части: управление вызовом и передача самого голоса.

SIP (Session Initiation Protocol) — это протокол установления сеанса. Он не передает звук. Его единственная задача — найти абонента, сообщить ему о звонке, договориться о том, как именно будет передаваться голос, и завершить звонок, когда кто-то положит трубку.

RTP (Real-Time Transport Protocol) — это транспортный протокол реального времени. Именно он переносит пакеты с вашим голосом от одного устройства к другому после того, как SIP выполнил свою работу.

SIP — это администратор в ресторане. Он встречает вас, проверяет бронь, провожает к столику и уходит. Он не готовит еду и не кормит вас. Еда, которую вам приносят официанты — это RTP.

tools.ietf.org

Программная АТС Asterisk и драйвер PJSIP

Чтобы управлять десятками или тысячами звонков, маршрутизировать их, записывать разговоры и создавать голосовые меню, нужен центральный мозг. Таким мозгом выступает Asterisk — самая популярная в мире программная АТС (Private Branch Exchange, PBX) с открытым исходным кодом.

Исторически в Asterisk использовался модуль chan_sip для работы с протоколом SIP. Однако со временем протокол усложнялся, и старый модуль перестал справляться с современными требованиями. Ему на смену пришел PJSIP — современный, модульный и высокопроизводительный стек.

Главное отличие PJSIP от предшественника заключается в его архитектуре. Если раньше все настройки абонента сваливались в одну кучу, то PJSIP разделяет конфигурацию на логические блоки:

  • Endpoint (Конечная точка) — базовый профиль устройства (кодеки, таймеры, функции)
  • Auth (Авторизация) — логин и пароль для подключения
  • AOR (Address of Record) — адресная книга, которая знает, какой IP-адрес сейчас у устройства
Характеристика Старый chan_sip Новый PJSIP
Архитектура Монолитная (все в одном файле) Модульная (разделение на Endpoint, Auth, AOR)
Поддержка устройств Одно устройство на один аккаунт Несколько устройств на один аккаунт (например, телефон на столе и приложение в смартфоне)
Статус Устарел (Deprecated) Активно развивается и поддерживается

Подготовка сервера Ubuntu 22.04

Любая надежная система IP-телефонии начинается с правильно подготовленного фундамента. Мы будем использовать операционную систему Ubuntu 22.04 LTS.

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

Откройте терминал вашего сервера и выполните команду обновления:

sudo apt update && sudo apt upgrade -y

После завершения обновления установите базовые зависимости. Этот процесс может занять несколько минут:

sudo apt install -y build-essential wget libssl-dev libncurses5-dev \
libnewt-dev libxml2-dev linux-headers-$(uname -r) libsqlite3-dev \
uuid-dev libjansson-dev

Каждая из этих библиотек выполняет свою роль. Например, libssl-dev нужна для шифрования звонков, а libjansson-dev позволяет Asterisk работать с форматом данных JSON, который активно используется в современных веб-интеграциях.

Установка Asterisk из исходного кода

Хотя Asterisk можно установить из стандартных репозиториев Ubuntu одной командой, в профессиональной среде его всегда собирают из исходного кода. Это дает полный контроль над тем, какие модули будут включены в систему, и позволяет использовать самую свежую стабильную версию.

Перейдите в директорию для загрузки исходников и скачайте архив с 20-й версией Asterisk (текущая LTS-версия):

cd /usr/src
sudo wget https://downloads.asterisk.org/pub/telephony/asterisk/asterisk-20-current.tar.gz

Распакуйте скачанный архив и перейдите в созданную папку:

sudo tar xvf asterisk-20-current.tar.gz
cd asterisk-20.*

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

sudo contrib/scripts/install_prereq install

Теперь запустите конфигуратор:

sudo ./configure

Если конфигурация прошла успешно, вы увидите на экране логотип Asterisk, нарисованный символами ASCII. Это значит, что система готова к сборке.

Запустите процесс компиляции. Команда make переведет исходный код на языке C в исполняемые бинарные файлы. Это самая ресурсоемкая часть установки:

sudo make

После успешной компиляции установите программу в систему:

sudo make install

Чтобы не писать конфигурационные файлы с абсолютно чистого листа, установите базовые примеры конфигураций. Они послужат отличным шаблоном для дальнейшей настройки:

sudo make samples

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

sudo make config
sudo ldconfig

Запустите службу Asterisk и проверьте ее статус:

sudo systemctl start asterisk
sudo systemctl enable asterisk
sudo systemctl status asterisk

Если в выводе последней команды вы видите зеленую надпись active (running), значит, ядро вашей будущей IP-АТС успешно установлено и работает.

Установка Asterisk на Ubuntu 22.04.3

Успешная компиляция исходного кода — это лишь половина пути. Программная АТС установлена на сервер, но в данный момент она абсолютно пуста. Она не знает ни одного абонента, не умеет маршрутизировать звонки и заблокирована сетевым экраном операционной системы.

Чтобы превратить набор бинарных файлов в полноценную телефонную станцию, необходимо выполнить базовую настройку: открыть порты, создать учетные записи для телефонов и написать правила обработки вызовов.

Настройка сетевого экрана (Firewall)

По умолчанию операционная система Ubuntu 22.04 защищена встроенным брандмауэром UFW (Uncomplicated Firewall). Он блокирует все входящие соединения, кроме тех, которые вы явно разрешили. Если не открыть нужные порты, телефоны просто не смогут достучаться до сервера Asterisk.

Для работы IP-телефонии требуются два типа портов:

  1. Порт для сигнального трафика (SIP/PJSIP) — по умолчанию это порт 5060. По нему передаются команды вызова, отбоя и авторизации.
  2. Диапазон портов для голосового трафика (RTP) — по умолчанию от 10000 до 20000. По ним передается сам звук.

Откройте терминал сервера и выполните следующие команды:

sudo ufw allow 5060/udp
sudo ufw allow 10000:20000/udp
sudo ufw reload

Теперь сервер готов принимать входящие подключения от IP-телефонов и программных софтфонов.

Конфигурация абонентов: знакомство с pjsip.conf

Все настройки учетных записей в современном Asterisk хранятся в файле /etc/asterisk/pjsip.conf. Как упоминалось ранее, драйвер PJSIP имеет модульную структуру. Вместо того чтобы описывать все параметры телефона в одном огромном блоке, мы собираем профиль абонента из нескольких независимых кирпичиков.

Откройте конфигурационный файл в текстовом редакторе (например, nano):

sudo nano /etc/asterisk/pjsip.conf

Если файл содержит демонстрационные данные, удалите их и начните с чистого листа. Первым делом необходимо создать Транспорт (Transport). Это правило, которое указывает Asterisk, на каком IP-адресе и порту нужно слушать входящие подключения.

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060

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

Теперь создадим первого абонента с внутренним номером 101. Для этого нам понадобятся три блока: AOR, Auth и Endpoint.

1. AOR (Address of Record) Это адресная книга. Она сообщает серверу, сколько устройств могут одновременно зарегистрироваться под номером 101 и как их найти в сети.

[101]
type=aor
max_contacts=1

2. Auth (Авторизация) Это паспорт абонента. Здесь хранится логин и пароль, которые телефон должен предъявить при подключении.

[101]
type=auth
auth_type=userpass
password=SuperSecretPassword123
username=101

3. Endpoint (Конечная точка) Это главный профиль устройства. Он связывает воедино транспорт, авторизацию и адресную книгу, а также задает кодеки и контекст (правила маршрутизации).

[101]
type=endpoint
context=internal
disallow=all
allow=alaw
allow=ulaw
auth=101
outbound_auth=101
aors=101

Обратите внимание на параметр context=internal. Контекст — это изолированная зона в правилах маршрутизации. Присваивая абоненту контекст internal, мы говорим серверу: «Когда этот телефон пытается куда-то позвонить, ищи правила для этого звонка в разделе internal».

Чтобы создать второго абонента (например, номер 102), просто скопируйте блоки AOR, Auth и Endpoint, заменив везде 101 на 102, и задайте новый пароль. Сохраните файл и закройте редактор.

Маршрутизация вызовов: пишем первый Диалплан

Телефоны созданы, но если сейчас номер 101 попытается позвонить на номер 102, вызов оборвется. Asterisk не знает, что делать с этим звонком. Логика обработки вызовов описывается в Диалплане (Dialplan), который находится в файле /etc/asterisk/extensions.conf.

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

Откройте файл диалплана:

sudo nano /etc/asterisk/extensions.conf

Очистите его и напишите следующие строки:

[internal]
exten => 101,1,Dial(PJSIP/101)
exten => 102,1,Dial(PJSIP/102)

Разберем синтаксис этой магии по частям. Каждая строка маршрутизации состоит из четырех элементов, разделенных запятыми:

  • exten => — ключевое слово, обозначающее начало правила.
  • 101 — номер, который набрал пользователь на клавиатуре телефона.
  • 1 — приоритет (порядковый номер шага). Шаги выполняются строго по очереди: 1, 2, 3 и так далее.
  • Dial(PJSIP/101) — приложение (команда), которое должен выполнить Asterisk. В данном случае команда Dial приказывает серверу позвонить на устройство 101 через драйвер PJSIP.

Если перевести первую строку на человеческий язык, она звучит так: «Если кто-то, находящийся в контексте internal, наберет номер 101, то первым шагом нужно вызвать устройство 101 по протоколу PJSIP».

Применение настроек и консоль Asterisk

Файлы конфигурации изменены, но Asterisk загружает их в оперативную память только при старте. Чтобы система увидела новые настройки без перезагрузки всего сервера, нужно воспользоваться командной строкой (CLI) самой АТС.

Подключитесь к консоли Asterisk командой:

sudo asterisk -rvvv

Ключи -rvvv означают подключение к работающему процессу (remote) с высоким уровнем детализации логов (verbose). Вы увидите приглашение вида *CLI>.

Перезагрузите модуль PJSIP и Диалплан:

*CLI> pjsip reload
*CLI> dialplan reload

Теперь ваша АТС полностью готова к работе.

Подключение софтфона и первый звонок

Для проверки работоспособности системы вам понадобятся два устройства. Проще всего использовать софтфоны — программы для компьютера или смартфона, имитирующие настоящий IP-телефон (например, MicroSIP для Windows, Zoiper или Linphone для смартфонов).

Установите софтфон на компьютер и создайте новый аккаунт. В настройках программы укажите данные, которые мы прописали в pjsip.conf:

  • SIP Сервер (Domain): IP-адрес вашего сервера Ubuntu
  • Пользователь (Username): 101
  • Пароль (Password): SuperSecretPassword123

После сохранения настроек софтфон отправит запрос на сервер. Если все сделано верно, в консоли Asterisk вы увидите сообщение об успешной регистрации:

Registered contact 'sip:101@192.168.1.50:5060'

Настройте второй софтфон на смартфоне, используя данные абонента 102. Теперь наберите номер 102 на компьютере и нажмите кнопку вызова.

В этот момент произойдет следующее:

  1. Софтфон 101 отправит SIP-запрос на порт 5060 сервера.
  2. Asterisk проверит, в каком контексте находится абонент 101 (мы указали context=internal).
  3. Сервер заглянет в extensions.conf, найдет в контексте [internal] правило для набранного номера 102.
  4. Выполнится команда Dial(PJSIP/102).
  5. Ваш смартфон зазвонит. При поднятии трубки установится RTP-соединение, и вы услышите свой голос.

Поздравляем! Вы только что с нуля настроили собственную IP-АТС и совершили свой первый VoIP-звонок.

Настройка каналов связи и абонентов

Настройка каналов связи и абонентов

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

Для выхода в телефонную сеть общего пользования (ТФОП) нам потребуется подключить сервер Asterisk к оператору связи. В IP-телефонии такое подключение называется SIP-транком (SIP Trunk).

Что такое SIP-транк и как он работает

Представьте, что ваша офисная АТС — это остров. Внутренние абоненты (номера 101 и 102) свободно перемещаются по этому острову и общаются друг с другом. Но чтобы отправить сообщение на материк, им нужен мост. SIP-транк — это и есть виртуальный мост, или канал связи, который соединяет ваш сервер с оборудованием телеком-провайдера через интернет.

Провайдер выделяет вам внешний телефонный номер (например, +7 495 123-45-67), логин, пароль и адрес своего сервера. Ваша задача — научить Asterisk стучаться на этот сервер, подтверждать свою личность и передавать голосовой трафик.

Настройка подключения к провайдеру в pjsip.conf

Откройте конфигурационный файл абонентов, с которым мы работали ранее:

sudo nano /etc/asterisk/pjsip.conf

Для подключения к провайдеру нам нужно создать четыре новых блока. В отличие от обычного телефона, транк требует дополнительного блока — Registration. Он заставляет Asterisk регулярно отправлять провайдеру сигнал: «Я здесь, я в сети, вот мой IP-адрес, присылай звонки сюда».

Добавьте в конец файла следующие настройки (замените данные на те, что выдал ваш провайдер):

[provider-reg]
type=registration
outbound_auth=provider-auth
server_uri=sip:sip.provider.com
client_uri=sip:74951234567@sip.provider.com
retry_interval=60

[provider-auth]
type=auth
auth_type=userpass
password=SecretProviderPassword
username=74951234567

[provider-aor]
type=aor
contact=sip:sip.provider.com

[provider-endpoint]
type=endpoint
context=from-external
disallow=all
allow=alaw
allow=ulaw
outbound_auth=provider-auth
aors=provider-aor

Разберем ключевые параметры:

  • server_uri — адрес сервера провайдера.
  • client_uri — ваш логин (обычно совпадает с номером телефона) и адрес провайдера.
  • retry_interval=60 — если связь оборвется, Asterisk будет пытаться переподключиться каждые 60 секунд.
  • context=from-external — критически важный параметр. Мы помещаем провайдера в изолированную зону from-external. Если поместить его в контекст internal, любой хакер сможет позвонить на ваш номер и за ваш счет совершать международные вызовы. Это явление называется Toll Fraud (телефонное мошенничество).

Сохраните файл и примените настройки в консоли Asterisk:

*CLI> pjsip reload

Чтобы убедиться, что регистрация прошла успешно, введите команду pjsip show registrations. Статус должен измениться на Registered.

Шаблоны номеров (Паттерны) в Диалплане

Транк подключен, но абоненты 101 и 102 все еще не могут звонить наружу. Asterisk не знает, что делать, если пользователь наберет номер 89001234567.

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

Чтобы Asterisk понял, что перед ним шаблон, а не конкретный номер, правило должно начинаться с символа подчеркивания _.

Основные символы шаблонов:

  • X — любая цифра от 0 до 9.
  • Z — любая цифра от 1 до 9.
  • N — любая цифра от 2 до 9.
  • . (точка) — один или более любых символов.

Пример: шаблон _8X. означает: «Любой номер, который начинается с восьмерки, за которой следует хотя бы одна любая цифра».

Маршрутизация исходящих вызовов

Откройте файл Диалплана:

sudo nano /etc/asterisk/extensions.conf

Найдите контекст [internal], в котором находятся наши телефоны, и добавьте правило для исходящих звонков по России (номера, начинающиеся с 8 и состоящие из 11 цифр):

[internal]
exten => 101,1,Dial(PJSIP/101)
exten => 102,1,Dial(PJSIP/102)

; Исходящие вызовы через провайдера
exten => _8XXXXXXXXXX,1,Dial(PJSIP/${EXTEN}@provider-endpoint)

Здесь появляется новая магия — переменная ${EXTEN}. Когда абонент набирает номер (например, 89991112233), этот номер совпадает с шаблоном _8XXXXXXXXXX. Asterisk берет набранные цифры, сохраняет их в переменную ${EXTEN} и подставляет в команду Dial.

В результате сервер выполняет команду: «Позвонить на номер 89991112233 через профиль provider-endpoint».

Маршрутизация входящих вызовов

Теперь настроим обратный путь. Когда клиент звонит на ваш внешний номер +7 495 123-45-67, провайдер отправляет этот вызов на ваш сервер.

Поскольку в pjsip.conf мы указали для провайдера context=from-external, Asterisk будет искать инструкции именно в этом блоке. Добавим его в extensions.conf:

[from-external]
exten => 74951234567,1,Dial(PJSIP/101,30)
exten => 74951234567,2,Hangup()

Разберем логику:

  1. Когда приходит звонок на номер 74951234567, первым шагом (1) Asterisk вызывает внутреннего абонента 101.
  2. Параметр 30 в команде Dial означает таймаут. Телефон будет звонить ровно 30 секунд.
  3. Если абонент 101 не взял трубку за 30 секунд, выполнение переходит ко второму шагу (2).
  4. Команда Hangup() принудительно завершает вызов (кладет трубку).

Сохраните файл и перезагрузите Диалплан в консоли:

*CLI> dialplan reload

Теперь ваша АТС умеет принимать звонки из города и направлять их секретарю (номер 101), а также позволяет сотрудникам звонить клиентам.

Решение проблемы односторонней слышимости (NAT)

На практике после базовой настройки транка новички часто сталкиваются с классической проблемой VoIP: звонок проходит, вы снимаете трубку, но в динамике тишина. При этом собеседник может вас слышать, а вы его нет (или наоборот). Это проблема NAT (Network Address Translation).

Протокол SIP передает только текстовые команды (кто кому звонит), а сам голос летит отдельным потоком по протоколу RTP. Когда Asterisk формирует пакет с приглашением к разговору, он вкладывает в него свой IP-адрес, чтобы провайдер знал, куда отправлять звук.

Если ваш сервер стоит за домашним или офисным роутером, он имеет локальный IP-адрес (например, 192.168.1.50). Asterisk честно отправляет этот локальный адрес провайдеру. Провайдер пытается отправить голос на 192.168.1.50, но этот адрес существует только внутри вашей сети. В глобальном интернете такого адреса нет, и пакеты со звуком теряются.

Это похоже на ситуацию, когда вы отправляете письмо в другой город и в качестве обратного адреса пишете просто «Кабинет №5», забыв указать город, улицу и номер дома. Почтальон не сможет доставить ответ.

Чтобы решить эту проблему, нужно явно указать серверу его публичный IP-адрес. Откройте pjsip.conf и найдите блок [transport-udp], который мы создали в предыдущей статье. Добавьте в него две строки:

[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
local_net=192.168.1.0/24
external_media_address=203.0.113.50
external_signaling_address=203.0.113.50
  • local_net — указывает вашу внутреннюю подсеть. Asterisk поймет, что при общении с телефонами внутри этой сети подменять IP-адрес не нужно.
  • external_media_address и external_signaling_address — ваш внешний статический IP-адрес, который выдал интернет-провайдер (в примере 203.0.113.50).

После внесения изменений обязательно перезагрузите модуль PJSIP. Теперь Asterisk будет корректно представляться внешнему миру, и проблема с односторонней слышимостью исчезнет.

Отладка в консоли (CLI)

Если что-то пошло не так, консоль Asterisk — ваш лучший друг. Подключитесь к ней (sudo asterisk -rvvv) и включите логирование SIP-пакетов командой:

*CLI> pjsip set logger on

После этого совершите тестовый звонок. Вы увидите весь обмен сообщениями между вашей АТС и провайдером в реальном времени. Это позволит быстро понять, на каком этапе происходит сбой: отклоняет ли провайдер ваш пароль, неправильно ли настроен шаблон номера или звук уходит на неверный IP-адрес. Чтобы выключить логирование, введите pjsip set logger off.

Маршрутизация вызовов в Dialplan

Маршрутизация вызовов в Dialplan

Сердце любой телефонной станции — это её логика распределения звонков. В Asterisk эта логика называется Диалпланом (Dialplan). Если конфигурационный файл pjsip.conf, который мы настраивали ранее, определяет кто подключен к серверу, то диалплан определяет, что происходит, когда эти устройства пытаются позвонить.

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

Вся маршрутизация настраивается в одном текстовом файле:

sudo nano /etc/asterisk/extensions.conf

Анатомия Диалплана: Четыре кита маршрутизации

Чтобы научиться писать правила маршрутизации, необходимо понять четыре базовых термина, на которых строится синтаксис файла extensions.conf. Это Контексты, Экстеншены, Приоритеты и Приложения.

1. Контексты (Contexts)

Контекст — это изолированная зона внутри диалплана. Контексты разделяют правила маршрутизации так, чтобы они не пересекались. Имена контекстов всегда пишутся в квадратных скобках, например [internal] или [from-provider].

Зачем нужна изоляция? Представьте, что у вас есть телефон в холле для гостей и телефон в кабинете директора. Гостевой телефон должен иметь право звонить только на ресепшен (внутренний номер 100), а телефон директора — куда угодно, включая международные линии. Поместив эти телефоны в разные контексты, вы физически запрещаете гостевому аппарату использовать правила маршрутизации директора.

Безопасность IP-АТС начинается с правильного распределения контекстов. Никогда не помещайте внешние подключения (транки провайдеров) в тот же контекст, где разрешены исходящие платные звонки, иначе вы станете жертвой телефонных мошенников.

2. Экстеншены (Extensions)

Экстеншен — это то, что набирает пользователь на клавиатуре телефона (номер назначения), или системное событие. Каждое правило в контексте начинается со слова exten =>, за которым следует сам экстеншен.

Например, если пользователь набирает 101, Asterisk будет искать в текущем контексте строку, которая начинается с exten => 101.

3. Приоритеты (Priorities)

Каждый экстеншен может состоять из нескольких шагов. Приоритет — это порядковый номер шага. Asterisk всегда начинает выполнение с приоритета 1, затем переходит к 2, 3 и так далее, пока шаги не закончатся или вызов не прервется.

Вместо того чтобы вручную нумеровать каждый шаг (что неудобно при редактировании кода), в Asterisk используется символ n (next — следующий). Первый шаг всегда 1, а все последующие — n.

4. Приложения (Applications)

Приложение — это конкретное действие, которое Asterisk должен выполнить на данном шаге. Приложения могут принимать аргументы (параметры), которые указываются в круглых скобках.

Самые популярные приложения:

  • Dial() — позвонить на указанное устройство.
  • Answer() — «снять трубку» (ответить на входящий вызов со стороны сервера).
  • Playback() — проиграть заранее записанный аудиофайл.
  • Hangup() — положить трубку (завершить вызов).

Базовая маршрутизация: звонки внутри офиса

Давайте соберем все четыре элемента вместе и напишем простое правило для звонка на номер 101. Откройте файл extensions.conf и добавьте следующий код:

[internal]
; Шаг 1: Звоним на устройство PJSIP/101, ждем 30 секунд
exten => 101,1,Dial(PJSIP/101,30)

; Шаг 2: Если за 30 секунд никто не ответил, кладем трубку
exten => 101,n,Hangup()

Разберем синтаксис первой строки:

  1. exten => — объявление правила.
  2. 101 — экстеншен (набранный номер).
  3. 1 — приоритет (первый шаг).
  4. Dial(PJSIP/101,30) — приложение. Мы говорим серверу: «Используй канал PJSIP, чтобы вызвать устройство 101. Если абонент не ответит через 30 секунд, прекрати вызов».

Если у вас в офисе 50 сотрудников, писать такие две строчки для каждого номера (101, 102, 103...) — это пустая трата времени. Здесь на помощь приходят шаблоны и переменные.

Шаблоны (Patterns) и переменные

Asterisk умеет обрабатывать номера по маскам. Чтобы система поняла, что перед ней шаблон, а не конкретный номер, экстеншен должен начинаться с символа подчеркивания _.

В таблице ниже представлены основные символы для составления шаблонов:

Символ Значение
X Любая цифра от 0 до 9
Z Любая цифра от 1 до 9 (исключает ноль)
N Любая цифра от 2 до 9 (исключает 0 и 1)
. Один или более любых символов (используется в конце)

Перепишем наш диалплан так, чтобы он автоматически обрабатывал любые трехзначные номера, начинающиеся с единицы (от 100 до 199):

[internal]
exten => _1XX,1,Dial(PJSIP/${EXTEN},30)
exten => _1XX,n,Hangup()

В этом примере мы использовали системную переменную ${EXTEN}. Когда абонент набирает номер 105, этот номер совпадает с шаблоном _1XX. Asterisk автоматически сохраняет набранные цифры 105 в переменную ${EXTEN}. На этапе выполнения приложение Dial подставит это значение, и команда превратится в Dial(PJSIP/105,30).

Маршрутизация исходящих вызовов (Транки)

Теперь научим наших абонентов звонить во внешний мир через оператора связи. Предположим, мы хотим разрешить звонки на мобильные номера по России, которые начинаются с восьмерки и содержат 11 цифр.

Создадим для этого отдельный контекст:

[outbound-calls]
; Разрешаем звонки на номера формата 8XXXXXXXXXX
exten => _8XXXXXXXXXX,1,Dial(PJSIP/${EXTEN}@provider-endpoint)
exten => _8XXXXXXXXXX,n,Hangup()

Обратите внимание на синтаксис внутри Dial: PJSIP/${EXTEN}@provider-endpoint. Здесь мы указываем серверу не просто набрать номер, а отправить этот вызов через конкретное подключение — provider-endpoint (имя транка, которое мы задавали в pjsip.conf в предыдущей статье).

Объединение контекстов (Includes)

У нас есть контекст [internal] для связи внутри офиса и [outbound-calls] для звонков в город. Но в файле настроек абонентов (pjsip.conf) мы можем привязать пользователя только к одному контексту. Как дать сотруднику доступ и к внутренним, и к внешним звонкам?

Для этого используется директива include =>. Она позволяет вкладывать один контекст в другой, как матрешку.

[outbound-calls]
exten => _8XXXXXXXXXX,1,Dial(PJSIP/${EXTEN}@provider-endpoint)
exten => _8XXXXXXXXXX,n,Hangup()

[internal]
; Включаем правила из контекста outbound-calls
include => outbound-calls

; Внутренние звонки
exten => _1XX,1,Dial(PJSIP/${EXTEN},30)
exten => _1XX,n,Hangup()

Теперь любой пользователь, находящийся в контексте [internal], сможет звонить как на номера 1XX, так и на номера 8XXXXXXXXXX.

Такая модульная структура позволяет гибко управлять правами. Например, вы можете создать контекст [managers], который включает в себя [internal], [outbound-calls] и дополнительный контекст [international-calls]. Обычные сотрудники получат базовый доступ, а менеджеры — расширенный.

Обработка входящих вызовов

Когда клиент звонит на ваш городской номер, провайдер направляет этот вызов на ваш сервер Asterisk. В настройках транка мы указали, что все входящие звонки от провайдера должны попадать в контекст [from-external].

Часто провайдеры присылают вызов не на конкретный номер, а просто отправляют сигнал на сервер. Для обработки таких вызовов используется специальный системный экстеншен s (start).

Настроим диалплан так, чтобы все входящие звонки направлялись на номер секретаря (101):

[from-external]
; Принимаем любой входящий звонок
exten => s,1,Answer()
; Звоним секретарю
exten => s,n,Dial(PJSIP/101,60)
; Если секретарь не ответил за 60 секунд, сбрасываем
exten => s,n,Hangup()

Приложение Answer() здесь крайне важно. Прежде чем начать маршрутизацию входящего вызова из внешней сети, Asterisk должен «снять трубку», чтобы установить аудиоканал с провайдером.

Применение настроек и отладка

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

Зайдите в консоль Asterisk:

sudo asterisk -rvvv

Выполните команду перезагрузки диалплана:

*CLI> dialplan reload

Если вы хотите проверить, как Asterisk «видит» ваши правила, используйте команду dialplan show. Например, dialplan show 105@internal покажет, какие именно шаги будут выполнены, если пользователь из контекста internal наберет номер 105.

Консоль с ключами -rvvv (три буквы v означают высокий уровень детализации логов) — ваш главный инструмент отладки. Совершите тестовый звонок, и вы увидите на экране каждую строчку диалплана, которую в данный момент выполняет сервер. Это позволяет мгновенно находить ошибки: опечатки в экстеншенах, неверные имена переменных или проблемы с правами доступа в контекстах.

Подключение софтфонов и тестовые звонки

Подключение софтфонов и тестовые звонки

IP-телефония обретает смысл только в тот момент, когда вы можете поднять трубку и услышать голос собеседника на другом конце провода. На предыдущих этапах мы подготовили надежный фундамент: установили серверную часть на Ubuntu 22.04, создали учетные записи абонентов в файле pjsip.conf и прописали логику маршрутизации в диалплане extensions.conf. Теперь настало время превратить эти текстовые конфигурации в реальную систему связи.

Для совершения звонков нам потребуются клиентские устройства. В корпоративной среде это обычно аппаратные IP-телефоны, стоящие на столах сотрудников. Однако для обучения, тестирования и удаленной работы идеально подходят софтфоны.

Что такое софтфон и как его выбрать

Софтфон (Software Telephone) — это программное обеспечение, которое устанавливается на компьютер, смартфон или планшет и выполняет все функции классического телефонного аппарата. Софтфон использует микрофон и динамики вашего устройства для передачи голоса, а подключение к серверу Asterisk происходит через интернет или локальную сеть по протоколу SIP.

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

Существует множество бесплатных решений. В таблице ниже представлены наиболее популярные варианты для начинающих:

Название Платформы Особенности Идеально для...
MicroSIP Windows Очень легкий, портативный (не требует установки), минималистичный интерфейс. Тестирования на ПК и слабых компьютерах.
Zoiper Windows, macOS, Linux, iOS, Android Кроссплатформенный, поддерживает сканирование QR-кодов для быстрой настройки. Использования на смартфонах и Mac.
Linphone Windows, macOS, Linux, iOS, Android Полностью открытый исходный код (Open Source), поддержка видеозвонков и шифрования. Продвинутых пользователей и энтузиастов.

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

Сбор учетных данных для подключения

Прежде чем открывать настройки софтфона, необходимо четко понимать, какие данные от нас потребуются. Любому SIP-клиенту для успешной регистрации на сервере нужны четыре базовых параметра.

  1. IP-адрес сервера (Domain/SIP Server): Это сетевой адрес вашей машины с Ubuntu 22.04. Если вы настраиваете систему в локальной сети, это будет внутренний адрес, например 192.168.1.50.
  2. Логин (Username/Extension): Имя пользователя, которое мы задавали в квадратных скобках в блоке [Endpoint] файла pjsip.conf. В нашем случае это внутренний номер, например 101.
  3. Пароль (Password/Secret): Секретный ключ, указанный в параметре password блока [Auth] для данного абоненнта.
  4. Транспорт (Transport): Протокол передачи данных. По умолчанию Asterisk использует UDP на порту 5060.

Безопасность начинается с паролей. Никогда не используйте пароли, совпадающие с номером экстеншена (например, логин 101 и пароль 101). Боты-сканеры в интернете подберут такой пароль за несколько секунд, что приведет к взлому вашей АТС.

Практика: Настройка MicroSIP

Скачайте портативную версию MicroSIP с официального сайта и запустите приложение. В правом верхнем углу нажмите на иконку треугольника (меню) и выберите пункт «Добавить аккаунт» (Add Account).

Заполните поля следующим образом:

  • Название аккаунта (Account Name): Любое понятное имя, например Мой Asterisk.
  • SIP сервер (SIP Server): IP-адрес вашего сервера Ubuntu (например, 192.168.1.50).
  • Пользователь (Username): Ваш экстеншен 101.
  • Домен (Domain): Снова IP-адрес вашего сервера 192.168.1.50.
  • Логин (Login): Дублируем экстеншен 101.
  • Пароль (Password): Ваш сложный пароль из pjsip.conf.
  • Транспорт (Transport): Выберите UDP.

Остальные поля можно оставить пустыми. Нажмите «Сохранить» (Save).

Если все сделано верно, в левом нижнем углу окна MicroSIP загорится зеленый индикатор со статусом «Онлайн» (Online).

Анатомия регистрации: Что происходит под капотом

Когда вы нажимаете кнопку «Сохранить», софтфон не просто меняет цвет индикатора. В этот момент по сети пролетает серия служебных сообщений. Этот процесс называется SIP-регистрацией.

  1. Софтфон отправляет на сервер пакет REGISTER. В нем он говорит: «Привет, я абонент 101, и я сейчас нахожусь по вот этому IP-адресу».
  2. Asterisk видит запрос, но не верит на слово. Он отвечает пакетом 401 Unauthorized (Не авторизован), к которому прикрепляет криптографическую задачу (хэш).
  3. Софтфон решает эту задачу, используя свой пароль, и отправляет пакет REGISTER повторно, уже с правильным ответом.
  4. Asterisk сверяет ответ со своей базой данных (pjsip.conf). Если пароли совпадают, сервер отвечает пакетом 200 OK. Регистрация успешна.

Теперь Asterisk точно знает, на какой IP-адрес отправлять вызов, если кто-то наберет номер 101.

Создание тестового сервиса: Эхо-тест

Прежде чем звонить другим людям, полезно проверить, правильно ли работает микрофон и динамики, а также корректно ли Asterisk обрабатывает звук. Для этого в IP-телефонии существует стандартный инструмент — Эхо-тест (Echo Test).

Эхо-тест работает как зеркало для звука: все, что вы скажете в микрофон, сервер немедленно отправит вам обратно в наушники.

Давайте добавим этот сервис в наш диалплан. Откройте файл маршрутизации:

sudo nano /etc/asterisk/extensions.conf

В контекст [internal], который мы создали в предыдущей статье, добавьте специальный сервисный номер, например *43:

[internal]
; Существующие правила для звонков абонентам
exten => _1XX,1,Dial(PJSIP/${EXTEN},30)
exten => _1XX,n,Hangup()

; Новое правило: Эхо-тест
exten => *43,1,Answer()
exten => *43,n,Playback(demo-echotest)
exten => *43,n,Echo()
exten => *43,n,Hangup()

Разберем новые приложения:

  • Answer() — сервер снимает трубку, чтобы установить аудиоканал.
  • Playback(demo-echotest) — сервер проигрывает стандартный аудиофайл Asterisk с приветствием (на английском языке).
  • Echo() — запускает само приложение эхо-теста. Оно будет работать до тех пор, пока вы не положите трубку.

Сохраните файл и обязательно примените настройки в консоли Asterisk:

sudo asterisk -rx "dialplan reload"

Теперь откройте MicroSIP и наберите *43. Вы должны услышать голос диктора, а затем собственный голос с небольшой задержкой. Если это произошло — поздравляю, ваш сервер Asterisk полностью работоспособен, а проблема с NAT и прохождением RTP-трафика (диапазон портов 10000≤p≤2000010000 \leq p \leq 20000) вас не коснулась!

Чтение логов: Отладка в консоли (CLI)

Настоящий системный администратор не смотрит на экран софтфона, он смотрит в логи сервера. Консоль Asterisk — это рентгеновский аппарат для вашей АТС.

Подключитесь к консоли с максимальным уровнем детализации (три ключа v):

sudo asterisk -rvvv

Совершите звонок на номер *43 еще раз и посмотрите на экран терминала. Вы увидите примерно следующий вывод:

    -- Executing [*43@internal:1] Answer("PJSIP/101-00000001", "") in new stack
    -- Executing [*43@internal:2] Playback("PJSIP/101-00000001", "demo-echotest") in new stack
    -- <PJSIP/101-00000001> Playing 'demo-echotest.gsm' (language 'en')
    -- Executing [*43@internal:3] Echo("PJSIP/101-00000001", "") in new stack

Каждая строка начинается со слова Executing (Выполнение). Далее в квадратных скобках указано, какое именно правило сработало: [*43@internal:1] означает, что был вызван экстеншен *43 в контексте internal, шаг (приоритет) 1.

Далее указано приложение Answer() и уникальный идентификатор канала PJSIP/101-00000001. Этот идентификатор позволяет отследить конкретный звонок, даже если на сервере одновременно разговаривают сотни людей.

Типичные ошибки и их решение

Если что-то пошло не так, консоль Asterisk подскажет, где искать проблему. Рассмотрим три самые частые ошибки новичков.

Ошибка 401 / 403: Проблема с регистрацией

Если софтфон пишет «Ошибка регистрации», а в консоли Asterisk появляются сообщения вида Endpoint '101' failed to authenticate, это означает проблему с учетными данными.

Решение: Проверьте правильность ввода пароля в софтфоне. Убедитесь, что логин в софтфоне точно совпадает с именем блока [101] в файле pjsip.conf.

Ошибка 404 Not Found: Вызов не идет

Вы набираете номер, но звонок сразу сбрасывается. В консоли появляется сообщение: Call from '101' to extension '105' rejected because extension not found in context 'internal'.

Это классическая ошибка маршрутизации. Сервер говорит: «Абонент 101 пытается позвонить на номер 105, но в контексте internal нет правила для номера 105».

Решение: Проверьте файл extensions.conf. Возможно, вы забыли написать правило для нужного номера, ошиблись в синтаксисе шаблона (например, написали 1XX вместо _1XX) или забыли выполнить команду dialplan reload после сохранения файла.

Односторонняя слышимость (Проблема NAT)

Звонок проходит, время идет, но вы не слышите собеседника (или он не слышит вас). В консоли при этом нет никаких ошибок.

Эта проблема связана с тем, что SIP (сигнализация) прошел успешно, а RTP (голосовой трафик) заблокирован брандмауэром или потерялся на маршрутизаторе из-за NAT (подмены IP-адресов).

Решение: Убедитесь, что в брандмауэре Ubuntu (UFW) открыт диапазон портов 10000≤p≤2000010000 \leq p \leq 20000 по протоколу UDP. Если сервер находится за домашним роутером, необходимо пробросить эти порты (Port Forwarding) в настройках роутера на внутренний IP-адрес сервера Asterisk.

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