Page MenuHomeVyOS Platform

OpenVPN client tap interfaces not coming up
Closed, ResolvedPublicBUG

Description

After configure OpenVPN and commit it, everything works ok. But after reboot, if I'll do

show interfaces o

I'v got:

Configuration path: interfaces [o] is not valid

But

sudo cat /config/config.boot

...
 openvpn vtun1 {
    description VPN
    device-type tap
    mode client
    openvpn-option "--script-security 2"
    persistent-tunnel
    protocol udp
    remote-host ip
    remote-port port
    tls {
        ca-cert-file /config/auth/ca.crt
        cert-file /config/auth/MSklad.crt
        key-file /config/auth/MSklad.key
        tls-version-min 1.0
    }
    use-lzo-compression
}
...

And

ifconfig:
vtun1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 10.255.95.7  netmask 255.255.0.0  broadcast 10.255.255.255
    inet6 fe80::849a:b7ff:fe5d:d8d9  prefixlen 64  scopeid 0x20<link>
    ether 86:9a:b7:5d:d8:d9  txqueuelen 100  (Ethernet)
    RX packets 10717  bytes 872467 (852.0 KiB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 11571  bytes 1679746 (1.6 MiB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

If I'll change anything in config and do commit&save, i'll loose openvpn.
In logs i found this:

[ interfaces openvpn vtun1 ]
Traceback (most recent call last):
  File "/usr/libexec/vyos/conf_mode/interfaces-openvpn.py", line 1028, in <module>
    apply(c)
  File "/usr/libexec/vyos/conf_mode/interfaces-openvpn.py", line 1018, in apply
    Interface(openvpn['intf']).set_state('up')
  File "/usr/lib/python3/dist-packages/vyos/ifconfig.py", line 110, in __init__
    raise Exception('interface "{}" not found'.format(self.config['ifname']))
Exception: interface "vtun1" not found

[[interfaces openvpn vtun1]] failed
Commit failed

What's wrong with that?

Details

Version
current
Is it a breaking change?
Unspecified (possibly destroys the router)
Issue type
Bug (incorrect behavior)

Event Timeline

vyos@MSklad# show interfaces openvpn 
+openvpn vtun1 {
+    description VPN
+    device-type tap
+    mode client
+    openvpn-option "--script-security 2"
+    persistent-tunnel
+    protocol udp
+    remote-host ip
+    remote-port port
+    tls {
+        ca-cert-file /config/auth/ca.crt
+        cert-file /config/auth/MSklad.crt
+        key-file /config/auth/MSklad.key
+        tls-version-min 1.0
+    }
+    use-lzo-compression
+}
[edit]
vyos@MSklad# commit
[ interfaces openvpn vtun1 ]
Traceback (most recent call last):
  File "/usr/libexec/vyos/conf_mode/interfaces-openvpn.py", line 1028, in <module>
    apply(c)
  File "/usr/libexec/vyos/conf_mode/interfaces-openvpn.py", line 1018, in apply
    Interface(openvpn['intf']).set_state('up')
  File "/usr/lib/python3/dist-packages/vyos/ifconfig.py", line 110, in __init__
    raise Exception('interface "{}" not found'.format(self.config['ifname']))
Exception: interface "vtun1" not found

[[interfaces openvpn vtun1]] failed
Commit failed
vyos@MSklad# save 
Warning: you have uncommitted changes that will not be saved.

Saving configuration to '/config/config.boot'...
Done
[edit]
vyos@MSklad# sudo cat /config/config.boot
interfaces {
    ethernet eth0 {
        address dhcp
        duplex auto
        hw-id c4:12:f5:33:f5:22
        smp-affinity auto
        speed auto
    }
    ethernet eth1 {
        address 192.168.0.50/24
        address 192.168.100.234/24
        duplex auto
        hw-id 00:27:0e:38:09:66
        smp-affinity auto
        speed auto
    }
    loopback lo {
    }
}
[edit]
vyos@MSklad# commit
[edit]
vyos@MSklad# show interfaces openvpn 
 openvpn vtun1 {
     description VPN
     device-type tap
     mode client
     openvpn-option "--script-security 2"
     persistent-tunnel
     protocol udp
     remote-host ip
     remote-port port
     tls {
         ca-cert-file /config/auth/ca.crt
         cert-file /config/auth/MSklad.crt
         key-file /config/auth/MSklad.key
         tls-version-min 1.0
     }
     use-lzo-compression
 }
[edit]
vyos@MSklad# save 
Saving configuration to '/config/config.boot'...
Done
[edit]
vyos@MSklad# sudo cat /config/config.boot
interfaces {
    ethernet eth0 {
        address dhcp
        duplex auto
        hw-id c4:12:f5:33:f5:22
        smp-affinity auto
        speed auto
    }
    ethernet eth1 {
        address 192.168.0.50/24
        address 192.168.100.234/24
        duplex auto
        hw-id 00:27:0e:38:09:66
        smp-affinity auto
        speed auto
    }
    loopback lo {
    }
    openvpn vtun1 {
        description VPN
        device-type tap
        mode client
        openvpn-option "--script-security 2"
        persistent-tunnel
        protocol udp
        remote-host ip
        remote-port port
        tls {
            ca-cert-file /config/auth/ca.crt
            cert-file /config/auth/MSklad.crt
            key-file /config/auth/MSklad.key
            tls-version-min 1.0
        }
        use-lzo-compression
    }
}

Unfortunately I receive a different error:

+openvpn vtun1 {
+    description "fooo bar"
+    device-type tap
+    mode client
+    openvpn-option "--script-security 2"
+    persistent-tunnel
+    protocol udp
+    remote-host 1.1.1.1
+    remote-port 4444
+    tls {
+        ca-cert-file /config/auth/CAcert_chain.pem
+        cert-file /config/auth/lnx04.pem
+        key-file /config/auth/lnx04.key
+        tls-version-min 1.0
+    }
+    use-lzo-compression
+}
Report Time:      2020-06-02 17:46:49
Image Version:    VyOS 1.3-rolling-202006011159
Release Train:    equuleus

Built by:         autobuild@vyos.net
Built on:         Mon 01 Jun 2020 11:59 UTC
Build UUID:       fddadd4c-3a4f-448d-8715-f713e1efc6eb
Build Commit ID:  0f7b9ac53414b6

Architecture:     x86_64
Boot via:         installed image
System type:      VMware guest

Hardware vendor:  VMware, Inc.
Hardware model:   VMware Virtual Platform
Hardware S/N:     VMware-42 3f 67 73 77 df c4 80-42 c9 42 af ff 15 de 0b
Hardware UUID:    73673f42-df77-80c4-42c9-42afff15de0b

Traceback (most recent call last):
  File "/usr/libexec/vyos/conf_mode/interfaces-openvpn.py", line 1112, in <module>
    apply(c)
  File "/usr/libexec/vyos/conf_mode/interfaces-openvpn.py", line 1102, in apply
    VTunIf(interface).set_admin_state('up')
  File "/usr/lib/python3/dist-packages/vyos/ifconfig/interface.py", line 221, in __init__
    self._create()
  File "/usr/lib/python3/dist-packages/vyos/ifconfig/interface.py", line 235, in _create
    self._cmd(cmd)
  File "/usr/lib/python3/dist-packages/vyos/ifconfig/control.py", line 48, in _cmd
    return cmd(command, self.debug)
  File "/usr/lib/python3/dist-packages/vyos/util.py", line 178, in cmd
    raise OSError(code, feedback)
FileNotFoundError: [Errno 2] failed to run command: ip link add dev vtun1 type vtun
returned:
exit code: 2

@hexes please provide exact version number "current" does not really help in this case as definately something else is going on with 1.3-rolling-202006011159

https://github.com/vyos/vyos-1x/pull/440

should help to go further in the testing, but it is still failing on set_state but I do not know why it should be done if the interface is managed by openvpn. The relevant code is:

# TAP interface needs to be brought up explicitly
if openvpn['type'] == 'tap':
    if not openvpn['disable']:
        VTunIf(interface).set_admin_state('up')

The error I get when testing this config is now:

noteworthy:
cmd 'ip link set dev vtun1 nomaster'
returned (out):
returned (err):

Cannot find device "vtun1"
cmd 'ip link set dev vtun1 up'
returned (out):

The noteworthy command about a previous command which failed (and that we ignored comes from the VRF setup)

# 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'])

Main reason would be I guess this error:

Jun  4 16:39:55 LR1 openvpn-vtun1[21166]: Could not determine IPv4/IPv6 protocol
Jun  4 16:39:55 LR1 openvpn-vtun1[21166]: SIGUSR1[soft,init_instance] received, process restarting

Looking at the above errors:

  File "/usr/libexec/vyos/conf_mode/interfaces-openvpn.py", line 1018, in apply
    Interface(openvpn['intf']).set_state('up')
  File "/usr/lib/python3/dist-packages/vyos/ifconfig.py", line 110, in __init__
    raise Exception('interface "{}" not found'.format(self.config['ifname']))
Exception: interface "vtun1" not found

The set_state was added in 2e6cd026 to fix T1975 and was changed in b36e6e6c but I think it's not correct. It seems like it should be moved into the 'try' block above it and changed to o.set_admin_state('up'). But that it fails seems to indicate that the interface doesn't exist, hence the above try block would also fail if the interface doesn't come up. In client mode, openvpn adds the interface only after the connection to the remote succeeds. Due to this, there is a wait loop above it that waits 50*250ms for the interface to come up. But if the tunnel doesn't connect during this initial configuration time, the subsequent interface config calls in the try block will also fail, and once the tunnel does come up (later) there is no mechanism to configure it, so it'll be left in the unconfigured state.

The best way to solve this IMO would be to use openvpn --mktun to first create a persistent tunnel interface, then start the daemon and configure the interface. I'm not sure we can set the persistent interface to up state when it's not yet connected. If not, we'd need to add a up script to the config that runs the VTunIf commands that are now in the try block (this would be better than manually setting it to up state while it's still disconnected anyway).

Some settings also seem to be applied in all cases, that aren't applicable in tun mode (set_ipv6_accept_ra, autoconf, forwarding, dad_messages) as openvpn manages addresses there (not sure but probably). The generated up script would need to be different in these cases: tun mode: just set_alias; tap: set everything, including addresses. Bridging in tap mode doesn't work right with the current code either, I think there's a task for that as well. When first generating the interface, it needs to add itself to the bridge like it was done for all other interfaces in T2241.

So to conclude, the tap part of the code was never right in the first place :)

