summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2019-09-15 20:13:07 +0200
committerChristian Poessinger <christian@poessinger.com>2019-09-15 20:13:07 +0200
commitc4d0b9ed4736911d341efdebf34997e6cee8c5a8 (patch)
tree69a17499eb72a52b33cf5b92551316b879984694
parenta9a68a6f1086fd4c978deaf5ddace69c18443756 (diff)
parent6e169b011569bddd0c07d476528a3ecad56e6499 (diff)
downloadvyos-1x-c4d0b9ed4736911d341efdebf34997e6cee8c5a8.tar.gz
vyos-1x-c4d0b9ed4736911d341efdebf34997e6cee8c5a8.zip
Merge branch 'current' of github.com:vyos/vyos-1x into equuleus
* 'current' of github.com:vyos/vyos-1x: bonding: T1614: do not overwrite interface description with interface name [openvpn] T1661 Adding additional check for tls_dh if it not need for ovpn client [openvpn] T1662 Defined default remote port if it not set in cli [openvpn] T1661 Fixing returned value on check function bonding: T1614: use proper (previously missing) miimon property Python/ifconfig: T1557: bonding: add miimon property Python/ifconfig: T1557: bonding: fix class name in comments bonding: T1660: bugfix for triggered OS permission denied exception Revert "[bonding] T1660 Adding additional check. Some bonding mode don't support arp_interval" [bonding] T1660 Adding additional check. Some bonding mode don't support arp_interval [l2tp] T834 Implementation advanced ppp-options/lcp. openvpn: T1548: fix missing sys import [l2tp] T834 fix cli reset commands for l2tp and pptp. Adding l2tp%d tunnel naming.
-rw-r--r--Makefile1
-rw-r--r--interface-definitions/l2tp-server.xml24
-rw-r--r--op-mode-definitions/reset-vpn.xml84
-rw-r--r--python/vyos/ifconfig.py55
-rwxr-xr-xsrc/conf_mode/accel_l2tp.py22
-rwxr-xr-xsrc/conf_mode/interface-bonding.py10
-rwxr-xr-xsrc/conf_mode/interface-openvpn.py19
-rwxr-xr-xsrc/op_mode/reset_vpn.py85
-rwxr-xr-xsrc/op_mode/show_openvpn.py7
9 files changed, 284 insertions, 23 deletions
diff --git a/Makefile b/Makefile
index ad05acff5..61bc06c47 100644
--- a/Makefile
+++ b/Makefile
@@ -43,6 +43,7 @@ op_mode_definitions:
rm -f $(OP_TMPL_DIR)/show/vpn/node.def
rm -f $(OP_TMPL_DIR)/show/system/node.def
rm -f $(OP_TMPL_DIR)/delete/node.def
+ rm -f $(OP_TMPL_DIR)/reset/vpn/node.def
.PHONY: all
all: clean interface_definitions op_mode_definitions
diff --git a/interface-definitions/l2tp-server.xml b/interface-definitions/l2tp-server.xml
index 721913dfe..f795c96db 100644
--- a/interface-definitions/l2tp-server.xml
+++ b/interface-definitions/l2tp-server.xml
@@ -405,6 +405,7 @@
<leafNode name="disable">
<properties>
<help>Option to disable a L2TP Server user</help>
+ <valueless/>
</properties>
</leafNode>
<leafNode name="password">
@@ -553,6 +554,29 @@
</node>
</children>
</node>
+ <node name="ppp-options">
+ <properties>
+ <help>Advanced protocol options</help>
+ </properties>
+ <children>
+ <leafNode name="lcp-echo-interval">
+ <properties>
+ <help>LCP echo-requests/sec</help>
+ <constraint>
+ <validator name="numeric" argument="--positive"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="lcp-echo-failure">
+ <properties>
+ <help>Maximum number of Echo-Requests may be sent without valid reply</help>
+ <constraint>
+ <validator name="numeric" argument="--positive"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
</children>
</node>
</children>
diff --git a/op-mode-definitions/reset-vpn.xml b/op-mode-definitions/reset-vpn.xml
new file mode 100644
index 000000000..c0b0ddeb1
--- /dev/null
+++ b/op-mode-definitions/reset-vpn.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="reset">
+ <properties>
+ <help>Reset a service</help>
+ </properties>
+ <children>
+ <node name="vpn">
+ <properties>
+ <help>Reset Virtual Private Network (VPN) information</help>
+ </properties>
+ <children>
+ <node name="remote-access">
+ <properties>
+ <help>Reset remote access VPN connections</help>
+ </properties>
+ <children>
+ <node name="all">
+ <properties>
+ <help>Terminate all user's current remote access VPN session(s)</help>
+ </properties>
+ <children>
+ <node name="protocol">
+ <properties>
+ <help>Terminate specified user's current remote access VPN session(s) with specified protocol</help>
+ </properties>
+ <children>
+ <leafNode name="l2tp">
+ <properties>
+ <help>Terminate all user's current remote access VPN session(s) with L2TP protocol</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="all_users" --protocol="l2tp"</command>
+ </leafNode>
+ <leafNode name="pptp">
+ <properties>
+ <help>Terminate all user's current remote access VPN session(s) with PPTP protocol</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="all_users" --protocol="pptp"</command>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="all_users"</command>
+ </node>
+ <tagNode name="interface">
+ <properties>
+ <help>Terminate a remote access VPN interface</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --interface="$5"</command>
+ </tagNode>
+ <tagNode name="user">
+ <properties>
+ <help>Terminate specified user's current remote access VPN session(s)</help>
+ </properties>
+ <children>
+ <node name="protocol">
+ <properties>
+ <help>Terminate specified user's current remote access VPN session(s) with specified protocol</help>
+ </properties>
+ <children>
+ <leafNode name="l2tp">
+ <properties>
+ <help>Terminate all user's current remote access VPN session(s) with L2TP protocol</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="all_users" --protocol="l2tp"</command>
+ </leafNode>
+ <leafNode name="pptp">
+ <properties>
+ <help>Terminate all user's current remote access VPN session(s) with PPTP protocol</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="all_users" --protocol="pptp"</command>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="$5"</command>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/python/vyos/ifconfig.py b/python/vyos/ifconfig.py
index 62bf94d79..0793fad39 100644
--- a/python/vyos/ifconfig.py
+++ b/python/vyos/ifconfig.py
@@ -1086,7 +1086,7 @@ class BondIf(EthernetIf):
The default value is layer2
Example:
- >>> from vyos.ifconfig import Interface
+ >>> from vyos.ifconfig import BondIf
>>> BondIf('bond0').xmit_hash_policy = 'layer2+3'
>>> BondIf('bond0').proxy_arp
'1'
@@ -1130,7 +1130,7 @@ class BondIf(EthernetIf):
The default value is no IP addresses.
Example:
- >>> from vyos.ifconfig import Interface
+ >>> from vyos.ifconfig import BondIf
>>> BondIf('bond0').arp_interval = '100'
>>> BondIf('bond0').arp_interval
'100'
@@ -1171,7 +1171,7 @@ class BondIf(EthernetIf):
The default value is no IP addresses.
Example:
- >>> from vyos.ifconfig import Interface
+ >>> from vyos.ifconfig import BondIf
>>> BondIf('bond0').arp_ip_target = '192.0.2.1'
>>> BondIf('bond0').arp_ip_target
'192.0.2.1'
@@ -1179,12 +1179,51 @@ class BondIf(EthernetIf):
return self._write_sysfs('/sys/class/net/{}/bonding/arp_ip_target'
.format(self._ifname), target)
+ @property
+ def miimon(self):
+ """
+ Specifies the MII link monitoring frequency in milliseconds.
+ This determines how often the link state of each slave is
+ inspected for link failures. A value of zero disables MII
+ link monitoring. A value of 100 is a good starting point.
+
+ The default value is 0.
+
+ Example:
+ >>> from vyos.ifconfig import BondIf
+ >>> BondIf('bond0').miimon
+ '250'
+ """
+ return self._read_sysfs('/sys/class/net/{}/bonding/miimon'
+ .format(self._ifname))
+
+
+ @miimon.setter
+ def miimon(self, time):
+ """
+ Specifies the MII link monitoring frequency in milliseconds.
+ This determines how often the link state of each slave is
+ inspected for link failures. A value of zero disables MII
+ link monitoring. A value of 100 is a good starting point.
+
+ The default value is 0.
+
+ Example:
+ >>> from vyos.ifconfig import BondIf
+ >>> BondIf('bond0').miimon = 250
+ >>> BondIf('bond0').miimon
+ '250'
+ """
+ return self._write_sysfs('/sys/class/net/{}/bonding/miimon'
+ .format(self._ifname), time)
+
+
def add_port(self, interface):
"""
Enslave physical interface to bond.
Example:
- >>> from vyos.ifconfig import Interface
+ >>> from vyos.ifconfig import BondIf
>>> BondIf('bond0').add_port('eth0')
>>> BondIf('bond0').add_port('eth1')
"""
@@ -1201,7 +1240,7 @@ class BondIf(EthernetIf):
Remove physical port from bond
Example:
- >>> from vyos.ifconfig import Interface
+ >>> from vyos.ifconfig import BondIf
>>> BondIf('bond0').del_port('eth1')
"""
return self._write_sysfs('/sys/class/net/{}/bonding/slaves'
@@ -1212,7 +1251,7 @@ class BondIf(EthernetIf):
Return a list with all configured slave interfaces on this bond.
Example:
- >>> from vyos.ifconfig import Interface
+ >>> from vyos.ifconfig import BondIf
>>> BondIf('bond0').get_slaves()
['eth1', 'eth2']
"""
@@ -1253,7 +1292,7 @@ class BondIf(EthernetIf):
balance-alb mode.
Example:
- >>> from vyos.ifconfig import Interface
+ >>> from vyos.ifconfig import BondIf
>>> BondIf('bond0').primary = 'eth2'
>>> BondIf('bond0').primary
'eth2'
@@ -1295,7 +1334,7 @@ class BondIf(EthernetIf):
slaves
Example:
- >>> from vyos.ifconfig import Interface
+ >>> from vyos.ifconfig import BondIf
>>> BondIf('bond0').mode = '802.3ad'
>>> BondIf('bond0').mode
'802.3ad'
diff --git a/src/conf_mode/accel_l2tp.py b/src/conf_mode/accel_l2tp.py
index 3af8b7958..244a720db 100755
--- a/src/conf_mode/accel_l2tp.py
+++ b/src/conf_mode/accel_l2tp.py
@@ -94,6 +94,7 @@ wins2={{wins[1]}}
[l2tp]
verbose=1
+ifname=l2tp%d
ppp-max-mtu={{mtu}}
mppe={{authentication['mppe']}}
{% if outside_addr %}
@@ -133,7 +134,16 @@ single-session=replace
{% if idle_timeout %}
lcp-echo-timeout={{idle_timeout}}
{% endif %}
+{% if ppp_options['lcp-echo-interval'] %}
+lcp-echo-interval={{ppp_options['lcp-echo-interval']}}
+{% else %}
lcp-echo-interval=30
+{% endif %}
+{% if ppp_options['lcp-echo-failure'] %}
+lcp-echo-failure={{ppp_options['lcp-echo-failure']}}
+{% else %}
+lcp-echo-failure=3
+{% endif %}
{% if ccp_disable %}
ccp=0
{% endif %}
@@ -287,6 +297,7 @@ def get_config():
'mtu' : '1436',
'ip6_column' : '',
'ip6_dp_column' : '',
+ 'ppp_options' : {},
}
### general options ###
@@ -439,6 +450,17 @@ def get_config():
if c.exists('ccp-disable'):
config_data['ccp_disable'] = True
+ ### ppp_options
+ ppp_options = {}
+ if c.exists('ppp-options'):
+ if c.exists('ppp-options lcp-echo-failure'):
+ ppp_options['lcp-echo-failure'] = c.return_value('ppp-options lcp-echo-failure')
+ if c.exists('ppp-options lcp-echo-interval'):
+ ppp_options['lcp-echo-interval'] = c.return_value('ppp-options lcp-echo-interval')
+
+ if len(ppp_options) !=0:
+ config_data['ppp_options'] = ppp_options
+
return config_data
def verify(c):
diff --git a/src/conf_mode/interface-bonding.py b/src/conf_mode/interface-bonding.py
index dc0363fb7..f0a33beff 100755
--- a/src/conf_mode/interface-bonding.py
+++ b/src/conf_mode/interface-bonding.py
@@ -157,8 +157,6 @@ def get_config():
# retrieve interface description
if conf.exists('description'):
bond['description'] = conf.return_value('description')
- else:
- bond['description'] = bond['intf']
# get DHCP client identifier
if conf.exists('dhcp-options client-id'):
@@ -354,12 +352,12 @@ def apply(bond):
for intf in b.get_slaves():
b.del_port(intf)
- # ARP link monitoring frequency
- b.arp_interval = bond['arp_mon_intvl']
- # reset miimon on arp-montior deletion
+ # ARP link monitoring frequency, reset miimon when arp-montior is inactive
if bond['arp_mon_intvl'] == 0:
# reset miimon to default
- b.bond_miimon = 250
+ b.miimon = 250
+ else:
+ b.arp_interval = bond['arp_mon_intvl']
# ARP monitor targets need to be synchronized between sysfs and CLI.
# Unfortunately an address can't be send twice to sysfs as this will
diff --git a/src/conf_mode/interface-openvpn.py b/src/conf_mode/interface-openvpn.py
index 548c78535..34c094862 100755
--- a/src/conf_mode/interface-openvpn.py
+++ b/src/conf_mode/interface-openvpn.py
@@ -326,14 +326,14 @@ def checkCertHeader(header, filename):
Returns True on success or on file not found to not trigger the exceptions
"""
if not os.path.isfile(filename):
- return True
+ return False
with open(filename, 'r') as f:
for line in f:
if re.match(header, line):
return True
- return False
+ return True
def get_config():
openvpn = deepcopy(default_config_data)
@@ -696,8 +696,9 @@ def verify(openvpn):
#
# TLS/encryption
#
- if not checkCertHeader('-----BEGIN OpenVPN Static key V1-----', openvpn['shared_secret_file']):
- raise ConfigError('Specified shared-secret-key-file "{}" is not valid'.format(openvpn['shared_secret_file']))
+ if openvpn['shared_secret_file']:
+ if not checkCertHeader('-----BEGIN OpenVPN Static key V1-----', openvpn['shared_secret_file']):
+ raise ConfigError('Specified shared-secret-key-file "{}" is not valid'.format(openvpn['shared_secret_file']))
if openvpn['tls']:
if not openvpn['tls_ca_cert']:
@@ -719,11 +720,13 @@ def verify(openvpn):
if not checkCertHeader('-----BEGIN (?:RSA )?PRIVATE KEY-----', openvpn['tls_key']):
raise ConfigError('Specified key-file "{}" is not valid'.format(openvpn['tls_key']))
- if not checkCertHeader('-----BEGIN X509 CRL-----', openvpn['tls_crl']):
- raise ConfigError('Specified crl-file "{} not valid'.format(openvpn['tls_crl']))
+ if openvpn['tls_crl']:
+ if not checkCertHeader('-----BEGIN X509 CRL-----', openvpn['tls_crl']):
+ raise ConfigError('Specified crl-file "{} not valid'.format(openvpn['tls_crl']))
- if not checkCertHeader('-----BEGIN DH PARAMETERS-----', openvpn['tls_dh']):
- raise ConfigError('Specified dh-file "{}" is not valid'.format(openvpn['tls_dh']))
+ if openvpn['tls_dh']:
+ if not checkCertHeader('-----BEGIN DH PARAMETERS-----', openvpn['tls_dh']):
+ raise ConfigError('Specified dh-file "{}" is not valid'.format(openvpn['tls_dh']))
if openvpn['tls_role']:
if openvpn['mode'] in ['client', 'server']:
diff --git a/src/op_mode/reset_vpn.py b/src/op_mode/reset_vpn.py
new file mode 100755
index 000000000..52677b58d
--- /dev/null
+++ b/src/op_mode/reset_vpn.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2019 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
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# import os
+import sys
+import subprocess
+import argparse
+#import re
+
+pptp_cmd = ["/usr/bin/accel-cmd", "-p 2003"]
+l2tp_cmd = ["/usr/bin/accel-cmd", "-p 2004"]
+
+def terminate_sessions(username='', interface='', protocol=''):
+ if username:
+ if username == "all_users":
+ if protocol == "pptp":
+ pptp_cmd.append("terminate all")
+ subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ return
+ elif protocol == "l2tp":
+ l2tp_cmd.append("terminate all")
+ subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ return
+ else:
+ pptp_cmd.append("terminate all")
+ subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ l2tp_cmd.append("terminate all")
+ subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ return
+
+ if protocol == "pptp":
+ pptp_cmd.append("terminate username {0}".format(username))
+ subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ return
+ elif protocol == "l2tp":
+ l2tp_cmd.append("terminate username {0}".format(username))
+ subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ return
+ else:
+ pptp_cmd.append("terminate username {0}".format(username))
+ subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ l2tp_cmd.append("terminate username {0}".format(username))
+ subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ return
+
+ # rewrite `terminate by interface` if pptp will have pptp%d interface naming
+ if interface:
+ pptp_cmd.append("terminate if {0}".format(interface))
+ subprocess.call(pptp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ l2tp_cmd.append("terminate if {0}".format(interface))
+ subprocess.call(l2tp_cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+
+def main():
+ #parese args
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--username', help='Terminate by username (all_users used for disconnect all users)', required=False)
+ parser.add_argument('--interface', help='Terminate by interface', required=False)
+ parser.add_argument('--protocol', help='Set protocol (pptp|l2tp)', required=False)
+ args = parser.parse_args()
+
+ if args.username or args.interface:
+ terminate_sessions(username=args.username, interface=args.interface, protocol=args.protocol)
+ else:
+ print("Param --username or --interface required")
+ sys.exit(1)
+
+ terminate_sessions()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/op_mode/show_openvpn.py b/src/op_mode/show_openvpn.py
index 23a8156ec..577ed7eb7 100755
--- a/src/op_mode/show_openvpn.py
+++ b/src/op_mode/show_openvpn.py
@@ -18,6 +18,7 @@
import jinja2
import argparse
+from sys import exit
from vyos.config import Config
outp_tmpl = """
@@ -136,7 +137,7 @@ if __name__ == '__main__':
config = Config()
if len(config.list_effective_nodes('interfaces openvpn')) == 0:
print("No OpenVPN interfaces configured")
- sys.exit(0)
+ exit(0)
# search all OpenVPN interfaces and add those with a matching mode to our
# interfaces list
@@ -161,6 +162,10 @@ if __name__ == '__main__':
remote_host = config.return_effective_values('interfaces openvpn {} remote-host'.format(intf))
remote_port = config.return_effective_value('interfaces openvpn {} remote-port'.format(intf))
+
+ if not remote_port:
+ remote_port = '1194'
+
if len(remote_host) >= 1:
client['remote'] = str(remote_host[0]) + ':' + remote_port