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"

Идём сюда, и проверяем свой сайт на HSTS preload eligibility. Должен быть включен редирект 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>

В один прекрасный день редирект стал вешать сайт. После каких-то обновлений, после чего был заменён на вот этот:

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

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

Wordpress HTTPS

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

Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS 
- обращаю внимание убрали always. Чтобы было понятно: always всегда, нам не надо всегда, 
а лишь когда HTTPS.

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

Wordpress HTTPS

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


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

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

Полезности для скорости работы
  • Проверить сайт на вирусы;

Сделать это можно штатными средствами хостера (бесплатно или по тарифу) или же внешними средствами.

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

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

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

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

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

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

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

Если что-то можно сделать без плагина, то именно так и стоит поступить. Допустим, как управлять обновлениями? Долгое время у меня стоял тяжеловесный плагин. Всё для того чтобы заблокировать обновления темы. Оказалось нужно всего лишь изменить версию темы в настройках WordPress: Внешний вид - Редактор тем - style.css.

Version: 3.1 - было
Version: 310.0 - стало, помножил версию темы на 100

Всё, тема не будет обновляться. Плагин не нужен. Для контроля обновлений самого WordPress нужна всего 1 строчка в wp-config.php:

define('WP_AUTO_UPDATE_CORE', 'minor');
  • Проверить версию PHP;

Для оптимальной скорости работы включить 7.4 (и выше) версию PHP и все расширения, которые рекомендует WordPress на вкладке здоровья сайта. В 2024 году сайт работает на PHP 8.2, сам WordPress и все мои плагины с этой версией совместимы, всё нравится.

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

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

Прочие полезности
  • Убрать fbclid;

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

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

Если сайт используется давно, то он засоряется неиспользуемыми файлами. Эти файлы остаются после установки/удаления плагинов, обновления самого WordPress и других манипуляций. Также засоряется база данных. Что куда хуже.

Сразу так и не скажешь нужен этот файл или нет. Поэтому есть плагин WPS Cleaner. Всё время его использовать нет нужны. Но разово почистить будет очень хорошо. Предварительно обязательно сделать резервную копию. Силами хостера либо же есть другой очень хороший плагин UpdraftPlus Backup. Настоятельно рекомендую сделать обе копии (и инструментами хостера, и плагином) перед любыми манипуляциями с файлами. И не говори потом что я тебя не предупреждал.

  • Заблокировать опасные адреса.

Обычно хостер какую-то статистику даёт. Посмотреть топ запросов, с каких IP. Затем пробить эти IP по базе. Заблокировать выявленные опасные адреса. Сейчас это можно сделать штатно, в бесплатном FW плагина Jetpack. Поделать так с недельку-две.


Update 10.04.2021 — Content Security Policy (CSP)

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

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

С CSP тот же пользователь заходит на твой сайт и.. 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 (или F12), открывается панель разработчика, ставим горизонтальное отображение, так удобнее и не сжимает сайт по ширине:

Переходим на вкладку 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 *.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 *.yandex.ru yastatic.net *.wp.com translate.google.com translate-pa.googleapis.com translate.googleapis.com *.facebook.com *.facebook.net *.twitter.com *.gravatar.com public-api.wordpress.com api.pinterest.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 code.jquery.com; font-src 'self' data: 'unsafe-inline' *.wp.com fonts.gstatic.com yastatic.net; frame-src 'self' 'unsafe-inline' *.yandex.ru yastatic.net mc.yandex.md *.wp.com *.yastatic.net *.wordpress.com *.twitter.com www.youtube.com yoomoney.ru; media-src 'self' data: strm.yandex.ru strm.yandex.net *.strm.yandex.ru *.strm.yandex.net"

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

В августе 2021 Яндекс прислал письмо, что для правильного отображения их рекламы нужно настроить CSP вот так.

Leave a Comment

Scroll to Top