Also regarding bridging: the current VTunIf says vtun is bridgeable. I doubt bridging a tun interface is wanted as that's a purely L3 tunnel. As the bridge member config syntax places the members under the bridge interface, the bridge interface determines if a interface is bridgeable by looking at its class definition. Thus to make openvpn in tun mode not bridgeable and tap mode bridgeable, those would need to be 2 different classes with different interface names ('vtun' and 'vtap'?). A hackish way is possible by making the bridge code check the openvpn config directly, but I highly dislike hackish solutions. Even T2241 was a 'hackish' solution that was necessary due to a previous bridge syntax migration without thinking about the consequences of it (moving the bridge member config under the bridge code makes syntactical sense, but it requires hackish workarounds like T2241 with the curernt way the config system operates)

jjakob renamed this task from OpenVPN loose config to OpenVPN client tap interfaces not coming up.Jun 5 2020, 1:28 PM
jjakob triaged this task as High priority.

I also don't think we can find out whether a interface is tun or tap from the up/down script (no parameter or environment variable seems to tell it this) so it'd be good if tun and tap had different names due to this too. It would require migrating the name of existing interfaces (from vtun to vtap if tunnel type is tap) under interfaces openvpn, interfaces bridge member, service router-advert, firewall, nat, possibly other places as well.

Another possibility would be to modify the VTunIf's bridgeable parameter when creating it. That wouldn't require a different name for tap and all the config migration that comes with it, but I don't know if it's possible.

Vtun interfaces are now created prior to starting OpenVPN to always ensure there is a kernel interface available

c-po claimed this task.
erkin set Issue type to Bug (incorrect behavior).Aug 30 2021, 5:49 AM
erkin removed a subscriber: Global Notifications.