// DevOps

BGP on Keenetic: how to set up dynamic routing via Entware and FRR

Published on 2026-05-30

The backbone dynamic routing protocol BGP (Border Gateway Protocol) is traditionally associated with enterprise hardware or full-fledged Linux servers. However, in modern realities the task of building resilient VPN networks (Mesh, Site-to-Site) or automatic traffic distribution often forces engineers to look for ways to run BGP on client SOHO routers.

Few people know, but starting from KeeneticOS 3.x the firmware includes an official built-in BGP component (under the hood a lightweight BIRD daemon is used, integrated with the NDM subsystem). It has no web interface at all, and all configuration is performed exclusively via the Keenetic CLI (router bgp ...). At the same time, capabilities for customizing filters, route-maps and communities in the stock solution are severely limited.

For network engineers who require full control over the protocol, a familiar Cisco-like syntax (vtysh) and maximum filtering flexibility, there is an alternative “hardcore” path — using OPKG/Entware to run a full modern FRRouting (FRR) stack.

BGP itself runs over TCP/179. Before starting integration it is important to remember: opening this port to the outside world without strict filtering makes the router vulnerable to control-plane attacks. Official Keenetic support allows installation of third-party Entware packages, but does not provide configuration guidance, so all FRR configuration is performed by the user.

2. Detailed solution

Architecture diagram

A practical interaction diagram looks like this:

             ┌──────────────────────┐
             │  Upstream / VPS / DC │
             │  AS 65001            │
             │  10.255.0.1          │
             └──────────┬───────────┘
                  WireGuard / GRE / IPIP / Ethernet
             ┌──────────▼───────────┐
             │      Keenetic         │
             │  KeeneticOS + Entware │
             │  FRR bgpd (vtysh)     │
             │  AS 65010             │
             │  10.255.0.2           │
             └──────────┬───────────┘
                 LAN / VLAN / VPN clients

It is important to understand that Keenetic in this scheme acts as a small edge router for a home, lab or office infrastructure. Its tasks include:

  • Receiving a default route or a limited set of prefixes from the VPS / central node.
  • Announcing local subnets.
  • Dynamically switching routes between backup VPN tunnels.

Keenetic is categorically not suitable for obtaining a Full-View (the full Internet routing table, consisting of more than 1M prefixes). It is an embedded device with limited CPU and RAM resources.

When BGP on Keenetic makes sense

Justified scenarios:

  1. Site-to-site VPN with dynamics: Several offices or home locations connected via WireGuard/GRE. BGP automatically notifies neighbors about the appearance or change of internal subnets.
  2. Failover between tunnels: Having primary and backup providers/VPN channels. The protocol reacts to link failures faster and cleaner than custom static-switching scripts.
  3. Lab benches: Studying BGP behavior in combination with VyOS, Cisco or other vendors on inexpensive hardware.
  4. Announcing private prefixes: Advertising routes like 10.10.10.0/24 or 192.168.30.0/24 towards the central network core.

Bad scenarios:

  • Trying to accept Full-View from an ISP.
  • Building the core network of a large provider (Production ISP Edge).
  • Publishing BGP to the outside without ACL.
  • Acting as a Route Reflector for a large number of clients.

Implementation options

The most stable and safe option that does not load the router:

Keenetic ── LAN ── Linux/VyOS/FRR (in LXC/VM/Mini-PC) ── VPN/BGP ── Upstream

The router handles only switching and NAT, and all BGP logic is encapsulated on the server. On Keenetic you only set a static route to the local Linux router.

Option B. Run BGP directly on Keenetic via Entware

The main option of this article. Requires a router model with a USB port (the storage filesystem must be EXT4) or a modern model with support for installing Entware directly into internal NAND memory (available from KeeneticOS 3.7.x). The modern FRR stack is used as the daemon.

Option C. Use the legacy Quagga stack

Quagga is the historical predecessor of FRR. This option should be considered only as a fallback scenario if FRR is not available for your router’s CPU architecture in the Entware repository. Note that the Quagga project is officially considered obsolete (active development stopped in 2018), so all new installations should use FRR.


Preparing Keenetic for FRR installation

Step 1. Enable OPKG support

In the Keenetic web interface go to Management → General settings → Edit components and enable the “Support for open packages (OPKG)” item.

If a USB drive is used, format it as EXT4, connect it to the device and select it as storage for OPKG. To install into internal memory (on supported models) use the CLI command:

(config)> opkg disk storage:

After successful installation of the Entware environment an init script /opt/etc/init.d/rc.unslung is automatically created, through which our services will be started.

Step 2. Enter Entware environment and update

Connect to Keenetic via SSH and enter the Entware shell:

(config)> exec sh

Update package lists and set a password for the superuser:

opkg update
opkg upgrade
passwd root

Step 3. Install routing packages

Search for available packages:

opkg list | grep -E '^(frr|quagga)'

If a stable FRR build is available, install the main daemon, the BGP module, the kernel interaction component and the management utility:

opkg install frr frr-bgpd frr-zebra frr-vtysh

If FRR is not available for your architecture, install legacy Quagga packages:

opkg install quagga quagga-bgpd quagga-zebra

Note: Package names in different repositories (MIPS/ARM/AArch64) may vary slightly.


Configuring BGP via FRRouting (FRR)

Let’s consider a minimal working configuration for the following inputs:

  • Keenetic autonomous system: 65010
  • VPS autonomous system: 65001
  • Keenetic tunnel IP address: 10.255.0.2
  • VPS tunnel IP address: 10.255.0.1
  • Local network behind Keenetic: 192.168.10.0/24

Step 1. Create directory structure

mkdir -p /opt/etc/frr
mkdir -p /opt/var/log/frr
mkdir -p /opt/var/run/frr

Step 2. Create frr.conf configuration file

Open editor: vi /opt/etc/frr/frr.conf and apply the following settings:

frr version 8
frr defaults traditional
hostname keenetic-bgp
log file /opt/var/log/frr/frr.log informational
service integrated-vtysh-config
!
! Filter for outgoing announcements (allow only local LAN)
ip prefix-list PL-LAN seq 10 permit 192.168.10.0/24
ip prefix-list PL-LAN seq 999 deny 0.0.0.0/0 le 32
!
! Filter for incoming announcements (block full-view, allow default and private nets)
ip prefix-list PL-IN seq 10 permit 0.0.0.0/0
ip prefix-list PL-IN seq 20 permit 10.0.0.0/8 le 24
ip prefix-list PL-IN seq 30 permit 172.16.0.0/12 le 24
ip prefix-list PL-IN seq 40 permit 192.168.0.0/16 le 24
ip prefix-list PL-IN seq 999 deny 0.0.0.0/0 le 32
!
router bgp 65010
 bgp router-id 10.255.0.2
 no bgp ebgp-requires-policy
 neighbor 10.255.0.1 remote-as 65001
 neighbor 10.255.0.1 description upstream-vps
 neighbor 10.255.0.1 timers 10 30
 !
 address-family ipv4 unicast
  network 192.168.10.0/24
  neighbor 10.255.0.1 activate
  neighbor 10.255.0.1 prefix-list PL-IN in
  neighbor 10.255.0.1 prefix-list PL-LAN out
 exit-address-family
!
line vty

Important: Explicitly setting bgp router-id is necessary because in an isolated Entware environment the zebra daemon may not always be able to correctly read the addresses of the router’s physical interfaces.

Step 3. Check the local routing table

The BGP daemon advertises the network specified in the network directive only if that prefix physically exists in the kernel routing table. Verify with:

ip route show 192.168.10.0/24

Step 4. Start services

If the FRR package from the repository automatically created init scripts, run:

/opt/etc/init.d/S*frr start

Otherwise start the daemons manually in the background:

zebra -d -f /opt/etc/frr/frr.conf -z /opt/var/run/frr/zserv.api -i /opt/var/run/frr/zebra.pid
bgpd -d -f /opt/etc/frr/frr.conf -z /opt/var/run/frr/zserv.api -i /opt/var/run/frr/bgpd.pid

Configuring the opposite side (Linux / VPS)

Example frr.conf on your cloud server:

frr version 8
frr defaults traditional
hostname upstream-vps
log syslog informational
service integrated-vtysh-config
!
ip prefix-list FROM-KEENETIC seq 10 permit 192.168.10.0/24
ip prefix-list FROM-KEENETIC seq 999 deny 0.0.0.0/0 le 32
!
ip prefix-list TO-KEENETIC seq 10 permit 0.0.0.0/0
ip prefix-list TO-KEENETIC seq 999 deny 0.0.0.0/0 le 32
!
router bgp 65001
 bgp router-id 10.255.0.1
 neighbor 10.255.0.2 remote-as 65010
 neighbor 10.255.0.2 description keenetic-router
 !
 address-family ipv4 unicast
  neighbor 10.255.0.2 activate
  neighbor 10.255.0.2 prefix-list FROM-KEENETIC in
  neighbor 10.255.0.2 prefix-list TO-KEENETIC out
  network 0.0.0.0/0
 exit-address-family

Don’t forget to enable packet forwarding on the Linux server:

sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.d/99-forwarding.conf

Autostart configuration on Keenetic

To ensure resilience after reboot create an init script /opt/etc/init.d/S80frr:

#!/opt/bin/sh

PATH=/opt/sbin:/opt/bin:/sbin:/bin:/usr/sbin:/usr/bin
CONF="/opt/etc/frr/frr.conf"
RUN_DIR="/opt/var/run/frr"
LOG_DIR="/opt/var/log/frr"
ZEBRA_PID="${RUN_DIR}/zebra.pid"
BGPD_PID="${RUN_DIR}/bgpd.pid"
ZSOCK="${RUN_DIR}/zserv.api"

start() {
  mkdir -p "$RUN_DIR" "$LOG_DIR"
  if [ -f "$ZEBRA_PID" ] && kill -0 "$(cat "$ZEBRA_PID")" 2>/dev/null; then
    echo "Zebra is already running."
  else
    zebra -d -f "$CONF" -z "$ZSOCK" -i "$ZEBRA_PID"
  fi

  if [ -f "$BGPD_PID" ] && kill -0 "$(cat "$BGPD_PID")" 2>/dev/null; then
    echo "Bgpd is already running."
  else
    bgpd -d -f "$CONF" -z "$ZSOCK" -i "$BGPD_PID"
  fi
}

stop() {
  [ -f "$BGPD_PID" ] && kill "$(cat "$BGPD_PID")" 2>/dev/null && rm -f "$BGPD_PID"
  [ -f "$ZEBRA_PID" ] && kill "$(cat "$ZEBRA_PID")" 2>/dev/null && rm -f "$ZEBRA_PID"
}

case "$1" in
  start) start ;;
  stop) stop ;;
  restart) stop; sleep 2; start ;;
  *) echo "Usage: $0 {start|stop|restart}"; exit 1 ;;
esac

Make the script executable: chmod +x /opt/etc/init.d/S80frr.


3. Diagnostics and debugging

To enter the interactive router console run:

vtysh

Key session monitoring commands:

  • show bgp summary — check neighbor state. Desired status: Established.
  • show ip bgp — view BGP prefix table.
  • show ip bgp neighbors 10.255.0.1 received-routes — routes received from the neighbor (requires soft-reconfiguration enabled).
  • show ip route bgp — routes successfully injected from BGP into the Zebra subsystem.

Exit the console with exit. To ensure that routes have been injected directly into the kernel of the Keenetic itself run from the main shell:

ip route show proto bgp

Typical faults

  1. Session stuck in Active/Connect: Check TCP/179 reachability with nc -vz 10.255.0.1 179. Check KeeneticOS built-in firewall rules — they may block incoming traffic on the tunnel interface.
  2. Session is active (Established) but no prefixes: Error in prefix-list. Verify that filters are not blocking announcements on either side.
  3. After router reboot configuration disappears: An Entware peculiarity. Services are initialized only after the disk with the EXT4 filesystem is fully mounted. Ensure the parent script rc.unslung has run.

4. Potential drawbacks of the solution

Despite the attractiveness of the scheme, running FRR on Keenetic carries architectural risks:

  • Conflict with KeeneticOS routing logic (NDM): The Keenetic OS kernel strictly controls its routing tables, Multi-WAN logic (policy routing), interface bindings and hardware offload (PPE/WhNat). Routes injected by a third-party zebra daemon directly into the Linux kernel are not visible in the Keenetic web interface. This can lead to hard-to-diagnose conflicts (for example, traffic going out via the wrong WAN interface due to table priorities).
  • Fragility of storage subsystem: If the USB flash drive fails or is unmounted due to a power failure — the whole network will go down because Entware daemons become unavailable.
  • Resource consumption: Even a small instability on the neighbor side (route flapping) will cause constant route recalculation, which can load a weak SOHO router CPU to 100% and paralyze its other functions.

Conclusion

Using BGP on Keenetic via Entware and FRR is a working, flexible but specialized tool. It is ideal for geeky installations, home labs and connecting remote points when deploying a dedicated server is impractical.

For stable commercial use (Production Enterprise) the priority choice remains moving BGP to dedicated virtual machines or using specialized devices (VyOS, MikroTik, Juniper) designed from the ground up for dynamic routing tasks.

// Contact

Need help?

Get in touch with me and I'll help solve the problem

Message on Telegram

Отвечаю в течение рабочего дня (03:00–13:00 GMT)

Или оставьте заявку здесь:

Send request
Write and get a quick reply