June 18th, 2019

Cat-light

CA для X509 с EC-ключами и немного про OpenVPN (памятка)

Задача.

Нужно соединить несколько устройств при помощи OpenVPN. Некоторые из них весьма слабомощные (роутеры на ARM-процессорах). Для этого хочется использовать криптографию на эллиптических кривых (EC), а также поднять свой собственный CA для выпуска сертификатиков.

Решение, часть первая. CA.

Вообще, существует уже довольно много "легковесных" CA. Один из самых "навороченных", с графическим интерфейсом, из числа "полупромышленных" — XCA. Но мне консолька ближе и милее, поэтому я беру EasyRSA 3.0.6. В моем примере везде используется Debian. Как готовить.


  1. Поставить пакет "easy-rsa" из тестируемого выпуска (посвежее).

  2. Придумать в какой папке будем хранить все эти наши ключики, натравить на неё "/usr/bin/make-cadir <folder_name>". Для успеха мероприятия такой папки заранее существовать не должно.

  3. Находим внутри файл "vars". Редактируем его на своё усмотрение. Особое внимание обращаем на переменные "EASYRSA_ALGO" и "EASYRSA_CURVE". Первой присваиваем значение "ec" (elliptic curve), второй "prime256v1" (она же secp256r1, она же NIST P-256). Почему именно эта? Во-первых, разумный компромисс между стойкостью и прожорливостью вычислительных мощностей. Во-вторых, данный алгоритм реализован и в OpenSSL, и в mbedTLS, что важно для подключения роутеров.

  4. Произносим заклинание "export EASYRSA_VARS_FILE=путь_к_файлу_vars". Это костыль для обхода багов в скриптах easy-rsa.

  5. Переходим в папку из пункта 2 ("cd <folder_name>"). Произносим заклинание "./easyrsa init-pki". Оно очистит содержимое папок и обнулит счетчик выпущенных сертификатов.

  6. Очередной костыль для обхода багов. Нужно создать файлик с 256-ю байтами случайных данных с именем "./pki/.rnd". Заклинание "dd if=/dev/urandom of=/<folder_name>/pki/.rnd bs=256 count=1".

  7. Создаем корневой сертификат: "./easyrsa build-ca". В процессе скрипты попросят придумать пароль, которым будет зашифрован закрытый ключ корня. Стоит его записать в надежном месте.

  8. Дальше создаем собственно сами сертификаты для каждого устройства. Перед этим не забываем сделать "export EASYRSA_VARS_FILE=бла-бла-бла".

  9. Если хотим создать сертификат с пометкой "серверный", то "./easyrsa build-server-full <имя_сертификата> nopass". Под "<имя_сертификата>" я подразумеваю его CN (common name).

  10. Если хотим создать сертификат с пометкой "клиентский", то "./easyrsa build-client-full <имя_сертификата> nopass". В процессе создания скрипты спросят пароль, придуманный на шаге 7.

Часть вторая, про OpenVPN.


  • Для "серверного" конфига OpenVPN в случае сертификатов на эллиптических кривых нужно явно прописывать директиву "dh none". В противном случае он будет материться на отсутствие таковой и откажется запускаться.

  • Чтобы явно задать используемые шифры, существуют директивы "ncp-disable" и "cipher". Я использую "cipher AES-128-GCM". Тоже компромисс между стойкостью и прожорливостью.

  • Чтобы явно задать режим обмена ключами (рукопожатиями), существует директива "tls-cipher". Я использую "tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256" по тем же причинам, что и в пункте 3 части 1.

  • Чтобы OpenVPN не матерился в логах, можно добавить "auth-nocache". Чисто для красоты.

  • В клиентский конфиг для большей лучшести имеет смысл добавить "remote-cert-tls server". Вроде как дополнительный кордон защиты против MITM-атак.

  • Если сервер торчит "голой попой в интернет", а вычислительных ресурсов у него не очень много, полезно использовать "tls-crypt" или "tls-auth". Отсечёт всяких брутфорсеров и скрипткиддисов.