воскресенье, 23 сентября 2018 г.

Сборка RAID-массива на контроллере LSI MegaSAS в Linux

В прошлом я уже писал ряд заметок про RAID-контроллеры семейства LSI MegaSAS - Intel RS2WC040 и Intel RSBL040, которые используются у меня на работе:
Иногда приходится менять диски, подключенные к аппаратным RAID-контроллерам. Замену диска при помощи mfiutil во FreeBSD я уже описывал, а аналогичная задача в Linux решается при помощи утилиты megacli, которая доступна в стороннем репозитории. Процедура замены дисков у меня до автоматизма не доведена, т.к. менять их приходится не часто. Поэтому я завёл для себя страницу в wiki, в которой делал заметки, чтобы не пришлось вспоминать команды и последовательность действий в следующий раз. Несколько раз я исправлял ошибки в заметке и даже дополнил её описанием решения проблемы с добавлением диска, который ранее уже состоял в другом RAID-массиве. Наконец, заметка дозрела до состояния, пригодного к публикации.

Установка утилиты

Установить утилиту megacli в Debian можно из неофициального репозитория HwRAID. Например, чтобы подключить репозиторий в Debian Stretch, нужно добавить в файл /etc/apt/sources.list такую строчку:
deb http://hwraid.le-vert.net/debian stretch main
Установим в систему GPG-ключ для проверки подлинности репозитория при помощи команды:
# wget -O - https://hwraid.le-vert.net/debian/hwraid.le-vert.net.gpg.key | apt-key add -
Теперь можно обновить список пакетов, доступных для установки из репозиториев:
# apt-get update
И установить утилиту mecacli для управления RAID-контроллером:
# apt-get install megacli

Просмотр информации о RAID-контроллере

Чтобы просмотреть модель, серийный номер, настройки RAID-контроллера:
# megacli -AdpAllInfo -aAll

Диагностика

Смотрим список и состояние RAID-массивов в поле Sate:
# megacli -LdInfo -Lall -aALL
Если там Degraded, значит массив развалился. Смотрим, есть ли строчки Firmware state с состоянием Failed:
# megacli -PdList -a0
Если есть, можно посмотреть состояние диск по SMART. Для этого в выводе команды смотрим идентификаторы дисков в поле Device Id. Дальше указывая эти идентификаторы можно увидеть состояние SMART каждого из дисков и определить его серийный номер:
# smartctl -a -d megaraid,4 /dev/sda
# smartctl -a -d megaraid,5 /dev/sda
# smartctl -a -d megaraid,7 /dev/sda
# smartctl -a -d megaraid,6 /dev/sda

Диск исправен - запуск перестроения массива

Если диск исправен, можно попробовать перестроить массив. Для этого находим значения полей Enclosure Device ID и Slot Number у неисправного диска и выполняем для него команду запуска перестроения массива. В примере ниже используются значения 252 и 3:
# megacli -PdRbld -Start -PhysDrv[252:3] -a0
Наблюдать за состоянием перестроения массива можно при помощи команды:
# megacli -PdRbld -ShowProg -PhysDrv [252:3] -a0

Диск неисправен - замена диска

Если диск неисправен, его нужно заменить. Помечаем его как отключенный:
# megacli -PdOffline -PhysDrv [252:3] -a0
Затем - как отсутствующий в массиве:
# megacli -PdMarkMissing -PhysDrv [252:3] -a0
И теперь - как подготовленный к удалению из системы:
# megacli -PdPrpRmv -PhysDrv [252:3] -a0
Неисправный диск можно подсветить светодиодом:
# megacli -PdLocate -start -PhysDrv [252:3] -a0
Если индикация не заработала, можно попробовать починить её при помощи следующей команды:
# megacli -AdpSetProp \{UseDiskActivityforLocate -1\} -aALL
Заменяем диск (в случае SAS это можно сделать на горячую, если по светодиодным индикаторам видно, какой из дисков неактивен).

Когда новый диск вставлен, убираем подсветку светодиодом:
# megacli -PdLocate -stop -PhysDrv [252:3] -a0
После замены диска смотрим, каких дисков не хватает в RAID-массиве:
# megacli -PdGetMissing -a0
                                     
    Adapter 0 - Missing Physical drives

    No.   Array   Row   Size Expected
    0     1       1     428199 MB

Exit Code: 0x00
Вставляем новый диск в пустующее место в массиве:
# megacli -PdReplaceMissing -PhysDrv [252:3] -array1 -row1 -a0
Если диск не вставляется и выводится ошибка следующего вида:
Adapter: 0: Failed to replace Missing PD at Array 1, Row 1.

FW error description: 
 The specified device is in a state that doesn't support the requested command.  

Exit Code: 0x32
То можно проверить текущее состояние прошивки диска:
# megacli -PdInfo -PhysDrv [252:3] -a0
Если в строке Firmware state отображается состояние JBOD, то исправить это состояние можно следующим образом:
# megacli -PdMakeGood -PhysDrv[252:3] -Force -a0
Если же в строке Firmware state отображается состояние Unconfigured(good), Spun Up, но в строке Foreign State отображается состояние Foreign, то надо просканировать наличие дисков, переставленных из других RAID-контроллеров и снять у таких дисков отметку о других контроллерах:
# megacli -CfgForeign -Scan -aALL
# megacli -CfgForeign -Сlear -aALL
Включаем новый диск в работу массива:
# megacli -PdRbld -Start -PhysDrv [252:3] -a0
Посмотреть продвижение процесса перестроения можно так:
# megacli -PdRbld -ShowProg -PhysDrv [252:3] -a0

Подробнее:

воскресенье, 16 сентября 2018 г.

Multiarch в Debian Stretch

