summaryrefslogtreecommitdiff
path: root/src/conf_mode/interfaces-openvpn.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode/interfaces-openvpn.py')
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py45
1 files changed, 31 insertions, 14 deletions
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 3b8fae710..4750ca3e8 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2019-2021 VyOS maintainers and contributors
+# Copyright (C) 2019-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -32,8 +32,10 @@ from shutil import rmtree
from vyos.config import Config
from vyos.configdict import get_interface_dict
+from vyos.configdict import is_node_changed
from vyos.configverify import verify_vrf
from vyos.configverify import verify_bridge_delete
+from vyos.configverify import verify_mirror_redirect
from vyos.ifconfig import VTunIf
from vyos.pki import load_dh_parameters
from vyos.pki import load_private_key
@@ -47,6 +49,7 @@ from vyos.template import is_ipv4
from vyos.template import is_ipv6
from vyos.util import call
from vyos.util import chown
+from vyos.util import cmd
from vyos.util import dict_search
from vyos.util import dict_search_args
from vyos.util import makedir
@@ -82,10 +85,12 @@ def get_config(config=None):
tmp_pki = conf.get_config_dict(['pki'], key_mangling=('-', '_'),
get_first_key=True, no_tag_node_value_mangle=True)
- openvpn = get_interface_dict(conf, base)
+ ifname, openvpn = get_interface_dict(conf, base)
if 'deleted' not in openvpn:
openvpn['pki'] = tmp_pki
+ if is_node_changed(conf, base + [ifname, 'openvpn-option']):
+ openvpn.update({'restart_required': {}})
# We have to get the dict using 'get_config_dict' instead of 'get_interface_dict'
# as 'get_interface_dict' merges the defaults in, so we can not check for defaults in there.
@@ -225,11 +230,12 @@ def verify(openvpn):
if 'local_address' not in openvpn and 'is_bridge_member' not in openvpn:
raise ConfigError('Must specify "local-address" or add interface to bridge')
- if len([addr for addr in openvpn['local_address'] if is_ipv4(addr)]) > 1:
- raise ConfigError('Only one IPv4 local-address can be specified')
+ if 'local_address' in openvpn:
+ if len([addr for addr in openvpn['local_address'] if is_ipv4(addr)]) > 1:
+ raise ConfigError('Only one IPv4 local-address can be specified')
- if len([addr for addr in openvpn['local_address'] if is_ipv6(addr)]) > 1:
- raise ConfigError('Only one IPv6 local-address can be specified')
+ if len([addr for addr in openvpn['local_address'] if is_ipv6(addr)]) > 1:
+ raise ConfigError('Only one IPv6 local-address can be specified')
if openvpn['device_type'] == 'tun':
if 'remote_address' not in openvpn:
@@ -268,7 +274,7 @@ def verify(openvpn):
if dict_search('remote_host', openvpn) in dict_search('remote_address', openvpn):
raise ConfigError('"remote-address" and "remote-host" can not be the same')
- if openvpn['device_type'] == 'tap':
+ if openvpn['device_type'] == 'tap' and 'local_address' in openvpn:
# we can only have one local_address, this is ensured above
v4addr = None
for laddr in openvpn['local_address']:
@@ -423,8 +429,8 @@ def verify(openvpn):
# verify specified IP address is present on any interface on this system
if 'local_host' in openvpn:
if not is_addr_assigned(openvpn['local_host']):
- raise ConfigError('local-host IP address "{local_host}" not assigned' \
- ' to any interface'.format(**openvpn))
+ print('local-host IP address "{local_host}" not assigned' \
+ ' to any interface'.format(**openvpn))
# TCP active
if openvpn['protocol'] == 'tcp-active':
@@ -489,6 +495,7 @@ def verify(openvpn):
raise ConfigError('Username for authentication is missing')
verify_vrf(openvpn)
+ verify_mirror_redirect(openvpn)
return None
@@ -600,7 +607,7 @@ def generate(openvpn):
# Generate User/Password authentication file
if 'authentication' in openvpn:
- render(openvpn['auth_user_pass_file'], 'openvpn/auth.pw.tmpl', openvpn,
+ render(openvpn['auth_user_pass_file'], 'openvpn/auth.pw.j2', openvpn,
user=user, group=group, permission=0o600)
else:
# delete old auth file if present
@@ -616,16 +623,16 @@ def generate(openvpn):
# Our client need's to know its subnet mask ...
client_config['server_subnet'] = dict_search('server.subnet', openvpn)
- render(client_file, 'openvpn/client.conf.tmpl', client_config,
+ render(client_file, 'openvpn/client.conf.j2', client_config,
user=user, group=group)
# we need to support quoting of raw parameters from OpenVPN CLI
# see https://phabricator.vyos.net/T1632
- render(cfg_file.format(**openvpn), 'openvpn/server.conf.tmpl', openvpn,
+ render(cfg_file.format(**openvpn), 'openvpn/server.conf.j2', openvpn,
formater=lambda _: _.replace(""", '"'), user=user, group=group)
# Render 20-override.conf for OpenVPN service
- render(service_file.format(**openvpn), 'openvpn/service-override.conf.tmpl', openvpn,
+ render(service_file.format(**openvpn), 'openvpn/service-override.conf.j2', openvpn,
formater=lambda _: _.replace(""", '"'), user=user, group=group)
# Reload systemd services config to apply an override
call(f'systemctl daemon-reload')
@@ -647,9 +654,19 @@ def apply(openvpn):
return None
+ # verify specified IP address is present on any interface on this system
+ # Allow to bind service to nonlocal address, if it virtaual-vrrp address
+ # or if address will be assign later
+ if 'local_host' in openvpn:
+ if not is_addr_assigned(openvpn['local_host']):
+ cmd('sysctl -w net.ipv4.ip_nonlocal_bind=1')
+
# No matching OpenVPN process running - maybe it got killed or none
# existed - nevertheless, spawn new OpenVPN process
- call(f'systemctl reload-or-restart openvpn@{interface}.service')
+ action = 'reload-or-restart'
+ if 'restart_required' in openvpn:
+ action = 'restart'
+ call(f'systemctl {action} openvpn@{interface}.service')
o = VTunIf(**openvpn)
o.update(openvpn)