wireguard: Form to add server

Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
James Valleroy 2019-09-06 16:54:09 -04:00
parent 5d287ce579
commit 901f89f393
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
6 changed files with 144 additions and 1 deletions

View File

@ -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()

View File

@ -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.'))

View File

@ -74,7 +74,12 @@
<ul>{% trans "last connected time" %}</ul>
<ul>{% trans "edit" %}</ul>
<p>{% trans "No connections to remove servers are configured yet." %}</p>
<ul>{% trans "Add Server" %}</ul>
<a title="{% trans 'Add a new server' %}"
role="button" class="btn btn-default"
href="{% url 'wireguard:add-server' %}">
<span class="fa fa-plus" aria-hidden="true"></span>
{% trans "Add Server" %}
</a>
{{ block.super }}

View File

@ -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 <http://www.gnu.org/licenses/>.
#
{% endcomment %}
{% load bootstrap %}
{% load i18n %}
{% block content %}
<h3>{{ title }}</h3>
<form class="form" method="post">
{% csrf_token %}
{{ form|bootstrap }}
<input type="submit" class="btn btn-primary"
value="{% trans "Add Server" %}"/>
</form>
{% endblock %}

View File

@ -30,4 +30,6 @@ urlpatterns = [
views.ShowClientView.as_view(), name='show-client'),
url(r'^apps/wireguard/client/(?P<public_key>[^/]+)/delete/$',
views.DeleteClientView.as_view(), name='delete-client'),
url(r'^apps/wireguard/server/add/$', views.AddServerView.as_view(),
name='add-server'),
]

View File

@ -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)