На свежеустановленной системе Debian Stretch столкнулся с проблемой при запуске 32-битного двоичного исполняемого файла в 64-битной системе:
# ./cfgfmt.linux -tptag.dat -sip ata0025459496ab.txt ata0025459496ab
-su: ./cfgfmt.linux: Нет такого файла или каталога
# file cfgfmt.linux 
cfgfmt.linux: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.0.0, stripped
И тут я вспомнил о том, что нужно включить multiarch - мультиархитектурность, которая позволяет запускать исполняемые файлы совместимых архитектур в операционной системе, которая обычно расчитана на поддержку только какой-либо одной конкретной архитектуры. Например, моя операционная система расчитана на архитектуру amd64, однако с поддержкой мультиархитектурности имеется возможность запуска приложений для совместимой с ней архитектуры i386.

Для добавления дополнительной совместимой архитектуры i386 в операционную систему архитектуры amd64 понадобится выполнить следующую команду:
# dpkg --add-architecture i386
Текущую архитектуру можно посмотреть такой командой:
# dpgk --print-architecture
Список совместимых архитектур, поддержка которых включена в системе, можно посмотреть при помощи такой команды:
# dpkg --print-foreign-architectures
Для получения возможности устанавливать пакеты архитектуры i386 из репозиториев понадобится настроить менеджер пакетов APT. Для этого зададим основную архитектуру и список всех используемых архитектур, создав файл /etc/apt/apt.conf.d/arch со следующим содержимым:
APT::Architecture "amd64";
APT::Architectures "amd64,i386";
Обновим список доступных к установке пакетов из репозиториев:
# apt-get update
Для запуска двоичных файлов, скомпилированных для архитектуры i386, нужно как минимум установить стандартную библиотеку поддержки языка Си:
# apt-get install libc6-i386
Пробуем выполнить первоначальную команду ещё раз:
# ./cfgfmt.linux -tptag.dat -sip ata0025459496ab.txt ata0025459496ab
На этот раз ошибок нет.

воскресенье, 9 сентября 2018 г.

Flash-плеер в Debian Stretch

Чуть больше года назад я уже писал заметку Flash-плагин для Chromium и Iceweasel/Firefox в Debian, в которой чинил флеш-плеер в Debian Jessie. Я пропустил тот момент, когда из репозитория Debian исчезли пакеты со скриптами для установки и обновления флеш-плеера. В моей системе, обновлённой до Stretch, всё ещё присутствовали эти пакеты и поэтому я продолжал считать, что они всё ещё есть в репозиториях. Однако, в свежеустановленной системе Debian Stretch эти пакеты установить из репозиториев не удалось. И если решить проблему с установкой флеш-плеера для Firefox удалось довольно быстро, то над аналогичным решением для Chromium пришлось поломать голову. Результатом своих изысков и спешу поделиться.

Flash-плагин NPAPI в Iceweasel


В Debian Stretch браузер Iceweasel более ничем не отличается от браузера Firefox, т.к. Debian и Mozilla договорились об использовании бренда Firefox вместо Iceweasel. Если в вашей системе всё ещё установлен Iceweasel, можете установить вместо него Firefox, а Iceweasel удалить.

Flash-плагин NPAPI в Firefox


Если браузер ещё не установлен в системе, сделать это можно такой командой:
# apt-get install firefox-esr firefox-esr-l10n-ru
Скачиваем с официального сайта Adobe файл flash_player_npapi_linux.x86_64.tar.gz Для этого заходим на официальную страницу Adobe, переходим по ссылке внизу Adobe Flash Player, переходим по ссылке Нужен проигрыватель Flash Player для другого компьютера?, в выпадающем списке «Шаг 1» вместо «Выберите операционную систему» выбираем «Linux (64-бит)», в выпадающем списке «Шаг 2» вместо «Выберите версию» выбираем «FP 30.0 for Linux 64-bit (tar.gz) - NPAPI» и жмём на кнопку «Загрузить».

Далее по пользователем root перейдём в каталог /usr/lib и создадим каталог для разделяемой библиотеки Flash-плеера:
# cd /usr/lib
# mkdir flashplugin-nonfree
# cd flashplugin-nonfree
Извлечём разделяемую библиотеку из скачанного архива:
# tar xzvf /home/stupin/Downloads/flash_player_npapi_linux.x86_64.tar.gz libflashplayer.so
Поменяем владельца библиотеки и права доступа к ней:
# chown root:root libflashplayer.so 
# chmod u=rw,go=r libflashplayer.so
Добавим разделяемую библиотеку в список альтернативных версий флеш-плагина для браузеров семейства Mozilla:
# update-alternatives --quiet --install /usr/lib/mozilla/plugins/flash-mozilla.so flash-mozilla.so /usr/lib/flashplugin-nonfree/libflashplayer.so 50
И выберем эту альтернативу в качестве текущей используемой:
# update-alternatives --set flash-mozilla.so /usr/lib/flashplugin-nonfree/libflashplayer.so

Flash-плагин PPAPI в Chromium

Если браузер ещё не установлен в системе, сделать это можно такой командой:
# apt-get install chromium chromium-l10n
Скачиваем с официального сайта Adobe файл flash_player_npapi_linux.x86_64.tar.gz Для этого заходим на официальную страницу Adobe, переходим по ссылке внизу Adobe Flash Player, переходим по ссылке Нужен проигрыватель Flash Player для другого компьютера?, в выпадающем списке «Шаг 1» вместо «Выберите операционную систему» выбираем «Linux (64-бит)», в выпадающем списке «Шаг 2» вместо «Выберите версию» выбираем «FP 30.0 for Linux 64-bit (tar.gz) - PPAPI» и жмём на кнопку «Загрузить».

