mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-09 16:24:45 +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.
469 lines
19 KiB
Markdown
469 lines
19 KiB
Markdown
# Deploy a `fips-gateway` on an OpenWrt AP
|
|
|
|
In every other tutorial in this set you put FIPS *on* the host that
|
|
needs to talk to the mesh. This one is the exception. Here you stand
|
|
up a `fips-gateway` on an OpenWrt access point so the unmodified LAN
|
|
behind it — phones, laptops, smart-home gear — can reach mesh
|
|
destinations by `<npub>.fips` without any FIPS software of their own,
|
|
and so a service running on a LAN box can be exposed to mesh peers
|
|
through a port forward. Two halves, one binary, one config.
|
|
|
|
This is **advanced** material. It assumes you have already worked
|
|
through [join-the-test-mesh](join-the-test-mesh.md) on some other
|
|
machine, you understand what `<npub>.fips` means, and now you want to
|
|
fold an existing LAN into the mesh from the edge router rather than
|
|
installing FIPS on every device. The whole exercise should take about
|
|
forty-five minutes.
|
|
|
|
## What you'll build
|
|
|
|
```text
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
│ OpenWrt access point │
|
|
│ │
|
|
│ br-lan ┌──────────────┐ fips0 ┌──────────────┐ │
|
|
│ (LAN side) ◀──│ fips-gateway │──────────▶│ fips daemon │ │
|
|
│ │ (service) │ │ │──┼─▶ mesh
|
|
│ │ │ fd97:.. │ fd97:.. │ │
|
|
│ │ fd01::/112 │ │ │ │
|
|
│ │ pool │ │ │ │
|
|
│ └──────┬───────┘ └──────────────┘ │
|
|
│ │ │
|
|
│ ▼ │
|
|
│ nftables NAT │
|
|
│ (inet fips_gateway) │
|
|
└─────────────────┬────────────────────────────────────────────┘
|
|
│ br-lan
|
|
▼
|
|
┌──────────────────────────────────────────────┐
|
|
│ LAN clients (phones, laptops, smart-home) │
|
|
│ │
|
|
│ no FIPS install — just IPv6 + DNS │
|
|
│ ▲ │
|
|
│ │ curl http://test-us01.fips/ │
|
|
│ └────── DNS to dnsmasq ──▶ gateway DNS │
|
|
│ │
|
|
└──────────────────────────────────────────────┘
|
|
```
|
|
|
|
By the end you will have:
|
|
|
|
- An OpenWrt AP whose LAN clients can fetch `http://test-us01.fips/`
|
|
with no FIPS software installed on them.
|
|
- An inbound port forward exposing one LAN service to the mesh as
|
|
`<your-gateway-npub>.fips:<port>`.
|
|
- An understanding of which LAN-side glue OpenWrt automates for you
|
|
(DNS forwarding, RA route, IPv6 prefix) and which the operator owns
|
|
(port forwards, mesh firewall).
|
|
|
|
## Why an OpenWrt AP
|
|
|
|
The gateway has very specific dependencies on the box it runs on. It
|
|
needs to own DNS for the LAN, it needs to advertise an IPv6 route to
|
|
the LAN, it needs a stable LAN-side interface, and it needs to be the
|
|
default IPv6 router for the segment. An OpenWrt-based access point
|
|
already does all of those things — it runs `dnsmasq`, it runs
|
|
`odhcpd` for IPv6 RA, it owns `br-lan`, and clients are already using
|
|
it as their gateway. The OpenWrt ipk leans into that: the `gateway:`
|
|
block in `/etc/fips/fips.yaml` is pre-populated, and the
|
|
`/etc/init.d/fips-gateway` init script wires up the LAN-side glue
|
|
automatically when you start the service.
|
|
|
|
On a non-OpenWrt host the same integration is manual; that path is
|
|
covered by [../how-to/deploy-gateway.md](../how-to/deploy-gateway.md).
|
|
|
|
## Prerequisites
|
|
|
|
- An OpenWrt 22.03+ AP serving DHCP and DNS to a wired or wireless
|
|
LAN segment.
|
|
- The FIPS ipk installed and a working FIPS daemon on the AP. If you
|
|
haven't done that yet, follow
|
|
[../../packaging/openwrt-ipk/README.md](../../packaging/openwrt-ipk/README.md)
|
|
for the install, then come back here.
|
|
- The AP joined to the mesh — at least one healthy peer link. If it
|
|
isn't, work through [join-the-test-mesh](join-the-test-mesh.md) on
|
|
the AP first.
|
|
- Root SSH to the AP. Every command in this tutorial runs on the AP.
|
|
- A LAN client (phone, laptop) to test the outbound half from.
|
|
|
|
## Step 1: Verify the FIPS daemon is up
|
|
|
|
Confirm the daemon is running, the TUN is up, and at least one mesh
|
|
peer is reachable:
|
|
|
|
```sh
|
|
service fips status
|
|
ip -6 addr show fips0
|
|
fipsctl show peers
|
|
```
|
|
|
|
You should see:
|
|
|
|
- `service fips status` reports `running`.
|
|
- `fips0` exists and has one `inet6 fd97:...` address. That is the
|
|
AP's mesh-side identity.
|
|
- `fipsctl show peers` lists at least one peer with active
|
|
connectivity (not `idle` / not zero bytes).
|
|
|
|
Confirm the AP can resolve a known mesh node by name:
|
|
|
|
```sh
|
|
ping6 -c 2 test-us01.fips
|
|
```
|
|
|
|
If any of these fail, fix the daemon side first — the gateway is a
|
|
separate service that runs alongside a working daemon, not a
|
|
substitute for one.
|
|
|
|
## Step 2: Inspect the pre-populated gateway config
|
|
|
|
The OpenWrt ipk ships `/etc/fips/fips.yaml` with the `gateway:` block
|
|
already filled in. View the relevant section:
|
|
|
|
```sh
|
|
sed -n '/^gateway:/,$p' /etc/fips/fips.yaml
|
|
```
|
|
|
|
You will see roughly:
|
|
|
|
```yaml
|
|
gateway:
|
|
enabled: true
|
|
pool: "fd01::/112" # virtual IP range (up to 65535 addresses)
|
|
lan_interface: "br-lan" # LAN-facing interface for proxy NDP
|
|
dns:
|
|
listen: "[::1]:5353" # gateway DNS listener (dnsmasq forwards here)
|
|
upstream: "[::1]:5354" # FIPS daemon DNS resolver (matches daemon default)
|
|
ttl: 60 # DNS TTL and mapping lifetime (seconds)
|
|
pool_grace_period: 60 # seconds after last session before reclaiming
|
|
```
|
|
|
|
Three things to notice:
|
|
|
|
- `pool: "fd01::/112"` — the virtual-IP CIDR the gateway hands out
|
|
to LAN clients. 65 536 addresses, the gateway's hard cap. Pick a
|
|
different `fdXX::/N` prefix if `fd01::/112` collides with anything
|
|
on your network.
|
|
- `lan_interface: "br-lan"` — the OpenWrt LAN bridge. The gateway
|
|
installs proxy-NDP entries on this interface so LAN clients can
|
|
ARP-equivalent for pool addresses.
|
|
- `dns.listen: "[::1]:5353"` — the gateway's DNS listener is bound
|
|
to IPv6 loopback only. dnsmasq, which owns LAN port 53, forwards
|
|
`.fips` queries to it. The init script wires up that forwarding;
|
|
you don't bind to a LAN address yourself.
|
|
|
|
For the full reference, see
|
|
[../reference/configuration.md § Gateway](../reference/configuration.md#gateway-gateway).
|
|
|
|
## Step 3: Enable and start fips-gateway
|
|
|
|
The service is shipped disabled — enable it once and start it:
|
|
|
|
```sh
|
|
service fips-gateway enable
|
|
service fips-gateway start
|
|
```
|
|
|
|
Behind that single command, the init script
|
|
(`/etc/init.d/fips-gateway`) does five things:
|
|
|
|
1. **Loads gateway sysctls.** `net.ipv6.conf.all.proxy_ndp=1` and
|
|
`net.ipv6.conf.all.forwarding=1` from
|
|
`/etc/sysctl.d/fips-gateway.conf`.
|
|
2. **Reconfigures dnsmasq via UCI** so `.fips` queries arriving at
|
|
the LAN's port 53 are forwarded to the gateway's loopback
|
|
listener on port 5353 instead of going straight to the daemon's
|
|
resolver on port 5354. (Dnsmasq still owns 53; the gateway sits
|
|
in front of the daemon for `.fips` only.)
|
|
3. **Adds a global-scope IPv6 prefix** to `br-lan`. Without a
|
|
non-ULA address on the local interface, Android and Chrome
|
|
suppress AAAA queries entirely — they assume the LAN has no
|
|
real IPv6 and don't bother. The init script adds a small
|
|
benchmarking-range prefix to convince them otherwise.
|
|
4. **Adds an RA route for the virtual pool.** A UCI `route6` entry
|
|
under `dhcp` tells `odhcpd` to advertise the pool CIDR via Router
|
|
Advertisement (RFC 4191), so LAN clients learn how to reach pool
|
|
addresses automatically. No per-client static routes needed.
|
|
5. **Spawns `fips-gateway` under procd** with `--config
|
|
/etc/fips/fips.yaml`, with crash-respawn.
|
|
|
|
Verify it is running:
|
|
|
|
```sh
|
|
service fips-gateway status
|
|
logread | grep fips-gateway | tail
|
|
```
|
|
|
|
Expect a `running` status and a startup log line of the form
|
|
`fips-gateway 0.x.y starting`, followed by entries for DNS bind, NAT
|
|
table install, and pool initialisation.
|
|
|
|
> **What just changed on the LAN.** The AP is now offering two
|
|
> things it wasn't offering a moment ago: AAAA records under `.fips`
|
|
> that resolve to virtual IPs in `fd01::/112`, and a route to that
|
|
> CIDR in its Router Advertisements. Existing LAN clients pick both
|
|
> up the next time they re-resolve a name and the next time `odhcpd`
|
|
> sends an RA, respectively. No reboot required on the client side.
|
|
|
|
## Step 4: Test the outbound half from a LAN client
|
|
|
|
From a phone or laptop on the AP's LAN — anything that does IPv6 and
|
|
DNS, with no FIPS software installed — try one of the public test
|
|
mesh nodes:
|
|
|
|
```sh
|
|
dig test-us01.fips AAAA
|
|
ping6 -c 4 test-us01.fips
|
|
curl -6 http://test-us01.fips/
|
|
```
|
|
|
|
Expectations:
|
|
|
|
- `dig` returns an AAAA in `fd01::...`, **not** `fd97:...`. The
|
|
`fd01:` address is the gateway's virtual-IP allocation; the LAN
|
|
client never sees the raw mesh address.
|
|
- `ping6` succeeds. ICMPv6 echo travels through the NAT pipeline and
|
|
back.
|
|
- `curl` fetches the page (whatever the test mesh is currently
|
|
serving on `test-us01`).
|
|
|
|
> **What just happened end to end.** Your client asked dnsmasq for
|
|
> `test-us01.fips`. Dnsmasq forwarded the query to the gateway's
|
|
> loopback listener on port 5353. The gateway forwarded the query on
|
|
> to the daemon's resolver on port 5354. The daemon answered with
|
|
> `test-us01`'s mesh address (`fd97:...`). The gateway allocated a
|
|
> virtual IP from `fd01::/112`, installed nftables DNAT/SNAT/
|
|
> masquerade rules pinning that virtual IP to the mesh address,
|
|
> installed a proxy-NDP entry on `br-lan` so the client could resolve
|
|
> the virtual IP at the link layer, and returned the virtual IP in
|
|
> the AAAA reply. Your client then routed traffic to the virtual IP
|
|
> via the RA-advertised pool route, the AP's kernel rewrote the
|
|
> destination to the mesh address, and the daemon's adapter carried
|
|
> the packets across the mesh. Return traffic followed conntrack
|
|
> back. The client never knew the mesh existed.
|
|
|
|
## Step 5 (optional): Inspect the gateway state
|
|
|
|
The gateway exposes its own control socket separate from the daemon's.
|
|
Two useful queries:
|
|
|
|
```sh
|
|
echo '{"command":"show_gateway"}' | nc -U /run/fips/gateway.sock
|
|
echo '{"command":"show_mappings"}' | nc -U /run/fips/gateway.sock
|
|
```
|
|
|
|
`show_gateway` reports pool utilisation, the DNS listen address,
|
|
uptime, and the conntrack/NAT counters. `show_mappings` lists each
|
|
allocated virtual IP, the mesh address it points at, the DNS name
|
|
that triggered the allocation, and the mapping's lifecycle state
|
|
(`Allocated`, `Active`, `Draining`).
|
|
|
|
For the full command catalog and JSON shapes, see
|
|
[../reference/control-socket.md § Gateway Command Catalog](../reference/control-socket.md#gateway-command-catalog).
|
|
The same data is rendered visually in the **Gateway** tab of
|
|
[`fipstop`](../reference/cli-fipstop.md).
|
|
|
|
If you want to see the kernel rules the gateway installed:
|
|
|
|
```sh
|
|
nft list table inet fips_gateway
|
|
```
|
|
|
|
You will see DNAT, SNAT, and masquerade chains populated with one
|
|
rule per active mapping.
|
|
|
|
## Step 6: Add an inbound port-forward for a LAN service
|
|
|
|
The outbound half is the steady-state use of a gateway. The inbound
|
|
half — exposing a LAN service to mesh peers — is a separate decision,
|
|
configured per service under `gateway.port_forwards[]`.
|
|
|
|
For the worked example, run a one-page static web server on the AP
|
|
itself, bound to its `br-lan` address, and expose it to the mesh
|
|
through a port-forward. Anything would do — the point of the exercise
|
|
is the port-forward, not the service. We use what is already on the
|
|
AP: `busybox httpd`. In a real deployment the LAN-side target would
|
|
typically be a separate host (a NAS, a home server, a dev box on the
|
|
LAN); the rule shape is identical.
|
|
|
|
Find the AP's `br-lan` IPv6 address and save it for the rest of the
|
|
step:
|
|
|
|
```sh
|
|
BR_LAN_ADDR=$(ip -6 addr show br-lan \
|
|
| awk '/inet6 fd|inet6 2/ && !/scope link/ {print $2}' \
|
|
| head -1 | cut -d/ -f1)
|
|
echo "$BR_LAN_ADDR"
|
|
```
|
|
|
|
Pick from the global-scope benchmarking prefix the init script added
|
|
in Step 3, or your own ULA if `br-lan` has one — anything except a
|
|
link-local `fe80::/10` address.
|
|
|
|
Set up a one-file docroot and start a foreground `busybox httpd`
|
|
bound to that LAN address on port 8000:
|
|
|
|
```sh
|
|
mkdir -p /tmp/mesh-demo
|
|
echo '<h1>Hello from the mesh-gateway demo</h1>' > /tmp/mesh-demo/index.html
|
|
busybox httpd -f -p "[${BR_LAN_ADDR}]:8000" -h /tmp/mesh-demo
|
|
```
|
|
|
|
Leave it running in this shell. Open a second SSH session on the AP
|
|
to add the port-forward.
|
|
|
|
Edit `/etc/fips/fips.yaml`. Inside the existing `gateway:` block,
|
|
add a `port_forwards:` list:
|
|
|
|
```yaml
|
|
gateway:
|
|
enabled: true
|
|
pool: "fd01::/112"
|
|
lan_interface: "br-lan"
|
|
dns:
|
|
listen: "[::1]:5353"
|
|
upstream: "[::1]:5354"
|
|
ttl: 60
|
|
pool_grace_period: 60
|
|
port_forwards:
|
|
- listen_port: 8080
|
|
proto: tcp
|
|
target: "[<BR_LAN_ADDR>]:8000"
|
|
```
|
|
|
|
Substitute the real address for `<BR_LAN_ADDR>`. The IPv6 form
|
|
(`[addr]:port`) is required — IPv4 targets are rejected at config
|
|
load.
|
|
|
|
Restart the gateway so it re-reads the config:
|
|
|
|
```sh
|
|
service fips-gateway restart
|
|
```
|
|
|
|
From any *other* mesh node, fetch the demo page through the gateway
|
|
using the AP's npub:
|
|
|
|
```sh
|
|
# on the AP, get the npub:
|
|
NPUB=$(cat /etc/fips/fips.pub)
|
|
echo "$NPUB"
|
|
```
|
|
|
|
Then on the remote mesh node:
|
|
|
|
```sh
|
|
curl -6 "http://${NPUB}.fips:8080/"
|
|
```
|
|
|
|
Expect:
|
|
|
|
```text
|
|
<h1>Hello from the mesh-gateway demo</h1>
|
|
```
|
|
|
|
The connection landed on the gateway's `fips0` ingress on TCP/8080,
|
|
nftables DNAT rewrote the destination to `[BR_LAN_ADDR]:8000`,
|
|
LAN-side masquerade rewrote the source so `busybox httpd` saw a
|
|
LAN-routable address, and the response retraced via conntrack.
|
|
|
|
> **What you exposed.** With the port-forward active, every mesh
|
|
> peer that can route to your AP can hit `${NPUB}.fips:8080/` and
|
|
> reach this service. That is exactly what the inbound half is
|
|
> for — but if you want to scope visibility to a specific subset
|
|
> of peers, the FIPS mesh firewall is the layer that does it; see
|
|
> [../how-to/enable-mesh-firewall.md](../how-to/enable-mesh-firewall.md).
|
|
> The port-forward rule and the firewall rule are independent: the
|
|
> port-forward installs the rewrite; the firewall decides who is
|
|
> allowed to reach the listen port.
|
|
|
|
## Step 7: Tidy up
|
|
|
|
In the first shell, stop `busybox httpd` with `Ctrl-C`. The demo
|
|
docroot at `/tmp/mesh-demo` can stay — it is wiped on reboot — or
|
|
remove it now (`rm -rf /tmp/mesh-demo`).
|
|
|
|
If you want to keep the outbound half but withdraw the inbound
|
|
forward, remove the `port_forwards:` entry from `/etc/fips/fips.yaml`
|
|
and `service fips-gateway restart`. The mesh-side listener disappears
|
|
and so does the corresponding nftables rule.
|
|
|
|
To turn the gateway off entirely:
|
|
|
|
```sh
|
|
service fips-gateway stop
|
|
service fips-gateway disable
|
|
```
|
|
|
|
The init script's `stop_service` handler reverses the LAN-side
|
|
integration on the way out: dnsmasq's `.fips` forwarder is pointed
|
|
back at the daemon's port 5354, the RA route for the pool is
|
|
withdrawn from `odhcpd`, and the global-scope IPv6 prefix on
|
|
`br-lan` is removed. The LAN reverts to the state it was in before
|
|
you ran `service fips-gateway start` in Step 3.
|
|
|
|
The daemon and the rest of `/etc/fips/` are untouched. Existing mesh
|
|
peering on the AP itself continues to work.
|
|
|
|
## What you've learned
|
|
|
|
- **The gateway is a niche feature for a niche box.** Most FIPS
|
|
hosts run the daemon and reach the mesh directly. The gateway
|
|
exists so an AP can fold an entire unmodified LAN behind it into
|
|
the mesh in one place.
|
|
- **Two halves of the same binary.** Outbound mode hands LAN clients
|
|
virtual IPs and NATs them onto the mesh; inbound mode listens on
|
|
`fips0` and forwards to LAN targets. They share one nftables
|
|
table, one control socket, and one config block, but each half
|
|
has its own use case.
|
|
- **OpenWrt does the LAN-side glue for you.** The init script
|
|
reconfigures dnsmasq, installs the RA route, adds the global IPv6
|
|
prefix, and loads sysctls. On a non-OpenWrt host that integration
|
|
is manual — see [../how-to/deploy-gateway.md](../how-to/deploy-gateway.md).
|
|
- **Inbound forwards stay manual on every distro.** The
|
|
`port_forwards[]` block is uniform across hosts, and on every
|
|
distro you still own the decision of which LAN target to expose
|
|
and on which mesh-side port.
|
|
- **The mesh firewall is a separate decision.** Opening a port
|
|
forward on the gateway side does not open it on the firewall
|
|
side; if `fips-firewall.service` is enabled, you still need a
|
|
drop-in that admits the listen port.
|
|
|
|
## Troubleshooting
|
|
|
|
If something doesn't work as described above, the operator-recipe
|
|
guide [../how-to/troubleshoot-gateway.md](../how-to/troubleshoot-gateway.md)
|
|
groups the common failures by symptom:
|
|
|
|
| Symptom | Where to look |
|
|
| ------- | ------------- |
|
|
| LAN client gets `fd97:...`, not `fd01:...` | DNS path: dnsmasq still pointing at port 5354. See "DNS queries fail". |
|
|
| `dig` succeeds with a pool address but `ping6` times out | Pool route or proxy NDP. See "Virtual IP unreachable from client". |
|
|
| `ping6` works but TCP times out | NAT pipeline or mesh-side firewall. See "Ping works but TCP does not". |
|
|
| Gateway service won't start | "No gateway section in configuration" recipe. |
|
|
| Inbound `curl` hits the listen port but never reaches the LAN target | Mesh-side firewall first, then the port-forward rule. |
|
|
|
|
The first thing the troubleshoot guide does in any of these cases is
|
|
ask the gateway directly via `show_gateway` and `show_mappings`. If
|
|
the mapping you expect is not there, the failure is on the DNS path;
|
|
if it is there in `state: Active` but traffic still fails, the
|
|
failure is downstream.
|
|
|
|
## What's next
|
|
|
|
- [../how-to/deploy-gateway.md](../how-to/deploy-gateway.md) —
|
|
Manual deployment on a non-OpenWrt Linux host. Same gateway,
|
|
same config, but you wire up dnsmasq/Unbound/etc. yourself,
|
|
install a pool route per LAN client (or via your own RA daemon),
|
|
and manage the systemd unit instead of the procd init script.
|
|
- [../design/fips-gateway.md](../design/fips-gateway.md) — The
|
|
design doc: NAT pipeline (DNAT, SNAT, masquerade, inbound DNAT),
|
|
virtual-IP pool lifecycle (Allocated -> Active -> Draining ->
|
|
reclaimed), DNS resolution flow, conntrack integration.
|
|
- [../reference/configuration.md § Gateway](../reference/configuration.md#gateway-gateway)
|
|
— Every field of the `gateway:` block, including the conntrack
|
|
timeout overrides not used in this tutorial.
|
|
- [../reference/cli-fips-gateway.md](../reference/cli-fips-gateway.md)
|
|
— The `fips-gateway` binary's CLI options, exit codes, and
|
|
environment variables.
|