Соединение двух Asterisk через IAX2

В прошлой заметке Соединение двух 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.

1. Создание учётных записей

Откроем файл /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'

2. Входящие звонки с удалённых станций

Звонки, поступающие от удалённых станций будут попадать в контексты 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'

3. Взаимная регистрация телефонных станций

Теперь заставим обе телефонные станции подключиться друг к другу. Для этого впишем в секцию 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.

4. Исходящие звонки на удалённые станции

Вся необходимая подготовка уже выполнена, осталось только объяснить обеим станциям, звонки на какие телефонные номера нужно направлять через 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'

5. Возможные проблемы

Одна из проблем, с которой я столкнулся, заключалась в том, что в одной из записей номерного плана я указал вместо протокола 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})

Указывать имя пользователя, пароль и адрес удалённой станции каждый раз не удобно. Избавиться от такого неудобства, насколько я понял, можно при помощи раздельных учётных записей для исходящих и входящих подключений. С этим я попробую разобраться попозже. Сейчас же я ограничился первым рабочим вариантом.

Написать автору