Lists
Lists define named collections of domains and/or IP CIDRs used in route rules and DNS rules.
The lists key is an object where each key is the list name and the value is the list configuration.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
url |
string | no | URL to a remote list file to download and cache |
domains |
array of string | no | Inline domain patterns (supports *. prefix wildcards) |
ip_cidrs |
array of string | no | Inline IP addresses or CIDR ranges |
file |
string | no | Path to a local list file |
ttl_ms |
integer | no (default: 0) |
TTL in milliseconds for dnsmasq-resolved IPs added to the dynamic set; 0 means no timeout |
At least one of url, domains, ip_cidrs, or file must be provided. Multiple sources can be combined in a single list entry — all entries are merged.
Static and dynamic IP sets
Each list is backed by two pairs of kernel IP sets:
| Set name | Contents | TTL |
|---|---|---|
kpbr4_<list> / kpbr6_<list> |
Static IPs from ip_cidrs, file, url |
none (permanent) |
kpbr4d_<list> / kpbr6d_<list> |
IPs resolved by dnsmasq at DNS query time | ttl_ms (if set) |
Firewall MARK rules match packets whose destination address appears in either the static or dynamic set (OR semantics), so traffic is correctly routed regardless of whether the IP was loaded at startup or resolved later by dnsmasq.
The dnsmasq resolver config (ipset= / nftset= directives) references the dynamic sets (kpbr4d_* / kpbr6d_*). When a listed domain is resolved, dnsmasq writes the resulting IP directly into the dynamic set. If ttl_ms is set, that entry automatically expires after the specified duration so stale IPs from changed DNS records are removed without a daemon reload.
Static entries (from ip_cidrs, file, url) are always permanent — they persist until the next reload regardless of ttl_ms.
List File Format
Whether loaded from url or file, keen-pbr expects one entry per line:
- IPv4 address:
93.184.216.34 - IPv4 CIDR:
10.0.0.0/8 - IPv6 address:
2606:2800:220:1:248:1893:25c8:1946 - IPv6 CIDR:
2001:db8::/32 - Domain:
example.com— matches the domain and all its subdomains (dnsmasqserver=/example.com/semantics) - Wildcard domain:
*.example.org— equivalent toexample.org; the*.prefix is stripped automatically - Comments: lines starting with
#are ignored - Empty lines are ignored
Examples
Remote URL list
{
"lists": {
"remote-list": {
"url": "https://raw.githubusercontent.com/v2fly/domain-list-community/refs/heads/master/data/apple"
}
}
}Downloaded files are cached in daemon.cache_dir. If the URL is unreachable at startup, the cached copy is used.
Inline domain list
{
"lists": {
"my-domains": {
"domains": ["example.com", "other.org"]
}
}
}Both entries match the domain and all its subdomains. Writing *.example.com is equivalent to example.com — the *. prefix is stripped automatically.
Inline IP list
{
"lists": {
"my-ips": {
"ip_cidrs": [
"93.184.216.34",
"10.0.0.0/8",
"2606:2800:220:1:248:1893:25c8:1946",
"2001:db8::/32"
]
}
}
}Local file
{
"lists": {
"local-list": {
"file": "/etc/keen-pbr/my-list.txt"
}
}
}Combined sources
{
"lists": {
"combined": {
"url": "https://example.com/remote-list.txt",
"domains": ["extra.example.com"],
"ip_cidrs": ["192.168.100.0/24"],
"file": "/etc/keen-pbr/local-additions.txt",
"ttl_ms": 86400000
}
}
}All four sources are merged into a single list. ttl_ms: 86400000 sets a 24-hour TTL for dnsmasq-resolved IPs in the dynamic set (kpbr4d_combined / kpbr6d_combined). Static IPs from ip_cidrs and the cached URL/file are loaded into the permanent static set (kpbr4_combined / kpbr6_combined) and are never expired automatically.