Далее по пользователем root перейдём в каталог /usr/lib и создадим каталог для разделяемой библиотеки Flash-плеера:
# cd /usr/lib
# mkdir pepperflashplugin-nonfree
# cd pepperflashplugin-nonfree
Извлечём разделяемую библиотеку из скачанного архива:
# tar xzvf /home/stupin/Downloads/flash_player_ppapi_linux.x86_64.tar.gz libpepflashplayer.so
Поменяем владельца библиотеки и права доступа к ней:
# chown root:root libpepflashplayer.so 
# chmod u=rw,go=r libpepflashplayer.so
Извлечём файл manifest.json, чтобы посмотреть версию скачанного плагина:
# tar xzvf /home/stupin/Downloads/flash_player_ppapi_linux.x86_64.tar.gz manifest.json
Смотрим версию скачанного плагина и удаляем этот файл - он нам больше не понадобится:
# grep version manifest.json 
  "version": "30.0.0.154",
Открываем файл /etc/chromium.d/default-flags и вписываем вниз файла опции, которые указывают путь к плагину и его версию:
export CHROMIUM_FLAGS="$CHROMIUM_FLAGS --ppapi-flash-path=/usr/lib/pepperflashplugin-nonfree/libpepflashplayer.so --ppapi-flash-version=30.0.0.154"
Версию указывать необходимо, т.к. в противном случае определяется версия 11.x и некоторые флеш-приложения отказываются работать, требуя обновить флеш-плеер.

Теперь нужно завершить браузер, завершить текущий сеанс (выйти из графической оболочки). Это тоже необходимо сделать, т.к. в противном случае изменения из отредактированного файла не будут применены к текущему сеансу и настроенные в этом файле переменные окружения в текущем сеансе сохранят свои прежние значения.

После повторного входа можно запустить браузер и перейти по ссылке chrome://version/ или chrome://flash/ и убедиться, что в строчке Flash или Flash plugin соответственно фигурируют установленные версия плагина и путь к нему.

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

воскресенье, 2 сентября 2018 г.

Настройка кэширующего DNS-сервера BIND в связке с openresolv

Обнаружил, что заметка Настройка кэширующего DNS-сервера BIND в связке с resolvconf в новых релизах Debian больше не работает. Вспомнил об аналоге resolvconf под названием openresolv, который я когда-то нашёл, но воспользоваться которым пока не доводилось. Решил попробовать и openresolv заработал как надо. Спешу поделиться рецептом.

Первым делом установим openresolv:
# apt-get install openresolv
Приведём его файл конфигурации /etc/resolvconf.conf к следующему виду:
resolv_conf=/etc/resolv.conf
name_servers=127.0.0.1
named_options=/var/run/named/named.options
Обновим файлы с DNS-серверами при помощи следующей команды:
# resolvconf -u
В файле /var/run/named/named.options можно увидеть фрагмент конфигруации BIND, которую можно подключить к основной конфигурации. В моём случае он выглядит следующим образом:
# Generated by resolvconf
forward first;
forwarders {
 109.195.144.4;
 5.3.3.3;
 81.30.199.5;
 81.30.199.94;
};
Чтобы включить этот фрагмент в конфигурацию BIND, впишем в файл /etc/bind9/named.conf.options одну строчку:
include "/var/run/named/named.options";
Ещё раз обновим файлы с DNS-серверами при помощи команды:
# resolvconf -u
В процессе обновления BIND будет автоматически перезапущен, так что в его файл конфигурации будет вписан актуальный список вышестоящих рекурсивных DNS-серверов.

Список интерфейсов, с которых взяты DNS-серверы, можно узнать при помощи следующей команды:
# resolvconf -i
В моём случае она вывела такой список:
ppp0 vlan3
Список DNS-серверов, полученных через эти интерфейсы, можно узнать при помощи такой команды:
# resolvconf -l
В моём случае вывод был таким:
# resolv.conf from ppp0
# Generated by ppp.ip-up for ppp0
nameserver 109.195.144.4
nameserver 5.3.3.3

# resolv.conf from vlan3
# resolv.conf for vlan3
domain ipoe3.ufanet.ru
nameserver 81.30.199.5
nameserver 81.30.199.94

воскресенье, 26 августа 2018 г.

Настройка PPPoE-подключения к ЭР-Телеком/Дом.ru (Уфанет, Башинформсвязь)

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

Установим пакет RP-PPPoE, при помощи которого можно устанавливать подключения:
# apt-get install pppoe
Создадим файл /etc/ppp/peers/ertelecom и впишем в него настройки подключения:
user "login"
plugin rp-pppoe.so
eth0
noipdefault
usepeerdns
defaultroute
persist
noauth
maxfail 0
unit 0
Где:
  • login - ваш логин по договору,
  • eth0 - имя Ethernet-интерфейса, к которому подключен кабель провайдера.
Теперь откроем файл /etc/ppp/chap-secrets и впишем в него логин и пароль для подключения.
# Secrets for authentication using CHAP
# client server secret   IP addresses
login         *       password                *
Первые две строчки - это комментарии, которые уже есть в файле. В третьей строчке указаны учётные данные для подключения: login - логин, password - пароль.

Осталось вписать настройки в файл /etc/network/interfaces, чтобы связь с провайдером устанавливалась при загрузке компьютера:
# ertelecom ethernet
auto eth0
iface eth0 inet manual

# ertelecom pppoe
auto ertelecom
iface ertelecom inet ppp
  provider ertelecom
Установить подключение или разорвать его из командной строки можно такими командами:
# ifup ertelecom
# ifdown ertelecom

Настройка подключения к Уфанет по технологии PPPoE была полностью аналогична рассмотренной выше, однако в последнее время Уфанет переводит всех клиентов на технологию IPoE. При этом абонент просто получает настройки Ethernet-интерфейса по протоколу DHCP, а попытка открыть любую веб-страницу в браузере приведёт к попаданию на страницу авторизации. После того, как абонент введёт на странице авторизации свои учётные данные, доступ в интернет открывается. Повторно авторизация запрашивается при смене MAC-адреса компьютера.

Настройка подключения к Башинформсвязи аналогична рассмотренной выше за исключением того, что в Башинформсвязи используется аутентификация по протоколу PAP, а не CHAP, из-за чего логин и пароль нужно вписывать в файл /etc/ppp/pap-secrets, а не в файл /etc/ppp/chap-secrets, как это описано выше.

