воскресенье, 24 апреля 2016 г.

Соединение двух Asterisk через раздельные учётные записи IAX2 для входящих и исходящих звонков

Рассмотрим соединение двух станций Asterisk по протоколу IAX2. В прошлой заметке, в которой была описана настройка IAX2, я использовал учётные записи типа friend, каждая из которых использовалась как для входящих, так и для исходящих звонков. В этот раз я воспользуюсь учётными записями типов peer и user. Учётная запись типа peer будет использоваться для исходящих звонков, а учётная запись типа user - для входящих. При этом фактически учётная запись типа peer подключается к учётной записи типа user на другой станции, а для двустороннего обмена звонками используется два отдельных подключения.

Повторю пару абзацев из своей прошлой заметки о раздельных учётных записях SIP, которые полностью справедливы и для случая учётных записей IAX2. На самом деле учётная запись любого типа может использоваться для входящих и исходящих звонков. Учётная запись user для входящих звонков будет требовать у удалённой стороны пройти процедуру аутентификации, я для получения исходящих звонков удалённая сторона должна зарегистрироваться в системе - указать свой IP-адрес и порт, куда отправлять звонки. Учётная запись типа peer при совершении исходящих звонков готова пройти аутентификацию на удалённой стороне, а для входящих звонков от удалённой стороны проверяет только соответствие IP-адреса и порта удалённой стороны, но не требует аутентификации.

Разделением учётных записей на peer и user мы добьёмся, кроме всего прочего, того, что входящий звонок всегда будет поступать с данными аутентификации, а не будет полагаться на соответствие IP-адреса и порта удалённой стороны. Потенциальный взломщик, сидящий за сервером NAT, не сможет притвориться соседом, воспользовавшись одинаковым с соседом IP-адресом NAT-сервера, и совершить звонок в систему от имени соседа. Также звонки из системы будут всегда уходить в заранее предусмотренном направлении, а не туда, откуда совершена регистрация. Если злоумышленник раздобудет логин и пароль и зарегистрируется в системе, звонки всё равно будут уходить туда, куда указывают настройки из файла конфигурации.

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

Как и в прошлых заметках, первая станция называется desktop, имеет IP-адрес 169.254.254.1, к ней подключены телефоны с номерами 1XXX. Вторая станция называется notebook и имеет IP-адрес 169.254.254.4, к ней подключены телефоны с номерами 2XXX.

1. Создание учётных записей для входящих звонков

Откроем файл /etc/asterisk/iax.conf на станции desktop и добавим туда шаблон для телефонных станций и учётную запись IAX2, через которую desktop будет принимать звонки от телефонной станции notebook:
[asterisk_iax_in](!)
language=ru
type=user
context=stations
host=dynamic
trunk=yes
;qualify=yes
;transfer=no
deny=0.0.0.0/0

[notebook](asterisk_iax_in)
secret=notebook_password
permit=169.254.254.4
Телефонная станция notebook сможет зарегистрироваться только с IP-адреса 169.254.254.4. Входящие звонки будут попадать в контекст stations.

Теперь откроем файл /etc/asterisk/iax.conf на станции notebook и впишем туда следующие симметричные настройки:
[asterisk_iax_in](!)
language=ru
type=user
context=stations
host=dynamic
trunk=yes
;qualify=yes
;transfer=no
deny=0.0.0.0/0

[desktop](asterisk_iax_in)
secret=desktop_password
permit=169.254.254.1
Теперь выполним на обеих телефонных станциях следующую команду, чтобы на них появились учётные записи IAX2:
# asterisk -rx 'iax2 reload'
2. Создание учётных записей для исходящих звонков

Откроем файл /etc/asterisk/iax.conf на станции desktop и создадим учётную запись, через которую станция desktop будет направлять звонки на станцию notebook:
[asterisk_iax_out](!)
language=ru
type=peer
trunk=yes
;transfer=no

[to_desktop](asterisk_iax_out)
fromuser=desktop
secret=desktop_password
host=169.254.254.4
Откроем файл /etc/asterisk/iax.conf на станции notebook и впишем симметричные настройки - создадим учётную запись, через которую станция notebook будет отправлять звонки на станцию desktop:
[asterisk_iax_out](!)
language=ru
type=peer
trunk=yes
;transfer=no
  
