Title: О ключевой инфраструктуре TLS
Author: Vitus Wagner
Зачем вообще нужна PKI
Использование шифрования соединения имеет смысл только тогда, когда у нас существует надежный способ проверить, что мы соединились и договариваемся о сессионных ключах шифрования с тем, с кем хотели, а не с каким-то злоумышленником посредине, который потом от нашего имени договорится с тем концом и будет спокойно читать весь траффик. Такая атака называется Man in the Middle (MitM).
В TLS для защиты от этой атаки применяется инфраструктура открытых ключей X509.
Инфраструктура открытых ключй (Public Key Infrastructure, PKI), это некий комплекс технических и организационных мер, позволяющий убедиться, что такой-то открытый ключ принадлежит такому-то субъекту взаимодействия. Далее, мы уже средствами протокола TLS убеждаемся, что тот конец соединения владеет закрытой половиной от этого открытого ключа, а значит он и есть тот субъект, с которым мы хотим соединиться и можно договариваться о ключах шифрования.
Инфраструктура открытых ключей X509 имеет более широкую область применения, чем TLS.
Она может также использоваться для защиты электронной почты S/MIME. В этом случае она позволяет убедиться что закрытой половинкой открытого ключа, используемого для шифрования письма обладает именно адресат, а значит никто, кроме него, письмо не прочтет, и что электронную подпись под письмом поставил именно тот, кто прописан в поле From, а значит письмо не было искажено по дороге.
Кроме того, она может быть использована для подписи программного кода — бинарных файлов в Windows, классов Java, расширений к браузерам. Здесь смысл тот же — проверить, что подпись выработана тем, кого мы считаем поставщиком данного модуля, и значит, никто по дороге ничего несанкционированного туда не встроил.
Сертификат
Базовым элементом PKI X509 является сертификат. Сертификат это электронный документ, в котором указан субъект (владелец ключа) - это может быть человек или хост, и содержится его открытый ключ.
Все это вместе подписано электронной подписью некоего доверенного удостоверяющего центра (Certifcation Authority, CA). Наименование того субъекта, который подписал сертификат, находится в поле Issuer (тот, кто выпустил).
Кроме этого в сертификате есть всякие служебные поля - дата начала и конца действия, порядковый номер (Serial number), расширения, которые могут, например, ограничивать область действия (то есть для TLS применять можно, а для шифрования электронной почты нелья или наоборот), но это уже второстепенные технические вещи.
Главное это Subject, Issuer и открытый ключ.
Структура Subject
Subject сертификата это набор полей, в которые могут входить самые разнообразные элементы. См RFC 5280. В частности там есть поля Common Name (CN), Organization (O) и Organization Unit. Раньше было принято помещать туда также и поле с адресом электронной почты, теперь полагается адрес email класть в расширение Subject alternative name.
Наибольший интерес в случае TLS представляет собой поле Common Name (CN). Именно туда полагается помещать доменное имя сервера, к которому клиент коннектится. Т.е. при установлении соединения сервер должен отдать клиенту сертификат, в котором в поле Subject CN содержится его доменное имя, и подтвердить в процессе TLS-хэндшейка что владеет секретной половинкой от того открытого ключа, который содержится в этом сертификате.
Возможны wildcard сертификаты, которые устроят клиента, коннектящегося к любому поддомену домена. Возможны также сертификаты у которых в расширении SAN перечислено несколько доменных имен и IP-адресов. Такие сертификаты можно отдавать клиенту, коннектящемуся к любому из этих имен.
Вообще говоря IP-стэк операционной системы не позволяет узнать по какому DNS-имени из множества резолвящихся в данный адрес, пришел на этот адрес клиент. Поэтому было разработано расширение протокола TLS Server Name Indication (SNI) которое позволяет клиенту сообщить серверу, сертификат на какое именно из его имен следует предъявить.
Самоподписанный сертификат
Самоподписанный сертификат, это сертификат, у которого Subject и Issuer совпадает, а подпись выработана на закрытой половинке того же открытого ключа, что содержится в самом сертификате.
Такой сертификат вообще говоря, ничего не защищает. Кто угодно может сгенерировать ключевую пару и выработать на ней самоподписанынй сертификат с любым Subject. Поэтому самоподписанные сертификаты годятся только для тестовых целей.
Клиентский сертификат
Проткол TLS позволяет обеим сторонам соединения аутентифицировать себя сертификатами. Обычно считается что сервер аутентифцировать обязательно, а установив с сервером защищенное соединение клиент уже может аутентифицировать себя как угодно, например по имени и пароль. Это достаточно безопасно. Но в некоторых случаях идут на то чтобы создать сертификат и закрытый ключ для каждого клиента. А то и использовать аппаратные токены для хранения этих закрытых ключей.
Postgres умеет аутентифицировать пользователей по сертификату. Для этого необходимо пользователям выдавать такие сертификаты, в CN которых записано имя пользователя базы данных. Впрочем существует возможность мэппинга имен.
Кроме того в контрибе есть расширение sslinfo, некогда написанное автором этих строк, которое позволяет из SQL получить доступ к информации из Subject сертификата, использованного при аутентификации пользователя текущей сессии.
Удостоверяющие центры
Публичный удостоверяющий центр
Когда мы идем на веб-сайт, принадлежащий кому-то постороннему, то мы нуждаемся в какой-то третьей стороне, которая подтвердит, что доменом, который мы ввели в адресную строку браузера, действительно владеет хозяин того открытого ключа, который содержится в сертификате, предъявленном сервером.
Для этой цели существуют коммерческие удостоверяющие центры. В составе любого браузера, криптобиблиотеки или операционной системы обычно есть набор сертификатов так называемых «корневых» удостоверяющих центров.
Эти центры в свою очередь могут выдавать сертификаты «подчиненных» удостоверяющих центров, которые уже в свою очередь будут подписывать сертификаты сервером, и можно будет проверить подпись, выстроив цепочку доверия от серверного сертификата до содержащегося в хранилище браузера.
Они могут выдавать сертификаты разного уровня защищенности. Например, бесплатный CA Let's Encrypt выдает Domain-validated only сертификаты. То есть по специальному протоколу автоматчески проверяется, что тот, кто подал заявку на сертификат, может выкладывать файлы указанным содержимым на этом домене или манипулировать его DNS-записями, т.е. контролирует этот домен, и этого достаточно.
Стандартные (organization validation) сертификаты, которые выдают (уже за деньги) другие удостоверяющие центры, предполагают проверку еще и того, что домен действительно принадлежит указанной организации по базе регистратора доменов и проверку существования организации по реестру юридических лиц.
В свое время были придуманы Extended Validation сертификаты, которые стоили дороже, но соединения защищенные ими отображались в браузере красивым зелененьким цветом. Сейчас от этого производители браузеров отказались, так как выяснилось что существенного улучшения безопасности владельцев торговых марок эти дополнительные проверки не дают.
Как правило, публичные удостоверяющие центры дорожат своей репутацией, и выданным ими сертификатам можно доверять. Но бывают исключения, когда из высших государственных соображений они идут на обман пользователей.
Широко известен такой случай в Казахстане, но он не единственный аналогичные случаи хотя и меньшего масштаба были и в Китае, и в Катаре.
Приватные удостоверяющие центры
Поэтому для внутрикорпоративных целей, особенно если речь идет не об использовании браузера, у которого есть хранилище сертификатов публичных УЦ, а о софте, которому список доверенных сертификатов указывается явным образом, например OpenVPN или программе, использующей библиотеку libpq, лучше сторонним удостоверяющим центрам не доверять.
В этом случае правильнее будет создать свой внутрикорпоративный УЦ, или даже УЦ предназначенный для обслуживания конкретной клиент-серверной системы, который не выписывает сертификатов кому попало, и доверять только ему.
Тогда отпадёт и необходимость проверять Subject, область применения и прочие свойства сертификата. Если сертификат выписан нашим УЦ, значит ему можно доверять и всё (в libpq этому упрощённому режиму соответствует sslmode=verify-ca, а полноценному, соответственно verify-full).
Создать свой собственный УЦ очень просто. Командно-строчная утилита
openssl
имеет подкоманду ca
, которая умеет делать все необходимое.
В том числе генерировать и поддерживать базу сертификатов, списки отзыва
и так далее. Для ещё большего упрощения жизни в состав OpenSSL входят
скрипты CA.sh
и CA.pl
которые автоматизируют типичный набор операций
необходимый для поддержания мини-УЦ. Кроме того в дистрибутив для той же
цели обычно включается комплект скриптов easy_rsa
.
Получение сертификата
Стандартный способ получения сертификата X509 выглядит так:
Пользователь генерирует ключевую пару. Секретная половинка этой ключевой пары хранится в каком-нибудь защищённом хранилище или вообще в специальном аппаратном токене и никогда компьютера пользователя не покидает (разве что складывается в сейф вместе с токеном).
Формируется заявка на сертификат. Заявка это документ, очень похожий на самоподписанный сертификат, только без поля Issuer (она всегда самоподписанная) сроков начала и конца действия и порядкового номера. Все эти поля прописываются уже удостоверяющим центром при выдаче сертификата. Расширения в заявке могут быть указаны, но удостоверяющий центр вправе их повыкидывать, добавить другие и вообще обращаться с содержимым заявки довольно вольно. Например, тот же Lets Encrypt удалит из Subject все поля кроме CN. CN он проверил, а под непроверенными данными подписываться не имеет права.
Заявка отправляется в удостоверяющий центр, который выполняет необходимые проверки и выдаёт сертификат. Кроме этого он помещает сертификат в свою базу.
Альтернативный способ выглядит как
- Системный администратор генерирует ключевую пару и заявку.
- Тут же он же в роли администратора УЦ формирует сертификат
- Пользователю выдаётся его секретный ключ, сертификат на его открытый ключ и сертификат УЦ, на котором это подписано.
Так удобно поступать в случае узкоспециализированных CA.
Отзыв сертификата
Возможны ситуации, когда нужно приостановить действие сертификата до истечения его срока действия. Например если кто-то взломал ваш сервер и похитил секретный ключ.
В этих случаях используется отзыв сертификата. То есть удостоверяющий центр помечает в своей базе сертификат как отозванный.
Далее существуют два способа для клиента использовать эту информацию:
- Периодически (обычно раз в неделю) скачивать из удостоверяющего центра список отозванных сертификатов (CRL, Certificate Revocation List)
- Непосредственно в момент соединения проверять статус сертификата с помощью OCSP (Online Certificate Status Protocol).
Постгрес OCSP не поддерживает. А вот указание CRL-файла поддерживает.
Как для сервера (в конфигурационном файле), так и для клиента
(~/.postgresql/root.crl
или параметр sslcrl в connection string)