вернуться к обзору Больше статей

Утечка часового пояса: VPN меняет ваш IP, но не ваши часы

Загрузка...

Вы включаете VPN, выбираете сервер в Амстердаме и открываете страницу. IP-адрес исправно числится голландским на каждом сервисе проверки IP, какой ни возьми. И всё же на кассе появляется лишний шаг верификации, каталог стриминга так и остаётся не тем, а вход в аккаунт заканчивается письмом о «новом устройстве». То, что вас выдало, умещается в одну строку JavaScript: Intl.DateTimeFormat().resolvedOptions().timeZone.

Этот вызов возвращает часовой пояс, установленный в операционной системе, и VPN на него не влияет никак. Ваши пакеты теперь приходят из Амстердама, а браузер по-прежнему бодро сообщает America/New_York. Виджет на этой странице делает то же сравнение, что и антифрод-скрипт: смотрит, какой часовой пояс следует из вашего IP-адреса, читает пояс, который сообщает браузер, и проверяет, согласны ли эти двое между собой.

Если коротко: на вопрос «откуда этот посетитель» сайт получает два независимых ответа: часовой пояс IP-адреса и часовой пояс операционной системы. VPN меняет только первый. Сравнить их стоит одну строку кода, а подделать второй наполовину — единственный ход, который выглядит хуже, чем не подделывать его вовсе.

Два ответа на один вопрос

Первый ответ приходит из сети. Сайт видит IP, с которого вы подключились, и ищет его в базе геолокации: ipinfo.io, MaxMind и их конкуренты вместе с локацией возвращают и часовой пояс. С включённым VPN этот ответ указывает на выходной сервер: подключитесь через Амстердам — и база скажет Europe/Amsterdam. Как устроены эти базы и насколько сильно они могут ошибаться, когда речь идёт о вашей улице, мы разбирали в статье о точности IP-геолокации. Но на уровне часовых поясов они не ошибаются почти никогда.

Второй ответ приходит из вашей операционной системы. Локальное смещение от UTC JavaScript умеет читать ещё с девяностых — через new Date().getTimezoneOffset(), — а современные браузеры через API Intl отдают и полное имя зоны по базе IANA. Ни запроса разрешения, ни действия пользователя, ни строчки в каком-нибудь журнале приватности. Это считается обычными метаданными — из того же разряда, что и размер экрана.

Один посетитель — два ответа
Что говорят ваши пакеты
IP выходного узла VPN 198.51.100.7 база геолокации Europe/Amsterdam
Что говорит ваш браузер
настройки часов ОС Intl.DateTimeFormat() America/New_York
Несовпадение
Europe/AmsterdamAmerica/New_York — поймано одним сравнением строк, ещё до первого вашего клика.
Сетевой ответ — результат геолокации IP, с которого вы подключились. Ответ браузера приходит из вашей операционной системы. VPN всегда меняет только первый.

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

Почему VPN тут бессилен

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

Сайт узнаёт не время на ваших часах, а идентификатор зоны. America/New_York — это заявление о местоположении с точностью до вертикальной полосы на глобусе, и лежит оно на самом виду, рядом с navigator.language и заголовком Accept-Language, которые делают заявления того же рода о том, где вы живёте.

Справедливости ради, сам по себе такой разнобой ничего не доказывает. Люди летают с ноутбуками, которые всё ещё думают, что они дома, а удалёнщики нарочно живут по часовому поясу своей команды. Системы детекта это знают, поэтому несовпадение не влечёт бан, а идёт в риск-скоринг. Но баллы складываются: несовпадение часового пояса плюс IP дата-центра плюс утечка WebRTC — такое сочетание уже не истолковать двояко, и каждый сигнал увеличивает вес следующего.

Ловушка половинчатого спуфинга

Очевидное решение — соврать и про часовой пояс, благо расширений, предлагающих именно это, целая гора. Большинство из них переопределяют Intl.DateTimeFormat, чтобы resolvedOptions().timeZone возвращал то, что вы настроили. Проблема в том, что браузер объявляет свой часовой пояс не в одном месте:

  • new Date().getTimezoneOffset() сообщает, на сколько минут ваши часы отстают от UTC, — по совершенно другому пути в коде.
  • Date.prototype.toString() проговаривает зону словами: «GMT-0400 (Eastern Daylight Time)».
  • Форматирование даты для произвольного дня года раскрывает ваши правила перехода на летнее время, а они — часть самого определения зоны.

Фиксированное смещение — это ещё не часовой пояс. Амстердам в июле живёт по UTC+2, а в январе по UTC+1, и переводит стрелки не в те же даты, что Нью-Йорк: ЕС меняет время в последнее воскресенье марта, США — на две-три недели раньше. Скрипт может спросить, каким было ваше смещение первого января и первого июля, и сверить эту пару с заявленной зоной. Подделка, прибившая гвоздями одно смещение на весь год, не совпадает ни с одним местом, где вообще переводят часы, — и уж точно не с Амстердамом, за который себя выдаёт.

Упустите любой из этих каналов — и браузер начнёт спорить сам с собой:

Часовой пояс IP (геолокация) с выходного сервера VPN
Europe/Amsterdam согласовано
Заявление Intl.DateTimeFormat() напрямую из ОС
America/New_York не согласовано
Смещение часов прямо сейчас через getTimezoneOffset()
UTC−4 не согласовано
Несовпадение
IP говорит «Амстердам», браузер — «Нью-Йорк». Читается как VPN или прокси.
Смещения указаны для июля. Если пропатчить имя зоны, но упустить смещение часов, получится браузер, спорящий сам с собой, а это противоречие — сигнал куда сильнее, чем сам VPN.

У этой ловушки есть и второй слой. Переопределённый Intl.DateTimeFormat перестаёт выглядеть нативным, когда скрипт заглядывает в его исходный код. Это та же примета пропатченной функции, что выдаёт stealth-плагины, — мы разбирали её в статье об обнаружении ботов. Чистое несовпадение говорит «вероятно, VPN». Пропатченный API говорит «этот человек активно вмешивается в браузер», и в любой серьёзной скоринговой системе это обходится дороже.

Что делать на практике

  1. Сначала проверьте, потом доверяйте. Виджет на этой странице прямо сейчас сравнивает часовой пояс вашего браузера с поясом вашего IP, а полное сканирование браузера запускает его вместе с проверками WebRTC, платформы и отпечатка. Прогоните его с включённым VPN. Если виджет вас пометил — пометит и любой антифрод-скрипт.
  2. Переводите часы вместе с VPN. Скучное решение — самое надёжное: перед подключением выставьте в ОС часовой пояс города выхода. Детектировать нечего, потому что ничего не подделано: все API сообщают одну и ту же зону из одного и того же источника. Альтернатива для ценителей приватности — Tor Browser, который всем сообщает UTC: ваша настоящая зона скрыта — ценой того, что вы выглядите в точности как Tor Browser.
  3. Если вы ведёте несколько личностей — перестаньте делать это вручную. Управление аккаунтами в разных регионах означает, что каждому профилю нужны свой IP, часовой пояс, язык и отпечаток, согласованные между собой в каждой сессии. Именно эту бухгалтерию автоматизируют антидетект-браузеры: Incogniton выводит часовой пояс каждого профиля из IP его прокси, так что два ответа из этой статьи просто не успевают разойтись.

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

Логотип Incogniton

Повысьте уровень своей приватности

Стрелка