Troubleshooting
Start with logs and service status, then move to DNS, firewall, routing tables, and interfaces. In keen-pbr 3.x the daemon actively writes failure reasons to the system log, so logs are usually faster than guessing from symptoms.
Quick Diagnostic Order
- Check the system log for
keen-pbranddnsmasqerrors. - Check that the
keen-pbranddnsmasqservices are running. - If
keen-pbrcrashes during startup, run it manually in foreground mode to see more logs:keen-pbr --log-level verbose service. - Check DNS: the user device must use the router DNS, and
dnsmasqmust answer locally. - Check the firewall:
keen-pbrrules must be present inKeenPbrTable. - Check policy routing: the
fwmarkmust point to the expected routing table. - Check interfaces and VPN tunnels.
- If the problem remains, check remote lists,
urltest, rule filters, and low-level routing conflicts.
System Log
This is the first place to look. Search for keen-pbr, dnsmasq, and the [E] / [W] levels: keen-pbr uses those prefixes for errors and warnings. If libraries for iptables / nftables are missing, an interface is not found, the API port is busy, or JSON is broken, the reason is usually written here.
In the Keenetic Web UI, open Diagnostics -> System log.
From the console, read the log like this:
ndmc -c "show log once" | grep -E 'keen-pbr|dnsmasq|\[E\]|\[W\]|error|warn|warning'Service Does Not Start
In this scenario, do not start by editing the config blindly. Check status first, then read the logs immediately.
- Confirm that the config exists:
bash
ls -l /opt/etc/keen-pbr/config.json - Restart
keen-pbr:bash/opt/etc/init.d/S80keen-pbr restart - Check
keen-pbrstatus:bash/opt/etc/init.d/S80keen-pbr status - Check
dnsmasqstatus:bash/opt/etc/init.d/S56dnsmasq status - Read the system log:
bash
ndmc -c "show log once" | grep -E 'keen-pbr|dnsmasq|\[E\]|\[W\]|error|warn|warning'
If keen-pbr does not stay running, stop the managed service and run the daemon manually in foreground mode with verbose logs. The error will appear directly in the console.
/opt/etc/init.d/S80keen-pbr stop
keen-pbr --log-level verbose serviceNormally the foreground command does not return a prompt while the daemon is running. If it exits immediately, the last error in the output is usually the cause.
Advanced checks
- Validate JSON:
jq . /opt/etc/keen-pbr/config.json- Make sure the directory for
daemon.pid_fileexists and is writable. - Make sure
daemon.cache_direxists and is writable. - If the API is enabled, check that the address and port from
api.listenare not already used by another process. - If logs mention a firewall backend error, check that
iptables/ipsetornftablesis installed for your platform. - If
keen-pbris alive but Web UI does not open, make sure the config was not replaced with a headless-only example and thatconfig.jsoncontains theapisection.
Sites Are Not Going Through the VPN
- Make sure the user device is using the router DNS.
- Open
http://<router-ip>:12121/and look at the DNS Check widget. It should say “DNS request from the browser reached dnsmasq”. - Alternatively, run this from your PC:
nslookup check.keen.pbr. It should return127.0.0.88.
- Open
- Run a routing test:
- Open
http://<router-ip>:12121/and enter a domain or IP into the “Where does this traffic go?” widget. - Alternatively, run this from the router or server:
bash
keen-pbr test-routing google.com
- Open
- Make sure the domain or IP is in the correct list.
- Make sure the route rule for that list points to the expected outbound.
- Make sure the VPN interface is actually up and passing traffic.
If the expected and actual outbounds differ, continue through the DNS, firewall, and routing sections below.
DNS and dnsmasq
DNS must pass the whole chain: the client uses the router DNS, dnsmasq is running, the generated keen-pbr config is included, domains are placed into ipset or nftset, and ordinary domains go to dns.fallback.
Check DNS From the User Device
Open http://<router-ip>:12121/ and check DNS Check. If Web UI is unavailable, run this from the client device:
nslookup check.keen.pbrExpected response: 127.0.0.88. If there is no response, the device is not using the router DNS or dnsmasq is not answering.
Check dnsmasq on the Router or Server
/opt/etc/init.d/S56dnsmasq status
nslookup google.com 127.0.0.1If client DNS requests do not reach Entware dnsmasq, check the Keenetic-only setting:
opkg dns-overrideAfter changing it, save the Keenetic configuration:
system configuration saveExpected result: nslookup <domain> 127.0.0.1 returns IP addresses. If you see Connection refused, dnsmasq is not running or is not listening on 127.0.0.1:53.
Check the Generated Resolver Config
Choose the backend used on your system.
keen-pbr generate-resolver-config dnsmasq-ipsetExpected output contains directives like ipset=/example.com/<set>.
The command should not exit with an error. If it says the remote list cache is missing, run:
keen-pbr downloadIf DNS rules do not work
- Make sure the list name in
dns.rulesexactly matches the list name inlists. - Make sure the DNS rule points to the correct DNS server tag.
- If the DNS server uses
detour, make sure the selected outbound works. - Make sure the
dnsmasqconfig includes the generated config throughconf-file=orconf-script=. - Restart
keen-pbranddnsmasq, then check logs again.
Websites Are Not Opening: DNS_PROBE_FINISHED_NXDOMAIN / ERR_NAME_NOT_RESOLVED
- Make sure
dns.fallbackis configured and points to at least one working DNS server tag. - Make sure the fallback DNS server is reachable from the router or server. If that DNS server uses
detour, check the selected outbound. - Make sure the user device is using the router DNS.
- Restart
keen-pbrafter changing DNS configuration.
Example:
{
"dns": {
"servers": [
{
"tag": "default_dns",
"address": "1.1.1.1"
}
],
"fallback": ["default_dns"]
}
}Without dns.fallback, domains that do not match any dns.rules entry may fail to resolve.
Websites Are Not Opening: DNS_PROBE_FINISHED_BAD_CONFIG
This usually means dnsmasq is not running or failed to apply its configuration.
- Check
dnsmasqlogs. - Check
dnsmasqstatus. - If you recently changed DNS settings, restart
keen-pbranddnsmasq.
ndmc -c "show log once" | grep dnsmasq
/opt/etc/init.d/S56dnsmasq statusFirewall and KeenPbrTable
If DNS works and the domain resolves, but traffic still bypasses the VPN, check the firewall. keen-pbr creates an isolated chain or table named KeenPbrTable; traffic must enter it, match configured lists, and receive the correct fwmark.
First run the general self-check:
keen-pbr statusLook for firewall checks with missing, mismatch, or ERROR status.
Check Firewall Rules
iptables-save | grep KeenPbrTable
ip6tables-save | grep KeenPbrTableExpected result: there is a jump from PREROUTING to KeenPbrTable and packet marking rules. Example of a healthy rule:
-A KeenPbrTable -m set --match-set <set> dst -j MARK --set-xmark <mark>/<mask>To check set contents:
ipset list
ipset test <set_name> <IP-address>Expected response for a match: the IP is in the specified set.
If KeenPbrTable is missing, return to keen-pbr logs: the cause is usually an unavailable backend, permissions, missing packages, or a configuration error.
Routing Tables and fwmark
If the firewall marks packets but the site loads forever or opens through the ISP, check policy routing. The OS must see the fwmark, apply an ip rule, and send the packet to the routing table for the expected outbound.
-
Check the state expected by
keen-pbr:bashkeen-pbr statusLook for lines with
missing,mismatch, orERRORstatus. -
Check a specific domain or IP:
bashkeen-pbr test-routing google.comExpected result: expected and actual outbound match.
-
Check policy rules:
baship rule showExpected result: there is a rule like
fwmark <mark> lookup <table>. -
Check the routing table:
baship route show table <table_number>Expected result: the table has a route through the expected VPN interface or gateway. For a blackhole outbound, a blackhole route is expected.
If the table is empty, the interface is not found, or the rule points to the wrong place, check the outbound name, interface name, and fwmark / iproute.table_start conflicts.
Interfaces and VPN Tunnels
If DNS, firewall, and policy routing look correct, check that the interface itself exists, is up, and can send traffic.
- Open
http://<router-ip>:12121/and check runtime state for outbounds and interfaces. - Get the interface list through the REST API:
bash
curl http://127.0.0.1:12121/api/runtime/interfaces - Compare with system state:
bash
ip link show ip addr show ip route - Check egress through a specific VPN interface:
bash
curl -v --interface <interface_name> https://ifconfig.co/json
Expected result: curl returns the external VPN IP. If the command hangs or exits with an error, the problem is below keen-pbr: the tunnel is down, there is no route, the gateway is unreachable, or outbound traffic is blocked.
If you use urltest or fallback
- Check that child outbounds have correct interfaces or tables.
- Check
GET /api/health/serviceand runtime outbound state in Web UI. - If the circuit breaker is
"open", wait forcircuit_breaker.timeout_msto expire or fix the unavailable child outbound. - If the backup interface does not activate, first check each child outbound separately with
curl --interface.
Remote Lists Do Not Update
- Run on the router or server:
bash
keen-pbr download - If the list still does not update, check whether the URL is reachable from the same system.
- If the list should be downloaded through VPN, check
lists[].detourand the corresponding outbound. - If automatic refresh is used, check
lists_autoupdate.cron. - After an error, read
keen-pbrlogs again.
Advanced checks
If you need to force a full reload:
kill -HUP $(cat /var/run/keen-pbr.pid)If your config sets a different daemon.pid_file, use that path. Also confirm that daemon.cache_dir is writable.
urltest Always Shows Degraded
- Make sure the test
urlis reachable and returns a good HTTP response, such as200 OKor204 No Content. - For custom probes, HTTP URLs are strongly recommended over HTTPS. HTTPS probes can be unstable because of expired certificates, incomplete trust chains, or TLS limitations on the router. For
urltest, the final2xxHTTP status is considered successful. - Recommended default URL:
https://www.gstatic.com/generate_204. - Make sure child outbounds work separately.
- Check interfaces with
curl --interface <interface_name> https://ifconfig.co/json. - Wait for the next probe cycle, or temporarily lower
interval_msduring diagnostics. - Check
GET /api/health/servicefor circuit breaker state. If a child outbound is"open", wait forcircuit_breaker.timeout_ms.
Port/Address Filter Rules Not Matching
When using negation in src_addr / dest_addr fields, the negation applies to all IP addresses/subnets specified in that field. Mixing entries with negation and without negation in the same list is not supported. As an alternative, you can create two separate rules.
This is also valid for src_port / dest_port.
If rules are not matching as expected:
- Verify that
protois set correctly:nullfor any protocol,"tcp","udp", or"tcp/udp". - Check that the list name in the rule exactly matches the key in
lists, including case. - Run
keen-pbr test-routing <domain-or-ip>and compare expected / actual. - Check
keen-pbr statusto see whether firewall rules were created for this rule.
Low-Level Routing Conflicts
If you changed fwmark or iproute, or another tool manages policy routing on the same system, packets may be misrouted or dropped.
Check for conflicts:
keen-pbr status
ip rule show
ip route show table allFor firewall marks:
iptables-save | grep -E 'MARK|CONNMARK|KeenPbrTable'
ip6tables-save | grep -E 'MARK|CONNMARK|KeenPbrTable'Move fwmark to a non-conflicting range:
{
"fwmark": {
"start": "0x00020000",
"mask": "0x00FF0000"
}
}The mask must consist of one or more adjacent hex nibbles set to F and be aligned to a nibble boundary. Use hex strings such as "0x00FF0000" and "0x00020000".