Skip to content

Parker config broker - #11

Open
maurerle wants to merge 19 commits into
mainfrom
parker_config_broker
Open

maurerle wants to merge 19 commits into
mainfrom
parker_config_broker

Conversation

@maurerle

Copy link
Copy Markdown
Member

Configured a NAT64 and jool on SN03 - needs a proper review - but works so far:
https://map.aachen.freifunk.net/#/en/map/ea5981962ae4

One SIIT+PLAT instance; the role applies the config itself, so no dropped
handler can leave the file and the running instance apart, and jool_port_range
is asserted against the host's own port space because NAT64 on a public pool4
address shares it.
The guard drops traffic to pool6 that is not from an allowed prefix on the
expected interface, with a DROP that exists before anything can jump into it.
Forward-only recursion with dns64 for 64:ff9b::/96 and DNSSEC validation off,
since synthesised records carry no RRSIG. The ACL names the networks whose
IPv4 transits our NAT64 - synthesised answers handed to native IPv4 clients
break their Happy Eyeballs.
Reloads after the start unconditionally, so a dropped handler cannot leave
named serving the previous file.
Minute cron like autoupdate_wg.py, but AllowedIPs are the delegated /64s the
broker told the node, and their routes in parker_route_table are diffed
against the interface so a deleted record takes its routes with it.
A record conflict aborts the pass instead of routing two nodes' client LANs to
one prefix.
ff.dns64 and ff.jool existed, but no play referenced them, so the pair we
have never run could not be tried at all. New parker_concentrators group (one
host, sn03); the pool is the first /56 of the upper half of our /48, and
DNS64 ACL plus the NAT64 guard allow only that pool.
The play also checks what it does not install: IPv6 forwarding (ff.ipforward
lives in supernode.yml) and that DNS64 and NAT64 agree on the /96.
ff.parker_concentrator adds one /64 per node with 'ip route replace' and
never tells bird, so the routes reached neither master6 nor OSPF and no
return traffic found its way back. The kernel protocol gains an optional
learn flag; sn03 turns it on with an import filter for the pool, and the play
asserts that a kernel protocol is attached to parker_route_table and learns.
The NAT64's return packets carry 64:ff9b:: as their source, so none of the
existing from-based rules match them and the pool is looked up in main. A
RoutingPolicyRule learns optional To= and Priority=; without them it renders
as before. sn03 routes traffic to the pool (32750) and from it (32749) into
table 42, clear of the auto-assigned 3276x block and above the kernel's
'from all lookup main': the pool is announced to FFRL only, so main's
default via the site uplink has no path back.
GET /config mints global state, unlike add_key: look up by pubkey first
(a node re-asks every retry seconds), allocate a sequential id under flock,
commit before answering, and check every git return code - the reply carries
a prefix, so a swallowed push failure hands two nodes the same /63.
parker_lib.py holds the record format, the id <-> prefix bijection
(range6 + xlat_range6, 464XLAT first), first-fit reuse for the GC, the rate
limiter and usign signing by file (signify-openbsd writes the same format).

The records live in a registry of their own, /var/lib/parker/registry, not in
peers-wg: that tree is rewritten by every batman node poll, and parker keys
have a different owner and lifetime. It starts without a remote, so the broker
commits and the log on that host is the audit; the daily GC deletes a record
only when no gateway published a recent handshake for it.
The id <-> /63-pair bijection, first-fit reuse and exhaustion, idempotent
re-registration, commit-but-unpushed deferral, a registry without a remote,
concurrent registration of one key, the record parser and the rate limiter,
against real scratch git repositories; usign is stubbed.
Fingerprint 3befd26f90d9530e; the nodes verify it against the public key in
site.parker.config_pubkey. Re-encrypting the vault rewrites the whole file.
The broker moves from monitor, which runs ff.nginx and ff.certbot, to a host
that runs neither. With wgbroker_vhost set the role installs both, answers the
ACME challenge over http, obtains the certificate and only then switches to
the https vhost - an ssl block pointing at a missing file keeps nginx from
starting at all. Empty wgbroker_vhost leaves the role as it was, so monitor
does not grow a second vhost.
site.conf now sends add_key and /config to 03.wg-node, so the broker has to
run there. monitor keeps its instance for images that carry the old name; only
sn03 has a parker block, and part of what a node gets back is a prefix, so the
parker service stays on one host.
Private half of the wg-nodes interface; the public key sits in the
concentrators list the broker hands out.
The role now runs before dns64 and jool so the guard can name its
interface, and it derives node prefixes from the same pool the broker
allocates out of. Handshake liveness is published into the registry for
the broker-side collector.

sn03 gets its tunnel address from the reserved id-0 block and the full
config the broker answers with: community client IPv4, xlat on, both
concentrators, rate limit, and a log-only garbage collector for the
first cycle.
Two ways the reconciler deleted routes it should have kept. The add branch
never added the new prefixes to the expected set, so one pass with a new
peer emptied table 42 of every /64 for a minute. And current_routes()
counted every route through the interface, including the /128 bird
installs and restores, so each pass deleted it and watched it come back.

Both are fixed at the source: the expected set gets the added prefixes,
and only /64s count as this gateway's routes.

parker_lib exposes DELEGATION_BITS for that.
BIRD 2 only accepts import/export inside a channel block, so the static
protocol the template rendered was a syntax error ("unexpected IMPORT").
Pick the channel the way the kernel block does: is_ipv6, IPv6 by default.
bb-a's uplink_hostroute is an IPv4 route and says so.
FFRL routes our /56s but nothing beyond, and the pool only existed as
per-node /64s, so nothing announced it and replies to pool addresses died
at FFRL's tunnel ends. Originate the aggregate on sn03 like the bat /56:
OSPF carries it to both backbones, which announce it via is_aachen_3006().
A static on the backbones would keep announcing it when a backbone loses
its adjacency to sn03; this way that backbone withdraws it.
A parker node is not part of a batman domain and the monitor records the
concentrator as its address, so nothing polls it for statistics. The
concentrator can: one unicast request over the tunnel reaches the same
respondd a Gluon node runs.

Add the module list, port, node_address() and parse_respondd(). The answer
is raw-deflated JSON; decoding it here only keeps junk out of the monitor's
log and names the node that stayed silent, the payload itself is forwarded
unchanged. node_address() also replaces the inline ip_network()[1] in
build_config so the address rule lives in one place.
Pin the answer format instead of the code: raw deflate only, a JSON object
only, and a 12 hex digit node id that may come from any of the three
modules. A node id of the wrong length or with non-hex characters must be
rejected, otherwise the monitor drops the answer without a trace.
The monitor can neither multicast into the parker pool nor reach a node
directly: it records the concentrator as the node's address and never asks
the node itself. Every parked node therefore stayed invisible on the map.

The concentrator now asks each node in the registry for nodeinfo,
statistics and neighbours on port 1001, checks the answer and forwards it
untouched to the monitor's central yanic listener. That is the same
deframed format the monitor's own respondd connection uses for bat nodes,
so it parses the push like a local answer; a lost request costs one minute
of freshness, not a node marked offline.

Off by default and switched on for parker_concentrators, with the cron job
removed again when the flag goes back to false.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant