Руководства

Как различать посетителей по IPv4 и IPv6 в логах

Адреса вида 203.0.113.42 и 2001:db8::1 явно выглядят по-разному, но когда адреса спрятаны в лог-файле или столбце базы данных, скрипт, рассчитанный на один формат, будет незаметно неправильно обрабатывать другой.

Чтение поля version

Эндпоинт /v1/ip возвращает поле version в каждом ответе, со значением 4 или 6, вместе с остальными данными о местоположении. Разбирать строку адреса самостоятельно, чтобы понять, к какому семейству она относится, не нужно.

GET /v1/ip?ip=2001:db8::1
{
  "status": "ok",
  "ip": "2001:db8::1",
  "version": 6,
  "found": true,
  "country": "Canada",
  "country_code": "CA",
  "region": "Ontario",
  "city": "Toronto",
  "postcode": "M5H",
  "lat": 43.6511,
  "lon": -79.3808,
  "timezone": "America/Toronto",
  "asn": 4321,
  "org": "Example ISP"
}

Почему это различие важно для квоты

Бесплатная квота считается по сети, и для каждого семейства адресов сеть определяется по-своему: все адреса IPv4 из одной /24 делят одну квоту, и все адреса IPv6 из одной /48 делят одну квоту. Один клиент с IPv6 и большим выделенным блоком может выглядеть в ваших логах как множество разных адресов, хотя на самом деле находится в пределах одной общей квоты, а знание версии помогает группировать записи логов по правильному типу сетевой границы, а не считать каждую отдельную строку адреса не связанной с остальными.

Конкретный случай, где это даёт о себе знать

Посетитель с домашним подключением к интернету, поддерживающим оба семейства адресов, может появиться в ваших логах в виде двух, казалось бы, не связанных адресов за два визита, одного IPv4 и одного IPv6, в зависимости от того, какой из них его устройство использовало в тот день. При наивной обработке это выглядит как два разных посетителя. Группировка по версии вместе со стабильным идентификатором, например сессионной cookie, а не только по голому адресу, позволяет не завышать число посетителей и не разбивать историю одного клиента на два профиля.

Практическая работа с логами

Когда вы пишете собственную аналитику или обнаружение злоупотреблений поверх сырых логов, сначала проверяйте поле version и только потом вычисляйте сетевой префикс, поскольку маска /24 не имеет смысла для адреса IPv6, а маска /48 не имеет смысла для адреса IPv4. Храните версию рядом с самим адресом, а не вычисляйте её заново разбором строки каждый раз, когда читаете лог.

Ошибка, которой стоит избегать

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

Стоимость проверки

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

Если относиться к IPv4 и IPv6 как к действительно разным семействам адресов, а не просто к строкам разной длины, можно избежать целого класса ошибок, которые проявляются только тогда, когда трафик IPv6 становится заметной долей ваших посетителей. Эндпоинт полностью описан в документации по определению IPv6.