Авторизация с помощью клиентских SSL сертификатов.Протокол безопасной передачи данных SSL (Secure Sockets Layer) помимо обеспечения безопасной передачи данных позволяет также реализовать авторизацию клиентов на сервере с помощью клиентских SSL сертификатов. Данная статья является практическим руководством по реализации данного вида авторизации. В статье не рассматриваются теоретические основы криптографии или передачи данных по протоколу SSL. Подразумеваемся, что читатель хотя бы поверхностно знаком с понятиями, используемыми в этой статье, такими как сертификат, секретный ключ, подпись сертификата и т.д. Процесс авторизация выглядит следующим образом. При переходе клиента в закрытую область сайта веб-сервер запрашивает у броузера клиента сертификат, если проверка клиентского сертификата веб-сервером прошла удачно, то клиент получает доступ к закрытым данным. Наиболее наглядным примером использования авторизации посредством клиентских сертификатов является система платежей WebMoney Transfer, а точнее реализация WM Keeper Light. Данная схема авторизации признана наиболее надежной и, в том или ином виде, широко используется в сфере предоставления банковских услуг. Практическая реализация рассматривается на основе популярной связки веб-сервера Apacheї и модуля mod_sslї, основанного на использовании библиотеки opensslї. Предполагается, что соответствующее программное обеспечение у вас уже установлено. Для реализации процесса авторизации по клиентским сертификатам требуется:
Примечание: Для работы с ключами используется программа openssl, входящая в пакет библиотеки openssl. Все приведенные в статье примеры максимально адаптированы для их выполнения из серверных скриптов при автоматизации процесса выдачи клиентских сертификатов, в частности нигде не используется интерактивный режим. При создании закрытых ключей не используется шифрование ключа, поэтому рекомендуется максимально использовать систему ограничения прав доступа операционной системы на файлы ключей. $1. Создание собственного самоподписанного доверенного сертификата.Собственный доверенный сертификат (Certificate Authority - далее CA) необходим для подписи клиентских сертификатов и для их проверки при авторизации клиента веб-сервером. С помощью приведенной ниже команды создается закрытый ключ и самоподписанный сертификат. # openssl req -new -newkey rsa:1024 -nodes -keyout ca.key -x509 -days 500 -subj /C=RU/ST=Msk/L=Msk/O=My\ Inc/OU=Sale/CN=bla/emailAddress=usr@dom.ru -out ca.crt Описание аргументов:
В результате выполнения команды появятся два файла ca.key и ca.crt. Просмотреть данные закрытого ключа и сертификата вы можете с помощью команд: # openssl rsa -noout -text -in ca.key (для ключа) # openssl x509 -noout -text -in ca.crt (для сертификата) $2. Создание клиентских сертификатов$2.1. Подготовка конфигурации и файлов для подписи сертификатов.Создайте конфигурационный файл с именем ca.config следующего содержания. [ ca ] default_ca = CA_CLIENT # При подписи сертификатов # использовать секцию CA_CLIENT [ CA_CLIENT ] dir = ./db # Каталог для служебных файлов certs = $dir/certs # Каталог для сертификатов new_certs_dir = $dir/newcerts # Каталог для новых сертификатов database = $dir/index.txt # Файл с базой данных # подписанных сертификатов serial = $dir/serial # Файл содержащий серийный номер # сертификата # (в шестнадцатиричном формате) certificate = ./ca.crt # Файл сертификата CA private_key = ./ca.key # Файл закрытого ключа CA default_days = 365 # Срок действия подписываемого # сертификата default_crl_days = 7 # Срок действия CRL (см. $4) default_md = md5 # Алгоритм подписи policy = policy_anything # Название секции с описанием # политики в отношении данных # сертификата [ policy_anything ] countryName = optional # Код страны - не обязателен stateOrProvinceName = optional # ...... localityName = optional # ...... organizationName = optional # ...... organizationalUnitName = optional # ...... commonName = supplied # ...... - обязателен emailAddress = optional # ...... Создайте структуру каталогов и файлов, соответсвующую описанной в конфигурационном файле # mkdir db # mkdir db/certs # mkdir db/newcerts # touch db/index.txt # echo "01" > db/serial Примечание: В файле db/serial записывается текущий серийный номер подписываемого сертификата в шестнадцатиричном формате. В файл db/index.txt сохраняются данные о подписываемых сертификатах. $2.2. Создание клиентского закрытого ключа и запроса на сертификат (CSR).Для создания подписанного клиентского сертификата предварительно необходимо создать запрос на сертификат, для его последующей подписи. Аргументы команды полностью аналогичны аргументам использовавшимся при создании самоподписанного доверенного сертификата (см. $1), но отсутсвует параметр -x509. # openssl req -new -newkey rsa:1024 -nodes -keyout client01.key -subj /C=RU/ST=Msk/L=Msk/O=Inc/OU=Web/CN=usr/emailAddress=usr@dm.ru -out client01.csr В результате выполнения команды появятся два файла client01.key и client01.csr. Просмотреть данные закрытого ключа и запроса на сертификат (CSR) вы можете с помощью команд: # openssl rsa -noout -text -in client01.key (для ключа) # openssl req -noout -text -in client01.csr (для запроса) $2.3. Подпись запроса на сертификат (CSR) с помощью доверенного сертификата (CA).При подписи запроса используются параметры заданные в файле ca.config (см. $2.1.) # openssl ca -config ca.config -in client01.csr -out client01.crt -batch Описание аргументов:
В результате выполнения команды появится файл клиентского сертификата client01.crt. Просмотреть данные сертификата вы можете с помощью команды: # openssl x509 -noout -text -in client01.crt $2.4. Подготовка данных для передачи клиенту.Для передачи полученных в результате предыдущих операций файлов клиенту, обычно используется файл в формате PKCS#12. В этот файл упаковывается и защищается паролем вся информация необходимая клиенту для инсталяции сертификата в броузер. # openssl pkcs12 -export -in client01.crt -inkey client01.key -certfile ca.crt -out client01.p12 -passout pass:q1w2e3 Описание аргументов:
На этом процесс создания клиентского сертификата завершен. Теперь вам необходимо передать клиенту файл client01.p12 и пароль к нему любым удобным безопасным способом, а также проинструктировать его о процедуре инсталяции сертификата в броузер. Для создания новых клиентских сертификатов повторите операции с $2.2. по $2.4. $3. Настройка веб-сервера.Для реализации процесса авторизации по клиентским сертификатам необходимо сконфигурировать веб-сервер для решения следующих задач:
$3.1. Запрет доступа к защищаемой области по протоколу HTTP.Найдите в конфигурационном файле веб-сервера http2d.conf секцию <VirtualHost IP-ADDRESS>, соответсвующую вашему сайту и добавьте в неё следующие директивы <Directory /path/to/secure/area/> SSLRequire </Directory> Описание директив:
$3.2. Запрос и проверка клиентских сертификатов.Найдите в конфигурационном файле веб-сервера http2d.conf секцию SSLCACertificateFile /path/to/ca.crt <Directory /path/to/secure/area/> SSLVerifyClient require </Directory> Описание директив:
Для того, чтобы изменения конфигурационного файла веб-сервера вступили в силу необходимо перезапустить веб-сервер # apachectl restart $3.3. Альтернативные способы настройки веб-сервера.В этом разделе будут рассмотрены альтернативные пути настройки веб-сервера для авторизации по клиентским сертификатам. Вариантов настройки и их комбинаций может быть много, нижеприведенные примеры проиллюстрируют некоторые из них и помогут при разработке собственных конфигураций. Пример 1. Допустим файл указанный в директиве SSLCACertificateFile содержит несколько доверенных сертификатов (см. описание директивы SSLCACertificateFile). Требуется разрешить доступ до защищенной области только владельцам сертификатов, подписанных только одним из поставщиков. <Directory /path/to/secure/area/> SSLVerifyClient require SSLRequire %{SSL_CLIENT_I_DN_O} eq "First CA Inc." </Directory> Описание директив:
Пример 2. Предположим требуется разрешить доступ до защищенной области владельцам сертификатов со слишком разными данными, настолько, что их сложно описать с помощью директивы SSLRequire. В этом случае полезно использовать метод, основанный на имитации простой авторизации веб-сервером по паролю. <Directory /path/to/secure/area/> SSLVerifyClient require SSLOptions +FakeBasicAuth AuthName "My secure area" AuthType Basic AuthUserFile /path/to/passwd/file require valid-user </Directory> Содержимое файла /path/to/passwd/file /C=RU/L=Msk/O=My Inc./CN=user/emailAddress=user@domain.ru:xxj31ZMTZzkVA /C=RU/L=Sam/O=My LTD./CN=vas/emailAddress=vas@domain.ru:xxj31ZMTZzkVA /C=RU/L=Zel/O=My LLC./CN=prs/emailAddress=prs@domain.ru:xxj31ZMTZzkVA ........ Описание директив:
$4. Отзыв сертификатов.Результат проверки веб-сервером клиентского сертификата будет успешным на весь срок действия сертификата. Возникает вопрос, что делать в случае если вы хотите отказать какому-либо клиенту в доступе по его клиентскому сертификату. Для решения этой проблемы создается список отзыва сертификатов (Certificate Revocation List - CRL). В списке отзыва перечисляются отозванные вами клиентские сертификаты. В соответсвии с этим списком веб-сервер будет отклонять запросы если сертифкат клиента отозван. $4.1. Создание списка отзыва (CRL).При создании списка отзыва используется тот же конфигурационный файл и таже структура файлов, что и при подписи сертификатов (см. $2.1.), поэтому при выполнении следующей команды вы должны находиться в том же каталоге. # openssl ca -gencrl -config ca.config -out ca.crl Описание аргументов:
В результате будет создан список отзыва, основанный на базе данных подписанных сертификатах db/index.txt. Так как на данный момент ни один из сертификатов в базе данных не помечен как отозванный, то созданный список будет пустым. Просмотреть данные списка отзыва вы можете с помощью следующей команды. # openssl crl -in ca.crl -text -noout Одной из важных черт списка отзыва является его срок действия, указываемый в конфигурационном файле ca.config с помощью директивы default_crl_days. Также альтернативно может быть использована директива default_crl_hours, если вы планируете часто обновлять ваш CRL. Список отзыва должен обновляться не позже истечения срока действия. Для переодического вызова приведенной выше команды можно использовать cron. $4.2. Отзыв сертификата.Для того чтобы отозвать клиентский сертификат необходимо пометить его в базе данных сертификатов db/index.txt как отозванный, тогда при следующем обновлении списка отзыва, этот сертификат будет в него включен. Для пометки сертификата как отозванного используйте приведенную ниже команду. # openssl ca -config ca.config -revoke client01.crt Описание аргументов:
$4.3. Настройка веб-сервераПосле создания списка отзыва сертификатов необходимо дать возможность веб-серверу использовать его. Для этого добавьте приведенную ниже директиву в конфигурационный файл веб-сервера. SSLCARevocationFile /path/to/ca.crl Описание директив:
Не забывайте перезапускать веб-сервер после каждого изменения его конфигурации. # apachectl restart Заключение.Вышеизложенный материал можно дополнять и углублять, цель статьи - минимальное руководство по реализации авторизации по клиентским сертификатам на практике. Любой читатель, имеющий доступ к использовавшемуся программному обеспечению, с помощью этой статьи может за короткое время настроить свой веб-сервер для решения этой задачи. Каждый из изложенных пунктов можно расширить и написать по нему отдельную статью, заинтересовавшиеся читатели могут получить дополнительные сведения в документации по Apache, mod_ssl и openssl. В заключение хочется дать несколько советов по программной реализации вышеописанных процессов. В openssl не предусмотрен механизм блокирования одновременного доступа к ресурсам, то есть, если две программы одновременно будут осуществлять подпись сертификата, то корректность содержимого текстовой базы данных, файла с серийным номером, как впрочем и самого результата не гарантируется. Поэтому необходимо использовать внешний механизм блокировки, например, так это можно реализовать на языке Perl. open ( LOCK, ">/tmp/cert-sign.lck" ) or error_handling(); flock ( LOCK, 2 ) or error_handling(); # ... код, реализующий подпись сертификата ... close( LOCK ); Описанный метод чрезвычайно прост: ставится блокировка на временный файл, выполняются критические действия, снимается блокировка с файла. Если во всех программах, работающих с вашими файлами придерживаться этого метода, то они не смогут в критические моменты вмешиваться в процесс, а будут ждать снятия блокировки. Второй совет связан с извлечением и обработкой данных клиентских сертификатов в CGI-скриптах. При простой авторизации клиента по имени и паролю веб-сервер помещает имя пользователя в переменную окружения REMOTE_USER. Аналогичным образом из переменных окружения можно извлечь данные клиентского сертификата при авторизации по сертификату. Для того чтобы веб-сервер устанавливал значения переменных окружения, относящихся к клиентскому сертификату необходимо добавить в конфигурацию веб-сервера следующую директиву: SSLOptions +StdEnvVars +ExportCertData Описание директив:
По умолчанию установка переменных окружения, относящихся к SSL, отключена, так как их извлечение из сертификатов влечет за собой снижение быстродействия веб-сервера. Поэтому следует добавлять эти опции только в случае реальной необходимости. Альтернативой переменной REMOTE_USER могут служить следующие переменные: SSL_CLIENT_M_SERIAL - серийный номер клиентского сертификата, SSL_CLIENT_S_DN_CN - имя сертификата (Common Name) или SSL_CLIENT_S_DN - данные сертификата (Subject Name, см. описание аргумента -subj в $1). Если вы хотите использовать переменную SSL_CLIENT_S_DN_CN для идентификации пользователя, то вы должны обеспечить уникальность Common Name для разных сертификатов при создании запросов на клиентский сертификат (см. $2.2.). Уникальность SSL_CLIENT_M_SERIAL и SSL_CLIENT_S_DN гарантируется автоматически при подписи сертификатов. |