linuxrouter/docker/router-dash/app/action_apply_vpn.py

93 lines
3.6 KiB
Python

from flask import Blueprint, request, redirect, flash
from auth import require_level
from config_utils import load_core, save_core, verify_core_hash, apply_msg, _APPLY_CMD_VPN
import sanitize
import validate
bp = Blueprint('action_apply_vpn', __name__)
_VIEW = '/view/view_vpn'
_MTU_MIN = 576
_MTU_MAX = 9000
@bp.route('/action/apply_vpn', methods=['POST'])
@require_level('administrator')
def apply_vpn():
listen_port_raw = request.form.get('vpn_listen_port', '').strip()
gateway_raw = request.form.get('vpn_gateway', '').strip()
domain = sanitize.hostname(request.form.get('vpn_domain', ''))
dns_raw = request.form.get('vpn_dns_server', '').strip()
mtu_raw = request.form.get('vpn_mtu', '').strip()
# -- Listen port -----------------------------------------------------------
if not listen_port_raw:
flash('The configuration has not been saved because the listen port is required.', 'error')
return redirect(_VIEW)
try:
listen_port = int(listen_port_raw)
if not (1 <= listen_port <= 65535):
raise ValueError
except (ValueError, TypeError):
flash(f'The configuration has not been saved because "{listen_port_raw}" is not a valid port number (1-65535).', 'error')
return redirect(_VIEW)
# -- Gateway (required) ----------------------------------------------------
if not gateway_raw:
flash('The configuration has not been saved because a gateway IP address is required.', 'error')
return redirect(_VIEW)
gateway = validate.ip(gateway_raw)
if not gateway:
flash(f'The configuration has not been saved because "{gateway_raw}" is not a valid IP address.', 'error')
return redirect(_VIEW)
# -- DNS server (optional) -------------------------------------------------
dns_server = ''
if dns_raw:
dns_server = validate.ip(dns_raw)
if not dns_server:
flash(f'The configuration has not been saved because "{dns_raw}" is not a valid IP address for DNS server.', 'error')
return redirect(_VIEW)
# -- MTU (optional) --------------------------------------------------------
mtu = None
if mtu_raw:
try:
mtu = int(mtu_raw)
if not (_MTU_MIN <= mtu <= _MTU_MAX):
raise ValueError
except (ValueError, TypeError):
flash(f'The configuration has not been saved because "{mtu_raw}" is not a valid MTU '
f'(must be a number between {_MTU_MIN} and {_MTU_MAX}).', 'error')
return redirect(_VIEW)
# -- Hash check and save ---------------------------------------------------
if not verify_core_hash(request.form.get('config_hash', '')):
flash('Configuration was modified by another session. Please refresh and try again.', 'error')
return redirect(_VIEW)
core = load_core()
vpn_vlan = next((v for v in core.get('vlans', []) if 'vpn_information' in v), None)
if vpn_vlan is None:
flash('The configuration has not been saved because no VPN VLAN was found in the configuration.', 'error')
return redirect(_VIEW)
info = vpn_vlan.setdefault('vpn_information', {})
info['listen_port'] = listen_port
info['gateway'] = gateway
info['domain'] = domain
overrides = info.setdefault('explicit_overrides', {})
if dns_server:
overrides['dns_server'] = dns_server
else:
overrides.pop('dns_server', None)
if mtu is not None:
overrides['mtu'] = mtu
else:
overrides.pop('mtu', None)
save_core(core)
flash(apply_msg(_APPLY_CMD_VPN), 'success')
return redirect(_VIEW)