Найти в Дзене
Записки High-Risk CMO

Фильтрация по ASN в Keitaro 11: Полный гайд (от простого к хардкору)

В арбитраже трафика умение точно отсекать ботов и конкурентов — это половина успеха. Стандартные фильтры по IP или UserAgent часто пропускают умных ботов, а базы провайдеров (ISP) не всегда дают точную картину. Здесь на сцену выходит ASN (Autonomous System Number). Это уникальный номер, закрепленный за владельцем сети. Например, у Google это AS15169, у Facebook — AS32934. Имена провайдеров могут меняться («Google LLC», «Google Ireland», «Google Cloud»), а номер ASN остается неизменным. В этой статье разберем, как реализовать фильтрацию по ASN в Keitaro 11 (версия Advanced и выше), обойти ограничения стандартных баз и написать свой кастомный фильтр. По умолчанию Keitaro использует базу Keitaro Geo. Она отличная, легкая и бесплатная, но у неё есть нюанс: она хранит имена провайдеров, но часто вырезает сами номера ASN для экономии места. Если вы посмотрите в лог кликов, вы увидите:
ISP: Private Networks Labs LLC А нам нужно:
ISP: AS399498 Private Networks Labs LLC Без номера мы не можем
Оглавление

В арбитраже трафика умение точно отсекать ботов и конкурентов — это половина успеха. Стандартные фильтры по IP или UserAgent часто пропускают умных ботов, а базы провайдеров (ISP) не всегда дают точную картину.

Здесь на сцену выходит ASN (Autonomous System Number). Это уникальный номер, закрепленный за владельцем сети. Например, у Google это AS15169, у Facebook — AS32934. Имена провайдеров могут меняться («Google LLC», «Google Ireland», «Google Cloud»), а номер ASN остается неизменным.

В этой статье разберем, как реализовать фильтрацию по ASN в Keitaro 11 (версия Advanced и выше), обойти ограничения стандартных баз и написать свой кастомный фильтр.

Проблема: "Где мои номера?"

По умолчанию Keitaro использует базу Keitaro Geo. Она отличная, легкая и бесплатная, но у неё есть нюанс: она хранит имена провайдеров, но часто вырезает сами номера ASN для экономии места.

Если вы посмотрите в лог кликов, вы увидите:
ISP: Private Networks Labs LLC

А нам нужно:
ISP: AS399498 Private Networks Labs LLC

Без номера мы не можем использовать списки блокировок типа "ТОП-100 хостингов", которые гуляют по чатам, потому что они состоят из номеров (AS12345).

У нас есть три пути решения.

Способ 1. "Нативный" (Фильтр по имени)

Подходит для: новичков, малых объемов, блокировки конкретных ISP.

Если вы не хотите лезть в код, используйте стандартный фильтр ISP. Вам придется гуглить название ASN и вписывать его текстовое имя.

Как настроить:

  1. В потоке выбираем фильтр ISP.
  2. Пишем текстом: Amazon, Google Cloud, DigitalOcean.
  3. Режим: Reject (Отклонить).

Минусы: Неточность. Amazon может заблокировать и покупателей с Amazon Fire Tablet, и ботов с AWS. Без точного номера риск задеть лишнее выше.

Способ 2. "Профессиональный" (Платные базы)

Подходит для: больших объемов, High-load, команд.

Единственный способ заставить Keitaro видеть номера ASN "из коробки" без костылей — подключить профессиональную Geo-базу.

Что нужно:

  1. Купить лицензию IP2Location (DB4 или PX2) или MaxMind ISP.
  2. В Keitaro: Maintenance → Geo DBs → Settings. Вставить ключ.
  3. Обновить базы.

После этого в логах появится заветный формат: AS12345 Organization Name. Стандартный фильтр ISP начнет понимать номера.

Минусы: Стоит денег (от $50/мес).

Способ 3. "Хакерский" (Кастомный фильтр + API)

Подходит для: Keitaro v11, тестов, точечной фильтрации без покупки баз.

Если платить за базы рано, а фильтровать нужно сейчас, мы напишем свой фильтр на PHP. Он будет делать то, что не делает Keitaro: "стучаться" во внешний сервис (API), узнавать реальный ASN и сверять его с вашим списком.

Подготовка

В Keitaro 11 (на Docker/Podman) изменилась структура папок.
Все кастомные скрипты теперь живут здесь:
/var/www/keitaro/var/filters/

(Забудьте про application/filters, это для старых версий).

Код фильтра

Создаем файл FilterAsn.php в папке /var/www/keitaro/var/filters/.

Этот код делает две крутые вещи:

  1. Добавляет удобное поле Textarea (можно вставлять списки столбиком).
  2. Обращается к API ip-api.com, чтобы получить реальный номер ASN.

<?php
namespace Filters;

