Предложил коллегам провести внутреннюю мини-лекцию по сабжу — идея зашла. Сел писать план лекции и… чот психанул — в итоге очнулся, дописывая небольшой гайд. Подумал, что будет полезно добавить сюда что-то для быстрого понимания, что такое PKI, зачем она нужна и как работает, так как пока готовился, чтобы освежить память, искал информацию в том числе на полюбившемся «Хабрахабре», но статей в таком формате не нашел.

Пишу на примере наших повседневных задач, которые знакомы многим: беспарольный доступ к серверам OpenVPN и защита доступа к ресурсам с помощью HTTPS.

Без теории не обойтись


PKI (Public Key Infrastructure, инфраструктура открытых ключей) — это про безопасность. Подразумевается, что у каждой сущности в инфраструктуре есть свой ключ, которым она однозначно идентифицируется. То есть, если ключ украден, пострадавшей сущностью может представиться укравший. PKI нужна для того, чтобы оперативно минимизировать последствия такой кражи. Ключ представлен двумя частями: публичной и приватной.

Аналог — это RSA ключи для SSH, но инфраструктурой их назвать сложно, так как отсутствует централизованный механизм управления ими. Также разница в том, что публичная часть ключа в паре ключей для SSH неизменна, а сертификат (публичную часть ключа участника PKI) можно перевыпустить в любой момент.

В PKI существует один (на самом деле, должно быть минимум два) или несколько Certification Authority — центров сертификации (удостоверяющих центров), отдающих публичные части своих ключей клиентам, которым выдают подписанные ими сертификаты. Таким образом, участники инфраструктуры «понимают», кто ими управляет, и действителен ли сертификат, выданный им или их «товарищам», в настоящий момент времени (одним из важнейших атрибутов сертификатов является срок их действия). Либо же сервер, у которого есть публичная часть ключа CA инфраструктуры, в которой он и его клиенты работают, понимает, что к нему пришел клиент с действительным сертификатом, и разрешает ему что-то, или запрещает в противном случае.

OpenVPN: как это бывает


На самом деле во многих компаниях на этот случай уже есть «PKI» и у него есть имя, потому что это кто-то из сотрудников. Назовем такого человека, к примеру, Полуэкт (с) и расскажем, как обычно это работает, а потом я расскажу, как это должно быть в идеале.

При появлении в компании нового сотрудника Полуэкт создает и присылает ему архив, в котором, помимо конфигурации собственно OpenVPN клиента, находятся файлы (на примере сотрудника Иванова А.А.):

  • a.ivanov-office.key — его приватный ключ, самая мякотка, которую нужно хранить как зеницу ока и никому не показывать (аналог в SSH — файл id_rsa);
  • a.ivanov-office.csr — Certificate Signing Request, запрос на подпись сертификата, в котором описано, для кого нужно выписать сертификат, сгенерирован на основе предыдущего файла, чтобы не «палить» приватный ключ (для работы самого OpenVPN нафиг не нужен);
  • a.ivanov-office.crt — вожделенный сертификат, который он предъявляет OpenVPN серверу, чтобы тот разрешил ему подключение (по сути это публичная часть ключа);
  • ca.crt — сертификат нашего CA, чтобы OpenVPN клиент предъявил его серверу, чтобы тот сопоставил его с приватной частью, которая лежит у него, и убедился, что сертификат подписывал именно он, а не кто-то другой. «Деталька», которая обозначает принадлежность OpenVPN клиента Иванова А.А. к PKI, в которой работает сервер.

Это простые текстовые файлики в специальном формате PEM. Очень удобно, в отличие от, например, мозголомных Java Keystore или PFX от Microsoft: можно сливать сертификаты в один файл простым cat'ом для образования цепочек CA (так называемых bundle, что полезно для nginx, например, в конфигурации которого нет отдельной директивы для указания сертификата CA), можно совмещать сертификаты CA и свой, и даже свой приватный ключ, если зачем-то понадобится. И еще полезность: можно прописать сертификат CA прямо в конфигурации OpenVPN клиента, между тегами <ca> </ca>. Наверное, должно быть можно и сертификат прописать подобным образом. Впрочем, я уже отвлекаюсь на частности.

