From 901f89f393ed0655692cbfccfd9abf80a337f158 Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Fri, 6 Sep 2019 16:54:09 -0400 Subject: [PATCH] wireguard: Form to add server Signed-off-by: James Valleroy Reviewed-by: Sunil Mohan Adapa --- actions/wireguard | 41 +++++++++++++++++++ plinth/modules/wireguard/forms.py | 25 +++++++++++ .../wireguard/templates/wireguard.html | 7 +++- .../templates/wireguard_add_server.html | 37 +++++++++++++++++ plinth/modules/wireguard/urls.py | 2 + plinth/modules/wireguard/views.py | 33 +++++++++++++++ 6 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 plinth/modules/wireguard/templates/wireguard_add_server.html diff --git a/actions/wireguard b/actions/wireguard index a8a309316..693477bcb 100755 --- a/actions/wireguard +++ b/actions/wireguard @@ -43,6 +43,18 @@ def parse_arguments(): help='Remove a client') remove_client.add_argument('publickey', help=PUBLIC_KEY_HELP) + add_server = subparsers.add_parser('add-server', help='Add a server') + add_server.add_argument('--endpoint', required=True, + help='Server endpoint') + add_server.add_argument('--client-ip', required=True, + help='Client IP address provided by server') + add_server.add_argument('--public-key', required=True, + help='Public key of the server') + add_server.add_argument('--pre-shared-key', help='Pre-shared key') + add_server.add_argument( + '--all-outgoing', action='store_true', + help='Use this connection to send all outgoing traffic') + subparsers.required = True return parser.parse_args() @@ -52,6 +64,9 @@ def subcommand_setup(_): subprocess.run( ['ip', 'link', 'add', 'dev', SERVER_INTERFACE, 'type', 'wireguard'], check=True) + subprocess.run( + ['wg', 'set', SERVER_INTERFACE, 'listen-port', '51820'], check=True) + # TODO: generate key pair def subcommand_get_info(_): @@ -82,6 +97,7 @@ def subcommand_get_info(_): } clients.append(client_info) + # TODO: Add servers info from other interfaces. info = { 'server': server, 'clients': clients, @@ -103,6 +119,31 @@ def subcommand_remove_client(arguments): check=True) +def subcommand_add_server(arguments): + """Add a server.""" + output = subprocess.check_output( + ['wg', 'show', 'interfaces']).decode().strip() + interfaces = output.split() + interface_num = 1 + for interface in interfaces: + new_interface_name = 'wg' + str(interface_num) + if interface == new_interface_name: + interface_num += 1 + else: + break + + subprocess.run( + ['ip', 'link', 'add', 'dev', new_interface_name, 'type', 'wireguard'], + check=True) + + args = ['wg', 'set', interface, 'peer', arguments.public_key] + if arguments.pre_shared_key: + args += ['preshared-key', arguments.pre_shared_key] + + args += ['endpoint', arguments.endpoint] + subprocess.run(args, check=True) + + def main(): """Parse arguments and perform all duties.""" arguments = parse_arguments() diff --git a/plinth/modules/wireguard/forms.py b/plinth/modules/wireguard/forms.py index 54c65a584..2fe72d2d4 100644 --- a/plinth/modules/wireguard/forms.py +++ b/plinth/modules/wireguard/forms.py @@ -27,3 +27,28 @@ class AddClientForm(forms.Form): public_key = forms.CharField( label=_('Public Key'), strip=True, help_text=_('Public key of the peer.')) + + +class AddServerForm(forms.Form): + """Form to add server.""" + endpoint = forms.CharField( + label=_('Endpoint'), strip=True, + help_text=_('Server endpoint with the form "ip:port".')) + + client_ip_address = forms.CharField( + label=_('Client IP address provided by server'), strip=True, + help_text=_('Client IP address provided by server.')) + + public_key = forms.CharField( + label=_('Public key of the server'), strip=True, + help_text=_('Public key of the server.')) + + pre_shared_key = forms.CharField( + label=_('Pre-shared key'), strip=True, required=False, + help_text=_('Optional: a shared secret key provided by the server to ' + 'add an additional layer of encryption.')) + + all_outgoing_traffic = forms.BooleanField( + label=_('Use this connection to send all outgoing traffic'), + required=False, + help_text=_('Use this connection to send all outgoing traffic.')) diff --git a/plinth/modules/wireguard/templates/wireguard.html b/plinth/modules/wireguard/templates/wireguard.html index c94ceef0d..584c7abd6 100644 --- a/plinth/modules/wireguard/templates/wireguard.html +++ b/plinth/modules/wireguard/templates/wireguard.html @@ -74,7 +74,12 @@
    {% trans "last connected time" %}
    {% trans "edit" %}