воскресенье, 10 июня 2018 г.

Изменение размера NTFS-раздела в образе диска в формате VDI

В одной из прошлых заметок я описывал использование VirtualBox в Debian Stretch. При создании виртуальной машины я указал слишком маленький размер образа диска.

Чтобы изменить размер образа VDI, имеющего динамический размер, нужно в главном окне Virtual Box переключиться на инструмент "Менеджер виртуальных носителей", выбрать образ диска, указать его новый размер и нажать на кнопку "Применить".

На этом можно было бы закончить рассказ, если бы VirtualBox знал бы что-нибудь о разделах и файловых системах, находящихся внутри образа диска. Так как он ничего об этом не знает, поменять размеры всего этого нам придётся вручную. Для этого, кроме самого VirtualBox, нам понадобятся три пакета:
  1. parted - утилита для манипуляции дисковыми разделами, которая умеет не только удалять разделы и создавать новые, но и изменять существующие,
  2. ntfs-3g - в этом пакете находится утилита ntfsresize, с помощью которой можно изменить размеры файловой системы NTFS,
  3. partclone - в этом пакете имеется утилита partclone.ntfsfixboot, при помощи которой можно исправить загрузочный сектор файловой системы NTFS, так чтобы он знал геометрию диска и положение раздела NTFS на этом диске.
Если какие-то из пакетов ещё не установлены в системе, то установить их можно такой командой:
# apt-get install parted ntfs-3g partclone
Первым делом нам понадобится преобразовать образ диска виртуальной машины из формата VDI в формат, представляющий собой побайтовую копию диска. Для этого воспользуемся утилитой VBoxManage, которая поставляется совместно с VirtualBox:
$ VBoxManage clonemedium --format RAW win.vdi win.img
Несмотря на кажущуюся универсальность концепции файла в Unix, простые файлы отличаются от блочных устройств, поэтому нам нужно отобразить простой файл с образом диска в блочное устройство. Для этого воспользуемся утилитой losetup, которая как раз позволяет делать то, что нам требуется:
# losetup -f win.img
Смотрим, какому блочному устройству соответствует файл образа диска:
# losetup -a
Вывод команды:
/dev/loop0: [2051]:14947724 (/home/stupin/VirtualBox VMs/win/win.img)
Приступим к изменению размеров раздела. Воспользуемся для этого утилитой parted и для начала выведем таблицу имеющихся разделов. В качестве единицы измерения размеров и координат разделов попросим утилиту использовать секторы:
# parted /dev/loop0 unit s print
Вывод команды:
Model: Loopback device (loopback)
Disk /dev/loop0: 8388608s
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start  End       Size      Type     File system  Flags
 1      63s    4185215s  4185153s  primary  ntfs         boot
Судя по таблице разделов, в образе диска имеется только один первичный раздел, который является загрузочным. Общий размер образа - 8388608 секторов. Переместим конечный сектор первого раздела в конец образа диска, для чего укажем номер последнего сектора раздела на единицу меньше:
# parted /dev/loop0 resizepart 1 8388607s
Теперь нужно изменить размер файловой системы в первом разделе образа диска. Для начала сделаем так, чтобы операционная система узнала о разделах, имеющихся на блочном устройстве /dev/loop0. Для этого воспользуемся утилитой partprobe, которая имеется в комплекте утилиты parted:
# partprobe /dev/loop0
После поиска разделов появится файл устройства /dev/loop0p1, соответствующий первому первичному разделу в образе.

Для изменения размера файловой системы, как уже было написано выше, мы воспользуемся утилитой ntfsresize. Однако, прежде чем изменить размер файловой системы, узнаем текущий размер этой файловой системы и раздела, на котором она расположена. Сделать это можно при помощи самой утилиты ntfsresize:
# ntfsresize -i /dev/loop0p1
Вывод команды:
ntfsresize v2016.2.22AR.1 (libntfs-3g)
Device name        : /dev/loop0p1
NTFS volume version: 3.1
Cluster size       : 2048 bytes
Current volume size: 2142798336 bytes (2143 MB)
Current device size: 4294935040 bytes (4295 MB)
Checking filesystem consistency ...
100.00 percent completed
Accounting clusters ...
Space in use       : 1440 MB (67,2%)
Collecting resizing constraints ...
You might resize at 1439602688 bytes or 1440 MB (freeing 703 MB).
Please make a test run using both the -n and -s options before real resizing!
Изменяем размер файловой системы до размеров раздела:
# ntfsresize -s 4294935040 /dev/loop0p1
Вывод команды (нужно будет подтвердить её выполнение нажатием y):
ntfsresize v2016.2.22AR.1 (libntfs-3g)
Device name        : /dev/loop0p1
NTFS volume version: 3.1
Cluster size       : 2048 bytes
Current volume size: 2142798336 bytes (2143 MB)
Current device size: 4294935040 bytes (4295 MB)
New volume size    : 4294935040 bytes (4295 MB)
Checking filesystem consistency ...
100.00 percent completed
Accounting clusters ...
Space in use       : 1440 MB (67,2%)
Collecting resizing constraints ...
WARNING: Every sanity check passed and only the dangerous operations left.
Make sure that important data has been backed up! Power outage or computer
crash may result major data loss!
Are you sure you want to proceed (y/[n])? y
Schedule chkdsk for NTFS consistency check at Windows boot time ...
Resetting $LogFile ... (this might take a while)
Updating $BadClust file ...
Updating $Bitmap file ...
Updating Boot record ...
Syncing device ...
Successfully resized NTFS on device '/dev/loop0p1'.
Размер файловой системы изменён и её даже можно смонтировать, но вот попытка загрузить с неё систему приведёт к ошибке "disk read error occured". Дело в том, что мы изменили размер файловой системы, но загрузчику операционной системы об этом не сообщили.

