mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Restructures /docs/ by reader purpose (tutorials, how-to, reference, design), adds the new-user-progression and operator-recipe content the prior layout lacked, runs an accuracy pass against current source across the pre-existing design docs, and rewrites the gateway feature-set documentation end-to-end around its actual operational profile (a niche feature designed for systems already serving DHCP/DNS to a LAN, with two independent halves — outbound LAN→mesh, inbound mesh→LAN — sharing one nftables table, one binary, and one control socket). Top-level README and getting-started rewritten around two equally-weighted deployment modes (overlay on existing IP networks; ground-up over non-IP transports). ## Additions - 11 new tutorials in docs/tutorials/: an 8-step new-user progression from single-daemon test-mesh peering through to a ground-up two-device mesh, an IPv6-adapter side-trip walkthrough, an Advanced Tutorials index, and a hand-held OpenWrt walk-through for fips-gateway deployment that exercises both halves of the feature. - 12 new how-tos in docs/how-to/: firewall activation, Nostr discovery (resolve / advertise / open across five scenarios), Tor onion (directory + control_port modes), UDP buffer tuning, unprivileged-user setup, persistent identity, host aliases, Bluetooth LE peering, MTU diagnostics, manual Linux-host gateway deployment (covers both halves), gateway troubleshooting (organised by half), and a section index. - 9 new reference docs in docs/reference/: configuration, wire formats, control-socket protocol, four CLI references (fips, fipsctl, fipstop, fips-gateway), security posture matrix, and Nostr events catalog. Configuration and wire-formats are renamed-and-extended from prior design/ versions; the other seven are net-new. - 6 new design docs: fips-concepts, fips-architecture, and fips-prior-work split out of the deleted fips-intro.md; consolidated fips-mmp and fips-mtu aggregations; and a new generic port-advertisement-and-nat-traversal doc (Nostr-signaled port advertisement plus UDP NAT-traversal protocol, FIPS as an example implementation, suitable for eventual NIP submission). - Top-level docs/getting-started.md walking through the binary-installer-only Install story. - packaging/common/hosts pre-populated with the eight public test-mesh nodes so shortnames resolve out of the box on every fresh install. ## Changes - 23 wire-format diagrams relocated to reference/diagrams/ alongside the wire-formats move. - 4 design diagrams corrected against source code (fips-protocol-stack, fips-identity-derivation, fips-coordinate-discovery, fips-routing-decision). - 10 pre-existing design docs reconciled with current source. Numeric corrections: stale link-MMP report bounds (now [1s, 5s] with 200 ms cold-start floor); UDP default MTU (now 1280, IPv6 minimum); node_addr formula (SHA-256(pubkey)[..16]); Noise patterns (IK at link, XK at session); peer-ACL semantics (strict allowlist requires ALL in peers.deny); daemon DNS upstream ([::1]:5354); on-the-wire bloom-filter size (1,071 bytes); obsolete Cargo-feature references (PR #79 dropped them) removed. - Transport framing tightened across the docs: TCP is for UDP-filtered networks (not NAT traversal); Tor is a deployment mode (not failover); WebSocket dropped (not a shipped FIPS transport); WiFi promoted to Implemented via Ethernet in infrastructure mode; classic-Bluetooth row removed (BLE is the only Bluetooth-mode transport). - docs/design/fips-gateway.md rewritten end-to-end to lead with the niche-feature framing and the two-halves structure. Title moved from "FIPS Outbound LAN Gateway" to "FIPS Gateway"; architecture section describes the common machinery (the fips-gateway service, the nftables table, the control socket) before splitting into separate "Outbound Half" and "Inbound Half" sections of equal weight; security considerations split per-half; no Future Work section (speculative directions live in the project tracker, not in protocol design docs). Inbound port forwarding is a first-class half rather than a buried "Implemented Extensions" subsection. - Gateway terminology unified across all gateway docs as a separate Linux service running alongside the fips daemon (its own systemd unit / OpenWrt init script). Container- pattern terms (sidecar) are reserved for the Docker/Kubernetes sidecar deployment examples — the testing/sidecar/ tree, examples/k8s-sidecar/, examples/sidecar-nostr-relay/, examples/wireguard-sidecar-macos/, and the related CHANGELOG / top-level README entries — where the term carries its standard container meaning. - Net-new design body content: rekey section in fips-mesh-layer (Noise IK msg1/msg2 over the established link, K-bit cutover, drain window, smaller-NodeAddr-wins tie-breaker on dual-init); Mesh Size Estimation and Antipoison FPR Cap sections in fips-bloom-filters; Mesh-Interface Query Filter subsection in fips-ipv6-adapter; failure-suppression knobs and clock- skew tolerance in fips-nostr-discovery; loop-rejection and mid-chain ancestor swap added to spanning-tree propagation / stability rules; Priority Chain in fips-mesh-operation renumbered to match the routing-decision diagram. - Top-level README: dropped the stale nostr-discovery cargo-feature parenthetical. docs/README.md and the four section READMEs (tutorials, how-to, reference, design) refreshed for the new structure; index rows reflect both halves of the gateway feature and the new fips-gateway CLI reference. - Cargo.toml [package.metadata.deb] assets path updated for the fips-security.md move; .gitignore /reference/ rule anchored to repo root so docs/reference/ is trackable. - packaging/openwrt-ipk/files/etc/fips/fips.yaml configuration-doc URL updated to the new docs/reference/configuration.md location. ## Deletions - docs/design/fips-intro.md (split into the three new intro design docs). - docs/design/document-relationships.svg (orphan, no longer referenced). - docs/proposals/ tree removed; the only proposal it contained (the Nostr UDP hole-punch protocol) was rewritten as the new generic design/port-advertisement-and-nat-traversal.md.
300 lines
9.5 KiB
Markdown
300 lines
9.5 KiB
Markdown
# Set Up a Bluetooth (BLE) Peer Link
|
|
|
|
FIPS supports Bluetooth Low Energy as a transport for short-range
|
|
mesh extension — same room, same building, no IP infrastructure
|
|
between the two endpoints. The BLE transport runs as L2CAP
|
|
Connection-Oriented Channels on a configurable PSM and reports
|
|
per-link MTU back to the mesh layer for path-MTU computation.
|
|
|
|
For the design rationale and per-link MTU model, see
|
|
[../design/fips-transport-layer.md](../design/fips-transport-layer.md).
|
|
For all `transports.ble.*` configuration keys, see
|
|
[../reference/configuration.md](../reference/configuration.md).
|
|
|
|
> **Experimental.** The BLE transport works but is still maturing.
|
|
> Expect rougher edges than UDP or TCP — particularly around link
|
|
> stability under interference and MTU negotiation on older
|
|
> controllers. Treat it as you would any experimental transport in a
|
|
> production deployment.
|
|
|
|
## When to use
|
|
|
|
BLE is the right transport when:
|
|
|
|
- Two nodes are within roughly 10 metres line-of-sight (more with
|
|
external antennas, less through walls).
|
|
- You want a self-contained mesh segment with no shared WiFi or
|
|
Ethernet between the participants.
|
|
- You can work within practical L2CAP CoC throughput (1-2 Mbps in
|
|
good conditions, often substantially less under interference or
|
|
at range) and the higher latency variance compared to WiFi.
|
|
|
|
It is **not** the right transport for backbone links between rooms
|
|
where WiFi or Ethernet exists, for high-throughput data, or for any
|
|
deployment where range matters more than infrastructure-freedom.
|
|
|
|
## Platform support
|
|
|
|
The BLE transport is **Linux-only** in the current implementation.
|
|
The runtime depends on BlueZ via the `bluer` crate, which in turn
|
|
needs `glibc` (musl builds skip BLE; the build script gates the
|
|
crate accordingly).
|
|
|
|
| Platform | BLE transport |
|
|
| -------- | -------------- |
|
|
| Linux (glibc) | Supported. |
|
|
| Linux (musl, OpenWrt) | Disabled at build time. |
|
|
| macOS | Not supported. |
|
|
| Windows | Not supported. |
|
|
|
|
The Debian package `Recommends: bluez`; install it explicitly if you
|
|
opted out:
|
|
|
|
```sh
|
|
sudo apt install bluez
|
|
```
|
|
|
|
## Prerequisites
|
|
|
|
Both endpoints need:
|
|
|
|
1. A BLE-capable HCI adapter visible to BlueZ. Confirm with:
|
|
|
|
```sh
|
|
sudo bluetoothctl show
|
|
```
|
|
|
|
Note the controller name (typically `hci0`).
|
|
|
|
2. The `bluetoothd` service running and the adapter powered on:
|
|
|
|
```sh
|
|
sudo systemctl enable --now bluetooth
|
|
sudo bluetoothctl power on
|
|
```
|
|
|
|
3. Sufficient privileges for the FIPS daemon. There are two
|
|
independent privilege concerns; the BLE-only deployment case
|
|
(mesh router with `tun.enabled: false`) needs only the second.
|
|
|
|
- **TUN adapter (always required when `tun.enabled: true`).**
|
|
The daemon needs `CAP_NET_ADMIN` to create and configure the
|
|
TUN device. The shipped systemd unit handles this by running
|
|
as root; if you prefer to drop privileges, see
|
|
[run-as-unprivileged-user.md](run-as-unprivileged-user.md).
|
|
|
|
- **BLE access (required for this how-to).** BlueZ exposes
|
|
L2CAP and D-Bus paths under either group membership or
|
|
`CAP_NET_RAW`. Pick one:
|
|
|
|
- Run the daemon as root. The shipped systemd unit takes
|
|
this route.
|
|
- Run as an unprivileged user that is a member of the
|
|
`bluetooth` group. No additional capability is needed for
|
|
the BLE side.
|
|
- Run as an unprivileged user with no group membership, and
|
|
grant the binary `CAP_NET_RAW`:
|
|
|
|
```sh
|
|
sudo setcap cap_net_raw+ep $(which fips)
|
|
```
|
|
|
|
This bypasses BlueZ's polkit/group check by holding
|
|
`CAP_NET_RAW` directly. If you also need `CAP_NET_ADMIN`
|
|
for TUN, combine them:
|
|
|
|
```sh
|
|
sudo setcap cap_net_admin,cap_net_raw+ep $(which fips)
|
|
```
|
|
|
|
4. The same L2CAP PSM on both endpoints. The default is `0x0085`
|
|
(133); override only if you need to coexist with another L2CAP
|
|
service on that PSM.
|
|
|
|
## Configuration
|
|
|
|
Add a `ble` block under `transports` in `fips.yaml`. A minimum BLE-
|
|
active node looks like this:
|
|
|
|
```yaml
|
|
transports:
|
|
ble:
|
|
adapter: "hci0"
|
|
advertise: true
|
|
scan: true
|
|
auto_connect: true
|
|
accept_connections: true
|
|
```
|
|
|
|
Note: `auto_connect: true` is intentionally non-default (the default
|
|
is `false`). For a symmetric ground-up discovery flow where either
|
|
side may dial, both ends must opt in explicitly.
|
|
|
|
| Key | Purpose |
|
|
| --- | ------- |
|
|
| `adapter` | HCI controller name. Default: `hci0`. |
|
|
| `psm` | L2CAP PSM. Default: `0x0085` (must match on both ends). |
|
|
| `mtu` | Default L2CAP CoC MTU. Default: `2048`. The kernel may negotiate lower per link. |
|
|
| `max_connections` | Concurrent BLE connections. Default: `7` (Bluetooth controllers typically support up to ~7 simultaneous L2CAP CoCs). |
|
|
| `advertise` | Broadcast our BLE adverts so other FIPS nodes discover us. Default: `true`. |
|
|
| `scan` | Listen for other FIPS nodes' BLE adverts. Default: `true`. |
|
|
| `auto_connect` | Initiate a BLE connection to discovered FIPS adverts. Default: `false`. |
|
|
| `accept_connections` | Accept inbound L2CAP connections. Default: `true`. |
|
|
| `connect_timeout_ms` | Outbound L2CAP connect timeout. Default: `10000`. |
|
|
| `probe_cooldown_secs` | After probing a BD_ADDR (success or failure), wait this long before probing it again. Default: `30`. |
|
|
|
|
Two pairing patterns are common:
|
|
|
|
**Symmetric auto-discovery.** Both nodes advertise, scan, and
|
|
auto-connect. Whichever side completes the L2CAP connection first
|
|
wins; the other side aborts its in-flight attempt. This is the
|
|
"toss two devices in the same room" setup.
|
|
|
|
```yaml
|
|
# Both nodes
|
|
transports:
|
|
ble:
|
|
adapter: "hci0"
|
|
advertise: true
|
|
scan: true
|
|
auto_connect: true
|
|
accept_connections: true
|
|
```
|
|
|
|
**Asymmetric peripheral / central.** One node only listens
|
|
(peripheral), the other actively dials (central). Useful when one
|
|
endpoint is a dedicated bootstrap and the other is mobile.
|
|
|
|
```yaml
|
|
# Listener
|
|
transports:
|
|
ble:
|
|
adapter: "hci0"
|
|
advertise: true
|
|
scan: false
|
|
auto_connect: false
|
|
accept_connections: true
|
|
```
|
|
|
|
```yaml
|
|
# Dialer
|
|
transports:
|
|
ble:
|
|
adapter: "hci0"
|
|
advertise: false
|
|
scan: true
|
|
auto_connect: true
|
|
accept_connections: false
|
|
```
|
|
|
|
After editing, restart the daemon on each side:
|
|
|
|
```sh
|
|
sudo systemctl restart fips
|
|
```
|
|
|
|
## Verify
|
|
|
|
On each endpoint, confirm the transport came up:
|
|
|
|
```sh
|
|
fipsctl show transports
|
|
```
|
|
|
|
Look for an entry of type `ble` in the `state: Running` (or
|
|
equivalent) state. The `mtu` field reports the configured default;
|
|
per-link MTU is reported separately.
|
|
|
|
Confirm the link is established:
|
|
|
|
```sh
|
|
fipsctl show peers
|
|
```
|
|
|
|
The peer entry for the BLE-attached neighbour should report
|
|
`transport_type: "ble"` and a non-zero `last_seen_ms`.
|
|
|
|
BLE peering is auto-discovery only: there is no `fipsctl connect`
|
|
path for BLE (the command accepts `udp`, `tcp`, `tor`, and
|
|
`ethernet` only). Links come up via advert/scan; if you don't see
|
|
the peer here, the configuration above is the only knob.
|
|
|
|
To watch the link in real time, use `fipstop`'s **Peers** and
|
|
**Transports** tabs:
|
|
|
|
```sh
|
|
fipstop
|
|
```
|
|
|
|
The Performance tab reports the per-link MMP metrics — SRTT, loss
|
|
rate, ETX — which on BLE typically run an order of magnitude worse
|
|
than over UDP, with much higher jitter.
|
|
|
|
## Troubleshooting
|
|
|
|
### Transport never comes up
|
|
|
|
Check the BlueZ side first:
|
|
|
|
```sh
|
|
systemctl status bluetooth
|
|
sudo bluetoothctl show
|
|
```
|
|
|
|
If `bluetoothctl show` reports `Powered: no`, fix that before
|
|
debugging FIPS. The FIPS daemon will log a warning if it cannot
|
|
acquire the adapter.
|
|
|
|
If the FIPS log contains `bluer` D-Bus errors, the daemon usually
|
|
lacks permission. Run as root or grant `CAP_NET_ADMIN` and add the
|
|
fips user to the `bluetooth` group.
|
|
|
|
### Peers see each other but never connect
|
|
|
|
Verify `accept_connections` is true on at least one side and
|
|
`auto_connect` is true on at least one side. Two listen-only nodes
|
|
will discover each other but never establish an L2CAP connection.
|
|
|
|
Check `psm` matches on both ends. A mismatch presents as adverts
|
|
visible (in `fipstop` discovery counters) but every connect attempt
|
|
fails.
|
|
|
|
### Link comes up but throughput is poor
|
|
|
|
Practical L2CAP CoC throughput in good conditions reaches
|
|
1-2 Mbps, but interference, range, and controller capability all
|
|
push it lower. If throughput is well below that range, check the
|
|
negotiated ATT_MTU — a small ATT_MTU (default 23 bytes when
|
|
extended ATT MTU is not negotiated) caps per-PDU payload
|
|
regardless of radio conditions. The per-link MTU reported in
|
|
`fipsctl show transports` reveals what was negotiated.
|
|
|
|
If MTU is unexpectedly low, both endpoints must support and have
|
|
negotiated the BlueZ L2CAP `cocmode=2` extension. Older Bluetooth
|
|
controllers cap MTU regardless.
|
|
|
|
### Unstable links / repeated reconnects
|
|
|
|
Bluetooth in busy 2.4 GHz environments suffers from WiFi
|
|
interference. Switch the adapter to a less crowded channel (kernel
|
|
side, not configurable from FIPS) or add an external antenna. The
|
|
`probe_cooldown_secs` tunable backs off retry attempts; raise it if
|
|
the daemon log shows many short-lived probes.
|
|
|
|
### Permission errors on socket open
|
|
|
|
Most modern systemd installs do not allow non-root processes to
|
|
open raw L2CAP sockets without an explicit policy. Run the daemon
|
|
as root (the shipped systemd unit does this) or add a `polkit`
|
|
rule for the `bluetooth` group.
|
|
|
|
## See also
|
|
|
|
- [../design/fips-transport-layer.md](../design/fips-transport-layer.md)
|
|
— per-transport MTU reporting and the BLE row of the supported-
|
|
transports table.
|
|
- [../reference/configuration.md](../reference/configuration.md) —
|
|
full `transports.ble.*` reference.
|
|
- [run-as-unprivileged-user.md](run-as-unprivileged-user.md) —
|
|
adjacent privilege handling for the daemon process.
|