Показаны сообщения с ярлыком jessie. Показать все сообщения
Показаны сообщения с ярлыком jessie. Показать все сообщения

воскресенье, 18 июня 2017 г.

Flash-плагин для Chromium и Iceweasel/Firefox в Debian

В 2012 году Adobe объявил о прекращении выхода новых версий Flash-плагина для Linux: 01.04.2012 14:29 Релиз Adobe Flash 11.2, последней версии с поддержкой Linux. Мне этот плагин не нужен, но вот люди, любящие играть во Flash-игры под Linux в социальных сетях, опечалились - многие игры отказываются работать в старых версиях плагина.

Надо сказать, что браузер Iceweasel/Firefox, являющийся далёким потомком браузера Netscape, предоставляет интерфейс для подключения к нему плагинов. Этот интерфейс называется NPAPI - Netscape Plugin Application Programming Interface - программный интерфейс подключаемых модулей Netscape.

У браузера Chromium, являющегося свободной версией браузера Chrome, разрабатываемого Google, имеется собственный интерфейс для подключения плагинов. В Google решили не использовать NPAPI, посчитав что в нём имеется масса проблем и нет нужных функций. Взамен Google предложили новый интерфейс - PPAPI - Pepper Plugin Application Program Interface - программный интерфейс подключаемых модулей Pepper.

Когда Adobe объявил, что новые версии Flash-плагина для Linux выпускаться не будут, это объявление не касалось Flash-плагина, который выпускался Google. Google продолжил поддержку выпуска Flash-плагина в варианте PPAPI для своего браузера Chrome. Этот плагин можно было использовать и в Linux.

И вот в прошлом году я прочитал такие две новости: 05.09.2016 16:52 Adobe возобновляет выпуск NPAPI-плагина с Flash Player для Linux, 20.12.2016 12:10 Релиз Adobe Flash 24 для Linux. "Неплохо" - сказал я и решил попробовать обновить Flash-плагин. На тот момент плагины без проблем обновились штатными средствами.

1.1. Штатная установка Flash-плагина в Chromium

Штатно Flash-плагин для Chromium устанавливается так:
# apt-get install pepperflashplugin-nonfree
# update-pepperflashplugin-nonfree --install

1.2. Штатная установка Flash-плагина в Iceweasel/Chromium

Для Iceweasel/Firefos штатно Flash-плагин устанавливается так:
# apt-get install flashplugin-nonfree
# update-flashplugin-nonfree --install

2.1. Проблемы при установке Flash-плагина в Chromium

Я бы и не стал писать эту небольшую заметку, если бы штатные средства продолжали бы работать и сейчас. Но, к сожалению, сейчас они работать перестали. Например, при попытке обновить Flash-плеер PPAPI для Chromium выдаются такие ошибки:
# update-pepperflashplugin-nonfree --install
--2017-03-28 22:28:55--  http://dl.google.com/linux/chrome/deb/pool/main/g/google-chrome-stable/google-chrome-stable_57.0.2987.110-1_amd64.deb
Распознаётся dl.google.com (dl.google.com)… 209.85.233.190, 209.85.233.91, 209.85.233.136, ...
Подключение к dl.google.com (dl.google.com)|209.85.233.190|:80... соединение установлено.
HTTP-запрос отправлен. Ожидание ответа... 200 OK
Длина: 47312644 (45M) [application/x-debian-package]
Сохранение в: «/tmp/pepperflashplugin-nonfree.VjH7fdoXcK/google-chrome-stable_57.0.2987.110-1_amd64.deb»

     0K .......... .......... .......... .......... ..........  0%  483K 95s
------------------8<------------------8<------------------8<------------------
 46150K .......... .......... .......... .......... .......... 99% 5,47M 0s
 46200K ...                                                   100% 7160G=11s

2017-03-28 22:29:07 (4,01 MB/s) - «/tmp/pepperflashplugin-nonfree.VjH7fdoXcK/google-chrome-stable_57.0.2987.110-1_amd64.deb» сохранён [47312644/47312644]

mv: не удалось выполнить stat для «unpackchrome/opt/google/chrome/PepperFlash/libpepflashplayer.so»: Нет такого файла или каталога

2.2. Проблемы при установке Flash-плагина в Iceweasel/Firefox

При попытке обновить Flash-плагин для Iceweasel/Firefox происходит другая ошибка:
# update-flashplugin-nonfree --install
--2017-03-28 22:48:07--  https://fpdownload.adobe.com/get/flashplayer/pdc/24.0.0.186/flash_player_npapi_linux.x86_64.tar.gz
Распознаётся fpdownload.adobe.com (fpdownload.adobe.com)… 2.17.215.70
Подключение к fpdownload.adobe.com (fpdownload.adobe.com)|2.17.215.70|:443... соединение установлено.
HTTP-запрос отправлен. Ожидание ответа... 404 Not Found
2017-03-28 22:48:07 ОШИБКА 404: Not Found.

ERROR: wget failed to download https://fpdownload.adobe.com/get/flashplayer/pdc/24.0.0.186/flash_player_npapi_linux.x86_64.tar.gz
More information might be available at:
  http://wiki.debian.org/FlashPlayer

3.1. Решение проблемы с установкой Flash-плагина в Chromium

Чинить будем в том же порядке. Во-первых, чтобы починить Flash-плагин для Chromium, из браузера Chromium заходим на официальную страницу Adobe, переходим по ссылке внизу Продукты, справа в списке "Загрузить" переходим по ссылке Adobe Flash Player, в выпадающем списке выбираем формат ".tar.gz для Linux" и жмём на кнопку "Загрузить". Извлечём из скачанного архива с именем "flash_player_ppapi_linux.x86_64.tar.gz" интересующий нас файл динамической библиотеки и поместим его в нужное место:
# tar xzvf flash_player_ppapi_linux.x86_64.tar.gz libpepflashplayer.so
# mv libpepflashplayer.so /usr/lib/pepperflashplugin-nonfree/
# chown root:root /usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so
# chmod u=rw,go=r /usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so

3.2. Решение проблемы с установкой Flash-плагина в Iceweasel/Firefox

Теперь точно такие же действия можно проделать из браузера Iceweasel/Firefox. В результате должен скачаться архив с именем "flash_player_npapi_linux.x86_64.tar.gz". Поступаем с ним аналогично - извлекаем интересующий нас файл динамической библиотеки и помещаем его в нужное место. В случае Iceweasel кладём файл в каталог /usr/lib/flashplugin-nonfree/:
# tar xzvf flash_player_npapi_linux.x86_64.tar.gz libflashplayer.so
# mv libflashplayer.so /usr/lib/flashplugin-nonfree/libflashplayer.so
# chown root:root /usr/lib/flashplugin-nonfree/libflashplayer.so
# chmod u=rw,go=r /usr/lib/flashplugin-nonfree/libflashplayer.so
В случае Firefox кладём файл в каталог /usr/lib/mozillz/plugins/:
# tar xzvf flash_player_npapi_linux.x86_64.tar.gz libflashplayer.so
# mv libflashplayer.so /usr/lib/mozilla/plugins/libflashplayer.so
# chown root:root /usr/lib/mozilla/plugins/libflashplayer.so
# chmod u=rw,go=r /usr/lib/mozilla/plugins/libflashplayer.so

4. Использование PPAPI-плагина в Iceweasel/Firefox

Когда Adobe объявила о прекращении поддержки NPAPI-плагина для Linux, наш соотечественник Ринат Ибрагимов - программист из Казани, занялся разработкой специального адаптера интерфейсов, который бы позволил использовать PPAPI-плагин в браузерах, предоставляющих NPAPI-интерфейс. Проект называется FreshPlayer и устанавливается в браузер как NPAPI-плагин. Вместо использования git-репозитория и сборки адаптера из исходных текстов мы воспользуемся готовым репозиторием для Debian Jessie. Добавим в файл /etc/apt/sources.list такую строчку:
deb http://http.debian.net/debian jessie-backports main contrib
Теперь обновим списки пакетов, доступных для установки из репозиториев:
# apt-get update
И установим пакет с адаптером:
# apt-get install browser-plugin-freshplayer-pepperflash

Заключение

Как правило, Flash-плагин без проблем работает в Chromium. А вот с Iceweasel/Firefox могут возникнуть сложности. Например, в Iceweasel плагин NPAPI у меня не заработал, зато заработал PPAPI-плагин через адаптер FreshPlayer. В Firefox заработали оба варианта - и плагин NPAPI и плагин PPAPI через адаптер FreshPlayer. Если не получается заставить работать первый попавшийся вариант - попробуйте другой: попробуйте сначала плагин NPAPI, затем попробуйте обновить Iceweasel до Firefox, а если это не поможет - вместо плагина NPAPI можно попробовать воспользоваться плагином PPAPI через FreshPlayer.

воскресенье, 11 июня 2017 г.

Настройка zswap в Debian

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

