WordPress HTTPS

WordPress HTTPS — усиливаем защиту с помощью Security Headers и включаем для сайта HSTS, который сразу скажет браузеру использовать HTTPS.

В прошлый раз в статье SSL сертификат для сайта говорил как перевести сайт с HTTP на HTTPS. Краткая выжимка (содержание первой серии):

  • Сертификат не покупаем, пользуемся бесплатным Let's Encrypt;
  • Для автоматического обновления сертификата, который действует всего 3 месяца, используем возможности хостера;

Скорее всего тут есть разные варианты, мой хостер предлагает cPanel и тут такое есть:

Wordpress HTTPS

  • Поскольку получаются 2 версии сайта: HTTP и HTTPS, то нужно включить принудительный редирект 301 на HTTPS. Использовал для этого плагин Really Simple SSL.

Security Headers

Читатель открывает сайт как HTTP и мы его перенаправляем. А можно сразу как-то передать информацию, что сайт использует только HTTPS, ещё на этапе открытия? Да, поможет заголовок безопасности Strict-Transport-Security.

Посмотреть установлен ли этот заголовок и другие, и какие именно, можно здесь. А установить с помощью плагина GD Security Headers. Со страницы плагина:

The plugin can add all the generated headers into HTACCESS file (for Apache web servers), and they will be applied to all files, not just WordPress generated content. If your website is not using Apache (or .HTACCESS), all rules are generated with each page request and will work with any server type.

Поскольку мой хостер использует Apache, то отказался от плагина и прописал директивы вручную в .htaccess.

# Security Headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin"

Это на мой взгляд оптимальный набор заголовков. Permissions-Policy не особо нужен:

The Permissions-Policy HTTP header replaces the existing Feature-Policy header for controlling delegation of permissions and powerful features

Он может, допустим, отключить у пользователей камеру или геолокацию. Возможно приверну позже, пока не знаю в связи с чем его использовать.

Content-Security-Policy требует понимания и тонкой настройки, иначе нарушит работу сайта в плане отображения отдельных элементов. Возможно тоже позже.

После чего получил циклическую перезагрузку и неработоспособный сайт. Виноват оказался плагин Really Simple SSL. Удалил его и какое-то время сайт перенаправлял только за счёт Strict-Transport-Security. И это работает. Совместимость браузеров:

Wordpress HTTPS

Единичные заходы по HTTP видел в Я.Метрике с Android Browser (кто-то ещё им пользуется..?). Это и есть HSTS, теперь подробнее.

Технология HSTS

Было уже немало камней: что ты ... мне насоветовал? Поэтому, в частности, убрал с сайта все материалы по работе с жёсткими дисками. Прежде чем делать как тут сказано, включи мозги, пожалуйста. Сайт не сможет открываться по HTTP (совсем, никак, без исключений), не только в Хроме, но и в большинстве других браузеров.

This is a list of sites that are hardcoded into Chrome as being HTTPS only.

Most major browsers (Chrome, Firefox, Opera, Safari, IE 11 and Edge) also have HSTS preload lists based on the Chrome list.

HSTS (HTTP Strict Transport Security) использует одноимённый заголовок для работы. В общем-то сделанного ранее уже вполне достаточно. Но тут есть особый вариант использования, с параметром preload.

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

Идём сюда, и проверяем свой сайт. Должен быть включен редирект 301 на HTTPS. Подобрал рабочий вариант без зацикливания здесь (внизу страницы).

# Редирект http в https
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

Снова проверяю, ошибка Warning: Unnecessary HSTS header over HTTP.

Wordpress HTTPS

Исправляем заголовок на (только для HTTPS):

Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS

Ошибка уходит:

Wordpress HTTPS

Добавление сайта в preload list займёт какое-то время, после чего он будет доступен только по HTTPS.

Ещё полезности

Поскольку статьи про сайт пишу очень редко, то выложу тут несколько простых способов причесать свой сайт с помощью cPanel и не только.

  • Включить сжатие GZIP;

Выбрать Сжать все содержимое, проверить тут.

  • Включить защиту от хотлинкинга;

Ушлые люди встраивают в свой сайт картинки с твоего сайта. Чтобы этого не было. Настройки добавляются в .htaccess, важно их не снести при правке этого файла, для этого лучше добавить комментарий.

  • Проверять использование ресурсов;

Периодически смотреть этот раздел и если сайт постоянно зашкаливает по CPU и/или PHP-запросам, значит плагины. Что-то неправильно настроено или конфликтует. Вообще плагинов должно быть минимальное количество.

Так при очередной ревизии сократил количество плагинов с 20 до 17, а затем до 14. А ведь вроде всё нужное было, оказывается нет.. Потестирую, возможно получится снести ещё 2-3. Сайту стало "легче дышать" прям на глаз, без всяких замеров. А вот как раз инструмент для замера.

  • Версия PHP;

Для оптимальной скорости работы включить 7.4 версию PHP и все расширения, которые рекомендует WordPress на вкладке здоровья сайта.

  • Проверить сайт на скорость загрузки;