{% trans "No connections to remove servers are configured yet." %}

-
    {% trans "Add Server" %}
+ + + {% trans "Add Server" %} + {{ block.super }} diff --git a/plinth/modules/wireguard/templates/wireguard_add_server.html b/plinth/modules/wireguard/templates/wireguard_add_server.html new file mode 100644 index 000000000..dc508b99c --- /dev/null +++ b/plinth/modules/wireguard/templates/wireguard_add_server.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} +{% comment %} +# +# This file is part of FreedomBox. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +{% endcomment %} + +{% load bootstrap %} +{% load i18n %} + +{% block content %} + +

{{ title }}

+ +
+ {% csrf_token %} + + {{ form|bootstrap }} + + +
+ +{% endblock %} diff --git a/plinth/modules/wireguard/urls.py b/plinth/modules/wireguard/urls.py index a454dbd4e..2135867bc 100644 --- a/plinth/modules/wireguard/urls.py +++ b/plinth/modules/wireguard/urls.py @@ -30,4 +30,6 @@ urlpatterns = [ views.ShowClientView.as_view(), name='show-client'), url(r'^apps/wireguard/client/(?P[^/]+)/delete/$', views.DeleteClientView.as_view(), name='delete-client'), + url(r'^apps/wireguard/server/add/$', views.AddServerView.as_view(), + name='add-server'), ] diff --git a/plinth/modules/wireguard/views.py b/plinth/modules/wireguard/views.py index dcf5acfa1..84bf3ff1a 100644 --- a/plinth/modules/wireguard/views.py +++ b/plinth/modules/wireguard/views.py @@ -104,3 +104,36 @@ class DeleteClientView(SuccessMessageMixin, TemplateView): actions.superuser_run('wireguard', ['remove-client', public_key]) messages.success(request, _('Client deleted.')) return redirect('wireguard:index') + + +class AddServerView(SuccessMessageMixin, FormView): + """View to add a server.""" + form_class = forms.AddServerForm + template_name = 'wireguard_add_server.html' + success_url = reverse_lazy('wireguard:index') + success_message = _('Added new server.') + + def get_context_data(self, **kwargs): + """Return additional context for rendering the template.""" + context = super().get_context_data(**kwargs) + context['title'] = _('Add Server') + return context + + def form_valid(self, form): + """Add the server.""" + endpoint = form.cleaned_data.get('endpoint') + client_ip_address = form.cleaned_data.get('client_ip_address') + public_key = form.cleaned_data.get('public_key') + pre_shared_key = form.cleaned_data.get('pre_shared_key') + all_outgoing_traffic = form.cleaned_data.get('all_outgoing_traffic') + args = ['add-server', '--endpoint', endpoint, '--client-ip', + client_ip_address, '--public-key', public_key] + if pre_shared_key: + # TODO: pass pre-shared key through stdin + args += ['--pre-shared-key', pre_shared_key] + + if all_outgoing_traffic: + args.append('--all-outgoing') + + actions.superuser_run('wireguard', args) + return super().form_valid(form)