diff --git a/docs/design/README.md b/docs/design/README.md index 1903783..67127fe 100644 --- a/docs/design/README.md +++ b/docs/design/README.md @@ -17,3 +17,4 @@ Protocol design specifications and analysis for the Federated Interoperable Peer | ---------------------------------------------------------- | --------------------------------------------------------------------------------------- | | [fips-architecture.md](fips-architecture.md) | Software architecture: entities, state machines, transport abstractions, configuration | | [fips-architecture-review.md](fips-architecture-review.md) | Architecture review issues and resolution status | +| [fips-tun-driver.md](fips-tun-driver.md) | TUN interface driver: reader/writer threads, ICMPv6, packet flow | diff --git a/docs/design/fips-tun-driver.md b/docs/design/fips-tun-driver.md new file mode 100644 index 0000000..4646f27 --- /dev/null +++ b/docs/design/fips-tun-driver.md @@ -0,0 +1,236 @@ +# FIPS TUN Driver Design + +This document describes the design and implementation of the TUN interface +driver that connects FIPS to the local system's network stack. + +## Overview + +The TUN driver provides the interface between local applications and the FIPS +mesh network. It presents a virtual network interface (`fips0`) with the node's +FIPS address, allowing standard socket applications to communicate over the +mesh transparently. + +## Architecture + +```text +┌─────────────────────────────────────────────────────────────────┐ +│ Local System │ +│ ┌──────────────┐ │ +│ │ Applications │ (sockets using fd00::/8 addresses) │ +│ └──────┬───────┘ │ +│ │ │ +│ ┌──────▼───────┐ │ +│ │ Kernel │ routing: fd00::/8 → fips0 │ +│ │ IPv6 Stack │ local table intercepts traffic to self │ +│ └──────┬───────┘ │ +└─────────┼───────────────────────────────────────────────────────┘ + │ raw IPv6 packets +┌─────────▼───────────────────────────────────────────────────────┐ +│ TUN Device (fips0) │ +│ ┌─────────────────────────────────────────────────────────────┐│ +│ │ File Descriptor ││ +│ │ (duplicated for reader/writer) ││ +│ └──────────┬─────────────────────────────┬────────────────────┘│ +│ │ │ │ +│ ┌──────▼──────┐ ┌──────▼──────┐ │ +│ │ Reader │ │ Writer │ │ +│ │ Thread │ │ Thread │ │ +│ │ (blocking) │ │ (blocking) │ │ +│ └──────┬──────┘ └──────▲──────┘ │ +│ │ │ │ +└─────────────┼─────────────────────────────┼──────────────────────┘ + │ │ + ▼ │ + ┌─────────────┐ ┌───────┴───────┐ + │ Packet │ │ TX Queue │ + │ Processing │──────────────▶ (mpsc) │ + │ (routing) │ │ │ + └─────────────┘ └───────▲───────┘ + │ + (future: transports) +``` + +## Components + +### TunDevice (`src/tun.rs`) + +The main TUN device wrapper that handles creation, configuration, and lifecycle. + +**Responsibilities:** + +- Create TUN interface via `tun` crate +- Configure IPv6 address via netlink (`rtnetlink`) +- Set MTU and bring interface up +- Provide read access for incoming packets +- Create writer handle via fd duplication + +**Lifecycle:** + +1. **Startup**: Delete existing interface if present, create new +2. **Active**: Reader and writer threads operate independently +3. **Shutdown**: Delete interface via netlink, threads exit on I/O error + +### TunWriter (`src/tun.rs`) + +Services a queue of outbound packets and writes them to the TUN device. + +**Design rationale:** + +Multiple sources will need to write to TUN: + +- ICMPv6 error responses (from packet processing) +- Inbound mesh traffic from peers (future: transports) +- Locally-generated control traffic (future) + +A single writer thread with an mpsc queue provides: + +- No contention on TUN writes +- Clean separation of concerns +- Easy addition of new packet sources via `TunTx::clone()` + +### ICMPv6 Module (`src/icmp.rs`) + +Generates RFC 4443 compliant ICMPv6 error messages. + +**Currently implemented:** + +- Type 1 Code 0: Destination Unreachable - No route + +**Validation (when NOT to send errors):** + +- Original packet was an ICMPv6 error (types 0-127) +- Source address is multicast (0xff prefix) +- Source address is unspecified (::) + +**Response format:** + +- Total size ≤ 1280 bytes (IPv6 minimum MTU) +- Includes as much of original packet as fits +- Proper checksum with pseudo-header + +## Packet Flow + +### Outbound (local → mesh) + +1. Application sends to `fd00::/8` address +2. Kernel routes to `fips0` (requires manual route addition) +3. TUN reader receives raw IPv6 packet +4. Packet processing determines next hop +5. If routable: forward to transport (future) +6. If not routable: send ICMPv6 Destination Unreachable via TX queue + +### Inbound (mesh → local) + +1. Transport receives packet from peer (future) +2. Check destination address +3. If destination is self: write to TUN via TX queue +4. If destination is other: forward to next hop (transit) + +### Local Address Guarantee + +Packets arriving at the TUN reader are guaranteed NOT to be destined for +local addresses. The Linux kernel routing order ensures this: + +1. **Local routing table** - intercepts traffic to addresses on this machine +2. **Main routing table** - routes `fd00::/8` to fips0 + +This means every packet in the TUN reader requires a routing decision. +No "is this for me?" check needed on the read path. + +## Configuration + +From `fips.yaml`: + +```yaml +tun: + enabled: true + name: fips0 + mtu: 1400 +``` + +**Parameters:** + +| Field | Default | Description | +|-------|---------|-------------| +| `enabled` | `true` | Enable TUN interface | +| `name` | `fips0` | Interface name | +| `mtu` | `1400` | Maximum transmission unit | + +## Privileges + +TUN device creation requires `CAP_NET_ADMIN`. Options: + +1. **Run as root**: `sudo ./fips` +2. **Set capability**: `sudo setcap cap_net_admin+ep ./target/debug/fips` +3. **Pre-created device**: Admin creates persistent TUN, FIPS just opens it + +## Route Configuration + +The kernel route must be added manually (not done by FIPS): + +```bash +sudo ip -6 route add fd00::/8 dev fips0 +``` + +This routes all FIPS addresses through the TUN interface. + +## Implementation Status + +### Completed + +- [x] TUN device creation and configuration +- [x] IPv6 address assignment via netlink +- [x] Interface lifecycle (startup cleanup, graceful shutdown) +- [x] Reader thread with blocking I/O +- [x] Writer thread with mpsc queue +- [x] fd duplication for independent read/write +- [x] ICMPv6 Destination Unreachable (Type 1 Code 0) +- [x] Packet validation for ICMPv6 error generation + +### Planned + +- [ ] ICMPv6 Echo Reply (respond to ping) +- [ ] ICMPv6 Packet Too Big (PMTUD support) +- [ ] ICMPv6 Time Exceeded (hop limit) +- [ ] Rate limiting for ICMPv6 errors +- [ ] Integration with routing/forwarding logic +- [ ] Transit packet handling (decrement hop limit, forward) +- [ ] Automatic route management (add/remove fd00::/8 route) + +## Testing + +### Manual Testing + +```bash +# Terminal 1: Run FIPS with debug logging +sudo RUST_LOG=debug ./target/debug/fips + +# Terminal 2: Add route and test +sudo ip -6 route add fd00::/8 dev fips0 +ping6 -c 1 fd00::1 + +# Expected: "Destination unreachable: No route" (not timeout) +``` + +### Verifying Local Routing + +```bash +# Check that local address goes via loopback, not TUN +ip -6 route get +# Should show: local ... dev lo +``` + +## Dependencies + +| Crate | Purpose | +|-------|---------| +| `tun` | TUN device creation | +| `rtnetlink` | Netlink interface configuration | +| `libc` | fd duplication (`dup`) | +| `futures` | Async netlink operations | + +## References + +- RFC 4443: ICMPv6 for IPv6 +- RFC 4291: IPv6 Addressing Architecture +- Linux TUN/TAP documentation