воскресенье, 22 октября 2017 г.

Контроль температуры с датчиков sysctl во FreeBSD через Zabbix

Для контроля температурного режима серверов под управлением операционной системы FreeBSD можно воспользоваться датчиками температуры, доступными по команде sysctl:
# sysctl -a | grep temperature
hw.acpi.thermal.tz0.temperature: 27.8C
hw.acpi.thermal.tz1.temperature: 29.8C
В выводе команды sysctl, приведённом выше, имеется два датчика температуры, находящихся в "тепловых зонах" с номерами 0 и 1. Кроме этого возможно ещё контролировать температуру процессорных ядер. Для контроля температуры процессорных ядер на процессорах Intel можно подгрузить модуль ядра операционной системы FreeBSD, который называется coretemp:
# kldload coretemp
После загрузки этого модуля добавятся датчики температуры, соответствующие ядрам процессора:
# sysctl -a | grep temperature
hw.acpi.thermal.tz0.temperature: 27.8C
hw.acpi.thermal.tz1.temperature: 29.8C
dev.cpu.0.temperature: 43.0C
dev.cpu.1.temperature: 43.0C
dev.cpu.2.temperature: 38.0C
dev.cpu.3.temperature: 38.0C
dev.cpu.4.temperature: 41.0C
dev.cpu.5.temperature: 41.0C
dev.cpu.6.temperature: 32.0C
dev.cpu.7.temperature: 32.0C
В данном случае у процессора всего четыре ядра, но каждое из них поддерживает так называемый гипертрединг (общепринятое слово "гипертрейдинг" ассоциируется у меня с торговлей в четрырёхмерном пространстве - hyper-trading) - возможность выполнять два независимых потока инструкций, используя общие вычислительные устройства ядра (грубо говоря, в ядре процессора есть два регистровых файла, два устройства управления, но одно арифметико-логическое устройство). Это хорошо видно по тому, что показания каждой из четырёх пар датчиков - одинаковые.

Чтобы модуль ядра загружался при загрузке операционной системы автоматически, нужно прописать соответствующую опцию в файл конфигурации загрузчика ядра /boot/loader.conf:
coretemp_load="YES"
Для процессоров AMD имеется соответствующий модуль под названием amdtemp. У меня, однако, таких процессоров нигде нет, поэтому описанное ниже будет относиться только к процессорам Intel.

Чтобы следить за показаниями датчиков температуры через систему мониторинга Zabbix, на наблюдаемом узле должен быть установлен и настроен Zabbix-агент. Добавим в файл конфигурации Zabbix-агента /usr/local/etc/zabbix24/zabbix_agentd.conf две строчки:
UserParameter=sysctl.temperatures.discovery,/sbin/sysctl -N dev.cpu hw.acpi.thermal 2>/dev/null | awk 'BEGIN { printf "{\"data\":["; first=1; } /\.temperature$/ { name=$0; gsub("dev.cpu.", "CPU", name); gsub(".temperature", "", name); gsub("hw.acpi.thermal.tz", "ZONE", name); if (first) first=0; else printf ","; printf "{\"{#SYSCTL}\":\"%s\",\"{#NAME}\":\"%s\"}", $0, name; } END { print "]}"; }'
UserParameter=sysctl.temperature[*],/sbin/sysctl -n $1 | sed 's/C$//'
Чтобы новые настройки вступили в силу, перезапустим Zabbix-агента при помощи следующей команды:
# /usr/local/etc/rc.d/zabbix_agentd restart
Для контроля показаний датчиков температуры команды sysctl я подготовил два шаблона:
В шаблоне имеется одно правило обнаружения датчиков:

В этом правиле обнаружения есть один прототип элемента данных:

Добавлять в шаблон триггеры я не стал, т.к. во-первых пороги для "тепловых зон" и для процессорных ядер наверняка будут отличаться друг от друга, во-вторых - пороги будут зависеть от температурного режима серверной и в-третьих, пороги будут зависеть от типовой нагрузки. Например, на абсолютно одинаковых серверах, расположенных в разных серверных, я наблюдал разброс температур процессорных ядер от 32 до 45 градусов Цельсия. Под нагрузкой процессорные ядра разогреваются до 66 градусов Цельсия. Поэтому, если вам нужны пороги по этим датчикам, то добавьте в шаблон триггеры самостоятельно.

Снимаемые данные выглядят следующим образом:

воскресенье, 15 октября 2017 г.

Совместное использование expert_recipe, mdraid, LVM, GPT и GRUB2 в Ubuntu Lucid и Debian Squeeze

Перевод: Get expert_recipe, mdraid, LVM, GPT and grub2 Playing Together on Ubuntu Lucid and Debian Squeeze
Автор: Эндрю Гамильтон (Andrew Hamilton)

Жёсткие диски растут и растут. Теперь можно взять жёсткие диски на 3 терабайта и получить по огромному хранилищу на каждом сервере. Но тогда можно заметить, что текущие файлы автоматизации установки не работают, завершаясь аварийно на попытке установить GRUB2. Если нажать "Alt-F4", чтобы проверить журнал ошибок, то можно увидеть ошибки о том, что GRUB2 невозможно встроить в диск GPT.

Когда размер диска достигает 2 терабайт, установщик Debian и менеджер разделов partman по умолчанию используют разбивку разделов по схеме GPT. К несчастью старые версии partman неправильно настраивают GPT, если диски являются частью программного RAID-массива. К счастью, исправить это не так сложно, нужно только добавить несколько директив (или, возможно, поменять их, если некоторые из них уже используются в вашем файле автоматизации установки).

Что нам нужно - это добавить раздел, который не создают подобающим образом старые версии менеджера разделов partman. Этот раздел имеет тип bios_grub и должен иметь размер 1 мегабайт. Этот раздел позволяет GRUB2 найти место для размещения всего загрузчика и позволяет BIOS найти загрузочную информацию GRUB для загрузки загрузчика. Более подробную информацию о загрузочном разделе BIOS можно найти в Wikipedia – BIOS Boot Partition (Загрузочный раздел BIOS).

Чтобы добавить раздел bios_grub в файл автоматизации установки при помощи менеджера разделов partman, мы добавим к нашему рецепту expert_recipe следующее:
1 1 1 free \
            $iflabel{ gpt } \
            method{ biosgrub } \
        . \
Эти настройки добавят раздел размером 1 мегабайт с высшим приоритетом. Если метка диска имеет значение "GPT", то раздел будет создан методом biosgrub.

Поскольку мы добавили к диску ещё один раздел, также нужно будет увеличить на единицу номера всех разделов, используемых в RAID-массивах. Например, если сначала в файле автоматизации установки использовались следующие настройки RAID:
d-i partman-auto-raid/recipe string \
    1 2 0 ext3 /boot /dev/sda1#/dev/sdb1 \
    . \
    1 2 0 lvm - /dev/sda2#/dev/sdb2 \
    .
То теперь нам нужно отредактировать эту запись и увеличить номера разделов на единицу:
d-i partman-auto-raid/recipe string \
    1 2 0 ext3 /boot /dev/sda2#/dev/sdb2 \
    . \
    1 2 0 lvm - /dev/sda3#/dev/sdb3 \
    .
Полностью настройки диска в новом файле автоматизации установки будут выглядеть следующим образом:
d-i partman-auto/disk string /dev/sda /dev/sdb
d-i partman-auto/method string raid
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-md/confirm_nochanges boolean true
d-i partman-lvm/confirm boolean true
d-i partman-auto/choose_recipe select boot-root
d-i partman-auto-lvm/new_vg_name string vg01
d-i partman-auto-lvm/guided_size string 100%
d-i partman-auto-raid/recipe string \
    1 2 0 ext3 /boot /dev/sda2#/dev/sdb2 \
    . \
    1 2 0 lvm - /dev/sda3#/dev/sdb3 \
    .
d-i partman-auto/expert_recipe string \
    boot-root :: \
        1 1 1 free \
            $iflabel{ gpt } \
            method{ biosgrub } \
        . \
        256 10 256 raid \
            $lvmignore{ } \
            $primary{ } \
            method{ raid } \
        . \
        1000 20 1000000 raid \
            $lvmignore{ } \
            $primary{ } \
            method{ raid } \
        . \
        150% 30 150% swap \
            $defaultignore{ } \
            $lvmok{ } \
            lv_name{ lv_swap } \
            method{ swap } \
            format{ } \
        . \
        20480 40 20480 ext4 \
            $defaultignore{ } \
            $lvmok{ } \
            lv_name{ lv_root } \
            method{ format } \
            format{ } \
            use_filesystem{ } \
            filesystem{ ext4 } \
            mountpoint{ / } \
        . \
            1 50 -1 ext4 \
            $defaultignore{ } \
            $lvmok{ } \
            lv_name{ lv_dummy } \
        .
d-i mdadm/boot_degraded boolean true
d-i partman-md/confirm boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select Finish partitioning and write changes to disk
d-i partman/confirm boolean true
d-i partman-md/confirm_nooverwrite boolean true
d-i partman/confirm_nooverwrite boolean true
Ищете подробности об использовании expert_recipe в файлах автоматизации установки? Посмотрите другую статью в моём блоге, где описано больше подробностей - Заметки по использованию using expert_recipe в файлах автоматизации установки Debian/Ubuntu.

воскресенье, 8 октября 2017 г.

Заметки по использованию using expert_recipe в файлах автоматизации установки Debian/Ubuntu

Перевод: Notes on using expert_recipe in Debian/Ubuntu Preseed Files
Автор: Эндрю Гамильтон (Andrew Hamilton)

При работе с IaaS всегда необходим лёгкий доступ к "голому железу". Так, в Eucalyptus используются файлы автоматизации настройки серверов Debian и Ubuntu для тестирования программного обеспечения, оказания поддержи потребителям и обучения новых пользователей. Временами бывает нужно выполнить сложную настройку серверов и это не всегда простая задача.

Поначалу файл автоматизации установки со сложным разбиением разделов partman-auto/expert_recipe кажется пугающим. Может возникнуть множество вопросов о некоторых загадочных настройках. Документация Debian на первый взгляд не выглядит особо полезной, однако по мере понимания устройства файла автоматизации, она становится гораздо понятнее. При добавлении RAID и LVM, d-i partman-auto/expert_recipe может создать более сложную последовательность подготовки диска, что является очень мощной функцией для автоматизации установки операционной системы.

Базовая схема разбиения диска /dev/sda при помощи директивы автоматизации установки partman-auto/expert_recipe показана ниже:
d-i partman-auto/disk string /dev/sda
d-i partman-auto/method string regular
d-i partman-auto/expert_recipe string root :: \
    19000 50 20000 ext3 \
        $primary{ } $bootable{ } method{ format } \
        format{ } use_filesystem{ } filesystem{ ext3 } \
        mountpoint{ / } \
    . \
    2048 90 2048 linux-swap \
        $primary{ } method{ swap } format{ } \
    . \
    100 100 10000000000 ext3 \
        $primary{ } method{ format } format{ } \
        use_filesystem{ } filesystem{ ext3 } \
        mountpoint{ /srv/extra } \
    .
