Troubleshooting
Daemon won’t start
- Check config JSON validity — parse errors are logged to stderr on startup. Validate with
jq . /etc/keen-pbr/config.json. - PID file permissions — ensure the directory for
daemon.pid_fileexists and is writable by the process user. - Cache directory — ensure
daemon.cache_direxists and is writable. Create it if needed:mkdir -p /var/cache/keen-pbr. - Port conflict — if the API is enabled, check that the
api.listenaddress/port is not already in use.
Traffic not routed through VPN
Check the routing health endpoint:
curl http://127.0.0.1:8080/api/health/routingLook for entries with "status": "missing" or "status": "mismatch" in:
firewall— the keen-pbr chain may not be hooked into PREROUTINGfirewall_rules— fwmark rules for your sets may be missingroute_tables— routing table may not have a default route via the VPN interfacepolicy_rules— ip rule to lookup the table by fwmark may be missing
Also verify that fwmark.start, fwmark.mask, and iproute.table_start don’t conflict with existing rules:
ip rule list
ip route show table 150urltest always shows “degraded”
The urltest outbound is degraded when no child has been successfully selected.
- Check that the probe
urlis reachable from the outbound interface. - Check circuit breaker states via
GET /api/health/service— if a child shows"circuit_breaker": "open", it is in cooldown. Wait forcircuit_breaker.timeout_msto elapse. - Check that child outbound interfaces are up:
ip link show tun0. - Reduce
interval_mstemporarily to force faster re-probing.
dnsmasq not resolving domains to VPN
- Verify
generate-resolver-configproduces output:keen-pbr generate-resolver-config dnsmasq-nftset. - Ensure your dnsmasq configuration includes
conf-script=pointing to keen-pbr, e.g.:conf-script=/usr/sbin/keen-pbr generate-resolver-config dnsmasq-nftset - Restart dnsmasq after adding the
conf-script=line. - Check that
dns.ruleslists the correct list names and server tag. - If using
detour, ensure the outbound interface is up.
Remote list not updating
- Check keen-pbr logs for HTTP errors when downloading the list.
- Verify the URL is reachable from the router:
curl -I <url>. - Check
lists_autoupdate.cron— ensure the schedule is correct. - Trigger a manual reload to test:
kill -HUP $(cat /var/run/keen-pbr.pid) - Check that
daemon.cache_diris writable; failed writes prevent caching.
Port/address filter rules not matching
Mixed negation in
src_addr / dest_addr is not supported. All entries in the array must either all start with ! or none of them should.If rules aren’t matching as expected:
- Verify that
protois set correctly ("tcp","udp", or"tcp/udp") - Ensure negated address arrays use
!on every entry, not just some - Check that the list name in the rule matches exactly (case-sensitive) the key in
lists
High fwmark conflicts
If other software on your system uses the same fwmark range, packets may be misrouted or dropped.
Check for conflicts:
ip rule list
nft list ruleset | grep markAdjust to a non-conflicting range:
{
"fwmark": {
"start": "0x00020000",
"mask": "0x00FF0000"
}
}The mask must be exactly two adjacent hex nibbles. Use hex strings such as "0x00FF0000" and "0x00020000".