Route Rules
Route rules connect your lists to your outbounds.
Most users only need one simple rule for each list, for example:
config.json
{
"route": {
"rules": [
{
"list": ["my_sites"],
"outbound": "vpn"
}
]
}
}Rules are checked from top to bottom. The first match wins. Traffic that matches no rule is left unmarked and follows normal system routing.
Configuration
config.json
{
"route": {
"inbound_interfaces": [...],
"rules": [...]
}
}| Field | Type | Required | Description |
|---|---|---|---|
inbound_interfaces |
array of string | no | Optional ingress-interface filter. If omitted or empty, all interfaces are eligible. If non-empty, only packets entering via listed interfaces are processed by KeenPbrTable. |
rules |
array | yes | Ordered list of route rules |
Route Rule Fields
| Field | Type | Required | Description |
|---|---|---|---|
enabled |
boolean | no | Whether this rule is active. false disables it. true, omitted, or null all mean enabled. |
list |
array of string | yes | List names whose traffic this rule matches |
outbound |
string | yes | Outbound tag to route matched traffic through |
proto |
string | no | Protocol: "tcp", "udp", or "tcp/udp" |
src_port |
string | no | Match only specific source ports |
dest_port |
string | no | Match only specific destination ports |
src_addr |
string | no | Match only specific source addresses |
dest_addr |
string | no | Match only specific destination addresses |
Examples
Basic — route a list through VPN
config.json
{
"route": {
"rules": [
{
"enabled": true,
"list": ["my_domains", "my_ips", "remote_list"],
"outbound": "vpn"
}
]
}
}Disable a rule temporarily without deleting it
config.json
{
"route": {
"rules": [
{
"enabled": false,
"list": ["my_domains"],
"outbound": "vpn"
}
]
}
}When enabled is omitted or set to null, the rule is treated as enabled.
Ingress interface filter — process only packets from br0
config.json
{
"route": {
"inbound_interfaces": ["br0"],
"rules": [
{
"list": ["my_domains"],
"outbound": "vpn"
}
]
}
}Ingress interface filter disabled (omitted or empty)
If inbound_interfaces is omitted (default) or explicitly set to an empty array, interface filtering is disabled and route rules are applied regardless of ingress interface.
config.json
{
"route": {
"inbound_interfaces": [],
"rules": [
{
"list": ["my_domains"],
"outbound": "vpn"
}
]
}
}Port filter — only HTTPS TCP from two subnets
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"
}
]
}
}Address filter — match a specific source subnet
config.json
{
"route": {
"rules": [
{
"list": ["my_ips"],
"src_addr": "192.168.10.0/24",
"outbound": "vpn"
}
]
}
}Full filter — Google DNS from a subnet through 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"
}
]
}
}Negation — all sources except local LAN
config.json
{
"route": {
"rules": [
{
"list": ["my_ips"],
"src_addr": "!192.168.1.0/24",
"outbound": "vpn"
}
]
}
}Negation — all TCP except HTTPS goes through VPN
config.json
{
"route": {
"rules": [
{
"list": ["my_domains"],
"proto": "tcp",
"dest_port": "!443",
"outbound": "vpn"
}
]
}
}Negation — all UDP except DNS and NTP goes through VPN
config.json
{
"route": {
"rules": [
{
"list": ["my_domains"],
"proto": "udp",
"dest_port": "!53,123",
"outbound": "vpn"
}
]
}
}Keep in mind that DNS is working over TCP and UDP, but this rule covers only UDP. This rule is shown just for your reference, in real life you would probably like to add TCP rule for port 53 as well.
Negation — block traffic NOT going to a trusted subnet
config.json
{
"route": {
"rules": [
{
"list": ["my_ips"],
"dest_addr": "!10.0.0.0/8,172.16.0.0/12",
"outbound": "block"
}
]
}
}Advanced filters: address and port syntax
src_addr, dest_addr, src_port, and dest_port all use the same string syntax:
| Format | Example | Matches |
|---|---|---|
| Single value | "192.168.1.0/24" |
this subnet |
| List | "192.168.1.0/24,8.8.8.8" |
either subnet/ip |
| Negation | "!192.168.1.0/24" |
any source except this subnet |
| Negated list | "!192.168.1.0/24,8.8.8.8" |
any source except either subnet |
| Single port | "443" |
port 443 |
| Port list | "80,443" |
port 80 or 443 |
| Port range | "8000-9000" |
ports 8000 through 9000 |
| Negated port | "!443" |
all ports except 443 |
| Negated port list | "!80,443" |
all ports except 80 and 443 |
A single ! at the start negates the entire value. Negation applies to all comma-separated entries.