fix: WireGuard peers keep their tunnel key when others come and go (#32)
driver / lint (pull_request) Successful in 17s
driver / standard (pull_request) Failing after 17s
driver / test (3.10) (pull_request) Failing after 3s
driver / test (3.11) (pull_request) Failing after 6s
driver / types (pull_request) Successful in 1m2s
driver / lowest (pull_request) Successful in 59s
driver / test (3.13) (pull_request) Successful in 1m39s
driver / test (3.12) (pull_request) Successful in 1m42s
driver / build (pull_request) Successful in 29s
driver / security (pull_request) Successful in 1m11s
CI / driver (pull_request) Failing after 3m12s
driver / publish (pull_request) Skipped
driver / lint (pull_request) Successful in 17s
driver / standard (pull_request) Failing after 17s
driver / test (3.10) (pull_request) Failing after 3s
driver / test (3.11) (pull_request) Failing after 6s
driver / types (pull_request) Successful in 1m2s
driver / lowest (pull_request) Successful in 59s
driver / test (3.13) (pull_request) Successful in 1m39s
driver / test (3.12) (pull_request) Successful in 1m42s
driver / build (pull_request) Successful in 29s
driver / security (pull_request) Successful in 1m11s
CI / driver (pull_request) Failing after 3m12s
driver / publish (pull_request) Skipped
get_vpn_tunnels() keyed WireGuard peers with a running counter over the peer rows, so a peer added ahead of an existing one renumbered every peer after it. Whatever a consumer stores per key moved with it: netOrk's site link and tunnel check ended up on a new, offline peer and alarmed while the real tunnel was up. The key is now the interface and the start of the public key, as in napalm-linux, made URL-safe because the key is a path segment. Two peers sharing the prefix get the whole key; a row without a public key keeps its position. IPsec and OpenVPN keys were already stable. Every WireGuard key changes once; netOrk carries its per-tunnel metadata across (netork#1654).
This commit is contained in:
1 parent
63ce6e78bd
commit
9f45952605
3 files changed
+137
-3
No files matched your search
@@ -93,6 +93,28 @@ def _carp_master(entry: dict[str, Any]) -> bool:
|
||||
return str(entry.get("status") or "").strip().upper() == "MASTER"
|
||||
|
||||
|
||||
#: How much of a public key names a peer, the same length as napalm-linux uses.
|
||||
_WG_KEY_PREFIX = 8
|
||||
|
||||
|
||||
def _wireguard_key(row: dict[str, Any], position: int, taken: dict[str, Any]) -> str:
|
||||
"""A WireGuard peer's tunnel key: its interface and the start of its public key.
|
||||
|
||||
Not its position: a peer added ahead of another would renumber it, and
|
||||
whatever a consumer keeps per key would move to a different peer (#32). The
|
||||
base64 is made URL-safe because the key is used as a path segment. Two peers
|
||||
sharing a prefix get the whole key; one without a key keeps its position.
|
||||
"""
|
||||
public_key = (row.get("public-key") or "").strip()
|
||||
if not public_key:
|
||||
return f"wireguard-{position}"
|
||||
safe = public_key.rstrip("=").replace("+", "-").replace("/", "_")
|
||||
key = f"wireguard-{row.get('if') or 'wg'}-{safe[:_WG_KEY_PREFIX]}"
|
||||
if key in taken:
|
||||
key = f"wireguard-{row.get('if') or 'wg'}-{safe}"
|
||||
return key
|
||||
|
||||
|
||||
class OPNsenseDriver(
|
||||
OPNsensePingMixin,
|
||||
ConfigSyncMixin,
|
||||
@@ -2172,8 +2194,8 @@ class OPNsenseDriver(
|
||||
# {"if":"wg0", "type":"interface", ...},
|
||||
# {"if":"wg0", "type":"peer", "public-key":"...",
|
||||
# "endpoint":"1.2.3.4:51820", "transfer-rx":N, "transfer-tx":N,
|
||||
# "name":"HCQ", "peer-status":"online",
|
||||
# "latest-handshake-age":45, "ifname":"HCQ"}, ...
|
||||
# "name":"office", "peer-status":"online",
|
||||
# "latest-handshake-age":45, "ifname":"office"}, ...
|
||||
# ]}
|
||||
data = self._get("/api/wireguard/service/show")
|
||||
rows = data.get("rows", []) if isinstance(data, dict) else []
|
||||
@@ -2202,7 +2224,7 @@ class OPNsenseDriver(
|
||||
or f"wg-peer-{wg_idx}"
|
||||
)
|
||||
|
||||
tunnels[f"wireguard-{wg_idx}"] = {
|
||||
tunnels[_wireguard_key(row, wg_idx, tunnels)] = {
|
||||
"type": "WireGuard",
|
||||
"local_endpoint": "",
|
||||
"remote_endpoint": remote_ip,
|
||||
|
||||
Reference in new issue
Block a user