d-i partman-auto/choose_recipe select root
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select Finish partitioning and write changes to disk
d-i partman/confirm boolean true
Основная часть, на которой я сосредоточусь - это строка partman-auto/expert_recipe. (Примечание: Она выглядит как несколько строк, но на самом деле является одной строкой с заэкранированными переводами строк.) В примере выше создаются три первичных раздела: /
- корневой раздел, swap - раздел подкачки и /srv/extra - дополнительный раздел. Директива partman-auto/expert_recipe разобрана ниже.
d-i partman-auto/expert_recipe string root ::
Первая часть этой строки сообщает установщику Debian, что для разбивки диска, указанного в строке d-i partman-auto/disk, в менеджере разделов partman будет использоваться функция "expert_recipe". Далее установщику Debian сообщается, что директива ожидает строковое значение. Наконец, строке рецепта назначается имя "root". Имя рецепта используется в директиве d-i partman-auto/choose_recipe select root, чтобы сообщить ей, какой из рецептов нужно использовать. Знаки :: сообщают установщику Debian, что далее следует рецепт разбивки разделов.

Теперь рассмотрим, как будет создаваться один из разделов.
19000 50 20000 ext3 \
        $primary{ } $bootable{ } method{ format } \
        format{ } use_filesystem{ } filesystem{ ext3 } \
        mountpoint{ / } \
    . \
Первая часть приведённого выше рецепта раздела состоит из трёх чисел. Числа указывают минимальный размер раздела в мегабайтах (19000), приоритет получения максимального размера (меньшие числа указыают на более высокий приоритет) (30) и максимальный размер создаваемого раздела. Оба значения размера задаются в мегабайтах (20000). Следующее слово указывает формат создаваемого раздела.

Следующие три строки сообщают менеджеру разделов partman, что этот раздел должен быть первичным, раздел должен быть помечен как загрузочный, раздел должен быть отформатирован, формат файловой системы должен быть ext3 и, наконец, что точкой монтирования этого раздела должен быть "/". Последняя строка с одной точкой сообщает менеджеру разделов partman, что это конец определения этого раздела. Если далее текст продолжается, то менеджер разделов partman понимает, что далее следуют определения других разделов, но если был найден перевод строки, то он понимает, что рецепт разбивки разделов завершился.

К несчастью, часть expert_recipe менеджера разделов partman может обрабатывать только рецепты для одного диска. Существует несколько обходных решений, основанных на том, что в команде preseed/late_command можно использовать sfdisk, который может выполнить дополнительные действия над другими дисками. Если expert_recipe используется для настройки LVM, тогда можно использовать несколько дисков, как это показано ниже.

Ниже приводится более сложный пример настройки массива RAID 1 на дисках /dev/sda и /dev/sdb с созданием LVM поверх массива RAID.
d-i partman-auto/disk string /dev/sda /dev/sdb
d-i partman-auto/method string raid
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-md/device_remove_md boolean true
d-i partman-lvm/confirm boolean true
d-i partman-auto/choose_recipe select boot-root
d-i partman-auto-lvm/new_vg_name string vg00
d-i partman-auto/expert_recipe string \
    boot-root :: \
        1024 30 1024 raid \
            $lvmignore{ } \
            $primary{ } method{ raid } \
        . \
        1000 35 100000000 raid \
            $lvmignore{ } \
            $primary{ } method{ raid } \
        . \
        19000 50 20000 ext4 \
            $defaultignore{ } \
            $lvmok{ } \
            lv_name{ root } \
            method{ format } \
            format{ } \
            use_filesystem{ } \
            filesystem{ ext4 } \
            mountpoint{ / } \
        . \
        2048 60 2048 swap \
            $defaultignore{ } \
            $lvmok{ } \
            lv_name{ swap } \
            method{ swap } \
            format{ } \
        .
d-i partman-auto-raid/recipe string \
    1 2 0 ext2 /boot \
        /dev/sda1#/dev/sdb1 \
    . \
    1 2 0 lvm - \
        /dev/sda2#/dev/sdb2 \
    .
d-i mdadm/boot_degraded boolean false
d-i partman-md/confirm boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select Finish partitioning and write changes to disk
d-i partman/confirm boolean true
d-i partman-md/confirm_nooverwrite boolean true
d-i partman/confirm_nooverwrite boolean true
В этих строчках сообщается о необходимости настроить RAID-массив:
d-i partman-auto/method string raid
d-i partman-md/confirm boolean true
В первую очередь менеджер разделов partman использует директиву partman-auto-raid/recipe. Строка рецепта в ней определяет, что RAID-массив должен быть настроен на дисках /dev/sda и /dev/sdb. Например, мы создаём массив RAID 1 для LVM на дисках /dev/sda и /dev/sdb, воспользовавшись следующими настройками:
1 2 0 lvm - \
        /dev/sda2#/dev/sdb2 \
    .
Первое число указывает уровень RAID (1), второе число указывает количество устройств, используемых в массиве RAID (2), а третье число указывает количество запасных дисков, доступных RAID-массиву (0). Далее задаётся тип раздела на RAID-массиве (lvm), "-" указывает точку монтирования массива. Поскольку на этом RAID-массиве создаётся LVM, то точки монтирования нет. Используемые массивом разделы на дисках перечисляются через знак "#". Аналогично примеру разбивки разделов, указанному выше, определение массива завершается точкой, а любой следующий далее текст будет рассматриваться как другой массив. Перевод строки сообщит менеджеру разделов partman, что рецепт закончился.

Строка partman-auto/expert_recipe используется для определения разделов, создаваемых на массиве RAID. Выше создаются на RAID-массиве создаются два раздела: раздел /boot и раздел LVM. Затем в рецепте определяются два логических тома - "/" и swap, которые будут созданы на LVM.

Далее следует определение раздела RAID:
1024 30 1024 raid \
            $lvmignore{ } \
            $primary{ } method{ raid } \
        . \
Выше описан RAID-массив размером 1 гигабайт с высочайшим приоритетом и типом раздела "raid". Поскольку этот раздел имеет высочайший приоритет, им будут созданы /dev/sda1 и /dev/sda2, которые будут использоваться операционной системой как "/boot", как это уже было описано при объяснении директивы partman-auto-raid/recipe. Флаг $lvmignore{ } используется для того, чтобы гарантировать, что менеджер разделов partman при создании логических томов LVM не воспримет этот раздел как описание логического тома. Далее разделы RAID определяются как первичные и указывается, что при создании этих разделов нужно использовать метод, создающий массивы RAID.

Чтобы установщик Debian обрабатывал определения разделов LVM, нужно указать следующее:
d-i partman-lvm/confirm boolean true
d-i partman-auto-lvm/new_vg_name string vg00
d-i partman-auto-lvm/guided_size string 30GB
Убедитесь, что значение “guide_size”, указанное выше, больше или равно размеру всех создаваемых логических томов. Чтобы создать логический том, определите его в рецепте:
19000 50 20000 ext4 \
            $defaultignore{ } \
            $lvmok{ } \
            lv_name{ root } \
            method{ format } \
            format{ } \
            use_filesystem{ } \
            filesystem{ ext4 } \
            mountpoint{ / } \
        . \
Выше приведено описание логического тома размером от 19 до 20 гигабайт с файловой системой ext4. Флаг $defaultignore{ } используется для того, чтобы менеджер разделов partman не обрабатывал это описание при создании физических разделов на дисках. Далее при помощи флага $lvmok{ } указывается, что менеджер разделов partman должен использовать это определение тома при создании логических томов, а флаг $lv_name{ root } сообщает, что созданный том должен иметь имя "root". Остальные флаги уже были описаны в примерах выше и сообщают менеджеру разделов partman, что логический том должен быть отформатирован и что точкой монтирования должен быть "/".

Выше приведён полный пример, который можно доработать для получения необходимых результатов и поместить в файл автоматизации установки. К счастью этот пример partman-auto/expert_recipe пригодится и при стандартной установке, и при установке с использованием RAID и LVM.

Обновление: Я добавил полные примеры файлов автоматизации установки на GitHub. Посмотрите их в моём репозитории Blog Scripts.

Ещё одно обновление: Я написал ещё одну заметку об использовании файла автоматизации установки в Ubuntu Lucid и Debian Squeeze, где используется разбивка разделов в формате GPT (для дисков размером 2 и более терабайт). Прочитать её можно здесь: Совместное использование expert_recipe, mdraid, LVM, GPT и GRUB2 в Ubuntu Lucid и Debian Squeeze.

воскресенье, 1 октября 2017 г.

Автоматизация установки Ubuntu/Debian с LVM

Перевод: Ubuntu/Debian preseedint with LVM
Автор: Джеймс Тран (James Tran)

Примечания переводчика:
Перед тем, как я написал заметку Установка Debian с флешки по SSH, я готовил флешку, воспользовавшись несколькими материалами из интернета. Я сохранил ссылки на использованные материалы, чтобы потом перевести их на русский язык. Эта статья оказалась не очень качественной - в ней практически отсутствуют объяснения, а есть только примеры preseed-файла. Следующие две статьи, ссылки на которые я сохранил и переводы которых выложу в блог, должны быть получше - там больше объяснений. Более того - на них ссылается автор этой статьи.
Когда увидите заставку Ubuntu или Debian, нажмите клавишу табуляции, а затем добавьте:
auto url=http://mywebserver/mypreseed.cfg
Вы можете воспользоваться этим примером для быстрого развёртывания сервера для размещения файла автоматизации установки: Python Simple HTTP Server

У вас по-прежнему будет запрашиваться информация для локализации, поскольку она запрашивается ДО загрузки файла автоматизации установки для Debian/Ubuntu (согласен, это глупо). Эти настройки не подтягиваются.
# Настройки клавиатуры и локализации
####################################################################

d-i debian-installer/locale string en_US
d-i console-keymaps-at/keymap select sg-latin1

# Сеть
####################################################################

d-i netcfg/disable_dhcp boolean false
d-i netcfg/get_hostname string localhost
d-i netcfg/get_domain string localdomain
d-i netcfg/choose_interface select eth0
Вы можете обойти это ограничение, пересобрав загрузочный компакт-диск или выполнив установку по PXE, при которой загружается вся информация, указанная выше.

Пример:
auto url=http://mywebserver/mypreseed.cfg \
locale=en_US console-keymaps-at/keymap=sg-latin1 \
interface=eth0 hostname=localhost domain=localdomain --

ТЕПЕРЬ СОЗДАДИМ НАСТОЯЩИЙ ФАЙЛ КОНФИГУРАЦИИ ДЛЯ АВТОМАТИЗАЦИИ УСТАНОВКИ