В компании Acme все эти файлы генерирует Полуэкт…

А теперь как должно быть


На моем примере, упрощенно:

  • я у себя локально генерирую свой приватный ключ (можно и, пожалуй, логично, использовать уже готовый из ~/.ssh/id_rsa):

openssl genrsa -out openvpn.key 2048

  • готовлю запрос на подпись сертификата — CSR, для чего заполняю небольшую анкету:

openssl req -new -key openvpn.key -out a.vrublevskiy-office.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.
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) [XX]:RU
State or Province Name (full name) []:.
Locality Name (eg, city) [Default City]:Moscow
Organization Name (eg, company) [Default Company Ltd]:Pixonic
Organizational Unit Name (eg, section) []:Sysadmins Dept
Common Name (eg, your name or your server's hostname) []:Alexander Vrublevskiy
Email Address []:a.vrublevskiy@pixonic.ru

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:


(пароль в конце лучше не указывать, а то придется его вводить каждый раз при подключении, а VPN у нас по сертификатам как раз, чтобы этого не было; тем более у нас в Pixonic есть OTP от Google);

  • отправляю получившийся файл a.vrublevskiy-office.csr Полуэкту;

  • Полуэкт, получив мой запрос и имея обе части ключа CA (здесь — ca.key и ca.crt), выпускает для меня сертификат, подписывая его ключом CA (модные хипстеры пользуются easy-rsa, но мы суровые бородатые админы):

openssl x509 -req -in a.vrublevskiy-office.csr -CA ca.crt -CAkey ca.key -out a.vrublevskiy-office.crt -days 90

  • Полуэкт отправляет мне получившийся файл.

Возникает резонный вопрос: к чему такие сложности? В чем «фишка» PKI? Отвечаю. Дело в том, что в этой цепочке фишка просто отсутствует. А называется она — CRL (Cerificate Revocation List). Это список отозванных сертификатов, который публикует CA, и в который Полуэкт может внести мой сертификат, выпущенный и подписанный ранее, в случае, если выяснилось, что, к примеру, я упоролся веществами и смог продиктовать свой приватный ключ конкурентам (ну или у меня украли ноут).

Нужна ли вам эта фишка — вопрос для обсуждения. Соответственно, то, как ее внедрить, пока что выходит за рамки этой статьи.

И про срок действия клиентского сертификата: если предположить, что я устроился в Pixonic по временному контракту на 3 месяца, и мы его не продлили, то в описанной ситуации мой доступ к VPN автоматически отключится через 90 дней с момента выпуска сертификата. Чего не случится с SSH-доступом, если коллеги забудут отключить аккаунт во FreeIPA или удалить строчку из authorized_keys руками. C — сесуриту.

Теперь по Борщеву HTTPS


Предположим, вы хотите «включить SSL» для вашего сайта, чтобы у посетителей появился красивый замочек в браузере. Тут, собственно, все то же самое, но с некоторыми нюансами:

  • Очевидно, что на своей стороне вы можете только сгенерировать приватный ключ и запрос на подпись сертификата.
  • При генерировании запроса в качестве Common Name обязательно нужно указывать ServerName вашего виртуального хоста и все алиасы, которые вы пропишете для него в конфигурации веб-сервера. Например, domain.tld и www.domain.tld, хотя «www» CA обычно сами добавляют при выпуске сертификатов. Чаще всего можно указать просто *.domain.tld (чтобы запросить так называемый wildcard certificate), но возможно ли это, нужно узнавать у конкретного CA, а также четко понимать последствия такого решения. Как правило, общедоступные CA не дают в качестве алиаса использовать IP-адрес.
  • При генерировании запроса не стоит указывать challenge password, иначе вам придется вводить его вручную при каждом рестарте веб-сервера.
  • Обычно общедоступные CA — это маститые конторы вроде Comodo, Symantec и GoDaddy. Выпуск сертификата стоит денег, а хорошего сертификата — много денег. Впрочем, помимо них относительно недавно существует Let's Encrypt — бесплатный проект, которому склонны доверять многие, но я бы очень хорошо подумал, какие ресурсы и при каких обстоятельствах защищать их сертификатами.
  • Эти ребята договорились с другими ребятами таким образом, что последние предустанавливают сертификаты (публичные части ключей, т.е. ca.crt из прошлого примера) этих CA в свои браузеры. То есть о PKI как таковой речи быть не может. Просто все договорились верить определенным компаниям. Это не плохо, так как HTTPS в конечном итоге нужен для шифрования трафика, а шифровать его можно и самоподписанной парой ключей. Скорее, тут вопрос престижа, чтобы не светить на весь интернет предупреждением о просроченном/недействительном сертификате.
  • Некоторые особо одаренные CA предлагают для удобства сгенерировать приватный ключ и CSR за вас. Этого делать не надо. Надеюсь, понятно, почему.
  • О сроке действия сертификатов. Всегда нужно заранее продумать систему их своевременного обновления. Особенно это актуально для сертификатов от Let's Encrypt, срок действия которых составляет всего 3 месяца (на момент написания).
  • И о договоренностях между «этими ребятами». Как оказалось после давешней фееричной истории с Google и Symantec, теперь нужно уметь подстелить соломки и на такой «веселый» случай.

Такие дела. Надеюсь, обещанное в начале статьи понимание появилось.

P.S. Конечно, у маститого профи-безопасника, который на этом собаку съел, могут волосы зашевелится в самых нескромных местах от того, как в статье описана такая сложная штука, как PKI. Я же написал этот небольшой гайд для тех, кто вроде как сталкивается с этим по работе, но не очень понимает, что и зачем он делает. А хардкорного «матана» и без меня хватает в этих ваших ынтырнетах. Если же, несмотря на это, вам есть, что сказать — добро пожаловать в комментарии.

Комментарии (13)


  1. vesper-bot
    10.08.2017 13:39
    +2

    Также разница в том, что публичная часть ключа в паре ключей для SSH неизменна, а сертификат (публичную часть ключа участника PKI) можно перевыпустить в любой момент.

    Тут неверно в случае использования RSA как алгоритма генерации публичного и приватного ключа. В случае SSH и постоянной пары ключей открытый ключ статичен, если же пару пересоздать, понадобится заменить authorized key на сервере, что в принципе соответствует авторизации ещё одного пользователя (проверка доверия в ключах отсутствует). Сертификат можно и перевыпустить, но ключ в нем будет тот же самый, если взять тот же запрос. Т.е. сертификат не есть публичная часть ключа, а удостоверение о том, что владелец закрытого ключа от данного публичного является "Васей Пупкиным" (о котором информация в том же сертификате), подписанное центром сертификации ("Полуэктом").


    А так — довольно чОтко расписано.


    1. bofh666 Автор
      10.08.2017 14:36

      Пример с SSH я привел как грубую аналогию и чтобы не вдаваться в подробности (см. название статьи). Вы, конечно, правы. Спасибо за уточнение — изучающим тему оно будет полезно.


  1. olekhov
    10.08.2017 14:28
    +1

    Раз уж заговорили, что ключ может быть украден — следует упомянуть о возможности отзыва сертификата. (openssl ca -revoke).
    В этом случае серверам требуется рассылать ещё CRL-ку, у которой по-хорошему должен быть короткий срок жизни.


    1. bofh666 Автор
      10.08.2017 14:39
      +1

      Отзыву сертификатов и CRL посвящен целый абзац. Тут или я «незаметно» написал, или вы невнимательно читали ;)


      1. olekhov
        10.08.2017 18:24
        +1

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


        1. bofh666 Автор
          10.08.2017 22:19

          Сталкивался неоднократно. Но это выходит за рамки того, о чем говорится в статье. Понимаю, это основа основ PKI, но объяснить это начинающему довольно сложно.
          За критику спасибо, буду стараться :)


  1. nmk2002
    10.08.2017 18:27
    +1

    Тут плохо прям все. У меня подгорает, когда так некомпетентно рассказывают о важных вещах.
    Попробую по порядку:

    Что за публичная часть ключа? Нет такой части ключа. Вообще нет такого термина в PKI. Вы используете этот термин в статье в двух значениях: сертификат и публичный ключ. Но даже это не синонимы.

    Также разница в том, что публичная часть ключа в паре ключей для SSH неизменна, а сертификат (публичную часть ключа участника PKI) можно перевыпустить в любой момент.

    Во-первых сертификат можно перевыпустить не заменяя ключевую пару. Во вторых сертификат не является публичным ключом.
    Полуэкт, получив мой запрос и имея обе части ключа CA (здесь — ca.key и ca.crt), выпускает для меня сертификат

    На самом деле для подписи сертификата нужен только закрытый ключ.
    В чем «фишка» PKI? Отвечаю. Дело в том, что в этой цепочке фишка просто отсутствует. А называется она — CRL (Cerificate Revocation List).

    CRL — это один из инструментов, который используется в PKI для достижения самой важной цели — организации доверия. Очевидно, что главная «фишка» в том, что не надо доверять каждому открытому ключу отдельно, а достаточно доверять УЦ, который удостоверяет соответствие открытого ключа и набора информации из, как выразился автор, «небольшой анкеты».
    Let's Encrypt — бесплатный проект, которому склонны доверять многие, но я бы очень хорошо подумал, какие ресурсы и при каких обстоятельствах защищать их сертификатами.

    Вот почему? Какие риски вы видите? И чем они отличаются, если использовать платный сертификат?
    Эти ребята договорились с другими ребятами таким образом, что последние предустанавливают сертификаты (публичные части ключей, т.е. ca.crt из прошлого примера) этих CA в свои браузеры. То есть о PKI как таковой речи быть не может. Просто все договорились верить определенным компаниям.

    Да, производители ОС и браузеров решают, каким УЦ они доверяют. Что вы хотите сказать фразой «о PKI как таковой речи быть не может»?


    1. bofh666 Автор
      10.08.2017 22:16

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


      1. nmk2002
        11.08.2017 11:42

        Понимаю, к чему вы клоните. Но я негодую не из-за подачи материала, а из-за фактических ошибок. Вот например, вам проще называть и открытый ключ и сертификат термином «публичная часть ключа». Но это некорректно. Потому, что нет никаких частей ключа. И даже если предположить, что вы называете этим термином открытый ключ ключевой пары, то в других предложениях вы этим же термином называете сертификат. А сертификат != открытый ключ. Вы можете таким «упрощением» запутать читателя и него будут ложные представления о рассмотренном материале.

        В моем комментарии было не так много вопросов, в основном я указываю на ошибки, не задавая вопросы. Если так будет проще, то давайте я соберу вопросы, на которые мне хотелось бы услышать ваш ответ:
        1. Чем сертификат от Let's Encrypt хуже платного?
        2. Что вы хотите сказать фразой «о PKI как таковой речи быть не может»?

        Игнорирование вопросов, это, конечно, ваше право.


        1. bofh666 Автор
          11.08.2017 14:51
          +1

          То, что вы называете фактическими ошибками, вы называете справедливо. Но статья предназначается для сильно начинающих. Такие утрирования я ввел намеренно, чтобы упростить понимание — думаю, вы согласитесь, что лучше примера с SSH сложно что-то придумать. Если человек всерьез озаботится изучением материала (на что, надеюсь, кого-то может сподвигнуть эта статья, а может быть и ваши комментарии), он и без меня поймет разницу. А если не озаботится, ему не будет большой разницы в таких нюансах, но, надеюсь, будет хотя бы видимость big picture. В любом случае я не считаю, что после прочтения такого «некомпетентного рассказа» с кучей «фактических ошибок» мир для потенциального читателя перестанет быть прежним.

          1. Чем сертификат от Let's Encrypt хуже платного?

          Заметим, чот я не говорил, что сертификаты от Let's Encrypt какие-то «бракованные» (пунктом ниже я пишу, что шифровать трафик можно и самоподписанным сертификатом). Я лишь написал, что лично я бы хорошо подумал. Поэтому отвечаю на ваш вопрос со своей точки зрения, почему их сертификаты могли бы не подойти лично мне. Итак:

          • Let's Encrypt предоставляют сертификаты только с базовой степенью верификации владельца (Domain Validation).
          • Let's Encrypt не сделают меня своим доверенным CA, чтобы браузеры доверяли моему CA так же, как их.
          • Let's Encrypt не предоставляют wildcard сертификаты (ОК-ОК, на момент написания ;).
          • Let's Encrypt не предоставляют Code Signing сертификаты.

          2. Что вы хотите сказать фразой «о PKI как таковой речи быть не может»?

          Речь идет о «тех ребятах, которые договорились». Как можно назвать инфраструктурой множество сущностей (я про ОС, браузеры, почтовые клиенты и пр.), которые по своему разумению могут доверять или не доверять разным CA (добавлять или удалять соответствующие сертификаты)? В лучшем случае это некий mesh из разных PKI в рамках каждого CA. Солидные дяди называют это «global SSL ecosystem».


    1. Dorlas
      11.08.2017 07:50
      +2

      Насчет Let's Encrypt согласен — риски от его использования точно такие же, как если у нас сертификат от Comodo, Digicert and Symantec…

      В чем суть SSL-сертификатов? В том — чтобы данные между Вашим браузером и WEB-сервером шифровались в процессе передачи.

      Чем отличаются самоподписанные сертификаты от платных или бесплатных (Let's Encrypt) с точки зрения пользователя браузера? В удобстве и статусе проверки сертификата (зеленый, красный, зеленый с названием компании и т.д.) Т.е. это маркер, сообщающий — все хорошо или не совсем хорошо. Его можно проигнорировать, а можно пойти и посмотреть на сертификат WEB-сервера (т.е. сделать следующий шаг).

      Можно ли осуществить атаку на сертификат? Да — можно. На любое SSL соединение можно осуществить атаку (на стороне клиента, на стороне сервера, на канале — вопрос только в сложности).

      Вывод — никакой разницы между Let's Encrypt или платным сертификатом нет с точки зрения безопасности.

      Вывод личный — не доверяйте никакому CA — если Вам важны данные, которые Вы вводите в форму (например, логин и пароль от Банк-Клиента) — всегда перед этим проверяйте предъявленный сертификат, даты, цепочку доверия и сравнивайте с прошлым входом)… так как всегда есть вероятность (не нулевая), что в данный момент Ваше SSL соединение уже Bump-нуто.


  1. gikido
    11.08.2017 18:43
    +1

    ca.crt — сертификат нашего CA, чтобы OpenVPN клиент предъявил его серверу, чтобы тот сопоставил его с приватной частью, которая лежит у него, и убедился, что сертификат подписывал именно он, а не кто-то другой.

    — а разве это так работает? Я всегда думал, что ca.crt в данном случае, доверенный сертификат того CA, кторый подписал сертификат сервера — чтобы мы могли его проверить с помощью этого доверенного сертификата. Поправьте, если не прав.


    1. bofh666 Автор
      11.08.2017 19:39

      Вы правы, спасибо за дополнение. Я просто не остановился на этом моменте, чтобы не усложнять, и, поскольку речь шла о файлах на клиентской стороне, описал только привычную картину: клиент подключается к серверу, поэтому очевидно, что сервер должен проверить, «честный» ли это клиент (аналогично аутентификации по PSK). Но также и клиент должен убедиться, что сервер принадлежит его PKI — сертификат сервера подписан тем же СА, что и его собственный.

      Обратимся к документации (с вашего позволения, я переведу):

      И сервер, и клиент аутентифицируют друг друга, сначала проверяя, что предоставленные ими сертификаты были подписаны главным удостоверяющим центром, и только потом проверяя остальную информацию из сертификатов, такую как CN и тип сертификата (клиент или сервер).