В Drupal при использовании мультисайтовой конфигурации (sites/sites.php
) существует скрытая особенность: если домен не найден в $sites
, Drupal по умолчанию загружает настройки из sites/default
. Это может привести к неожиданным проблемам:
- Открытие сайта по IP-адресу;
- Подмена домена в
Host
-заголовке (в том числе в атакующих целях); - Доступ к сайту в неподходящем контексте (на продакшене с тестовым доменом и т.д.);
- Использование кеша с абсолютными ссылками с «чужого домена»;
- и т.д.
К счастью, поведение легко изменить.
Вообще это — частая и недооценённая проблема. Когда Drupal начинает обслуживать сайт по «чужому» домену (например, IP-адресу, левому хосту или поддомену без настройки), он может:
- генерировать абсолютные ссылки (
<link href="http://bad-host/...">
) - создавать кешированные страницы с неправильными
base_url
- вставлять
canonical
,og:url
,hrefLang
и другие теги с неправильным доменом
Всё это приводит к:
- случайному загрязнению кеша (
page cache
,render cache
,dynamic page cache
) — особенно в анонимных сессиях - ошибкам CORS (Cross-Origin Resource Sharing) при загрузке ресурсов (шрифтов, скриптов и т. д.)
- дублированию страниц в поисковой выдаче с «левыми» доменами
- невалидной индексации, особенно если сайт проксируется или тестируется с других хостов
Решение
Решение заключается в жестком контроле разрешенных доменов.
Пример sites/sites.php
с жёстким контролем
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php $sites['test.local'] = 'default'; $sites['example.com'] = 'default'; $sites['www.example.com'] = 'default'; // Получаем текущий хост $host = $_SERVER['HTTP_HOST'] ?? ''; // Если хост не зарегистрирован — прерываем выполнение if (!isset($sites[$host])) { header($_SERVER['SERVER_PROTOCOL'] . ' 403 Forbidden'); echo 'Access denied.'; exit; } return $sites; |
Этот код явно перечисляет допустимые домены, которым разрешён доступ к сайту. Если значение заголовка HTTP_HOST
не найдено в списке, выполнение прерывается и возвращается ошибка 403 Forbidden — это происходит ещё до загрузки ядра Drupal. Таким образом, исключается возможность обращения к сайту через незарегистрированные домены, включая IP-адреса или подставленные имена, и блокируется нежелательный fallback на sites/default
.
Дополнительно:
Если sites/default
не используется — удалите папку её.
Удаление папки sites/default
без дополнительных ограничений может привести к непредсказуемым ошибкам при обращении с незарегистрированного домена. Drupal будет пытаться использовать sites/default
как fallback, и при её отсутствии выдаст фатальную ошибку. Поэтому удаление этой папки имеет смысл только после того, как вы настроили фильтрацию допустимых доменов в sites/sites.php
, и убедились, что sites/default
больше не нужен.
Зачем это нужно
Такая проверка:
- Повышает безопасность;
- Исключает случайные ошибки при деплое;
- Делает мультисайт более предсказуемым;
- Предотвращает «размывание» конфигурации, когда один и тот же сайт начинает открываться с нескольких хостов, не предназначенных для этого.