diff --git a/actions/wireguard b/actions/wireguard index 9770b207a..61125d85d 100755 --- a/actions/wireguard +++ b/actions/wireguard @@ -25,6 +25,8 @@ import os import pathlib import subprocess +from plinth import network + PUBLIC_KEY_HELP = 'Public key for the client' SERVER_INTERFACE = 'wg0' @@ -193,23 +195,34 @@ def _find_next_interface(): return new_interface_name +def _get_connection_settings(name, interface, client_ip): + """Return settings for Network Manager connection.""" + return { + 'common': { + 'name': name, + 'type': 'wireguard', + 'interface': interface, + 'zone': 'internal', + }, + 'ipv4': { + 'method': 'manual', + 'address': client_ip, + 'netmask': '', + 'gateway': '', + 'dns': '', + 'second_dns': '', + }, + } + + def _create_connection(name, interface, client_ip): """Create a NetworkManager connection.""" - subprocess.run(['nmcli', 'con', 'add', - 'con-name', name, - 'ifname', interface, - 'type', 'wireguard'], check=True) + settings = _get_connection_settings(name, interface, client_ip) + network.add_connection(settings) subprocess.run(['nmcli', 'con', 'modify', name, 'connection.autoconnect', 'TRUE'], check=True) - subprocess.run(['nmcli', 'con', 'modify', name, - 'connection.zone', 'internal'], check=True) - - subprocess.run(['nmcli', 'con', 'modify', name, - 'ipv4.method', 'manual', - 'ipv4.addresses', client_ip + '/24'], check=True) - with PRIVATE_KEY_PATH.open() as private_key_file: private_key = private_key_file.read().strip() @@ -257,15 +270,23 @@ def subcommand_modify_server(arguments): args += ['endpoint', arguments.endpoint] subprocess.run(args, check=True) - subprocess.run(['nmcli', 'con', 'modify', - 'WireGuard-' + interface_to_modify, - 'ipv4.method', 'manual', - 'ipv4.addresses', arguments.client_ip + '/24'], - check=True) + connection = network.get_connection_by_interface_name( + interface_to_modify) + + settings = _get_connection_settings('WireGuard-' + interface_to_modify, + interface_to_modify, + arguments.client_ip) + + if connection: + network.edit_connection(connection, settings) + + else: + # XXX: raise error? + network.add_connection(settings) else: raise InterfaceNotFoundError( - 'Interface with peer %s not found' % arguments.publickey) + 'Interface with peer %s not found' % arguments.public_key) def subcommand_remove_server(arguments): @@ -280,9 +301,11 @@ def subcommand_remove_server(arguments): interface_to_remove = interface['interface_name'] if interface_to_remove: - subprocess.run( - ['nmcli', 'con', 'delete', 'WireGuard-' + interface_to_remove], - check=True) + connection = network.get_connection_by_interface_name( + interface_to_remove) + if connection: + network.delete_connection(connection.get_uuid()) + subprocess.run(['ip', 'link', 'delete', interface_to_remove], check=True) diff --git a/plinth/network.py b/plinth/network.py index 7943f4fcb..b77d3061e 100644 --- a/plinth/network.py +++ b/plinth/network.py @@ -289,6 +289,18 @@ def get_active_connection(connection_uuid): raise ConnectionNotFound(connection_uuid) +def get_connection_by_interface_name(interface_name): + """Return connection with matching interface. + + Return None if a connection with the interface is not found.""" + client = get_nm_client() + for connection in client.get_connections(): + if connection.get_interface_name() == interface_name: + return connection + + return None + + def get_device_by_interface_name(interface_name): """Return a device by interface name.""" return get_nm_client().get_device_by_iface(interface_name)