Чтобы загрузчик узнал о новом положении файловой системы на диске и её размере, воспользуемся уже упомянутой утилитой partclone.ntfsfixboot. По умолчанию эта утилита пытается узнать геометрию жёсткого диска при помощи системного вызова ioctl. Поскольку образ диска, даже будучи отображённым в блочное устройство, не превращается в настоящий диск, то системные вызовы ioctl будут завершаться ошибкой.

Однако, у современных жёстких дисков реальная геометрия учитывается встроенным в жёсткий диск контроллером, а снаружи весь диск выглядит как линейная последовательность блоков. Этот режим адресации называется LBA - Logical Block Addressing - логическая адресация блоков. Поэтому геометрия диска, которая записана в загрузчике, в настоящее время является атавизмом и реально не используется. В поля геометрии диска, работающего в режиме LBA, записываются максимальные возможные значения: 255 головок, 63 сектора на дорожке. Самая первая по счёту дорожка на диске обычно называлась загрузочной, т.к. на ней располагался загрузочный сектор. Внутри раздела диска содержится собственный загрузочный сектор, который инициирует загрузку операционной системы, находящейся в этом разделе. Смещение загрузочного сектора относительно начала раздела тоже может быть разным для файловых систем разного типа. В случае с NTFS этот загрузчик находится в 63 секторе внутри раздела.

Вооружившись всей этой информацией, поправим загрузочный сектор файловой системы NTFS на первом разделе образа диска:
# partclone.ntfsfixboot -b -w -h 255 -t 63 -s 63 /dev/loop0p1
Задача почти выполнена. Отключаем отображение файла с образом диска в блочное устройство:
# losetup -d /dev/loop0
Преобразовываем отредактированный образ обратно в формат VDI (на всякий случай старый файл с образом VDI оставляем):
$ VBoxManage convertfromraw --format VDI win.img win2.vdi
Осталось выбрать новый файл образа в настройках виртуальной машины и попробовать загрузить виртуальную машину с нового образа диска. Если всё в порядке, то исходный VDI-файл и его побайтовую версию можно удалить.

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


воскресенье, 22 апреля 2018 г.

VirtualBox в Debian Stretch

Когда-то я тестировал несколько эмуляторов, о чём написал заметку Эмуляторы VirtualBox и QEmu в Debian. Недавно мне снова понадобилось воспользоваться эмулятором и я решил воспользоваться старыми наработками. Однако, ситуация с тех пор несколько изменилась. Во-первых, VirtualBox теперь отсутствует в стандартных репозиториях Debian, а во-вторых, графическая оболочка qemulator для qemu теперь обросла функциями и сменила название на virtualbricks.

VirtualBricks

Попробуем установить virtualbricks:
# apt-get install virtualbricks
Сразу после запуска программа выводит сообщение об отсутствующих компонентах:

Если проигнорировать это сообщение, создать виртуальную машину и попытаться перейти к её настройке, выводится сообщение о том, что virtualbricks не смог распознать версию qemu:

Если попытаться установить недостающие компоненты, сообщений об отсутствующих компонентах станет меньше.
# apt-get install vde2-cryptcab qemu ksmtuned

Однако делу это совершенно не помогает: если после создания виртуальной машины попытаться перейти к её настройке, то программа по-прежнему продолжает выводить сообщение о нераспознанной версии qemu. Как видно, попытка нарастить функциональности при помощи груды кода на Python, не пошла проекту на пользу. На этом я решил закончить эксперименты с virtualbricks, удалил всё установленное и решил снова попытать судьбу с VirtualBox.

Установка VirtualBox

На официальном сайте проекта в разделе скачивания Download VirtualBox for Linux Hosts имеется рекомендация устанавливать VirtualBox в Debian Jessie из репозитория https://download.virtualbox.org/virtualbox/debian. Пропишем его в файл /etc/apt/sources.list:
deb http://download.virtualbox.org/virtualbox/debian stretch contrib
Обратите внимание, что на официальном сайте указана ссылка, использующая протокол https. Эта ссылка не работает. Чтобы репозиторий подключился без ошибок, нужно поменять в ссылке протокол https на http, как это и было сделано в строчке выше.

Сразу же скачаем и установим в систему PGP-ключи репозитория:
# wget -q https://www.virtualbox.org/download/oracle_vbox_2016.asc -O- | sudo apt-key add -
# wget -q https://www.virtualbox.org/download/oracle_vbox.asc -O- | sudo apt-key add -
Обновим списки пакетов, доступных через репозитории:
# apt-get update
И установим пакет с VirtualBox:
# apt-get install virtualbox-5.2
При попытке запуска созданной виртуальной машины может появиться сообщение об ошибке следующего вида:

Для работы VirtualBox использует собственный модуль ядра vboxdrv. Если этот модуль не загружен, то и VirtualBox не будет работать. Для устранения ошибки нужно подгрузить модуль ядра:
# modprobe vboxdrv
Чтобы этот модуль автоматически загружался при загрузке системы, его можно вписать в файл /etc/modules:
vboxdrv
Если в системе отсутствует модуль ядра vboxdrv для текущей версии ядра, то modprobe будет ругаться следующим образом:
# modprobe vboxdrv
modprobe: FATAL: Module vboxdrv not found in directory /lib/modules/4.9.0-6-amd64
В частности, такая ошибка может появиться, если вы обновляли систему и было установлено ядро новой версии. В таком случае нужно собрать модуль ядра снова. Для этого надо выполнить команду vboxconfig:
# vboxconfig
Если в системе не установлены заголовочные файлы ядра, то команда сообщит об ошибке сборки модуля ядра вот таким образом:
vboxdrv.sh: Building VirtualBox kernel modules.
This system is currently not set up to build kernel modules.
Please install the Linux kernel "header" files matching the current kernel
for adding new hardware support to the system.
The distribution packages containing the headers are probably:
    linux-headers-amd64 linux-headers-4.9.0-6-amd64