use Core\Filter\AbstractFilter;
use Core\Locale\LocaleService;
use Traffic\Model\StreamFilter;
use Traffic\RawClick;

class FilterAsn extends AbstractFilter
{
// Используем бесплатный API (лимит 45 запросов в минуту!)
private const API_URL = 'http://ip-api.com/json/%s?fields=status,as';

public function getAttribute()
{
return 'asn_custom';
}

public function getName()
{
return 'ASN (API + List)';
}

public function getModes()
{
return [
StreamFilter::ACCEPT => LocaleService::t('filters.binary_options.' . StreamFilter::ACCEPT),
StreamFilter::REJECT => LocaleService::t('filters.binary_options.' . StreamFilter::REJECT),
];
}

// Делаем большое поле для ввода
public function getTemplate()
{
return '<textarea class="form-control" ng-model="filter.payload" rows="4" placeholder="AS12345&#10;AS67890"></textarea>';
}

public function isPass(StreamFilter $filter, RawClick $rawClick)
{
$payload = $filter->getPayload();
$mode = $filter->getMode(); // IS или IS NOT

if (empty($payload)) return true;

// Превращаем список (через запятую или с новой строки) в массив
$cleanPayload = str_replace(["\r\n", "\r", "\n"], ',', $payload);
$searchValues = array_map('trim', explode(',', $cleanPayload));

$ip = $rawClick->getIp();

// Локальные IP пропускаем мимо API
if ($ip === '127.0.0.1' || $ip === '0.0.0.0') return $mode == StreamFilter::REJECT;

// Запрос к API
$asnString = $this->fetchAsnFromApi($ip);

// Если API недоступен или лимиты — считаем, что ASN не определен
if (empty($asnString)) {
return $mode == StreamFilter::REJECT;
}

$match = false;
foreach ($searchValues as $val) {
// Ищем вхождение (например, AS12345 внутри строки от API)
if ($val !== '' && stripos($asnString, $val) !== false) {
$match = true;
break;
}
}

// Логика:
// Если режим "Есть в списке" (Allow) и нашли совпадение -> Пускаем (True)
// Если режим "Нет в списке" (Block) и нашли совпадение -> Блочим (False)
return ($mode == StreamFilter::ACCEPT && $match) || ($mode == StreamFilter::REJECT && !$match);
}

private function fetchAsnFromApi($ip)
{
$url = sprintf(self::API_URL, $ip);
// Таймаут 1.5 сек, чтобы клик не висел вечно
$ctx = stream_context_create(['http' => ['timeout' => 1.5, 'ignore_errors' => true]]);
try {
$response = @file_get_contents($url, false, $ctx);
if ($response) {
$data = json_decode($response, true);
if (isset($data['as'])) return $data['as']; // Возвращает "AS12345 Name"
}
} catch (\Exception $e) { return null; }
return null;
}
}

Установка и "Подводные камни" v11

В Keitaro 11 PHP-код загружается в оперативную память демоном RoadRunner. Просто сохранить файл недостаточно — трекер его не увидит.

После сохранения файла нужно перезагрузить контейнер, отвечающий за трафик:

codeBash

kctl podman start tracker-traffic

(Или systemctl restart roadrunner-keitaro, если у вас bare-metal установка).

Как пользоваться

  1. Заходим в поток.
  2. Добавляем фильтр ASN (API + List).
  3. Вставляем список "плохих" ASN:codeTextAS15169
    AS16509
    AS14618
    AS8075
  4. Ставим IS NOT (Reject).
  5. Profit!

Важные нюансы

  1. Скорость: Запрос к внешнему API добавляет задержку к клику (от 0.1 до 1 секунды). Для пуш-трафика не критично, для попсов может быть заметно.
  2. Лимиты API: ip-api.com в бесплатной версии дает 45 запросов в минуту. Если вы льете тизеры или попсы большим объемом — вас забанят, и фильтр перестанет работать (будет пропускать всех или отклонять всех, в зависимости от настроек). Для продакшена лучше купить у них ключ или использовать прокси.
  3. Прокси на сервере: Если ваш сервер Keitaro ходит в сеть через "грязные" прокси (AstroProxy и т.д.), API может отклонить запрос соединения.

Бонус: Список ASN для блокировки дата-центров (ботов)

Вот "стартовый пакет" ASN, с которых чаще всего идут боты модераторов и спай-сервисы (хостинги):

codeText

AS15169 (Google)
AS16509 (Amazon.com)
AS14618 (Amazon.com)
AS8075 (Microsoft)
AS32934 (Facebook)
AS14061 (DigitalOcean)
AS16276 (OVH)
AS36352 (Hostinger)
AS20473 (Choopa / Vultr)
AS63949 (Linode)

Используйте с умом и всегда проверяйте логи!