Блог Ерёмина Андрея обо всём на свете…

Posts tagged ‘Communication Theory’

Используем сертификаты x.509 в apache


Была у меня на работе задачка — сделать авторизацию пользователей на сайте через сертификаты X.509. Вроде бы, всё просто – погуглил, почитал, оказалось, десятки разных статей и все противоречат друг другу.

Создание сертификатов

Первое, что сделаем, это создадим серверный и клиентские сертификаты. Нужна програмка openssl.exe (у меня установлен xampp, в нём есть всё, что нужно – вам его тоже советую). Итак, в папке /сервер/apache/bin находим openssl.exe и создаём файлы ca.config и openssl.cnf. Также, создадим папку db, а в ней папки certs, newcerts, пустые текстовые файлы index.txt и serial (внутри этого файла написать “01” без ковычек.)

Содержимое файла 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        # ……

Содержимое файла openssl.cnf

# =================================================
# OpenSSL configuration file
# =================================================
RANDFILE         = .rnd
[ ca ]
default_ca       = CA_default
[ CA_default ]
dir              = .
certs            = $dir
new_certs_dir    = $dir
crl_dir          = $dir
database         = $dir/db/index.txt
private_key      = $dir/ca.key
certificate      = $dir/ca.crt
serial           = $dir/db/serial
crl              = $dir/crl.pem
RANDFILE         = $dir/db/private/.rand
default_days     = 365
default_crl_days = 30
default_md       = sha1
preserve         = no
policy           = policy_anything
name_opt         = ca_default
cert_opt         = ca_default
[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional
[ req ]
default_bits            = 1024
default_md              = sha1
default_keyfile         = privkey.pem
distinguished_name      = req_distinguished_name
x509_extensions         = v3_ca
string_mask             = nombstr
[ req_distinguished_name ]
countryName             = Country Name (2 letter code)
countryName_min         = 2
countryName_max         = 2
stateOrProvinceName     = State or Province Name (full name)
localityName            = Locality Name (eg, city)
0.organizationName      = Organization Name (eg, company)
organizationalUnitName  = Organizational Unit Name (eg, section)
commonName              = Common Name (eg, YOUR name)
commonName_max          = 64
emailAddress            = Email Address
emailAddress_max        = 64
[ usr_cert ]
basicConstraints        = CA:FALSE
# nsCaRevocationUrl       = https://url-to-exposed-clr-list/crl.pem
[ ssl_server ]
basicConstraints        = CA:FALSE
nsCertType              = server
keyUsage                = digitalSignature, keyEncipherment
extendedKeyUsage        = serverAuth, nsSGC, msSGC
nsComment               = «OpenSSL Certificate for SSL Web Server»
[ ssl_client ]
basicConstraints        = CA:FALSE
nsCertType              = client
keyUsage                = digitalSignature, keyEncipherment
extendedKeyUsage        = clientAuth
nsComment               = «OpenSSL Certificate for SSL Client»
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage         = nonRepudiation, digitalSignature, keyEncipherment
[ v3_ca ]
basicConstraints        = critical, CA:true, pathlen:0
nsCertType              = sslCA
keyUsage                = cRLSign, keyCertSign
extendedKeyUsage        = serverAuth, clientAuth
nsComment               = «OpenSSL CA Certificate»
[ crl_ext ]
basicConstraints        = CA:FALSE
keyUsage                = digitalSignature, keyEncipherment
nsComment               = «OpenSSL generated CRL»

открываем cmd.exe (Пуск –> Выполнить –> cmd –> enter), далее запускаем через cmd программу openssl.exe и приступаем непосредственно к созданию наших сертификатов.

1) создаём серверный ключ и сертификат

req -new -x509 -days 365 -sha1 -newkey rsa:1024 -nodes -keyout server.key -out server.crt -subj ‘/O=НазваниеКомпании/OU=Подразделение/CN=localhost’

