Перейти к содержанию

Ваш CDN дописывает теги в вашу разметку: как это проверить и где выключается у Cloudflare

Опубликовано
  • Админы
Сторонний скрипт на сайте без JavaScript
Тега нет в репозитории, но в браузер он приходит

Бывает расхождение, которое не ловится ни code review, ни аудитом зависимостей: в системе контроля версий лежит одно, а посетитель получает другое. Никакого взлома, никакой подмены DNS, никакого зловреда в сборке — между сервером и читателем просто стоит прокси, у которого есть техническая возможность править разметку на лету.

Классическая иллюстрация всплыла на днях: у владельца сайта, где вообще не используется JavaScript, в исходном коде страницы обнаружился чужой <script> с домена Cloudflare. Обсуждение получилось шумным, а мнения разделились надвое — «у меня ровно то же» против «это известное поведение прокси, вы сами его включили».

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

Как выглядит проблема

В отдаваемом браузеру HTML перед закрывающим </body> появляется тег, отсутствующий в исходниках проекта:

<script defer src="https://static.cloudflareinsights.com/beacon.min.js"
        data-cf-beacon='{"token":"..."}'></script>

Обнаруживают его обычно не глазами, а по косвенным признакам: в консоли браузера с активной усиленной защитой от отслеживания появляется Cross-Origin Request Blocked, а при жёсткой политике безопасности контента скрипт блокируется с соответствующей ошибкой. В подробном разборе на burgeonlab описан характерный случай: скрипт присутствовал на двух доменах из трёх примерно пять месяцев, и заметили его только из-за этих ошибок.

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

curl -sL https://example.com | grep -o 'cloudflareinsights[^"]*'

Откуда он берётся

Виновник — Cloudflare Web Analytics, она же система RUM. Раздел документации Enabling Cloudflare Web Analytics формулирует это без обиняков: для проксируемых через Cloudflare сайтов автоматическая установка активна изначально, и beacon-скрипт добавляется без участия владельца. Масштаб уточняет FAQ: автоматический режим «вставляет JS-сниппет на всех страницах (поддоменах) в пределах зоны».

❗ Главное

Здесь важна поправка, которая теряется в громких пересказах: причина не в переезде NS-серверов как таковом. Дописать что-либо в ответ можно только там, где Cloudflare завершает TLS-соединение и физически держит тело ответа, — то есть при включённом «оранжевом облаке» (Proxied) у DNS-записи. В режиме DNS only клиент получает адрес вашего сервера напрямую, трафик идёт мимо инфраструктуры Cloudflare, и вмешательство исключено.

Смешение возникает по простой причине: при подключении домена проксируемый режим предлагается по умолчанию, так что «я поменял NS» и «я включил прокси» для большинства случаются одним действием.

Два режима записи в DNS Cloudflare
Схема на основе документации developers.cloudflare.com — разделы Web Analytics и DNS proxy status

Соседи по разметке

Если уж речь о правке HTML на границе, полезно знать весь набор функций, способных туда вмешаться. Все они описаны в документации и все отключаются, но состояние по умолчанию у них разное — и это как раз то, что чаще всего застаёт врасплох:

ФункцияЧто делает с HTMLВключено по умолчанию
Web Analytics (RUM)вставляет beacon.min.js перед </body>да, для проксируемых зон
Email Address Obfuscationзаменяет адреса почты и подключает email-decode.min.jsда, «автоматически при регистрации»
Rocket Loaderпереписывает теги <script>, откладывая исполнение JSнет, включается вручную

📌 Заметка

Обфускация почты недооценена сильнее прочего. Дело не в подключаемом скрипте, а в том, что функция меняет саму разметку: почтовый адрес превращается в <a href="/cdn-cgi/l/email-protection#...">. Если контакты со страницы разбирает внешний сервис или проверяет автотест, вот вам объяснение, почему локально всё зелёное, а на боевом домене — нет.

Как это выключить

Настройка живёт на уровне аккаунта, а не отдельной зоны, — поэтому её и не находят там, где обычно ищут:

✅ Как правильно

  1. откройте панель Cloudflare на уровне аккаунта, а не конкретного сайта;
  2. перейдите в Analytics & Logs → Web Analytics;
  3. напротив нужного домена нажмите Manage site;
  4. выберите режим и подтвердите кнопкой Update.

Документация описывает три режима:

  • Enable — вставка активна; отдельным вариантом идёт исключение посетителей из ЕС;
  • Enable with JS Snippet installation — автоматической вставки нет, сниппет устанавливается вручную;
  • Disable — вставки не происходит.

Есть обходной путь через кэш-политику: по документации автоматическая вставка не срабатывает, когда origin присылает заголовок Cache-Control: public, no-transform — прокси в этом случае не вправе трогать полезную нагрузку. Приём работает, но менять кэш-политику целого сайта ради одного скрипта — сомнительный размен. Крайняя мера — перевести запись в DNS only, однако вместе с проксированием исчезнут WAF, кэширование и защита от DDoS, то есть ровно то, ради чего Cloudflare обычно и подключают.

⚠️ Осторожно

Строгая политика безопасности контента почти наверняка вступит в конфликт. Документация Cloudflare требует: при автоматической вставке в connect-src должно быть 'self' (данные уходят на тот же домен), при ручной — в connect-src нужен cloudflareinsights.com, а в script-srchttps://static.cloudflareinsights.com/beacon.min.js. Иначе говоря, придётся выбирать между ошибками в консоли и ослабленной политикой; промежуточного варианта нет.

🔒 Безопасность

Юридическая сторона галочкой не закрывается. Когда сайт обслуживает посетителей из ЕС, а баннер согласия составлялся под известный перечень скриптов, скрипт, появившийся без ведома владельца, в этот перечень не попал. У Cloudflare есть режим «Enable, excluding visitor data in the EU», и в спорной ситуации компромиссом чаще оказывается именно он, а не полное отключение, — своя аналитика при этом продолжает работать. Но контроль за тем, что уходит со страниц, остаётся обязанностью владельца сайта: прокси эту задачу не решает.

В чём тут собственно новость

Строго говоря — ни в чём, кроме количества удивлённых. Поведение задокументировано публично, выключается за четыре клика, багом и уязвимостью не является. Показательно другое: модель «по умолчанию включено, отключайте сами», применённая на инфраструктурном уровне, остаётся невидимой почти для всех, кроме тех немногих, кто периодически смотрит в исходник собственной страницы.

Отсюда обобщение, годное для любого посредника между вашим сервером и читателем: после смены хостинга, CDN или тарифного плана имеет смысл один раз сличить вывод curl по своему домену с тем, что лежит в репозитории. Занимает секунды, а результат порой удивляет.

Источники

💬 Вопрос к сообществу

Проверьте свои домены — любопытно, у скольких beacon висит не первый год. И вопрос по существу: где для вас граница дозволенного для CDN? Отложить исполнение <script> ради скорости — приемлемо, а добавить собственный тег — уже нет? Или раз вы отдали посреднику ключи от TLS, разницы никакой?

Featured Replies

No posts to show

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

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

Последние посетители 0

  • Ни одного зарегистрированного пользователя не просматривает данную страницу
Яндекс.Метрика

Account

Navigation

Поиск

Поиск

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.