Настроим локализацию:
d-i debian-installer/locale string en_US
d-i console-setup/ask_detect boolean false
d-i time/zone string UTC
d-i debian-installer/splash boolean false
d-i debian-installer/language string en
d-i debain-installer/country string US
d-i console-keymaps-at/keymap select sg-latin1
Настроим сеть:
d-i netcfg/get_nameservers string 192.168.1.5
d-i netcfg/get_ipaddress string 192.168.1.10
d-i netcfg/get_netmask string 255.255.255.0
d-i netcfg/get_gateway string 192.168.1.1
d-i netcfg/confirm_static boolean true
d-i netcfg/get_hostname string tempnode
d-i netcfg/get_domain string localdomain
Настроим используемый репозиторий и каталоги репозитория, в которых будет производиться поиск устанавливаемых файлов:
d-i mirror/country string manual
d-i mirror/http/hostname string http.us.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string
Произведём разбивку диска и настроим на нём LVM:
d-i partman-auto/disk string /dev/sda
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/device_remove_lvm_span boolean true
d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-auto-lvm/new_vg_name string system
Настроим разделы диска и логические тома LVM.

Сделаем следующее:
  • /boot : - загрузочная файловая система ext3 размером 300 мегабайт,
  • / : - файловая система ext3 от 10 гигабайт и более вплоть до конца диска,
  • swap : использовать 200% размера оперативной памяти системы или 8 гигабайт.
ОБРАТИТЕ ВНИМАНИЕ НА ФОРМАТИРОВАНИЕ В ЭТОМ РАЗДЕЛЕ - ОНО ОЧЕНЬ ВАЖНО
#d-i partman-auto/init_automatically_partition \
# select Guided - use entire disk and set up LVM
d-i partman-auto/expert_recipe string \
    boot-root :: \
        40 300 300 ext3 \
            $primary{ } \
            $bootable{ } \
            method{ format } format{ } \
            use_filesystem{ } filesystem{ ext3 } \
            mountpoint{ /boot } \
        . \
        2000 10000 1000000000 ext3 \
            $lvmok{ } \
            method{ format } format{ } \
            use_filesystem{ } filesystem{ ext3 } \
            mountpoint{ / } \
        . \
        8000 8000 200% linux-swap \
            $lvmok{ } \
            method{ swap } format{ } \
.
Вот другой пример LVM:
d-i partman-auto/expert_recipe string \
    boot-root :: \
        40 300 300 ext4 \
            $primary{ } \
            $bootable{ } \
            method{ format } format{ } \
            use_filesystem{ } filesystem{ ext4 } \
            mountpoint{ /boot } \
        . \
        2000 10000 1000000000 ext4 \
            $lvmok{ } \
            method{ format } format{ } \
            use_filesystem{ } filesystem{ ext4 } \
            mountpoint{ / } \
        . \
        2000 1000 10000 ext4 \
            $lvmok{ } \
            method{ format } format{ } \
            use_filesystem{ } filesystem{ ext4 } \
            mountpoint{ /var } \
        . \
        2000 1000 60000 ext4 \
            $lvmok{ } \
            method{ format } format{ } \
            use_filesystem{ } filesystem{ ext4 } \
            mountpoint{ /var/lib/mysql } \
        . \
        2000 1000 30000 ext4 \
            $lvmok{ } \
            method{ format } format{ } \
            use_filesystem{ } filesystem{ ext4 } \
            mountpoint{ /www } \
        . \
        8000 8000 200% linux-swap \
            $lvmok{ } \
            method{ swap } format{ } \
.
Ответьте да на все запросы о разделах и LVM:
d-i partman-lvm/confirm boolean true
d-i partman/confirm_write_new_label boolean true
d-i partman/choose_partition select Finish partitioning and write changes to disk
d-i partman/confirm boolean true
Настроим часовой пояс:
d-i clock-setup/utc boolean true
d-i clock-setup/ntp boolean true
d-i clock-setup/ntp-server string ntp.ubuntu.com
d-i time/zone string US/Los_Angeles
Настроим пользователя root и первого пользователя:
d-i base-installer/kernel/image string linux-server
d-i passwd/root-login boolean true
d-i passwd/root-password-crypted password $1$VuPOoDRD$seX.C54E8TUdMkaAmKvjx0
d-i passwd/user-fullname string Ubuntu User
d-i passwd/username string ubuntu
d-i passwd/user-password-crypted password $1$NvFY8IuR$BGqOozSN91ljvQB.pVLDw.
d-i user-setup/encrypt-home boolean false
d-i user-setup/allow-password-weak boolean true
d-i passwd/user-default-groups string adm cdrom dialout lpadmin plugdev sambashare
Разное:
d-i apt-setup/services-select multiselect security
d-i debian-installer/allow_unauthenticated string true
d-i pkgsel/upgrade select safe-upgrade
d-i pkgsel/language-packs multiselect
d-i pkgsel/update-policy select none
d-i pkgsel/updatedb boolean true
popularity-contest popularity-contest/participate boolean false
tasksel tasksel/first multiselect standard, openssh-server
d-i grub-installer/skip boolean false
d-i lilo-installer/skip boolean false
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean false
d-i finish-install/keep-consoles boolean false
d-i finish-install/reboot_in_progress note
d-i cdrom-detect/eject boolean true
d-i debian-installer/exit/halt boolean false
d-i debian-installer/exit/poweroff boolean false
Выбор устанавливаемых пакетов:
d-i pkgsel/include string vim openssh-server
ВОТ КАК ЭТО ВЫГЛЯДИТ ОДНИМ ФАЙЛОМ:
d-i debian-installer/locale string en_US
d-i console-setup/ask_detect boolean false
d-i time/zone string UTC
d-i debian-installer/splash boolean false
d-i debian-installer/language string en
d-i debain-installer/country string US
d-i netcfg/get_nameservers string 192.168.1.5
d-i netcfg/get_ipaddress string 192.168.1.10
d-i netcfg/get_netmask string 255.255.255.0
d-i netcfg/get_gateway string 192.168.1.1
d-i netcfg/confirm_static boolean true
d-i netcfg/get_hostname string tempnode
d-i mirror/country string manual
d-i mirror/http/hostname string http.us.debian.org
d-i mirror/http/directory string /debian
d-i mirror/http/proxy string
d-i partman-auto/disk string /dev/sda
d-i partman-auto/method string lvm
d-i partman-lvm/device_remove_lvm boolean true
d-i partman-lvm/device_remove_lvm_span boolean true
d-i partman-auto/purge_lvm_from_device boolean true
d-i partman-auto-lvm/new_vg_name string system
#d-i partman-auto/init_automatically_partition \
# select Guided - use entire disk and set up LVM
d-i partman-auto/expert_recipe string \
    boot-root :: \
        40 300 300 ext3 \
            $primary{ } \
            $bootable{ } \
            method{ format } format{ } \
            use_filesystem{ } filesystem{ ext3 } \
            mountpoint{ /boot } \
        . \
        2000 10000 1000000000 ext3 \
            $lvmok{ } \
            method{ format } format{ } \
            use_filesystem{ } filesystem{ ext3 } \
            mountpoint{ / } \
        . \
        8000 8000 200% linux-swap \
            $lvmok{ } \
            method{ swap } format{ } \
        .
d-i partman-lvm/confirm boolean true
d-i partman/confirm_write_new_label boolean true
d-i partman/choose_partition select Finish partitioning and write changes to disk
d-i partman/confirm boolean true
d-i clock-setup/utc boolean true
d-i clock-setup/ntp boolean true
d-i clock-setup/ntp-server string ntp.ubuntu.com
d-i time/zone string US/Los_Angeles
d-i base-installer/kernel/image string linux-server
d-i base-installer/kernel/image string linux-server
d-i passwd/root-login boolean true
d-i passwd/root-password-crypted password $1$VuPOoDRD$seX.C54E8TUdMkaAmKvjx0
d-i passwd/user-fullname string Ubuntu User
d-i user-setup/allow-password-weak boolean true
d-i user-setup/encrypt-home boolean false
d-i passwd/user-default-groups string adm cdrom dialout lpadmin plugdev sambashare
d-i apt-setup/services-select multiselect security
d-i debian-installer/allow_unauthenticated string true
d-i pkgsel/upgrade select safe-upgrade
d-i pkgsel/language-packs multiselect
d-i pkgsel/update-policy select none
d-i pkgsel/updatedb boolean true
popularity-contest popularity-contest/participate boolean false
tasksel tasksel/first multiselect standard, openssh-server
d-i grub-installer/skip boolean false
d-i lilo-installer/skip boolean false
d-i grub-installer/only_debian boolean true
d-i grub-installer/with_other_os boolean false
d-i finish-install/keep-consoles boolean false
d-i finish-install/reboot_in_progress note
d-i cdrom-detect/eject boolean true
d-i debian-installer/exit/halt boolean false
d-i debian-installer/exit/poweroff boolean false
d-i pkgsel/include string vim openssh-server
Информация для этой статьи была взята отсюда (спасибо):
http://cptyesterday.wordpress.com/2012/06/17/notes-on-using-expert_recipe-in-debianubuntu-preseed-files/
Пример файла автоматизации установки можно найти здесь:
https://github.com/cookingclouds/Preseed

воскресенье, 24 сентября 2017 г.

Решение проблемы с Open vSwitch после обновления Debian до Stretch

В одной из своих прошлых заметок Установка и настройка Open vSwitch в Debian я писал о настройке Open vSwitch. Тогда я воспользовался информацией из статьи Boot integration of the Openvswitch in Ubuntu.

Через некоторое время после выхода Deban Stretch, я решил обновить систему до него. После обновления столкнулся с проблемой: при загрузке системы происходит задержка при настройке сети и запуске демона Open vSwitch, после чего загрузка продолжается, но в загрузившейся системе оказываются настроенными только интерфейсы, не связанные с Open vSwitch.

Исправить проблему помогла всё та же статья Boot integration of the Openvswitch in Ubuntu, где была приведён юнит-файл systemd со следующим содержимым:
[Unit]
Description=Open vSwitch Internal Unit
PartOf=openvswitch-switch.service

DefaultDependencies=no

After=apparmor.service local-fs.target systemd-tmpfiles-setup.service

Wants=network-pre.target openvswitch-switch.service
Before=network-pre.target openvswitch-switch.service

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=-/etc/default/openvswitch-switch
ExecStart=/usr/share/openvswitch/scripts/ovs-ctl start \
          --system-id=random $OVS_CTL_OPTS
ExecStop=/usr/share/openvswitch/scripts/ovs-ctl stop
Этот текст нужно поместить в файл /lib/systemd/system/openvswitch-nonetwork.service

Затем нужно добавить в файл /etc/default/openvswitch-switch вот такую опцию:
OVS_CTL_OPTS='--delete-bridges'
Однако этого оказалось не достаточно.

Затем нужно создать ещё один юнит-файл вот с таким содержимым:
[Unit]
Description=Open vSwitch
After=network.target openvswitch-nonetwork.service
Requires=openvswitch-nonetwork.service