[to_desktop](asterisk_iax_out)
fromuser=notebook
secret=notebook_password
host=169.254.254.1
Теперь выполним на обеих телефонных станциях следующую команду, чтобы на них появились учётные записи IAX2:
# asterisk -rx 'iax2 reload'
В отличие от прошлой статьи, где были настроены учётные записи типа friend, здесь отсутствуют выражения register. Регистрация используется для информирования удалённой стороны о том, в каком направлении нужно отправлять обратные звонки. В прошлой статье регистрация использовалась скорее только для установки подключения и для его именования, но информация о местоположении удалённой стороной реально не использовалась. В этой статье выражения register отсутствуют, поскольку их роль выполняют учётные записи типа peer.

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

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

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

Откроем файл /etc/asterisk/extensions.conf на станции desktop и приведём контекст internal к следующему виду:
[internal]
include => test

exten => _1XXX,1,Dial(SIP/${EXTEN})

exten => _2XXX,1,Dial(IAX2/to_notebook/${EXTEN})
Из этого контекста видно, что звонки на тестовые номера и номера 1XXX будут обрабатываться самой станцией desktop, а звонки на номера 2XXX будут направляться через IAX2-подключение to_notebook, то есть - на станцию notebook. Там они попадут в контекст stations, в котором предписывается направлять вызовы SIP-абонентам самой станции notebook.

Откроем файл /etc/asterisk/extensions.conf на станции notebook и приведём контекст internal к такому виду:
[internal]
exten => _5XX,1,Dial(IAX2/to_desktop/${EXTEN})

exten => _1XXX,1,Dial(IAX2/to_desktop/${EXTEN})

exten => _2XXX,1,Dial(SIP/${EXTEN})
Звонки на номера 2XXX будут обрабатываться внутри самой станции notebook, а звонки на тестовые номера 5XX и номера 1XXX будут направляться через IAX2-подключение to_desktop, то есть - на станцию desktop, где так же попадут в контекст stations. Там же уже прописано, как нужно обрабатывать входящие звонки на эти номера.

Осталось перезагрузить номерные планы на обеих станциях:
# asterisk -rx 'dialplan reload'

воскресенье, 17 апреля 2016 г.

Соединение двух Asterisk через раздельные учётные записи SIP для входящих и исходящих звонков

Эта заметка является усовершенствованным вариантом заметки Соединение двух Asterisk через SIP. В прошлой заметке я использовал учётные записи типа friend, каждая из которых может использоваться как для входящих, так и для исходящих звонков. В этот раз я воспользуюсь учётными записями типов peer и user. Учётная запись типа peer будет использоваться для совершения исходящих звонков, а учётная запись типа user - для входящих. При этом фактически учётная запись типа peer подключается к учётной записи типа user на другой станции, а для двустороннего обмена звонками используется два отдельных разнонаправленных подключения.

На самом деле учётная запись любого типа может использоваться для входящих и исходящих звонков. Учётная запись user для входящих звонков будет требовать у удалённой стороны пройти процедуру аутентификации, я для получения исходящих звонков удалённая сторона должна зарегистрироваться в системе - указать свой IP-адрес и порт, куда отправлять звонки. Учётная запись типа peer при совершении исходящих звонков готова пройти аутентификацию на удалённой стороне, а для входящих звонков от удалённой стороны проверяет только соответствие IP-адреса и порта удалённой стороны, но не требует аутентификации.

Разделением учётных записей на peer и user мы добьёмся, кроме всего прочего, того, что входящий звонок всегда будет поступать с данными аутентификации, а не будет полагаться на соответствие IP-адреса и порта удалённой стороны. Потенциальный взломщик, сидящий за сервером NAT, не сможет притвориться соседом, воспользовавшись одинаковым с соседом IP-адресом NAT-сервера, и совершить звонок в систему от имени соседа. Также звонки из системы будут всегда уходить в заранее предусмотренном направлении, а не туда, откуда совершена регистрация. Если злоумышленник раздобудет логин и пароль и зарегистрируется в системе, звонки всё равно будут уходить туда, куда указывают настройки из файла конфигурации.

Как и в прошлых заметках, первая станция называется desktop, имеет IP-адрес 169.254.254.1, к ней подключены телефоны с номерами 1XXX. Вторая станция называется notebook и имеет IP-адрес 169.254.254.4, к ней подключены телефоны с номерами 2XXX.

