improve export view

This commit is contained in:
Eduardo Silva
2026-02-03 16:50:29 -03:00
parent 6ab13c14f1
commit 2945be9ffa
4 changed files with 80 additions and 31 deletions

View File

@@ -0,0 +1,20 @@
# Generated by Django 5.2.9 on 2026-02-03 19:30
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('firewall', '0015_alter_firewallsettings_default_forward_policy_and_more'),
('wireguard', '0032_remove_peer_enabled_by_schedule'),
]
operations = [
migrations.AddField(
model_name='firewallsettings',
name='instance_to_execute_firewall',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='wireguard.wireguardinstance'),
),
]

View File

@@ -79,6 +79,7 @@ class FirewallSettings(models.Model):
wan_interface = models.CharField(max_length=12, default='eth0') wan_interface = models.CharField(max_length=12, default='eth0')
pending_changes = models.BooleanField(default=False) pending_changes = models.BooleanField(default=False)
last_firewall_reset = models.DateTimeField(blank=True, null=True) last_firewall_reset = models.DateTimeField(blank=True, null=True)
instance_to_execute_firewall = models.ForeignKey(WireGuardInstance, on_delete=models.SET_NULL, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True) updated = models.DateTimeField(auto_now=True)

View File

@@ -14,7 +14,7 @@ from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from cluster.models import ClusterSettings, Worker from cluster.models import ClusterSettings, Worker
from firewall.models import RedirectRule from firewall.models import RedirectRule, FirewallSettings
from firewall.tools import export_user_firewall, generate_firewall_footer, generate_firewall_header, \ from firewall.tools import export_user_firewall, generate_firewall_footer, generate_firewall_header, \
generate_port_forward_firewall, generate_redirect_dns_rules, generate_route_policy_rules generate_port_forward_firewall, generate_redirect_dns_rules, generate_route_policy_rules
from user_manager.models import UserAcl from user_manager.models import UserAcl
@@ -76,43 +76,61 @@ def export_firewall_configuration():
return return
@login_required def set_instance_to_include_firewall():
def export_wireguard_configs(request): firewall_settings, firewall_settings_created = FirewallSettings.objects.get_or_create(name='global')
if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=30).exists(): if firewall_settings.instance_to_execute_firewall:
return render(request, 'access_denied.html', {'page_title': 'Access Denied'}) force_export_all_instances = False
instance_to_execute_firewall = firewall_settings.instance_to_execute_firewall
else:
force_export_all_instances = True
instance_to_execute_firewall = WireGuardInstance.objects.order_by('instance_id').first()
if instance_to_execute_firewall:
firewall_settings.instance_to_execute_firewall = instance_to_execute_firewall
firewall_settings.save()
return instance_to_execute_firewall, force_export_all_instances
def export_wireguard_configuration(instance_only: WireGuardInstance = None):
cluster_settings = ClusterSettings.objects.filter(name='cluster_settings', enabled=True).first() cluster_settings = ClusterSettings.objects.filter(name='cluster_settings', enabled=True).first()
if cluster_settings: if cluster_settings:
if WireGuardInstance.objects.filter(pending_changes=True).exists(): if WireGuardInstance.objects.filter(pending_changes=True).exists():
cluster_settings.config_version += 1 cluster_settings.config_version += 1
cluster_settings.save() cluster_settings.save()
instances = WireGuardInstance.objects.all() cleanup_orphaned = True
instance_to_execute_firewall, force_export_all_instances = set_instance_to_include_firewall()
if instance_only and not force_export_all_instances:
instances = WireGuardInstance.objects.filter(id=instance_only.id)
cleanup_orphaned = False
else:
instances = WireGuardInstance.objects.all()
base_dir = "/etc/wireguard" base_dir = "/etc/wireguard"
os.makedirs(base_dir, exist_ok=True) os.makedirs(base_dir, exist_ok=True)
export_firewall_configuration()
firewall_inserted = False firewall_inserted = False
active_instance_conf_set = {f"wg{instance.instance_id}.conf" for instance in instances} if cleanup_orphaned:
for old_conf_file in glob.glob(os.path.join(base_dir, "wg[0-9]*.conf")): active_instance_conf_set = {f"wg{instance.instance_id}.conf" for instance in instances}
filename = os.path.basename(old_conf_file) for old_conf_file in glob.glob(os.path.join(base_dir, "wg[0-9]*.conf")):
if filename not in active_instance_conf_set: filename = os.path.basename(old_conf_file)
logging.info("Removing abandoned WireGuard config: %s", filename) if filename not in active_instance_conf_set:
try: logging.info("Removing abandoned WireGuard config: %s", filename)
os.remove(old_conf_file) try:
except FileNotFoundError: os.remove(old_conf_file)
pass except FileNotFoundError:
except IsADirectoryError: pass
continue except IsADirectoryError:
except PermissionError: continue
continue except PermissionError:
continue
for instance in instances: for instance in instances:
if instance.legacy_firewall: if instance.legacy_firewall:
post_up_processed = clean_command_field(instance.post_up) if instance.post_up else "" post_up_processed = clean_command_field(instance.post_up) if instance.post_up else ""
post_down_processed = clean_command_field(instance.post_down) if instance.post_down else "" post_down_processed = clean_command_field(instance.post_down) if instance.post_down else ""
if post_up_processed: if post_up_processed:
post_up_processed += '; ' post_up_processed += '; '
if post_down_processed: if post_down_processed:
@@ -127,27 +145,26 @@ def export_wireguard_configs(request):
if peer_allowed_ip_address: if peer_allowed_ip_address:
rule_destination = peer_allowed_ip_address.allowed_ip rule_destination = peer_allowed_ip_address.allowed_ip
if rule_destination: if rule_destination:
rule_text_up = f"iptables -t nat -A PREROUTING -p {redirect_rule.protocol} -d wireguard-webadmin --dport {redirect_rule.port} -j DNAT --to-dest {rule_destination}:{redirect_rule.port} ; " rule_text_up = f"iptables -t nat -A PREROUTING -p {redirect_rule.protocol} -d wireguard-webadmin --dport {redirect_rule.port} -j DNAT --to-dest {rule_destination}:{redirect_rule.port} ; "
rule_text_down = f"iptables -t nat -D PREROUTING -p {redirect_rule.protocol} -d wireguard-webadmin --dport {redirect_rule.port} -j DNAT --to-dest {rule_destination}:{redirect_rule.port} ; " rule_text_down = f"iptables -t nat -D PREROUTING -p {redirect_rule.protocol} -d wireguard-webadmin --dport {redirect_rule.port} -j DNAT --to-dest {rule_destination}:{redirect_rule.port} ; "
if redirect_rule.add_forward_rule: if redirect_rule.add_forward_rule:
rule_text_up += f"iptables -A FORWARD -d {rule_destination} -p {redirect_rule.protocol} --dport {redirect_rule.port} -j ACCEPT ; " rule_text_up += f"iptables -A FORWARD -d {rule_destination} -p {redirect_rule.protocol} --dport {redirect_rule.port} -j ACCEPT ; "
rule_text_down += f"iptables -D FORWARD -d {rule_destination} -p {redirect_rule.protocol} --dport {redirect_rule.port} -j ACCEPT ; " rule_text_down += f"iptables -D FORWARD -d {rule_destination} -p {redirect_rule.protocol} --dport {redirect_rule.port} -j ACCEPT ; "
if redirect_rule.masquerade_source: if redirect_rule.masquerade_source:
rule_text_up += f"iptables -t nat -A POSTROUTING -d {rule_destination} -p {redirect_rule.protocol} --dport {redirect_rule.port} -j MASQUERADE ; " rule_text_up += f"iptables -t nat -A POSTROUTING -d {rule_destination} -p {redirect_rule.protocol} --dport {redirect_rule.port} -j MASQUERADE ; "
rule_text_down += f"iptables -t nat -D POSTROUTING -d {rule_destination} -p {redirect_rule.protocol} --dport {redirect_rule.port} -j MASQUERADE ; " rule_text_down += f"iptables -t nat -D POSTROUTING -d {rule_destination} -p {redirect_rule.protocol} --dport {redirect_rule.port} -j MASQUERADE ; "
post_up_processed += rule_text_up post_up_processed += rule_text_up
post_down_processed += rule_text_down post_down_processed += rule_text_down
pass pass
else: else:
post_down_processed = '' post_down_processed = ''
if not firewall_inserted: if not firewall_inserted and instance == instance_to_execute_firewall:
post_up_processed = '/etc/wireguard/wg-firewall.sh' post_up_processed = '/etc/wireguard/wg-firewall.sh'
firewall_inserted = True firewall_inserted = True
else: else:
post_up_processed = '' post_up_processed = ''
config_lines = [ config_lines = [
"[Interface]", "[Interface]",
@@ -177,6 +194,17 @@ def export_wireguard_configs(request):
with open(config_path, "w") as config_file: with open(config_path, "w") as config_file:
config_file.write(config_content) config_file.write(config_content)
return
@login_required
def view_export_wireguard_configs(request):
if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=30).exists():
return render(request, 'access_denied.html', {'page_title': 'Access Denied'})
export_firewall_configuration()
export_wireguard_configuration()
if request.GET.get('action') == 'update_and_restart' or request.GET.get('action') == 'update_and_reload': if request.GET.get('action') == 'update_and_restart' or request.GET.get('action') == 'update_and_reload':
messages.success(request, _("Export successful!|WireGuard configuration files have been exported to /etc/wireguard/.")) messages.success(request, _("Export successful!|WireGuard configuration files have been exported to /etc/wireguard/."))
else: else:

View File

@@ -43,7 +43,7 @@ from wireguard.views import view_apply_db_patches, view_wireguard_manage_instanc
from wireguard_peer.views import view_manage_ip_address, view_wireguard_peer_list, view_wireguard_peer_manage, \ from wireguard_peer.views import view_manage_ip_address, view_wireguard_peer_list, view_wireguard_peer_manage, \
view_wireguard_peer_sort, view_apply_route_template, view_wireguard_peer_create, view_wireguard_peer_edit_field, \ view_wireguard_peer_sort, view_apply_route_template, view_wireguard_peer_create, view_wireguard_peer_edit_field, \
view_wireguard_peer_suspend, view_wireguard_peer_schedule_profile view_wireguard_peer_suspend, view_wireguard_peer_schedule_profile
from wireguard_tools.views import download_config_or_qrcode, export_wireguard_configs, restart_wireguard_interfaces from wireguard_tools.views import download_config_or_qrcode, view_export_wireguard_configs, restart_wireguard_interfaces
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
@@ -71,7 +71,7 @@ urlpatterns = [
path('user/manage/', view_manage_user, name='manage_user'), path('user/manage/', view_manage_user, name='manage_user'),
path('user/peer-group/list/', view_peer_group_list, name='peer_group_list'), path('user/peer-group/list/', view_peer_group_list, name='peer_group_list'),
path('user/peer-group/manage/', view_peer_group_manage, name='peer_group_manage'), path('user/peer-group/manage/', view_peer_group_manage, name='peer_group_manage'),
path('tools/export_wireguard_config/', export_wireguard_configs, name='export_wireguard_configs'), path('tools/export_wireguard_config/', view_export_wireguard_configs, name='export_wireguard_configs'),
path('tools/download_peer_config/', download_config_or_qrcode, name='download_config_or_qrcode'), path('tools/download_peer_config/', download_config_or_qrcode, name='download_config_or_qrcode'),
path('tools/restart_wireguard/', restart_wireguard_interfaces, name='restart_wireguard_interfaces'), path('tools/restart_wireguard/', restart_wireguard_interfaces, name='restart_wireguard_interfaces'),
path('server/manage/', view_wireguard_manage_instance, name='wireguard_manage_instance'), path('server/manage/', view_wireguard_manage_instance, name='wireguard_manage_instance'),