Одним из возможных выходов из этой непростой ситуации может быть использование модуля ядра zswap, который перед выгрузкой страниц в раздел подкачки сначала старается сжать их и оставить в оперативной памяти. Внешне этот эффект проявляется так, что оперативной памяти как будто стало больше и выгрузка страниц в раздел подкачки осуществляется гораздо реже.

Для сжатия страниц памяти воспользуемся новым алгоритмом сжатия LZ4, который обладает более высокой производительностью по сравнению с предлагаемым по умолчанию алгоритмом сжатия LZO. Несмотря на то, что LZ4 сжимает чуть хуже, он меньше грузит процессор. Таким образом соблюдается более приемлемый баланс между экономией памяти и нагрузкой на процессор.

Модули ядра для поддержки LZ4

Для начала впишем в файл /etc/initramfs-tools/modules модули ядра, реализующие быстрый алгоритм сжатия LZ:
lz4
lz4_compress
И пересоберём образ загрузочной файловой системы, чтобы в него попали добавленные нами модули:
# update-initramfs -u -k all

Модуль ядра для сжатия страниц подкачки

Теперь прописываем автоматическое включение zswap при загрузке ядра в конфигурации загрузчика GRUB в файле /etc/default/grub. Для этого добавим ряд новых настроек в GRUB_CMDLINE_LINUX_DEFAULT:
zswap.enabled=1 zswap.compressor=lz4 zswap.max_pool_percent=80
Значение настроек:
  • zswap.enabled=1 - включает использование zswap,
  • zswap.compressor=lz4 - выбирает более быстрый алгоритм сжатия lz4 вместо алгоритма сжатия по умолчанию lzo,
  • zswap.max_pool_percent=80 - разрешает использовать до 80 процентов оперативной памяти для хранения сжатых данных.
После изменения конфигурации загрузчика обновим его автоматически генерируемые файлы с настройками:
# update-grub
Всё готово, теперь нужно перезагрузить систему. Очень редкое действие, но этом случае перезагрузка действительно необходимо, т.к. загрузить модули без перезагрузки мне лично не удалось:
# reboot

Проверка

После перезагрузки можно проверить, работает ли модуль и какой алгоритм сжатия используется:
$ dmesg | grep zswap:
[    0.830940] zswap: loading zswap
[    0.835122] zswap: using lz4 compressor

Использованные материалы

воскресенье, 25 сентября 2016 г.

Стандарт SNMPv3 и суровая действительность USM_TIME_WINDOW

В прошлой статье Zabbix и проблемы с опросом по SNMPv3 при дублировании EngineID я описал решение первой проблемы, возникшей при внедрении SNMP третьей версии. После этого я столкнулся с ещё одной проблемой, которую исправлял в два подхода.

D-Link не соблюдает стандарт RFC3414

Дело в том, что даже после исправления EngineID на всех коммутаторах, на некоторых коммутаторах проблема повторялась. После перезагрузки коммутатора, Zabbix считал коммутатор недоступным по SNMP. Если разбираться глубже, с помощью приведённых в прошлой заметке OID'ов, то оказывается, что на коммутаторе после перезагрузки значение EngineBoots остаётся прежним или даже уменьшается! Первым делом были проверены версии прошивок - возможно эта проблема уже была исправлена и надо только обновить прошивку. Но оказалось, что прошивки на проблемных коммутаторах были самые свежие. Поискал в интернете, сталкивался ли кто-нибудь с подобной проблемой, и нашёл аж три темы, в которых открытым текстом утверждается, что эта проблема известна производителю и исправлять он её не собирается:
Поразмыслив, я решил, что можно было бы отключить проверку монотонности возрастания EngineBoots. В конце концов, лучше использовать SNMP третьей версии без защиты от повторного воспроизведения запросов, но зато с более безопасной аутентификацией и с защитой информации от подслушивания, чем вернуться к использованию SNMP второй или первой версии и передавать по сети в открытом виде и строку сообщества и сами запросы и ответы. Решено - будем править библиотеку.

Подготовка к пересборке Net-SNMP

Для начала отредактируем файл /etc/apt/sources.list и добавим строчки с репозиториями deb-src с исходными текстами:
deb http://mirror.ufanet.ru/debian/ wheezy main contrib non-free
deb http://mirror.ufanet.ru/debian/ wheezy-updates main contrib non-free
deb http://mirror.ufanet.ru/debian/ wheezy-proposed-updates main contrib non-free
deb http://mirror.ufanet.ru/debian-security wheezy/updates main contrib non-free

deb-src http://mirror.ufanet.ru/debian/ wheezy main contrib non-free
deb-src http://mirror.ufanet.ru/debian/ wheezy-updates main contrib non-free
deb-src http://mirror.ufanet.ru/debian/ wheezy-proposed-updates main contrib non-free
deb-src http://mirror.ufanet.ru/debian-security wheezy/updates main contrib non-free
Обновим список доступных пакетов, чтобы можно было скачать из вновь подключенных репозиториев пакеты с исходными текстами:
# apt-get update
Скачаем и распакуем исходные тексты, а затем перейдём в каталог с распакованными исходными текстами:
$ apt-get source snmp
$ cd net-snmp-5.4.3~dfsg/
Описание исправлений, внесённых в Net-SNMP

