diff options
author | Christian Breunig <christian@breunig.cc> | 2023-03-21 21:00:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-21 21:00:20 +0100 |
commit | e98ad8cfdbc4bee608f668bf121085674971caf7 (patch) | |
tree | f6986df1e607d10d6691ea373bab4ba13ce638ad | |
parent | b3629cc33ba8eeefa34c5ec3420d0f293fbb0325 (diff) | |
parent | ecdc9b1f0bf47b762669d8600aaddc5cfa5ed206 (diff) | |
download | vyos-1x-e98ad8cfdbc4bee608f668bf121085674971caf7.tar.gz vyos-1x-e98ad8cfdbc4bee608f668bf121085674971caf7.zip |
Merge pull request #1894 from aapostoliuk/T5043-sagitta
ipsec: T5043: Rewritten and fixed 'reset vpn' commands
-rw-r--r-- | data/op-mode-standardized.json | 1 | ||||
-rw-r--r-- | op-mode-definitions/reset-vpn.xml.in | 120 | ||||
-rw-r--r-- | op-mode-definitions/vpn-ipsec.xml.in | 97 | ||||
-rwxr-xr-x | src/op_mode/ipsec.py | 81 | ||||
-rwxr-xr-x | src/op_mode/reset_vpn.py | 75 |
5 files changed, 230 insertions, 144 deletions
diff --git a/data/op-mode-standardized.json b/data/op-mode-standardized.json index 3b2599790..c7c67198e 100644 --- a/data/op-mode-standardized.json +++ b/data/op-mode-standardized.json @@ -17,6 +17,7 @@ "nhrp.py", "openconnect.py", "openvpn.py", +"reset_vpn.py", "route.py", "system.py", "ipsec.py", diff --git a/op-mode-definitions/reset-vpn.xml.in b/op-mode-definitions/reset-vpn.xml.in index 94ee1c7df..8de95d1cc 100644 --- a/op-mode-definitions/reset-vpn.xml.in +++ b/op-mode-definitions/reset-vpn.xml.in @@ -7,82 +7,78 @@ <help>Reset Virtual Private Network (VPN) information</help> </properties> <children> - <node name="remote-access"> + <node name="l2tp"> <properties> - <help>Reset remote access VPN connections</help> + <help>Reset L2TP server VPN sessions</help> </properties> <children> <node name="all"> <properties> - <help>Terminate all users current remote access VPN session(s)</help> + <help>Reset all L2TP server VPN sessions</help> </properties> - <children> - <node name="protocol"> - <properties> - <help>Terminate specified users current remote access VPN session(s) with specified protocol</help> - </properties> - <children> - <leafNode name="l2tp"> - <properties> - <help>Terminate all users 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 users 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> - <leafNode name="sstp"> - <properties> - <help>Terminate all users current remote access VPN session(s) with SSTP protocol</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="all_users" --protocol="sstp"</command> - </leafNode> - </children> - </node> - </children> - <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="all_users"</command> + <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py reset_conn --protocol="l2tp"</command> </node> <tagNode name="interface"> <properties> - <help>Terminate a remote access VPN interface</help> + <help>Reset specified interface on L2TP VPN server</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --interface="$5"</command> + <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py reset_conn --protocol="l2tp" --interface="$5"</command> </tagNode> <tagNode name="user"> <properties> - <help>Terminate specified users current remote access VPN session(s)</help> + <help>Reset specified user on L2TP VPN server</help> </properties> - <children> - <node name="protocol"> - <properties> - <help>Terminate specified users current remote access VPN session(s) with specified protocol</help> - </properties> - <children> - <leafNode name="l2tp"> - <properties> - <help>Terminate all users current remote access VPN session(s) with L2TP protocol</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="$5" --protocol="l2tp"</command> - </leafNode> - <leafNode name="pptp"> - <properties> - <help>Terminate all users current remote access VPN session(s) with PPTP protocol</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="$5" --protocol="pptp"</command> - </leafNode> - <leafNode name="sstp"> - <properties> - <help>Terminate all users current remote access VPN session(s) with SSTP protocol</help> - </properties> - <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="$5" --protocol="sstp"</command> - </leafNode> - </children> - </node> - </children> - <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py --username="$5"</command> + <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py reset_conn --protocol="l2tp" --username="$5"</command> + </tagNode> + </children> + </node> + <node name="pptp"> + <properties> + <help>Reset PPTP server VPN sessions</help> + </properties> + <children> + <node name="all"> + <properties> + <help>Reset all PPTP server VPN sessions</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py reset_conn --protocol="pptp"</command> + </node> + <tagNode name="interface"> + <properties> + <help>Reset specified interface on PPTP VPN server</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py reset_conn --protocol="pptp" --interface="$5"</command> + </tagNode> + <tagNode name="user"> + <properties> + <help>Reset specified user on PPTP VPN server</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py reset_conn --protocol="pptp" --username="$5"</command> + </tagNode> + </children> + </node> + <node name="sstp"> + <properties> + <help>Reset SSTP server VPN sessions</help> + </properties> + <children> + <node name="all"> + <properties> + <help>Reset all SSTP server VPN sessions</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py reset_conn --protocol="sstp"</command> + </node> + <tagNode name="interface"> + <properties> + <help>Reset specified interface on SSTP VPN server</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py reset_conn --protocol="sstp" --interface="$5"</command> + </tagNode> + <tagNode name="user"> + <properties> + <help>Reset specified user on SSTP VPN server</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/reset_vpn.py reset_conn --protocol="sstp" --username="$5"</command> </tagNode> </children> </node> diff --git a/op-mode-definitions/vpn-ipsec.xml.in b/op-mode-definitions/vpn-ipsec.xml.in index ee006a2d5..5baaec7ce 100644 --- a/op-mode-definitions/vpn-ipsec.xml.in +++ b/op-mode-definitions/vpn-ipsec.xml.in @@ -7,49 +7,88 @@ <help>Reset Virtual Private Network (VPN) information</help> </properties> <children> - <tagNode name="ipsec-peer"> + <node name="ipsec"> <properties> - <help>Reset all tunnels for given peer</help> - <completionHelp> - <path>vpn ipsec site-to-site peer</path> - </completionHelp> + <help>Reset IPSec VPN sessions</help> </properties> <children> - <tagNode name="tunnel"> + <tagNode name="profile"> <properties> - <help>Reset a specific tunnel for given peer</help> + <help>Reset all tunnels for given DMVPN profile</help> <completionHelp> - <path>vpn ipsec site-to-site peer ${COMP_WORDS[3]} tunnel</path> + <path>vpn ipsec profile</path> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_peer --peer="$4" --tunnel="$6"</command> + <children> + <tagNode name="tunnel"> + <properties> + <help>Reset a specific tunnel for given DMVPN profile</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/vpn_ipsec.py --action="reset-profile" --name="$6" --tunnel="$8"</command> + </tagNode> + </children> + <command>sudo ${vyos_op_scripts_dir}/vpn_ipsec.py --action="reset-profile" --name="$6" --tunnel="all"</command> </tagNode> - <node name="vti"> + <node name="remote-access"> <properties> - <help>Reset the VTI tunnel for given peer</help> + <help>Reset remote access IPSec VPN connections</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_peer --peer="$4" --tunnel="vti"</command> + <children> + <node name="all"> + <properties> + <help>Reset all users current remote access IPSec VPN sessions</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_ra</command> + </node> + <tagNode name="user"> + <properties> + <help>Reset specified user current remote access IPsec VPN session(s)</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_ra --user="$6"</command> + </tagNode> + </children> </node> - </children> - <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_peer --peer="$4"</command> - </tagNode> - <tagNode name="ipsec-profile"> - <properties> - <help>Reset all tunnels for given DMVPN profile</help> - <completionHelp> - <path>vpn ipsec profile</path> - </completionHelp> - </properties> - <children> - <tagNode name="tunnel"> + <node name="site-to-site"> <properties> - <help>Reset a specific tunnel for given DMVPN profile</help> + <help>Reset site-to-site IPSec VPN connections</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/vpn_ipsec.py --action="reset-profile" --name="$4" --tunnel="$6"</command> - </tagNode> + <children> + <node name="all"> + <properties> + <help>Reset all site-to-site IPSec VPN sessions</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_all_peers</command> + </node> + <tagNode name="peer"> + <properties> + <help>Reset all tunnels for given peer</help> + <completionHelp> + <path>vpn ipsec site-to-site peer</path> + </completionHelp> + </properties> + <children> + <tagNode name="tunnel"> + <properties> + <help>Reset a specific tunnel for given peer</help> + <completionHelp> + <path>vpn ipsec site-to-site peer ${COMP_WORDS[5]} tunnel</path> + </completionHelp> + </properties> + <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_peer --peer="$6" --tunnel="$8"</command> + </tagNode> + <node name="vti"> + <properties> + <help>Reset the VTI tunnel for given peer</help> + </properties> + <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_peer --peer="$6" --tunnel="vti"</command> + </node> + </children> + <command>sudo ${vyos_op_scripts_dir}/ipsec.py reset_peer --peer="$6"</command> + </tagNode> + </children> + </node> </children> - <command>sudo ${vyos_op_scripts_dir}/vpn_ipsec.py --action="reset-profile" --name="$4" --tunnel="all"</command> - </tagNode> + </node> </children> </node> </children> diff --git a/src/op_mode/ipsec.py b/src/op_mode/ipsec.py index 8e76f4cc0..6acde08ea 100755 --- a/src/op_mode/ipsec.py +++ b/src/op_mode/ipsec.py @@ -13,7 +13,6 @@ # # 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 re import sys import typing @@ -24,6 +23,7 @@ from tabulate import tabulate from vyos.util import convert_data from vyos.util import seconds_to_human +from vyos.configquery import ConfigTreeQuery import vyos.opmode import vyos.ipsec @@ -401,30 +401,91 @@ def _get_childsa_id_list(ike_sas: list) -> list: return list_childsa_id +def _get_all_sitetosite_peers_name_list() -> list: + """ + Return site-to-site peers configuration + :return: site-to-site peers configuration + :rtype: list + """ + conf: ConfigTreeQuery = ConfigTreeQuery() + config_path = ['vpn', 'ipsec', 'site-to-site', 'peer'] + peers_config = conf.get_config_dict(config_path, key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) + peers_list: list = [] + for name in peers_config: + peers_list.append(name) + return peers_list + + def reset_peer(peer: str, tunnel: typing.Optional[str] = None): # Convert tunnel to Strongwan format of CHILD_SA + tunnel_sw = None if tunnel: if tunnel.isnumeric(): - tunnel = f'{peer}-tunnel-{tunnel}' + tunnel_sw = f'{peer}-tunnel-{tunnel}' elif tunnel == 'vti': - tunnel = f'{peer}-vti' + tunnel_sw = f'{peer}-vti' try: - sa_list: list = vyos.ipsec.get_vici_sas_by_name(peer, tunnel) - + sa_list: list = vyos.ipsec.get_vici_sas_by_name(peer, tunnel_sw) if not sa_list: - raise vyos.opmode.IncorrectValue('Peer not found, aborting') + raise vyos.opmode.IncorrectValue( + f'Peer\'s {peer} SA(s) not found, aborting') if tunnel and sa_list: childsa_id_list: list = _get_childsa_id_list(sa_list) if not childsa_id_list: raise vyos.opmode.IncorrectValue( - 'Peer or tunnel(s) not found, aborting') - vyos.ipsec.terminate_vici_by_name(peer, tunnel) - print('Peer reset result: success') + f'Peer {peer} tunnel {tunnel} SA(s) not found, aborting') + vyos.ipsec.terminate_vici_by_name(peer, tunnel_sw) + print(f'Peer {peer} reset result: success') except (vyos.ipsec.ViciInitiateError) as err: raise vyos.opmode.UnconfiguredSubsystem(err) - except (vyos.ipsec.ViciInitiateError) as err: + except (vyos.ipsec.ViciCommandError) as err: raise vyos.opmode.IncorrectValue(err) +def reset_all_peers(): + sitetosite_list = _get_all_sitetosite_peers_name_list() + if sitetosite_list: + for peer_name in sitetosite_list: + try: + reset_peer(peer_name) + except (vyos.opmode.IncorrectValue) as err: + print(err) + print('Peers reset result: success') + else: + raise vyos.opmode.UnconfiguredSubsystem( + 'VPN IPSec site-to-site is not configured, aborting') + +def _get_ra_session_list_by_username(username: typing.Optional[str] = None): + """ + Return list of remote-access IKE_SAs uniqueids + :param username: + :type username: + :return: + :rtype: + """ + list_sa_id = [] + sa_list = vyos.ipsec.get_vici_sas() + for sa_val in sa_list: + for sa in sa_val.values(): + if 'remote-eap-id' in sa: + if username: + if username == sa['remote-eap-id'].decode(): + list_sa_id.append(sa['uniqueid'].decode()) + else: + list_sa_id.append(sa['uniqueid'].decode()) + return list_sa_id + + +def reset_ra(username: typing.Optional[str] = None): + #Reset remote-access ipsec sessions + if username: + list_sa_id = _get_ra_session_list_by_username(username) + else: + list_sa_id = _get_ra_session_list_by_username() + if list_sa_id: + vyos.ipsec.terminate_vici_ikeid_list(list_sa_id) + def show_sa(raw: bool): sa_data = _get_raw_data_sas() diff --git a/src/op_mode/reset_vpn.py b/src/op_mode/reset_vpn.py index 3a0ad941c..46195d6cd 100755 --- a/src/op_mode/reset_vpn.py +++ b/src/op_mode/reset_vpn.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (C) 2019 VyOS maintainers and contributors +# Copyright (C) 2022-2023 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 @@ -13,60 +13,49 @@ # # 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 sys -import argparse +import typing from vyos.util import run +import vyos.opmode + cmd_dict = { - 'cmd_base' : '/usr/bin/accel-cmd -p {} terminate {} {}', - 'vpn_types' : { - 'pptp' : 2003, - 'l2tp' : 2004, - 'sstp' : 2005 + 'cmd_base': '/usr/bin/accel-cmd -p {} terminate {} {}', + 'vpn_types': { + 'pptp': 2003, + 'l2tp': 2004, + 'sstp': 2005 } } -def terminate_sessions(username='', interface='', protocol=''): - # Reset vpn connections by username +def reset_conn(protocol: str, username: typing.Optional[str] = None, + interface: typing.Optional[str] = None): if protocol in cmd_dict['vpn_types']: - if username == "all_users": - run(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][protocol], 'all', '')) - else: - run(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][protocol], 'username', username)) - - # Reset vpn connections by ifname - elif interface: - for proto in cmd_dict['vpn_types']: - run(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][proto], 'if', interface)) - - elif username: - # Reset all vpn connections - if username == "all_users": - for proto in cmd_dict['vpn_types']: - run(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][proto], 'all', '')) + # Reset by Interface + if interface: + run(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][protocol], + 'if', interface)) + return + # Reset by username + if username: + run(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][protocol], + 'username', username)) + # Reset all else: - for proto in cmd_dict['vpn_types']: - run(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][proto], 'username', username)) - -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|sstp)', required=False) - args = parser.parse_args() - - if args.username or args.interface: - terminate_sessions(username=args.username, interface=args.interface, protocol=args.protocol) + run(cmd_dict['cmd_base'].format(cmd_dict['vpn_types'][protocol], + 'all', + '')) else: - print("Param --username or --interface required") - sys.exit(1) - - terminate_sessions() + vyos.opmode.IncorrectValue('Unknown VPN Protocol, aborting') if __name__ == '__main__': - main() + try: + res = vyos.opmode.run(sys.modules[__name__]) + if res: + print(res) + except (ValueError, vyos.opmode.Error) as e: + print(e) + sys.exit(1) |