Чтобы решить эту проблему, нужно установить пакет с заголовочными файлами ядра:
# apt-get install linux-headers-amd64
Таким образом, нужно сначала установить заголовочные файлы ядра, потом собрать модуль ядра vboxdrv при помощи команды vboxconfig, затем подгрузить модуль ядра и прописать его автозагрузку в файл /etc/modules:
# apt-get install linux-headers-amd64
# vboxconfig
# modprobe vboxdrv
# vim /etc/modules
Последняя команда в списке запускает текстовый редактор для редактирования файла /etc/modules, куда нужно вписать одну строчку:
vboxdrv

Настройка виртуальной машины

После установки запустим VirtualBox при помощи команды virtualbox, создадим и настроим виртуальную машину:

Виртуальная машина в целом создана, теперь просмотрим и отредактируем остальные её свойства:

Для установки Windows в виртуальную машину уберём из виртуальной машины дисковод для дискет и вставим в CD-ROM виртуальной машины образ установочного диска:

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

Установка Windows и Oracle VM VirtualBox Guest Additions

Запустим созданную виртуальную машину:

На этом экране можно видеть сводку свойств виртуальной машины:

После установки Windows в виртуальную машину (не показано), стоит поставить в неё Oracle VM VirtualBox Guest Additions - дополнительные драйверы и программы, делающие работу с виртуальной машиной более комфортной:



После установки Oracle VM VirtualBox Guest Additions заработал общий каталог с хост-системой, ради чего, преимущественно, эти дополнения и ставились:

воскресенье, 15 апреля 2018 г.

Локальный просмотр роликов с Youtube: утилиты cclive, mpv, rename

Иногда я скачиваю файлы с Youtube, чтобы смотреть их на телевизоре. Иногда это бывают сериалы. В таких случаях мне пригождается несколько утилит: cclive, mpv и rename. Рассмотрим их использование на примере мультсериала Гравити Фоллз.

cclive

cclive - это утилита командной строки, при помощи которой можно скачать ролик с Youtube. Утилита есть в репозиториях Debian, поэтому установить её очень легко. Для этого нужно установить одноимённый пакет:
# apt-get install cclive
Использование очень простое - надо вызвать эту программу, указав ей в качестве аргумента ссылку на страницу Youtube с роликом. Стоит заключить ссылку в одиночные кавычки, чтобы знаки амперсанда и вопроса не интерпретировались оболочкой:
$ cclive 'https://www.youtube.com/watch?v=uKjjDctxD6w&list=PLVtYY3Ujl33NFDWuw_E-OJcngyWayn7pA'
После скачивания в текущем каталоге появится файл с именем "Гравити Фолз Зомбикараоке Серия 1 Сезон 2.webm".

mpv

Мой медиаплеер WD TV Play, про который я ранее уже писал в заметке Настройка MiniDLNA для цифрового мультимедийного плеера WD TV Play и при помощи которого я смотрю видео на телевизоре, имеет ограниченную поддержку видеоформатов и кодеков. В частности, он не умеет воспроизводить видео в контейнере WebM, не поддерживает кодеки VP8 и Vorbis. Чтобы просматривать такие ролики на этом плеере, их нужно перекодировать. Пожалуй самым широко распространённым сочетанием контейнеров и кодеков, которое поддерживается большинством видеоплееров, являются контейнер AVI и кодеки MPEG4 и MP3.

Ранее в целях перекодирования видео я пользовался утилитой mencoder, которая разрабатывалась вместе с видеоплеером mplayer. Одно из достоинств этой утилиты заключалось в том, что она поддерживала двухпроходное кодирование, что позволяло достичь наилучшего качества при необходимости уместить результат в файл определённого размера. Это было очень полезно для перекодирования DVD-дисков в 700-мегабайтные AVI-файлы, которые умещались на компакт-диск. В репозиториях Debian Jessie пакет mencoder отсутствовал, поэтому тогда я подыскал замену для mencoder'а - утилиту mpv, которая совмещает в себе как функции видеоплеера, так и функции перекодировщика.

Установим mpv при помощи команды:
# apt-get install mpv
Теперь внесём ряд правок в файл /etc/mpv/encoding-profiles.conf с настройками профилей перекодирования.

Во-первых, я задал битрейт 128 килобит/с, частоту дискретизации 22 килогерца - для фильмов этого, как правило, бывает достаточно и 16-битные целочисленные отсчёты со знаком:
[enc-a-mp3]
profile-desc = "MP3 (LAME)"
oac = libmp3lame
oacopts = b=128k
audio-samplerate = 22050
audio-format = s16
Во-вторых, задал изменение соотношения сторон видео. Для телевизоров с электронно-лучевой трубкой не имеет особого смысла делать ширину видео более 720 пикселей, т.к. физическое разрешение электронно-лучевой трубки такого телевизора составляет 768x576 пикселей. На деле размер видимой области может оказаться и того меньше - 640x480 пикселей. В настройках укажем, что ширина видео должна равняться 720 пикселям, а высота должна рассчитываться исходя из отображаемого на экране соотношения сторон. Бывает что видео имеет не квадратный пиксель и при отображении дополнительно растягивается, чтобы убрать искажения. Опция предписывает использовать именно отображаемое соотношение сторон, чтобы при воспроизведении видео не нужно было масштабировать с разными коэффициентами по разным осям.
[enc-v-mpeg4]
profile-desc = "MPEG-4 Part 2 (FFmpeg)"
ovc = mpeg4
ovcopts = qscale=4
vf = scale=720:-2
В-третьих, оба профиля объединяются в один общий:
[enc-f-avi]
profile-desc = "MPEG-4 + MP3 (for AVI)"
of = avi
ocopyts = no
oautofps = yes
profile = enc-v-mpeg4
profile = enc-a-mp3
ofopts-clr = yes
Перекодировать видео с использованием этого профиля можно при помощи такой команды:
$ mpv --profile=enc-f-avi "Гравити Фолз Зомбикараоке Серия 1 Сезон 2.webm" -o "Гравити Фолз Зомбикараоке Серия 1 Сезон 2.avi"
Для последовательного перекодирования всех файлов с расширением webm в текущем каталоге можно воспользоваться таким однострочным скриптом:
$ ls *.webm | while read webm ; do avi=`echo "$webm" | sed 's/\.webm$/\.avi/g'` ; mpv --profile=enc-f-avi "$webm" -o "$avi" ; done

