Firewall settings form and small papercuts

This commit is contained in:
Eduardo Silva 2024-03-01 16:32:14 -03:00
parent 5f8627e3f3
commit 1de3bd132f
8 changed files with 149 additions and 11 deletions

View File

@ -1,5 +1,6 @@
from firewall.models import RedirectRule, FirewallRule, FirewallSettings from firewall.models import RedirectRule, FirewallRule, FirewallSettings
from wireguard.models import Peer, WireGuardInstance, NETMASK_CHOICES from wireguard.models import Peer, WireGuardInstance, NETMASK_CHOICES
from wgwadmlibrary.tools import list_network_interfaces
from django import forms from django import forms
import re import re
@ -135,4 +136,19 @@ class FirewallRuleForm(forms.ModelForm):
return cleaned_data return cleaned_data
class FirewallSettingsForm(forms.ModelForm):
interface_choices = []
for interface in list_network_interfaces():
if not interface.startswith('wg') and interface != 'lo':
interface_choices.append((interface, interface))
#if interface.startswith('wg'):
# list_network_interfaces().remove(interface)
default_forward_policy = forms.ChoiceField(label='Default Forward Policy', choices=[('accept', 'ACCEPT'), ('reject', 'REJECT'), ('drop', 'DROP')], initial='accept')
allow_peer_to_peer = forms.BooleanField(label='Allow Peer to Peer', required=False)
allow_instance_to_instance = forms.BooleanField(label='Allow Instance to Instance', required=False)
wan_interface = forms.ChoiceField(label='WAN Interface', choices=interface_choices, initial='eth0')
class Meta:
model = FirewallSettings
fields = ['default_forward_policy', 'allow_peer_to_peer', 'allow_instance_to_instance', 'wan_interface']

View File

