Что проверить на сайте перед запуском

10 минут

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

Стенд не исчезает — он становится публичным

До запуска сайт живёт удобной жизнью тестового стенда: админка на стандартном адресе, потому что так быстрее; шрифты с чужого CDN, потому что так было в туториале; капча «прикрутим потом», потому что форму всё равно заполняют только свои. Ничто из этого не проблема — ровно до дня, когда стенд объявляют боевым сайтом.

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

Ниже — девять следов тестовой жизни, которые чаще всего уезжают в прод, с симптомом и командой для проверки. Команды рассчитаны на терминал Linux или macOS; в Windows их выполнит WSL или Git Bash. Если вы не запускаетесь, а переезжаете на другой хостинг — это отдельный сюжет, и для него есть отдельный разбор.

1. Тестовые поддомены знают о вас больше, чем главная

Симптом: staging.example.ru открывается любому желающему — со старым кодом, тестовыми данными и админкой без пароля.

Кажется, что тестовый поддомен спрятан: ссылок на него нет, в поиске его нет, адрес знают трое. На деле его имя опубликовано в тот момент, когда на него выпустили сертификат: каждый выпущенный сертификат попадает в открытые журналы Certificate Transparency, и они доступны всем — в том числе тем, кто целенаправленно ищет чужие стенды. Прятать поддомен бессмысленно, его можно только закрыть.

Что о ваших поддоменах знают журналы сертификатов
curl -s "https://crt.sh/?q=%25.example.ru&output=json" \
  | grep -oE '"common_name":"[^"]+"' | sort -u | head -n 20

Ищите в списке dev, staging, test, qa, demo, beta — всё, что не должно быть публичным. Такие окружения обычно защищены хуже боевого: на них редко ставят актуальные обновления и почти никогда не смотрят логи. Правильное состояние тестового стенда — за аутентификацией, списком IP или VPN; выключенный стенд тоже вариант, но тогда снимите с него DNS-запись, чтобы адрес не достался чужому серверу.

2. Админка живёт на /admin, потому что так было удобно

Симптом: страница входа в админку открывается у любого посетителя по адресу, который угадывается с первой попытки.

На стенде стандартный адрес админки был удобен: не надо запоминать, не надо объяснять коллегам. В проде те же свойства работают против вас: боты обходят стандартные пути входа круглосуточно — /admin, /admin/login, /administrator у Joomla, /user/login у Drupal, /bitrix/admin/ у Битрикса, /wp-login.php у WordPress. Открытая страница входа — это не взлом, но это постоянный перебор паролей, и однажды он совпадёт.

Отвечают ли стандартные адреса входа
curl -s -o /dev/null -w '%{http_code} %{url_effective}\n' -L https://example.ru/admin
curl -s -o /dev/null -w '%{http_code} %{url_effective}\n' -L https://example.ru/wp-login.php

Важная оговорка: код 200 сам по себе ничего не доказывает. Одностраничное приложение отвечает 200 на любой путь, отдавая одну и ту же оболочку. Мы считаем админку найденной, только если по адресу отвечает отдельная страница с формой входа — иначе ложная тревога случалась бы на каждом втором современном сайте.

Что делать: закрыть страницу входа списком IP или вторым фактором. Перенос на нестандартный адрес защитой не является, но срезает почти весь автоматический перебор.

3. Сайт сам называет свою CMS и её версию

Симптом: в коде страницы — тег <meta name="generator" content="WordPress 6.2">, поставленный движком из коробки.

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

Что сайт рассказывает о своём движке
curl -s https://example.ru | grep -io ']*>'

Пустой вывод — правильный ответ. Если тег есть, уберите его в настройках или шаблоне движка; для WordPress это одна строка в functions.php. И это не отменяет главного: версию нужно не прятать, а обновлять — тег лишь делает устаревшую версию удобной мишенью.

4. Формы, которым на стенде никто не писал

Симптом: через неделю после запуска в почте — сотни заявок от «клиентов» с адресами вида qwe@qwe.com.

На стенде форму обратной связи заполняли только свои, и защита от ботов казалась лишней возней. Боты находят открытую форму быстрее первых клиентов — и дальше через неё идут спам, перебор и нагрузка на почту, среди которой легко потерять настоящую заявку. Лечится это капчей — Yandex SmartCaptcha, reCAPTCHA, Turnstile — и ограничением частоты отправок.