[Service]
Type=oneshot
ExecStart=/bin/true
ExecStop=/bin/true
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
Этот текст нужно поместить в файл /lib/systemd/system/openvswitch-switch.service

Теперь нужно чтобы systemd перечитал обновления в своей конфигурации. Сделаем это при помощи следующей команды:
# systemctl daemon-reload
Теперь можно включить созданные нами сервис-файлы:
# systemctl enable /lib/systemd/system/openvswitch-nonetwork.service
# systemctl enable openvswitch-switch.service
Теперь можно перезагрузить систему и проверить, правильно ли настроилась сеть после перезагрузки.

Меня всё меньше радуют тенденции в новых релизах Debian и в Linux в целом. Я бы не возмущался, если бы лоббисты systemd, протащившие его в систему, заменили бы всё так, чтобы ничего не сломалось. А то получается, что старое сломали, а новое не работает как положено. В самих юнит-файлах по-прежнему используются shell-скрипты для запуска и остановки сервиса - достаточно посмотреть на значения опций ExecStart и ExecStop. Раньше было достаточно уметь писать shell-скрипты для того, чтобы запустить сервис, правильно подготовив для него окружение, и остановить сервис, убрав за ним мусор. Сейчас же получается, что shell-скрипты по-прежнему нужно знать, но ещё нужно знать и опции юнит-файлов systemd. Подумываю о FreeBSD, где знания об ipfw, rc.conf и системе портов в той или иной мере актуальны до сих пор, хотя система и развивается. Настораживает только то, что в последнее время даже самые ярые сторонники FreeBSD стали всё чаще использовать Ubuntu.

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

воскресенье, 17 сентября 2017 г.

SSL-сертификат для ejabberd

Перевод: Ejabberd SSL Certificate
Автор: Реми ван Элст (Remy van Elst)

Примечания переводчика:
Как и в случае со статьёй "Заметки о Dockerfile", сейчас не помню - с чего вдруг я решил перевести эту статью.
Сейчас смотрю и недоумеваю от количества воды в ней. Ну да ладно, "пусть будет". Возможно я решил её перевести для комплекта с предыдущим переводом про настройку ejabberd.

Содержание

  • Введение
  • Создание запроса на подпись сертификата
  • Создание сертификата для ejabberd
  • Установка сертификата в ejabberd
В этом руководстве показано, как настроить SSL-сертификат для использования с ejabberd. Руководство охватывает вопросы создания запроса на подпись сертификата - Certificate Signing Request, подготовку сертификата для использования в ejabberd и установку сертификата.

В этом руководстве подразумевается использование уже настроенного ejabberd. Руководство протестировано в Debian и Ubuntu, но должно подойти для любого сервера ejabberd.

Введение

Для получения SSL-сертификата для сервера ejabberd нужно несколько вещей:
  • Создать запрос на подпись сертификата - Certificate Signing Request (CSR) и приватный ключ,
  • Передать запрос на подпись сертификата в удостоверяющий центр, дать ему подписать его и забрать оттуда готовый сертификат.
  • Объединить сертификат, приватный ключ (и цепочку сертификатов) в PEM-файл, совместимый с ejabberd,
  • Установить сертификат в ejabberd.
При помощи сертификата можно защитить XMPP-подключения и содержимое переговоров. Таким образом другим становится значительно сложнее прослушивать переговоры. В сочетании с включенным протоколом OTR это позволит создать сверхзащищённый канал для переговоров.

Создание запроса на подпись сертификата

Создадим каталог для хранения всех необходимых файлов и перейдём в него:
mkdir -p ~/Certificates/xmpp
cd ~/Certificates/xmpp
Теперь воспользуемся OpenSSL для создания приватного ключа и запроса на подпись сертификата - CSR. При помощи первой команды это можно сделать интерактивно, а при помощи второй - не интерактивно. Убедитесь, что задали правильное значение в поле Общее имя - Common Name (CN). В нём должен быть указан URL XMPP-сервера:

Интерактивная команда:
openssl req -nodes -newkey rsa:2048 -keyout private.key -out CSR.csr
Не интерактивная команда:
openssl req -nodes -newkey rsa:2048 -keyout private.key -out CSR.csr -subj "/C=NL/ST=State/L=City/O=Company Name/OU=Department/CN=chat.example.org"
В результате работы команды появятся два файла: CSR.csr и private.key. Теперь нужно передать запрос на подпись сертификата - CSR в удостоверяющий центр. Это может быть любой удостоверяющий центр. У меня есть успешный опыт использования Xolphin, но это могут быть другие удостоверяющие центры, например, Digicert и Verisign.

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

Создание сертификата для ejabberd

Как только у вас появятся все необходимые файлы (приватный ключ, сертификат, цепочка сертификатов), поместите их в каталог и продолжайте. Нужно объединить эти файлы в один файл ejabberd.pem.

Они должны располагаться в следующем порядке:
  • Приватный ключ,
  • Сертификат,
  • Цепочка сертификатов.
Замените имена файлов в следующей команде на ваши и создайте PEM-файл:
cat private.key >> ejabberd.pem
cat certificate.pem >> ejabberd.pem
cat chain-1.pem >> ejabberd.pem
cat chain-2.pem >> ejabberd.pem
Если всё сделано, то продолжим.

Установка сертификата в ejabberd

