Preparing to run ferrix next to BIRD on the production router.
- build: the config proto is now parsed in pure Rust, so building needs no
`protoc` binary. It previously worked only where one happened to be
installed; the Dockerfile in this repo could not have built.
- peers gain `local_address`, the source IP for connections we open (and
therefore the next hop we advertise). When both speakers share a host
the OS would otherwise pick an arbitrary local address and the peer,
which identifies us by address, would refuse the session. Address-family
mismatches are rejected at config load; an address the host lacks shows
up as the peer's backoff reason.
- docs/lab/prod/on-router: static musl cross-build instructions, config,
hardened systemd unit (unprivileged, SIGTERM gives BIRD a Cease),
loopback addresses for networkd, the BIRD stanza for a same-host
multihop session, and reverse-proxy examples with TLS and a password,
since the API has no authentication.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Phase 4 of the teaching demo: the daemon now brings up its own sessions.
- New dialer task per configured peer: connect with a timeout, run the
same FSM as the passive side, back off exponentially (from
connect_retry_seconds, capped at two minutes) and retry forever. Stays
idle while a session with the same remote IP and ASN already exists.
- The peer's OPEN must carry the configured ASN, otherwise the session is
refused with a Bad Peer AS notification. Inbound connections from a
configured peer's address get the same check plus the configured name
and hold time.
- SessionRegistry tracks configured peers and their dial state
(Idle / Connecting / Backoff with last error and retry time).
- /api/peers merges configured peers with live sessions so the page shows
peers that are down, why, and when the next attempt is; unconfigured
inbound sessions are listed after them.
- fake_peer gains --listen so it can stand in for a router the daemon
dials.
- Integration tests: dial and establish, reconnect after the peer closes,
wrong ASN refused, inbound from a configured address checked and named.
Not implemented: RFC 4271 §6.8 collision detection; a real router on the
other end resolves the rare race by closing one connection.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>