воскресенье, 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:сертификат отозван