Защита сайта при помощи HTTP Public Key Pinning (HPKP)
Данная технология призвана защитить посетителя вашего сайта от атаки типа MITM (Man in the middle, человек посередине). Иными словами посетитель может быть уверен, что данные, которые он получает, исходят с вашего сайта, а не с какого-то другого.
Суть технологии состоит в создании публичного ключа на основе сертификата, который установлен на вашем сайте. Соответственно, чтобы она работала, требуется валидный сертификат. Впрочем, она будет работать и на самоподписанных (self-signed) сертификатах. Полученный на основе вашего сертификата ключ добавляется в заголовок ответа вашего сервера, после чего браузер сравнивает полученный ключ с тем, который он вычисляет после получения данных о вашем сертификате.
Итак, что нам требуется:
- Какой-либо установленный для сайта сертификат.
- Консоль для получения публичного ключа.
Кстати, не так давно для нормального функционирования этой технологии требовался всего лишь один ключ, сейчас же нужно указывать два или более ключей. На мой взгляд двух будет достаточно, от этого и будем отталкиваться. Второй ключ является «резервным», этот момент я не совсем понимаю, но не будем отступать от требований.
Действовал я по следующей схеме:
- — получаем сертификат на сайте Let’s Encrypt для двух сайтов: example.com и www.example.com;
- — так как я использую вариант без www, то ключ, полученный на базе первого будет основным, на базе второго — резервным;
- — генерируем ключи для обоих сертификатов;
- — добавляем нужные инструкции в файл /etc/httpd2/conf/sites-available/default-http.conf.
О получении сертификата рассказывать не буду, достаточно почитать главную страницу сайта. Допустим, вы его получили и установили на свой сайт. Теперь требуется создать ключи при помощи следующей команды:
openssl x509 -noout -in certificate.pem -pubkey | openssl rsa -pubin -outform der | \
openssl dgst -sha256 -binary | base64
где certificate.pem — полный путь к сертфикату.
После выполнения команды вы получите нечто подобное:
LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=
Это и есть нужный вам ключ. Повторяем команду для второго сертификата и добавляем данные в файл конфигурации сайта:
Header set Public-Key-Pins "pin-sha256=\"pin1\"; pin-sha256=\"pin2\"; max-age=time"
где:
- pin1 — основной ключ для данного сайта. В моем случае example.com;
- pin2 — резервный ключ для сайта. То есть www.example.com;
- time — время действия ключа в секундах.
Опциональный параметр includeSubDomains указывает на то, что ключи действительны также для поддоменов. Еще один необязательный параметр report-uri указывает на адрес, куда должны отправляться отчеты об ошибках в формате JSON. Его я, возможно, добавлю на сайт, но пока что считаю его ненужным для себя.
Какие тут есть нюансы? Если вы неправильно настроите HPKP, ваш сайт станет недоступен. Можно также настроить отправку отчетов в случае каких-либо ошибок. Для этого немного меняем заголовок (или просто добавляем еще одной строкой):
Header set Public-Key-Pins-Report-Only "pin-sha256=\"pin1\"; pin-sha256=\"pin2\"; max-age=time"