Перейти к содержимому
Полный пример конфигурации

Полный пример конфигурации

На этой странице приведён один полный пример конфигурации с комментариями, который показывает все поддерживаемые разделы и все поддерживаемые опции.

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

Имена списков, теги outbound и теги DNS-серверов должны соответствовать шаблону ^[a-z][a-z0-9_]*$ и не превышать 24 символа.
config.json
{
  // Необязательное имя устройства в заголовке браузера и под логотипом keen-pbr.
  // Максимальная длина: 128 символов. По умолчанию: пустая строка
  // (используется стандартный брендинг keen-pbr).
  "device_name": "Домашний роутер",

  // Глобальные настройки демона.
  // Все поля в этом разделе необязательны.
  "daemon": {
    // Путь к PID-файлу.
    // По умолчанию: PID-файл не создаётся, если поле опущено.
    "pid_file": "/var/run/keen-pbr.pid",

    // Каталог для кэша удалённых списков и метаданных кэша.
    // По умолчанию: "/var/cache/keen-pbr".
    "cache_dir": "/var/cache/keen-pbr",

    // Выбор backend firewall.
    // Поддерживаемые значения: "auto", "iptables", "nftables".
    // По умолчанию: "auto".
    "firewall_backend": "auto",

    // Пропускать пакеты, которые уже имеют fwmark, до обработки keen-pbr.
    // По умолчанию: true (также если задано null).
    "skip_marked_packets": true,

    // Очищать динамические наборы dnsmasq при полном применении или перезапуске runtime.
    // По умолчанию: true (также если задано null).
    "clear_dynamic_sets_on_apply": true,

    // Необязательный начальный размер хеш-таблицы ipset, создаваемых бэкендом iptables.
    // Не действует с nftables. Минимум: 1; максимум: 2147483648. Оставьте null
    // или опустите поле для значения по умолчанию (1024).
    // Изменение при работающем iptables пересоздаёт owned ipset и очищает
    // изученные dnsmasq адреса.
    "ipset_hashsize": null,

    // Необязательное максимальное число элементов ipset, создаваемых бэкендом iptables.
    // Не действует с nftables. Минимум: 1; максимум: 4294967295. Оставьте null
    // или опустите поле для значения по умолчанию (65536).
    // Изменение при работающем iptables пересоздаёт owned ipset и очищает
    // изученные dnsmasq адреса.
    "ipset_maxelem": null,

    // Использовать текущие наборы списков при безопасном обновлении runtime.
    // По умолчанию: true; при ошибке preflight используется PreserveSets.
    "reuse_static_sets_on_runtime_refresh": true,

    // Устанавливать IPv4/IPv6-наборы firewall и цели наборов резолвера.
    // По умолчанию: true (также если задано null). Если в системе нет IPv6,
    // keen-pbr запишет ошибку в журнал и продолжит работу только с IPv4.
    "ipv6_enabled": true,

    // Глобальное поведение strict routing для outbounds типа interface.
    // По умолчанию: false.
    "strict_enforcement": false,

    // Терминальное действие strict enforcement.
    // Допустимые значения: "unreachable" (вернуть сетевую ошибку) или
    // "blackhole" (молча отбросить пакеты). По умолчанию: "unreachable".
    "strict_enforcement_action": "unreachable",

    // Максимальный допустимый размер загружаемого удалённого контента, например URL-списков.
    // По умолчанию: 8388608 байт (8 MiB).
    "max_file_size_bytes": 8388608,

    // Максимальный размер stdout, сохраняемый для одной команды проверки firewall.
    // Используйте 0, чтобы не ограничивать размер.
    // По умолчанию: 262144.
    "firewall_verify_max_bytes": 262144,

    // Максимальное время в секундах для привилегированных helper-процессов и hook-ов.
    // Минимум: 1. По умолчанию: 30.
    "exec_timeout_seconds": 30,

    // Максимальное время в секундах ожидания генерации конфигурации резолвера
    // после завершения hook-а перезагрузки резолвера. Минимум: 1. По умолчанию: 120.
    "resolver_ready_timeout_seconds": 120,

    // Пауза в секундах после SIGTERM перед отправкой SIGKILL зависшему helper-процессу.
    // Минимум: 0. По умолчанию: 2.
    "exec_kill_grace_seconds": 2
  },

  // Настройки встроенного HTTP API и Web UI.
  // ВНИМАНИЕ: этот раздел недоступен в пакете keen-pbr-headless
  "api": {
    // Включить или выключить HTTP API / Web UI.
    // По умолчанию: false.
    "enabled": true,

    // Адрес прослушивания API-сервера.
    // По умолчанию: "0.0.0.0:12121".
    "listen": "0.0.0.0:12121",

    // Максимальный размер тела HTTP-запроса в байтах. Минимум: 1024.
    // По умолчанию: 1048576.
    "max_request_body_bytes": 1048576,

    // Максимальное время в секундах чтения HTTP-запроса.
    // Минимум: 1. По умолчанию: 15.
    "read_timeout_seconds": 15,

    // Максимальное время в секундах записи HTTP-ответа.
    // Минимум: 1. По умолчанию: 15.
    "write_timeout_seconds": 15,

    // Таймаут простоя HTTP keep-alive-соединения в секундах.
    // Минимум: 1. По умолчанию: 20.
    "keep_alive_timeout_seconds": 20,

    // Необязательные настройки аутентификации HTTP API. По умолчанию отключена.
    "authentication": {
      "enabled": false
    },

    // Точные HTTP- или HTTPS-origin, которым разрешены вызовы API с аутентификацией.
    // Если CORS не нужен, этот объект можно опустить.
    "cors": {
      "allowed_origins": ["https://router.example"]
    }
  },

  // Все поддерживаемые типы outbounds.
  // Их теги используются в route rules, detour у DNS-серверов и detour у списков.
  // Поле "type" обязательно. Поддерживаются: interface, table, blackhole,
  // ignore, urltest и icmptest.
  "outbounds": [
    {
      // "interface" отправляет трафик через конкретный сетевой интерфейс.
      "type": "interface",

      // Уникальный тег outbound.
      // По умолчанию: нет, поле обязательно.
      "tag": "vpn",

      // Имя исходящего интерфейса.
      // По умолчанию: нет, обязательно для type="interface".
      "interface": "wg0",

      // Необязательный IPv4-шлюз для interface outbound.
      // По умолчанию: null
      "gateway": "10.8.0.1",

      // Необязательный IPv6-шлюз для interface outbound.
      // По умолчанию: null
      "gateway6": "2001:db8::1",

      // Переопределение strict_enforcement для конкретного outbound.
      // Если указано, имеет приоритет над daemon.strict_enforcement.
      // По умолчанию: наследуется daemon.strict_enforcement.
      "strict_enforcement": true,

      // Переопределение терминального действия strict enforcement.
      // Допустимые значения: "unreachable" или "blackhole".
      // По умолчанию: наследуется daemon.strict_enforcement_action.
      "strict_enforcement_action": "unreachable"
    },
    
    {
      // Ещё один interface outbound, часто используемый для обычного WAN-пути.
      "type": "interface",
      "tag": "wan",
      "interface": "eth0",
      // Указывайте gateway, только если он не меняется. Для динамического WAN-шлюза
      // используйте table outbound с table=254 (основная таблица маршрутизации).
      "gateway": "172.12.33.1"
    },
    
    {
      // "table" использует уже существующую таблицу маршрутизации ядра.
      "type": "table",

      // Уникальный тег outbound.
      "tag": "wan_as_table",

      // ID существующей Linux routing table.
      // По умолчанию: нет, обязательно для type="table".
      "table": 254
    },

    {
      // "blackhole" отбрасывает совпавший трафик.
      "type": "blackhole",
      
      // Уникальный тег outbound.
      "tag": "block"
    },

    {
      // "ignore" позволяет совпавшему трафику пройти мимо обработки keen-pbr
      // и использовать обычную системную маршрутизацию.
      "type": "ignore",

      // Уникальный тег outbound.
      "tag": "direct"
    },

    {
      // "urltest" проверяет несколько кандидатов и автоматически выбирает один outbound.
      "type": "urltest",

      // Уникальный тег outbound.
      "tag": "auto_select",

      // URL для проверки задержки / доступности.
      // По умолчанию: нет, обязательно для type="urltest".
      "url": "https://www.gstatic.com/generate_204",

      // Интервал проверок в миллисекундах.
      // По умолчанию: 180000 для urltest; 60000 для icmptest.
      "interval_ms": 180000,

      // Таймаут каждой отдельной попытки проверки в миллисекундах.
      // По умолчанию: 5000 для urltest; 1000 для icmptest.
      // Не указывайте поле или задайте null, чтобы использовать значение по умолчанию для типа outbound.
      "probe_timeout_ms": 5000,

      // Не переключаться, если новый кандидат лишь немного лучше текущего.
      // Минимум: 0 мс. Для urltest по умолчанию: 100.
      "tolerance_ms": 100,

      // Поле оставлено для совместимости со старыми конфигами.
      // Urltest всегда добавляет терминальные IPv4/IPv6 маршруты unreachable как kill-switch.
      // Сейчас это поле не даёт дополнительного эффекта для outbounds типа urltest.
      "strict_enforcement": true,

      // Обработка установившихся conntrack-потоков при смене здорового кандидата.
      // Допустимые значения: "preserve" (по умолчанию) или "delete".
      // При отказе выбранного пути записи всё равно удаляются.
      "conntrack_on_switch": "preserve",

      // Упорядоченные группы outbounds.
      // По умолчанию: нет, обязательно для type="urltest".
      // Меньший weight имеет более высокий приоритет.
      "outbound_groups": [
        {
          // Относительный приоритет этой группы.
          // По умолчанию: 1.
          "weight": 1,

          // Теги кандидатов внутри этой группы.
          // Поддерживаемые дочерние типы: interface, table, blackhole.
          "outbounds": ["vpn", "wan_as_table"]
        },
        {
          // Если первая группа нездорова, keen-pbr может переключиться на эту.
          "weight": 2,
          "outbounds": ["wan", "block"]
        }
      ],

      // Поведение повторных проверок.
      "retry": {
        // Число повторных попыток до признания проверки неуспешной.
        // По умолчанию: 3.
        "attempts": 3,

        // Задержка между повторами в миллисекундах.
        // По умолчанию: 1000.
        "interval_ms": 1000
      },

      // Настройки circuit breaker для нестабильных outbounds.
      "circuit_breaker": {
        // Число последовательных ошибок до открытия circuit breaker.
        // Минимум: 1; максимум: 20. По умолчанию: 5.
        "failure_threshold": 5,

        // Число успешных проверок для возврата в нормальное состояние.
        // Минимум: 1; максимум: 20. По умолчанию: 2.
        "success_threshold": 2,

        // Пауза перед переходом из open в half-open.
        // Минимум: 1 мс; максимум: 86400000 мс. По умолчанию: 30000.
        "timeout_ms": 30000,

        // Максимум проверок, разрешённых в состоянии half-open.
        // Минимум: 1; максимум: 10. По умолчанию: 1.
        "half_open_max_requests": 1
      }
    },

    {
      // "icmptest" отправляет ICMP Echo через кандидатов и автоматически
      // выбирает здоровый outbound.
      "type": "icmptest",
      "tag": "auto_ping",

      // Интервал проверок в миллисекундах. По умолчанию: 60000.
      "interval_ms": 60000,

      // Число ICMP Echo-запросов для каждого кандидата за один запуск.
      // Минимум: 1; максимум: 10. По умолчанию: 3.
      "count": 3,

      // Максимум неудачных пакетов в успешном запуске. Минимум: 0.
      // Значение должно быть меньше count. По умолчанию: 0.
      "max_failed": 0,

      // Пауза между последовательными ICMP-попытками. Минимум: 100 мс;
      // максимум: 1000 мс. По умолчанию: 200.
      "packet_interval_ms": 200,

      // Таймаут каждой ICMP-попытки. Рабочий диапазон: 100–5000 мс.
      // По умолчанию: 1000.
      "probe_timeout_ms": 1000,

      // Ответы медленнее этого значения считаются неудачными. Минимум: 1 мс;
      // значение не должно превышать probe_timeout_ms. По умолчанию: 500.
      "max_rtt_ms": 500,

      // Не переключаться, если новый кандидат лишь немного лучше.
      // Минимум: 0 мс. По умолчанию: 10.
      "tolerance_ms": 10,

      // Сохранять или удалять установившиеся conntrack-потоки при смене
      // здорового кандидата. Допустимые значения: "preserve" (по умолчанию)
      // или "delete".
      "conntrack_on_switch": "preserve",

      // Упорядоченные группы явных пар outbound/target. Обязательно для
      // type="icmptest". Каждый кандидат требует оба поля ниже.
      "outbound_groups": [
        {
          "weight": 1,
          "candidates": [
            {
              // Тег outbound типа interface или table.
              "outbound": "vpn",
              // Литеральный IPv4- или IPv6-адрес для ping через этот outbound.
              "target": "1.1.1.1"
            },
            {
              "outbound": "wan",
              "target": "9.9.9.9"
            }
          ]
        }
      ]
    }
  ],

  // Список может использовать один или несколько источников: url, domains, ip_cidrs, file.
  "lists": {

    "inline_domains": {
      // Домены, заданные прямо в конфиге.
      // Совпадают и с самим доменом, и с его поддоменами.
      // Шаблоны вида "*.example.com" необязательны: "example.com" работает так же.
      "domains": ["example.com", "othersite.net"],

      // Сколько миллисекунд IP-адреса, разрешённые dnsmasq для этих доменов,
      // остаются в динамическом наборе. 0 означает бессрочно.
      // Задавайте значение выше dnsmasq max-cache-ttl (он указывается в секундах),
      // с запасом. При max-cache-ttl=300 используйте не менее 2100000 (35 мин).
      // По умолчанию: 0 (без таймаута); в этом примере используется 24 часа.
      "ttl_ms": 86400000
    },

    "inline_ips": {
      // IPv4/IPv6-адреса или CIDR, заданные прямо в конфиге.
      "ip_cidrs": [
        "93.184.216.34",
        "10.0.0.0/8",
        "2001:db8::1",
        "2001:db8::/32"
      ]
    },

    "remote_list": {
      // URL удалённого списка.
      "url": "https://raw.githubusercontent.com/v2fly/domain-list-community/refs/heads/master/data/apple",

      // Необязательный outbound, через который будет загружаться этот список.
      // Поддерживаются routable-типы, такие как interface, table или urltest.
      // По умолчанию: null (используется обычная системная маршрутизация)
      "detour": "auto_select",

      // Сколько миллисекунд IP-адреса, разрешённые dnsmasq для этих доменов,
      // остаются в динамическом наборе. 0 означает бессрочно.
      // Задавайте значение выше dnsmasq max-cache-ttl (он указывается в секундах),
      // с запасом. При max-cache-ttl=300 используйте не менее 2100000 (35 мин).
      // По умолчанию: 0 (без таймаута); в этом примере используется 24 часа.
      "ttl_ms": 86400000
    },
  
    "local_file_list": {
      // Путь к локальному файлу списка.
      "file": "/etc/keen-pbr/local.lst",
      
      // Сколько миллисекунд IP-адреса, разрешённые dnsmasq для этих доменов,
      // остаются в динамическом наборе. 0 означает бессрочно.
      // Задавайте значение выше dnsmasq max-cache-ttl (он указывается в секундах),
      // с запасом. При max-cache-ttl=300 используйте не менее 2100000 (35 мин).
      // По умолчанию: 0 (без таймаута); в этом примере используется 24 часа.
      "ttl_ms": 86400000
    },

    "mixed_sources": {
      // В текущих версиях keen-pbr можно объединять несколько источников в одном списке.
      // Это поддерживается, но отдельные списки обычно проще сопровождать.
      "domains": ["intranet.example"],
      "ip_cidrs": ["192.168.50.0/24"],
      "file": "/etc/keen-pbr/mixed.lst",
      "url": "https://example.com/mixed.lst",
      "detour": "vpn",
      // ttl_ms применяется к доменным источникам этого списка. Рекомендации по
      // выбору значения приведены в примере inline_domains выше.
      "ttl_ms": 86400000
    }
  },

  // DNS-конфигурация.
  // dns.system_resolver обязателен для работающего демона.
  "dns": {
    // Резолвер, используемый для runtime-интеграции и TXT health checks.
    // По умолчанию: нет, поле обязательно для работающего демона.
    "system_resolver": {
      "address": "127.0.0.1"
    },

    // Необязательный встроенный DNS-сервер для проверки Web UI и диагностики.
    // Чтобы проверить, что этот компьютер отправляет DNS-запросы через keen-pbr, выполните:
    // > nslookup check.keen.pbr
    // В ответе должен быть указан answer_ipv4 (127.0.0.88).
    "dns_test_server": {
      // IPv4-адрес прослушивания в формате host:port.
      // По умолчанию: нет, обязателен если dns_test_server присутствует.
      "listen": "127.0.0.88:12153",

      // IPv4 A-record, возвращаемый probe server.
      // По умолчанию: часть адреса listen, содержащая хост.
      "answer_ipv4": "127.0.0.88"
    },

    // Все поддерживаемые типы DNS-серверов.
    "servers": [
      {
        // Обычный static DNS-сервер без detour.
        "tag": "google_dns",

        // Поддерживаемые значения: "static" (по умолчанию) или "keenetic".
        // По умолчанию: "static".
        "type": "static",

        // Адрес для static DNS-серверов.
        // По умолчанию: нет, обязателен для type="static".
        "address": "8.8.8.8"
      },

      {
        // Static DNS-сервер, доступ к которому идёт через interface outbound.
        "tag": "vpn_dns",
        "address": "10.8.0.1:5353",

        // Необязательный outbound, через который нужно обращаться к этому DNS-серверу.
        // Поддерживаемые detour-цели: interface, table, urltest.
        // Не допускаются: blackhole, ignore.
        // По умолчанию: использовать обычную системную маршрутизацию.
        "detour": "vpn"
      },

      {
        // Static DNS-сервер через urltest outbound.
        "tag": "auto_dns",
        "address": "[2606:4700:4700::1111]:53",
        "detour": "auto_select"
      },

      {
        // Использовать встроенные DNS-настройки роутера через RCI.
        // Сначала настройте DoT/DoH на роутере, затем добавьте этот Keenetic DNS-сервер.
        // Доступно только на роутерах Keenetic и Netcraze.
        "tag": "keenetic_dns",
        "type": "keenetic"
      }
    ],

    // Правила сопоставления доменов и DNS-серверов.
    "rules": [
      {
        // Активно ли это DNS-правило.
        // По умолчанию: true, если поле опущено или равно null.
        "enabled": true,

        // Списки, чьи домены нужно резолвить этим сервером.
        "list": ["inline_domains", "remote_list"],

        // Тег DNS-сервера.
        "server": "vpn_dns",

        // Разрешить ответы, которые указывают на приватные / локальные IP-диапазоны.
        // По умолчанию: false.
        "allow_domain_rebinding": false
      },

      {
        // Пример правила для локальных сервисов, которые специально резолвятся в RFC1918-адреса.
        "list": ["mixed_sources"],
        "server": "keenetic_dns",
        "allow_domain_rebinding": true
      },

      {
        // Пример отключённого DNS-правила, оставленного на будущее.
        "enabled": false,
        "list": ["inline_domains"],
        "server": "google_dns"
      }
    ],

    // Upstream DNS-серверы, используемые если ни одно DNS-правило не совпало.
    // По умолчанию: upstream-серверы не заданы.
    // ВНИМАНИЕ: если вы не укажете здесь хотя бы один DNS-сервер, доступ в интернет может перестать работать.
    "fallback": ["google_dns", "auto_dns", "keenetic_dns"]
  },

  // Настройки распределения firewall mark.
  // Этот раздел необязателен.
  "fwmark": {
    // Первый fwmark, который назначается routable outbounds, в hex-строке.
    // По умолчанию: "0x00010000".
    "start": "0x00010000",

    // Битовая маска fwmark в hex-строке.
    // Должна содержать один или несколько последовательных F-нибблов.
    // По умолчанию: "0x00FF0000".
    "mask": "0x00FF0000"
  },

  // Настройки выделения policy-routing table.
  // Этот раздел необязателен.
  "iproute": {
    // Первый ID таблицы маршрутизации для автоматически выделяемых outbound-таблиц.
    // По умолчанию: 150.
    // Избегайте зарезервированных ID, таких как 128 и 250-260.
    "table_start": 150,

    // Первый приоритет policy-routing rule для выделения.
    // По умолчанию: null, то есть используется table_start.
    "rule_priority_start": null
  },

  // Правила обработки маршрутизации.
  "route": {
    // Необязательный фильтр по входящим интерфейсам.
    // Если поле опущено или пустое, keen-pbr обрабатывает пакеты с любых интерфейсов.
    // По умолчанию: фильтр отсутствует.
    "inbound_interfaces": ["br0", "wg-lan"],

    "rules": [
      {
        // Базовое правило маршрутизации по списку.
        // По умолчанию для enabled: true, если поле опущено или равно null.
        "list": ["inline_domains", "remote_list"],
        "outbound": "auto_select"
      },

      {
        // Маршрутизировать inline IP через существующую таблицу маршрутизации.
        "list": ["inline_ips"],
        "outbound": "wan_as_table"
      },

      {
        // Пример полного фильтра с DSCP, proto, адресом источника/назначения и портом назначения.
        "enabled": true,

        // Сопоставлять трафик только если домен/IP назначения есть в списке
        "list": ["mixed_sources"],

        // Сопоставлять трафик только если протокол TCP
        // Возможные значения: null (любой протокол), tcp, udp, tcp/udp
        "proto": "tcp",

        // Сопоставлять трафик только если DSCP-метка равна этому значению.
        // Поддерживается: целое число от 1 до 63.
        "dscp": 46,

        // Сопоставлять трафик только если совпадает IP источника
        // Поддерживается: один IP, CIDR
        "src_addr": "192.168.10.0/24,192.168.20.0/24",

        // Сопоставлять трафик только если совпадает IP назначения
        // Поддерживается: один IP, CIDR
        "dest_addr": "203.0.113.0/24",

        // Сопоставлять трафик только если совпадает порт источника
        // Поддерживается: один порт, несколько портов через запятую, диапазон
        "src_port": "1024-65535",

        // Сопоставлять трафик только если совпадает порт назначения
        // Поддерживается: один порт, несколько портов через запятую, диапазон
        "dest_port": "443,8443",

        // Направить весь совпавший трафик в этот outbound
        "outbound": "vpn"
      },

      {
        // В rules можно не указывать "list", если есть другое условие.
        // Этот пример блокирует DNS на любые адреса, кроме доверенной подсети резолвера.
        "proto": "udp",
        "dest_port": "53",
        "dest_addr": "!10.10.0.0/16",
        "outbound": "block"
      },

      {
        // Пример правила "ignore", используемого как исключение перед более широкими VPN-правилами.
        "src_addr": "192.168.1.0/24",
        "dest_addr": "192.168.0.0/16",
        "outbound": "direct"
      },

      {
        // Пример IPv6: направить HTTPS-трафик к подсети документации через VPN.
        "proto": "tcp",
        "src_addr": "2001:db8:10::/64",
        "dest_addr": "2001:db8:203::/48",
        "dest_port": "443",
        "outbound": "vpn"
      },

      {
        // Пример отключённого правила, оставленного на будущее.
        "enabled": false,
        "list": ["inline_domains"],
        "proto": "tcp/udp",
        "dest_port": "!80,443",
        "outbound": "wan"
      }
    ]
  },

  // Автоматическое обновление URL-списков.
  // Этот раздел необязателен.
  "lists_autoupdate": {
    // Включить или выключить периодическое обновление.
    // По умолчанию: false.
    "enabled": true,

    // Стандартное 5-полевое cron-выражение.
    // Обязательно, когда enabled=true.
    // Значение по умолчанию отсутствует.
    "cron": "0 4 * * 0"
  }
}

Примечания

  • dns.servers[].detour поддерживает outbounds типов interface, table и urltest, но не blackhole и не ignore.
  • lists[].detour полезен, когда удалённый список нужно загружать через VPN или другой нестандартный маршрут.
  • route.rules[] должен содержать хотя бы одно условие совпадения: list, dscp, src_port, dest_port, src_addr или dest_addr.
  • dns.rules[].allow_domain_rebinding в основном нужен для внутренних доменов, которые специально резолвятся в приватные IP-адреса.