![](https://habrastorage.org/files/969/ad8/72b/969ad872bcdf4c6cb22dc3568c1c2ae0.png)
В работе системного администратора, занимающегося внедрением систем телефонии на базе Asterisk, рано или поздно может возникнуть ситуация, когда аппаратных возможностей одного сервера для обработки всех вызовов уже недостаточно. Соответственно, возникает необходимость разделить нагрузку на несколько серверов. Одним из способов решения такой задачи является использование SIP proxy, но стоит признать, что в отличие от Asterisk, информации по SIP proxy, форумов, примеров и описаний, меньше как минимум на порядок. Цель этой статьи — показать на простом примере возможность использования SIP proxy Kamailio в связке с Asterisk так, чтобы максимально облегчить освоение SIP proxy для новичков.
Все настройки в рамках данного примера мы будем производить на виртуальных машинах, размещенных в локальной сети, хотя если бы они имели публичные адреса и находились бы в облаке, принципиальной разницы бы не было.
Предположим, что в организации уже установлен Asterisk, и сотрудники обрабатывают большое количество входящих звонков, с которым сервер уже не справляется. Мы добавим еще один сервер Asterisk (точнее, клонируем существующий), а SIP proxy возьмет на себя роль «распределителя» входящих звонков.
Начнем с выбора SIP proxy. На хабре есть хорошая статья на эту тему, в которой рассмотрена история развития основных проектов. В отличие от автора этой статьи, мой выбор пал на Kamailio и web-интерфейс для него под названием Siremis.
Установим Kamailio. В качестве ОС будем использовать CentOs 6.8.
В первую очередь, необходимо отключить SELinux, обновить пакеты и установить необходимые зависимости:
yum -y update && yum -y groupinstall core && yum -y groupinstall base && yum -y install epel-release
yum -y install httpd mysql-server php php-mysql php-gd php-curl
Нам потребуется доступ к 80 порту для работы с web-интерфейсом и к 5060 udp для работы с sip, поэтому добавим правила IPTables:
iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -m state --state NEW -m udp -p udp --dport 5060 -j ACCEPT
Создаем файл /etc/yum.repos.d/kamailio.repo с содержимым:
[kamailio]
name=RPMs for Kamailio on CentOS 6
type=rpm-md
baseurl=http://rpm.kamailio.org/stable/CentOS_6/
gpgcheck=1
gpgkey=http://rpm.kamailio.org/stable/CentOS_6/repodata/repomd.xml.key
enabled=1
И устанавливаем kamailio:
yum install kamailio kamailio-presence kamailio-mysql
Не забудем добавить демоны в автозагрузку:
chkconfig mysqld on
chkconfig httpd on
chkconfig kamailio on
Отредактируем файл /etc/kamailio/kamctlrc: нужно раскомментировать строку
DBENGINE=MYSQL
и указать SIP_DOMAIN. В силу того, что мы настраиваем систему в локальной сети, достаточно будет указать ip-адрес, в моем случае
SIP_DOMAIN=192.168.0.237
Ниже можно отредактировать параметры подключения к базе данных, но в случае учебного стенда менять их не обязательно.
Запустим MySQL и сгенерируем необходимые таблицы:
service mysqld start
kamdbctl create
На все вопросы мастера отвечаем утвердительно.
Теперь отредактируем основной конфигурационный файл /etc/kamailio/kamailio.cfg. Логически он разбит на несколько секций: глобальные параметры, загрузка модулей, установка параметров модулей и маршруты. Каждый модуль Kamailio выполняет определенную функцию, поэтому можно загружать только необходимые для конкретной задачи библиотеки. Начало файла приведем к виду:
#!KAMAILIO
#!define WITH_MYSQL
#!define WITH_AUTH
#!define WITH_USRLOCDB
#!define WITH_PRESENCE
#!define WITH_ACCDB
Как понятно из комментариев ниже, эти директивы включают необходимые модули, например WITH_MYSQL, определенный в начале файла, ниже приводит к загрузке модуля mysql.so:
#!ifdef WITH_MYSQL
loadmodule "db_mysql.so"
#!endif
Безусловно, можно загрузить все модули вручную, но использование директивы гораздо удобнее. WITH_AUTH, например, дает возможность пользователям регистрироваться на Kamailio с использованием имени и пароля, а все варианты выбора вы можете посмотреть в комментариях ниже.
Для дальнейшей корректной работы web-интерфейса и статистики внесем еще несколько изменений:
После всех строк loadmodule добавим загрузку еще двух:
loadmodule "rtimer.so"
loadmodule "sqlops.so"
Перед секцией маршрутов, которая отделяется строкой ####### Routing Logic ######## добавим параметры загруженных модулей:
modparam("rtimer", "timer", "name=cdr;interval=300;mode=1;")
modparam("rtimer", "exec", "timer=cdr;route=CDRS")
modparam("sqlops", "sqlcon", "cb=>mysql://kamailio:kamailiorw@localhost/kamailio")
И добавим дополнительный маршрут после последней секции route в районе 910 строки файла:
route[CDRS] {
sql_query("cb","call kamailio_cdrs()","rb");
sql_query("cb","call kamailio_rating('default')","rb");
}
Запускаем Kamailio и проверяем, что он запустился:
service kamailio start
ps aux | grep kamailio
Если Kamailio не запускается, нужно посмотреть лог /var/log/messages — именно туда будут попадать ошибки Kamailio, если дополнительно не настроить rsyslog, что не представляет большой сложности.
По умолчанию используется база MySQL kamailio c пользователем kamailio c паролем kamailiorw, если конечно не изменить установки по умолчанию в файле /etc/kamailio/kamctlrc перед созданием базы данных. В том случае, если вы изменили эти установки, будет нелишним пройтись автозаменой по основному конфигурационному файлу kamailio.cfg и внести корректные данные подключения к базе.
В принципе, Kamailio может работать и без базы данных — все необходимые значения для модулей можно задавать в конфигурационном файле или хранить во внешних файлах, но использование БД, особенно на крупных проектах, гораздо удобнее, плюс именно с базой будет работать web-интерфейс Siremis, который мы сейчас установим.
Нужно скачать, разархивировать файлы, скопировать их в директорию, с которой будет работать apache и дать верные права:
cd /usr/src
wget http://siremis.asipto.com/pub/downloads/siremis/siremis-4.3.0.tgz
tar zxvf siremis*
cp -a siremis*/. /var/www/html
cd /var/www/html
make prepare
rm -rf /var/www/html/Makefile
rm -rf /var/www/html/Changelog
rm -rf /var/www/html/README
chown -R apache. /var/www/html
В секцию VirtualHost в конфигурации apache для Siremis добавим
<Directory "/var/www/html/siremis">
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
Allow from all
<FilesMatch "\.xml$">
Order deny,allow
Deny from all
</FilesMatch>
<FilesMatch "\.inc$">
Order deny,allow
Deny from all
</FilesMatch>
</Directory>
<Directory "/var/www/html/openbiz">
AllowOverride All
Order deny,allow
Deny from all
</Directory>
<Directory "/var/www/html/misc">
AllowOverride All
Order deny,allow
Deny from all
</Directory>
При дальнейшей установке последней на момент написания статьи версии Siremis 4.3.0 могут возникнуть проблемы в случае, если у вас не задан date.timezone, поэтому рекомендуется сразу внести изменения в php.ini:
date.timezone = Europe/Moscow
Для Siremis потребуется отдельная база данных. Добавим пользователя:
mysql -e "GRANT ALL PRIVILEGES ON siremis.* TO siremis@localhost IDENTIFIED BY 'siremisrw';"
Вы можете изменить параметры подключения к базе, но не забудьте тогда задать верные значения в дальнейшем.
Теперь можно перезапустить apache и перейти к завершающему этапу установки Siremis — уже через браузер. Перейдите по адресу ваш-ip/siremis
![](https://habrastorage.org/files/419/55a/653/41955a65305c4bb3ba542f4bc65ec51f.png)
Если проверка системы пройдена, можно начинать установку.
![](https://habrastorage.org/files/550/b91/d8e/550b91d8e5f9499db231a4e2d2241cd8.png)
Обратите внимание: по умолчанию под звездочками скрываются дефолтные пароли от пользователей Kamailio и Siremis, так что если вы не вносили изменений ранее, то и на этом шаге можно не забивать пароли вручную.
Обязательно поставьте галочки на всех пунктах — Create Siremus DB, Import Dafault Data, Update SIP DB, Replace DB config.
![](https://habrastorage.org/files/b8c/276/781/b8c276781a9d4c148b27601ea6f60b70.png)
Проверьте, что указаны корректные данные.
![](https://habrastorage.org/files/1d8/d50/d80/1d8d50d8024940e0a80d4b7ac83494a3.png)
И на этом установка завершена.
![](https://habrastorage.org/files/f62/eb1/e27/f62eb1e270874a778b3bbe9ae5e8a1be.png)
Давайте попробуем осуществить первый звонок через Kamailio. Для этого перейдем на вкладку SIP Admin menu и добавим новый домен в Domain List. Kamailio будет обслуживать только перечисленные здесь домены (или ip-адреса).
![](https://habrastorage.org/files/b7c/f4f/de4/b7cf4fde49944f4183d2729867ef9c4f.png)
В случае, если к адресу привязан домен, и пользователи могут регистрироваться как указав ip-адрес, так и указав домен, следует добавить и доменное имя в список. В нашем случае добавляем только ip-адрес сервера, к которому будут обращаться клиенты.
![](https://habrastorage.org/files/a73/780/565/a73780565d024e4a8fe276e8e2f389ce.png)
Для создания внутреннего абонента или подписчика перейдем к Subscriber Services -> Subscribers и добавим два номера — 101 и 102, указав для них пароли и серый адрес в качестве домена (в нашем случае 192.168.0.237).
![](https://habrastorage.org/files/b7d/df4/1db/b7ddf41db24a4703ac43b00d17d3b8cf.png)
Теперь, используя софтфон, например Zoiper, мы можем зарегистрироваться на сервере и осуществить звонок с 101 на 102 номер или наоборот и убедиться в том, что все предыдущие действия были выполнены верно.
Перейдем к настройке распределения входящих вызовов. В локальной сети у нас есть 2 виртуальные машины с Asterisk на адресах 192.168.0.234 и 192.168.0.235, и нам нужно поровну распределить входящие звонки между ними. В данной ситуации мы будем использовать модуль dispatcher, который предоставляет необходимый функционал.
Вернемся в консоль, и добавим в kamailio.cfg в секцию загрузки модулей
loadmodule "dispatcher.so"
а также два параметра — подключения к базе данных, в которой и будет храниться список серверов Asterisk, и частоту проверки этих серверов, чтобы звонок ни в коем случае не ушел на выключенный сервер:
modparam("dispatcher", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
modparam("dispatcher", "ds_ping_interval", 30)
Вообще, полный список модулей, их параметров и функций всегда можно посмотреть на официальном сайте. После подключения модуля перезапустим Kamailio и убедимся в том, что он запустился. В случае возникновения проблем (модули могут зависеть от других, требовать установки определенных параметров как для самого модуля, так и для тех, от которых он зависит) мы увидим ошибку в логе.
Теперь перейдем к секции маршрутов. Созданные по умолчанию маршруты в принципе обеспечивают необходимый минимум, например, при попытке зарегистрироваться с неверным паролем, Kamailio отдаст ошибку 401, а при попытке позвонить на несуществующее направление — 404. Сложность в понимании маршрутизации Kamailio представляют используемые переменные и функции, которые предоставляются различными используемыми модулями, и не всегда сходу можно понять, какая переменная или функция к какому модулю относится. Для наших учебных целей маршрут потребуется совсем простой — в самое начало главного маршрута мы добавим условие:
if ( method=="INVITE" ) {
ds_select_dst("1","4");
sl_send_reply("100","Trying");
forward();
exit();
}
Если приходит запрос типа INVITE, то есть приглашение к началу разговора, то мы выбираем один из серверов, которые позже занесем в таблицу, из группы 1 по стратегии выбора 4 — round-robin. Затем посылаем ответ вызывающему и осуществляем перевод звонка на выбранное назначение. Обратите внимание, что теперь абсолютно любой INVITE будет обрабатываться таким образом, так что возможность позвонить с 101 номера на 102, которые мы создавали ранее, будет утрачена — звонки с них тоже будут улетать на один из серверов Asterisk, и поступающие извне запросы INVITE также будут напрямую уходить на Asterisk без всякой проверки источника запроса.
Для того, чтобы Asterisk мог обработать такие вызовы, нужно добавить peer следующего вида на каждый из серверов:
[kamailio]
host=192.168.0.237
port=5060
insecure=invite
type=friend
context=from-pstn
Теперь можно добавить сервера Asterisk в базу данных Kamailio через web-интерфейс:
![](https://habrastorage.org/files/717/ba5/e06/717ba5e0638c444498f7c1f95174fa45.png)
Setid задаст к какой группе серверов относится новый сервер, Priority не используется в стратегии выбора round-robin, но может использоваться в других стратегиях, а Flags в данном случае устанавливает, что по умолчанию мы считаем сервер неактивным и проверяем его состояние.
После добавления серверов можно или перезапустить Kamailio, что недопустимо на продакшне, или выполнить команду
kamcmd dispatcher.reload
. Список команд для каждого модуля также можно посмотреть на официальном сайте.Можно переходить к тестированию. Используя софтфон, например, Zoiper, можно осуществить вызов напрямую на Kamailio, без всяких аккаунтов и регистраций. Достаточно в поле набора ввести sip:1@192.168.0.237. Сразу после этого вызов будет переадресован на один из Asterisk и обработан в соответствии с диалпланом. Следующий вызов пойдет на второй сервер.
В принципе, стоявшую перед нами учебную задачу — распределять входящие вызовы поровну между серверами, — мы решили. Однако, далеко не каждый оператор связи готов отдавать звонки на ваш ip-адрес напрямую, без регистрации, и нужно будет посылать запросы типа REGISTER. Этот функционал реализует модуль uac. Добавим в нашу схему еще один Asterisk — он будет исполнять роль провайдера. На нем создадим какой-нибудь внутренний номер, например, 200200, который будет требовать регистрацию.
Загрузим модуль в конфигурационном файле:
loadmodule "uac.so"
И зададим пару обязательных в нашем случае параметров:
modparam("uac", "reg_db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
modparam("uac", "reg_contact_addr", "192.168.0.237")
Кроме того, потребуется внести изменение в параметр другого модуля. Найдите в файле строку
modparam("rr", "append_fromtag", 0)
и замените на:
modparam("rr", "append_fromtag", 1)
Теперь можно настроить регистрацию, перезапустив предварительно Kamailio, чтобы модуль загрузился:
![](https://habrastorage.org/files/c4b/ded/5e5/c4bded5e59c44dd3aa148147ab2c0a2f.png)
Обратите внимание на поле Realm. По умолчанию, вы можете ввести в него что угодно, но тогда регистрация проходить не будет, а в логе вы увидите то-то вроде:
kamailio /usr/sbin/kamailio[26277]: ERROR: uac [uac_reg.c:799]: uac_reg_tm_callback(): realms do not match. requested realm: [asterisk]
Именно поэтому при возникновении каких-либо проблем не стоит сразу перечитывать мануал, искать другие инструкции и сомневаться в своих способностях — чаще всего объяснение можно найти в логе.
Остается только убедиться в том, что абонент 200200 зарегистрирован на Asterisk, играющем роль провайдера, и осуществить звонок с любого другого номера на 200200.
На этом пример настройки Kamailio мы заканчиваем, но обратите внимание, что в статье не рассмотрена работа за NAT, безопасность, маршрутизация исходящих вызовов и многое другое, что может потребоваться в реальной ситуации. Однако надеюсь, что эта статья облегчит для вас освоение Kamailio.