Перейти к содержимому
Правила маршрутизации

Правила маршрутизации

Правила маршрутизации соединяют ваши списки с вашими outbounds.

Большинству пользователей нужно только одно простое правило для каждого списка, например:

config.json
{
  "route": {
    "rules": [
      {
        "list": ["my_sites"],
        "outbound": "vpn"
      }
    ]
  }
}

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

Конфигурация

config.json
{
  "route": {
    "inbound_interfaces": [...],
    "rules": [...]
  }
}
Поле Тип Обязательно Описание
inbound_interfaces array of string нет Опциональный фильтр входящих интерфейсов. Если отсутствует или пустой, все интерфейсы доступны. Если непустой, только пакеты, входящие через перечисленные интерфейсы, обрабатываются KeenPbrTable.
rules array да Упорядоченный список правил маршрутизации

Поля правила маршрутизации

Поле Тип Обязательно Описание
enabled boolean нет Активно ли это правило. false отключает его. true, отсутствует или null все означают включено.
list array of string да Имена списков, трафик которых сопоставляется этим правилом
outbound string да Тег outbound для маршрутизации сопоставленного трафика
proto string нет Протокол: "tcp", "udp" или "tcp/udp"
dscp integer нет Значение DSCP-метки от 1 до 63
src_port string нет Сопоставлять только конкретные исходные порты
dest_port string нет Сопоставлять только конкретные порты назначения
src_addr string нет Сопоставлять только конкретные исходные адреса
dest_addr string нет Сопоставлять только конкретные адреса назначения

Примеры

Базовый — маршрутизация списка через VPN

config.json
{
  "route": {
    "rules": [
      {
        "enabled": true,
        "list": ["my_domains", "my_ips", "remote_list"],
        "outbound": "vpn"
      }
    ]
  }
}

Временное отключение правила без удаления

config.json
{
  "route": {
    "rules": [
      {
        "enabled": false,
        "list": ["my_domains"],
        "outbound": "vpn"
      }
    ]
  }
}

Когда enabled отсутствует или установлен в null, правило обрабатывается как включённое.

Фильтр входящих интерфейсов — обработка только пакетов с br0

config.json
{
  "route": {
    "inbound_interfaces": ["br0"],
    "rules": [
      {
        "list": ["my_domains"],
        "outbound": "vpn"
      }
    ]
  }
}

Фильтр входящих интерфейсов отключён (отсутствует или пустой)

Если inbound_interfaces отсутствует (по умолчанию) или явно установлен в пустой массив, фильтрация интерфейсов отключена и правила маршрутизации применяются независимо от входящего интерфейса.

config.json
{
  "route": {
    "inbound_interfaces": [],
    "rules": [
      {
        "list": ["my_domains"],
        "outbound": "vpn"
      }
    ]
  }
}

Фильтр портов — только HTTPS TCP из двух подсетей

config.json
{
  "route": {
    "rules": [
      {
        "list": ["my_domains"],
        "src_addr": "192.168.20.0/24,192.168.30.0/24",
        "proto": "tcp",
        "dest_port": "443",
        "outbound": "vpn"
      }
    ]
  }
}

Фильтр DSCP — направить маркированный трафик через VPN

DSCP (Differentiated Services Code Point) — это 6-битная метка в IP-заголовке. Обычно она используется для QoS, но keen-pbr может использовать её как условие маршрутизации: пометьте пакеты на клиентском устройстве, затем сопоставьте эту метку в правиле маршрутизации. Это удобно для маршрутизации по приложениям, когда у приложения нет стабильных доменов, IP-адресов или портов назначения.

config.json
{
  "route": {
    "rules": [
      {
        "dscp": 46,
        "outbound": "vpn"
      }
    ]
  }
}

DSCP можно комбинировать с теми же фильтрами списков, протокола, адресов и портов, что и в других правилах маршрутизации. Например, "dscp": 46 вместе с "src_addr": "192.168.10.20" направит только маркированные пакеты с этого хоста.

DSCP-метка должна уже быть в пакете, когда он приходит на роутер. Настраивайте маркировку на устройстве, где запущено приложение.

Windows: пометить одно приложение

Запустите PowerShell от имени администратора:

