Files
fips/packaging/openwrt-ipk/README.md
T
Johnathan Corgan d1b8a725ac Build working OpenWrt packages from the SDK feed Makefile
OpenWrt scans every package Makefile with DUMP=1 before it builds
anything, and that scan does not read the target config, so ARCH is
empty there. The unsupported-architecture error therefore fired on every
scan, the package's metadata came out empty, and make package/fips/compile
in the SDK built nothing at all. The error now applies only outside the
scan.

The SDK feed Makefile also declared no postinst, prerm or conffiles, so a
package built from it ran only OpenWrt's generated scripts. Their
default_postinst enables every init script a package ships on a fresh
install and starts every one on each install and upgrade, so such a
package enabled and started fips-gateway on a fresh install, started a
gateway the operator had disabled on every upgrade, and under opkg
replaced an edited fips.yaml. The Makefile now reads its postinst and
prerm bodies from scripts/, the same files build-ipk.sh and build-apk.sh
install, and lists fips.yaml as a conffile. Because the generated postinst
runs the package's body before the enable-and-start loop under opkg and
after it under apk, a new preinst, used only by the Makefile, leaves a
one-time hold in /var/run unless the gateway is enabled, and the gateway's
start_service, finding the hold, removes it, disables the service and
starts nothing. Under apk, where an upgrade runs no script of the old
package, the preinst also stops the services and leaves the upgrade
marker, as the old prerm does under opkg. The marker stays in /tmp,
because the prerm of an installed 0.5.2 package writes it there. The
prerm recognises an upgrade from PKG_UPGRADE as well as from its first
argument, since OpenWrt's default_prerm passes the script path first, and
the postinst clears the hold before re-enabling the gateway after an
upgrade from a package whose prerm disabled it.

An image build runs package scripts on the build host with IPKG_INSTROOT
naming the image root, so the preinst, postinst and prerm now do nothing
when it is set, rather than enabling and starting services on the host
and writing into its /tmp. The README tells image builders to pass
DISABLED_SERVICES=fips-gateway to keep the gateway off, and drops the
caveat that SDK builds lack the scripts.

Built in the openwrt/sdk 24.10.8 (ipk) and 25.12.5 (apk) images and
installed, upgraded and removed with the real opkg and apk in the
matching rootfs images: a fresh install leaves the gateway disabled and
stopped, an upgrade keeps it disabled or enabled as it was, and an
edited fips.yaml survives. A new scenario runs the same flows under ash
in local and GitHub CI and checks the scripts touch nothing on a build
host, and package-test.sh checks the Makefile names the scripts and the
conffile.
2026-10-01 14:21:40 +00:00

250 lines
7.8 KiB
Markdown

# FIPS OpenWrt Package
This directory is an OpenWrt feed package that builds and installs FIPS on any
OpenWrt 22.03+ router via the standard `opkg` package system.
## Package contents
| Installed path | Purpose |
|---|---|
| `/usr/bin/fips` | Mesh daemon |
| `/usr/bin/fipsctl` | CLI control tool (`fipsctl show peers`, `fipsctl show links`, …) |
| `/usr/bin/fipstop` | Live TUI dashboard |
| `/usr/bin/fips-gateway` | Outbound LAN gateway service (not started by default) |
| `/usr/bin/fips-mesh-setup` | Opt-in helper — creates an open 802.11s mesh interface for router↔router backhaul |
| `/usr/bin/fips-ap-setup` | Opt-in helper — creates the open `!FIPS` access SSID for client devices |
| `/etc/init.d/fips` | procd service for the daemon (auto-start, crash respawn) |
| `/etc/init.d/fips-gateway` | procd service for the gateway (disabled by default) |
| `/etc/fips/fips.yaml` | Node configuration (edit before first start) |
| `/etc/fips/firewall.sh` | Firewall helper — accepts traffic on `fips0` |
| `/etc/sysctl.d/fips-bridge.conf` | `br_netfilter` settings for Ethernet transport |
| `/etc/sysctl.d/fips-gateway.conf` | `proxy_ndp` and IPv6 forwarding for the gateway |
| `/etc/hotplug.d/net/99-fips` | Applies firewall rules when `fips0` comes up |
| `/etc/uci-defaults/90-fips-setup` | First-boot kernel module, firewall and dnsmasq `.fips` forwarding setup |
| `/lib/upgrade/keep.d/fips` | Preserves `/etc/fips/` across `sysupgrade` |
## Requirements
### Build host
| Requirement | Notes |
|---|---|
| OpenWrt SDK 22.03+ | Older versions lack fw4 / nftables support |
| Rust host toolchain | Enable in `make menuconfig` → Advanced → Rust, or install rustup |
| Rust target for your router | Added automatically by the Makefile via `rustup target add` |
### Router
| Requirement | Notes |
|---|---|
| `kmod-tun` | Required for `fips0` TUN interface |
| `kmod-br-netfilter` | Required for Ethernet transport on bridge member ports |
Both kernel modules are listed as package dependencies (`DEPENDS`) and will be
installed automatically by `opkg`.
## Target architectures
The Makefile maps the OpenWrt `ARCH` variable to the correct Rust musl target:
| OpenWrt `ARCH` | Rust target |
|---|---|
| `aarch64` | `aarch64-unknown-linux-musl` |
| `x86_64` | `x86_64-unknown-linux-musl` |
| `mipsel` | `mipsel-unknown-linux-musl` |
| `mips` | `mips-unknown-linux-musl` |
| `arm` | `arm-unknown-linux-musleabihf` |
To add a missing architecture, add an `ifeq` block in `Makefile` mapping the
OpenWrt `ARCH` value to the Rust target triple.
## Building with the OpenWrt SDK
### 1. Obtain the SDK
Download the SDK for your router's target from
[downloads.openwrt.org](https://downloads.openwrt.org) and extract it.
### 2. Add this package
Copy or symlink this directory into the SDK's `package/` tree:
```bash
# From inside the SDK root:
ln -s /path/to/fips/packaging/openwrt-ipk package/fips
```
Or add the FIPS repository as a feed in `feeds.conf`:
```
src-git-full fips https://github.com/jmcorgan/fips.git
```
Then update and install feeds:
```bash
./scripts/feeds update fips
./scripts/feeds install -a -p fips
```
### 3. Build
```bash
make package/fips/compile V=s
```
The resulting `.ipk` is placed in `bin/packages/<arch>/`.
Installed on a router, the package enables and starts `fips` and leaves
`fips-gateway` disabled. Built into a firmware image, it is different: the
maintainer scripts do nothing at image build time, and the image build enables
every init script a package ships, `fips-gateway` included. To build an image
with the gateway off, pass `DISABLED_SERVICES="fips-gateway"` to the image
builder's `make image`.
### 4. Pin the source version
For reproducible production builds, replace `PKG_SOURCE_VERSION:=master` in
`Makefile` with a specific commit SHA and set `PKG_MIRROR_HASH` to the correct
hash (or keep `skip` for development):
```makefile
PKG_SOURCE_VERSION:=bf117dfabc123... # full 40-char SHA
PKG_MIRROR_HASH:=skip
```
## Installing on the router
```bash
scp bin/packages/<arch>/fips_0.1.0-1_<arch>.ipk root@192.168.1.1:/tmp/
ssh root@192.168.1.1 opkg install /tmp/fips_0.1.0-1_<arch>.ipk
```
## First-time configuration
Edit `/etc/fips/fips.yaml` on the router before starting the daemon:
```bash
ssh root@192.168.1.1
vi /etc/fips/fips.yaml
```
The default config enables:
- An ephemeral identity, generated on each start. Uncomment
`node.identity.persistent: true` to keep one; the key is then saved next to
the config, as `/etc/fips/fips.key`.
- TUN interface `fips0`
- DNS responder on `[::1]:5354`
- UDP transport on `[::]:2121`
- TCP transport on `0.0.0.0:8443`
- Ethernet transport, including the `wan`, `wwan` and `lan` entries
For Ethernet transport, edit the interface names in the `ethernet:` section to
match your router. **Always use physical port names
(`eth0`, `eth1`, or DSA port names like `wan`/`lan1`), never bridge names
(`br-lan`).** The shipped default WAN port is `eth0` (OpenWrt 24); on OpenWrt
25 (DSA) boards the WAN port is named `wan` — the `.apk` package ships that
default. Run `ip link show` to confirm the names on your board.
## Service management
```bash
/etc/init.d/fips start
/etc/init.d/fips stop
/etc/init.d/fips restart
/etc/init.d/fips enable # start at boot (already enabled by opkg postinstall)
/etc/init.d/fips disable
```
### Outbound LAN gateway (optional)
The `fips-gateway` service is installed but disabled by default. It
turns the router into an outbound gateway that bridges LAN clients
onto the FIPS mesh. Enable only after configuring a `gateway:`
section in `/etc/fips/fips.yaml`:
```bash
/etc/init.d/fips-gateway enable
/etc/init.d/fips-gateway start
```
See `docs/tutorials/deploy-fips-gateway.md` in the source tree for
the full walkthrough.
## Inspection and logs
```bash
# Node-level status overview
fipsctl show status
# Peer table
fipsctl show peers
# Transport links
fipsctl show links
# Active end-to-end sessions
fipsctl show sessions
# Live TUI dashboard
fipstop
# Daemon logs (OpenWrt syslog)
logread | grep fips
```
See [`docs/reference/cli-fipsctl.md`](../../docs/reference/cli-fipsctl.md)
for the full subcommand list.
## Upgrading
OpenWrt 25 and later have no opkg. Upgrade there with the `.apk` package,
using the same command that installs it:
```bash
apk add --allow-untrusted /tmp/fips_<new-version>_<arch>.apk
```
The `.apk` package's upgrade scripts stop `fips` and `fips-gateway`, start
`fips` again, and start `fips-gateway` only if it was enabled; see
[`../openwrt-apk/README.md`](../openwrt-apk/README.md).
On OpenWrt 24.10 and earlier, install the new `.ipk` with a plain
`opkg install`:
```bash
opkg install /tmp/fips_<new-version>_<arch>.ipk
```
opkg runs this as an upgrade. The installed package's `prerm` stops `fips` and
`fips-gateway` without disabling them, and the new package's `postinst` starts
`fips` and starts `fips-gateway` again if it was enabled.
An upgrade from 0.5.1 or earlier is the exception. The `prerm` in those
packages disables `fips-gateway` and records nothing about whether it was
enabled, so the new `postinst` enables it again. If you had the gateway
disabled, disable it again after that first upgrade:
```bash
/etc/init.d/fips-gateway stop
/etc/init.d/fips-gateway disable
```
If opkg refuses because the new file's version sorts lower than the installed
one, as it can between development builds, add `--force-downgrade`. opkg then
takes the same upgrade path.
Do not use `--force-reinstall`. opkg runs it as a removal followed by a fresh
install, so `fips-gateway` ends up disabled. To turn it back on:
```bash
/etc/init.d/fips-gateway enable
/etc/init.d/fips-gateway start
```
The config in `/etc/fips/fips.yaml` and the identity key `/etc/fips/fips.key`
(when persistent identity is on) are preserved by `opkg` (the yaml is installed
as a conffile; the key is not a package file). Both survive `sysupgrade` via
`/lib/upgrade/keep.d/fips`.