Skip to content

Direct links

A direct link adds a WireGuard peer on each of two spoke routers so traffic between their LANs skips the hub. The hub path stays untouched as the fallback. Both peers must be nodes: peers with a router binding (cerberd peer set <name> --routeros) whose router cerberd can reach.

Terminal window
cerberd link up site-a site-b
# link 3f9c1a2b7d04 site-a - site-b: active (hub 48ms, direct 9ms)

Nodes are named by peer name, overlay IP or a public key prefix. cerberd then:

  1. preflight: inspects both routers, checks that each spoke’s hub peer covers the remote prefixes, plans the prefixes to commit, and measures the RTT through the hub;
  2. punch: turns on a low-TTL opener on both routers, stages a tagged peer (with a temporary 169.254.x.y/32) on the leader, then timers.punch_stagger later on the follower, and waits for a handshake on both sides (timers.punch_timeout);
  3. commit: moves the remote prefixes onto the direct peers on both routers;
  4. verify: pings the remote overlay over the direct path (verify.count pings) and compares with the hub RTT;
  5. active: the direct path carries the traffic.

The result is one of:

State Meaning
active direct path in use
failed no direct handshake, or the pings were lost; everything was removed
no-gain direct worked but wasn’t at least verify.min_gain faster than the hub; removed

--force keeps a link even without the RTT gain. cerberd link up exits non-zero unless the link ends active. It can take up to a few minutes.

Terminal window
cerberd link down site-a site-b
# link site-a - site-b removed, traffic is on the hub
Terminal window
cerberd status # LINK table: state, since, hub and direct RTT
cerberd events --follow # link-punching, link-active, link-down, ...

Links are not stored in the database yet. On start cerberd reads the tagged objects on each router: healthy active links are adopted (adopted at startup in status), leftovers are cleaned up.

Active links aren’t monitored yet: if a direct path dies later (a NAT mapping expires, a site changes its public IP), traffic between the two sites is lost until you run cerberd link down to move it back to the hub.

Object Tag
direct peer comment=cerber:link:<link-id>:<staged|active>
TTL mangle rule (during the punch) comment=cerber:ttl:<link-id>

Nothing else on the router is modified. To clean up by hand: /interface wireguard peers print where comment~"cerber:".