Поиск показал, что константа USM_TIME_WINDOW со значением 150 используется только в файле snmplib/snmpusm.c. Первым делом я нашёл строчку, в которой проверяется, что значение EngineBoots должно быть больше или равно значению из кэша:
if (theirBoots == ENGINEBOOT_MAX || theirBoots > boots_uint) {
Если значение EngineBoots не изменилось, то используются значение EngineTime, сохранённое в кэше. Если значение стало больше, то новые значения EngineBoots и EngineTime сохраняются в кэш. Если значение уменьшилось, то запрос завершается ошибкой SNMPERR_USM_NOTINTIMEWINDOW.

Это строчку я исправил следующим образом:
if (theirBoots == ENGINEBOOT_MAX) {
То есть при любом изменении значения EngineBoots новое значение будет сохранено в кэш для дальнейшего использования.

После этого я проделал описанные ниже процедуры по сборке пакета, установил исправленный пакет в систему и перезапустил Zabbix. Прошла пара дней, после чего стало понятно, что это исправление учитывает не все возможные случаи. Некоторые коммутаторы после перезагрузки всё-таки переставали опрашиваться.

Детальное изучение проблемы показало, что при перезагрузке значение EngineBoots у них не изменилось, зато EngineTime становилось меньше прошлого, т.к. отсчёт времени после перезагрузки начинался с нуля. В этом случае вступал в силу другой фрагмент кода, который при равенстве полученного значения EngineBoots и имеющегося в кэше проверяет соответствие времени. Если время из ответа больше расчётного, то библиотека запоминает новое значение времени в кэше и принимает ответ. Если время из ответа отстаёт от расчётного менее чем на 150 секунд, то такой ответ тоже принимается. Если же время из ответа отстаёт от расчётного более чем на 150 секунд, то ответ отбрасывается, а запрос завершается всё той же ошибкой SNMPERR_USM_NOTINTIMEWINDOW. Этот фрагмент кода выглядит следующим образом:
/*
 * Boots is ok, see if the boots is the same but the time
 * is old.
 */
if (theirBoots == boots_uint && time_uint < theirLastTime) {
        if (time_difference > USM_TIME_WINDOW) {
                DEBUGMSGTL(("usm", "%s\n", "Message too old."));
                *error = SNMPERR_USM_NOTINTIMEWINDOW;
                return -1;
        }
        else {              /* Old, but acceptable */
                *error = SNMPERR_SUCCESS;
                return 0;
        }
}
Его я исправил следующим образом:
/*
 * Boots is ok, see if the boots is the same but the time
 * is acceptable old.
 */
if (theirBoots == boots_uint && time_uint < theirLastTime && time_difference < USM_TIME_WINDOW) {
        *error = SNMPERR_SUCCESS;
        return 0;
}
Снова собрал пакет, установил его в систему и перезапустил Zabbix. Через несколько дней стало понятно, что это исправление помогло и опрос по SNMP третьей версии теперь продолжает работать даже после перезагрузок коммутаторов, когда значение EngineBoots не меняется или меняется в меньшую сторону. Был достигнут неприятный компромисс, на который пришлось пойти ради общего увеличения безопасности системы.

Сборка исправленных пакетов Net-SNMP

Теперь уже, когда в деталях раскрыта подноготная исправлений, опишу до конца процесс сборки пакета.

Скачиваем и устанавливаем пакеты, которые используются в процессе сборки Net-SNMP:
# apt-get build-dep snmp
Скачиваем патч:
$ wget http://stupin.su/files/netsnmp543_snmpv3.diff
Тут же, если вы используете библиотеку Net-SNMP из Python, можно скачать ещё один патч, описанный в заметке Исправление Python-прослойки библиотеки Net-SNMP:
$ wget http://stupin.su/files/netsnmp543_python_client.diff
Теперь перейдём в каталог с исходными текстами и наложим наши патчи:
# cd net-snmp-5.4.3~dfsg/
# patch -Np0 --ignore-whitespace < netsnmp543_snmpv3.diff
# patch -Np0 --ignore-whitespace < netsnmp543_python_client.diff
Добавим наши патчи в будущий пакет:
# dpkg-source --commit
Укажем имя патча snmpv3-python_client. В окне редактирования информации о патче введём что-нибудь подобное следующему (вплоть до двух нижних строчек, с которых начинается сам текст патча):
Description: Fixed Python bindings and SNMPv3 time window logic
Author: Vladimir Stupin <vladimir@stupin.su>
Last-Update: <2016-09-06>
--- net-snmp-5.4.3~dfsg.orig/python/netsnmp/client_intf.c
+++ net-snmp-5.4.3~dfsg/python/netsnmp/client_intf.c
Теперь отметим изменения, внесённые в пакет:
# dch -i
В окне редактирования введём информацию о нашей версии пакета:
net-snmp (5.4.3~dfsg-2.8+deb7u2) UNRELEASED; urgency=low

* Fixed Python bindings for IPv4 parameter in SET-requests
* Fixed SNMPv3 time window logic

-- Vladimir Stupin <vladimir@stupin.su>  Tue, 06 Sep 2016 16:01:20 +0500
Осталось собрать пакеты:
# dpkg-buildpackage -us -uc -rfakeroot
Теперь можно установить необходимые пакеты в систему:
# cd ..
# dpkg -i libsnmp-base_5.4.3~dfsg-2.8+deb7u2_amd64.deb
# dpkg -i libsnmp15_5.4.3~dfsg-2.8+deb7u2_amd64.deb
# dpkg -i snmp_5.4.3~dfsg-2.8+deb7u2_amd64.deb
# dpkg -i libsnmp-python_5.4.3~dfsg-2.8+deb7u2_amd64.deb
Python и SNMPv3 в Net-SNMP

Двух пересборок пакетов, на самом деле, оказалось недостаточно. Дело в том, что модуль netsnmp для Python не работает с SNMP третьей версии. Как оказалось, при попытке выполнить из программы на Python запроса SNMP с настройками третьей версии, библиотека "молчит" - в сеть не уходит ни единый пакет. В то же время я вспомнил, что на одном из серверов под управлением FreeBSD всё работало превосходно. Сразу же в глаза бросилось различие в версиях Net-SNMP во FreeBSD на том сервере и на сервере под управлением Debian Wheezy. Во FreeBSD был установлен Net-SNMP версии 5.7.2, а в Debian - 5.4.3. Чтобы проверить свои предположения о том, что этот функционал был исправлен в версии 5.7.2, я воспользовался Net-SNMP из Debian Jessie. Набросал небольшую тестовую программку на Python, запустил - всё отработало на ура.

После этого я заменил в файле /etc/apt/sources.list репозитории deb-src с релиза Wheezy на релиз Jessie и повторил проделанные выше операции, получив таким образом пропатченный бэкпорт Net-SNMP из Jessie для Wheezy. Дело, однако, этим не ограничилось. В бэкпорте вместо библиотеки libsnmp15 была библиотека libsnmp30, а пакет libsnmp-python был переименован в python-netsnmp. К библиотеке libsnmp15 были привязаны Zabbix и PHP5. Пришлось пересобрать и их, в том числе с использованием моих патчей Zabbix, описанных в заметке Установка и настройка Zabbix 2.2.0 в Debian Wheezy.

Патчи, адаптированные для Net-SNMP версии 5.7.2.1 из Jessie, можно взять по следующим ссылкам:
Мне невероятно "везёт" с программами, которыми я пользуюсь. Или просто я слишком часто стал заходить на никем ещё не топтанные дорожки?

воскресенье, 19 июня 2016 г.

Установка и настройка Open vSwitch в Debian

В прошлой заметке я создал виртуальную машину с AltLinux, которая работает под управлением Xen. Там сетевой интерфейс виртуальной машины соединяется мостом с интерфейсом хост-машины (или вернее - домена-0).

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

Чтобы ограничить передаваемые в виртуальную машину VLAN, рассмотрим использование виртуального коммутатора Open vSwitch.

1. Установка Open vSwitch

Для установки виртуального коммутатора, нужно установить в систему всего-лишь один пакет:
# apt-get install openvswitch-switch
2. Настройка виртуального коммутатора средствами Debian

В составе пакета имеются скрипты для настройки коммутатора привычными для Debian средствами, через файл /etc/network/interfaces. Почитать о настройке можно в файле /usr/share/doc/openvswitch-switch/README.Debian.gz, открыв его, например, при помощи zless, или в статье Boot integration of the Openvswitch in Ubuntu. Благодаря Open vSwitch, я смог избавиться от интерфейсов vlan и br, настроенных стандартными средствами Linux, и заменил их на функционально эквивалентные им интерфейсы Open vSwitch:
auto ovs0
allow-ovs ovs0
iface ovs0 inet manual
  ovs_type OVSBridge
  ovs_ports eth0 ovs0-vlan2 ovs0-vlan3 ovs0-vlan4

allow-ovs0 eth0
iface eth0 inet manual
  ovs_type OVSPort
  ovs_bridge ovs0
  ovs_options vlan_mode=native-untagged tag=2 trunks=2,3,4

allow-ovs0 ovs0-vlan2
iface ovs0-vlan2 inet static
  ovs_bridge ovs0
  ovs_type OVSIntPort
  ovs_options tag=2
  address 169.254.254.1
  netmask 255.255.255.0
  
allow-ovs0 ovs0-vlan3
iface ovs0-vlan3 inet dhcp
  ovs_bridge ovs0
  ovs_type OVSIntPort
  ovs_options tag=3

allow-ovs0 ovs0-vlan4
iface ovs0-vlan4 inet static
  ovs_bridge ovs0
  ovs_type OVSIntPort
  ovs_options tag=4
  address 0.0.0.0
  netmask 255.255.255.0
Интерфейс ovs0 соответствует созданию одного виртуального коммутатора. При необходимости их можно создать несколько. В этот коммутатор подключается порт eth0, по которому могут передаваться тегированные пакеты для VLAN 3 и 4, а не тегированный трафик помечается как принадлежащий VLAN 2. Следующие три интерфейса соответствуют этим трём VLAN'ам.

Если через интерфейсы, принадлежащие Open vSwitch, устанавливаются другие подключения, вроде pppoe или pptp, то эти интерфейсы можно упомянуть в опции ovs_ports после используемого им интерфейса. Далее останется только удалить опцию auto и добавить вместо неё опцию allow-ovs0 для того, чтобы поднятие этого интерфейса происходило уже по команде от демона Open vSwitch. Интерфейсы поднимаются демоном в том порядке, в котором они указаны в опции ovs_ports.

3. Ручная настройка виртуального коммутатора

Для ручной настройки всего этого хозяйства сгодились бы следующие команды:
# ovs-vsctl add-br ovs0
# ovs-vsctl add-port ovs0 eth0
# ovs-vsctl set port eth0 vlan_mode=native-untagged tag=2 trunks=2,3,4
# ovs-vsctl add-port ovs0 ovs0-vlan2 tag=2 -- set Interface ovs0-vlan2 type=internal
# ifconfig ovs0-vlan2 inet 169.254.254.1/24 up
# ovs-vsctl add-port ovs0 ovs0-vlan3 tag=3 -- set Interface ovs0-vlan3 type=internal
# dhclient ovs0-vlan3
# ovs-vsctl add-port ovs0 ovs0-vlan4 tag=4 -- set Interface ovs0-vlan4 type=internal
# ifconfig ovs0-vlan4 up
Чтобы удалить порт из коммутатора, можно воспользоваться такой командой:
# ovs-vsctl del-port ovs0-vlan2
Чтобы удалить сам коммутатор, можно воспользоваться такой командой:
# ovs-vsctl del-br ovs0
Посмотреть на текущие настройки виртуального коммутатора можно командой, которая уже была продемонстрирована выше:
# ova-vsctl show
Стоит также отметить, что имена коммутаторов и портов могут быть совершенно произвольными. Названия ovs0 и ovs0-vlan2 и т.п. были даны лишь для наглядности. При этом, название интерфейса eth0 соответствует реальному интерфейсу, который нужно подключить к порту виртуального коммутатора, поэтому он фигурирует под своим настоящим именем.

Описанное выше - лишь очень малая часть того, что умеет этот виртуальный коммутатор. Он поддерживает агрегацию портов, обнаружение петель, зеркалирование портов, сбор статистики о трафике на NetFlow-коллектор и многие другие вещи. Поддерживается даже специальный протокол OpenFlow, предназначенный для централизованного управления такими коммутаторами. Я же тут ограничился самыми простыми вещами, которые мне понадобились лишь для того, чтобы передать вовнутрь виртуальной машины под управлением Xen строго определённые VLAN.

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

Вот так, например, можно убедиться в том, что по крайней мере некоторая часть openvswitch работает в пространстве ядра:
# lsmod | grep vs
openvswitch            63932  0 
gre                    12777  1 openvswitch
vxlan                  35053  1 openvswitch
libcrc32c              12426  1 openvswitch
5. Виртуальный коммутатор и Xen

Для того, чтобы включить в виртуальный коммутатор интерфейс виртуальной машины, работающей под управлением Xen, можно воспользоваться соответствующими настройками в файле конфигурации виртуальной машины. Например, вот фрагмент файла конфигурации /etc/xen/inet.cfg виртуальной машины inet:
vif = ['script=vif-openvswitch,bridge=ovs0.2']
Таким образом виртуальная машина будет включена в нетегированный порт коммутатора в VLAN 2.

Чтобы передать в виртуальную машину VLAN'ы 3 и 4 в тегированном режиме, можно воспользоваться следующим способом настройки:
vif = ['script=vif-openvswitch,bridge=ovs0:3:4']
О других возможностях настройки сети в виртуальных машинах Xen можно почитать здесь: Xen Networking

P.S. 25 июня 2016. Внесён ряд правок, связанных с автоматическим восстановлением настроек при перезагрузке.

воскресенье, 12 июня 2016 г.

Запуск AltLinux как domU в Xen

При помощи утилиты xen-create-image можно легко создавать виртуальные машины с любой операционной системой, поддержка которой присутствует в каталоге /usr/share/xen-tools/. Заинтересовал вопрос, как же можно создать виртуальную машину не из списка поддерживаемых? В качестве предмета для экспериментов я выбрал AltLinux. Статья делится на две части: подготовка образа для многократного дальнейшего использования и создание из этого образа одной виртуальной машины.

Сразу предупреждаю, что тут я в хвост и в гриву пользуюсь LVM. Во-первых, это удобно. Во-вторых, ну не зря же я мучился? У кого нет LVM, выпутывайтесь сами ;-P

1. Подготовка образа для последующего использования

Скачиваем один из образов из каталога http://ftp.altlinux.org/pub/distributions/ALTLinux/p7/images/starterkits/

Например, я взял altlinux-p7-vm-net-20160312-x86_64.img.xz:
$ cd /home/stupin
$ wget http://ftp.altlinux.org/pub/distributions/ALTLinux/p7/images/starterkits/altlinux-p7-vm-net-20160312-x86_64.img.xz
Распакуем его:
$ cd /home/stupin
$ 7z x altlinux-p7-vm-net-20160312-x86_64.img.xz
Получится файл с именем altlinux-p7-vm-net-20160312-x86_64.img размером 504 мегабайт.

Посмотрим при помощи утилиты file, что представляет собой этот файл:
# file /home/stupin/altlinux-p7-vm-net-20160312-x86_64.img
/home/stupin/altlinux-p7-vm-net-20160312-x86_64.img: DOS/MBR boot sector, LInux i386 boot LOader; partition 1 : ID=0x83, start-CHS (0x0,32,33), end-CHS (0x40,63,63), startsector 2048, 1030144 sectors

Это образ диска с таблицей разделов в стиле DOS.

Создадим логический том такого же размера, что и образ и скопируем в него этот файл посекторно:
# lvcreate -n image -L 528482304b stupin
# cd /home/stupin
# dd if=altlinux-p7-vm-net-20160312-x86_64.img of=/dev/mapper/stupin-image
Если при помощи fdisk посмотреть таблицу разделов в образе, то можно ещё раз убедиться в том, что в образе имеется таблица разделов DOS:
# fdisk -l /dev/mapper/stupin-image

Disk /dev/mapper/stupin-image: 504 MiB, 528482304 bytes, 1032192 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0xd6c97625

Device                    Boot Start     End Sectors  Size Id Type
/dev/mapper/stupin-image1       2048 1032191 1030144  503M 83 Linux
Смонтируем файловую систему из первого раздела в каталог /mnt/root:
# partprobe
# mount /dev/mapper/stupin-image1 /mnt/root
Исправим файл etc/inittab, убрав оттуда две консоли и создав вместо них консоль, которая будет доступна из dom0:
1:2345:respawn:/sbin/mingetty hvc0
#1:2345:respawn:/sbin/mingetty --noclear tty1
#2:2345:respawn:/sbin/mingetty tty2
Также я отредактировал файл etc/fstab, прописав монтирование корневой файловой системы по имени устройства вместо монтирования по идентификатору:
/dev/xvda     /                       ext4    relatime                        1 1
#UUID=5b7c2d58-0afa-4bf4-9a42-542935636a05 / ext4 relatime 1 1
Чтобы в дальнейшем меньше пришлось вписывать в файл конфигурации виртуальной машины, создадим файл конфигурации для загрузчика pygrub. Для этого создадим каталог boot/grub:
# cd /mnt/root/boot
# mkdir grub
Внутри каталога создадим файл menu.lst со следующим содержимым:
default         0
timeout         2

title           AltLinux p7 x86_64
root            (hd0,0)
kernel          /boot/vmlinuz root=/dev/xvda ipv6.disable=1 ro
initrd          /boot/initrd.img

title           AltLinux p7 x86_64 (Single-User)
root            (hd0,0)
kernel          /boot/vmlinuz root=/dev/xvda ipv6.disable=1 ro single
initrd          /boot/initrd.img
Поменяем пароль по умолчанию у пользователя root:
# chroot /mnt/root
# passwd
# exit
Теперь создадим архив для последующего разворачивания новых виртуальных машин:
# cd /mnt/root
# tar cjvf /home/stupin/altlinux-p7-vm-net-20160312-x86_64.tbz *
Наконец, раздел можно отмонтировать и уничтожить:
# umount /mnt/root
# dd if=/dev/zero of=/dev/mapper/stupin-image
# partprobe
# lvremove /dev/mapper/stupin-image
2. Создание виртуальной машины

Создадим LVM-раздел для размещения корневого раздела будущей виртуальной машины:
# lvcreate -n inet-root -L 20G stupin
Создадим файловую систему:
# mkfs.ext4 /dev/stupin/inet-root
Смонтируем файловую систему:
# mount /dev/stupin/inet-root /mnt/inet/
И распакуем в неё подготовленный архив с системой:
# cd /mnt/inet/
# tar xjvf /home/stupin/altlinux-p7-vm-net-20160312-x86_64.tbz
Размонтируем корневую файловую систему будущей виртуальной машины:
# cd /
# umount /mnt/inet
Теперь создадим файл конфигурации виртуальной машины /etc/xen/inet.cfg:
bootloader = '/usr/lib/xen-4.4/bin/pygrub'
#kernel = '/boot/vmlinuz'
#ramdisk = '/boot/initrd.img'

name = 'inet'

vcpus = 1
memory = 1024

#root = '/dev/xvda ro'
disk = ['phy:/dev/stupin/inet-root,ioemu:xvda,w']
vif = ['script=vif-bridge,bridge=xenbr0']

on_poweroff = 'destroy'
on_reboot = 'restart'
on_crash = 'restart'
on_xend_start = 'ignore'
on_xend_stop = 'ignore'
Параметры kernel, ramdisk и root закомментированы, потому что внутри образа имеется файл /boot/grub/menu.lst, в котором прописано, в каком файле лежит образ ядра и образ минимального корневого диска, а также прописаны все параметры, передаваемые загрузчиком ядру. В том числе прописан параметр, настраивающий имя устройства, содержащей корневую файловую систему.

воскресенье, 5 июня 2016 г.

Перенос системы с mdadm RAID1 на mdadm RAID1+LVM

Ранее я уже писал о том, как перевести установленную на диск систему на два диска, объединённые в программный массив RAID1: Перевод работающей системы Debian на RAID 1. На этот раз я задумался о том, чтобы переделать DOS-разделы диска в логические тома LVM. LVM может пригодиться для размещения виртуальных машин под управлением Xen, для более безболезненного переноса системы на другие физические диски, для изменения размеров разделов, их создания и уничтожения.

Стратегия перехода была такая:
  1. Исключаем из настроенного RAID-массива один из дисков, так что у нас появляется один свободный диск и один деградировавший RAID-массив,
  2. Создаём деградировавший RAID-массив на освободившемся диске, выполняем разбивку, переносим на него данные,
  3. Выполняем загрузку системы с флешки, синхронизируем накопившиеся изменения, настраиваем загрузку системы с нового диска,
  4. Грузим систему с нового диска, удаляем старый RAID-массив, разбиваем его аналогично новому, включаем в новый RAID-массив в качестве второй половинки.
В комментариях к прошлой статье о переходе на RAID1 мне писали, что статья не годится, т.к. кто-то сломал систему и теперь не может её загрузить. Сам я по той статье переводил три системы и с проблемами не сталкивался. Насчёт этой статьи хочу сразу предупредить, что здесь нет готового на 100% работающего рецепта. Мне самому пришлось изрядно помучиться на этапе загрузки системы с флешки и последующей загрузки новой системы, т.к. нужно хорошо разбираться в нюансах ручной сборки RAID-массивов, определения LVM-томов, генерации файлов конфигурации загрузчика GRUB, создания загрузочных образов системы initramfs и работы с режимом восстановления на загрузочной флешке. Для этого этапа я лишь приведу несколько команд, которые наверняка пригодятся вам, если вы всё-таки решите попробовать проделать то же самое.

Приступим.

1. Извлечение одного из дисков из RAID-массива

Посмотрим на разделы одного из двух дисков:
# fdisk -l /dev/sda 

Disk /dev/sda: 931,5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x9a7a0fdb

Device     Boot     Start        End    Sectors   Size Id Type
/dev/sda1            2048    1977979    1975932 964,8M fd Linux raid autodetect
/dev/sda2         1978368   41064512   39086145  18,7G fd Linux raid autodetect
/dev/sda3  *     41066496   62208035   21141540  10,1G  7 HPFS/NTFS/exFAT
/dev/sda4        62210048 1953525167 1891315120 901,9G  5 Extended
/dev/sda5        62212096  140352192   78140097  37,3G  7 HPFS/NTFS/exFAT
/dev/sda6       140355584 1953525167 1813169584 864,6G fd Linux raid autodetect
Разделы sda1, sda2 и sda6 - это половинки RAID-массивов md1, md2, md6. На md1 расположен раздел подкачки, на md2 - корневой раздел Linux, на md6 - раздел home.

Разделы sda3 и sda5 являются разделами NTFS, на первый из которых когда-то был установлен Windows, а второй использовался для хранения данных для Windows. На разделах sdb3 и sdb5 были расположены посекторные резервные копии этих разделов.

Выведем из RAID-массивов диск /dev/sda:
# mdadm --manage /dev/md1 --fail /dev/sda1
# mdadm --manage /dev/md2 --fail /dev/sda2
# mdadm --manage /dev/md6 --fail /dev/sda6
2. Новая разбивка диска

Я решил воспользоваться консервативной схемой разбивки, когда GRUB будет находиться вне логических томов LVM, на отдельном разделе. Мне показалось, что так будет проще его починить, если что-то пойдёт не так. Новая схема разделов стала следующей:
# fdisk -l /dev/sda 

Disk /dev/sda: 931,5 GiB, 1000204886016 bytes, 1953525168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x382c6e6a

Device     Boot  Start        End    Sectors   Size Id Type
/dev/sda1  *      2048     411647     409600   200M fd Linux raid autodetect
/dev/sda2       411648 1953525167 1953113520 931,3G fd Linux raid autodetect
На созданных разделах я создал деградировавшие массивы RAID1, в которых пока что не хватает второй половинки:
# mdadm --create /dev/md11 -l1 -n2 missing /dev/sda1
# mdadm --create /dev/md12 -l1 -n2 missing /dev/sda2
Создадим файловую систему для будущего раздела /boot, на котором будет находиться загрузчик GRUB:
# mkfs.ext4 /dev/md11
Теперь установим менеджер томов, если он ещё не был установлен:
# apt-get install lvm2
Создадим физический том на разделе:
# pvcreate /dev/md12
Создадим группу томов stupin, в котором будет один физический том /dev/md12:
# vgcreate stupin /dev/md12
Создадим логический том размером 1 гигабайт для раздела подкачки:
# lvcreate -n dom0-swap -L 1G stupin
И разметим его как раздел подкачки:
# mkswap /dev/stupin/dom0-swap
Создадим логический том размером в 20 гигабайт для корневого раздела системы:
# lvcreate -n dom0-root -L 20G stupin
И разметим на нём файловую систему ext4:
# mkfs.ext4 /dev/stupin/dom0-root
Создадим логический том для раздела /home и разметим на нём файловую систему ext4:
# lvcreate -n dom0-home -L 800G stupin
# mkfs.ext4 /dev/stupin/dom0-home
3. Копирование разделов ext4

Для копирования ext4 я решил воспользоваться rsync. Создадим точки монтирования будущих разделов /mnt, /mnt/boot, /mnt/home:
# mkdir /mnt
# mount /dev/stupin/dom0-root /mnt/
# mkdir /mnt/boot
# mount /dev/md11 /mnt/boot/
# mkdir /mnt/home
# mount /dev/stupin/dom0-home /mnt/home/
И выполним первоначальное копирование данных на новые разделы:
# rsync -xavv --delete /home/ /mnt/home/
# rsync -xavv --delete / /mnt/
Этот этап копирования имеет целью уменьшить количество файлов, которые нужно будет скопировать во время загрузки системы с флешки. После загрузки системы с флешки копирование будет повторено с тем чтобы скопировать изменившиеся файлы.

4. Копирование NTFS-разделов

Для копирования NTFS-разделов я решил воспользоваться утилитой dd, хотя мог бы воспользоваться и утилитой ntfsclone. Здесь я изначально копировал диски остановленной системы, поскольку она бывает мне нужна лишь иногда и обычно выключена.

Создадим логические тома LVM с размером точно равным количеству секторов на исходных разделах:
# lvcreate -L 21141540S -n winxp-c-disk stupin
# lvcreate -L 78140097S -n winxp-d-disk stupin
И скопируем на них данные посекторно:
# dd if=/dev/sdb3 of=/dev/stupin/winxp-c-disk
# dd if=/dev/sdb5 of=/dev/stupin/winxp-d-disk
5. Загрузка с флешки

Этот момент - самый сложный и ответственный. По идее, если у вас ничего не получится, вы можете загрузить систему со старого диска, переразбить диск, который планировали использовать под LVM, и включить его обратно в зеркало. На этом неудачный опыт будет завершён и система вернётся в то состояние, в котором она находилась изначально.

Я использовал установочную флешку с Debian Jessie. Загрузившись с флешки нужно выбрать режим восстановления (rescue mode), через её меню определить RAID-массивы и логические тома, смонтировать корневой раздел и раздел /boot и перейти в командную строку в среду, где корнем является корневой раздел восстанавливаемой системы.

Попав в оболочку, для начала домонтируем будущий раздел /home:
# mount /dev/stupin/dom0-home /home
Теперь смонтируем разделы исходной системы для того, чтобы синхронизировать накопившиеся на ней изменения в будущую систему:
# mount /dev/sdb2 /mnt
# mount /dev/sdb6 /mnt/home
Скопируем изменения:
# rsync -xavv --delete /mnt/home/ /home/
# rsync -xavv --delete /mnt /
В прошлой статье я не останавливался подробно на моменте правильного переноса данных, поскольку считал, что статьёй воспользуются хорошо подготовленные пользователи, которые проделают ровно то же самое - синхронизируют изменения, загрузившись с флешки. В этот раз загрузка с флешки - необходимый этап, поэтому я решил чуть подробнее описать и момент переноса данных.

Теперь нужно сделать так, чтобы система загрузилась с нового диска. Сначала посмотрим идентификаторы UUID у имеющихся дисков и разделов:
# blkid
Впишем в файл /etc/fstab раздел подкачки, корневой раздел, разделы /boot и /home, указав их идентификаторы из вывода команды blkid:
# vim /etc/fstab
Обновим список RAID-массивов имеющихся в системе в образе initramfs:
# mdadm --examine --scan > /etc/mdadm/mdadm.conf
# update-initramfs -k all -u
Установим GRUB на новый диск и обновим его конфигурацию:
# grub-install /dev/sda
# update-grub
6. Загрузка новой системы

После этого можно выйти из оболочки и выбрать перезагрузку. В BIOS нужно выбрать загрузку с нового диска, а старый можно вообще для наглядности отсоединить, чтобы точно быть уверенным, что загрузка произошла с нового диска.

Если в процессе загрузки не появилось меню GRUB, то нужно проверить, что GRUB установлен, а его конфигурация обновлена. Для этого нужно снова загрузиться с флешки в режиме восстановления и убедиться, что grub-install сработал.

Если система не загрузилась и остановилась на этапе выполнения меню GRUB, то возможно дело в том, что GRUB не нашёл образ ядра или образ initramfs. В таком случае в загрузочной флешке нужно убедиться, что отработало обновление файла конфигурации GRUB при помощи команды grub-update.

Если система не загрузилась и перешла в оболочку initramfs, то скорее всего ядро не нашло корневой раздел. Нужно проверить, что корневой раздел определился в системе и имеется в каталоге /dev/stupin/ (stupin - имя логической группы) или в /dev/mapper/. Если он на месте, тогда нужно проверить, что он правильно указан в файле /etc/fstab.

В образе initramfs могут пригодиться следующие команды.

Поиск имеющихся RAID-массивов и обновление конфигурации:
# mdadm --examine --scan > /etc/mdadm/mdadm.conf
Сборка RAID-массивов вручную, после которой массивы должны появиться в каталогах /dev и /dev/md:
# mdadm --assemble /dev/md11
# mdadm --assemble /dev/md12
Определение доступных групп томов и логических томов LVM:
# vgchange -ay
Для редактирования файла /etc/fstab в образе initramfs имеется редактор vi.

После того, как вы убедились, что все RAID-массивы и логические тома определились системой, а в /etc/fstab указаны правильные разделы для монтирования, можно попробовать выйти из оболочки initramfs и продолжить загрузку системы.

В загрузившейся системе нужно повторить проделанные манипуляции, а затем обновить образ initramfs и файл конфигурации GRUB. После этого можно попробовать перезагрузить систему и проверить, грузится ли она автоматически, без ручного вмешательства. Когда система будет грузиться с нового раздела автоматически, можно подсоединить отсоединённый диск и продолжить. Если же вы не смогли добиться устойчивой автоматической загрузки системы, можно переключиться на загрузку со старого диска и вернуть всё обратно.

7. Добавление второй половины в новый RAID-массив

Теперь скопируем разбиение с нового диска на старый:
# sfdisk --dump /dev/sda | sfdisk /dev/sdb
И добавим разделы старого диска в зеркало:
# mdadm --manage /dev/md11 --add /dev/sdb1
# mdadm --manage /dev/md12 --add /dev/sdb2
Не забудьте поставить GRUB на второй диск:
# grub-install /dev/sdb
8. Переименование RAID-массивов

Есть ещё один не обязательный момент. Мне хотелось переименовать RAID-массивы так, чтобы они назывались md1 и md2, а не md11 и md12. Для этого я снова загрузился с флешки, разобрал RAID-массивы и собрал их уже под новыми именами:
# mdadm --stop /dev/md11
# mdadm --stop /dev/md12
# mdadm --assemble --update=name --name=1 /dev/md1 /dev/sda1 /dev/sdb1
# mdadm --assemble --update=name --name=2 /dev/md2 /dev/sda2 /dev/sdb2
Осталось обновить конфигурацию mdadm в initramfs:
# mdadm --examine --scan > /etc/mdadm/mdadm.conf
# update-initramfs -k all -u

воскресенье, 29 мая 2016 г.

Установка Windows XP в Xen

Возникла задача поставить Windows для запуска программы, которая не работает в Wine. Решил попробовать установить Windows под управлением Xen. Ранее я уже писал небольшую заметку о настройке Xen: Памятка по настройке Xen. В той статье для управления Xen использовалась утилита xm, поскольку писалась она применительно к Debian Wheezy. В этот раз будет использоваться утилита xl, поскольку дело происходит в Debian Jessie. Однако, несмотря на это различие, всё написанное в прошлой статье будет работать и сейчас. Надо всего лишь вместо xm использовать xl.

1. Установка операционной системы на виртуальную машину

Создадим LVM-раздел, куда будем устанавливать Windows:
# lvcreate -L10G -n winxp-disk
Создадим файл конфигурации /etc/xen/winxp.cfg, который первоначально будет использоваться для установки системы:
builder = 'hvm'
device_model_version = 'qemu-xen'
memory = 1024
vcpus = 1
pae = 0
acpi = 0
apic = 0
name = 'winxp'
disk = ['phy:/dev/vg0/winxp-disk,ioemu:hda,w',
        'phy:/home/stupin/WindowsXP_SP2.iso,ioemu:hdb:cdrom,r']
boot = 'd'

on_poweroff = 'destroy'
on_reboot = 'destroy'
on_crash = 'destroy'
on_xend_start = 'ignore'
on_xend_stop = 'ignore'

fullscreen = 1
sdl = 0
vnc = 1
vncconsole = 1
vncpasswd = ''
keymap = 'ru'
stdvga = 0
serial = 'pty'

usb = 1
usbdevice = 'tablet'
Особо стоит отметить следующие моменты в этом файле:
  • Опции acpi (интерфейс управления электропитанием) и apic (улучшенный контроллер прерываний) на время установки отключены,
  • В опции disk первым прописан LVM-раздел, в который будем устанавливать систему, а вторым прописан ISO-образ установочного диска с Windows,
  • Опция boot выставлена в значение d - загрузка "с диска D:", то есть - с компакт-диска, в роли которого выступает ISO-образ установочного диска,
  • Опция keymap позволяет в дальнейшем не следить за раскладкой на системе, где запущен VNC-клиент. Без этой опции в сеансе VNC русские буквы удастся ввести только в случае, если на системе с VNC-клиентом включена английская раскладка,
  • Включена поддержка usb, а в списке USB-устройств в опции usbdevice настроен "планшет". Эта настройка позволяет в дальнейшем без проблем манипулировать курсором мыши. Без неё при подключении через VNC будет два курсора мыши, слабо связанных между собой, так что управляться ими будет непросто.
Теперь запустим виртуальную машину:
# xl create /etc/xen/winxp.cfg
На всякий случай, если вдруг виртуальная машина зависнет, приведу команду для её принудительного выключения:
# xl destroy winxp
Напоминаю, что список запущенных виртуальных машин можно посмотреть такой командой:
# xl list
После запуска можно подключиться к виртуальной машине при помощи VNC-клиента на TCP-порт 5900 по IP-адресу 5900. Я воспользовался Remmina, о которой писал в одноимённой заметке - Remmina:

Если Вы хотите подключиться по сети не из домена dom0 или у Вас имеется несколько подобных доменов domU, к которым Вы хотите подключаться по протоколу VNC, можно настроить прослушиваемый адрес и порт при помощи опции vnclisten. Например, значение 192.168.0.1:2 будет соответствовать ожиданию подключений на TCP-порт 5902 и адрес 192.168.0.1.

Настроить переключение раскладки по нажатию Alt+Shift мне не удалось - это сочетание в сеанс VNC не попадало, поэтому пришлось настроить непривычное для меня сочетание Ctrl+Shift.

2. Изменение настроек после установки

После установки Windows нужно выключить виртуальную машину, воспользовавшись пунктом меню "Выключить компьютер", доступным по нажатию кнопки "Пуск":

Теперь нужно немного изменить конфигурацию в файле /etc/xen/winxp.cfg. Включим опции acpi и apic, уберём из списка дисков ISO-образ установочного компакт-диска и поменяем значение опции boot на c - загрузка "с диска C:":
acpi = 1
apic = 1
disk = ['phy:/dev/vg0/winxp-disk,ioemu:hda,w']
boot = 'c'
3. Проброс USB-устройств вовнутрь виртуальной машины

Ещё одна вещь, которая мне понадобилась - это пробросить флешку вовнутрь виртуальной машины. Для начала я вставил её в компьютер и нашёл её в списке имеющихся в системе USB-устройств при помощи команды:
$ lsusb -v | less
В несколько сокращённом виде, нужная мне флешка выглядела следующим образом:
Bus 001 Device 005: ID 0930:6534 Toshiba Corp. TravelDrive
Device Descriptor:
  ...
  idVendor           0x0930 Toshiba Corp.
  idProduct          0x6534 TravelDrive
  bcdDevice            1.00
  iManufacturer           1 Kingston
  iProduct                2 DataTraveler 2.0
  iSerial                 3 0201101728450
  bNumConfigurations      1
  Configuration Descriptor:
    ...
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           3
      bInterfaceClass         8 Mass Storage
Чтобы флешка автоматически пробрасывалась в виртуальную машину, нужно отредактировать список USB-устройств в файле конфигурации /etc/xen/winxp.cfg:
usbdevice = ['tablet', 'host:0930:6534']
Если в системе имеется несколько устройств с одинаковыми идентификаторами производителя и модели, то можно указать номер шины и устройства. В нашем случае это будет выглядеть вот так:
usbdevice = ['tablet', 'host:1.5']
Однако стоит учесть, что при отключении и повторном включении устройство может получить другой номер. Использовать идентификаторы производителя и модели.

В случае с утилитой xm можно было бы вставлять и удалять устройства налету, вот так:
# xm usb-add winxp host:0930:6534
# xm usb-del winxp host:0930:6534
Однако, в утилите xl подобная функциональность пока не реализована и для введения настроек в силу понадобится завершить работу виртуальной машины и запустить её снова, с использованием исправленной конфигурации.

4. Использованные материалы

воскресенье, 22 мая 2016 г.

Мониторинг Asterisk по протоколу SNMP

Меня заинтересовало наличие в Asterisk модуля res_snmp. Я решил попробовать настроить его и узнать, за какими параметрами Asterisk можно наблюдать с его помощью.

1. Установка и настройка SNMP-агента

Устанавливаем SNMP-агента:
# apt-get install snmpd
Нужно заглянуть в файл /etc/default/snmpd и убедиться, что запуск SNMP-агента разрешён:
SNMPDRUN=yes
Редактируем файл конфигурации SNMP-агента /etc/snmp/snmpd.conf, приведя к следующему виду:
agentAddress udp:127.0.0.1:161
  
view asterisk included .1.3.6.1.2.1.1.1
view asterisk included .1.3.6.1.2.1.1.2
view asterisk included .1.3.6.1.2.1.1.4
view asterisk included .1.3.6.1.2.1.1.5
view asterisk included .1.3.6.1.2.1.1.6
view asterisk included .1.3.6.1.4.1.22736

rocommunity public 127.0.0.1 -V asterisk
rwcommunity private 127.0.0.1 -V asterisk

createUser zabbix SHA auth_password AES encryption_password
rouser zabbix priv -V asterisk

sysLocation Ufa
sysContact Vladimir Stupin <vladimir@stupin.su>
sysObjectID .1.3.6.1.4.1.22736.1

master agentx
agentXSocket /var/agentx/master
agentXPerms 0660 0775 nobody asterisk
Указанный выше файл конфигурации является лишь примером. Реально вы можете захотеть поменять часть настроек. Например:
  • agentAddress - прослушиваемый SNMP-агентом IP-адрес,
  • view asterisk included - в этом представлении я ограничил доступ к OID'ам. Доступ разрешён только к OID'ам, содержащим информацию об узле и к дереву OID'ов с состоянием Asterisk,
  • rocommunity - строка сообщества для чтения данных для SNMP версий 1 и 2c,
  • rwcommunity - строка сообщества для записи данных для SNMP версий 1 и 2c,
  • createUser - строка описывает одного пользователя SNMP версии 3 - его имя, пароли и алгоритмы аутентификации и шифрования,
  • rouser - описывает права доступа пользователя SNMP версии 3,
  • sysLocation - строка местонахождения оборудования. Бывает полезно в больших компаниях, когда имеется много оборудования и сотрудников, или оборудование расположено в необычном месте: за фальшь-потолком или на радиомачте,
  • sysContact - строка с контактными данными администратора оборудования. Бывает полезно в больших компаниях, чтобы найти сотрудника, ответственного за оборудование,
  • sysObjectID - идентификатор типа оборудования. Полезно, например, для автоматического обнаружения оборудования и автоматической постановки на контроль с шаблоном, соответствующим этому OID'у,
  • master, agentXSocket, agentXPerms задают настройки Unix-сокета SNMP-агента, к которому будут подключаться субагенты.
Для генерации строк сообщества и паролей я рекомендую воспользоваться, например, программой pwgen, которую можно установить из одноимённого пакета:
# apt-get install pwgen
Сгенерировать 16-символьный пароль можно следующим образом:
$ pwgen 16
Чтобы Asterisk, запущенный от пользователя asterisk, имел доступ к каталогу с Unix-сокету SNMP-агента, меняем права доступа к каталогу /var/agentx:
# chmod o+rx /var/agentx
Перезапускаем SNMP-агента:
# systemctl restart snmpd.service
2. Включение SNMP-модуля в Asterisk

Открываем файл /etc/asterisk/res_snmp.conf и приводим его к следующему виду:
[general]
subagent = yes
enabled = yes
После чего просим Asterisk выгрузить модуль SNMP и загрузить его снова:
# asterisk -rx 'module unload res_snmp.so'
# asterisk -rx 'module load res_snmp.so'
3. Использование MIB-файлов

Посмотреть OID'ы в виде дерева:
$ snmptranslate -M /var/lib/mibs/:/var/lib/mibs/ietf/:/var/lib/mibs/iana/ -m DIGIUM-MIB:ASTERISK-MIB -Tp -Td -Ln 1.3.6.1.4.1.22736 | less
Посмотреть значения OID'ов с их символьными именами по SNMP второй версии можно следующим образом:
$ snmpwalk -v 2c -c public 127.0.0.1 .1.3.6.1.4.1.22736.1 | less
Для SNMP третьей версии то же самое делается так:
$ snmpwalk -v 3 -u zabbix -n '' -l authPriv -a SHA -x AES -A auth_password -X encryption_password 127.0.0.1 .1.3.6.1.2.4.1.22736.1 | less
4. Шаблоны для Zabbix

В качестве основы для шаблона я воспользовался официальными MIB-файлами:
Я подготовил два шаблона для контроля интересующих меня параметров с помощью Zabbix:
Поменять строки сообщества и пароли можно при помощи массового редактирования элементов данных. Из шаблона для второй версии SNMP можно массовым редактированием легко получить и шаблон, использующий первую версию SNMP. Собственно, массовым редактированием можно получить и шаблон, использующий третью версию SNMP.

На снимке экрана ниже показаны имеющиеся в шаблоне элементы данных:

На этом снимке показаны результаты опроса Asterisk по этому шаблону:

К сожалению, SNMP-модуль Asterisk не позволяет узнать состояние регистраций абонентов. Если бы состояние регистраций можно было бы контролировать, я обязательно добавил бы в шаблон низкоуровневое обнаружение регистраций и контроль их состояний. Это позволило бы своевременно обнаруживать проблемы со шлюзами абонентов.

Один из вариантов какого бы то ни было решения этой проблемы может быть следующим. Если VoIP-шлюзы находятся в находятся в отдельной сети, где больше нет никакого оборудования, можно воспользоваться функциями обнаружения Zabbix и автоматически ставить обнаруженные IP-адреса хотя бы на контроль доступности по ICMP.

воскресенье, 15 мая 2016 г.

Краткий обзор программного телефона SFLphone

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

Программа имеет несколько разных интерфейсов и разбита на несколько пакетов:
$ apt-cache search sflphone
sflphone-daemon - SIP and IAX2 compatible VoIP phone - core daemon
sflphone-data - SIP and IAX2 compatible VoIP phone - common data
sflphone-evolution - SIP and IAX2 compatible VoIP phone - Evolution plugin
sflphone-gnome - SIP and IAX2 compatible VoIP phone - GNOME client
sflphone-kde - SIP and IAX2 compatible VoIP phone - KDE client
Как видно, имеются варианты интерфейсов для рабочих сред KDE и GNOME, а также плагин для почтового клиента Evolution. Ещё два пакета содержат демон и данные для программы. Демон на самом деле и является программным телефоном: внутри него происходит работа с устройствами компьютера и сетью. Интерфейс программы взаимодействует с демоном через DBUS и занимается лишь передачей команд в демон и отображением его состояния. В этой заметке я рассмотрю только интерфейс для среди GNOME. Установим в систему соответствующий пакет:
# apt-get install sflphone-gnome

Общий вид программы:

Под меню видно имеется окно со списком текущих разговоров, ниже - регуляторы громкости для микрофона и наушников, ещё ниже - номеронабиратель. Справочник контактов спрятан в отдельное окно, что мне показалось несколько неудобным.

Чтобы попасть в настройки программы, нужно выбрать пункт меню "Правка", а в раскрывшемся списке выбрать пункт "Настройки":


Из всех имеющихся настроек особенный интерес представляют настройки звука:

Здесь можно выбрать аудиоустройства, которые будут использоваться для озвучивания поступившего звонка, для озвучивания речи собеседника, а также микрофон, который будет использоваться для отправки речи собеседнику.

Второй интересный пункт, это выбор видеоустройств:

К сожалению, совершить видеозвонок с использованием этого программного телефона мне не удалось. Но это, наверное, не столь важно для рабочего места секретаря.

Чтобы настроить учётные записи, нужно в основном окне программы выбрать пункт "Правка", а в раскрывшемся списке выбрать пункт "Аккаунты":


После этого откроется список учётных записей:

Здесь имеется отдельная учётная запись под названием "IP2IP". В ней хранятся настройки, которые будут использоваться для прямых вызовов, без использования какой-либо учётной записи. Можно добавлять, удалять и редактировать учётные записи, а также временно отключать их, снимая галочку.

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


Во вкладке аудионастроек можно выбрать используемые кодеки, их приоритеты, звук входящего звонка и режим передачи тоновых сигналов:


Во вкладке видеонастроек аналогично, можно выбрать используемые кодеки и их приоритеты, а также включить или выключить использование видео:

Ещё раз скажу, что совершить видеозвонок при использовании этой программы мне не удалось.

Во вкладке дополнительных настроек можно указать номер используемого UDP-порта, внешний IP-адрес и указать STUN-сервер:

В отличие от Ekiga, тут все настройки легко доступны и их можно настраивать для каждой учётной записи отдельно.

В последней вкладке можно указать настройки шифрования для сеансов SIP и для трафика RTP:

Я ни то ни другое настраивать пока не пробовал.

Теперь перейдём к самому интересному - к соединению абонентов друг с другом.

Вот так входящий звонок отображается в правом верхнем углу экрана:

Принят звонок можно щелчком по этому всплывающему окну.

Тот же звонок отображается в списке разговоров. Взять трубку можно либо нажатием на пиктограмму с телефонной трубкой и зелёной стрелкой, либо через меню "Вызов", либо сочетанием горячих клавиш, либо через контекстное меню, как это показано ниже:

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

Ставим входящий звонок на паузу:

Опять же - поставить на паузу можно сочетанием горячих клавиш, либо через меню "Вызов".

Стоящий в очереди звонок отображается следующим образом:

При этом телефонная станция воспроизводит ожидающему абоненту музыку.

Пока звонок стоит в очереди, совершаем исходящий звонок:


Этот же исходящий звонок будет отображаться всплывающей надписью в правом верхнем углу экрана:


Дозвонившись до специалиста, объясняем ему суть вопроса, который обсуждался с ожидающим абонентом и предлагаем им поговорить друг с другом.

Соединение абонентов друг с другом:

После соединения абонентов друг с другом, оба звонка исчезают из списка в программе и продолжают общаться между собой уже без нашего участия.

Как вы заметили, кроме передачи звонка другому абоненту, имеется ещё возможность создать конференцию. Во отличие от соединения двух абонентов между собой, когда соединённые звонки пропадают из списка, конференция остаётся в списке. Конференция поддерживается самим демоном sflphone, при этом не используются функции конференций Asterisk. Выглядит конференция следующим образом:

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

В процессе использования перенаправлений звонков обнаружил, что телефонные шлюзы Cisco ATA 186 не поддерживают функцию REINVITE, которая позволяет абоненту с другой стороны попросить согласовать параметры звука с другим абонентом. Именно эта опция используется для перенаправления звонков. На случай подобных телефонных шлюзов в Asterisk имеется опция canreinvite. Чтобы указать, что телефонный шлюз не умеет переключаться на другого абонента, нужно указать в настройках SIP-пользователя опцию canreinvite=no. В этом случае Asterisk будет выступать посредником при трансляции звука. При установлении первого сеанса звук от обоих абонентов будет проходить через Asterisk. Когда нужно будет выполнить переключение, Aterisk самостоятельно выполнит REINVITE с одним из абонентов, продолжая трансляцию звука через себя для другого абонента, который не поддерживает REINVITE.

воскресенье, 8 мая 2016 г.

Настройка видео в Asterisk и Ekiga

В прошлой заметке Краткий обзор программного телефона и клиента обмена мгновенными сообщениями Ekiga я обмолвился о том, что этот программный телефон позволяет, при наличии веб-камеры, в процессе разговора ещё и обмениваться видео. Я заинтересовался этой возможностью и решил попробовать настроить обмен видео через Asterisk.

1. Включение поддержки видео в SIP

Чтобы включить передачу видео через Asterisk, нужно в файле /etc/asterisk/sip.conf в раздел general добавить опцию:
videosupport=yes

2. Настройка кодеков в учётных записях SIP-абонентов

Далее, в том же файле в настройках учётных записей SIP, под которыми на Asterisk регистрируются программы Ekiga, нужно явным образом прописать список поддерживаемых кодеков:
disallow=all
allow=gsm
allow=alaw
allow=ulaw
allow=h264
allow=h261
allow=mpeg4
Как оказалось, по умолчанию были разрешены только аудиокодеки и один видеокодек h261. Здесь я не указал ещё два возможных видеокодека - h263 и h263p, при использовании которых видео почему-то не работало.

3. Настройка кодеков в учётных записях SIP-транков

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

Сразу замечу, что передавать видео между разными станциями по протоколу IAX2 мне не удалось.

4. Применение настроек Asterisk

Далее, чтобы новые настройки вступили в силу, нужно попросить Asterisk перечитать настройки модуля sip:
# asterisk -rx 'sip reload'
5. Настройка кодеков в Ekiga

Открываем меню "Правка", выбираем пункт "Параметры". В открывшемся окне "Настройки Ekiga" разворачиваем ветку "Звук" и выбираем пункт "Кодеки". Отмечаем только кодеки PCMU (соответствует ulaw в Asterisk), PCMA (соответствует alaw в Asterisk) и gsm:


Теперь разворачиваем в том же окне ветку "Видео" и выбираем в ней пункт "Кодеки". Отмечаем только кодеки H264 и MP4V-ES (соответствует mpeg4 в Asterisk). Можно отметить ещё кодек H261, но с помощью стрелок выставить его приоритет ниже кодека H264. По моему опыту, у него ниже качество (разрешение 176x144) и работает он менее стабильно (может рассыпаться на крупные кубики). Кодеки H263 и H263-1998 (соответствует h263p в Asterisk) у меня не заработали, поэтому их использование отключил.


6. Тестовый звонок

Когда всё заработало, выглядело это вот так:

Я сидел за компьютером с ноутбуком на коленях, поэтому в окне меня видно с двух сторон :) Гарнитура была подключена только к одному из компьютеров и лежала на столе.

Стоит приготовиться к тому, что видео не заработает сразу и придётся подбирать кодеки, с которыми оно, наконец, заработает.

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

воскресенье, 1 мая 2016 г.

Краткий обзор программного телефона и клиента обмена мгновенными сообщениями Ekiga

Отвлечёмся ненадолго от Asterisk и обратимся к смежной теме - программным телефонам для Linux.

Ekiga - это программа, сочетающая в себе возможности программного телефона, поддерживающего протоколы SIP и H.323, и клиента обмена мгновенными сообщениями, поддерживающего протокол Jabber/XMPP. Кроме звонков и обмена текстовыми сообщениями, программа при наличии веб-камеры, позволяет также обмениваться с собеседником видео. Программа была создана в рамках одноимённого сервиса - ekiga.net. В некотором роде его можно считать аналогом Skype, но построенном полностью на открытых технологиях. Конечно, не стоит считать Ekiga полным аналогом Skype, т.к. в Skype имеется много других возможностей - создание конференций, "приземление" звонков (то есть звонки на телефонные номера телефонной сети общего пользования) и т.п.

Установить программу можно очень просто, из репозиториев:
# apt-get install ekiga
Главное окно программы выглядит следующим образом.

Здесь можно увидеть список контактов. Между протоколами не делается никаких различий, все контакты, будь то SIP или XMPP, выводятся в общий список. Поддерживается группировка контактов.

При нажатии на соответствующую кнопку можно переключиться в окно номеронабирателя:

Это окно может оказаться полезным, если нужно позвонить на некий телефонный номер однократно. Постоянных собеседников удобнее добавить в список контактов.

Следующая кнопка отображает историю звонков:


Окно переписки с абонентами Jabber/XMPP выглядит следующим образом:

Стоит отметить, что программа обладает весьма ограниченной поддержкой протокола Jabber/XMPP. Фактически можно видеть только статусы собеседников и переписываться с ними. Нельзя посмотреть профиль собеседника, нельзя отправить или принять файл.

Список учётных записей можно открыть через меню "Правка" - "Учётные записи" или нажатием Ctrl-E:


Вот так выглядят настройки учётной записи Jabber/XMPP:

Настройки очень бедные. Нельзя задать прокси или настроить шифрование.

Вот так выглядят настройки учётной записи SIP:

Тоже очень бедные настройки. Нельзя задать STUN-прокси, нельзя выбрать прослушиваемый интерфейс и порт. Программа будет использовать UDP-порт 5060 и сообщать при регистрации на SIP-прокси IP-адрес первого попавшегося интерфейса, кроме lo.

Авторы явно были под влиянием Gnome HIG и убрали все настройки, которые посчитали лишними, в аналог реестра Windows - каталог .gconf/ с XML-файлами. Чтобы получить доступ к остальным настройкам, нужно установить программу gconf-editor из одноимённого пакета. Например, при помощи такой команды:
# apt-get install gconf-editor
При запуске команды gconf-editor от имени обычного пользователя можно исправлять настройки этого пользователя. Например, прослушиваемый порт можно поменять в параметре apps - ekiga - protocols - sip - listen_port:

Мне это понадобилось сделать для того, чтобы запустить Ekiga и Asterisk на одном и том же компьютере. Поскольку порт 5060 уже используется Asterisk, Ekiga должна использовать другой порт. То же самое может потребоваться сделать, если за компьютером работают несколько пользователей одновременно (мало ли в жизни бывает?) и каждому из них нужно использовать свой SIP-телефон (обычно SIP-телефоны по умолчанию прослушивают UDP-порт 5060, так что одного порта на всех не хватает). К сожалению, это не единственный случай, когда разработчики современных программ для Linux забывают, что Linux - это многопользовательская система, в которой одновременно может работать несколько пользователей, а один и тот же пользователь может открыть одновременно несколько сеансов.

Поменять используемый STUN-прокси тоже можно через gconf-editor:

Как видно, отвечают за него параметры enable_stun и stun_server в ветке apps - ekiga - general - nat.

Ещё один полезный раздел настроек - это список используемых программой портов. В ветке apps - ekiga - protocols - ports есть параметры tcp_port_range и udp_port_range:

Если на компьютере настроен пакетный фильтр, следует по крайней мере разрешить доступ к локальным UDP-портам из этого списка снаружи. Эти порты используются для обмена мультимедийным трафиком - аудио и видео. О назначении портов TCP сказать ничего не могу.

В следующей заметке я опишу настройку Asterisk для обмена видео между программными телефонами Ekiga.

воскресенье, 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'