
Всем приветь!
Часть данного мануала просто перепечатывание старого с адаптацией. Но я пойду дальше и добавлю скрипт, для автоматизации создания ssl сертификатов и их отзывов. Однако и на этом я не остановлюсь и сделаю инструкцию для создания безопасности web-сервера таким образом, чтобы доступ к нему был только у пользователей, имеющих сертификаты.
Для реализации нам понадобится три сервера/виртуальной машины: RootCA — корневой центр сертификации, SubCA — подчиненный/подписывающий центр сертификации, web-сервер — сервер, для которого мы будем подписывать ssl сертификат.
Идем на RootCA и создаем центр сертификации:
cd ~ wget -P ~/ https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz tar xvf EasyRSA-3.0.8.tgz mv ~/EasyRSA-3.0.8 ~/easyrsa-rootca/ cd ~/easyrsa-rootca/ cp vars.example vars vim vars
Находим блок, удалим # и подставим свои значения. Дабы при подписании сертификатов не вводить наши данные мы их пропишем тут (данный блок нужен для того, чтобы в подписанных сертификатах была информация о том кому принадлежат сертификаты):
#set_var EASYRSA_REQ_COUNTRY "US" #set_var EASYRSA_REQ_PROVINCE "California" #set_var EASYRSA_REQ_CITY "San Francisco" #set_var EASYRSA_REQ_ORG "Copyleft Certificate Co" #set_var EASYRSA_REQ_EMAIL "me@example.net" #set_var EASYRSA_REQ_OU "My Organizational Unit"
Далее находим следующие установки, удалим # и редактируем их значения. Эти директивы отвечают за сроки жизни сертификатов (первая — за срок сертификата ЦС, вторая — за срок сертификата, который подписывается, третья — за сертификат с данными об отозванных сертификатах):
#set_var EASYRSA_CA_EXPIRE 3650 #--> 3650 #set_var EASYRSA_CERT_EXPIRE 3650 #--> 1825 #set_var EASYRSA_CRL_DAYS 180
После редактирования файла vars и установки необходимых нам значений создадим ЦС:
./easyrsa init-pki ./easyrsa build-ca nopass
Если будет только один CA (RootCA), то переходим к выпуску сертификатов.
Теперь переходим на SubCA и повторяем те же самые шаги с небольшими изменениями:
cd ~ wget -P ~/ https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz tar xvf EasyRSA-3.0.8.tgz mv ~/EasyRSA-3.0.8 ~/easyrsa-subca/ cd ~/easyrsa-subca/ cp vars.example vars vim vars
Находим блок, удалим # и подставим свои значения:
#set_var EASYRSA_REQ_COUNTRY "US" #set_var EASYRSA_REQ_PROVINCE "California" #set_var EASYRSA_REQ_CITY "San Francisco" #set_var EASYRSA_REQ_ORG "Copyleft Certificate Co" #set_var EASYRSA_REQ_EMAIL "me@example.net" #set_var EASYRSA_REQ_OU "My Organizational Unit"
Далее находим следующие установки, удалим # и редактируем их значения:
#set_var EASYRSA_CA_EXPIRE 3650 #--> 1825 #set_var EASYRSA_CERT_EXPIRE 3650 #--> 365 #set_var EASYRSA_CRL_DAYS 180
Еще раз создадим ЦС и запрос на подпись сертификата и передадим его RootCA:
./easyrsa init-pki ./easyrsa build-ca subca nopass scp pki/reqs/ca.req user@ip_RootCA:/tmp
Возвращаемся на RootCA и подписываем сертификат и передаем его обратно на SubCA, а так же прихватим сертификат RootCA.crt. После этого сервер RootCA нам больше не нужен и в целях безопасности его лучше выключить. Все сертификаты теперь будут выпускаться на подписывающем сервере SubCA:
cd ~/easyrsa-rootca/ ./easyrsa import-req /tmp/ca.req SubCA ./easyrsa sign-req ca SubCA scp pki/issued/SubCA.crt user@ip_SubCA:/tmp scp pki/ca.crt user@ip_SubCA:/tmp/RootCA.crt
Переходим на SubCA и перемещаем подписанный сертификат в ЦС. Дабы в будущем не путаться в сертификатах, оставим имя сертификата SubCA.crt и сделаем на него символьную ссылку:
mv /tmp/SubCA.crt ~/easyrsa-subca/pki/ ln -s ~/easyrsa-subca/pki/SubCA.crt ~/easyrsa-subca/pki/ca.crt
Идем в директорию ЦС и создадим файл Диффи-Хелмана для повышения безопасности web-сервера. Файл Диффи-Хелмана (Diffie-Hellman) необходим для реализации протокола, позволяющего использовать небезопасный канал для получения общего секретного ключа. Этот ключ будет в дальнейшем использоваться для защищенного обмена данными с помощью алгоритмов симметричного шифрования.
cd ~/easyrsa-subca/ ./easyrsa gen-dh
Переходим к финальной части, а именно выпуск ssl сертификата и конфигурация web-сервера:
./easyrsa gen-req your_site_name nopass ./easyrsa sign-req server you_site_name
Создадим директорию для хранения сертификатов, перенесем туда сертификаты и подпишем запрос:
mkdir -p ~/ssl_cert/name_web_server mv pki/dh.pem ~/ssl_cert/name_web_server/ cp pki/SubCA.crt ~/ssl_cert/name_web_server/ cp pki/{issued,private}/your_site_name.* ~/ssl_cert/name_web_server/ sudo rm pki/reqs/your_site_name.req
Для работы сервера нам надо сделать цепочку сертификатов (объединить сертификат your_site_name.crt и SubCA.crt в fullchain.crt):
cat ~/ssl_cert/name_web_server/your_site_name.crt ~/ssl_cert/name_web_server/SubCA.crt > ~/ssl_cert/name_web_server/your_site_name.fullchain.crt
Cертификаты готовы, и нам надо перенести их на web-сервер и указать к ним путь:
sudo chown -R user:user ~/ssl_cert/name_web_server #(optional) scp ~/ssl_cert/name_web_server/*.{crt,key,pem} user@ip_web_server:/tmp
Идем на web-сервер создадим директорию для хранения сертификатов и перенесем их туда:
mkdir ~/ssl_cert/ mkdir ~/ssl_cert/{key,cert} sudo chmod 600 ~/ssl_cert/key/ mv /tmp/*.{crt,pem} ~/ssl_cert/cert/ sudo mv /tmp/*.key ~/ssl_cert/key/
Пропишем пути к сертификатам в Apache2 или Nginx.
sudo vim /etc/nginx/sites-available/your_site_name.com
Находим блок с путями к сертификатам и меняем его:
... listen 443 ssl; ssl_certificate /home/user/ssl_cert/cert/your_site_name.fullchain.crt; ssl_certificate_key /home/user/ssl_cert/key/your_site_name.com.key; ssl_dhparam /home/user/ssl_cert/cert/dh.pem; ...
Перезапускаем web-службу:
systemctl restart nginx
sudo vim /etc/apache2/sites-available/your_site_name.com.conf
Находим блок с путями к сертификатам и меняем его (данная схема подходит для Apache2 версии 2.4.8 и новее):
... SSLCertificateFile /home/user/ssl_cert/cert/your_site_name.fullchain.crt SSLCertificateKeyFile /home/user/ssl_cert/key/your_site_name.key SSLOpenSSLConfCmd DHParameters /home/user/ssl_cert/cert/dh.pem ...
Для Apache2 версии 2.4.7 и ниже объединяем сертификаты и редактируем конфигурацию:
cat /home/user/ssl_cert/cert/your_site_name.fullchain.crt /home/user/ssl_cert/cert/dh.pem > /home/user/ssl_cert/cert/your_site_name.dhfullchain.pem sudo vim /etc/apache2/sites-available/your_site_name.com.conf
... SSLEngine On SSLCertificateFile /home/user/ssl_cert/cert/your_site_name.dhfullchain.pem SSLCertificateKeyFile /home/user/ssl_cert/key/your_site_name.key ...
Перезапускаем web-службу:
systemctl restart apache2
Осталось сделать последний ход: на web-сервере мы разместили самоподписанный сертификат, значит для любого клиента этот сертификат не является надежным и безопасным. Для этого мы должны дать системе корневой сертификат и сказать, что всем сертификатам, которые подписаны этим ЦС и его подчиненными ЦС, мы можем доверять. Для этого мы берем сертификат RootCA.crt отдаем пользователям, которые будут ходить на наш web-сервер и устанавливаем в систему как "доверенные корневые центры сертификации". Теперь у нас все готово и можно работать дальше.
Прежде чем запустить скрипт мы должны создать инфраструктуру для хранения сертификатов и сами скрипты. Данные скрипты мы поместим на сервере SubCA, он у нас подписывающий. Скрипты можно отправить копипастом на сервер или установить git и клонировать репозиторий.
В процессе создания пользовательские сертификаты будут экспортироваться в формат .p12 именно такой формат ключа и нужен пользователя, для доступа к серверу. В процессе экспорта ключа будет запрошена парольная фраза (пароль) и тут есть один нюанс, а именно для windows и linux систем она не обязательна — это на ваше усмотрение, а вот для macOS нужна. Ниже я объясню каким образом наиболее безболезненно установить сертификат на системе macOS, потому что там приходится доставать бубен и исполнять танец дождя.
Установим git и клонируем репозиторий:
apt install git -y git clone https://github.com/dumasti/create_ssl.git mkdir -p ~/ssl_scripts/ssl_certs mv create_ssl/*.sh ssl_scripts/ rm -r create_ssl chmod +x ~/ssl_scripts/*.sh
Если скрипты не клонируем, тогда создадим необходимые директории:
mkdir -p ~/ssl_scripts/ssl_certs touch ~/ssl_scripts/{create_ssl,revoke_ssl}.sh chmod +x ~/ssl_scripts/*.sh
Теперь в файлы запишем сам скрипт:
vim ~/ssl_scripts/create_ssl.sh
#!/bin/bash echo "For whom/for what the certificate? ((S)erver/(U)ser/(C)ancel) " while true; do read -r object=$REPLY if [[ "$object" == "S" ]] || [[ "$object" == "s" ]]; then echo "What is the name of your site? " read -r name=$REPLY break elif [[ "$object" == "U" ]] || [[ "$object" == "u" ]]; then echo "What is the name of your user? " read -r name=$REPLY break elif [[ "$object" == "C" ]] || [[ "$object" == "c" ]]; then exit else echo "Correct answer is S/s/U/u/C/c only!" fi done echo "Which CA to use? " echo `ls ~/ | grep -E -i 'CA|easy|rsa'` read -r ca=$REPLY cd ~/$ca/ echo "How long to sign the certificate (in days)? 365 - 1 year 730 - 2 years 1095 - 3 years 1460 - 4 years 1825 - 5 years " read -r year_new=$REPLY mkdir -p ~/ssl_scripts/ssl_certs/$name year_old=`cat ~/$ca/vars | grep "set_var EASYRSA_CERT_EXPIRE"` sed -i "s/$year_old/set_var EASYRSA_CERT_EXPIRE $year_new/" ~/$ca/vars ./easyrsa gen-req $name nopass if [[ "$object" == "S" ]] || [[ "$object" == "s" ]]; then ./easyrsa sign-req server $name echo "Do you need dh.pem? (y/n)" read -r dh=$REPLY if [[ "$dh" == "y" ]]; then if [ -e pki/dh.pem ]; then mv pki/dh.pem ~/ssl_scripts/ssl_certs/$name else ./easyrsa gen-dh mv pki/dh.pem ~/ssl_scripts/ssl_certs/$name fi fi cp ~/$ca/pki/issued/$name.crt ~/ssl_scripts/ssl_certs/$name cp ~/$ca/pki/RootCA.crt ~/ssl_scripts/ssl_certs/$name cp ~/$ca/pki/private/$name.key ~/ssl_scripts/ssl_certs/$name cat ~/$ca/pki/issued/$name.crt ~/$ca/pki/SubCA.crt > ~/ssl_scripts/ssl_certs/$name/$name.fullchain.crt elif [[ "$object" == "U" ]] || [[ "$object" == "u" ]]; then ./easyrsa sign-req client $name ./easyrsa export-p12 $name cp ~/$ca/pki/issued/$name.crt ~/ssl_scripts/ssl_certs/$name cp ~/$ca/pki/RootCA.crt ~/ssl_scripts/ssl_certs/$name cp ~/$ca/pki/private/$name.{key,p12} ~/ssl_scripts/ssl_certs/$name fi echo "$name `date | cut -d " " -f2,3,4` $ca $year_new $object CREATE" >> ~/ssl_scripts/cert_base cd ~/ssl_scripts/ssl_certs/ tar -cvf $name/$name.tar $name/* tar -czvf $name/$name.tar.gz $name/* whoami=`whoami` sudo chown -R $whoami:$whoami ~/ssl_scripts/ssl_certs/$name/ echo "DONE!"
Хочу отметить тот факт, что хоть скрипт и предлагает подписывать сертификат на 5 лет, но iOS устройства считают такие сертификаты ненадежными и для поддержки таких устройств сертификаты нужно подписывать не больше чем на 3 года.
vim ~/ssl_scripts/revoke_ssl.sh
#!/bin/bash echo "Which CA to use? " echo `ls ~/ | grep -E -i 'CA|easy|rsa'` read -r ca=$REPLY cd ~/$ca/ echo "For whom/for what to revoke the certificate? ((S)erver/(U)ser/(C)ancel) " echo `ls pki/issued/ | cut -d '.' -f 1` read -r name_crt=$REPLY if [ -e ~/ssl_scripts/ssl_certs/revoke ]; then printf "yes" | ./easyrsa revoke $name_crt ./easyrsa gen-crl cp pki/crl.pem ~/ssl_scripts/ssl_certs/revoke/ else mkdir ~/ssl_scripts/ssl_certs/revoke printf "yes" | ./easyrsa revoke $name_crt ./easyrsa gen-crl cp pki/crl.pem ~/ssl_scripts/ssl_certs/revoke/ fi rm ~/$ca/pki/issued/$name_crt.crt rm ~/$ca/pki/private/$name_crt.* rm -r ~/ssl_scripts/ssl_certs/$name_crt echo "$name_crt `date | cut -d " " -f2,3,4` $ca REVOKE" >> ~/ssl_scripts/cert_base echo "DONE!"
Данные скрипты интерактивны, их нужно только запустить, а после отвечать на вопросы.
Бывают такие случаи, когда нужно ограничить доступ к сайту, но не закрывать сервер или сайт от доступа извне (из интернета). В таких случаях можно прибегнуть к простому решению, а именно разрешить доступ на сайт только по пользовательскому ssl сертификату. Сервер его проверит и если все устроит, то пустит пользователя. Выше я уже привел скрипты, которые сами все сделают, вам надо только ответить на вопросы для чего/кого выпускается сертификат и срок "жизни" сертификата. Скрипты заточены под двухуровневую иерархию, а значит будут работать на SubCA. Для тех, кто хочет выпускать сертификаты имея только один центр сертификации приведу тут инструкцию. Она проста: для начала возвращаемся в начало статьи и создаем CA как там (RootCA). Далее мы выпускаем сертификат для веб сервера и, если нужна авторизация пользователей по ssl, клиента:
cd ~/easyrsa-rootca/ ./easyrsa gen-dh ./easyrsa gen-req <FQDN> nopass ./easyrsa sign-req server <FQDN> mkdir -p ~/ssl_cert/<FQDN> cp pki/dh.pem ~/ssl_cert/<FQDN>/ cp pki/private/<FQDN>.key ~/ssl_cert/<FQDN>/ cp pki/issued/<FQDN>.crt ~/ssl_cert/<FQDN>/ # Если нужна авторизация пользователей, то ./easyrsa gen-req <user_name> nopass ./easyrsa sign-req client <user_name> ./easyrsa export-p12 <user_name> mkdir ~/ssl_cert/<user_name> cp pki/private/dara.p12 ~/ssl_cert/<user_name>/ cp pki/ca.crt ~/ssl_cert/{<FQDN>,<user_name>}/RootCA.crt
Далее отправляем серверные сертификаты на сервер, в настройках прописываем к ним пути и перезапускаем веб сервер, а пользовательский сертификат отдаем пользователю, который должен его установить в системе.
Конфигурация для Apache2 и Nginx проста, нам надо только добавить пару строк и прописать путь к сертификату. Приступим:
vim /etc/nginx/sites-available/your_site_name.com
... ssl_client_certificate /home/user/ssl_cert/cert/RootCA.crt; ssl_verify_client on; ssl_verify_depth 1; #ssl_crl /home/user/ssl_cert/cert/crl.pem; # --убрать комментарий для активации отзыва сертификатов ...
Перезапускаем сервис:
systemctl restart nginx

vim /etc/apache2/sites-available/your_site_name.com.conf
... SSLCACertificateFile /home/user/ssl_cert/cert/RootCA.crt #SSLCARevocationFile /home/user/ssl_cert/cert/crl.pem # --убрать комментарий для активации отзыва сертификатов SSLVerifyClient require SSLVerifyDepth 10 ...
Перезапускаем Apache2:
systemctl restart apache2
Настройка авторизации в Windows не отличается от Debian за исключением пути к conf файлу:
C:\Apache24\conf\httpd.conf
Далее прописываем настройка в конце файла и указываем пути к сертификатам:
LoadModule ssl_module modules/mod_ssl.so Listen 443 <VirtualHost *:443> ServerAdmin webmaster@localhost #DocumentRoot "${SRVROOT}/htdocs" DocumentRoot "C:\Apache24\htdocs" ServerName localhost:443 ServerAlias www.localhost:443 ErrorLog "${SRVROOT}/logs/error-ssl.log" TransferLog "${SRVROOT}/logs/access-ssl.log" SSLEngine on SSLCertificateFile "C:\Apache24\localhost\localhost.fullchain.crt" #SSLCertificateFile "C:\Apache24\localhost\localhost.crt" SSLCertificateKeyFile "C:\Apache24\localhost\localhost.key" SSLOpenSSLConfCmd DHParameters "C:\Apache24\localhost\dh.pem" SSLCACertificateFile "C:\Apache24\localhost\RootCA.crt" #SSLCARevocationFile "C:\Apache24\localhost\crl.pem" SSLVerifyClient require SSLVerifyDepth 10 </VirtualHost>
Сохраняем настройки и перезапускаем Apache в PowerShell (запускаем от имени администратора):
c:\Apache24\bin\httpd.exe -k restart
Когда все готово осталось попасть на сайт используя пользовательский ssl сертификат. Выпускаем сертификат используя скрипт выше или своим способом, который не запрещен религией и устанавливаем этот сертификат. Как я уже говорил выше, сертификат можно запаролить при выпуске. Самое главное — сертификат должен быть с расширением .p12.
Сертификат уже на маке? Тогда давайте его установим. Путей может быть несколько: дважды нажимаем на сертификат и вводим его пароль система сама решит в какую связку ключей его добавить, но может случиться так, что ключ будет добавлен в связку от которой постоянно придется вводить пароль — это геморно и я не нашел способа это исправить. Мы пойдем другим путем: открываем "Связка ключей" и правой кнопкой мыши нажимаем на "Связки ключей, созданные пользователем", выбираем "Новая связка ключей..." и задаем имя, а так же место хранения "Keychains", подтверждаем и задаем пароль для новой связки. Следующий шаг — это изменить параметры новой связки ключей для того, что бы не надо было постоянно вводить пароль от связки. Правой кнопкой мыши нажимаем на новую связку и выбираем "Изменить параметры .....", в открывшемся окне ставим галочку в чекбоксе/ах и устанавливаем время простоя, спустя это время система вновь запросит пароль от связки ключей.
Связка готова?
Отлично, тогда импортируем ключ — это можно сделать простым перетаскиванием/перемещением файла ключа.
После того, как сертификат будет установлен в системе при переходе на сайт браузер запросит пользовательский сертификат, мы его выбираем и подтверждаем. Все готово!
Сервера поднимал тут и тут. Еще использую сервера тут, данный хостинг имеет большое разнообразие локаций по приемлемым ценам.
Благодарю за внимание!
Благодарю за редакторские правки Дарью, а так же за проверку и тестирование мануала Станислава.