rename

rename - это утилита командной строки, позволяющая переименовывать файлы в соответствии с регулярными выражениями в стиле Perl. К слову, сама утилита представляет собой крохотный скрипт на Perl, использующий пару модулей. Утилита написана самим "великим и ужасным" Ларри Уоллом, если вам это о чём-то говорит. Утилита, несмотря на кажущуюся простоту, очень мощная и удобная. Во всяком случае, для тех, кто знает регулярные выражения Perl. Тот самый случай, когда подход Unix одерживает верх надо всеми приложениями с графическим интерфейсом.

Установка, как и в предыдущих случаях, очень проста:
# apt-get install rename
Для отладки регулярного выражения для переименования файлов можно воспользоваться опцией n:
$ rename -n 's/^Гравити Фолз (.*) Серия (\d+) Сезон (\d+).avi$/Гравити Фолз, E$3S$2 - $1.avi/' *.avi
После того, как результат будет соответствовать ожиданиям, можно выполнить ту же команду уже без опции n:
$ rename -n 's/^Гравити Фолз (.*) Серия (\d+) Сезон (\d+).avi$/Гравити Фолз, E$3S$2 - $1.avi/' *.avi
Вот ещё пример регулярного выражения - к номерам серий, состоящим из одной цифры, слева добавляется ноль:
$ rename 's/^Гравити Фолз, E(\d+)S(\d{1}) - (.*)\.avi$/Гравити Фолз, E$1S0$2 - $3\.avi/' *.avi
Остаётся положить файлы в каталог, к которому имеет доступ minidlna, чтобы через медиаплеер файлы можно было просматривать на телевизоре.

P.S. Медиаплеер WD TV Play позволяет просматривать ролики с Youtube прямо из интернета, но мне такой способ просмотра не кажется удобным, поэтому я им не пользуюсь.

воскресенье, 18 марта 2018 г.

Linux Capabilities и ping

Перевод: Linux Capabilities and Ping
Автор: Джим Макдоннелл (Jim McDonnell)

Примечания переводчика:
Перевод вдогонку к прошлой статье Пересборка uwsgi с поддержкой Linux Capabilities. Пока искал документацию о том, как скрестить uwsgi и POSIX Capabilities, наткнулся на эту статью. Сразу добавил ссылку в закладки, чтобы впоследствии перевести. Кстати, описанная в этой статье ошибка попадалась коллегам на работе. Я посоветовал просто принудительно переустановить пакет командой apt-get --reinstall install ping и это помогло. Причины были мне понятны, но вот о существовании команд для раздачи "возможностей" я не подозревал: мне почему-то казалось, что программы самостоятельно запрашивают необходимые им привилегии у ядра операционной системы.

Если вы используете свежую версию Linux (время написания заметки - май 2016), вы могли столкнуться с ошибкой утилиты ping:
$ ping somehost
ping: icmp open socket: Operation not permitted
Так происходит, потому что двоичный файл ping больше не устанавливается с правами setuid. Он не имеет необходимых привилегий для открытия сокета и завершается аварийно. Это легко исправить при помощи команды:
$ sudo setcap cap_net_raw+p /bin/ping
Предполагается, что двоичный файл ping находится в /bin/ping. Теперь он работает:
$ ping somehost
PING somehost (123.123.123.123) 56(84) bytes of data.
64 bytes from 123.123.123.123: icmp_seq=1 ttl=53 time=9.14 ms
Вы только что добавили возможность - capability к двоичному файлу ping, что дало ping право открыть raw-сокет, который позволил выполнить проверку доступности удалённой системы.

Linux Capabilities - возможности Linux

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

Ранее, до появления возможностей, ping и другие системные инструменты устанавливались с флагом setuid, позволяющим им работать от имени пользователя root. Вот так:
$ ls -l /bin/ping
-rwsr-xr-x 1 root root 44168 May 7 2014 /bin/ping
Символ "s" в строке разрешений соответствует флагу setuid, который означает, что ping будет выполняться с правами пользователя root, даже если он запущен обычным пользователем. Ping требует для работы повышенных привилегий. Вот несколько других программ, которые в Red Hat 6.5 по умолчанию устанавливаются с флагом setuid, который предписывает системе запускать их с правами root:
$ find /bin -perm +4000 -ls
652330 76 -rwsr-xr-x 1 root root 77336 Aug 6 2013 /bin/mount
656520 32 -rwsr-x--- 1 root fuse 32336 Nov 3 2011 /bin/fusermount
652317 36 -rwsr-xr-x 1 root root 36488 Sep 17 2013 /bin/ping6
652333 56 -rwsr-xr-x 1 root root 53472 Aug 6 2013 /bin/umount
652316 40 -rwsr-xr-x 1 root root 40760 Sep 17 2013 /bin/ping
651661 36 -rwsr-xr-x 1 root root 34904 Oct 17 2013 /bin/su

Опасность программ с флагом setuid

Механизм setuid отлично работает и широко распространён. Однако, он обладает низкой безопасностью. Процесс с флагом setuid во время работы получает гораздо больше привилегий, чем ему требуется на самом деле. Утилите ping требуется лишь открыть raw-сокет и права root, полученные ей через флаг setuid, позволяют это сделать, но также дают ей много других прав, которые ей не требуются. Если двоичный файл ping, например, был заменён взломанной версией, то код злоумышленника будет запущен с полными правами суперпользователя.

Это одна из причин, по которой предпочтительнее использовать возможности Linux, нежели флаг setuid. Вот почему они с каждым выпуском Linux стали использоваться всё шире.