Скопируйте сертификат на все ваши серверы ejabberd:
scp ejabberd.pem user@srv1.example.org:
Поместите сертификат в каталог /etc/ejabberd:
cp ejabberd.pem /etc/ejabberd/ejabberd.pem
Теперь отредактируем файл конфигурации ejabberd так, чтобы он указывал на новый сертификат:
vim /etc/ejabberd/ejabberd.cfg
Проверьте, что файл конфигурации указывает на сертификат. При необходимости исправьте:
[...]
{listen, [
  {5222, ejabberdc2s, [ {access, c2s}, {shaper, c2sshaper}, {maxstanzasize, 65536},
         starttls, {certfile, "/etc/ejabberd/ejabberd.pem"}]},
[...]
{s2susestarttls, true}.
{s2s_certfile, "/etc/ejabberd/ejabberd.pem"}.
[...]
После этого перезапустите ejabberd:
/etc/init.d/ejabberd restart
Теперь можно воспользоваться любым XMPP-клиентом, чтобы подключиться к SSL/TLS и убедиться, что он работает.

воскресенье, 10 сентября 2017 г.

Настройка ejabberd для обмена мгновенными сообщениями по протоколу XMPP - своя альтернатива Google Talk Hangouts

Перевод: Set up a federated XMPP Chat Network with ejabberd, your own Google Talk Hangouts alternative
Автор: Реми ван Эст (Remy van Elst)

Примечания переводчика:
В оригинальной статье часто использовалось слово "федерализация" для того, чтобы подчеркнуть, что протокол XMPP не предполагает наличие единых серверов для всей сети, как это происходит в случае ICQ, WhatsApp, Viber или Telegram. XMPP предусматривает возможность создания множества сетей, у каждой из которых есть свои собственные серверы. Серверы каждой из сетей могут взаимодействовать с серверами других сетей на равноправных началах. То есть по аналогии с унитарными и федеральными государствами, ICQ можно назвать унитарной сетью, а XMPP можно назвать федеральной сетью. В переводе эти слова убраны, т.к. они не общеприняты и только запутывают. В качестве компенсации я добавил это примечание.

Содержание

  • Зачем настраивать собственный сервер XMPP
  • Информация
  • Установка одиночного/ведущего узла ejabberd
    • Установка ejabberd
    • Настройка ejabberd
  • Кластеризация ejabberd
    • Подготовка ведущего узла
    • Подготовка ведомых узлов
    • Ошибки при кластеризации
  • Записи DNS SRV
  • Заключительное тестирование
В этом руководстве показано, как установить сервер ejabberd для обмена мгновенными сообщениями. В нём рассказывается о базовом одноузловом сервере ejabberd, а также о настройке кластера ejabberd. Руководство включает в себя примеры ошибок и записей DNS SRV. Для установки собственного сервера XMPP можно воспользоваться услугами хостинга Inception Hosting VPS. Я пользуюсь их услугами и на мой взгляд этот хостинг очень стабильный, обладает высокой производительностью и низкими ценами.

Зачем настраивать собственный сервер XMPP

Существует несколько причин для настройки собственного сервера XMPP.

Может быть вы пользовались сервисом Google Talk или, как он теперь называется, Hangouts. Не так давно сервис Google прекратил поддерживать совместимость с XMPP. Если у вас есть контакты не на gmail, можно продолжать общаться с ними. Можно по-прежнему использовать открытый протокол, поддержка которого широко распространена и не станет частью закрытого программного и аппаратного обеспечения Google.

Возможно также, что вы хотите получить больший контроль за историей переписки. Выключите историю переписки ejabberd и воспользуйтесь протоколом OTR, который позволит обеспечить вам полную тайну переписки (и Perfect Forward Secrecy - совершенно прямую секретность).

А может быть вы хотите пользоваться многопротокольными приложениями для обмена мгновенными сообщениями, такими как Pidgin, Psi+, Empathy, Adium, iChat/Messages или Miranda IM. На Android можно использовать Xabber, Beem или OneTeam. Знаете ли вы, что большие компании, такие как Facebook, WhatsApp и Google, используют (или использовали ранее) XMPP в качестве основного протокола для обмена мгновенными сообщениями?

Или можете быть вы - системный администратор, которому нужна локальная система для обмена мгновенными сообщениями. У одного из моих клиентов есть кластер ejabberd, состоящий из 4 виртуальных машин с Debian 7 (по 2 гигабайта оперативной памяти на каждой). Кластер располагается на трёх площадках и в одном дата-центре, и обслуживает 12000 пользователей, из которых обычно одновременно подключено 6000.

XMPP - это прекрасный расширяемый протокол, дополнительную информацию о котором можно найти здесь: https://en.wikipedia.org/wiki/XMPP

Информация

Эта статья проверена на Debian 7, Ubuntu 12.04 и 10.04, на OS X 10.8 Server. Все использовавшиеся серверы ejabberd были установлены через пакетный менеджер - либо через apt, либо через порты. Описанная конфигурация не проверялась, но также должна работать в Windows Server 2012 с ejabberd, собранном из исходных текстов на языке Erlang.

В статье используется домен example.org и сервер chat.example.org в качестве доменного имени XMPP-сервера. В разделе про кластеризацию используются серверы srv1.example.org и srv2.example.org. При настройке замените эти значения на ваши собственные.

Установка одиночного/ведущего узла ejabberd

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

Установка ejabberd

Это просто - для установки ejabberd воспользуйтесь пакетным менеджером:
apt-get install ejabberd
Также нужно установить несколько зависимостей среды поддержки Erlang.

Настройка ejabberd

Приступим к настройке сервиса ejabberd. Для начала остановим его:
/etc/init.d/ejabberd stop
Теперь запустите текстовый редактор для редактирования файлов конфигурации. Конфигурация ejabberd - это конфигурация на языке Erlang, поэтому комментарии начинаются не с #, а с %%. Также каждая опция в файле конфигурации завершается точкой (.).
vim /etc/ejabberd/ejabberd.cfg
Сначала добавим домен для обмена мгновенными сообщениями:
{hosts, ["example.org"]}.
Если нужно больше доменов, можно добавить и их следующим образом:
{hosts, ["sparklingclouds.nl", "raymii.org", "sparklingnetwork.nl"]}.
Эти доменные имена не являются именами серверов.

Далее объявим пользователя-администратора:
{acl, admin, {user, "remy", "example.org"}}.
remy соответствует части до символа @ в идентификаторе XMPP, а example.org соответствует части после этого символа. Если вам нужно больше пользователей-администраторов - добавьте дополнительные строки ACL.

Теперь если вы хотите разрешить регистрироваться через XMPP-клиента, включите встроенную функцию регистрации:
{access, register, [{allow, all}]}.
Если используется аутентификацию по данным из MySQL или LDAP, тогда возможность регистрации нужно отключить.

Мне нравится пользоваться общими списками контактов с группами списков контактов. Некоторые из моих клиентов используют общий список контактов для всех, так что никто не может добавить контакты, но могут видеть всех подключенных пользователей. Для этого нужно включить modsharedroster:
%% Сделайте это в блоке modules
{mod_shared_roster,[]},
Если файл конфигурации вас устраивает, сохраните его и перезапустите ejabberd:
/etc/init.d/ejabberd restart
Теперь для проверки нашей конфигурации нужно зарегистрировать пользователя. Если функция встроенной регистрации была включена, можно воспользоваться XMPP-клиентом. Если же функция встроенной регистрации была выключена - воспользуйтесь командой ejabberdctl:
ejabberdctl register remy example.org 'passw0rd'
Теперь проверим учётную запись, воспользовавшись клиентом XMPP, таким как Pidgin, Psi+ или Empathy. Если вам удалось подключиться, можно продолжать настройку. Если же не удалось - проверьте журналы ejabberd, настройки пакетного фильтра и тому подобное, чтобы устранить проблему.

Кластеризация ejabberd

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

Важно: используемые вами модули должны быть одинаковыми на каждом из узлов кластера. Если вы используете аутентификацию LDAP/MySQL или shared_roster, или особые настройки MUC, или отправку сообщений не подключенным в данный момент пользователям, то при кластеризации эти настройки не будут действовать, пока не выставить их на всех узлах.

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

Подготовка ведущего узла

Остановим сервер на ведущем узле и отредактируем файл /etc/default/ejabberd:
vim /etc/default/ejabberd
Раскомментируем опцию с именем узла и заменим её значение на полное доменное имя узла:
ERLANG_NODE=ejabberd@srv1.example.org
Затем добавим внешний (публичный) IP-адрес, указав его как кортеж - с запятыми вместо точек:
INET_DIST_INTERFACE={20,30,10,5}
Если ejabberd будет использоваться только в локальной сети, тогда укажите первичный адрес сетевой карты.

Мы собираемся удалить все таблицы mnesia. Они будут пересозданы при перезапуске ejabberd. Это проще, чем менять сами данные mnesia. Не делайте этого на уже настроенном узле, не сняв резервную копию с cookie-файла Erlang.

Для начала создадим резервную копию cookie-файла Erlang:
cp /var/lib/ejabberd/.erlang.cookie ~/
Затем удалим базу данных mnesia:
rm /var/lib/ejabberd/*
Теперь восстановим cookie-файл Erlang:
cp ~/.erlang.cookie /var/lib/ejabberd/.erlang.cookie
Чтобы удостовериться, что все процессы erlang были остановлены, завершите все процессы пользователя ejabberd принудительно. Делать это не обязательно, но диспетчер процессов epmd всё ещё может продолжать работать:
killall -u ejabberd
И теперь снова запустим ejabberd:
/etc/init.d/ejabberd start
Если после этого удалось подключиться и обмениваться сообщениями, тогда перейдите к следующей части - к настройке ведомых узлов.

Подготовка ведомых узлов

Сначала ведомые узлы нужно настроить так, как описано в первой части этой статьи. Для этого можно скопировать файлы конфигурации с ведущего узла.

Остановим сервер ejabberd:
/etc/init.d/ejabberd stop
Остановим сервер ejabberd на ведомом узле и отредактируем файл /etc/default/ejabberd:
vim /etc/default/ejabberd
Раскомментируем опцию с именем узла и заменим её значение на полное доменное имя узла:
ERLANG_NODE=ejabberd@srv2.example.org
Затем добавим внешний (публичный) IP-адрес, указав его как кортеж - с запятыми вместо точек:
INET_DIST_INTERFACE={30,40,20,6}
Если ejabberd будет использоваться только в локальной сети, тогда укажите первичный адрес сетевой карты.

Теперь удалим все таблицы mnesia:
rm /var/lib/ejabberd/*
Скопируем cookie-файл с ведущего узла ejabberd при помощи cat и vim или через scp:
# На ведущем узле
cat /var/lib/ejabberd/.erlang.cookie
HFHHGYYEHF362GG1GF

# На ведомом узле
echo "HFHHGYYEHF362GG1GF" > /var/lib/ejabberd/.erlang.cookie
chown ejabberd:ejabberd /var/lib/ejabberd/.erlang.cookie
Теперь приступим к компиляции модуля easy_cluster на Erlang. Это очень маленький модуль, который добавляет к оболочке Erlang команду для более простого добавления кластера. Вместо этих команд в оболочке Erlang можно выполнить сами Erlang-функции в отладочной оболочке, но я считаю, что модуль удобнее и его использование уменьшает вероятность ошибок:
vim /usr/lib/ejabberd/ebin/easy_cluster.erl
Добавьте следующее содержимое:
-module(easy_cluster).

-export([test_node/1,join/1]).

test_node(MasterNode) ->
    case net_adm:ping(MasterNode) of 'pong' ->
        io:format("server is reachable.~n"); %% Сервер доступен
    _ ->
        io:format("server could NOT be reached.~n") %% Сервер не доступен
    end.

join(MasterNode) ->
    application:stop(ejabberd),
    mnesia:stop(),
    mnesia:delete_schema([node()]),
    mnesia:start(),
    mnesia:change_config(extra_db_nodes, [MasterNode]),
    mnesia:change_table_copy_type(schema, node(), disc_copies),
    application:start(ejabberd).
Сохраните его и скомпилируйте в работающий Erlang-модуль:
cd /usr/lib/ejabberd/ebin/
erlc easy_cluster.erl
Теперь проверим, что компиляция была успешной:
ls | grep easy_cluster.beam
Если вы увидели файл, значит компиляция завершилась успешно. Дополнительную информацию по модулю можно найти здесь: https://github.com/chadillac/ejabberd-easy_cluster/

Теперь приступим к присоединению узла кластера к ведущему узлу. Убедитесь что ведущий узел запущен и работает. Также удостоверьтесь, что cookie-файлы Erlang синхронизированы.

На ведомом узле запустите интерактивную оболочку ejabberd:
/etc/init.d/ejabberd live
Эта команда запустит оболочку Erlang, после чего оболочка начнёт выводить информацию. Когда она прекратит вывод, можно нажать Enter и получить приглашение. Введите следующую команду, чтобы проверить, что ведущий узел достижим:
easy_cluster:test_node('ejabberd@srv1.example.org').
Вы должны получить сообщение "server is reachable" - "Сервер доступен". Если это так, то продолжим.

Введём следующую команду, чтобы действительно присоединить узел:
easy_cluster:join('ejabberd@srv1.example.org').
Вот пример вывода при успешной проверке и подсоединении узла:
/etc/init.d/ejabberd live
*******************************************************
* To quit, press Ctrl-g then enter q and press Return *
*******************************************************

Erlang R15B01 (erts-5.9.1) [source] [async-threads:0] [kernel-poll:false]

Eshell V5.9.1 (abort with ^G)

=INFO REPORT==== 10-Jun-2013::20:38:15 ===
I(<0.39.0>:cyrsasl_digest:44) : FQDN used to check DIGEST-MD5 SASL authentication: "srv2.example.org"

=INFO REPORT==== 10-Jun-2013::20:38:15 ===
I(<0.576.0>:ejabberd_listener:166) : Reusing listening port for 5222

=INFO REPORT==== 10-Jun-2013::20:38:15 ===
I(<0.577.0>:ejabberd_listener:166) : Reusing listening port for 5269

=INFO REPORT==== 10-Jun-2013::20:38:15 ===
I(<0.578.0>:ejabberd_listener:166) : Reusing listening port for 5280

=INFO REPORT==== 10-Jun-2013::20:38:15 ===
I(<0.39.0>:ejabberd_app:72) : ejabberd 2.1.10 is started in the node 'ejabberd@srv2.example.org'
easy_cluster:test_node('ejabberd@srv1.example.org').
server is reachable.
ok
(ejabberd@srv2.example.org)2> easy_cluster:join('ejabberd@srv1.example.org').

=INFO REPORT==== 10-Jun-2013::20:38:51 ===
I(<0.39.0>:ejabberd_app:89) : ejabberd 2.1.10 is stopped in the node 'ejabberd@srv2.example.org'

=INFO REPORT==== 10-Jun-2013::20:38:51 ===
    application: ejabberd
    exited: stopped
    type: temporary

=INFO REPORT==== 10-Jun-2013::20:38:51 ===
    application: mnesia
    exited: stopped
    type: permanent

=INFO REPORT==== 10-Jun-2013::20:38:52 ===
I(<0.628.0>:cyrsasl_digest:44) : FQDN used to check DIGEST-MD5 SASL authentication: "srv2.example.org"

=INFO REPORT==== 10-Jun-2013::20:38:53 ===
I(<0.1026.0>:ejabberd_listener:166) : Reusing listening port for 5222

=INFO REPORT==== 10-Jun-2013::20:38:53 ===
I(<0.1027.0>:ejabberd_listener:166) : Reusing listening port for 5269

=INFO REPORT==== 10-Jun-2013::20:38:53 ===
I(<0.1028.0>:ejabberd_listener:166) : Reusing listening port for 5280
ok
(ejabberd@srv2.example.org)3>

=INFO REPORT==== 10-Jun-2013::20:38:53 ===
I(<0.628.0>:ejabberd_app:72) : ejabberd 2.1.10 is started in the node 'ejabberd@srv2.example.org'
Покиньте оболочку Erlang дважды нажав Ctrl+C. Теперь остановите ejabberd и запустите его снова:
/etc/init.d/ejabberd restart
Теперь в административном веб-интерфейсе можно проверить, что узел успешно присоединился к кластеру: http://srv1.example.org:5280/admin/nodes/
Узлы ejabberd
Если будут отображены другие узлы, значит всё готово. Если нет, тогда убедитесь, что выполнили каждый шаг и обратитесь к разделу ниже с описанием решений проблем.

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

Ошибки при кластеризации

В процессе настройки кластера могут произойти ошибки. Ниже перечислены примечания по встречавшимся мне ошибкам.
  • Перезапуск ejabberd не приводит к перезапуску epmd (демона Erlang)
    • избыточное решение: killall -u ejabberd
  • ejabberd возвращает ошибки с именем узла
    • убедитесь в правильности настройки имени узла (имя узла - srv1.example.com).
  • ejabberd возвращает ошибки несогласованности базы данных
    • создайте резервную копию cookie-файла Erlang (/var/lib/ejabberd/.erlang.cookie), а затем удалите содержимое каталога /var/lib/ejabberd, чтобы mnesia перестроила таблицы.
  • ejabberd сообщает "Попытка подключения от запрещённого узла" - "Connection attempt from disallowed node"
    • убедитесь в корректности cookie-файла Erlang (/var/lib/ejabberd/.erlang.cookie). Перед вставкой содержимого в редакторе vim перейдите в режим вставки...

Записи DNS SRV

Записи DNS SRV используются XMPP-клиентами и другими XMPP-серверами для поиска правильного адреса сервера. Например, Алиса настраивает своего XMPP-клиента на адрес alice@example.org. Её клиент ищет запись SRV и узнаёт, что сервер для обмена мгновенными сообщениями находится по адресу chat.example.org. Боб настраивает своего клиента на адрес bob@bobsbussiness.com и добавляет Алису в список контактов. XMPP-сервер домена bobsbussiness.com ищет запись SRV и узнаёт, что он должен установить подключение типа сервер-к-серверу по адресу chat.example.org, чтобы дать Бобу возможность переписываться с Алисой.

Конфигурация BIND 9 будет выглядеть следующим образом:
; XMPP
_xmpp-client._tcp IN SRV 5 0 5222 chat.example.org.
_xmpp-server._tcp IN SRV 5 0 5269 chat.example.org.
_jabber._tcp IN SRV 5 0 5269 chat.example.org.
Основные записи SRV указывают порты для подключения клиентов и для подключений типа сервер-к-серверу, а третья запись - это устаревший формат записей Jabber. Если используется хостинг DNS, введите эти записи в панели администрирования или посоветуйтесь с технической поддержкой хостинга.

Для проверки правильности SRV-записей можно воспользоваться командой dig:
dig _xmpp-client._tcp.example.org SRV
dig _xmpp-server._tcp.example.org SRV
Или если на вашем компьютере установлена операционная система Windows, тогда воспользуйтесь nslookup:
nslookup -querytype=SRV _xmpp-client._tcp.example.org
nslookup -querytype=SRV _xmpp-server._tcp.example.org
Если результат будет похожим на приведённый ниже, значит всё настроено верно:
;; QUESTION SECTION:
;_xmpp-client._tcp.raymii.org. IN SRV
;; ANSWER SECTION:
_xmpp-client._tcp.raymii.org. 3600 IN SRV 5 0 5222 chat.raymii.org.
На самом же деле в моём случае у chat.raymii.org имеется несколько A-записей:
;; ADDITIONAL SECTION:
chat.raymii.org. 3600 IN A 84.200.77.167
chat.raymii.org. 3600 IN A 205.185.117.74
chat.raymii.org. 3600 IN A 205.185.124.11
Но если был настроен только один узел, то это будет либо запись CNAME, либо одна запись A/AAAA.

Заключительное тестирование

Чтобы протестировать, что всё работает, можно добавить в список контактов XMPP-бота Duck Duck Go. Если вам без проблем удалось добавить его и поговорить с ним, то значит всё было сделано верно. Адрес бота - im@ddg.gg.

воскресенье, 3 сентября 2017 г.

Командная строка OpenSSL: Корневой и промежуточный удостоверяющий центры, включая OCSP, CRL и отзыв сертификатов

Перевод: OpenSSL command line Root and Intermediate CA including OCSP, CRL and revocation
Автор: Реми ван Элст (Remy van Elst)

Содержание:

  • Корневой удостоверяющий центр
  • Создание промежуточного удостоверяющего центра 1
  • Настройка промежуточного удостоверяющего центра 1
  • Создание конечных пользовательских сертификатов
  • Проверка сертификата
Это короткие и неаккуратные заметки по созданию удостоверяющего центра, промежуточных удостоверяющих центров и конечных сертификатов при помощи OpenSSL. Сертификаты содержат информацию об OCSP - протоколе интерактивного статуса сертификата, CRL - списке отозванных сертификатов, информацию об удостоверяющем центре-эмитенте, назначении сертификата и сроке его годности.

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

Корневой удостоверяющий центр

Создадим и переместим в каталог корневой удостоверяющий центр:
mkdir ~/SSLCA/root/
cd ~/SSLCA/root/
Создадим ключ SHA-256 RSA длиной 8192 бит для нашего корневого удостоверяющего центра:
openssl genrsa -aes256 -out rootca.key 8192
Пример вывода:
Generating RSA private key, 8192 bit long modulus # Создание приватного ключа, с модулем длиной 8192 бит
.........++
....................................................................................................................++
e is 65537 (0x10001) # e равно 65537 (0x10001)
Если хотите защитить этот ключ паролем, добавьте опцию -passout pass:пароль или -passout file:файл_с_паролем.

Создадим самозаверенный сертификат удостоверяющего центра ca.crt. Нужно предоставить идентификационные данные вашего корневого удостоверяющего центра:
openssl req -sha256 -new -x509 -days 1826 -key rootca.key -out rootca.crt
Пример вывода:
You are about to be asked to enter information that will be incorporated     # У вас будет запрошена информация, которая будет вставлена
into your certificate request.                                               # в ваш запрос сертификата.
What you are about to enter is what is called a Distinguished Name or a DN.  # То, что вы введёте, называется Distinquised Name - Отличительное Имя или DN.
There are quite a few fields but you can leave some blank                    # Далее следует несколько полей, но некоторые из них можно не заполнять
For some fields there will be a default value,                               # У некоторых полей есть значение по умолчанию,
If you enter '.', the field will be left blank.                              # Если ввести '.', то поле останется пустым.
-----
Country Name (2 letter code) [AU]:NL                                         # Название страны (двухбуквенный код) [AU]:NL
State or Province Name (full name) [Some-State]:Zuid Holland                 # Название штата или провинции (полное название) [Некий-штат]:Южная Голландия
Locality Name (eg, city) []:Rotterdam                                        # Название местности (например, город) []:Роттердам
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Sparkling Network # Название организации (например, компания) [ООО Интернет-виджеты]:Искрящая сеть
Organizational Unit Name (eg, section) []:Sparkling CA                       # Название подразделения (например, отдел) []:Искрящий удостоверяющий центр
Common Name (e.g. server FQDN or YOUR name) []:Sparkling Root CA             # Общее имя (например, полное доменное имя сервера или ваше имя) []:Искрящий корневой удостоверяющий центр
Email Address []:                                                            # Адрес электронной почты []:
Создадим несколько файлов, в которых удостоверяющий центр будет хранить серийные номера:
touch certindex
echo 1000 > certserial
echo 1000 > crlnumber
Создадим файл конфигурации удостоверяющего центра. Этот файл содержит заглушки для конечных точек CRL - списка отозванных сертификатов и OCSP - протокола интерактивного статуса сертификата.
# vim ca.conf
[ca]
default_ca = myca

[crl_ext]
issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always

[myca]
dir = ./
new_certs_dir = $dir
unique_subject = no
certificate = $dir/rootca.crt
database = $dir/certindex
private_key = $dir/rootca.key
serial = $dir/certserial
default_days = 730
default_md = sha1
policy = myca_policy
x509_extensions = myca_extensions
crlnumber = $dir/crlnumber
default_crl_days = 730

[myca_policy]
commonName = supplied
stateOrProvinceName = supplied
countryName = optional
emailAddress = optional
organizationName = supplied
organizationalUnitName = optional

[myca_extensions]
basicConstraints = critical,CA:TRUE
keyUsage = critical,any
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
keyUsage = digitalSignature,keyEncipherment,cRLSign,keyCertSign
extendedKeyUsage = serverAuth
crlDistributionPoints = @crl_section
subjectAltName = @alt_names
authorityInfoAccess = @ocsp_section

[v3_ca]
basicConstraints = critical,CA:TRUE,pathlen:0
keyUsage = critical,any
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
keyUsage = digitalSignature,keyEncipherment,cRLSign,keyCertSign
extendedKeyUsage = serverAuth
crlDistributionPoints = @crl_section
subjectAltName = @alt_names
authorityInfoAccess = @ocsp_section

[alt_names]
DNS.0 = Sparkling Intermidiate CA 1 # DNS.0 = Искрящий промежуточный удостоверяющий центр 1
DNS.1 = Sparkling CA Intermidiate 1 # DNS.1 = Искрящий удостоверяющий центр промежуточный 1

[crl_section]
URI.0 = http://pki.sparklingca.com/SparklingRoot.crl
URI.1 = http://pki.backup.com/SparklingRoot.crl

[ocsp_section]
caIssuers;URI.0 = http://pki.sparklingca.com/SparklingRoot.crt
caIssuers;URI.1 = http://pki.backup.com/SparklingRoot.crt
OCSP;URI.0 = http://pki.sparklingca.com/ocsp/
OCSP;URI.1 = http://pki.backup.com/ocsp/
Если нужно задать определённые даты начала или завершения действия сертификата, добавьте в секцию [myca] следующие строки:
# формат: ГГГГММДДЧЧММСС
default_enddate = 20191222035911
default_startdate = 20181222035911

Создание промежуточного удостоверяющего центра 1

Создание приватного ключа промежуточного удостоверяющего центра:
openssl genrsa -out intermediate1.key 4096
Создание CSR - запроса на подписание сертификата промежуточного удостоверяющего центра 1:
openssl req -new -sha256 -key intermediate1.key -out intermediate1.csr
Пример вывода:
You are about to be asked to enter information that will be incorporated     # У вас будет запрошена информация, которая будет вставлена
into your certificate request.                                               # в ваш запрос сертификата.
What you are about to enter is what is called a Distinguished Name or a DN.  # То, что вы введёте, называется Distinquised Name - Отличительное Имя или DN.
There are quite a few fields but you can leave some blank                    # Далее следует несколько полей, но некоторые из них можно не заполнять
For some fields there will be a default value,                               # У некоторых полей есть значение по умолчанию,
If you enter '.', the field will be left blank.                              # Если ввести '.', то поле останется пустым.
-----
Country Name (2 letter code) [AU]:NL                                         # Название страны (двухбуквенный код) [AU]:NL
State or Province Name (full name) [Some-State]:Zuid Holland                 # Название штата или провинции (полное название) [Некий-штат]:Южная Голландия
Locality Name (eg, city) []:Rotterdam                                        # Название местности (например, город) []:Роттердам
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Sparkling Network # Название организации (например, компания) [ООО Интернет-виджеты]:Искрящая сеть
Organizational Unit Name (eg, section) []:Sparkling CA                       # Название подразделения (например, отдел) []:Искрящий удостоверяющий центр
Common Name (e.g. server FQDN or YOUR name) []:Sparkling Intermediate CA     # Общее имя (например, полное доменное имя сервера или ваше имя) []:Искрящий промежуточный удостоверяющий центр
Email Address []:                                                            # Адрес электронной почты []:

Please enter the following 'extra' attributes                                # Пожалуйста, введите следующие дополнительные атрибуты,
to be sent with your certificate request                                     # которые будут отправлены в составе запроса сертификата
A challenge password []:                                                     # Пароль вызова []:
An optional company name []:                                                 # Не обязательное название компании []:
Удостоверьтесь, что Общее Имя (Common Name - CN) промежуточного сертификата отличается от корневого.

Подпишем корневым удостоверяющим центром запрос на подписание сертификата промежуточного удостоверяющего центра:
openssl ca -batch -config ca.conf -notext -in intermediate1.csr -out intermediate1.crt
Пример вывода:
Using configuration from ca.conf                                         # Используется конфигурация из ca.conf
Check that the request matches the signature                             # Проверка соответствия подписи запросу
Signature ok                                                             # Подпись в порядке
The Subject's Distinguished Name is as follows                           # Содержимое Отличительного Имени показано ниже
countryName :PRINTABLE:'NL'
stateOrProvinceName :ASN.1 12:'Zuid Holland'
localityName :ASN.1 12:'Rotterdam'
organizationName :ASN.1 12:'Sparkling Network'
organizationalUnitName:ASN.1 12:'Sparkling CA'
commonName :ASN.1 12:'Sparkling Intermediate CA'
Certificate is to be certified until Mar 30 15:07:43 2017 GMT (730 days) # Сертификат был удостоверен до 30 марта 2017 года 15:07:43 по Гринвичу (730 дней)

Write out database with 1 new entries                                    # В базу данных записана 1 новая запись
Data Base Updated                                                        # База данных обновлена
Создадим CRL - список отозванных сертификатов в форматах PEM и DER:
openssl ca -config ca.conf -gencrl -keyfile rootca.key -cert rootca.crt -out rootca.crl.pem
openssl crl -inform PEM -in rootca.crl.pem -outform DER -out rootca.crl
Создавайте CRL - список отозванных сертификатов после каждого подписания сертификата удостоверяющим центром.

Если когда-нибудь понадобится отозвать этот промежуточный сертификат:
openssl ca -config ca.conf -revoke intermediate1.crt -keyfile rootca.key -cert rootca.crt

Настройка промежуточного удостоверяющего центра 1

Создадим новый каталог и переместим промежуточный удостоверяющий центр:
mkdir ~/SSLCA/intermediate1/
cd ~/SSLCA/intermediate1/
Скопируем сертификат промежуточного удостоверяющего центра и ключ из каталога корневого удостоверяющего центра:
cp ~/SSLCA/root/intermediate1.key ./
cp ~/SSLCA/root/intermediate1.crt ./
Создадим файлы индекса:
touch certindex
echo 1000 > certserial
echo 1000 > crlnumber
Создадим новый файл ca.conf:
# vim ca.conf
[ca]
default_ca = myca

[crl_ext]
issuerAltName=issuer:copy
authorityKeyIdentifier=keyid:always

[myca]
dir = ./
new_certs_dir = $dir
unique_subject = no
certificate = $dir/intermediate1.crt
database = $dir/certindex
private_key = $dir/intermediate1.key
serial = $dir/certserial
default_days = 365
default_md = sha1
policy = myca_policy
x509_extensions = myca_extensions
crlnumber = $dir/crlnumber
default_crl_days = 365

[myca_policy]
commonName = supplied
stateOrProvinceName = supplied
countryName = optional
emailAddress = optional
organizationName = supplied
organizationalUnitName = optional

[myca_extensions]
basicConstraints = critical,CA:FALSE
keyUsage = critical,any
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
keyUsage = digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth
crlDistributionPoints = @crl_section
subjectAltName = @alt_names
authorityInfoAccess = @ocsp_section

[alt_names]
DNS.0 = example.com
DNS.1 = example.org

[crl_section]
URI.0 = http://pki.sparklingca.com/SparklingIntermidiate1.crl
URI.1 = http://pki.backup.com/SparklingIntermidiate1.crl

[ocsp_section]
caIssuers;URI.0 = http://pki.sparklingca.com/SparklingIntermediate1.crt
caIssuers;URI.1 = http://pki.backup.com/SparklingIntermediate1.crt
OCSP;URI.0 = http://pki.sparklingca.com/ocsp/
OCSP;URI.1 = http://pki.backup.com/ocsp/
Отредактируйте секцию [alt_names] так, чтобы она содержала необходимые альтернативные имена. Если альтернативные имена не нужны, то удалите эту секцию и строку subjectAltName = @alt_names.

Если нужно задать определённые даты начала или завершения действия сертификата, добавьте в секцию [myca] следующие строки:
# формат: ГГГГММДДЧЧММСС
default_enddate = 20191222035911
default_startdate = 20181222035911
Создадим пустой CRL - список отозванных сертификатов в форматах PEM и DER:
openssl ca -config ca.conf -gencrl -keyfile rootca.key -cert rootca.crt -out rootca.crl.pem
openssl crl -inform PEM -in rootca.crl.pem -outform DER -out rootca.crl

Создание конечных пользовательских сертификатов

Воспользуемся новым промежуточным удостоверяющим центром для создания конечного пользовательского сертификата. Повторим эти шаги для каждого конечного пользовательского сертификата, который нужно подписать этим удостоверяющим центром.
mkdir enduser-certs
Создадим приватный ключ конечного пользователя:
openssl genrsa -out enduser-certs/enduser-example.com.key 4096
Создадим CSR - запрос на подписание сертификата конечного пользователя:
openssl req -new -sha256 -key enduser-certs/enduser-example.com.key -out enduser-certs/enduser-example.com.csr
Пример вывода:
You are about to be asked to enter information that will be incorporated    # У вас будет запрошена информация, которая будет вставлена
into your certificate request.                                              # в ваш запрос сертификата.
What you are about to enter is what is called a Distinguished Name or a DN. # То, что вы введёте, называется Distinquised Name - Отличительное Имя или DN.
There are quite a few fields but you can leave some blank                   # Далее следует несколько полей, но некоторые из них можно не заполнять
For some fields there will be a default value,                              # У некоторых полей есть значение по умолчанию,
If you enter '.', the field will be left blank.                             # Если ввести '.', то поле останется пустым.
-----
Country Name (2 letter code) [AU]:NL                                        # Название страны (двухбуквенный код) [AU]:NL
State or Province Name (full name) [Some-State]:Noord Holland               # Название штата или провинции (полное название) [Некий-штат]:Северная Голландия
Locality Name (eg, city) []:Amsterdam                                       # Название местности (например, город) []:Амстердам
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Inc      # Название организации (например, компания) [ООО Интернет-виджеты]:АО Пример
Organizational Unit Name (eg, section) [например, отдел]:IT Dept            # Название подразделения (например, отдел) []:Отдел информационных технологий
Common Name (e.g. server FQDN or YOUR name) []:example.com                  # Общее имя (например, полное доменное имя сервера или ваше имя) []:example.com
Email Address []:                                                           # Адрес электронной почты []:

Please enter the following 'extra' attributes                               # Пожалуйста, введите следующие дополнительные атрибуты,
to be sent with your certificate request # которые будут отправлены в составе запроса сертификата
A challenge password []: # Пароль вызова []:
An optional company name []: # Не обязательное название компании []:
Подпишем CSR - запрос на подписание сертификата конечного пользователя в промежуточном удостоверяющем центре 1:
openssl ca -batch -config ca.conf -notext -in enduser-certs/enduser-example.com.csr -out enduser-certs/enduser-example.com.crt
Пример вывода:
Using configuration from ca.conf                                         # Используется конфигурация из ca.conf
Check that the request matches the signature                             # Проверка соответствия подписи запросу
Signature ok                                                             # Подпись в порядке
The Subject's Distinguished Name is as follows                           # Содержимое Отличительного Имени показано ниже
countryName :PRINTABLE:'NL'
stateOrProvinceName :ASN.1 12:'Noord Holland'
localityName :ASN.1 12:'Amsterdam'
organizationName :ASN.1 12:'Example Inc'
organizationalUnitName:ASN.1 12:'IT Dept'
commonName :ASN.1 12:'example.com'
Certificate is to be certified until Mar 30 15:18:26 2016 GMT (730 days) # Сертификат был удостоверен до 30 марта 2016 года 15:18:26 по Гринвичу (365 дней)

Write out database with 1 new entries                                    # В базу данных записана 1 новая запись
Data Base Updated                                                        # База данных обновлена
Создадим CRL - список отозванных сертификатов в форматах PEM и DER:
openssl ca -config ca.conf -gencrl -keyfile intermediate1.key -cert intermediate1.crt -out intermediate1.crl.pem
openssl crl -inform PEM -in intermediate1.crl.pem -outform DER -out intermediate1.crl
Создавайте CRL - список отозванных сертификатов после каждого подписания сертификата удостоверяющим центром.

Если когда-то понадобится отозвать этот сертификат конечного пользователя:
openssl ca -config ca.conf -revoke enduser-certs/enduser-example.com.crt -keyfile intermediate1.key -cert intermediate1.crt
Пример вывода:
Using configuration from ca.conf # Используется конфигурация из ca.conf
Revoking Certificate 1000.       # Отзыв сертификата 1000.
Data Base Updated                # База данных обновлена
Создадим файл с цепочкой сертификатов, соединив вместе сертификаты корневого и промежуточного удостоверяющего центра 1.
cat ../root/rootca.crt intermediate1.crt > enduser-certs/enduser-example.com.chain
Отправим следующие файлы конечному пользователю:
  • enduser-example.com.crt
  • enduser-example.com.key
  • enduser-example.com.chain
Вы также можете дать конечному пользователю возможность предоставить его собственный CSR - запрос на подписание сертификата и просто отправить ему файл .crt. Не удаляйте сертификат с сервера, в противном случае его нельзя будет отозвать.

Проверка сертификата

Вы можете проверить сертификат конечного пользователя по цепочке при помощи следующей команды:
openssl verify -CAfile enduser-certs/enduser-example.com.chain enduser-certs/enduser-example.com.crt
enduser-certs/enduser-example.com.crt: OK
Вы также можете проверить его по CRL - списку отозванных сертификатов. Сначала соедините вместе CRL в формате PEM и цепочку:
cat ../root/rootca.crt intermediate1.crt intermediate1.crl.pem > enduser-certs/enduser-example.com.crl.chain
Проверим сертификат:
openssl verify -crl_check -CAfile enduser-certs/enduser-example.com.crl.chain enduser-certs/enduser-example.com.crt
Если не отозван, будет выведено:
enduser-certs/enduser-example.com.crt: OK
Если отозван, будет выведено:
enduser-certs/enduser-example.com.crt: CN = example.com, ST = Noord Holland, C = NL, O = Example Inc, OU = IT Dept
error 23 at 0 depth lookup:certificate revoked                                                                     # ошибка 23 на глубине просмотра 0:сертификат отозван

воскресенье, 27 августа 2017 г.

Краткое руководство по GPG

Перевод: GPG Quickstart
Автор: Эндрю Бикхоф (Andrew Beekhof)

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

Подготовка

Следующие настройки обеспечат, чтобы все ключи, создаваемые в дальнейшем, строго соответствовали стандартам 2013 года. Поместите эти настройки в файл ~/.gnupg/gpg.conf:
# Если все адресаты поддерживают несколько алгоритмов хэширования, выбирать самый надёжный из них:
personal-digest-preferences SHA512 SHA384 SHA256 SHA224
# Предпочтения для новых ключей должны учитывать приоритет алгоритмов, в соответствии с их надёжностью:
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 BZIP2 ZLIB ZIP Uncompressed
# При создании сертификата OpenPGP использовать наиболее надёжный алгоритм хэширования,
# а не алгоритм SHA1, который используется по умолчанию:
cert-digest-algo SHA512
Следующая порция настроек не обязательна, но полезна для улучшения вывода команд gpg в различных ситуациях - в частности, для защиты от подделки. Их тоже нужно поместить в ~/.gnupg/gpg.conf:
# При выводе сертификатов показывать идентификатор пользователя, выделенный из ключей:
fixed-list-mode
# Длинные идентификаторы ключей более защищены от коллизий, чем короткие идентификаторы ключей
# (можно легко создать ключ с любым желаемым коротким идентификатором ключа):
keyid-format 0xlong
# Если вы пользуетесь графической средой (и даже если не пользуетесь ей), вам нужно использовать агента
# (похожие аргументы в пользу этого приведены по ссылке https://www.debian-administration.org/users/dkg/weblog/64):
use-agent
# Взглянув на идентификатор пользователя, вы всегда должны знать, что по мнению gpg он является доверенным,
# т.к. ключ присутствует в вашем брелоке:
verify-options show-uid-validity
list-options show-uid-validity
# Включить недвусмысленный индикатор ключа, которым сделана подпись
# (см. http://thread.gmane.org/gmane.mail.notmuch.general/3721/focus=7234):
sig-notation issuer-fpr@notations.openpgp.fifthhorseman.net=%g

Создание нового ключа

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

Я воспользовался инструкциями из статьи Анны Гереро (Ana Guerrero), которые были основой текущего руководства Debian, но выбрал тип ключа по умолчанию в соответствии со стандартами 2013 года:
  1. Запустите gpg --gen-key
  2. Выберите 1: RSA и RSA (по умолчанию).
  3. Выберите размер ключа больше 2048.
  4. Задайте срок действия ключа - 2-5 лет (обоснование).
  5. НЕ указывайте комментарий для идентификатора пользователя (объяснение).

Добавление дополнительных идентификаторов пользователя и настройки по умолчанию

С этого момента мой брелок gpg --list-keys выглядит следующим образом:
pub 4096R/0x726724204C644D83 2013-06-24
uid               [ultimate] Andrew Beekhof <andrew@beekhof.net>
sub 4096R/0xC88100891A418A6B 2013-06-24 [expires: 2015-06-24]
Как и у большинства людей, у меня есть несколько адресов электронной почты и я хочу использовать GPG и с ними тоже. Поэтому сейчас самое время добавить их к ключу. Для этого нужно воспользоваться командой gpg --edit-key. У Анны есть хороший пример добавления идентификаторов пользователей и настройки предпочтений. Просто поищите в её инструкциях текст "Add other UID" - "Добавить другой идентификатор пользователя".

Отдельные подключи для шифрования и подписи

Общепринято использовать отдельные ключи для подписывания и шифрования.
Коротко: бывает нужно что-то зашифровать, не подписывая, поскольку подписание может повлечь за собой юридически последствия. Также существует вероятность, что подписанные сообщения могут быть использованы для взлома зашифрованных данных.
По умолчанию gpg создаёт подключ для шифрования, но я воспользуюсь руководством Debian по субключам, чтобы создать ещё один для подписания (вместо того, чтобы использовать секретный мастер-ключ).
Это позволит сделать ваш секретный мастер-ключ ещё более защищённым, избегая его повседневного использования.
Идея заключается в том, чтобы сначала создать копию и сохранить её в ещё более безопасном месте так, что если подключ (и компьютер, где он находится) будут взломаны, мастер-ключ оставался бы в безопасности и им бы всё равно можно было бы отозвать подключи и создать новые.

Подписание нового ключа старым

Если ваш ключ старый, то им можно подписать новый ключ. Это даст знать всем, кто доверяет старому ключу, что новый ключ законный и поэтому ему можно доверять.
Вернёмся снова к советам Анны. Делается это так:
gpg --default-key СТАРЫЙ-КЛЮЧ --sign-key НОВЫЙ-КЛЮЧ
В моём случае команда будет такой:
gpg --default-key 0xEC3584EFD449E59A --sign-key 0x726724204C644D83

Отправка новых ключей на сервер

Сообщим людям, что они могут проверять вашу подпись и отправлять вам зашифрованные сообщения:
gpg --send-key 0x726724204C644D83

Отзыв старых идентификаторов пользователя

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

Чтобы сделать это с моим старым ключом, я воспользуюсь инструкциями из списка рассылки gnupg.

При поиске старого ключа всё выглядит по-прежнему:
pub 1024D/D449E59A 2007-07-20 Andrew Beekhof <beekhof@mac.com>
                              Andrew Beekhof <abeekhof@suse.de>
                              Andrew Beekhof <beekhof@gmail.com>
                              Andrew Beekhof <andrew@beekhof.net>
                              Andrew Beekhof <abeekhof@novell.com>
        Fingerprint=E5F5 BEFC 781F 3637 774F C1F8 EC35 84EF D449 E59A
Но если заглянуть в детали ключа, можно увидеть, что адреса в Novell/SuSE в данное время отмечены красными символами revok.
pub 1024D/D449E59A 2007-07-20
        Fingerprint=E5F5 BEFC 781F 3637 774F C1F8 EC35 84EF D449 E59A

uid Andrew Beekhof <beekhof@mac.com>
sig  sig3 D449E59A 2007-07-20 __________ __________ [selfsig]

uid Andrew Beekhof <abeekhof@suse.de>
sig  sig3 D449E59A 2007-07-20 __________ __________ [selfsig]
sig revok D449E59A 2013-06-24 __________ __________ [selfsig]
...
Таким образом другие люди, имеющие копию gpg, узнают, что больше не нужно использовать этот адрес. Вот почему важно периодически обновлять свои ключи.

Отзыв старых ключей

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

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

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

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

Вот как выглядит один из моих старых отозванных ключей:
pub 1024D/DABA170E 2004-10-11 *** KEY REVOKED *** [not verified]
                              Andrew Beekhof (SuSE VPN Access) <andrew@beekhof.net>
        Fingerprint=9A53 9DBB CF73 AB8F B57B 730A 3279 4AE9 DABA 170E

Конечный результат

Мой новый ключ:
pub 4096R/4C644D83 2013-06-24 Andrew Beekhof <andrew@beekhof.net>
                              Andrew Beekhof <beekhof@mac.com>
                              Andrew Beekhof <abeekhof@redhat.com>
Fingerprint=C503 7BA2 D013 6342 44C0 122C 7267 2420 4C64 4D83

Заключение

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

воскресенье, 20 августа 2017 г.

Заметки о Dockerfile

Перевод: Dockerfile Notes
Автор: Соня Гамильтон (Sonia Hamilton)

Примечания переводчика:
Искал однажды что-то в интернете и вышел на блог этой авторши. Сейчас уже не помню почему, добавил этот материал в список того, что было бы неплохо перевести. Сейчас смотрю и недоумеваю - зачем мне это понадобилось? Ничего лучше фразы "чтоб было" в голову не пришло. Ну пусть будет.
Несколько заметок о Dockerfile'ах Docker.

Команды

  • MAINTAINER - автор, адрес электронной почты и т.п.
  • FROM - базовый образ, например Ubuntu.
  • CMD и ENTRYPOINT. Любая из них по отдельности может быть использована для указания исполняемого файла по умолчанию. Если используются обе, то CMD добавляется к ENTRYPOINT для получения командной строки контейнера. Любая из них может быть заменена при запуске docker. Однако CMD легче - она просто берёт остаток команды запуска docker (как "$*" в сценариях оболочки) - разрешая образу docker почувствовать себя в роли выполняемого файла, запущенного через "обёртку".
  • RUN - установочные команды. В режиме разработки разделите команды RUN, так что слои кэшировались и собирались быстрее. В рабочем режиме лучше воспользоваться цепочкой команд RUN, разделённых знаками && или точкой с запятой, поскольку несколько отдельных команд RUN создают несколько слоёв.
  • COPY и ADD. COPY копирует файлы в образ. ADD делает то же самое, но также может разархивировать файл или скачать его по ссылке. Избегайте использования команды ADD, поскольку она обладает излишне сложным поведением.
  • VOLUME - постоянный каталог на родительской файловой системе внутри /var/lib/docker/volumes. Для получения ожидаемого поведения (общий каталог для родительской системы и контейнера) воспользуйтесь командой docker run -v /var/tmp/foo:/var/tmp/foo.
  • ENV, WORKDIR и USER - переменные окружения, текущий каталог и идентификатор пользователя для команд CMD/ENTRYPOINT.
  • EXPOSE - открыть сетевой порт. Воспользуйтесь форматом nn, а не nn:mm, который позволяет пользователю указать публичный порт при помощи опции -p. Порт, открытый при помощи команды EXPOSE может быть автоматически отображён при помощи опции -P.

Сборка, запуск, выполнение

# Собрать образ и пометить его, использовать текущий каталог в качестве контекста
docker build -t="soniah/foo:1.0" .
# Запустить, автоматически отобразить порты. В режиме разработки опустите -D - стандартный поток
# вывода будет выводиться на экран, а контейнер автоматически остановится при нажатии Ctrl-C.
docker run -P sonia/foo
# Получить интерактивную оболочку
docker exec -it random_name bash
# Удалить все старые образы, за исключением базовых образов Ubuntu
docker rmi -f `docker images | tail -n +2 | grep -v 'ubuntu' | awk {'print $3'}`
# Удалить все контейнеры, включая остановленные контейнеры
docker rm -f `docker ps --no-trunc -aq`

Смотрите также