В прошлой заметке Соединение двух Asterisk через SIP мы рассмотрели соединение двух станций по протоколу SIP. Среди всех поддерживаемых Asterisk протоколов особое место занимает протокол IAX, а точнее - IAX2. Это собственный протокол Asterisk, название которого расшифровывается как Inter-Asterisk eXchange protocol - протокол обмена между Asterisk. Протокол первой версии в настоящее время уже не поддерживается, а его место заняла вторая версия. Для простоты номер версии обычно не оговаривают и под IAX обычно подразумевается IAX2. Этот протокол работает по UDP-порту 4569 и предназначен не только для обмена сеансовой информацией, но и для обмена голосовой информацией. Кроме всего прочего, протокол умеет агрегировать несколько параллельных сеансов в рамках одного соединения, так что в одном UDP-пакете может одновременно передаваться сеансовая и голосовая информация нескольких разговоров.
Как и в прошлой статье, в описании ниже предполагается, что первая станция называется desktop, имеет IP-адрес 169.254.254.1, к ней подключены телефоны с номерами 1XXX. Вторая станция называется notebook и имеет IP-адрес 169.254.254.4, к ней подключены телефоны с номерами 2XXX.
Откроем файл /etc/asterisk/iax.conf на станции desktop и добавим туда шаблон для телефонных станций и учётную запись IAX, через которую desktop будет принимать звонки от телефонной станции notebook:
[asterisk_iax2](!) language=ru type=friend context=stations host=dynamic trunk=yes deny=0.0.0.0/0 [notebook](asterisk_iax2) secret=notebook_password permit=169.254.254.4
Телефонная станция notebook сможет зарегистрироваться только с IP-адреса 169.254.254.4. Входящие звонки будут попадать в контекст stations. Настройка trunk=yes указывает, что по этому каналу можно передавать несколько одновременных звонков.
Теперь откроем файл /etc/asterisk/iax.conf на станции notebook и впишем туда следующие симметричные настройки:
[asterisk_iax2](!) language=ru type=friend context=stations host=dynamic trunk=yes deny=0.0.0.0/0 [desktop](asterisk_iax2) secret=desktop_password permit=169.254.254.1
Теперь выполним на обеих телефонных станциях следующую команду, чтобы на них появились учётные записи IAX2:
# asterisk -rx 'iax2 reload'
Звонки, поступающие от удалённых станций будут попадать в контексты stations. Удалённые станции должны иметь возможность дозвониться на номера местной станции. Впишем в файл /etc/asterisk/extensions.conf на станции desktop соответствующий контекст:
[stations] include => test exten => _1XXX,1,Dial(SIP/${EXTEN})
Соответственно, чтобы абоненты удалённых станций могли позвонить абонентам станции notebook, впишем в файл /etc/asterisk/extensions.conf на станции notebook симметричный контекст:
[stations] exten => _2XXX,1,Dial(SIP/${EXTEN})
Как можно увидеть, тестовые номера 5XX будут обслуживаться станцией desktop.
Выполним на обеих станциях команды, которые создадут на них контексты stations:
# asterisk -rx 'dialplan reload'
Теперь заставим обе телефонные станции подключиться друг к другу. Для этого впишем в секцию globals в файле /etc/asterisk/iax.conf на станции desktop такие настройки:
[general] autokill=yes register => desktop:desktop_password@169.254.254.4
Эта строчка предписывает зарегистрироваться на станции notebook под именем desktop и с паролем desktop_password. В секции глобальных настроек указана настройка autokill=yes, которая завершает неудачно установленные соединения по тайм-ауту.
Теперь впишем в секцию globals в файле /etc/asterisk/iax.conf на станции notebook симметричные настройки:
[general] autokill=yes register => notebook:notebook_password@169.254.254.1
Выполним на обеих телефонных станциях команду, после которой станции должны будут зарегистрироваться друг на друге:
# asterisk -rx 'iax2 reload'
Чтобы проверить, зарегистрировалась ли эта станция на удалённой, можно воспользоваться такой командой:
# asterisk -rx 'iax2 show registry'
Чтобы проверить, зарегистрировалась ли удалённая станция на этой, пригодится такая команда:
# asterisk -rx 'iax2 show peers'
По умолчанию эта команда покажет настроенную нами учётную запись как ненаблюдаемую (Unmonitored). Чтобы в списке отображалось текущее состояние регистрации, в настройки соответствующей учётной записи можно добавить опцию qualify=yes. Если указана эта настройка, состояние входящего подключения будет периодически проверяться специальными запросами, напоминающими пинг. Вместо значения yes можно указать периодичность проверки состояния подключения в секундах. По результатам проверки в списке будет отображаться состояние OK или UNREACHABLE.
Вся необходимая подготовка уже выполнена, осталось только объяснить обеим станциям, звонки на какие телефонные номера нужно направлять через IAX-подключение к другой станции.
Откроем файл /etc/asterisk/extensions.conf на станции desktop и приведём контекст internal к следующему виду:
[internal] include => test exten => _1XXX,1,Dial(SIP/${EXTEN}) exten => _2XXX,1,Dial(IAX2/desktop:desktop_password@169.254.254.4/${EXTEN})
Из этого контекста видно, что звонки на тестовые номера и номера 1XXX будут обрабатываться самой станцией desktop, а звонки на номера 2XXX будут направляться через IAX-подключение к станции с IP-адресом 169.254.254.4, то есть - к станции notebook. Там они попадут в контекст stations, в котором предписывается направлять вызовы SIP-абонентам самой станции notebook.
Откроем файл /etc/asterisk/extensions.conf на станции notebook и приведём контекст internal к такому виду:
[internal] exten => _5XX,1,Dial(IAX2/notebook:notebook_password@169.254.254.1/${EXTEN}) exten => _1XXX,1,Dial(IAX2/notebook:notebook_password@169.254.254.1/${EXTEN}) exten => _2XXX,1,Dial(SIP/${EXTEN})
Звонки на номера 2XXX будут обрабатываться внутри самой станции notebook, а звонки на тестовые номера 5XX и номера 1XXX будут направляться через IAX-подключение к станции с IP-адресом 169.254.254.1, то есть - на станцию desktop, где так же попадут в контекст stations. Там же уже прописано, как нужно обрабатывать входящие звонки на эти номера.
Осталось перезагрузить номерные планы на обеих станциях:
# asterisk -rx 'dialplan reload'
Одна из проблем, с которой я столкнулся, заключалась в том, что в одной из записей номерного плана я указал вместо протокола SIP протокол IAX. Поэтому до нужного мне номера дозвониться не удавалось. Обычная невнимательность.
Для экспериментов я пользовался примерами из книги "Asterisk. Будущее телефонии" авторов Ван Меггелен, Мадсен, Смит. Указанные в книге примеры, подобные показанному ниже, не работали:
exten => _5XX,1,Dial(IAX2/notebook/${EXTEN})
Проблема сопровождалась ошибками следующего вида:
[Mar 21 21:04:13] NOTICE[1115] chan_iax2.c: Auto-congesting call due to slow response
Долгие проверки файлов конфигурации на предмет возможных ошибок не помогли. Несколько попыток разобрать отладочный вывод, включенный командой iax2 debug on, не принесли результата. И только через некоторое время я обратил внимание на IP-адрес 127.0.0.1 в отладочном выводе. Оказалось, что имя notebook было прописано в файл /etc/hosts. По этой причине происходила попытка установить IAX-подключение по IP-адресу 127.0.0.1. Когда я удалил эту запись из файла, стали появляться ошибки другого рода:
[Mar 22 22:01:42] ERROR[6086][C-00000008] netsock2.c: getaddrinfo("notebook", "(null)", ...): Name or service not known [Mar 22 22:01:42] WARNING[6086][C-00000008] acl.c: Unable to lookup 'notebook' [Mar 22 22:01:42] WARNING[6086][C-00000008] chan_iax2.c: No such host: notebook [Mar 22 22:01:42] WARNING[6086][C-00000008] app_dial.c: Unable to create channel of type 'IAX2' (cause 20 - Subscriber absent)
Попытка заменить имя учётной записи на IP-адрес удалённой станции не помогла:
[Mar 23 21:38:16] NOTICE[1232] acl.c: IAX2 user ACL: Rejecting '169.254.254.4' due to a failure to pass ACL '(BASELINE)'
Подключение устанавливалось на правильный IP-адрес, но не использовало имя пользователя и пароль для авторизации. Чтобы пример из книжки заработал, пришлось прописать все настройки подключения:
exten => _5XX,1,Dial(IAX2/notebook:notebook_password@169.254.254.1/${EXTEN})
Указывать имя пользователя, пароль и адрес удалённой станции каждый раз не удобно. Избавиться от такого неудобства, насколько я понял, можно при помощи раздельных учётных записей для исходящих и входящих подключений. С этим я попробую разобраться попозже. Сейчас же я ограничился первым рабочим вариантом.