Port forwarding to peers! :)

This commit is contained in:
Eduardo Silva
2024-02-26 18:55:04 -03:00
parent 4bcf853e9e
commit abeafa228c
13 changed files with 386 additions and 32 deletions

View File

@@ -0,0 +1,52 @@
from firewall.models import RedirectRule
from wireguard.models import Peer, WireGuardInstance
from django import forms
class RedirectRuleForm(forms.ModelForm):
description = forms.CharField(label='Description', required=False)
protocol = forms.ChoiceField(label='Protocol', choices=[('tcp', 'TCP'), ('udp', 'UDP')], initial='tcp')
port = forms.IntegerField(label='Port', initial=8080, min_value=1, max_value=65535)
add_forward_rule = forms.BooleanField(label='Add Forward Rule', required=False, initial=True)
masquerade_source = forms.BooleanField(label='Masquerade Source (not recommended)', required=False)
peer = forms.ModelChoiceField(label='Peer', queryset=Peer.objects.all(), required=False)
wireguard_instance = forms.ModelChoiceField(label='WireGuard Instance', queryset=WireGuardInstance.objects.all().order_by('instance_id'), required=True)
ip_address = forms.GenericIPAddressField(label='IP Address', required=False)
class Meta:
model = RedirectRule
fields = ['description', 'protocol', 'port', 'add_forward_rule', 'masquerade_source', 'peer', 'wireguard_instance', 'ip_address']
def __init__(self, *args, **kwargs):
super(RedirectRuleForm, self).__init__(*args, **kwargs)
if self.fields['wireguard_instance'].queryset.exists():
self.fields['wireguard_instance'].initial = self.fields['wireguard_instance'].queryset.first().uuid
def clean(self):
cleaned_data = super().clean()
port = cleaned_data.get('port')
protocol = cleaned_data.get('protocol')
peer = cleaned_data.get('peer')
ip_address = cleaned_data.get('ip_address')
wireguard_instance = cleaned_data.get('wireguard_instance')
if port == 8000 and protocol == 'tcp':
raise forms.ValidationError("Port 8000 (tcp) is reserved for wireguard-webadmin.")
if protocol == 'udp':
if WireGuardInstance.objects.filter(udp_port=port).exists():
raise forms.ValidationError("Port " + str(port) + " (udp) is already in use by a WireGuard instance.")
if peer and ip_address:
raise forms.ValidationError("Peer and IP Address cannot be selected at the same time.")
if ip_address and not wireguard_instance:
raise forms.ValidationError("IP Address cannot be used without selecting a WireGuard instance.")
if peer:
cleaned_data['wireguard_instance'] = peer.wireguard_instance
cleaned_data['ip_address'] = None
if ip_address:
cleaned_data['peer'] = None
return cleaned_data

View File

@@ -1,15 +1,55 @@
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404, redirect
from firewall.models import RedirectRule
from firewall.forms import RedirectRuleForm
from django.contrib import messages
from wireguard.models import WireGuardInstance
from user_manager.models import UserAcl
def view_redirect_rule_list(request):
wireguard_instances = WireGuardInstance.objects.all().order_by('instance_id')
if wireguard_instances.filter(pending_changes=True).exists():
pending_changes_warning = True
else:
pending_changes_warning = False
context = {
'page_title': 'Port Forward List',
'pending_changes_warning': pending_changes_warning,
'redirect_rule_list': RedirectRule.objects.all().order_by('wireguard_instance', 'protocol', 'port')
}
return render(request, 'firewall/redirect_rule_list.html', context=context)
def manage_redirect_rule(request):
if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=40).exists():
return render(request, 'access_denied.html', {'page_title': 'Access Denied'})
context = {'page_title': 'Manage Port Forward'}
instance = None
uuid = request.GET.get('uuid', None)
if uuid:
instance = get_object_or_404(RedirectRule, uuid=uuid)
if request.GET.get('action') == 'delete':
if request.GET.get('confirmation') == instance.protocol + str(instance.port):
instance.wireguard_instance.pending_changes = True
instance.wireguard_instance.save()
instance.delete()
messages.success(request, 'Port Forward rule deleted successfully')
else:
messages.warning(request, 'Error deleting Port Forward rule|Confirmation did not match. Port Forward rule was not deleted.')
return redirect('/firewall/port_forward/')
if request.method == 'POST':
form = RedirectRuleForm(request.POST, instance=instance)
if form.is_valid():
wireguard_instance = form.cleaned_data['wireguard_instance']
wireguard_instance.pending_changes = True
wireguard_instance.save()
form.save()
messages.success(request, 'Port Forward rule saved successfully')
return redirect('/firewall/port_forward/')
else:
form = RedirectRuleForm(instance=instance)
context['form'] = form
context['instance'] = instance
return render(request, 'firewall/manage_redirect_rule.html', context=context)