1. Создание учётных записей для входящих звонков

Откроем файл /etc/asterisk/sip.conf на станции desktop и добавим туда шаблон для телефонных станций и учётную запись SIP, через которую desktop будет принимать звонки от телефонной станции notebook:
[asterisk_sip_in](!)
language=ru
type=user
context=stations
host=dynamic
insecure=invite,port
trunk=yes
deny=0.0.0.0/0

[notebook](asterisk_sip_in)
secret=notebook_password
permit=169.254.254.4
Телефонная станция notebook сможет зарегистрироваться только с IP-адреса 169.254.254.4. Входящие звонки будут попадать в контекст stations.

Теперь откроем файл /etc/asterisk/sip.conf на станции notebook и впишем туда следующие симметричные настройки:
[asterisk_sip_in](!)
language=ru
type=user
context=stations
host=dynamic
insecure=invite,port
trunk=yes
deny=0.0.0.0/0

[desktop](asterisk_sip_in)
secret=desktop_password
permit=169.254.254.1
Теперь выполним на обеих телефонных станциях следующую команду, чтобы на них появились учётные записи SIP:
# asterisk -rx 'sip reload'
2. Создание учётных записей для исходящих звонков

Откроем файл /etc/asterisk/sip.conf на станции desktop и создадим учётную запись, через которую станция desktop будет направлять звонки на станцию notebook:
[asterisk_sip_out](!)
language=ru
type=peer
trunk=yes

[to_notebook](asterisk_sip_out)
fromuser=desktop
secret=desktop_password
host=169.254.254.4
Откроем файл /etc/asterisk/sip.conf на станции notebook и впишем симметричные настройки - создадим учётную запись, через которую станция notebook будет отправлять звонки на станцию desktop:
[asterisk_sip_out](!)
language=ru
type=peer
trunk=yes

[to_desktop](asterisk_sip_out)
fromuser=notebook
secret=notebook_password
host=169.254.254.1
Теперь выполним на обеих телефонных станциях следующую команду, чтобы на них появились учётные записи SIP:
# asterisk -rx 'sip reload'
В отличие от прошлой статьи, где были настроены учётные записи типа friend, здесь отсутствуют выражения register. Регистрация используется для информирования удалённой стороны о том, в каком направлении нужно отправлять обратные звонки. В прошлой статье регистрация использовалась скорее только для установки подключения и для его именования, но информация о местоположении удалённой стороной реально не использовалась. В этой статье выражения register отсутствуют, поскольку их роль выполняют учётные записи типа peer.

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

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

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

Откроем файл /etc/asterisk/extensions.conf на станции desktop и приведём контекст internal к следующему виду:
[internal]
include => test

exten => _1XXX,1,Dial(SIP/${EXTEN})

exten => _2XXX,1,Dial(SIP/to_notebook/${EXTEN})
Из этого контекста видно, что звонки на тестовые номера и номера 1XXX будут обрабатываться самой станцией desktop, а звонки на номера 2XXX будут направляться через SIP-подключение to_notebook, то есть - на станцию notebook. Там они попадут в контекст stations, в котором предписывается направлять вызовы SIP-абонентам самой станции notebook.

Откроем файл /etc/asterisk/extensions.conf на станции notebook и приведём контекст internal к такому виду:
[internal]
exten => _5XX,1,Dial(SIP/to_desktop/${EXTEN})

exten => _1XXX,1,Dial(SIP/to_desktop/${EXTEN})

exten => _2XXX,1,Dial(SIP/${EXTEN})
Звонки на номера 2XXX будут обрабатываться внутри самой станции notebook, а звонки на тестовые номера 5XX и номера 1XXX будут направляться через SIP-подключение to_desktop, то есть - на станцию desktop, где так же попадут в контекст stations. Там же уже прописано, как нужно обрабатывать входящие звонки на эти номера.

Осталось перезагрузить номерные планы на обеих станциях:
# asterisk -rx 'dialplan reload'

воскресенье, 10 апреля 2016 г.

