Задача: Настроить телефоны (или любой другой абонентский девайс) автоматически на основе MAC-адреса, желательно не доставая устройство из коробки.
Идея централизованной настройки абонентских устройств давно была у меня и, наконец, нашла свою реализацию в одном из проектов. Видео в конце поста.
Практически все (Cisco, Polycom, D-Link, Escene) IP-телефоны, с которыми мне доводилось встречаться, в том или ином виде поддерживают централизованную настройку с сервера, т.е. Auto-Provisioning по нашему автопровизия. В данном случае рассмотрен пример с телефонами Polycom, но по сути, аналогичный подход позволит настроить любой телефон с определенными корректировками.
Как это работает (про Polycom)?
Телефон по умолчанию настроен на получение IP-адреса по DHCP, помимо самого адреса телефон получает от DHCP ряд опций в числе которых обычно указываются шлюз, маска сети и DNS- сервер, кроме того можно указать SNTP-сервер и еще много чего. Polycom’ы смотрят по умолчанию в опцию 66 и 160, там они пытаются найти адрес/имя сервера автопровизии. Если телефон обнаруживает адрес сервера, он пытается подключиться к нему по уполчанию через FTP (поддерживает еще HTTP, HTTPS, TFTP), используя в качестве логина и пароля:
Username | PlcmSpIp |
Password | PlcmSpIp |
Телефон запрашивает у сервера версию (файл sip.ver) и сами файлы прошивки и конфигурационные файлы. Телефон выкачивает новую прошивку, обновляется, затем после перезагрузки снова обращается к серверу, видит, что ПО не требует обновления, скачивает и применяет конфигурационные файлы в формате XML. В общем случае аппарат запрашивает следующие файлы.
Имя файла | Описание |
0000000000.cfg | Общий конфигурационный файл (говорит что и откуда качать) |
*.sip.ld (для split) sip.ld (для combined)* |
Прошивка телефона соответствующей модели (задается с 0000000000.cfg), |
sip.ver | Версия ПО |
1234123adba.cfg | Конфигурация телефона с MAC-адресом 1234123adba |
*- у поликома есть существует две версии ПО combined(много весит)-подходит для всех, split – для каждой линейки телефонов отдельный небольшой *sip.ld файл (уменьшает нагрузку на сеть).
Казалось бы, вот и все, телефон готов к работе! На самом деле для небольших систем так оно и есть, т.е. достаточно:
- Скачать прошивку с сайта производителя для своих телефонов support.polycom.com/PolycomService/support/us/support/voice/index.html
- В 0000000000.cfg указать какие именно конфигурационные файлы телефон должен загрузить с сервера (CONFIG_FILES="custom.cfg"), этого достаточно, т.к. по умолчанию.
- Создать custom.cfg содержащий настройки общие для всех устройств.
- Создать несколько конф-файлов для каждого из аппаратов <МАС-адрес>.cfg в котором будет содержаться информация уникальная для каждого абонента т.е. в общем случае только его SIP-логин и пароль.
Данное решение позволит быстро развернуть небольшую VoIP-инфраструктуру, однако на больших системах, придется создавать много однотипных файлов и удобна и не обладает особой гибкостью. К тому же это скучно.
Поэтому я пошел более изощренным путем:
- Через FTP настраиваем телефон чтобы он получал файлы через HTTP:8088
- На Asterisk’e с помощью phoneprov динамически формируем конфигурационный файл для каждого телефона на основе файла users.conf.
При таком способе настройки достаточно будет для добавления нового устройства внести его МАС в users.conf и там же задать ему логин и пароль, остальная настройка происходит автоматически.
Теперь более подробно рассмотрим, что нужно делать:
Настройка DHCP
В данном случае я задаю через конфиг статические адреса для каждого устройства, т.е. динамический адрес нужен аппарату только в первую и вторую загрузку, после третьей он уже полностью настроен и имеет статический IP. Посему я настроил время аренды – 5 минут, чтобы не занимать пул адресов в пустую. В общем случае адреса можно раздавать и динамически, сделав резервацию для каждого МАС-а. Кроме того нужно добавить опцию 66 или 160 – по вкусу, содержащую адрес сервера провизии. В винде это делается так:
В моем случае Mikrotik:
Итак, нужно чтобы динамически раздавались адреса и опции 66 с адресом сервера провизии. В моем случае диапазон динамических адресов с 20 до 99, а 101-199 диапазон для статических адресов, сделал так, чтобы внутренний номер абонента совпадал с его IP.
Настройка телефона по FTP
Для настройки по FTP нужен FTP, ставим (CentOS):
yum install -y vsftpd
chkconfig vsftpd on
service vsftpd start
Можете конфигурировать через /etc/vsftpd/vsftpd.conf .
Создадим пользователя под которым polycom будет пытаться подключиться:
useradd PlcmSpIp
passwd PlcmSpIp
Учитывая сложность пароля, будет нелишним позаботиться о том, чтобы данный пользователь был настолько бесправен, на сколько это возможно.
Теперь скачиваем архив с прошивкой и распаковываем его в /home/ PlcmSpIp
Когда будете качать прошивку читайте внимательно предупреждения, скорее всего придется скачать еще и обновления загрузчик, их так же распаковываем в директорию /home/ PlcmSpIp.
На данный момент подключенный к сети телефон должен при включении выкачать новый бутлоадер и прошивку и обновить ПО.
Работа с конфигурационными файлами
Тут я потерял уйму времени пытаясь править XML руками, и я заклинаю тебя, о читатель, не правь конфиги текстовым редактором, если ты не Оби-Ван-Кеноби в мире XML. Для работы с конфигами я использовал XML Notepad 2007. Если вы скачали прошивку combined-версии, то в папке config будет несколько конфигурационных файлов с расширением *.cfg и XML-схема polycomConfig.xsd.
*.cfg – примеры конфигурационных файлов тематически сгруппированы
polycomConfig.xsd | Схема |
video-integration.cfg | Настройка видео интеграции |
video.cfg | Настройка видео звонков |
site.cfg | Тут много всего, возможно даже все настройки |
sip-interop.cfg | Настройки sip, звонков, тонов |
sip-basic.cfg | Настройки sip |
region.cfg | Региональные настройки |
reg-basic.cfg | SIP-регистрации — базовая |
reg-advanced.cfg | SIP-регистрации — Расширенная |
H323.cfg | Настройки H323 |
features.cfg | Настройки переадресации удержания трансфера |
device.cfg | Настройки устройства, сетевые системные |
applications.cfg | Настройки приложений |
В каждом файле есть такая строка:
<polycomConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="polycomConfig.xsd">
Это значит, что если вы откроете конфигурационный файл XML-редактором, он будет искать в той же папке файл схемы polycomConfig.xsd, в нем содержаться все возможные поля конфигурационного файла и перечень доступных значений или краткий комментарий. На данном этапе нам нужно показать устройству, что загрузка должна происходить по протоколу HTTP и указать http-путь к файлам настройки.
Создадим в папке с polycomConfig.xsd текстовый файл custom.cfg следующего содержания.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<polycomConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="polycomConfig.xsd">
</polycomConfig>
Открываем его XML-редактором. Какие поля, что содержат нужно искать по средствам гугла или воспользоваться 600-страничной инструкцией для администратора по настройке телефонов то производителя.
Но по большей части все интуитивно понятно. Сначала создаем элемент (вероятно следует говорить раздел или еще как-то, но я не знаю и поэтому буду называть так, как они названы XML-редактором т.е. элементом) с помощью контекстного меню polycomConfig или просто ctrl+insert стоя на polycomConfig.
В падающем списке выбираем device т.к. нас интересуют настройки устройства, аналогичным образом создаем элемент device.dhcp в элементе device.
Теперь в нем создаем атрибут Alt+Insert или из контекстного меню на device.dhcp, открывается падающий список из доступных атрибутов, при наведении выскакивает подсказка с доступными значениями.
Ставим Static – в нашем случае это значит что опции 160 и 66 DHCP следует игнорировать. Аналогичным образом задаем другие параметры, в итоге имеем следующий файл:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<polycomConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="polycomConfig.xsd">
<device device.set="1">
<device.dhcp device.dhcp.bootSrvUseOpt="Static" device.dhcp.enabled="1">
<device.dhcp.enabled device.dhcp.enabled.set="1" />
<device.dhcp.bootSrvUseOpt device.dhcp.bootSrvUseOpt.set="1" />
</device.dhcp>
<device.prov device.prov.serverName="http://192.168.ххх.ххх:8088/phoneprov/" device.prov.serverType="HTTP">
<device.prov.serverName device.prov.serverName.set="1" />
<device.prov.serverType device.prov.serverType.set="1" />
</device.prov>
</device>
</polycomConfig>
<device device.set="1"> | Задать настройки для устройства |
device.dhcp.bootSrvUseOpt="Static" | Игнорировать опции 66 и 160 DHCP |
device.dhcp.enabled="1" | Использовать DHCP |
<device.dhcp.enabled device.dhcp.enabled.set="1" /> | Задать значение dhcp.enabled |
<device.dhcp.bootSrvUseOpt device.dhcp.bootSrvUseOpt.set="1" /> | Задать значение bootSrvUseOpt |
device.prov.serverName="http://192.168.ххх.ххх:8088/phoneprov/" | Путь к файлам |
device.prov.serverType="HTTP" | Тип сервера провизии |
<device.prov.serverName device.prov.serverName.set="1" /> | Задать значение serverName |
<device.prov.serverType device.prov.serverType.set="1" /> | Задать значение serverType |
Особое внимание стоит уделить атрибутам, выделенным житным шрифтом, это что-то вроде выключателя, т.е. не достаточно просто ввести значение какого-то параметра нужно еще и сказать конкретно «Да», этот параметр нужно применить. Особенно важно <device device.set="1"> т.к. если этом параметр 0, то все настройки элемента device будут проигнорированы.
Настройки Asterisk
Все, теперь наши телефоны будут просить файлы при загрузке у 192.168.ххх.ххх:8088/phoneprov/. Нужно их там сублимировать из небытия. Для этой цени у Asterisk’a есть специальный модуль, он позволяет автоматически генерировать файлы на основе шаблонов и отдавать их через встроенный HTTP-сервер астериска. Больше можно почерпнуть информации тут и частности там написано:
Удостовериться, что /etc/asterisk/manager.conf содержит:
[general]
enabled = yes; — вероятно так надо, хотя мне не понятно для чего именно
webenabled = yes; — вероятно так надо, хотя мне не понятно для чего именно
Удостовериться, что /etc/asterisk/http.conf содержит:
[general]
enabled = yes; включает встроенный HTTP-сервер
bindaddr = 192.168.ххх.ххх ; IP — на котором будет доступен сервер
bindport = 8088 ; — т.к. 80 порт у нас занят апачем, используем 8088
При запросе файла у http-сервера phoneprov берет шаблон файла и подставляет в него переменные которые берет из users.conf и, что особенно приятно можно использовать текстовые функции диал-плана. Например ${TOLOWER(${MAC})} в шаблоне будет заменен при формировании конфигурационного файла на МАС-адрес пользователя в нижнем регистре.
В шаблоне можно использовать следующие переменные:
fullname = User Two ; ${DISPLAY_NAME}
secret = test ; ${SECRET}
username = 6001 ; ${USERNAME}
macaddress = deadbeef4dad ; ${MAC}
label = 6001 ; ${LABEL}
cid_number = 6001 ; ${CALLERID}
кроме того можно использовать:
${SERVER} – берется из phoneprov.conf если там не задана, то берет значение bindaddr из http.conf
${SERVER_PORT} - берет значение bindport из sip.conf, если оно не задано, то 5060
Конфигурационный файл самого res_phoneprov лежит /etc/asterisk/phoneprov.conf, в нем нужно указать директорию статических файлов относительно пути /var/lib/asterisk/phoneprov/, перечень статических файлов, перечень шаблонов и шаблоны имен динамически-формируемых файлов. Вот пример:
[general]
serveraddr=192.168.ххх.ххх ; задается переменная ${SERVER}.
serverport=5060 ; задается переменная ${SERVER_PORT}.
default_profile=polycom ; профиль по умолчанию если не задан в users.conf
[polycom]
staticdir => configs/ ; Сюда кладете статические файлы, прошивку, фоновые картинки, телефонный справочник и т.п., путь относительно /var/lib/asterisk/phoneprov/
mime_type => text/xml
static_file => 2345-12345-001.bootrom.ld
static_file => 2345-12360-001.bootrom.ld
static_file => 2345-12365-001.bootrom.ld
static_file => 2345-12365-002.bootrom.ld
static_file => 2345-12375-001.bootrom.ld
static_file => 2345-12375-002.bootrom.ld
static_file => 2345-12450-001.bootrom.ld
static_file => 2345-12450-002.bootrom.ld
static_file => 2345-12500-001.bootrom.ld
static_file => 2345-12560-001.bootrom.ld
static_file => 2345-12600-001.bootrom.ld
static_file => 2345-12600-002.bootrom.ld
static_file => 2345-12670-001.bootrom.ld
static_file => 2345-12670-002.bootrom.ld
static_file => 3111-15600-001.bootrom.ld
static_file => 3111-30900-001.bootrom.ld
static_file => 3111-40000-001.bootrom.ld
static_file => bootrom.ld
static_file => sip.ver
static_file => sip.ld
static_file => 000000000000-directory.xml ;- это телефонный справочник
static_file => languages/Website_dictionary_language_ru-ru.xml
static_file => SoundPointIPLocalization/Russian_Russia/SoundPointIP-dictionary.xml
;------------шаблоны
${TOLOWER(${MAC})}.cfg => 000000000000.cfg ;Это значит, что при запросе http://192.168.ххх.ххх:8088/phoneprov/111111111111.cfg будет сформирован файл из шаблона 000000000000.cfg с именем 111111111111.cfg, при этом значения переменных будут взяты из файла users.conf из того юзера у которого macaddress=111111111111
${TOLOWER(${MAC})}-custom.cfg => 000000000000-phone.cfg ;При запросе файла http://192.168.ххх.ххх:8088/phoneprov/111111111111-custom.cfg будет сформирован файл 111111111111-custom.cfg при этом значения переменных будут взяты из файла users.conf из того юзера у которого macaddress=111111111111
Со статическими файлами все просто, если файл прописан в phoneprov.conf и находится по соответствующему адресу, то он будет доступен с веб-сервера.
С динамическими вроде немного сложнее, но сейчас все станет понятно. Вот пример шаблонов:
000000000000.cfg
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<APPLICATION APP_FILE_PATH="sip.ld" CONFIG_FILES="${TOLOWER(${MAC})}-custom.cfg" MISC_FILES="" LOG_FILE_DIRECTORY="" OVERRIDES_DIRECTORY="" CONTACTS_DIRECTORY="" LICENSE_DIRECTORY="" USER_PROFILES_DIRECTORY="" CALL_LISTS_DIRECTORY="">
</APPLICATION>
По умолчанию все телефоны запрашивают файл 1234123adba.cfg, где 1234123adba – МАС-адрес телефона, т.е. телефон отправит запрос http://192.168.ххх.ххх:8088/phoneprov/1234123adba.cfg. В данном шаблоне всего одна переменная, и директива CONFIG_FILES="${TOLOWER(${MAC})}-custom.cfg" превратиться в CONFIG_FILES="1234123adba-custom.cfg", что говорит телефону, что он должен скачать конфигурационный файл 1234123adba-custom.cfg. Телефон отправит запрос http://192.168.ххх.ххх:8088/phoneprov/1234123adba.cfg-custom.cfg в ответ на данный запрос сервер сформирует еще один динамический файл на основе второго шаблона 000000000000-phone.cfg:
000000000000-phone.cfg
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<polycomConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="polycomConfig.xsd">
<call call.callsPerLineKey="2"></call>
<reg reg.1.address="${USERNAME}" reg.1.auth.password="${SECRET}" reg.1.auth.userId="${USERNAME}" reg.1.label="${USERNAME}" reg.1.outboundProxy.address="${SERVER}" reg.1.lineKeys="2" reg.1.auth.domain="${SERVER}" reg.1.displayName="${USERNAME}" reg.1.server.1.address="${SERVER}" reg.1.server.1.register="1"></reg>
<device device.set="1">
<device.dhcp device.dhcp.bootSrvUseOpt="Static" device.dhcp.enabled="0">
<device.dhcp.enabled device.dhcp.enabled.set="1" />
<device.dhcp.bootSrvUseOpt device.dhcp.bootSrvUseOpt.set="1" />
</device.dhcp>
<device.dns device.dns.serverAddress="192.168.xxx.1" device.dns.altSrvAddress="8.8.8.8">
<device.dns.serverAddress device.dns.serverAddress.set="1" />
</device.dns>
<device.prov device.prov.serverName="http://192.168.xxx.xxx:8088/phoneprov/" device.prov.serverType="HTTP">
<device.prov.serverName device.prov.serverName.set="1" />
<device.prov.serverType device.prov.serverType.set="1" />
</device.prov>
<device.net device.net.ipAddress="192.168.XXX.${USERNAME}" device.net.subnetMask="255.255.255.0" device.net.IPgateway="192.168.xxx.1">
<device.net.ipAddress device.net.ipAddress.set="1" />
<device.net.subnetMask device.net.subnetMask.set="1" />
<device.net.IPgateway device.net.IPgateway.set="1" />
</device.net>
<device.sntp device.sntp.gmtOffset="14400" device.sntp.serverName="pool.ntp.org">
<device.sntp.gmtOffset device.sntp.gmtOffset.set="1" />
<device.sntp.serverName device.sntp.serverName.set="1" />
</device.sntp>
</device>
<dialplan dialplan.1.digitmap="" dialplan.1.digitmap.timeOut="" dialplan.1.impossibleMatchHandling="2" />
<lcl>
<lcl.ml lcl.ml.lang="Russian_Russia" />
</lcl>
<tcpIpApp>
<tcpIpApp.sntp.daylightSavings tcpIpApp.sntp.daylightSavings.enable="0" />
</tcpIpApp.sntp>
</tcpIpApp>
</polycomConfig>
Тут используется несколько переменных:
${SECRET} подставит значение secret из описания юзера с маком 1234123adba из users.conf
${USERNAME} подставит значение username из описания юзера с маком 1234123adba из users.conf.
${SERVER} подставит значение из phoneprov.conf
Обратите внимание! После изменения phoneprov.conf нужен reloadчтобы настройки подтянулись.
После того как все готово проверьте через консоль:
phoneprov show routes
Должны отображаться статические маршруты, динамические будут только если в users.conf есть юзеры у которых autoprov = yes и задан мас-адрес
Настройка users.conf
Почти все, осталось создать /etc/asterisk/users.conf. Тут тоже нашлась возможность для оптимизации. Приложением zxing для андроида я просканировал все МАС-адреса телефонов, прямо с коробок, и из того-же приложения отправил их себе на почту. Осталось дело за малым сопоставить каждому маку какой-то аккаунт. Руками писать для каждого macaddress=……, как-то не хотелось. Я сделал файл для автоматической генерации конфигов Asterisk на основе табличных данных, в нем же есть генератор паролей.
Осталось только скопировать столбец и вставить в users.conf. Телефоны в данном проекте все одинаковые потому есть смысл создать для всех шаблон, а в описании юзера добавить только МАС и пароль.
/etc/asterisk/users.conf
...
[def](!) ;- умолчательный шаблон
type=friend
fromuser="CPZ"
host=dynamic
nat=no
disallow=all
allow=ulaw
allow=alaw
hasvoicemail = no
hassip = yes
hasiax = no
hash323 = no
hasmanager = no
qualify=yes
autoprov = yes ;- включить для этого юзера автопровизию
context=full
[101](def)
secret=XAHNGNCCXGR
macaddress=0004f24ab859
[102](def)
secret=OSANPHVZIEX
macaddress=0004f24abdd6
[103](def)
secret=AHUDYLSXFGT
macaddress=0004f24ab766
……
Все готово проверьте через консоль: phoneprov show routes
Должны отображаться и статические маршруты и динамические маршруты. Осталось проверить браузером 192.168.ххх.ххх:8088/phoneprov/1234123adba.cfg например, и можно включать телефоны, дальше все происходит само.
Не забывайте про безопасность, после развертывания инфраструктуры лучше отключить фпт-сервер и на астериске встроенный веб-сервер, до необходимости обновления конфигов или ПО. Если вдруг конфигурации необходимо часто менять используйте HTTPS.
Автор: ShakinNN