diff --git a/actions/wireguard b/actions/wireguard index 3856f795e..3558bb79f 100755 --- a/actions/wireguard +++ b/actions/wireguard @@ -21,99 +21,23 @@ Configuration helper for WireGuard. import argparse import json -import os -import pathlib import subprocess -PUBLIC_KEY_HELP = 'Public key for the client' - SERVER_INTERFACE = 'wg0' -KEY_FOLDER = pathlib.Path('/var/lib/freedombox/wireguard') -PRIVATE_KEY_PATH = KEY_FOLDER / 'privatekey' -PUBLIC_KEY_PATH = KEY_FOLDER / 'publickey' - - -class InterfaceNotFoundError(Exception): - """Exception raised when no matching interface is found.""" - def parse_arguments(): """Return parsed command line arguments as dictionary.""" parser = argparse.ArgumentParser() subparsers = parser.add_subparsers(dest='subcommand', help='Sub command') - subparsers.add_parser('setup', help='Setup WireGuard') subparsers.add_parser('get-info', help='Get info for each configured interface') - add_client = subparsers.add_parser('add-client', help='Add a client') - add_client.add_argument('publickey', help=PUBLIC_KEY_HELP) - - remove_client = subparsers.add_parser('remove-client', - help='Remove a client') - remove_client.add_argument('publickey', help=PUBLIC_KEY_HELP) - - modify_server = subparsers.add_parser('modify-server', - help='Modify a server') - modify_server.add_argument('--endpoint', required=True, - help='Server endpoint') - modify_server.add_argument('--client-ip', required=True, - help='Client IP address provided by server') - modify_server.add_argument('--public-key', required=True, - help='Public key of the server') - modify_server.add_argument('--pre-shared-key', help='Pre-shared key') - modify_server.add_argument( - '--all-outgoing', action='store_true', - help='Use this connection to send all outgoing traffic') - - remove_server = subparsers.add_parser('remove-server', - help='Remove a server') - remove_server.add_argument('publickey', help=PUBLIC_KEY_HELP) - subparsers.required = True return parser.parse_args() -def _generate_key_pair(): - """Generate private/public key pair.""" - private_key = subprocess.check_output(['wg', 'genkey']) - public_key = subprocess.check_output(['wg', 'pubkey'], input=private_key) - KEY_FOLDER.mkdir(parents=True, exist_ok=True) - with PUBLIC_KEY_PATH.open(mode='wb') as public_key_file: - public_key_file.write(public_key) - - old_umask = os.umask(0o077) - try: - with PRIVATE_KEY_PATH.open(mode='wb') as private_key_file: - private_key_file.write(private_key) - - finally: - os.umask(old_umask) - - -def subcommand_setup(_): - """Setup WireGuard.""" - # Create interface. - try: - subprocess.run(['ip', 'link', 'show', SERVER_INTERFACE], - stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, - check=True) - except subprocess.CalledProcessError: - subprocess.run([ - 'ip', 'link', 'add', 'dev', SERVER_INTERFACE, 'type', 'wireguard' - ], check=True) - - if not (PUBLIC_KEY_PATH.exists() and PRIVATE_KEY_PATH.exists()): - _generate_key_pair() - - # Configure interface. - subprocess.run([ - 'wg', 'set', SERVER_INTERFACE, 'listen-port', '51820', 'private-key', - str(PRIVATE_KEY_PATH) - ], check=True) - - def _get_info(): """Return info for each configured interface.""" output = subprocess.check_output(['wg', 'show', 'all', @@ -125,14 +49,16 @@ def _get_info(): continue fields = line.split() + fields = [field if field != '(none)' else None for field in fields] interface_name = fields[0] if interface_name in interfaces: + latest_handshake = int(fields[5]) if int(fields[5]) else None peer = { 'public_key': fields[1], 'preshared_key': fields[2], 'endpoint': fields[3], 'allowed_ips': fields[4], - 'latest_handshake': fields[5], + 'latest_handshake': latest_handshake, 'transfer_rx': fields[6], 'transfer_tx': fields[7], 'persistent_keepalive': fields[8], @@ -157,20 +83,6 @@ def subcommand_get_info(_): print(json.dumps(_get_info())) -def subcommand_add_client(arguments): - """Add a client.""" - subprocess.run( - ['wg', 'set', SERVER_INTERFACE, 'peer', arguments.publickey], - check=True) - - -def subcommand_remove_client(arguments): - """Remove a client.""" - subprocess.run( - ['wg', 'set', SERVER_INTERFACE, 'peer', arguments.publickey, 'remove'], - check=True) - - def main(): """Parse arguments and perform all duties.""" arguments = parse_arguments() diff --git a/plinth/modules/wireguard/__init__.py b/plinth/modules/wireguard/__init__.py index 7cdb630e0..26d4bb552 100644 --- a/plinth/modules/wireguard/__init__.py +++ b/plinth/modules/wireguard/__init__.py @@ -18,13 +18,9 @@ FreedomBox app for wireguard. """ -import datetime -import json - from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from plinth import actions from plinth import app as app_module from plinth import cfg, frontpage, menu from plinth.modules.firewall.components import Firewall @@ -102,98 +98,4 @@ def init(): def setup(helper, old_version=None): """Install and configure the module.""" helper.install(managed_packages) - helper.call('post', actions.superuser_run, 'wireguard', ['setup']) helper.call('post', app.enable) - - -def get_public_key(): - """Return this box's public key.""" - public_key_path = '/var/lib/freedombox/wireguard/publickey' - try: - with open(public_key_path) as public_key_file: - public_key = public_key_file.read().strip() - - except FileNotFoundError: - public_key = None - - return public_key - - -def get_nm_info(): - """Get information from network manager.""" - client = nm.Client.new(None) - - connections = {} - for connection in client.get_connections(): - if connection.get_connection_type() != 'wireguard': - continue - - settings = connection.get_setting_by_name('wireguard') - secrets = connection.get_secrets('wireguard') - connection.update_secrets('wireguard', secrets) - - info = {} - info['interface'] = connection.get_interface_name() - info['private_key'] = settings.get_private_key() - info['listen_port'] = settings.get_listen_port() - info['fwmark'] = settings.get_fwmark() - info['mtu'] = settings.get_mtu() - info['default_route'] = settings.get_ip4_auto_default_route() - info['peers'] = [] - for peer_index in range(settings.get_peers_len()): - peer = settings.get_peer(peer_index) - peer_info = { - 'endpoint': peer.get_endpoint(), - 'public_key': peer.get_public_key(), - 'preshared_key': peer.get_preshared_key(), - 'persistent_keepalive': peer.get_persistent_keepalive(), - 'allowed_ips': [] - } - for index in range(peer.get_allowed_ips_len()): - allowed_ip = peer.get_allowed_ip(index, None) - peer_info['allowed_ips'].append(allowed_ip) - - info['peers'].append(peer_info) - - settings_ipv4 = connection.get_setting_ip4_config() - if settings_ipv4 and settings_ipv4.get_num_addresses(): - info['ip_address'] = settings_ipv4.get_address(0).get_address() - - connections[info['interface']] = info - - return connections - - -def get_info(): - """Return server and clients info.""" - output = actions.superuser_run('wireguard', ['get-info']) - status = json.loads(output) - - nm_info = get_nm_info() - - my_server_info = status.pop(SERVER_INTERFACE, {}) - my_client_servers = {} - - for interface, info in nm_info.items(): - my_client_servers[interface] = info - - if interface not in status: - continue - - for info_peer in info['peers']: - for status_peer in status[interface]['peers']: - if info_peer['public_key'] == status_peer['public_key']: - info_peer['status'] = status_peer - status_peer['latest_handshake'] = \ - datetime.datetime.fromtimestamp( - int(status_peer['latest_handshake'])) - - return { - 'my_server': { - 'public_key': my_server_info.get('public_key'), - 'clients': my_server_info.get('peers'), - }, - 'my_client': { - 'servers': my_client_servers, - }, - } diff --git a/plinth/modules/wireguard/forms.py b/plinth/modules/wireguard/forms.py index 9dc7ef977..3f03abb42 100644 --- a/plinth/modules/wireguard/forms.py +++ b/plinth/modules/wireguard/forms.py @@ -64,7 +64,7 @@ class AddServerForm(forms.Form): settings = { 'common': { 'type': 'wireguard', - 'zone': 'internal', + 'zone': 'external', }, 'ipv4': { 'method': 'manual', diff --git a/plinth/modules/wireguard/templates/wireguard.html b/plinth/modules/wireguard/templates/wireguard.html index 753836e44..8a85d2030 100644 --- a/plinth/modules/wireguard/templates/wireguard.html +++ b/plinth/modules/wireguard/templates/wireguard.html @@ -30,18 +30,22 @@ id="server-peers-list">
+ {% blocktrans %} + Public key for this {{ box_name }}: + {% endblocktrans %} +
{{ server.public_key }}
+
+
@@ -72,15 +83,19 @@
- {% blocktrans %} - Public key for this {{ box_name }}: - {% endblocktrans %} - -
{{ public_key }}
-
-
{{ block.super }}
{% endblock %}
diff --git a/plinth/modules/wireguard/templates/wireguard_show_client.html b/plinth/modules/wireguard/templates/wireguard_show_client.html
index 416a87c6c..51fc9edd7 100644
--- a/plinth/modules/wireguard/templates/wireguard_show_client.html
+++ b/plinth/modules/wireguard/templates/wireguard_show_client.html
@@ -22,23 +22,58 @@
{% block content %}
- | {% trans "Client public key:" %} | +{{ client.public_key }} | +
|---|---|
| {% trans "IP address to use:" %} | +{{ client.allowed_ips|join:", " }} | +
| {% trans "Pre-shared key:" %} | +{{ client.preshared_key }} | +
| {% trans "Server endpoints:" %} | +
+ {% for endpoint in endpoints %}
+ {{ endpoint }}
+ {% endfor %}
+ |
+
| {% trans "Server's public key:" %} | +{{ server.public_key }} | +
{% trans "IP address to use:" %}
-{% trans "Server endpoints:" %}
-{% trans "Server's public key:" %} {{ my_server.public_key }}
-{% trans "Pre-shared key:" %}
- -{% trans "Client Public Key:" %} {{ client.public_key }}
-{% trans "Data transmitted:" %} {{ client.transfer_tx|filesizeformat }}
-{% trans "Data received:" %} {{ client.transfer_rx|filesizeformat }}
-{% trans "Latest handshake:" %} {{ client.latest_handshake }}
+| {% trans "Data transmitted:" %} | +{{ client.status.transfer_tx|filesizeformat }} | +
|---|---|
| {% trans "Data received:" %} | +{{ client.status.transfer_rx|filesizeformat }} | +
| {% trans "Latest handshake:" %} | +{{ client.status.latest_handshake|default:'' }} | +
+
{% trans "Edit Client" %}
-
-
- {% trans "Endpoint:" %}
- {{ server.peers.0.endpoint }}
-
-
- {% trans "Public Key:" %}
- {{ server.peers.0.public_key }}
-
-
- {% trans "Pre-shared key:" %}
- {{ server.peers.0.preshared_key }}
-
-
- {% trans "Data transmitted:" %}
- {{ server.peers.0.status.transfer_tx|filesizeformat }}
-
-
- {% trans "Data received:" %}
- {{ server.peers.0.status.transfer_rx|filesizeformat }}
-
-
+ {% for peer in server.peers.values %}
+ {% if forloop.first %}
+ {% trans "Latest handshake:" %}
- {{ server.peers.0.status.latest_handshake }}
-
+
+ {% trans "Endpoint:" %}
+ {{ peer.endpoint }}
+
+
+ {% trans "Public Key:" %}
+ {{ peer.public_key }}
+
+
+ {% trans "Pre-shared key:" %}
+ {{ peer.preshared_key }}
+
+
+ {% trans "Data transmitted:" %}
+ {{ peer.status.transfer_tx|filesizeformat }}
+
+
+ {% trans "Data received:" %}
+ {{ peer.status.transfer_rx|filesizeformat }}
+
+
+ {% endif %}
+ {% endfor %}
diff --git a/plinth/modules/wireguard/utils.py b/plinth/modules/wireguard/utils.py
index d41ba042e..86c404001 100644
--- a/plinth/modules/wireguard/utils.py
+++ b/plinth/modules/wireguard/utils.py
@@ -18,9 +18,100 @@
Utilities for managing WireGuard.
"""
+import datetime
+import json
import subprocess
+import time
-from plinth import network
+from plinth import actions, network
+from plinth.utils import import_from_gi
+
+nm = import_from_gi('NM', '1.0')
+
+IP_TEMPLATE = '10.84.0.{}'
+WIREGUARD_SETTING = nm.SETTING_WIREGUARD_SETTING_NAME
+
+
+def get_nm_info():
+ """Get information from network manager."""
+ client = network.get_nm_client()
+
+ connections = {}
+ for connection in client.get_connections():
+ if connection.get_connection_type() != WIREGUARD_SETTING:
+ continue
+
+ settings = connection.get_setting_by_name(WIREGUARD_SETTING)
+ secrets = connection.get_secrets(WIREGUARD_SETTING)
+ connection.update_secrets(WIREGUARD_SETTING, secrets)
+
+ info = {}
+ info['interface'] = connection.get_interface_name()
+ info['private_key'] = settings.get_private_key()
+ info['public_key'] = None
+ info['listen_port'] = settings.get_listen_port()
+ info['fwmark'] = settings.get_fwmark()
+ info['mtu'] = settings.get_mtu()
+ info['default_route'] = settings.get_ip4_auto_default_route()
+ info['peers'] = {}
+ for peer_index in range(settings.get_peers_len()):
+ peer = settings.get_peer(peer_index)
+ peer_info = {
+ 'endpoint': peer.get_endpoint(),
+ 'public_key': peer.get_public_key(),
+ 'preshared_key': peer.get_preshared_key(),
+ 'persistent_keepalive': peer.get_persistent_keepalive(),
+ 'allowed_ips': []
+ }
+ for index in range(peer.get_allowed_ips_len()):
+ allowed_ip = peer.get_allowed_ip(index, None)
+ peer_info['allowed_ips'].append(allowed_ip)
+
+ info['peers'][peer_info['public_key']] = peer_info
+
+ settings_ipv4 = connection.get_setting_ip4_config()
+ if settings_ipv4 and settings_ipv4.get_num_addresses():
+ info['ip_address'] = settings_ipv4.get_address(0).get_address()
+
+ connections[info['interface']] = info
+
+ return connections
+
+
+def get_info():
+ """Return server and clients info."""
+ output = actions.superuser_run('wireguard', ['get-info'])
+ status = json.loads(output)
+
+ nm_info = get_nm_info()
+
+ my_server_info = None
+ my_client_servers = {}
+ for interface, info in nm_info.items():
+ if interface == 'wg0':
+ my_server_info = info
+ else:
+ my_client_servers[interface] = info
+
+ if interface not in status:
+ continue
+
+ info['public_key'] = status[interface]['public_key']
+ for status_peer in status[interface]['peers']:
+ if status_peer['latest_handshake']:
+ status_peer['latest_handshake'] = \
+ datetime.datetime.fromtimestamp(
+ status_peer['latest_handshake'])
+ public_key = status_peer['public_key']
+ info_peer = info['peers'].setdefault(public_key, {})
+ info_peer['status'] = status_peer
+
+ return {
+ 'my_server': my_server_info,
+ 'my_client': {
+ 'servers': my_client_servers,
+ },
+ }
def find_next_interface():
@@ -38,8 +129,106 @@ def find_next_interface():
def add_server(settings):
- """Add a server."""
+ """Add information for connecting to a server."""
interface_name = find_next_interface()
- settings['common']['name'] = 'WireGuard-' + interface_name
+ settings['common']['name'] = 'WireGuard-Client-' + interface_name
settings['common']['interface'] = interface_name
network.add_connection(settings)
+
+
+def setup_server():
+ """Setup a server connection that clients can connect to."""
+ process = subprocess.run(['wg', 'genkey'], check=True, capture_output=True)
+ private_key = process.stdout.decode().strip()
+ settings = {
+ 'common': {
+ 'name': 'WireGuard-Server-wg0',
+ 'type': WIREGUARD_SETTING,
+ 'zone': 'internal',
+ 'interface': 'wg0'
+ },
+ 'ipv4': {
+ 'method': 'manual',
+ 'address': IP_TEMPLATE.format(1),
+ 'netmask': '255.255.255.0',
+ 'gateway': '',
+ 'dns': '',
+ 'second_dns': '',
+ },
+ 'wireguard': {
+ 'private_key': private_key,
+ 'listen_port': 51820,
+ }
+ }
+ network.add_connection(settings)
+
+
+def _get_next_available_ip_address(settings):
+ """Get the next available IP address to allocate to a client."""
+ allocated_ips = set()
+ for peer_index in range(settings.get_peers_len()):
+ peer = settings.get_peer(peer_index)
+ for ip_index in range(peer.get_allowed_ips_len()):
+ allowed_ip = peer.get_allowed_ip(ip_index)
+ # We assume these are simple IP addresses but they can be subnets.
+ allocated_ips.add(allowed_ip)
+
+ for index in range(2, 254):
+ ip_address = IP_TEMPLATE.format(index)
+ if ip_address not in allocated_ips:
+ return ip_address
+
+ raise IndexError('Reached client limit')
+
+
+def _server_connection():
+ """Return a server connection. Create one if necessary."""
+ connection = network.get_connection_by_interface_name('wg0')
+ if not connection:
+ setup_server()
+
+ for _ in range(10):
+ # XXX: Improve this waiting by doing a synchronous D-Bus operation to
+ # add network manager connection instead.
+ time.sleep(1)
+ connection = network.get_connection_by_interface_name('wg0')
+ if connection:
+ break
+
+ if not connection:
+ raise RuntimeError('Unable to create a server connection.')
+
+ # Retrieve secrets so that when the connection is changed, secrets are
+ # preserved properly.
+ secrets = connection.get_secrets(WIREGUARD_SETTING)
+ connection.update_secrets(WIREGUARD_SETTING, secrets)
+
+ return connection
+
+
+def add_client(public_key):
+ """Add a permission for a client to connect our server."""
+ connection = _server_connection()
+ settings = connection.get_setting_by_name(WIREGUARD_SETTING)
+ peer, _ = settings.get_peer_by_public_key(public_key)
+ if peer:
+ raise ValueError('Peer with public key already exists')
+
+ peer = nm.WireGuardPeer.new()
+ peer.set_public_key(public_key, False)
+ peer.set_persistent_keepalive(25) # To keep NAT 'connections' alive
+ peer.append_allowed_ip(_get_next_available_ip_address(settings), False)
+ settings.append_peer(peer)
+ connection.commit_changes(True)
+
+
+def remove_client(public_key):
+ """Remove permission for a client to connect our server."""
+ connection = _server_connection()
+ settings = connection.get_setting_by_name(WIREGUARD_SETTING)
+ peer, peer_index = settings.get_peer_by_public_key(public_key)
+ if not peer:
+ raise KeyError('Client not found')
+
+ settings.remove_peer(peer_index)
+ connection.commit_changes(True)
diff --git a/plinth/modules/wireguard/views.py b/plinth/modules/wireguard/views.py
index 1e1f72141..1558646a0 100644
--- a/plinth/modules/wireguard/views.py
+++ b/plinth/modules/wireguard/views.py
@@ -29,7 +29,8 @@ from django.utils.translation import ugettext as _
from django.views.generic import FormView, TemplateView
import plinth.modules.wireguard as wireguard
-from plinth import actions, network
+from plinth import network
+from plinth.modules.names.components import DomainName
from plinth.views import AppView
from . import forms, utils
@@ -49,9 +50,8 @@ class WireguardView(AppView):
def get_context_data(self, **kwargs):
"""Return additional context for rendering the template."""
context = super().get_context_data(**kwargs)
- context['public_key'] = wireguard.get_public_key()
- info = wireguard.get_info()
- context['server_peers'] = info['my_server']['clients']
+ info = utils.get_info()
+ context['server'] = info['my_server']
context['client_peers'] = info['my_client']['servers']
return context
@@ -72,7 +72,13 @@ class AddClientView(SuccessMessageMixin, FormView):
def form_valid(self, form):
"""Add the client."""
public_key = form.cleaned_data.get('public_key')
- actions.superuser_run('wireguard', ['add-client', public_key])
+ try:
+ utils.add_client(public_key)
+ except ValueError:
+ messages.warning(self.request,
+ _('Client with public key already exists'))
+ return redirect('wireguard:index')
+
return super().form_valid(form)
@@ -86,12 +92,17 @@ class ShowClientView(SuccessMessageMixin, TemplateView):
context['title'] = _('Show Client')
public_key = urllib.parse.unquote(self.kwargs['public_key'])
- info = wireguard.get_info()
- context.update(info)
- for client in info['my_server']['clients']:
- if client['public_key'] == public_key:
- context['client'] = client
+ server_info = utils.get_info()['my_server']
+ if not server_info or public_key not in server_info['peers']:
+ raise Http404
+ domains = DomainName.list_names(filter_for_service='wireguard')
+ context['server'] = server_info
+ context['client'] = server_info['peers'][public_key]
+ context['endpoints'] = [
+ domain + ':' + str(server_info['listen_port'])
+ for domain in domains
+ ]
return context
@@ -117,10 +128,17 @@ class EditClientView(SuccessMessageMixin, FormView):
def form_valid(self, form):
"""Update the client."""
old_public_key = form.initial['public_key']
- actions.superuser_run('wireguard', ['remove-client', old_public_key])
-
public_key = form.cleaned_data.get('public_key')
- actions.superuser_run('wireguard', ['add-client', public_key])
+
+ if old_public_key != public_key:
+ try:
+ utils.add_client(public_key)
+ except ValueError:
+ messages.warning(self.request,
+ _('Client with public key already exists'))
+
+ utils.remove_client(old_public_key)
+
return super().form_valid(form)
@@ -138,8 +156,12 @@ class DeleteClientView(SuccessMessageMixin, TemplateView):
def post(self, request, public_key):
"""Delete the client."""
public_key = urllib.parse.unquote(public_key)
- actions.superuser_run('wireguard', ['remove-client', public_key])
- messages.success(request, _('Client deleted.'))
+ try:
+ utils.remove_client(public_key)
+ messages.success(request, _('Client deleted.'))
+ except KeyError:
+ messages.error(request, _('Client not found'))
+
return redirect('wireguard:index')
@@ -172,7 +194,7 @@ class ShowServerView(SuccessMessageMixin, TemplateView):
context['title'] = _('Server Information')
interface = self.kwargs['interface']
- info = wireguard.get_info()
+ info = utils.get_info()
server = info['my_client']['servers'].get(interface)
if not server:
raise Http404
@@ -199,14 +221,14 @@ class EditServerView(SuccessMessageMixin, FormView):
"""Get initial form data."""
initial = super().get_initial()
interface = self.kwargs['interface']
- info = wireguard.get_nm_info()
+ info = utils.get_nm_info()
server = info.get(interface)
if not server:
raise Http404
initial['ip_address'] = server.get('ip_address')
if server['peers']:
- peer = server['peers'][0]
+ peer = next(peer for peer in server['peers'].values())
initial['peer_endpoint'] = peer['endpoint']
initial['peer_public_key'] = peer['public_key']
initial['private_key'] = server['private_key']
@@ -220,7 +242,7 @@ class EditServerView(SuccessMessageMixin, FormView):
settings = form.get_settings()
interface = self.kwargs['interface']
settings['common']['interface'] = interface
- settings['common']['name'] = 'WireGuard-' + interface
+ settings['common']['name'] = 'WireGuard-Client-' + interface
connection = network.get_connection_by_interface_name(interface)
network.edit_connection(connection, settings)
return super().form_valid(form)
@@ -236,14 +258,14 @@ class DeleteServerView(SuccessMessageMixin, TemplateView):
context['title'] = _('Delete Server')
interface = self.kwargs['interface']
- info = wireguard.get_nm_info()
+ info = utils.get_nm_info()
server = info.get(interface)
if not server:
raise Http404
context['interface'] = interface
if server['peers']:
- peer = server['peers'][0]
+ peer = next(peer for peer in server['peers'].values())
context['peer_endpoint'] = peer['endpoint']
context['peer_public_key'] = peer['public_key']
diff --git a/plinth/network.py b/plinth/network.py
index d491e3083..7d3add55c 100644
--- a/plinth/network.py
+++ b/plinth/network.py
@@ -477,19 +477,27 @@ def _update_wireguard_settings(connection, wireguard):
settings.set_property(nm.SETTING_WIREGUARD_PRIVATE_KEY,
wireguard['private_key'])
- peer = nm.WireGuardPeer.new()
- peer.set_endpoint(wireguard['peer_endpoint'], False)
- peer.set_public_key(wireguard['peer_public_key'], False)
- if wireguard['preshared_key']:
- # Flag NONE means that NM should store and retain the secret.
- # Default seems to be NOT_REQUIRED in this case.
- peer.set_preshared_key_flags(nm.SettingSecretFlags.NONE)
- peer.set_preshared_key(wireguard['preshared_key'], False)
+ if 'listen_port' in wireguard:
+ settings.set_property(nm.SETTING_WIREGUARD_LISTEN_PORT,
+ wireguard['listen_port'])
- peer.append_allowed_ip('0.0.0.0/0', False)
- peer.append_allowed_ip('::/0', False)
- settings.clear_peers()
- settings.append_peer(peer)
+ if 'peer_public_key' in wireguard:
+ peer = nm.WireGuardPeer.new()
+ peer.set_public_key(wireguard['peer_public_key'], False)
+
+ if 'peer_endpoint' in wireguard:
+ peer.set_endpoint(wireguard['peer_endpoint'], False)
+
+ if wireguard['preshared_key']:
+ # Flag NONE means that NM should store and retain the secret.
+ # Default seems to be NOT_REQUIRED in this case.
+ peer.set_preshared_key_flags(nm.SettingSecretFlags.NONE)
+ peer.set_preshared_key(wireguard['preshared_key'], False)
+
+ peer.append_allowed_ip('0.0.0.0/0', False)
+ peer.append_allowed_ip('::/0', False)
+ settings.clear_peers()
+ settings.append_peer(peer)
def _update_settings(connection, connection_uuid, settings):
{% trans "Latest handshake:" %}
+ {{ peer.status.latest_handshake|default:'' }}
+