Соединение двух 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})
Указывать имя пользователя, пароль и адрес удалённой станции каждый раз не удобно. Избавиться от такого неудобства, насколько я понял, можно при помощи раздельных учётных записей для исходящих и входящих подключений. С этим я попробую разобраться попозже. Сейчас же я ограничился первым рабочим вариантом.

воскресенье, 3 апреля 2016 г.

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

В прошлой заметке Шаблоны и настройка звонков между SIP-клиентами в Asterisk мы научились соединять между собой абонентов одной станции. В этот раз попробуем настроить связь между двумя станциями Asterisk, чтобы дать возможность общаться между собой их абонентам. Для этого я воспользовался настольным компьютером и ноутбуком. Соответственно, в описании ниже они называются desktop и notebook.

Прежде чем соединять телефонные станции между собой, продумаем номерной план. Для телефонов на станции desktop я решил использовать четырёхзначные номера, начинающиеся с единицы. Для телефонов на станции notebook я решил использовать четырёхзначные номера, начинающиеся с двойки. В дальнейшем такое правило позволит нам настроить маршрутизацию звонков между телефонными станциями.

1. Контекст для тестовых номеров

В прошлых заметках были настроены тестовые номера 5XX. Выделим их в отдельную секцию с именем test. Откроем файл номерного плана /etc/asterisk/extensions.conf на телефонной станции desktop и сформируем такую секцию:
[test]

exten => 500,1,Playback(demo-echotest)
same  =>     n,Echo()
same  =>     n,Playback(demo-echodone)

exten => 501,1,MusicOnHold()

exten => 502,1,SayDigits(${CALLERID(num)})

exten => 503,1,SayNumber(${CALLERID(num)})

exten => 504,1,SayNumber(${CALLERID(num)})
same  =>     n,Wait(1)
same  =>     n,SayDigits(${CALLERID(num)})
Чтобы с телефонов, подключенных к станции desktop, по-прежнему можно было позвонить на тестовые номера, добавим в контекст internal строчку, подключающую контекст test:
[internal]
include => test

exten => _1XXX,1,Dial(SIP/${EXTEN})
На станции notebook в файле номерного плана /etc/asterisk/extensions.conf контекст internal при этом выглядит так:
[internal]

exten => _2XXX,1,Dial(SIP/${EXTEN})
Как обычно, чтобы новый номерной план вступил в силу, выполним команду:
# asterisk -rx 'dialplan show'
2. Создание учётных записей

Откроем файл /etc/asterisk/sip.conf на станции desktop и добавим туда шаблон учётных записей SIP для телефонных станций и саму учётную запись SIP на основе этого шаблона, через которую телефонная станция desktop будет принимать звонки от телефонной станции notebook:
[asterisk_sip](!)
language=ru
type=friend
context=stations
host=dynamic
insecure=invite,port
trunk=yes

[notebook](asterisk_sip)
secret=notebook_password
deny=0.0.0.0/0.0.0.0
permit=169.254.254.4
Телефонная станция notebook сможет зарегистрироваться только с IP-адреса 169.254.254.4. Входящие звонки будут попадать в контекст stations. Звонящей телефонной станции нужно будет авторизоваться только при регистрации, а авторизация при поступлении запросов invite проверяться не будет (insecure=invite,port). Это значит, что с удалённой телефонной станции могут поступать звонки от телефонов, отсутствующих на локальной телефонной станции. Эта настройка очень важная. Если её пропустить, входящие звонки будут отбрасываться как неавторизованные, поскольку будут поступать не от имени удалённой телефонной станции, для которой создана учётная запись, а от имени телефона, подключенного к ней.

Теперь откроем файл /etc/asterisk/sip.conf на станции notebook и впишем туда следующие симметричные настройки:
[asterisk_sip](!)
language=ru
type=friend
context=stations
host=dynamic
insecure=invite,port
trunk=yes

[desktop](asterisk_sip)
secret=desktop_password
deny=0.0.0.0/0.0.0.0
permit=169.254.254.1
Теперь выполним на обеих телефонных станциях следующую команду, чтобы на них появились учётные записи SIP:
# asterisk -rx 'sip reload'
3. Входящие звонки с удалённых станций

Звонки, поступающие от удалённых станций будут попадать в контексты 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'
4. Взаимная регистрация телефонных станций