@ -1,10 +1,11 @@
from django.shortcuts import render, get_object_or_404, redirect from django.shortcuts import render, get_object_or_404, redirect
from django.db.models import Max from django.db.models import Max
from firewall.models import RedirectRule, FirewallRule, FirewallSettings from firewall.models import RedirectRule, FirewallRule, FirewallSettings
from firewall.forms import RedirectRuleForm, FirewallRuleForm from firewall.forms import RedirectRuleForm, FirewallRuleForm, FirewallSettingsForm
from django.contrib import messages from django.contrib import messages
from wireguard.models import WireGuardInstance from wireguard.models import WireGuardInstance
from user_manager.models import UserAcl from user_manager.models import UserAcl
from wgwadmlibrary.tools import list_network_interfaces
def view_redirect_rule_list(request): def view_redirect_rule_list(request):
@ -124,3 +125,34 @@ def manage_firewall_rule(request):
context['current_chain'] = current_chain context['current_chain'] = current_chain
return render(request, 'firewall/manage_firewall_rule.html', context=context) return render(request, 'firewall/manage_firewall_rule.html', context=context)
def view_manage_firewall_settings(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 Firewall Settings'}
previous_firewall_chain = request.GET.get('chain')
if previous_firewall_chain not in ['forward', 'portforward', 'postrouting']:
previous_firewall_chain = 'forward'
if previous_firewall_chain == 'portforward':
redirect_url = '/firewall/port_forward/'
else:
redirect_url = '/firewall/rule_list/?chain=' + previous_firewall_chain
firewall_settings, firewall_settings_created = FirewallSettings.objects.get_or_create(name='global')
if request.method == 'POST':
form = FirewallSettingsForm(request.POST, instance=firewall_settings)
if form.is_valid():
form.save()
messages.success(request, 'Firewall settings saved successfully')
return redirect(redirect_url)
else:
form = FirewallSettingsForm(instance=firewall_settings)
context['form'] = form
context['instance'] = firewall_settings
context['back_url'] = redirect_url
return render(request, 'firewall/manage_firewall_settings.html', context=context)

View File

@ -86,6 +86,7 @@
</table> </table>
<a href="/firewall/manage_firewall_rule/?chain={{ current_chain }}" class='btn btn-primary'>Create Firewall Rule</a> <a href="/firewall/manage_firewall_rule/?chain={{ current_chain }}" class='btn btn-primary'>Create Firewall Rule</a>
<a href="/firewall/firewall_settings/?chain={{ current_chain }}" class='btn btn-outline-primary'>Firewall Settings</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -14,7 +14,7 @@
<div class="card-header" id="headingGeneral"> <div class="card-header" id="headingGeneral">
<h2 class="mb-0"> <h2 class="mb-0">
<button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#collapseGeneral" aria-expanded="true" aria-controls="collapseGeneral"> <button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#collapseGeneral" aria-expanded="true" aria-controls="collapseGeneral">
General <i class="fas fa-cogs"></i> General
</button> </button>
</h2> </h2>
</div> </div>
@ -93,7 +93,7 @@
<div class="card-header" id="headingInterface"> <div class="card-header" id="headingInterface">
<h2 class="mb-0"> <h2 class="mb-0">
<button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseInterface" aria-expanded="false" aria-controls="collapseInterface"> <button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseInterface" aria-expanded="false" aria-controls="collapseInterface">
Interface <i class="fas fa-network-wired"></i> Interface
</button> </button>
</h2> </h2>
</div> </div>
@ -134,7 +134,7 @@
<div class="card-header" id="headingSource"> <div class="card-header" id="headingSource">
<h2 class="mb-0"> <h2 class="mb-0">
<button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseSource" aria-expanded="false" aria-controls="collapseSource"> <button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseSource" aria-expanded="false" aria-controls="collapseSource">
Source <i class="fas fa-plane-departure"></i> Source
</button> </button>
</h2> </h2>
</div> </div>
@ -193,7 +193,7 @@
<div class="card-header" id="headingDestination"> <div class="card-header" id="headingDestination">
<h2 class="mb-0"> <h2 class="mb-0">
<button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseDestination" aria-expanded="false" aria-controls="collapseDestination"> <button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseDestination" aria-expanded="false" aria-controls="collapseDestination">
Destination <i class="fas fa-plane-arrival"></i> Destination
</button> </button>
</h2> </h2>
</div> </div>
@ -252,7 +252,7 @@
<div class="card-header" id="headingProtocol"> <div class="card-header" id="headingProtocol">
<h2 class="mb-0"> <h2 class="mb-0">
<button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseProtocol" aria-expanded="false" aria-controls="collapseProtocol"> <button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseProtocol" aria-expanded="false" aria-controls="collapseProtocol">
Protocol <i class="fas fa-book"></i> Protocol
</button> </button>
</h2> </h2>
</div> </div>
@ -310,7 +310,7 @@
<div class="card-header" id="headingPacketState"> <div class="card-header" id="headingPacketState">
<h2 class="mb-0"> <h2 class="mb-0">
<button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapsePacketState" aria-expanded="false" aria-controls="collapsePacketState"> <button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapsePacketState" aria-expanded="false" aria-controls="collapsePacketState">
Packet State <i class="fas fa-boxes"></i> Packet State
</button> </button>
</h2> </h2>
</div> </div>
@ -350,7 +350,7 @@
<div class="card-header" id="headingAction"> <div class="card-header" id="headingAction">
<h2 class="mb-0"> <h2 class="mb-0">
<button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseAction" aria-expanded="false" aria-controls="collapseAction"> <button class="btn btn-link btn-block text-left collapsed" type="button" data-toggle="collapse" data-target="#collapseAction" aria-expanded="false" aria-controls="collapseAction">
Action <i class="fas fa-directions"></i> Action
</button> </button>
</h2> </h2>
</div> </div>

View File

@ -0,0 +1,69 @@
{% extends 'base.html' %}
{% block content %}
<div class="row">
<div class="col-md-4">
<form method="post">
{% csrf_token %}
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-12">
<!-- WAN Interface -->
<div class="form-group">
<label for="id_wan_interface">{{ form.wan_interface.label }}</label>
<select class="form-control" id="id_wan_interface" name="wan_interface">
{% for value, display in form.wan_interface.field.choices %}
<option value="{{ value }}" {% if form.wan_interface.value == value %} selected {% endif %}>{{ display }}</option>
{% endfor %}
</select>
</div>
<!-- Default Forward Policy -->
<div class="form-group">
<label for="id_default_forward_policy">{{ form.default_forward_policy.label }}</label>
<select class="form-control" id="id_default_forward_policy" name="default_forward_policy">
{% for value, display in form.default_forward_policy.field.choices %}
<option value="{{ value }}" {% if form.default_forward_policy.value == value %} selected {% endif %}>{{ display }}</option>
{% endfor %}
</select>
</div>
<!-- Allow Peer to Peer -->
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="id_allow_peer_to_peer" name="allow_peer_to_peer" {% if form.allow_peer_to_peer.value %} checked {% endif %}>
<label for="id_allow_peer_to_peer">{{ form.allow_peer_to_peer.label }}</label>
</div>
<!-- Allow Instance to Instance -->
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="id_allow_instance_to_instance" name="allow_instance_to_instance" {% if form.allow_instance_to_instance.value %} checked {% endif %}>
<label for="id_allow_instance_to_instance">{{ form.allow_instance_to_instance.label }}</label>
</div>
</div>
<div class="col-md-6">
</div>
</div>
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary">Submit</button>
<a class="btn btn-outline-secondary" href="{{ back_url }}">Back</a>
</div>
</div>
</form>
</div>
</div>
{% endblock %}

View File

@ -67,7 +67,7 @@
</tbody> </tbody>
</table> </table>
<a href="/firewall/manage_port_forward_rule/" class='btn btn-primary'>Create Port forwarding Rule</a> <a href="/firewall/manage_port_forward_rule/" class='btn btn-primary'>Create Port forwarding Rule</a>
<a href="/firewall/firewall_settings/?chain=porforward" class='btn btn-outline-primary'>Firewall Settings</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,4 +1,5 @@
import ipaddress, re import ipaddress, re
import subprocess
def is_valid_ip_or_hostname(value): def is_valid_ip_or_hostname(value):
@ -15,3 +16,21 @@ def is_valid_ip_or_hostname(value):
return True return True
return False return False
def list_network_interfaces():
# Executa o comando 'ip link show' com grep para filtrar linhas com 'UP'
cmd = "ip link show | grep UP"
cmd_output = subprocess.check_output(cmd, shell=True, text=True)
# Processa a saída para extrair os nomes das interfaces
interfaces = []
for line in cmd_output.split('\n'):
if line: # Verifica se a linha não está vazia
parts = line.split(': ')
if len(parts) > 1:
# O nome da interface está na segunda posição após o split
interface_name = parts[1].split('@')[0] # Remove qualquer coisa após '@'
interfaces.append(interface_name)
return interfaces

View File

@ -23,7 +23,7 @@ from user_manager.views import view_user_list, view_manage_user
from accounts.views import view_create_first_user, view_login, view_logout from accounts.views import view_create_first_user, view_login, view_logout
from wireguard_tools.views import export_wireguard_configs, download_config_or_qrcode, restart_wireguard_interfaces from wireguard_tools.views import export_wireguard_configs, download_config_or_qrcode, restart_wireguard_interfaces
from api.views import wireguard_status, cron_check_updates, cron_update_peer_latest_handshake from api.views import wireguard_status, cron_check_updates, cron_update_peer_latest_handshake
from firewall.views import view_redirect_rule_list, manage_redirect_rule, view_firewall_rule_list, manage_firewall_rule from firewall.views import view_redirect_rule_list, manage_redirect_rule, view_firewall_rule_list, manage_firewall_rule, view_manage_firewall_settings
urlpatterns = [ urlpatterns = [
@ -49,5 +49,6 @@ urlpatterns = [
path('firewall/port_forward/', view_redirect_rule_list, name='redirect_rule_list'), path('firewall/port_forward/', view_redirect_rule_list, name='redirect_rule_list'),
path('firewall/manage_port_forward_rule/', manage_redirect_rule, name='manage_redirect_rule'), path('firewall/manage_port_forward_rule/', manage_redirect_rule, name='manage_redirect_rule'),
path('firewall/rule_list/', view_firewall_rule_list, name='firewall_rule_list'), path('firewall/rule_list/', view_firewall_rule_list, name='firewall_rule_list'),
path('firewall/manage_firewall_rule/', manage_firewall_rule, name='manage_firewall_rule') path('firewall/manage_firewall_rule/', manage_firewall_rule, name='manage_firewall_rule'),
path('firewall/firewall_settings/', view_manage_firewall_settings, name='firewall_settings'),
] ]