summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2020-10-18 18:04:34 +0200
committerChristian Poessinger <christian@poessinger.com>2020-10-18 18:15:30 +0200
commit029f9839c21317ec5959b331eee25da472d08dc1 (patch)
tree4d4d9b8d3d142f783e0cc84015303a9e2920cfc7
parentb3e486604c46c4aec858706ac90c833f3b4ebe5c (diff)
downloadvyos-1x-029f9839c21317ec5959b331eee25da472d08dc1.tar.gz
vyos-1x-029f9839c21317ec5959b331eee25da472d08dc1.zip
openvpn: T2969: force creation of tunnel interfaces
A lot of VyOS code requires the Kernel interface to be present in order to properly work and adjust the interface to the users CLI intends (alias, ipv6, vrf - just to name a few). OpenVPN - when run in client mode - only creates the interface (e.g. vtun1) when the connection to the OpenVPN server was successful. This can't be always the case due to e.g. software-updates or routing issues to the remote side. This will in the end result in a zombie OpenVPN client interface where some config items might not have been set when the interface finally comes up - imagine a wrong assigned VRF instance. By always creating the OpenVPN interface manuall we ensure that all the CLI settings are properly configured in the OS kernel.
-rwxr-xr-xsmoketest/scripts/cli/test_interfaces_openvpn.py4
-rwxr-xr-xsrc/conf_mode/interfaces-openvpn.py86
2 files changed, 39 insertions, 51 deletions
diff --git a/smoketest/scripts/cli/test_interfaces_openvpn.py b/smoketest/scripts/cli/test_interfaces_openvpn.py
index 0ac91c170..2af07a579 100755
--- a/smoketest/scripts/cli/test_interfaces_openvpn.py
+++ b/smoketest/scripts/cli/test_interfaces_openvpn.py
@@ -17,6 +17,8 @@
import os
import unittest
+from netifaces import interfaces
+
from vyos.configsession import ConfigSession
from vyos.configsession import ConfigSessionError
from vyos.util import cmd
@@ -72,8 +74,8 @@ class TestInterfacesOpenVPN(unittest.TestCase):
self.assertIn(f'remote {remote_host}', config)
self.assertIn('persist-tun', config)
-
self.assertTrue(process_named_running(PROCESS_NAME))
+ self.assertIn(interface, interfaces())
if __name__ == '__main__':
# Our SSL certificates need a subject ...
diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index f2b580c6f..9cd72f691 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -32,6 +32,7 @@ from vyos.template import render
from vyos.util import call, chown, chmod_600, chmod_755
from vyos.validate import is_addr_assigned, is_ipv4
from vyos import ConfigError
+from vyos.util import cmd
from vyos import airbag
airbag.enable()
@@ -1057,56 +1058,41 @@ def apply(openvpn):
# existed - nevertheless, spawn new OpenVPN process
call(f'systemctl start openvpn@{interface}.service')
- # better late then sorry ... but we can only set interface alias after
- # OpenVPN has been launched and created the interface
- cnt = 0
- while interface not in interfaces():
- # If VPN tunnel can't be established because the peer/server isn't
- # (temporarily) available, the vtun interface never becomes registered
- # with the kernel, and the commit would hang if there is no bail out
- # condition
- cnt += 1
- if cnt == 50:
- break
-
- # sleep 250ms
- sleep(0.250)
-
- try:
- # we need to catch the exception if the interface is not up due to
- # reason stated above
- o = VTunIf(interface)
- # update interface description used e.g. within SNMP
- o.set_alias(openvpn['description'])
- # IPv6 accept RA
- o.set_ipv6_accept_ra(openvpn['ipv6_accept_ra'])
- # IPv6 address autoconfiguration
- o.set_ipv6_autoconf(openvpn['ipv6_autoconf'])
- # IPv6 forwarding
- o.set_ipv6_forwarding(openvpn['ipv6_forwarding'])
- # IPv6 Duplicate Address Detection (DAD) tries
- o.set_ipv6_dad_messages(openvpn['ipv6_dup_addr_detect'])
-
- # IPv6 EUI-based addresses - only in TAP mode (TUN's have no MAC)
- # If MAC has changed, old EUI64 addresses won't get deleted,
- # but this isn't easy to solve, so leave them.
- # This is even more difficult as openvpn uses a random MAC for the
- # initial interface creation, unless set by 'lladdr'.
- # NOTE: right now the interface is always deleted. For future
- # compatibility when tap's are not deleted, leave the del_ in
- if openvpn['mode'] == 'tap':
- for addr in openvpn['ipv6_eui64_prefix_remove']:
- o.del_ipv6_eui64_address(addr)
- for addr in openvpn['ipv6_eui64_prefix']:
- o.add_ipv6_eui64_address(addr)
-
- # assign/remove VRF (ONLY when not a member of a bridge,
- # otherwise 'nomaster' removes it from it)
- if not openvpn['is_bridge_member']:
- o.set_vrf(openvpn['vrf'])
-
- except:
- pass
+ if interface not in interfaces():
+ dev_type = openvpn['type']
+ cmd(f'sudo openvpn --mktun --dev-type {dev_type} --dev {interface}')
+
+ # we need to catch the exception if the interface is not up due to
+ # reason stated above
+ o = VTunIf(interface)
+ # update interface description used e.g. within SNMP
+ o.set_alias(openvpn['description'])
+ # IPv6 accept RA
+ o.set_ipv6_accept_ra(openvpn['ipv6_accept_ra'])
+ # IPv6 address autoconfiguration
+ o.set_ipv6_autoconf(openvpn['ipv6_autoconf'])
+ # IPv6 forwarding
+ o.set_ipv6_forwarding(openvpn['ipv6_forwarding'])
+ # IPv6 Duplicate Address Detection (DAD) tries
+ o.set_ipv6_dad_messages(openvpn['ipv6_dup_addr_detect'])
+
+ # IPv6 EUI-based addresses - only in TAP mode (TUN's have no MAC)
+ # If MAC has changed, old EUI64 addresses won't get deleted,
+ # but this isn't easy to solve, so leave them.
+ # This is even more difficult as openvpn uses a random MAC for the
+ # initial interface creation, unless set by 'lladdr'.
+ # NOTE: right now the interface is always deleted. For future
+ # compatibility when tap's are not deleted, leave the del_ in
+ if openvpn['mode'] == 'tap':
+ for addr in openvpn['ipv6_eui64_prefix_remove']:
+ o.del_ipv6_eui64_address(addr)
+ for addr in openvpn['ipv6_eui64_prefix']:
+ o.add_ipv6_eui64_address(addr)
+
+ # assign/remove VRF (ONLY when not a member of a bridge,
+ # otherwise 'nomaster' removes it from it)
+ if not openvpn['is_bridge_member']:
+ o.set_vrf(openvpn['vrf'])
# TAP interface needs to be brought up explicitly
if openvpn['type'] == 'tap':