Можно тут, лучший бесплатный плагин кеширования WP Super Cache, настройка здесь.

  • Убираем fbclid

Умные ребята с Фейсбука решили при переходе на внешние ссылки навешивать id, из-за чего получаются дубли страниц. Решаем через .htaccess:

# Убрать fbclid
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} ^fbclid
RewriteRule ^(.*)$ /$1? [R=301,L]
</IfModule

Updated 10.04.2021 — Content Security Policy (CSP)

Решил таки настроить заголовок CSP. В чём тут смысл? Запретить подгрузку на сайт содержимого из недоверенных источников. Таким образом осуществляется защита от межсайтового скриптинга (XSS).

Допустим компьютер пользователя заражён. Какую бы страничку он ни открыл, подгружается реклама типа "азино три топора" и происходят редиректы на всякий левак. Этот пользователь заходит на твой сайт и.. CSP успешно блокирует всё это безобразие. Штука поэтому полезная. И не только для такой ситуации.

Но как уже говорил, есть сложность, CSP требует кропотливой настройки. Почему? Сайт подгружает данные из десятков источников. Тут скрипты, стили, шрифты, картинки и фреймы. И всё это нужно в явном виде разрешить.

Настроил где-то часа за полтора, но вообще эта штука бесконечная. Постоянно обнаруживается что ещё что-то заблокировано и требует разблокировки.

Непосредственно настройка

Теперь как это сделать. Открываем главную страницу нашего сайта. Как уже говорил выше для Apache в .htaccess пишем директиву:

Header add Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; connect-src 'self' 'unsafe-inline'; img-src *; style-src 'self' 'unsafe-inline'; font-src 'self' 'unsafe-inline'; frame-src 'self' 'unsafe-inline'"

У нас здесь определены внешние группы: default-src, script-src, connect-src, img-src, style-src, font-src, frame-src. По названию группы понятно для чего она нужна. В каждой группе пока разрешён тольно наш сайт как источник данных с помощью параметра 'self'. Кроме источника картинок:

img-src *; - тут разрешаем всё, так как картинки никак не могут сайту навредить, а правильно прописать все возможные источники картинок стало бы адовым занятием 

Теперь ещё раз открываем главную страницу на новой вкладке, сравниваем с тем что было. И видим что буквально всё развалилось. Нажимаем Ctrl-Shift-C, открывается панель разработчика, ставим горизонтальное отображение, так удобнее и не сжимает сайт по ширине:

Переходим на вкладку Console и смотрим. Тут весьма подробно написано что именно заблокировано и в какой внешней группе нашего заголовка следует прописать URL сурса:

В данном примере ошибка подсказывает, что в группе style-src нужно прописать c0.wp.com. Прописываем как *.wp.com после параметра 'unsafe-inline'. Синтаксис подробно рассказан в нете, заострять на нём внимание не буду. В основном будет так:

..-src 'self' 'unsafe-inline' список_сайтов через пробел;

Сначала разрешаем заблокированные источники для главной страницы, потом переходим на записи и тоже смотрим. Затем смотрим в админке. Да, тут тоже многое нужно разрешить. В частности у меня была заблокирована галерея медиафайлов и работа некоторых плагинов.

Что получилось

В результате получилось следующее:

Header add Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.yandex.ru yastatic.net *.wp.com translate.google.com translate.googleapis.com *.facebook.com *.gravatar.com; connect-src 'self' 'unsafe-inline' *.yandex.ru yandex.ru translate.googleapis.com yoast.com; img-src data: *; style-src 'self' 'unsafe-inline' fonts.gstatic.com *.googleapis.com *.wp.com *.gravatar.com; font-src 'self' data: 'unsafe-inline' fonts.gstatic.com fonts.googleapis.com *.wp.com; frame-src 'self' 'unsafe-inline' yastatic.net *.wp.com https://yastatic.net *.wordpress.com"

Не утверждаю что это идеальный заголовок CSP и что тут нет ошибок. Но 99% функционала сайта работает с таким заголовком. Хочу обратить внимание что 2 раза встречается data: — такой параметр нигде не описан, но запускает функционал только он.

Практически сразу после настройки CSP отказался от загрузки гугл шрифтов при открытии страницы, разместив их непосредственно на сайте. Поэтому заголовок CSP тоже нужно проредить:

Header add Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' *.yandex.ru yastatic.net *.wp.com translate.google.com translate.googleapis.com *.facebook.com *.gravatar.com; connect-src 'self' 'unsafe-inline' *.yandex.ru yandex.ru translate.googleapis.com yoast.com; img-src data: *; style-src 'self' 'unsafe-inline' *.googleapis.com *.wp.com *.gravatar.com; font-src 'self' data: 'unsafe-inline' *.wp.com; frame-src 'self' 'unsafe-inline' yastatic.net *.wp.com https://yastatic.net *.wordpress.com"

Конечно в дальнейшем будут всплывать ещё источники, требующие разблокировки. Так что это не конечный вариант.

Добавить комментарий