Нестрогая авторизация по клиентскому сертификату в Apache

Тема в разделе "Статьи", создана пользователем ma5ter, 25 окт 2011.

  1. ma5ter
    ma5ter Новичок
    Симпатии:
    2
    Задача: обеспечить проверку сертификатов только в некоторых областях сайта. То есть необходимо защищать приватные части сайта пользовательским сертификатом, например личные кабинеты, а остальные делать доступными публично или смешивать одно с другим в произвольных пропорциях.

    Однако, существующая реализация авторизации по сертификату (в связи с установкой патча ssl связанного с уязвимостью session renegotiation) не позволяет ставить SSLVerifyClient required на отдельные директории/файлы. Года полтора-два назад я бился над этим и нашел простое решение (данное решение, правда не так развернуто, постил в forums.gentoo.org) сейчас опять пришлось пройти этим путем и освежить память, а посему кидаю сюда последовательность действий.

    1. Ставим 2-й Апач. Скорее всего вместе с установкой встанут дефолтный ssl-вхост и его сертификат/ключ. Описание вхостов находится обычно здесь /etc/apache2/vhosts.d, по дефолту имеется 00_default_ssl_vhost.conf, можно создать новый, можно использовать дефолтный (если не планируется серьезный вхостинг), в него уже прописан сертификат и ключ. Толку от них чуть, так что смотрим пути и выносим их:
    Код:
    rm /etc/ssl/apache2/server.crt
    rm /etc/ssl/apache2/server.key
    2. Заодно надо раскомментить/поправить строчку для корневого сертификата, в итоге все должно выглядеть как-то так:
    Код:
    SSLCACertificateFile /etc/ssl/apache2/root.crt
    SSLCertificateFile /etc/ssl/apache2/server.crt
    SSLCertificateKeyFile /etc/ssl/apache2/server.key
    3. Прописываем переменную SLVerifyClient:
    Код:
    SSLVerifyClient optional
    4. Теперь самая главная фишка, задаем дополнительные опции для экспорта параметров ssl в переменные среды, для организации непосредственно авторизации внешними средствами, даю на примере пхп, но применимо к чему угодно:
    Код:
    <FilesMatch "\.php$">
    	SSLRequireSSL #если предполагается только https
    	SSLOptions +StdEnvVars
    </FilesMatch>
    5. С апачем пока все, теперь надо нагенерить ключей и сертификатов для собственно сервера и клиентов. Предполагается что openssl уже давно стоит. Работаем в папке /etc/ssl/apache2
    Код:
    cd /etc/ssl/apache2
    6. Создаем структуру для серийных номеров:
    Код:
    echo "01" > root.srl
    7.Создаём ключ корневого сертификата:
    Код:
    openssl genrsa -des3 -out root.key 1024
    когда спросит пароль ставим пароль и запоминаем его.

    8. Создаём самоподписанный корневой сертификат
    Код:
    openssl req -new -x509 -days 3653 -key root.key -out root.crt
    9. Создаём ключ сертификата вебсервера и запрос на подписание одной командой:
    Код:
    openssl req -new -newkey rsa:1024 -nodes -keyout server.key -subj /C=RU/ST=Moscow/L=Moscow/O=ma5ter/OU="homeserver"/CN="superserver" -out server.csr
    10. Подписываем запрос сертификата сервера на 10 лет:
    Код:
    openssl x509 -req -days 3653 -in server.csr -signkey server.key -out server.crt -CA root.crt -CAkey root.key
    11. Перезапускаем апач и проверяем:
    Код:
    openssl s_client -connect localhost:443 -prexit
    12. Выкладываем корневой сертификат (root.crt, можно переименовать) на http без s, чтобы его можно было скачать и установить в браузере, как сертификат доверенного центра.

    13. Для каждого нового клиента создаём ключ сертификата клиента и запрос на подписание:
    Код:
    openssl req -new -newkey rsa:1024 -nodes -keyout client01.key -subj /C=RU/ST=Moscow/L=Moscow/O="ma5ter"/OU="homeserver"/CN="vasya" -out client01.csr
    и подписываем запрос сертификата клиента на 10 лет (конечно можно изменить в days):
    Код:
    openssl x509 -req -days 3653 -in client01.csr -signkey client01.key -out client01.crt -CA root.crt -CAkey root.key
    14. Проверка
    Код:
    openssl verify -verbose -CAfile root.crt -purpose sslclient client01.crt
    14. Упаковываем клиентский сертификат в контейнер и передаем пользователю вместе с паролем на контейнер (указанном в pass):
    Код:
    openssl pkcs12 -export -in client01.crt -inkey client01.key -certfile root.crt -out client01.p12 -passout pass:123
    15. В коде скрипта на уровне переменных среды отлавливаем SSL_CLIENT_* переменные, в частности SSL_CLIENT_VERIFY == SUCCESS, например, для PHP будет выглядеть так: $_SERVER["SSL_CLIENT_S_DN_CN"] == ma5ter

    PS. Список экспортируемых переменных:
     
    Последнее редактирование: 25 окт 2011
    25 окт 2011
    2 пользователям это понравилось.
Загрузка...