From 4491377d9b1af8cbeef26c25f64e8c02b2503cab Mon Sep 17 00:00:00 2001 From: Slawomir Koszewski Date: Mon, 26 Oct 2026 02:50:39 +0100 Subject: [PATCH] fix: /remote-access gives the router's WireGuard public key, endpoint and allowed IPs, which a peer's configuration needs. --- README.md | 2 +- debian-package/debian/changelog | 9 ++++++ .../src/usr/lib/vpn-router/vpnrouter.py | 2 ++ debian-package/src/usr/lib/vpn-router/web | 31 ++++++++++++++++--- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9254817..76bccb5 100644 --- a/README.md +++ b/README.md @@ -1157,7 +1157,7 @@ OpenVPN (`openvpn`) and WireGuard (`wireguard`), with the same token as `/users` | Request | Body | Answer | | --- | --- | --- | -| `GET /remote-access` | | `{"p2s", "openvpn", "wireguard", "running", "local_fqdn"}` | +| `GET /remote-access` | | `{"p2s", "openvpn", "wireguard", "running", "local_fqdn", "wireguard_server"}`; `wireguard_server` is `{"public_key", "endpoint", "allowed_ips"}`: the router's WireGuard public key (`null` before setup made it), `:` (`null` without a name) and the networks a peer reaches through the tunnel, the router's local CIDRs and the WireGuard network | | `PUT /remote-access/` | any of the settings of the section `p2s`, `openvpn` or `wireguard` | the section | `running` tells for each system whether setup runs it. IKEv2 and OpenVPN run once enabled with an diff --git a/debian-package/debian/changelog b/debian-package/debian/changelog index 6e10903..ef559c1 100644 --- a/debian-package/debian/changelog +++ b/debian-package/debian/changelog @@ -1,3 +1,12 @@ +vpn-router (0.25.1-1) unstable; urgency=medium + + fix: /remote-access gives the router's WireGuard public key, endpoint and allowed IPs, which a peer's configuration needs. + + * GET /remote-access answers wireguard_server: {"public_key", + "endpoint", "allowed_ips"}. + + -- Slawomir Koszewski Tue, 03 Nov 2026 01:30:00 +0100 + vpn-router (0.25.0-1) unstable; urgency=medium feature: a VPN user has WireGuard peers, each a device with its public key and IPs, kept in the directory and written into wg0.conf by setup. diff --git a/debian-package/src/usr/lib/vpn-router/vpnrouter.py b/debian-package/src/usr/lib/vpn-router/vpnrouter.py index a996a8c..bdb78ee 100644 --- a/debian-package/src/usr/lib/vpn-router/vpnrouter.py +++ b/debian-package/src/usr/lib/vpn-router/vpnrouter.py @@ -38,6 +38,8 @@ SITE_TO_SITE = SWANCTL_CONF_D / 'site-to-site.conf' ROAD_WARRIOR = SWANCTL_CONF_D / 'road-warrior.conf' P2S_FORWARDER = pathlib.Path('/etc/systemd/resolved.conf.d/p2s-forwarder.conf') WG_CONF = pathlib.Path('/etc/wireguard/wg0.conf') +#: The router's WireGuard public key, which setup writes with its private key. +WG_PUBLIC_KEY = pathlib.Path('/etc/wireguard/wg0.pub') #: The lines around the [Peer] sections of the users' WireGuard peers in WG_CONF, which setup writes from the directory. WG_PEERS_BEGIN = "# BEGIN WireGuard peers of the users of the router's directory" WG_PEERS_END = "# END WireGuard peers of the users of the router's directory" diff --git a/debian-package/src/usr/lib/vpn-router/web b/debian-package/src/usr/lib/vpn-router/web index b71551e..1af3d35 100644 --- a/debian-package/src/usr/lib/vpn-router/web +++ b/debian-package/src/usr/lib/vpn-router/web @@ -89,6 +89,7 @@ import collections import configparser import fcntl import hashlib +import ipaddress import json import os import pwd @@ -823,13 +824,32 @@ def backup(method, path, body): return 200, {'settings': backup_settings(cfg['backup'])} +def wireguard_server(cfg, state): + """What a WireGuard peer's configuration needs of the router: {public_key, endpoint, allowed_ips}; public_key is + null before setup made the key pair, endpoint, :, null without a name, and + allowed_ips the networks reached through the tunnel, the router's local CIDRs and the WireGuard network.""" + try: + public_key = vpnrouter.WG_PUBLIC_KEY.read_text(encoding='utf-8').strip() or None + except OSError: + public_key = None + fqdn = cfg['wan']['local_fqdn'].strip() + address = cfg['wireguard']['address'].strip() + networks = section(state, 'network').get('local_cidrs') + allowed = [cidr for cidr in networks if isinstance(cidr, str)] if isinstance(networks, list) else [] + if address: + allowed.append(str(ipaddress.ip_interface(address).network)) + return {'public_key': public_key, 'endpoint': f'{fqdn}:{cfg["wireguard"]["listen_port"]}' if fqdn else None, + 'allowed_ips': list(dict.fromkeys(allowed))} + + def remote_access(state, method, path, body): """Answer a /remote-access request: the HTTP status and the JSON document. - GET /remote-access {"p2s", "openvpn", "wireguard", "running", "local_fqdn"}: the settings of the three - remote access systems (REMOTE_ACCESS), whether setup runs each (running: {p2s, - openvpn, wireguard}), and wan.local_fqdn, which IKEv2 and OpenVPN need with the - router's VPN server certificate + GET /remote-access {"p2s", "openvpn", "wireguard", "running", "local_fqdn", "wireguard_server"}: the + settings of the three remote access systems (REMOTE_ACCESS), whether setup runs + each (running: {p2s, openvpn, wireguard}), wan.local_fqdn, which IKEv2 and OpenVPN + need with the router's VPN server certificate, and what a WireGuard peer's + configuration needs of the router (wireguard_server) PUT /remote-access/ change any of the settings of the system's section; answers the section A change is made as /site-to-site makes one, and applied by restarting vpn-router-setup without waiting for it. @@ -843,7 +863,8 @@ def remote_access(state, method, path, body): cfg = vpnrouter.load_config() return 200, {**{system: cfg[system] for system in REMOTE_ACCESS}, 'running': {system: bool(state.get(system)) for system in REMOTE_ACCESS}, - 'local_fqdn': cfg['wan']['local_fqdn']} + 'local_fqdn': cfg['wan']['local_fqdn'], + 'wireguard_server': wireguard_server(cfg, state)} if method != 'PUT' or len(parts) != 2 or parts[1] not in REMOTE_ACCESS: return 404, {'error': f'no route {method} {path}'} system = parts[1]