README for a public release
What Ferrix is and does, that it routes AS210036, how to build it and try it without a router, the security points an operator must know, and a note that the code is written with an AI coding agent under the maintainer's review. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
35ce2e2e57
commit
3a1e42e594
1 file changed
+132
-38
@@ -1,45 +1,97 @@
|
|||||||
# Ferrix BGP
|
# Ferrix BGP
|
||||||
|
|
||||||
An implementation of the Border Gateway Protocol, which is used to exchange routing and control plane information between Autonomous Systems.
|
Ferrix is a BGP daemon for Linux routers, written in Rust. It exchanges
|
||||||
|
routes with neighbors, filters them by policy and the RPKI, selects the
|
||||||
|
best path for each prefix, installs it in the kernel, and passes routes on
|
||||||
|
as BGP roles and communities permit. It aims to be small, safe, observable,
|
||||||
|
and configured from one file that can be read by someone who did not write
|
||||||
|
it.
|
||||||
|
|
||||||
The aim of this project is to provide a modern, high performance, secure, programmatic and customizable software package that can be useful to network operators, researchers, and people interested in Internet.
|
## Status
|
||||||
|
|
||||||
## Current status
|
Ferrix routes the author's network, AS210036: three routers carrying full
|
||||||
|
tables from transit providers, route servers at several Internet exchanges,
|
||||||
|
and bilateral peers, with routes reflected between the routers over iBGP.
|
||||||
|
It is young software all the same. Read the [limitations](#not-supported)
|
||||||
|
before relying on it, and treat version `0.x` as meaning that configuration
|
||||||
|
and APIs may still change between releases.
|
||||||
|
|
||||||
The daemon establishes BGP sessions with configured neighbors, evaluates received routes against import policy, validates them with the RPKI (route origin validation and ASPA), selects the best path for each prefix, and, on Linux, installs it in the kernel. It advertises the routes that it originates and, to neighbors configured for it, the best paths learned from other neighbors, as BGP roles (RFC 9234) and communities permit.
|
What it does:
|
||||||
|
|
||||||
Ferrix has not been deployed in a production network.
|
- BGP-4 over IPv4 and IPv6, with four-octet AS numbers, multiprotocol
|
||||||
|
reach for both families, IPv4 routes with IPv6 next hops (RFC 8950),
|
||||||
|
route refresh, graceful restart and ADD-PATH receive.
|
||||||
|
- Import policy per neighbor: prefix limits, prefix and origin AS lists,
|
||||||
|
bogon checks, AS path checks, and communities added on the way in.
|
||||||
|
- Route origin validation and ASPA path verification against an RTR cache.
|
||||||
|
- BGP roles (RFC 9234) and the Only to Customer attribute, with export
|
||||||
|
limits as a second line of defence against route leaks.
|
||||||
|
- Best path selection and installation of the result in the Linux kernel
|
||||||
|
over netlink, in a routing table of your choice.
|
||||||
|
- Route reflection between routers of the same AS, and passive neighbors.
|
||||||
|
- A status page, a JSON API, server-sent events, and Prometheus metrics.
|
||||||
|
- Graceful restart of the daemon itself for upgrades, with routes left in
|
||||||
|
the kernel while it is away.
|
||||||
|
|
||||||
### Unsupported Features
|
### Not supported
|
||||||
|
|
||||||
- Per-client best path selection for route servers, and ADD-PATH for advertised routes
|
- Per-client best path selection for route servers, and ADD-PATH for
|
||||||
|
advertised routes
|
||||||
- TCP-AO, TCP MD5, and GTSM
|
- TCP-AO, TCP MD5, and GTSM
|
||||||
- Long-Lived Graceful Restart, BFD, and configuration changes without a restart
|
- Long-Lived Graceful Restart, BFD, and configuration changes without a
|
||||||
|
restart
|
||||||
- Recursive resolution of next hops that are not directly connected
|
- Recursive resolution of next hops that are not directly connected
|
||||||
|
- Address families other than IPv4 and IPv6 unicast
|
||||||
|
|
||||||
### Layout
|
## Building
|
||||||
|
|
||||||
| Crate | What is in it |
|
You need a stable Rust toolchain from [rustup.rs](https://rustup.rs), and a
|
||||||
|-------|---------------|
|
C compiler and `make` for the jemalloc allocator the daemon uses (for
|
||||||
| `crates/primitives` | Prefixes, address families, parsing helpers |
|
example `build-essential` on Debian and Ubuntu, `base-devel` on Arch Linux,
|
||||||
| `crates/packet` | The wire format: messages, attributes, capabilities |
|
or the Xcode command line tools on macOS). The Protocol Buffers compiler is
|
||||||
| `crates/rib` | The routing table, best route selection, the journal of changes |
|
not needed: the configuration schema is compiled in pure Rust.
|
||||||
| `crates/rpki` | The RTR client; origin validation and ASPA path verification |
|
|
||||||
| `crates/fib` | The best routes in the Linux kernel, over netlink |
|
```bash
|
||||||
| `crates/server` | Sessions, the state machine, policy, configuration |
|
git clone https://git.rayhaan.net/rayhaan/ferrix.git
|
||||||
| `crates/web` | The status page, HTTP API and metrics |
|
cd ferrix
|
||||||
| `crates/integration-tests` | A test server and test peers, and the tests that run the daemon end to end |
|
cargo build --release --locked -p bgp
|
||||||
| `crates/bench` | Benchmarks at the scale of the Internet routing table |
|
```
|
||||||
| `bin/bgp` | The daemon |
|
|
||||||
|
The binary is `target/release/bgp`. `--locked` builds with the dependency
|
||||||
|
versions recorded in `Cargo.lock`, which are the versions CI tested.
|
||||||
|
|
||||||
|
To try it without touching any router, run the quick-start configuration.
|
||||||
|
It listens on loopback, needs no privileges, and serves the status page at
|
||||||
|
<http://127.0.0.1:8080>; the [quick start
|
||||||
|
guide](docs/content/docs/getting-started/quick-start.md) adds a test peer
|
||||||
|
that announces routes to it.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
target/release/bgp --check docs/examples/quick-start.textpb
|
||||||
|
target/release/bgp docs/examples/quick-start.textpb
|
||||||
|
```
|
||||||
|
|
||||||
|
Other ways to build:
|
||||||
|
|
||||||
|
- **A static Linux executable** that runs on any x86_64 distribution with
|
||||||
|
nothing else installed: `scripts/build-static.sh`. It needs the
|
||||||
|
`x86_64-unknown-linux-musl` target and a musl C compiler; the script's
|
||||||
|
header says how to install them, including on macOS.
|
||||||
|
- **A container image** with the provided `Dockerfile`:
|
||||||
|
`docker build -t ferrix .`
|
||||||
|
|
||||||
|
Kernel route installation needs Linux and `CAP_NET_ADMIN`; everywhere else
|
||||||
|
Ferrix is a BGP speaker only. The [installation
|
||||||
|
guide](docs/content/docs/getting-started/installation.md) and the
|
||||||
|
[deployment guide](docs/content/docs/operations/deployment.md) cover
|
||||||
|
privileges, the systemd unit, and upgrading without withdrawing routes.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
The documentation is a website built from [`docs/`](docs/) with
|
The documentation is a website built from [`docs/`](docs/) with
|
||||||
[Zola](https://www.getzola.org):
|
[Zola](https://www.getzola.org) (`zola --root docs serve`, then
|
||||||
|
<http://127.0.0.1:1111>). The pages are plain Markdown and can be read
|
||||||
```
|
in the repository:
|
||||||
zola --root docs serve # http://127.0.0.1:1111
|
|
||||||
```
|
|
||||||
|
|
||||||
- [Overview](docs/content/docs/getting-started/introduction.md),
|
- [Overview](docs/content/docs/getting-started/introduction.md),
|
||||||
[installation](docs/content/docs/getting-started/installation.md) and
|
[installation](docs/content/docs/getting-started/installation.md) and
|
||||||
@@ -63,36 +115,78 @@ zola --root docs serve # http://127.0.0.1:1111
|
|||||||
[testing](docs/content/docs/development/testing.md) and
|
[testing](docs/content/docs/development/testing.md) and
|
||||||
[contributing](docs/content/docs/development/contributing.md)
|
[contributing](docs/content/docs/development/contributing.md)
|
||||||
|
|
||||||
|
Complete configurations for an edge router, an exchange router and a
|
||||||
|
transit customer are in [`docs/examples/`](docs/examples/); CI checks that
|
||||||
|
each of them loads.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- The status page and HTTP API are not authenticated and show the whole
|
||||||
|
configuration and routing table. Bind `http_endpoint` to a loopback
|
||||||
|
address, or put it behind a proxy that authenticates.
|
||||||
|
- Ferrix does not implement TCP-MD5 or TCP-AO. Filter TCP port 179 in the
|
||||||
|
host firewall so that only configured neighbors can connect.
|
||||||
|
- Everything read from the network, the RPKI cache, and the kernel is
|
||||||
|
parsed without panicking; each parser has property tests and a fuzz
|
||||||
|
target. `unsafe` code is forbidden throughout.
|
||||||
|
|
||||||
|
If you find a vulnerability, please contact the maintainer directly rather
|
||||||
|
than opening a public issue.
|
||||||
|
|
||||||
|
## Layout
|
||||||
|
|
||||||
|
| Crate | What is in it |
|
||||||
|
| -------------------------- | -------------------------------------------------------------------------- |
|
||||||
|
| `crates/primitives` | Prefixes, address families, parsing helpers |
|
||||||
|
| `crates/packet` | The wire format: messages, attributes, capabilities |
|
||||||
|
| `crates/rib` | The routing table, best route selection, the journal of changes |
|
||||||
|
| `crates/rpki` | The RTR client; origin validation and ASPA path verification |
|
||||||
|
| `crates/fib` | The best routes in the Linux kernel, over netlink |
|
||||||
|
| `crates/server` | Sessions, the state machine, policy, configuration |
|
||||||
|
| `crates/web` | The status page, HTTP API and metrics |
|
||||||
|
| `crates/integration-tests` | A test server and test peers, and the tests that run the daemon end to end |
|
||||||
|
| `crates/bench` | Benchmarks at the scale of the Internet routing table |
|
||||||
|
| `bin/bgp` | The daemon |
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
CI runs these on every push, and fails on any warning:
|
CI runs these on every push, and fails on any warning:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
cargo fmt --all -- --check
|
cargo fmt --all -- --check
|
||||||
cargo clippy --workspace --all-targets -- -D warnings
|
cargo clippy --locked --workspace --all-targets -- -D warnings
|
||||||
cargo test --workspace
|
cargo test --locked --workspace
|
||||||
RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --document-private-items
|
RUSTDOCFLAGS="-D warnings" cargo doc --locked --workspace --no-deps --document-private-items
|
||||||
zola --root docs build
|
zola --root docs build
|
||||||
```
|
```
|
||||||
|
|
||||||
It also runs the tests that need a real Linux kernel
|
It also runs the tests that need a real Linux kernel
|
||||||
(`scripts/kernel-tests.sh`) and the lab with FRR, BIRD and Routinator
|
(`scripts/kernel-tests.sh`) and a lab that peers the daemon with FRR, BIRD
|
||||||
(`scripts/interop/lab.sh`); `scripts/linux-vm.sh` runs either from macOS.
|
and Routinator (`scripts/interop/lab.sh`); `scripts/linux-vm.sh` runs
|
||||||
|
either from macOS in a Lima VM.
|
||||||
Lints are configured once, under `[workspace.lints]` in the root `Cargo.toml`.
|
|
||||||
`unsafe` code is forbidden throughout.
|
|
||||||
|
|
||||||
`cargo test` includes property tests: generated messages must survive being
|
`cargo test` includes property tests: generated messages must survive being
|
||||||
written and read back, and no input, however damaged, may make a parser
|
written and read back, and no input, however damaged, may make a parser
|
||||||
panic. They take about a second; for a longer hunt:
|
panic. They take about a second; for a longer hunt:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
PROPTEST_CASES=1000000 cargo test --release -p bgp-packet --test properties
|
PROPTEST_CASES=1000000 cargo test --release -p bgp-packet --test properties
|
||||||
```
|
```
|
||||||
|
|
||||||
Coverage-guided fuzz targets for the same parsers are in `fuzz/`; see
|
Coverage-guided fuzz targets for the same parsers are in `fuzz/`; see
|
||||||
`fuzz/README.md`. CI runs each of them for a minute.
|
[`fuzz/README.md`](fuzz/README.md). CI runs each of them for a minute.
|
||||||
|
|
||||||
|
### Development with AI agents
|
||||||
|
|
||||||
|
Much of Ferrix is written with an AI coding agent (Claude Code) working
|
||||||
|
alongside the maintainer, who directs the work, reviews every change, and
|
||||||
|
runs the result on real routers. Nothing is merged on the agent's say-so:
|
||||||
|
every change passes the checks above, the kernel tests and the
|
||||||
|
interoperability lab, and the changes that matter are tried on the network
|
||||||
|
first. Commits made with an agent carry a `Co-Authored-By` trailer that
|
||||||
|
says so. If you contribute, you are welcome to work the same way, or not;
|
||||||
|
what is reviewed is the change, not how it was produced.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Apache License 2.0; see `LICENSE`.
|
Apache License 2.0; see [`LICENSE`](LICENSE).
|
||||||
Reference in new issue
Block a user