Вторая, более серьёзная привычка стенда — атрибут action, указывающий на http://-адрес. Всё, что посетитель вводит в такую форму — телефон, пароль, данные карты, — уходит по сети открытым текстом: это видит провайдер, владелец Wi-Fi в кафе и любой узел на пути. Для персональных данных это ещё и прямое невыполнение требования 152-ФЗ защищать их при передаче.

Куда отправляются формы
curl -s https://example.ru | grep -ioE '
]*>'

В выводе не должно быть action="http://…" — только относительные пути или https://.

5. Шрифты с чужого CDN стали трансграничной передачей

Симптом: страница тянет ресурсы с fonts.gstatic.com, unpkg.com, jsdelivr.net — так было быстрее на этапе вёрстки.

Каждый внешний хост на странице — это запрос, который браузер посетителя делает напрямую, отдавая этому хосту свой IP-адрес. IP — персональные данные, а передача их на зарубежный сервер — то, что 152-ФЗ называет трансграничной передачей. Про счётчики аналитики это обычно помнят; про то, что шрифт, иконки и подключённая с CDN библиотека работают ровно так же, — почти никогда.

К кому ходит браузер посетителя
curl -s https://example.ru \
  | grep -oE '(src|href)="https?://[^"]+"' | cut -d'"' -f2 \
  | awk -F/ '{print $3}' | grep -v example.ru | sort -u

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

6. Политика и согласие — последние в очереди на запуск

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

Обязанность опубликовать политику возникает не с первого клиента, а с первой формы: как только сайт собирает персональные данные, документ должен быть доступен посетителю. Рядом второй пункт — согласие на обработку берётся в момент сбора, то есть чекбоксом у самой формы, а не абзацем в глубине сайта. Нарушение — статья 13.11 КоАП, и проверку запускает не плановый обход, а одна жалоба одного посетителя.

Упоминает ли сайт персональные данные
curl -s https://example.ru | grep -ic 'персональных данных'

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

7. Сайт всё ещё закрыт от поиска — или открыт, но молчит

Симптом: запустились месяц назад, поискового трафика — ноль.

Стенд закрывали от индексации сознательно — тегом noindex или заголовком X-Robots-Tag, — и это была правильная настройка. Неправильно одно: о ней забыли в день запуска. Сайт при этом выглядит совершенно здоровым, и отсутствие себя в поиске замечают через месяц, по нулевому трафику.

Не остался ли запрет индексации (проверьте руками)
curl -sI https://example.ru | grep -i x-robots-tag
curl -s https://example.ru | grep -io ']*>'

Честная оговорка: это единственный пункт списка, который наша проверка за вас не сделает — запрет индексации мы не ищем, поэтому выполните эти две команды сами. Пустой вывод или index, follow — правильный ответ.

Обратная сторона той же настройки: сайт открыт, но поисковику не сказали, что индексировать. Проверьте, что robots.txt объявляет карту сайта строкой Sitemap: и что по этому адресу действительно отвечает файл, а не заглушка стенда.

8. TLS, каким его поставил образ из туториала

Симптом: сайт работает по HTTPS, но конфигурацию TLS никто не открывал с момента «скопировал из туториала — заработало».

Дефолт старого туториала или дистрибутива — это в лучшем случае TLS 1.2 без TLS 1.3: не проблема, но упущенные скорость и строгость — TLS 1.3 убирает устаревшие шифры и ускоряет рукопожатие. В худшем случае сервер согласует только действительно устаревшие наборы — CBC и статический RSA без прямой секретности. Разница не академическая: без прямой секретности записанный сегодня трафик можно расшифровать потом, если ключ сервера когда-нибудь утечёт.

Договорится ли сервер о TLS 1.3
openssl s_client -connect example.ru:443 -tls1_3 /dev/null \
  | grep -E 'Protocol|Cipher'

Пустой вывод означает, что TLS 1.3 сервер не поддерживает. Включается он одной строкой в конфигурации веб-сервера или в панели CDN — перед запуском это самая дешёвая из настроек с постоянным эффектом.

9. Витрина: как сайт выглядит в репостах, для исследователей и ассистентов

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

Три маленьких файла и одна группа тегов решают, как сайт выглядит за его пределами. Open Graph и Twitter-теги — og:title, og:image, description — собирают карточку ссылки в мессенджерах и соцсетях; без них репост выглядит как спам. Файл /.well-known/security.txt со строкой Contact: даёт исследователю безопасности адрес, куда сообщить об уязвимости, — иначе он напишет в общую почту, и письмо утонет.

Третий пункт пока экзотика, но спрашивать о нём начнут раньше, чем кажется: /llms.txt — текстовое описание сайта для ИИ-ассистентов. Когда ChatGPT, Алису или Claude спросят про вашу компанию, пересказывать они будут то, что сумели понять; короткий файл с фактами о вас — способ поучаствовать в этом пересказе. Заодно решите осознанно, что разрешать ИИ-краулерам в robots.txt.

Готова ли витрина
curl -s https://example.ru | grep -io 'og:[a-z:]*' | sort -u
curl -s https://example.ru/.well-known/security.txt
curl -s https://example.ru/llms.txt | head -n 5

Чек-лист

ЧтоПризнак, что всё в порядке
Тестовые поддоменыЗакрыты аутентификацией, списком IP или VPN
Страница входа в админкуНедоступна с произвольного адреса без второго фактора
Тег generatorУбран; версия CMS в коде страницы не видна
ФормыС капчей, action только на HTTPS
Внешние ресурсыСписок пересчитан; шрифты и библиотеки у себя
Политика и согласиеПолитика опубликована, согласие — чекбоксом у формы
Индексацияnoindex снят, Sitemap: объявлен в robots.txt
TLSСервер согласует TLS 1.3
ВитринаOG-теги, security.txt и llms.txt на месте

Чего такая проверка не покажет

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

Она не найдёт забытый каталог .git или дамп базы в корне — для этого нужен перебор путей, а это уже не наблюдение, а попытка что-то нащупать. Не найдёт уязвимости в коде и плагинах и не проверит то, что дорисовывает скрипт после загрузки страницы: динамический баннер cookie или чекбокс согласия останутся за кадром. Журналы сертификатов покажут только поддомены, на которые когда-либо выпускался сертификат, — стенд на голом IP в них не значится. И запрет индексации, как сказано выше, проверяется руками.

Зато всё, что видно снаружи, видно и тем, кто ищет лёгкие цели, — а свежезапущенный сайт они проверяют в первые же дни, пока привычки стенда ещё на месте.

Проверьте всё это одной командой

Введите адрес — получите разбор с оценкой риска и объяснением каждой находки. Бесплатно и без регистрации.

Проверить сайт

Частые вопросы

Чем эта проверка отличается от проверки после переезда на хостинг?

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

Можно ли проверять сайт, который ещё закрыт паролем или SSO?

Да. Проверка распознаёт ответ 401/403 и страницы корпоративного входа, честно сообщает «сайт за аутентификацией» и не пугает ложными находками о содержимом, которого не видит. Глубина проверки при этом ограничена: всё, что живёт за формой входа, снаружи недоступно — полный список находок вы получите после открытия сайта.

Откуда видны мои тестовые поддомены, если я нигде их не публиковал?

Из журналов Certificate Transparency: каждый выпущенный сертификат публикуется в открытых журналах вместе с именем, на которое он выдан. Адрес стенда становится публичным в момент выпуска сертификата, независимо от того, есть ли на него ссылки. Поэтому прятать поддомен бессмысленно — закрывать нужно доступ, а не имя.

Когда запускать проверку — до открытия сайта или после?

Дважды. За день-два до запуска — пока правки дешёвые и никто не смотрит. И сразу после переключения на боевой домен: часть вещей — сертификат, TLS, редиректы, заголовки — зависит от боевого окружения и на стенде не проверяется.

Что из этого списка проверка не найдёт сама?

Запрет индексации (meta noindex и X-Robots-Tag) проверьте руками — пассивная проверка его не ищет. Также она не найдёт забытый .git и дампы в корне (для этого нужен перебор путей), уязвимости в коде и всё, что дорисовывает скрипт после загрузки страницы, — например, динамический баннер cookie.