Сайт жил по IPv4 и молчал по IPv6: полгода теряли часть аудитории
Никто не жаловался, аптайм-мониторинг был зелёным, конверсия в среднем не проседала — а часть аудитории всё это время получала заметно худший опыт от того же самого сайта. Разбираем, как отсутствие одной DNS-записи полгода оставалось незамеченным, потому что проблема не ломала сайт, а тихо ухудшала его для конкретного сегмента пользователей.
Содержание
- Что случилось: сайт, у которого никогда не было AAAA-записи
- Почему для части аудитории IPv6 — не опция, а основной путь
- Что реально добавляет провайдерский NAT64/CGNAT в путь пакета
- Почему проблема была не видна полгода
- Как это вскрылось: разбор метрик по регионам и типам подключения
- Что добавить, чтобы IPv6 реально заработал — и не создал новую тихую проблему
- Практический вывод: ищите не «работает ли», а «одинаково ли хорошо работает для всех»
Что случилось: сайт, у которого никогда не было AAAA-записи
Сайт работал штатно — быстро отдавался, проходил все проверки доступности, ошибок в логах не было. Всё, что можно увидеть в стандартном мониторинге («сайт отвечает», «код 200», «время ответа в норме»), выглядело нормально. Проблема была не в том, что что-то сломалось, а в том, что часть инфраструктуры никогда не была настроена — с самого запуска у домена существовала только A-запись:
dig A example.com +short
# 203.0.113.10
dig AAAA example.com +short
# (пусто)
Пустой ответ на AAAA означает одно: у домена нет адреса для подключения по IPv6. Это не ошибка конфигурации в привычном смысле — сервер прекрасно работал по IPv4, DNS отдавал корректную A-запись, TTL был в порядке. Просто IPv6-стек на сервере либо не был поднят вообще, либо был поднят, но никогда не публиковался в DNS — и то и другое означает для внешнего мира одно и то же: сайт для IPv6-клиентов не существует напрямую, только через посредника.
Полгода это никого не беспокоило. Не потому что всё было в порядке, а потому что метрика, которая могла бы это показать, ни разу не разбивалась на нужный срез. Общий показатель конверсии, среднее время загрузки, доля отказов — все агрегированные цифры складывали в одну кучу и тех, кто подключался напрямую по IPv4, и тех, кто на самом деле шёл в обход, через трансляцию протоколов у своего провайдера. Средняя температура по больнице скрывала, что часть пациентов лежит в холодном коридоре.
Почему для части аудитории IPv6 — не опция, а основной путь
Легко упустить, рассуждая в парадигме «IPv6 — это что-то новое и необязательное»: для значительной и растущей части подключений IPv6 давно не «протокол на будущее», а основной канал связи с интернетом, а IPv4-доступ реализован как надстройка поверх него.
Это касается прежде всего мобильных сетей. У многих операторов сотовой связи (особенно там, где сеть строилась или модернизировалась в последние годы) внутренняя инфраструктура — IPv6-native: устройству выдаётся реальный IPv6-адрес напрямую, без какой-либо трансляции. А вот для доступа к IPv4-адресам, которых в интернете физически не хватает на всех абонентов, оператор поднимает трансляцию — обычно по схеме NAT64/DNS64: в сети оператора стоит шлюз, который на лету превращает запрос от IPv6-клиента в IPv4-запрос к внешнему серверу, и наоборот на обратном пути.
Похожая логика — провайдерский CGNAT (Carrier-Grade NAT) — применяется и в фиксированном доступе, где у провайдера физически не хватает публичных IPv4-адресов на всех абонентов: пул реальных адресов делится на множество клиентов сразу, а конкретному абоненту публичный IPv4 не выделяется вовсе. Архитектурно это тот же принцип, что описан в статье про то, как работает NAT и почему два устройства не видят друг друга — только развёрнутый на уровне целой сети оператора и применённый к тысячам абонентов одновременно.
Для пользователя разница не видна вообще — браузер просто открывает страницу. Но путь пакета до сервера у него принципиально другой, чем у пользователя с прямым IPv4- или IPv6-подключением.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверЧто реально добавляет провайдерский NAT64/CGNAT в путь пакета
Когда клиент с IPv6-only подключением обращается к сайту без AAAA-записи, происходит следующее: устройство резолвит домен и получает только A-запись; система вынуждена идти по IPv4, которого нативно у неё нет; запрос уходит на шлюз оператора (NAT64), который транслирует IPv6-пакет в IPv4-пакет и отправляет его дальше от своего имени; ответ идёт обратно тем же путём, через тот же шлюз.
Это не теория, а лишнее звено в цепочке, которого не было бы, если бы сервер сам отвечал по IPv6 напрямую клиенту. Практические последствия такой схемы:
- Дополнительный сетевой узел на пути. Шлюз трансляции — отдельное устройство (или кластер) в инфраструктуре оператора, через которое обязан пройти каждый пакет в обе стороны. Больше узлов на пути — больше потенциальных источников задержки и точек отказа, даже если каждый узел сам по себе исправен.
- Нагрузка на таблицу трансляций. Шлюз держит в памяти таблицу соответствий «внутренний IPv6-адрес + порт → внешний IPv4-адрес + порт» для тысяч соединений сразу. Это конечный ресурс: под пиковой нагрузкой запись может вытесняться раньше, чем ожидает клиентское приложение — на практике это выглядит как случайный обрыв соединения без видимой причины на стороне сайта.
- Путь до сервера не обязательно короче. Прямое IPv6-соединение может пойти по более короткому маршруту в магистральной сети, тогда как трафик через трансляцию привязан к маршруту и загрузке конкретного шлюза оператора — который сайт никак не контролирует и даже не видит.
Важна честность: NAT64/CGNAT — не «сломанная» технология, операторы держат её годами без катастроф. Проблема не в том, что трансляция работает плохо сама по себе, а в том, что она добавляет переменную задержку и лишнюю точку отказа именно там, где при нативном IPv6 у сайта эта трансляция была бы вообще не нужна.
Почему проблема была не видна полгода
Здесь стоит разобрать честно, почему это не выглядело как авария и не попадало ни в один алерт.
Сайт формально работал для всех. Ни один пользователь не получал ошибку, «сайт недоступен» или белый экран. Разница была не в «работает / не работает», а в «работает нормально / работает чуть хуже» — а такую разницу штатный аптайм-мониторинг в принципе не предназначен ловить: он проверяет доступность, а не качество опыта в разрезе сегментов аудитории.
Не было явных жалоб. Пользователь, у которого страница грузится на секунду-другую дольше обычного или раз в несколько сессий обрывается соединение, крайне редко напишет тикет с формулировкой «у меня, кажется, трафик идёт через NAT64 вашего оператора». Он либо не замечает разницы осознанно, либо списывает её на «у меня просто интернет плохой» — и уходит молча, не оставляя следа, который можно связать с причиной.
Агрегированные метрики маскировали разницу. Средняя задержка, средний показатель отказов, средняя конверсия по всему трафику — это цифры, где меньшинство с худшим опытом растворяется в большинстве с нормальным. Если основная часть аудитории заходит с прямого IPv4-подключения, а часть — через CGNAT с более редкими, но более длинными паузами, среднее почти не сдвинется, особенно пока эта часть не составляет большинство.
Никто не проверял именно этот срез. Классический набор регулярных проверок — «сайт открывается», «SSL не просрочен», «error rate в норме», «core web vitals приемлемые» — не включает вопрос «а одинаково ли хорошо сайт работает у пользователей с разным типом подключения». Это конкретная гипотеза, которую нужно было явно сформулировать и проверить — а формулировать её никто не стал, пока не возник повод.
Как это вскрылось: разбор метрик по регионам и типам подключения
Поводом стал не инцидент, а рутинный квартальный разбор аналитики — попытка понять, почему конверсия в отдельных регионах стабильно ниже, чем в среднем по сайту, при сопоставимом объёме трафика. Подход «давайте посмотрим на воронку» ничего не показал — воронка выглядела одинаково по шагам, просто с разной итоговой конверсией.
Сдвиг случился, когда метрики разбили не по геолокации (страна/город), а по типу подключения — конкретно, по тому, каким протоколом реально устанавливалось соединение с сервером. Практически это делается так:
На уровне логов веб-сервера. Nginx пишет в $remote_addr реальный адрес клиента — по нему легко отличить IPv4-адрес от IPv6-адреса построчно:
awk '{print $1}' /var/log/nginx/access.log | \
grep -c '^[0-9]\{1,3\}\.[0-9]\{1,3\}\.' # счётчик IPv4-строк
awk '{print $1}' /var/log/nginx/access.log | \
grep -c '^[0-9a-fA-F:]*:[0-9a-fA-F:]*' # счётчик IPv6-строк
Но здесь принципиальная деталь: IPv6-адрес клиента виден в логах сервера только тогда, когда клиент подключился нативно по IPv6. У сайта не было AAAA-записи вообще, поэтому в логах веб-сервера все запросы, включая пришедшие через CGNAT провайдера, выглядели как обычные IPv4-подключения — трансляция произошла раньше, на стороне оператора. Отличить в логах, что конкретный IPv4-адрес на самом деле принадлежит шлюзу трансляции, а не «обычному» абоненту с настоящим IPv4, напрямую нельзя — это и есть главная сложность диагностики подобных случаев.
Обходной путь — через ASN и данные аналитики. Реальную картину дала связка веб-аналитики (custom-параметр с ASN/оператором сети, который передаёт клиентский JS при загрузке страницы) и открытых баз соответствия IP-диапазонов операторам. Часть IPv4-диапазонов, зарегистрированных за операторами мобильной связи, публично помечены как используемые под CGNAT-пулы — это проверяется через whois и базы RIPE/APNIC по конкретной подсети:
whois 203.0.113.10 | grep -iE "netname|descr|org"
Сопоставив, какая доля сессий в проблемных регионах шла с диапазонов, помеченных как принадлежащие операторам с известной CGNAT/NAT64-инфраструктурой, и сравнив показатели именно этого сегмента с остальным трафиком, разница стала видна — по времени ответа сервера и по доле сессий с обрывом до завершения ключевого действия. Именно этот срез — не «регион» и не «оператор» сам по себе, а «оператор с IPv6-first сетью, у которого IPv4-доступ идёт через трансляцию» — оказался тем сегментом, который проседал стабильно, а не время от времени.
Полезный инструмент того же назначения — регулярные синтетические проверки сайта с разных точек и типов подключения: они дают контролируемый способ замерять именно то, что интересует, а не ждать, пока разница проявится сама в проде.
Что добавить, чтобы IPv6 реально заработал — и не создал новую тихую проблему
Вывод из истории простой: у растущей доли аудитории с IPv6-first подключением есть прямой путь к серверу, если у сервера есть нативный IPv6-адрес и опубликованная AAAA-запись — тогда трафик идёт напрямую, минуя провайдерский CGNAT/NAT64 целиком. Но здесь есть оговорка, которая перевешивает саму идею «просто включить IPv6»: включённый, но не протестированный IPv6 может создать новую проблему вместо старой.
Если IPv6 настроен наполовину — слушает веб-сервер, но не продублированы правила firewall, не проверены исходящие соединения, не протестирован реальный путь через curl -6 — часть клиентов, раньше стабильно шедших по IPv4 через CGNAT, после появления AAAA начнёт пытаться идти по IPv6 первыми (так работает Happy Eyeballs) и упираться в путь, который на сервере не настроен как следует. Результат окажется хуже, чем «работает только по IPv4» — это будет «работает нестабильно по обоим протоколам».
Поэтому включение IPv6 здесь — не одна DNS-запись, а пункт технического плана с проверкой на каждом шаге: от firewall до логирования и исходящих соединений. Разбор мест, которые обычно ломаются при включении IPv6 на сервере, годами работавшем только с IPv4-предположением, — в статье «Переход на IPv6: что готово, а что сломается». Вывод из неё стоит держать в голове и здесь: IPv6 должен либо работать полностью корректно и быть протестирован по всем сценариям, либо не публиковаться в DNS вовсе — половинчатое включение хуже полного отсутствия. Отдельно стоит заложить время на повторный разбор тех же метрик через несколько недель после включения — чтобы подтвердить, что разница исчезла, а не сместилась в другое место.
Практический вывод: ищите не «работает ли», а «одинаково ли хорошо работает для всех»
Главный урок этой истории не про IPv6 конкретно, а про то, как устроен мониторинг производительности сайта в целом. Стандартный набор проверок отвечает на вопрос «сайт работает?» — и отвечает честно и в срок. Но он почти никогда не отвечает на вопрос «сайт работает одинаково хорошо для всех сегментов аудитории?» — а именно там прячутся тихие потери, которые не создают алертов и не порождают тикетов в поддержку.
Практический чек-лист на регулярной основе:
- Сегментируйте метрики производительности и конверсии не только по общему среднему и не только по географии («страна», «город»), но и по типу подключения — где возможно, по ASN/оператору, с явным выделением известных CGNAT/мобильных диапазонов.
- Проверяйте DNS-записи домена целиком регулярно, а не только в момент запуска:
dig A,dig AAAAпо основному домену и по всем реально используемым поддоменам (www, API, CDN-эндпоинты). - Не полагайтесь только на аптайм-мониторинг как на индикатор качества — он ловит «упало / не упало», но не ловит «стало заметно хуже для конкретного сегмента».
- Периодически спрашивайте не «работает ли сайт», а «для кого он может работать хуже прямо сейчас, а мы не смотрим в эту сторону» — и явно формулируйте гипотезы для проверки, а не ждите, пока разница всплывёт в общих цифрах сама.
Это дешевле, чем кажется: разбивка существующих метрик по новому срезу — обычно работа с уже собираемыми данными, а не новый источник с нуля. Дороже стоит полгода терять часть аудитории, даже не зная об этом.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Как узнать, есть ли у сайта вообще AAAA-запись?
Одна команда: dig AAAA ваш-домен.ru +short. Пустой ответ значит, что записи нет и IPv6-клиенты идут к сайту исключительно через IPv4-путь (в том числе через провайдерский CGNAT/NAT64). Проверьте так же www и все используемые поддомены — по одному пропущенному DNS может отличаться.
Можно ли определить долю аудитории через CGNAT без включения IPv6 на сервере?
Частично — через сопоставление IP-адресов в логах или аналитике с публичными базами ASN/whois, которые помечают диапазоны под трансляцию. Точность ограничена: не все такие диапазоны публично помечены, метод даёт оценку, а не точную цифру.
Правда ли, что задержка через NAT64/CGNAT всегда заметно хуже прямого подключения?
Не всегда и не одинаково — зависит от загрузки шлюза оператора и маршрута до сервера. Дополнительное звено в пути — структурный факт, а насколько это ощутимо в конкретной сети — вопрос измерения на своих данных, а не универсального числа.
Если у нас мало трафика с мобильных операторов, стоит ли этим заниматься?
Стоит хотя бы проверить долю — за счёт роста IPv6-first мобильных сетей она обычно не уменьшается со временем. Если после сегментации разница окажется незначительной, это тоже полезный результат: закрытый вопрос, а не забытый.
Достаточно ли добавить AAAA-запись, чтобы решить проблему?
Нет, это необходимый, но не достаточный шаг. Без проверки firewall, исходящих соединений и логирования по обоим стекам запись может превратить стабильную, но тихую проблему в менее заметную с виду, зато менее предсказуемую.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →