LibclusterMesh.WireGuardDump (libcluster_mesh v0.1.0)

Copy Markdown View Source

Parses wg show <interface> dump output into LibclusterMesh.Peer structs.

The dump format is stable and tab-separated: the first line describes the interface, every following line is a peer:

<public-key> <preshared-key> <endpoint> <allowed-ips> <latest-handshake> <rx> <tx> <keepalive>

The peer's mesh address is the first /32 entry in allowed-ips that falls inside the member CIDR. Both halves of that carry weight. A node is reached at one address, so an entry covering a range — the mesh itself, advertised by a subnet router — names no host and is not a candidate. And a subnet router lists the routes it carries alongside its own address, in no particular order, so the entry inside the CIDR is the one to take rather than the first one of any kind.

Plain WireGuard has no hostnames, so hostname is set to the IP string. A peer counts as online when its latest handshake is no older than handshake_max_age seconds (WireGuard rekeys about every 2 minutes on active tunnels).

Summary

Functions

Parses the dump output. now is the current Unix time in seconds and cidr selects which allowed-ips entry is the peer's mesh address.

Functions

parse_peers(out, now, handshake_max_age, cidr)

@spec parse_peers(String.t(), integer(), pos_integer(), LibclusterMesh.CIDR.t()) ::
  {:ok, [LibclusterMesh.Peer.t()]} | {:error, String.t()}

Parses the dump output. now is the current Unix time in seconds and cidr selects which allowed-ips entry is the peer's mesh address.

Never raises. Unrecognised peer lines are skipped, but output that is not a dump at all is an error rather than an empty mesh — the other three parsers draw that line too, and a cluster that never forms is the hardest failure here to tell from a mesh that is simply quiet.

iex> out = "privkey\tpubkey\t51820\toff\n" <>
...>   "peerkey1\t(none)\t172.17.0.3:51820\t192.168.1.0/24,10.77.0.2/32\t1700000000\t1000\t1000\toff\n" <>
...>   "peerkey2\t(none)\t(none)\t10.77.0.3/32\t0\t0\t0\toff\n"
iex> cidr = LibclusterMesh.CIDR.parse!("10.77.0.0/24")
iex> LibclusterMesh.WireGuardDump.parse_peers(out, 1700000060, 180, cidr)
{:ok,
 [
   %LibclusterMesh.Peer{ip: "10.77.0.2", hostname: "10.77.0.2", online?: true},
   %LibclusterMesh.Peer{ip: "10.77.0.3", hostname: "10.77.0.3", online?: false}
 ]}