MAATRIX / Блог / GeoDNS отправил клиента из Казани на сервер в Лондоне: когда геолокация IP ошибается

GeoDNS отправил клиента из Казани на сервер в Лондоне: когда геолокация IP ошибается

MAATRIX

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

Как устроены базы геолокации IP: от блока RIR до догадки

В основе любой базы геолокации IP лежат данные региональных интернет-регистратур (RIR) — RIPE NCC для Европы, Ближнего Востока и части Азии (включая Россию и СНГ), ARIN для Северной Америки, APNIC для Азиатско-Тихоокеанского региона, LACNIC для Латинской Америки, AFRINIC для Африки. Именно RIR выдают провайдерам и организациям блоки IP-адресов и ведут публичный whois-реестр, где у каждого блока указана организация-держатель, её страна регистрации и контактные данные:

whois 92.223.0.0 | grep -iE "country|netname|descr"

Проблема в том, что «страна регистрации в whois» и «страна физического использования адреса» — это два разных поля, которые совпадают далеко не всегда. Коммерческие базы геолокации (MaxMind GeoIP2/GeoLite2, IP2Location, DB-IP, ipinfo.io и другие) поверх данных RIR добавляют собственные эвристики: обратные DNS-записи с кодами городов в имени хоста (fra, lhr, dme — привычные IATA-подобные сокращения в rDNS транзитных сетей), точки анонсирования маршрутов в BGP, замеры задержки от собственной сети зондов, пользовательские корректировки через формы обратной связи. Результат — не факт, а наиболее вероятная оценка, взвешенная по нескольким источникам разного качества. Проверить, что видит конкретная база для вашего IP, можно так:

# локальный офлайн-поиск по MaxMind mmdb
mmdblookup --file GeoLite2-City.mmdb --ip 203.0.113.10 city names en

# быстрый онлайн-запрос без установки библиотек
curl -s https://ipinfo.io/203.0.113.10/json | jq '.city, .region, .country'

Разные базы для одного адреса нередко выдают разные города — это системное свойство метода, а не брак конкретного поставщика.

Зарегистрирован в одной стране, используется в другой

Классический источник ошибки — крупная организация с централизованным IT-департаментом. Компания получает блок IP-адресов через LIR (local internet registry) в стране, где сидит головной офис — скажем, в Германии, — и в whois весь блок числится за немецкой организацией. Дальше этот блок нарезается на подсети и раздаётся филиалам в других странах: филиал в Казахстане, представительство в Турции, дата-центр в Ирландии — все получают адреса из «немецкого» диапазона, потому что так проще с точки зрения внутреннего IP-менеджмента и маршрутизации через центральный дата-центр. Официальная пере-регистрация суб-блока на новую страну в RIR — процедура необязательная для многих типов выделений и требует отдельных усилий, поэтому на практике её делают далеко не всегда, особенно для небольших подсетей.

Итог: сотрудник филиала в Алматы физически сидит в Казахстане, но его исходящий IP числится как немецкий — и любой сервис, определяющий страну по IP, увидит Германию. Это не злой умысел, а следствие того, как исторически устроена IP-инфраструктура транснациональных компаний с центральным NOC.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Мобильные операторы: вся страна видна из одной точки

У мобильных операторов есть архитектурная особенность, которая систематически бьёт по точности геолокации: весь исходящий интернет-трафик абонентов нередко заворачивается через ограниченное число центральных шлюзов (GGSN/PDN Gateway в терминах 3G/4G, UPF в 5G), которые физически расположены в одном-двух крупных городах на всю страну или даже на несколько стран региона. Абонент может находиться в Казани, но его пакеты выходят в публичный интернет через шлюз, физически стоящий в Москве или Петербурге — и именно на этот шлюз указывает исходящий публичный IP после трансляции CGNAT.

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

Корпоративные VPN и прокси: клиент не тот, кем выглядит