Теперь заставим обе телефонные станции подключиться друг к другу. Для этого впишем в секцию globals в файле /etc/asterisk/sip.conf на станции desktop такие настройки:
register => desktop:desktop_password@169.254.254.4/notebook
Эта строчка предписывает зарегистрироваться на станции notebook под именем desktop и с паролем desktop_password. Установленное SIP-подключение будет называться notebook. Это название в дальнейшем можно будет использовать в номерном плане для вызова абонентов, подключенных к станции notebook.

Теперь впишем в секцию globals в файле /etc/asterisk/sip.conf на станции notebook симметричные настройки:
register => notebook:notebook_password@169.254.254.1/desktop
Выполним на обеих телефонных станциях команду, после которой станции должны будут зарегистрироваться друг на друге:
# asterisk -rx 'sip reload'
Чтобы проверить, зарегистрировалась ли эта станция на удалённой, можно воспользоваться такой командой:
# asterisk -rx 'sip show registry'
Чтобы проверить, зарегистрировалась ли удалённая станция на этой, пригодится такая команда:
# asterisk -rx 'sip show peers'
5. Исходящие звонки на удалённые станции

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

Откроем файл /etc/asterisk/extensions.conf на станции desktop и приведём контекст internal к следующему виду:
[internal]
include => test

exten => _1XXX,1,Dial(SIP/${EXTEN})

exten => _2XXX,1,Dial(SIP/notebook/${EXTEN})
Из этого контекста видно, что звонки на тестовые номера и номера 1XXX будут обрабатываться самой станцией desktop, а звонки на номера 2XXX будут направляться через SIP-подключение, помеченное как notebook. Там они попадут в контекст stations, в котором предписывается направлять вызовы SIP-абонентам самой станции notebook.

Откроем файл /etc/asterisk/extensions.conf на станции notebook и приведём контекст internal к такому виду:
[internal]
exten => _5XX,1,Dial(SIP/desktop/${EXTEN})

exten => _1XXX,1,Dial(SIP/desktop/${EXTEN})

exten => _2XXX,1,Dial(SIP/${EXTEN})
Звонки на номера 2XXX будут обрабатываться внутри самой станции notebook, а звонки на тестовые номера 5XX и номера 1XXX будут направляться через SIP-подключение, названное desktop. То есть - будут отправляться на станцию desktop, где так же попадут в контекст stations. Там же уже прописано, как нужно обрабатывать входящие звонки на эти номера.

Осталось перезагрузить номерные планы на обеих станциях:
# asterisk -rx 'dialplan reload'

Теперь можно пробовать звонить.
6. Возможные проблемы

Я лично при настройке этой конфигурации столкнулся с двумя проблемами.

Первая проблема заключалась в том, что при поступлении звонка с удалённой станции, звонок отклонялся как неавторизованный. Выглядело это как отказ станции desktop принимать звонок с номера 2000, принадлежащего станции notebook (и наоборот):
[Mar 15 20:33:41] NOTICE[17686][C-00000077] chan_sip.c: Failed to authenticate device <sip:2000@169.254.254.4>;tag=as6c5edf7c
Со стороны звонящей станции (notebook) эта же ошибка выглядела следующим образом:
[Mar 15 20:33:41] WARNING[1146][C-00000000] chan_sip.c: Received response: "Forbidden" from '<sip:2000@169.254.254.4>;tag=as6c5edf7c'
Решается эта проблема прописыванием опции insecure=invite,port в настройки SIP-подключения для удалённой станции в файле /etc/asterisk/sip.conf

Вторая проблема была довольно специфичной. При удачном звонке с телефонного аппарата, обслуживаемого одной станцией, на телефонный аппарат, обслуживаемый другой станцией, напрочь отсутствовал звук. Я сразу подумал, что не проходит трафик RTP и проверил, на всякий случай, настройки фаерволлов на обеих станциях. Но с фаерволлом оказалось всё в порядке. Потом попытался поймать RTP-трафик сниффером, но не смог. И уже только потом сообразил, что телефонные шлюзы отправляют голосовой трафик другу напрямую. Такая особенность была мне известна, но в тот момент она вылетела у меня из головы. Я вспомнил, что на коммутаторе настроена изоляция портов. Несмотря на то, что оба голосовых шлюза были в одной VLAN на соседних портах, трафик напрямую между портами не ходил, пока я не разрешил портам общаться между собой.