Укажите здесь название вашей компании, подразделения, а также доменное имя.

2) создаём CA сертификат для авторизации пользователей

req  -config openssl.cnf  -new  -x509  -days 3652  -sha1  -newkey rsa:1024  -keyout ca.key  -out ca.crt -subj ‘/O=Организация/OU=Подразделение’

Укажите здесь название вашей компании, подразделения.

3) создаём пользовательские сертификаты

  • req -new -sha1 -newkey rsa:1024 -nodes -keyout server.key -out request.pem -subj ‘/O=Skif Grid/OU=PSI RAS/CN=localhost’
  • ca -config openssl.cnf -policy policy_anything -extensions ssl_server -out signed.pem -infiles request.pem
  • x509 -in signed.pem -out server.crt
  • openssl pkcs12 -export –in signed.pem –inkey server.key -certfile ca.crt -name «Имя\Отчество» -out user.p12

Получившееся ca.crt и user.p12 импортируем в браузер. С сертификатами покончено, теперь пришло время Apach’a.

Настройка Apache

Открываем файл /сервер/apache/conf/extra/httpd-ssl.conf, стираем всё, что там есть и копируем туда следующее:

ErrorLog    D:/www/apache/logs/ssl_error.log
LogLevel warn

Listen 443

AddType application/x-x509-ca-cert .crt .pem
AddType application/x-pkcs7-crl    .crl
AddType application/x-pkcs12-cert  .p12

SSLPassPhraseDialog  builtin
SSLSessionCache         dbm:logs/ssl.scache
SSLSessionCacheTimeout  300
SSLMutex  default
SSLOptions +StdEnvVars +ExportCertData +StrictRequire

NameVirtualHost *:443

<VirtualHost _default_:443>

AddDefaultCharset utf-8
AddCharset utf-8 *

DocumentRoot «D:/www/htdocs»
ServerName http://www.youhost.ru:443
ServerAdmin admin@nocrash.ru.ru
ErrorLog D:/www/apache/logs/ssl_error1.log

SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLProtocol all -SSLv2
SSLOptions +StdEnvVars +ExportCertData

SSLCertificateFile conf/ssl/server.crt
SSLCertificateKeyFile conf/ssl/server.key
SSLCACertificateFile conf/ssl/ca/ca.crt

SSLVerifyClient require
SSLVerifyDepth 1

SSLProxyEngine off

<Location />

</Location>
SetEnvIf User-Agent ..*MSIE.*. nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
</VirtualHost>

Если мы хотим сделать авторизацию не обязательной (скажем, чтобы, если у пользователя не будет сертификата, то показать ему красивую страничку с надписью, скажем – получите сначала сертификат), то SSLVerifyClient поставьте как optional.

В папке /сервер/apache/conf/ создадим папку ssl. В неё скопируем созданные нами чуть раньше файлы server.crt, server.key, ca.crt

Проверяем

Если сервер был запущен – перезапустите его. Создадим простенькую страничку на php со следующем кодом:

<?
echo “<pre>”;
print_r($_SERVER);
echo “</pre>”;
?>

Сохраним, и зайдём на неё через https, т.е, скажем так: https://localhost/ssl_try.php

¦С¦¦¦¬TЛ¦-TП¦-¦-TЛ¦¦

Браузер должен показать вам окно выбора сертификата. Если SSLVerifyClient установлен как require, то при неправильном сертификате браузер выдаст вам страницу с ошибкой.

Если же всё прошло хорошо, то мы увидим нашу страницу со всеми серверными переменными, включая SSL_CLIENT_CERT, в котором хранится клиентский сертификат (из неё же можно будет вытащить, при необходимости, нужные нам данные – имя, организация, email  и т.д.)

2

Полезные ссылки

  1. OpenSSL Functions
  2. X.509 PKI LOGIN WITH PHP AND APACHE
  3. Client certificates with apache
  4. Авторизация с помощью клиентских SSL сертификатов.

Облако меток