New-NetQosPolicy -Name "keen-pbr Zoom DSCP" -AppPathNameMatchCondition "zoom.exe" -DSCPAction 46

AppPathNameMatchCondition может быть именем исполняемого файла, например zoom.exe, или полным путём к приложению. После этого Windows будет помечать трафик подходящего приложения DSCP 46, а keen-pbr сможет маршрутизировать его правилом с "dscp": 46.

Linux: пометить трафик пользователя

В Linux можно помечать пакеты, созданные конкретным локальным пользователем. Замените ivan в примерах ниже на имя пользователя, от которого запускается приложение, которое нужно маршрутизировать.

Через nftables:

sudo nft add table inet pbr_dscp
sudo nft 'add chain inet pbr_dscp output { type route hook output priority mangle; policy accept; }'
sudo nft add rule inet pbr_dscp output meta skuid ivan ip dscp set 46
sudo nft add rule inet pbr_dscp output meta skuid ivan ip6 dscp set 46

Через iptables:

sudo iptables -t mangle -A OUTPUT -m owner --uid-owner ivan -j DSCP --set-dscp 46
sudo ip6tables -t mangle -A OUTPUT -m owner --uid-owner ivan -j DSCP --set-dscp 46

Матчер owner в iptables работает с локально созданными пакетами, а не с пересылаемым трафиком. Для DSCP-маршрутизации с Linux-ноутбука или ПК добавляйте эти правила на этом ноутбуке или ПК, а не на роутере с keen-pbr.

Фильтр адресов — сопоставление конкретной подсети источника

config.json
{
  "route": {
    "rules": [
      {
        "list": ["my_ips"],
        "src_addr": "192.168.10.0/24",
        "outbound": "vpn"
      }
    ]
  }
}

Полный фильтр — Google DNS из подсети через VPN

config.json
{
  "route": {
    "rules": [
      {
        "list": ["my_domains"],
        "src_addr": "192.168.10.0/24",
        "dest_addr": "8.8.8.8",
        "dest_port": "53",
        "outbound": "vpn"
      }
    ]
  }
}

Отрицание — все источники, кроме локальной LAN

config.json
{
  "route": {
    "rules": [
      {
        "list": ["my_ips"],
        "src_addr": "!192.168.1.0/24",
        "outbound": "vpn"
      }
    ]
  }
}

Отрицание — весь TCP, кроме HTTPS, идёт через VPN

config.json
{
  "route": {
    "rules": [
      {
        "list": ["my_domains"],
        "proto": "tcp",
        "dest_port": "!443",
        "outbound": "vpn"
      }
    ]
  }
}

Отрицание — весь UDP, кроме DNS и NTP, идёт через VPN

config.json
{
  "route": {
    "rules": [
      {
        "list": ["my_domains"],
        "proto": "udp",
        "dest_port": "!53,123",
        "outbound": "vpn"
      }
    ]
  }
}
Имейте в виду, что DNS работает поверх TCP и UDP, но это правило покрывает только UDP. Это правило показано только для справки, в реальной жизни вы, вероятно, также захотите добавить TCP-правило для порта 53.

Отрицание — блокировка трафика, НЕ идущего в доверенную подсеть

config.json
{
  "route": {
    "rules": [
      {
        "list": ["my_ips"],
        "dest_addr": "!10.0.0.0/8,172.16.0.0/12",
        "outbound": "block"
      }
    ]
  }
}
Расширенные фильтры: синтаксис адресов и портов

src_addr, dest_addr, src_port и dest_port все используют одинаковый строковый синтаксис:

Формат Пример Сопоставление
Одиночное значение "192.168.1.0/24" эта подсеть
Список "192.168.1.0/24,8.8.8.8" либо подсеть/IP
Отрицание "!192.168.1.0/24" любой источник, кроме этой подсети
Список с отрицанием "!192.168.1.0/24,8.8.8.8" любой источник, кроме любой подсети
Одиночный порт "443" порт 443
Список портов "80,443" порт 80 или 443
Диапазон портов "8000-9000" порты 8000-9000
Отрицание порта "!443" все порты, кроме 443
Список портов с отрицанием "!80,443" все порты, кроме 80 и 443

Одиночный ! в начале отрицает всё значение. Отрицание применяется ко всем записям через запятую.