feature: Added an internally only exposed status web service.
Release / release (push) Successful in 17s
Release / release (push) Successful in 17s
This commit is contained in:
1 parent
5402256ef6
commit
7163f167e0
10 files changed
+593
No files matched your search
@@ -10,8 +10,10 @@ firewall and NAT rules are written against them, so choosing the wrong one
|
||||
would be a silent and security-relevant mistake.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -24,13 +26,18 @@ from vpnrouter import fail
|
||||
BEFORE_RULES = pathlib.Path('/etc/ufw/before.rules')
|
||||
UFW_DEFAULTS = pathlib.Path('/etc/default/ufw')
|
||||
WG_DIR = pathlib.Path('/etc/wireguard')
|
||||
WEB_STATE = pathlib.Path('/run/vpn-router/web.json')
|
||||
|
||||
FILTER_ANCHOR = '# End required lines'
|
||||
|
||||
#: Configuration options whose values are masked wherever the configuration is shown.
|
||||
SECRET_OPTION = re.compile(r'(^psk$)|secret|password|token|_key$')
|
||||
|
||||
BLOCKS = (
|
||||
('# IPSEC RULES START', '# IPSEC RULES END'),
|
||||
('# WIREGUARD RULES START', '# WIREGUARD RULES END'),
|
||||
('# P2S DNS RULES START', '# P2S DNS RULES END'),
|
||||
('# WEB RULES START', '# WEB RULES END'),
|
||||
('# ROUTER FORWARD RULES START', '# ROUTER FORWARD RULES END'),
|
||||
('# ROUTER NAT RULES START', '# ROUTER NAT RULES END'),
|
||||
('# ROUTER MSS RULES START', '# ROUTER MSS RULES END'),
|
||||
@@ -149,6 +156,14 @@ def filter_block(ctx):
|
||||
]
|
||||
lines += ['# P2S DNS RULES END']
|
||||
|
||||
if ctx['web_enabled'] and ctx['int_iface']:
|
||||
lines += [
|
||||
'',
|
||||
'# WEB RULES START',
|
||||
f'-A ufw-before-input -i {ctx["int_iface"]} -p tcp --dport {ctx["web_port"]} -j ACCEPT',
|
||||
'# WEB RULES END',
|
||||
]
|
||||
|
||||
if vpnrouter.routing_ready(ctx):
|
||||
lines += ['', '# ROUTER FORWARD RULES START']
|
||||
for subnet in ctx['local_cidr_list']:
|
||||
@@ -309,6 +324,48 @@ def refresh_docker_rules():
|
||||
run(['systemctl', 'restart', 'vpn-router-docker.service'], check=False)
|
||||
|
||||
|
||||
def refresh_web(cfg, ctx):
|
||||
"""Hand the web service what it needs and restart it.
|
||||
|
||||
The service takes the address to bind to, the port, the features of the
|
||||
router, the secret that signs its tokens, the configuration with its
|
||||
secrets masked and the facts resolved from the system from a file here, so
|
||||
that it needs nothing but the standard library and the configuration code.
|
||||
The file is readable by root only. The service ends quietly when
|
||||
web.enabled is false.
|
||||
"""
|
||||
masked = {
|
||||
section: {option: '********' if SECRET_OPTION.search(option) and value else value
|
||||
for option, value in options.items()}
|
||||
for section, options in cfg.items()
|
||||
}
|
||||
WEB_STATE.parent.mkdir(parents=True, exist_ok=True)
|
||||
WEB_STATE.touch(mode=0o600)
|
||||
WEB_STATE.chmod(0o600)
|
||||
WEB_STATE.write_text(json.dumps({
|
||||
'enabled': bool(ctx['web_enabled']),
|
||||
'bind': ctx['int_addr'],
|
||||
'port': ctx['web_port'],
|
||||
'jwt_secret': cfg['web']['jwt_secret'],
|
||||
'site_to_site': bool(vpnrouter.s2s_ready(ctx)),
|
||||
'p2s': bool(vpnrouter.p2s_ready(ctx)),
|
||||
'wireguard': bool(vpnrouter.wg_ready(ctx)),
|
||||
'configuration': masked,
|
||||
'network': {
|
||||
'external_interface': ctx['wan_iface'],
|
||||
'internal_interface': ctx['int_iface'],
|
||||
'external_addresses': ctx['local_addr_list'],
|
||||
'internal_address': ctx['int_addr'],
|
||||
'internal_gateway': ctx['int_gateway_ip'],
|
||||
'local_identity': ctx['local_id'],
|
||||
'remote_identity': ctx['remote_id'],
|
||||
'local_cidrs': ctx['local_cidr_list'],
|
||||
'remote_cidrs': ctx['remote_cidr_list'],
|
||||
},
|
||||
}) + '\n', encoding='utf-8')
|
||||
run(['systemctl', 'restart', 'vpn-router-web.service'], check=False)
|
||||
|
||||
|
||||
def main():
|
||||
cfg = vpnrouter.load_config()
|
||||
ctx, changed = vpnrouter.configure(cfg)
|
||||
@@ -348,6 +405,7 @@ def main():
|
||||
|
||||
run_platform_setup(cfg, ctx)
|
||||
refresh_docker_rules()
|
||||
refresh_web(cfg, ctx)
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user