Третий источник ошибки — не столько недостаток базы, сколько намеренное или побочное искажение видимого IP на стороне клиента. Корпоративный VPN с единой точкой выхода в интернет — обычная практика безопасности: все сотрудники, независимо от того, где они физически находятся, выходят в публичную сеть через один шлюз, часто в стране штаб-квартиры. Сотрудник на удалёнке в Казани через корпоративный VPN с выходом в Лондоне для любого внешнего сервиса выглядит именно как лондонский клиент — и это не ошибка геобазы, а корректное определение адреса, который на самом деле не имеет отношения к физическому местоположению человека.

Прокси-серверы, к которым точка подключается через провайдера (например, некоторые мобильные и корпоративные сети используют transparent proxy для кэширования и фильтрации трафика), добавляют тот же эффект. Ещё один слой той же проблемы — работа самого DNS. Классический GeoDNS без расширения EDNS Client Subnet (ECS) видит не IP конечного клиента, а IP рекурсивного DNS-резолвера, к которому клиент обратился за ответом. Если пользователь настроил публичный резолвер вроде 8.8.8.8 или 1.1.1.1, запрос до авторитативного GeoDNS-сервера может прийти вовсе не из той страны, где сидит клиент, — и балансировка ошибётся ещё до того, как речь дойдёт до неточности самой базы IP-геолокации.

Что получает пользователь на практике: Казань вместо Москвы — Лондон

Собираем причины воедино на конкретном сценарии. Пользователь в Казани открывает сайт. Его провайдер — мобильный оператор с центральным шлюзом в другом регионе, или он подключён через корпоративный VPN с выходом за рубежом, или использует публичный DNS-резолвер без ECS. GeoDNS смотрит на видимый IP (клиента или резолвера — в зависимости от конфигурации), сверяется с базой геолокации и находит для этого диапазона запись «Великобритания, Лондон» — потому что именно там физически или по регистрации находится точка, к которой этот IP привязан в базе. Ближайший к пользователю сервер в Москве или Санкт-Петербурге в этот момент даже не рассматривается: с точки зрения GeoDNS клиент не в России, значит, российский узел не в приоритете.

Результат ощущает сам пользователь — заметно более долгий отклик, чем мог бы быть, притом что «рядом» физически стоит сервер, который его вообще не получил в качестве кандидата. Для владельца сервиса это выглядит как необъяснимая жалоба от части аудитории при в целом нормальных средних показателях — такие «промахнувшиеся» клиенты обычно тонут в общей статистике, если не разбирать её по сегментам.

Проверка точности своей геобазы: как не гадать

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

# сравниваем ответ своей базы (mmdblookup) с независимым сервисом
mmdblookup --file GeoLite2-City.mmdb --ip $IP city names en
curl -s https://ipinfo.io/$IP/json | jq '.city'

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

Практическое решение: RUM и fallback вместо слепого доверия GeoDNS

Главный вывод — GeoDNS не должен быть единственным механизмом принятия решения о том, к какому серверу отправить клиента, если для вас важна реальная скорость, а не только общее направление трафика. Рабочая схема строится в три слоя.

Первый слой — GeoDNS как быстрая грубая прикидка. Он остаётся полезным: для подавляющего большинства клиентов на стабильных проводных подключениях он работает достаточно точно и не требует лишнего RTT на подтверждение. Короткий TTL (минуты, а не часы) снижает цену ошибки, если клиент всё-таки попал не туда — переключение произойдёт быстрее.

Второй слой — активная проверка задержки с браузера пользователя (RUM, real user monitoring) поверх того, что отдал GeoDNS. Логика простая: после того как клиент получил ответ и начал грузить страницу, скрипт в фоне опрашивает несколько кандидатов-регионов и запоминает, какой реально быстрее для этого конкретного браузера — а не для абстрактного IP-диапазона:

<script>
async function pickFastestRegion(candidates) {
  const results = await Promise.all(candidates.map(async (region) => {
    const start = performance.now();
    try {
      await fetch(`https://${region.host}/ping`, { mode: 'no-cors', cache: 'no-store' });
      return { region: region.id, rtt: performance.now() - start };
    } catch (e) {
      return { region: region.id, rtt: Infinity };
    }
  }));
  results.sort((a, b) => a.rtt - b.rtt);
  const fastest = results[0];
  // текущий регион ощутимо хуже реально быстрого — переключаемся
  const current = results.find(r => r.region === CURRENT_REGION);
  if (current && fastest.rtt < current.rtt * 0.6) {
    document.cookie = `preferred_region=${fastest.region}; path=/; max-age=86400`;
    location.reload();
  }
}
</script>

Порог * 0.6 — ориентир, не универсальная константа: у вашей аудитории и набора регионов оптимальное значение может отличаться, его стоит подбирать по факту, глядя на реальное распределение замеров, а не брать как готовое правило. Такой RUM-замер и cookie-переопределение обходят все перечисленные выше искажения разом: не важно, почему GeoDNS ошибся — из-за корпоративного VPN, мобильного шлюза или неточной базы, — реальная задержка от браузера пользователя показывает правду напрямую, без посредников.

Третий слой — fallback-логика на стороне приложения или балансировщика для случаев, когда GeoDNS явно промахнулся в отдельных сегментах трафика, которые можно распознать заранее (например, известные диапазоны конкретного мобильного оператора или корпоративного VPN-провайдера, замеченные в проверке точности). Здесь работает статическая таблица исключений поверх стандартной GeoIP-логики — что подробно разобрано в статье про балансировку между серверами в разных странах: L7-балансировщик или сама GeoDNS-конфигурация может учитывать явные overrides для известных проблемных диапазонов, а не полагаться на общую базу без исключений.

СлойЧто делаетКогда срабатываетЦена ошибки
GeoDNS по базе геолокацииБыстрый грубый выбор региона при первом DNS-запросеВсегда, для всех клиентовНизкая при коротком TTL
RUM-замер в браузереПроверяет реальную задержку и переключает при явном расхожденииПосле загрузки страницы, асинхронноТребует лишнего RTT, но исправляет ошибку GeoDNS
Таблица исключений (override)Жёстко переопределяет регион для известных проблемных диапазоновДля заранее выявленных сетей (операторы, VPN)Требует ручного сопровождения списка

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

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

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

Можно ли вообще отказаться от GeoDNS и полагаться только на RUM-замеры?

Технически можно, но на практике невыгодно: RUM требует, чтобы страница уже загрузилась хотя бы с какого-то сервера, а первый выбор всё равно должен кто-то сделать — обычно это и есть GeoDNS или anycast. RUM — это слой коррекции поверх первого грубого выбора, а не полная его замена.

Насколько вообще можно доверять базам геолокации IP?

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

EDNS Client Subnet (ECS) решает проблему с публичными DNS-резолверами?

Частично. ECS передаёт авторитативному серверу часть IP-подсети реального клиента вместо IP резолвера, что улучшает точность GeoDNS для пользователей публичных резолверов вроде 8.8.8.8. Но это не устраняет остальные причины ошибок — регистрацию блока не по месту использования, мобильные шлюзы, корпоративные VPN, — и работает только если сам резолвер и авторитативный сервер поддерживают это расширение.

Как быстро проверить, не промахнулся ли GeoDNS для конкретного клиента, без сложной инфраструктуры?

Достаточно попросить пользователя (или прогнать самостоятельно с зонда в нужном городе, например через globalping) выполнить dig к вашему домену и сравнить возвращённый IP с ожидаемым для его города, а затем свериться с публичным сервисом геолокации для этого же IP — расхождение будет видно сразу, без развёртывания RUM.

Что делать с корпоративными VPN, если исправить их маршрут я не могу?

Переопределить для них ничего нельзя на уровне вашей инфраструктуры — но можно распознать сегмент (по диапазону IP известного VPN-провайдера) и либо исключить его из строгой GeoDNS-логики через override, либо полагаться в первую очередь на RUM-переключение, которое сработает независимо от того, откуда на самом деле пришёл запрос.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →