Build log · MikroTik · BGP + BFD failover · CHR relay
MikroTik CHR BFD failover on RouterOS
Bind BFD to the existing MikroTik/CHR BGP session over WireGuard so the IPv6 default route withdraws quickly when the relay path dies.
Build log · MikroTik · BGP + BFD failover · CHR relay
Bind BFD to the existing MikroTik/CHR BGP session over WireGuard so the IPv6 default route withdraws quickly when the relay path dies.
This is the MikroTik CHR variant of the
BGP+BFD failover companion for the
VPS path. It assumes the relay VPS is already
running RouterOS CHR with WireGuard wg-vps and an eBGP session to the home
router.
BFD does not replace BGP. It gives the existing BGP session a fast liveness signal, so the home router withdraws the learned IPv6 default route when the WireGuard path is dead instead of waiting for the BGP hold timer.
With RouterOS on both ends, the implementation is symmetric: add a BFD configuration for the WireGuard interface on each router, enable BFD on each BGP connection, and permit BFD control packets on the tunnel.
Bind BFD to the existing CHR BGP session. The CHR relay already originates
::/0 to the home router, and the home router already advertises the
routed /48 back. BFD should monitor that same eBGP session; it should not
introduce another routing path.
Permit BFD explicitly on both routers. RouterOS BFD uses UDP/3784 and UDP/3785. Add tunnel-scoped input rules on both ends so a later input-drop policy cannot leave BGP established while BFD stays down.
Keep Happy Eyeballs behavior intentional. If BFD withdraws the CHR-learned IPv6 default route and no other IPv6 default is active, clients fail IPv6 quickly and move to IPv4. Do not add another IPv6 default route unless you intentionally want a second IPv6 uplink to catch the failure.
Use the same values from the CHR relay variant of the VPS post:
| Placeholder | Meaning |
|---|---|
<LAN_PREFIX> | Routed /48, written without trailing ::. |
<HOME_AS> / <VPS_AS> | Home router and CHR private ASNs. |
wg-vps | WireGuard interface on both RouterOS peers. |
home | CHR BGP connection name toward home. |
chr-vps | Home router BGP connection name to CHR. |
The examples use <LAN_PREFIX>:0::1 on CHR and <LAN_PREFIX>:0::2 on the
home router.
Add a BFD configuration for the CHR WireGuard interface, enable BFD on the existing BGP connection, and allow BFD from the tunnel.
CHR — BFD on the home BGP connection
bash
1/routing/bfd/configuration/add interfaces=wg-vps \
2 min-rx=200ms min-tx=200ms multiplier=3 \
3 comment="Home BFD"
4
5/routing/bgp/connection/set [find name=home] use-bfd=yes
6
7/ipv6/firewall/filter/add chain=input action=accept protocol=udp \
8 in-interface=wg-vps dst-port=3784,3785 comment="BFD from home"If the CHR input policy has a final drop rule, move the BFD rule above it. For the minimal relay firewall in the CHR VPS post, placing it near the BGP input accept keeps the control-plane surface readable.
Do the matching RouterOS change on the home router.
Home router — BFD on the CHR BGP connection
bash
1/routing/bfd/configuration/add interfaces=wg-vps \
2 min-rx=200ms min-tx=200ms multiplier=3 \
3 comment="CHR VPS BFD"
4
5/routing/bgp/connection/set [find name=chr-vps] use-bfd=yes
6
7/ipv6/firewall/filter/add chain=input action=accept protocol=udp \
8 in-interface=wg-vps dst-port=3784,3785 comment="BFD from chr-vps"
9
10:local bfdRule [/ipv6/firewall/filter/find where comment="BFD from chr-vps"]
11:local dropRule [/ipv6/firewall/filter/find where chain=input and comment="defconf: drop everything else not coming from LAN"]
12/ipv6/firewall/filter/move $bfdRule destination=$dropRuleIf a BFD configuration for wg-vps already exists, edit that entry instead
of adding a duplicate. If the firewall rule already exists, enable or update
it instead of adding a second copy.
Both RouterOS peers should show BFD up, BGP established, and the learned
::/0 installed on the home router.
CHR — BFD, BGP, and return route
bash
1/routing/bfd/session/print detail
2/routing/bgp/session/print detail
3/ipv6/route/print detail where dst-address="<LAN_PREFIX>::/48"Home router — BFD, BGP, and default route
bash
1/routing/bfd/session/print detail
2/routing/bgp/session/print detail
3/ipv6/route/print detail where dst-address="::/0"
4/ping 2606:4700:4700::1111 count=3Healthy RouterOS BFD should show:
text
text
1state=up
2actual-tx-interval=200ms
3required-min-rx=200ms
4remote-min-rx=200ms
5remote-min-tx=200ms
6multiplier=3
7hold-time=600msTo prove clients get a fast signal, temporarily block BFD on the CHR side and watch the home router withdraw its IPv6 default route.
CHR — temporary BFD block
bash
1/ipv6/firewall/filter/add chain=input action=drop protocol=udp \
2 in-interface=wg-vps dst-port=3784,3785 comment="TEMP block BFD test"Home router — watch while testing
bash
1/routing/bfd/session/print detail
2/routing/bgp/session/print detail
3/ipv6/route/print detail where dst-address="::/0"Remove the temporary block after the test:
CHR — remove temporary BFD block
bash
1/ipv6/firewall/filter/remove [find comment="TEMP block BFD test"]Expected result:
| Failure condition | Router behavior |
|---|---|
| BFD down | BGP session drops quickly |
| BGP default withdrawn | ::/0 via wg-vps disappears |
| No IPv6 default left | Clients fail IPv6 quickly and try IPv4 |
| BFD restored | BGP re-establishes and ::/0 returns via wg-vps |
Comments
Comments are powered by GitHub Discussions and require a free GitHub account to post.