Наборы возможностей

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

Каждый поток или процесс, обладает тремя наборами связанных с ним возможностей: Permitted - разрешённые, Inheritable - наследуемые и Effective - действующие. В примере выше, символы "+p" в команде "setcap cap_net_raw+p /bin/ping" добавили возможность cap_net_raw к набору разрешённых возможностей двоичного файла ping, которые означают, что последующий процесс (или поток) ping получит соответствующие права. Соотношения наборов возможностей, файлов и потоков, объясняются на соответствующей странице руководства.

CAP_NET_RAW

Возникает вопрос. Если ping для работы требуется определённая возможность или флаг setuid, почему тогда они не требуются другим сетевым утилитам, таким как ssh, ftp, wget и т.д.? И тем более, браузерам вроде Firefox и Safari? Разве им не требуется тоже открывать сетевые сокеты? Да, требуется, но не такие сокеты.

Давайте воспользуемся strace и посмотрим, как ping открывает сокет:
$ strace -e socket ping 192.168.1.254
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
...
ping открывает сокет типа SOCK_RAW.

Попробуем сделать то же самое с FTP и увидим, что он не открывает сокет типа SOCK_RAW. Он использует сокет типа SOCK_STREAM:
$ strace -e socket ftp 192.168.1.254
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
ftp: connect: Connection refused
Как и ожидалось. SOCK_STREAM создаёт полное транспортно-ориентированное подключение через сокет TCP для длительной связи. С другой стороны, SOCK_RAW просто даёт доступ к нижестоящему уровню IP, позволяя ping отправлять пакеты ICMP напрямую.

Таким образом, CAP_NET_RAW позволяет открывать сокет типа SOCK_RAW, но не требуется для сокетов SOCK_STREAM.

ping в различных дистрибутивах Linux

Утилита ping полезна для пользователей, администраторов и разработчиков. В действительности, нет никакого смысла давать к ней доступ только пользователю root. Некоторые дистрибутивы согласны с этим мнением и в них необходимые возможности назначены ping по умолчанию. В более старых выпусках зачастую в ядре имеется поддержка возможностей, но ping не настроен для их использования.

Выпуски, в которых утилите ping уже предоставлены возможности:
  • Red Hat 7.0, где утилите ping предоставлены возможности cap_net_admin,cap_net_raw+ep
  • Raspbian (Debian 8 Jessie) в выпуске мая 2016 года (но не в феврале 2016)
Выпуски, в которых возможности не установлены:
  • Red Hat 6.5
  • SLES 12 (getcap/setcap по умолчанию не установлены)
  • Ubuntu 14.04/Mint 17

Благодарности

При написании этой статьи была использована информация из Linux Audit.

воскресенье, 11 марта 2018 г.

Пересборка uwsgi с поддержкой Linux Capabilities

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

Мне в голову сразу пришли две идеи. Первая идея - сделать отдельное небольшое веб-приложение, которое будет работать от имени пользователя root, но будет уметь только пинговать и будет доступно только на локальном петлевом интерфейсе. Основное веб-приложение будет обращаться к этому небольшому веб-приложению только для выполнения ICMP-запросов, а все остальные функции будет выполнять самостоятельно. Вторая идея - воспользоваться POSIX Capabilities. POSIX Capabilities позволяет выполнять лишь определённые функции, доступные пользователю root, не работая при этом от имени пользователя root.

Так как в качестве сервера веб-приложений я использую uwsgi, то поддержку POSIX Capabilities нужно искать в нём. И такая поддержка имеется. Её описание можно увидеть на странице Setting POSIX Capabilities

Реализовать мне пришлось обе идеи, т.к. это веб-приложение должно работать в том числе и на FreeBSD, где POSIX Capabilities не поддерживается. В случае Linux положение немного осложняется тем, что в стандартной поставке uwsgi из репозитория Debian Wheezy поддержка POSIX Capabilities отсутствует. К счастью, исправить это сравнительно просто: нужно пересобрать пакеты, предварительно установив в систему пакет libcap-dev.

Установим инструменты для сборки и нужную нам библиотеку:
# apt-get install dpkg-dev devscripts fakeroot libcap-dev
Распакуем в текущий каталог исходные тексты uwsgi, из которых можно собрать как двоичные пакеты, так и пакеты с исходными текстами:
# apt-get source uwsgi
Установим все зависимости, необходимые для сборки uwsgi:
# apt-get build-dep uwsgi
Внесём в журнал изменений пакета описание последнего изменения, которое мы добавляем. Для этого запустим команду:
# dch -i
И приведём запись о последних изменениях к следующему виду:
uwsgi (1.2.3+dfsg-5+deb7u2) UNRELEASED; urgency=low

* Compiled with libcap-dev to support linux capabilities

-- Vladimir Stupin <vladimir@stupin.su>  Mon, 11 Sep 2017 09:53:11 +0500
Теперь осталось собрать пакеты:
# cd uwsgi-1.2.3+dfsg
# dpkg-buildpackage -us -uc -rfakeroot
И можно устанавливать готовые пакеты, которые были помещены в вышестоящем каталоге:
# cd ..
# dpkg -i uwsgi_1.2.3+dfsg-5+deb7u2_amd64.deb uwsgi-core_1.2.3+dfsg-5+deb7u2_amd64.deb uwsgi-plugin-python_1.2.3+dfsg-5+deb7u2_amd64.deb
Для использования функции, нужно добавить в файл конфигурации веб-приложения, например, в моём случае это файл /etc/uwsgi/apps-available/ncc.ini, одну строчку:
cap = net_raw
P.S. Понадобилось недавно повторить все эти действия. Был уверен, что описал всё в блоге, но, неожиданно, записей не нашёл. Зато нашёл черновик, где были записаны команды по сборке, пример текста для журнала изменений и ссылка на документацию uwsgi. Повторил сборку по черновику и заодно довёл заметку до вида, пригодного к публикации.