feature: the firewall lets the Router Manager in on the internal interface.
Release / release (push) Successful in 11s
Release / release (push) Successful in 11s
This commit is contained in:
1 parent
a7b29e0655
commit
0ff74cc8c9
7 files changed
+70
-2
No files matched your search
@@ -189,3 +189,29 @@ options at all. They are recognised by name as before: `psk`, and options with `
|
|||||||
|
|
||||||
Consequences: No secret reaches the web service's state file or any answer of the API. A client
|
Consequences: No secret reaches the web service's state file or any answer of the API. A client
|
||||||
cannot tell whether a secret is set. A new secret option still needs a name that matches.
|
cannot tell whether a secret is set. A new secret option still needs a name that matches.
|
||||||
|
|
||||||
|
## ADR-9: The Router Manager is a separate package with a small Python server
|
||||||
|
|
||||||
|
Status: Accepted
|
||||||
|
|
||||||
|
Context: The router needs a web application to manage it, which may run on the router or on
|
||||||
|
another Linux system. The router's web service needs a token signed with `web.jwt_secret` for
|
||||||
|
`/config` and `/users` and sends no CORS headers, so a browser cannot call it with the secret
|
||||||
|
kept away from the page.
|
||||||
|
|
||||||
|
Decision: `vpn-router-manager` is a Debian package of its own, built in the repository `linux-cloud-router-manager`. A React and
|
||||||
|
MUI application in the style of manage-ui is built with Vite when the package is built and
|
||||||
|
shipped as static files. A Python server, using the Ubuntu packages `python3-jwt` and `python3-requests`, serves them and
|
||||||
|
passes every `/api/<path>` call to the router's `/<path>`, signing a short-lived token with the
|
||||||
|
router's secret; it holds no logic of the router's own. It reads its settings from
|
||||||
|
`/etc/vpn-router-manager/manager.json` at each request; on the router the settings not given
|
||||||
|
come from `vpn-router.json`, and it listens on the internal address like the status web
|
||||||
|
service, with the same discovery thread. `vpn-router-setup` opens the manager's port on the
|
||||||
|
internal interface while the manager is installed, so the firewall stays in one place. The
|
||||||
|
manager asks for no authentication yet.
|
||||||
|
|
||||||
|
Consequences: The router needs no Node.js; the package needs only `python3` and packages of the Ubuntu archive. The secret never
|
||||||
|
reaches the browser. The application checks the shape of every answer of the router. Anyone who
|
||||||
|
reaches the manager's port manages the router, so on another system it listens on `127.0.0.1`
|
||||||
|
unless told otherwise. The router's firewall depends on whether the manager is installed, and a
|
||||||
|
changed manager port needs `vpn-router-setup` to run again.
|
||||||
@@ -502,6 +502,14 @@ request reads the token secret from `vpn-router.json`, and the features and the
|
|||||||
before that file exists the page shows no features. `vpn-router-setup` opens `web.port` on the
|
before that file exists the page shows no features. `vpn-router-setup` opens `web.port` on the
|
||||||
internal interface in the firewall.
|
internal interface in the firewall.
|
||||||
|
|
||||||
|
## Router Manager
|
||||||
|
|
||||||
|
The `vpn-router-manager` package, built in the repository `linux-cloud-router-manager`, is a web
|
||||||
|
application that shows the state of the router and manages its users through the status web
|
||||||
|
service. It can be installed on the router or on another Linux system. While it is installed on
|
||||||
|
the router, `vpn-router-setup` opens its port (`port` in `/etc/vpn-router-manager/manager.json`,
|
||||||
|
8090 by default) on the internal interface; restart `vpn-router-setup` after changing it.
|
||||||
|
|
||||||
## Removal
|
## Removal
|
||||||
|
|
||||||
`apt-get remove` stops `vpn-router-docker`, which removes the Docker rules. It terminates the
|
`apt-get remove` stops `vpn-router-docker`, which removes the Docker rules. It terminates the
|
||||||
|
|||||||
Whitespace-only changes.
@@ -1,3 +1,13 @@
|
|||||||
|
vpn-router (0.5.4-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
feature: the firewall lets the Router Manager in on the internal interface.
|
||||||
|
|
||||||
|
* While vpn-router-manager is installed, vpn-router-setup opens its port,
|
||||||
|
port in /etc/vpn-router-manager/manager.json or 8090, on the internal
|
||||||
|
interface. Purging the package removes the rule.
|
||||||
|
|
||||||
|
-- Slawomir Koszewski <slawek@koszewscy.waw.pl> Sat, 24 Oct 2026 13:00:00 +0200
|
||||||
|
|
||||||
vpn-router (0.5.3-1) unstable; urgency=medium
|
vpn-router (0.5.3-1) unstable; urgency=medium
|
||||||
|
|
||||||
fix: the status always shows the state of slapd.
|
fix: the status always shows the state of slapd.
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ strip_ufw_blocks() {
|
|||||||
|
|
||||||
tmp="$(mktemp)"
|
tmp="$(mktemp)"
|
||||||
awk '
|
awk '
|
||||||
/^# (IPSEC|WIREGUARD|OPENVPN|P2S DNS|WEB|ROUTER FORWARD|ROUTER NAT|ROUTER MSS) RULES START$/ {
|
/^# (IPSEC|WIREGUARD|OPENVPN|P2S DNS|WEB|MANAGER|ROUTER FORWARD|ROUTER NAT|ROUTER MSS) RULES START$/ {
|
||||||
skip = 1; pending = 0; next
|
skip = 1; pending = 0; next
|
||||||
}
|
}
|
||||||
/^# (IPSEC|WIREGUARD|OPENVPN|P2S DNS|WEB|ROUTER FORWARD|ROUTER NAT|ROUTER MSS) RULES END$/ {
|
/^# (IPSEC|WIREGUARD|OPENVPN|P2S DNS|WEB|MANAGER|ROUTER FORWARD|ROUTER NAT|ROUTER MSS) RULES END$/ {
|
||||||
skip = 0; next
|
skip = 0; next
|
||||||
}
|
}
|
||||||
skip { next }
|
skip { next }
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ UFW_DEFAULTS = pathlib.Path('/etc/default/ufw')
|
|||||||
WG_DIR = pathlib.Path('/etc/wireguard')
|
WG_DIR = pathlib.Path('/etc/wireguard')
|
||||||
WEB_STATE = pathlib.Path('/run/vpn-router/web.json')
|
WEB_STATE = pathlib.Path('/run/vpn-router/web.json')
|
||||||
|
|
||||||
|
#: The Router Manager, vpn-router-manager, when it is installed, and its settings.
|
||||||
|
MANAGER = pathlib.Path('/usr/lib/vpn-router-manager/manager')
|
||||||
|
MANAGER_CONFIG = pathlib.Path('/etc/vpn-router-manager/manager.json')
|
||||||
|
MANAGER_PORT = 8090
|
||||||
|
|
||||||
FILTER_ANCHOR = '# End required lines'
|
FILTER_ANCHOR = '# End required lines'
|
||||||
|
|
||||||
#: Configuration options left out wherever the configuration is shown.
|
#: Configuration options left out wherever the configuration is shown.
|
||||||
@@ -42,6 +47,7 @@ BLOCKS = (
|
|||||||
('# OPENVPN RULES START', '# OPENVPN RULES END'),
|
('# OPENVPN RULES START', '# OPENVPN RULES END'),
|
||||||
('# P2S DNS RULES START', '# P2S DNS RULES END'),
|
('# P2S DNS RULES START', '# P2S DNS RULES END'),
|
||||||
('# WEB RULES START', '# WEB RULES END'),
|
('# WEB RULES START', '# WEB RULES END'),
|
||||||
|
('# MANAGER RULES START', '# MANAGER RULES END'),
|
||||||
('# ROUTER FORWARD RULES START', '# ROUTER FORWARD RULES END'),
|
('# ROUTER FORWARD RULES START', '# ROUTER FORWARD RULES END'),
|
||||||
('# ROUTER NAT RULES START', '# ROUTER NAT RULES END'),
|
('# ROUTER NAT RULES START', '# ROUTER NAT RULES END'),
|
||||||
('# ROUTER MSS RULES START', '# ROUTER MSS RULES END'),
|
('# ROUTER MSS RULES START', '# ROUTER MSS RULES END'),
|
||||||
@@ -129,6 +135,15 @@ def is_configured(ctx):
|
|||||||
vpnrouter.openvpn_ready(ctx)))
|
vpnrouter.openvpn_ready(ctx)))
|
||||||
|
|
||||||
|
|
||||||
|
def manager_port():
|
||||||
|
"""The port of the Router Manager: port in its settings, or MANAGER_PORT when it is not set or not a port."""
|
||||||
|
try:
|
||||||
|
port = json.loads(MANAGER_CONFIG.read_text(encoding='utf-8')).get('port')
|
||||||
|
except (OSError, ValueError, AttributeError):
|
||||||
|
return MANAGER_PORT
|
||||||
|
return port if isinstance(port, int) and not isinstance(port, bool) and 1 <= port <= 65535 else MANAGER_PORT
|
||||||
|
|
||||||
|
|
||||||
def filter_block(ctx):
|
def filter_block(ctx):
|
||||||
lines = [
|
lines = [
|
||||||
'',
|
'',
|
||||||
@@ -185,6 +200,15 @@ def filter_block(ctx):
|
|||||||
'# WEB RULES END',
|
'# WEB RULES END',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if MANAGER.exists() and ctx['int_iface']:
|
||||||
|
port = manager_port()
|
||||||
|
lines += [
|
||||||
|
'',
|
||||||
|
'# MANAGER RULES START',
|
||||||
|
f'-A ufw-before-input -i {ctx["int_iface"]} -p tcp --dport {port} -j ACCEPT',
|
||||||
|
'# MANAGER RULES END',
|
||||||
|
]
|
||||||
|
|
||||||
if vpnrouter.routing_ready(ctx):
|
if vpnrouter.routing_ready(ctx):
|
||||||
lines += ['', '# ROUTER FORWARD RULES START']
|
lines += ['', '# ROUTER FORWARD RULES START']
|
||||||
for subnet in ctx['local_cidr_list']:
|
for subnet in ctx['local_cidr_list']:
|
||||||
|
|||||||
File renamed without changes.
Reference in new issue
Block a user