mirror of
https://github.com/eduardogsilva/wireguard_webadmin.git
synced 2026-02-19 19:26:17 +00:00
suspend/unsuspend peer with interface reload
This commit is contained in:
@@ -18,6 +18,8 @@ from wgwadmlibrary.tools import check_sort_order_conflict, deduplicate_sort_orde
|
|||||||
from wireguard.models import Peer, PeerAllowedIP, WireGuardInstance
|
from wireguard.models import Peer, PeerAllowedIP, WireGuardInstance
|
||||||
from wireguard_peer.forms import PeerAllowedIPForm, PeerNameForm, PeerKeepaliveForm, PeerKeysForm, PeerSuspensionForm, \
|
from wireguard_peer.forms import PeerAllowedIPForm, PeerNameForm, PeerKeepaliveForm, PeerKeysForm, PeerSuspensionForm, \
|
||||||
PeerScheduleProfileForm
|
PeerScheduleProfileForm
|
||||||
|
from wireguard_tools.functions import func_reload_wireguard_interface
|
||||||
|
from wireguard_tools.views import export_wireguard_configuration
|
||||||
|
|
||||||
|
|
||||||
def generate_peer_default(wireguard_instance):
|
def generate_peer_default(wireguard_instance):
|
||||||
@@ -425,8 +427,6 @@ def view_wireguard_peer_suspend(request):
|
|||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
form.save()
|
form.save()
|
||||||
messages.success(request, _('Peer suspension/unsuspension scheduled successfully.'))
|
messages.success(request, _('Peer suspension/unsuspension scheduled successfully.'))
|
||||||
current_peer.wireguard_instance.pending_changes = True
|
|
||||||
current_peer.wireguard_instance.save()
|
|
||||||
else:
|
else:
|
||||||
messages.error(request, _('Error scheduling peer suspension/unsuspension. Please correct the errors below.'))
|
messages.error(request, _('Error scheduling peer suspension/unsuspension. Please correct the errors below.'))
|
||||||
|
|
||||||
@@ -436,24 +436,31 @@ def view_wireguard_peer_suspend(request):
|
|||||||
peer_scheduling.manual_suspend_reason = None
|
peer_scheduling.manual_suspend_reason = None
|
||||||
peer_scheduling.save()
|
peer_scheduling.save()
|
||||||
messages.success(request, _('Schedule cleared successfully.'))
|
messages.success(request, _('Schedule cleared successfully.'))
|
||||||
current_peer.wireguard_instance.pending_changes = True
|
|
||||||
current_peer.wireguard_instance.save()
|
|
||||||
|
|
||||||
elif action == 'suspend_now':
|
elif action == 'suspend_now':
|
||||||
current_peer.suspended = True
|
current_peer.suspended = True
|
||||||
current_peer.suspend_reason = manual_suspend_reason
|
current_peer.suspend_reason = manual_suspend_reason
|
||||||
current_peer.save()
|
current_peer.save()
|
||||||
messages.success(request, _('Peer suspended successfully.'))
|
|
||||||
current_peer.wireguard_instance.pending_changes = True
|
export_wireguard_configuration(current_peer.wireguard_instance)
|
||||||
current_peer.wireguard_instance.save()
|
success, message = func_reload_wireguard_interface(current_peer.wireguard_instance)
|
||||||
|
if success:
|
||||||
|
messages.success(request, _('Peer suspended successfully.'))
|
||||||
|
else:
|
||||||
|
messages.error(request, _('Peer suspended, but failed to reload WireGuard interface: ') + message)
|
||||||
|
|
||||||
elif action == 'unsuspend_now':
|
elif action == 'unsuspend_now':
|
||||||
current_peer.suspended = False
|
current_peer.suspended = False
|
||||||
current_peer.suspend_reason = ''
|
current_peer.suspend_reason = ''
|
||||||
current_peer.save()
|
current_peer.save()
|
||||||
messages.success(request, _('Peer reactivated successfully.'))
|
|
||||||
current_peer.wireguard_instance.pending_changes = True
|
export_wireguard_configuration(current_peer.wireguard_instance)
|
||||||
current_peer.wireguard_instance.save()
|
success, message = func_reload_wireguard_interface(current_peer.wireguard_instance)
|
||||||
|
if success:
|
||||||
|
messages.success(request, _('Peer reactivated successfully.'))
|
||||||
|
else:
|
||||||
|
messages.error(request, _('Peer reactivated, but failed to reload WireGuard interface: ') + message)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
messages.error(request, _('Invalid action.'))
|
messages.error(request, _('Invalid action.'))
|
||||||
|
|
||||||
|
|||||||
67
wireguard_tools/functions.py
Normal file
67
wireguard_tools/functions.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from wireguard.models import WireGuardInstance
|
||||||
|
|
||||||
|
|
||||||
|
def func_reload_wireguard_interface(target: Union[str, WireGuardInstance], config_dir: str = "/etc/wireguard") -> tuple[bool, str]:
|
||||||
|
"""
|
||||||
|
Reload a WireGuard interface safely using:
|
||||||
|
wg syncconf <iface> <(wg-quick strip <conf>)
|
||||||
|
|
||||||
|
Accepts:
|
||||||
|
- "wg0"
|
||||||
|
- "wg0.conf"
|
||||||
|
- WireGuardInstance object
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(success: bool, message: str)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Resolve interface name and config path
|
||||||
|
if isinstance(target, WireGuardInstance):
|
||||||
|
interface_name = f"wg{target.instance_id}"
|
||||||
|
conf_filename = f"{interface_name}.conf"
|
||||||
|
else:
|
||||||
|
name = target.replace(".conf", "")
|
||||||
|
interface_name = name
|
||||||
|
conf_filename = f"{name}.conf"
|
||||||
|
|
||||||
|
conf_path = os.path.join(config_dir, conf_filename)
|
||||||
|
|
||||||
|
if not os.path.exists(conf_path):
|
||||||
|
return False, f"Config file not found: {conf_path}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
# First, run wg-quick strip to produce a clean wg-compatible config
|
||||||
|
strip_proc = subprocess.run(
|
||||||
|
["wg-quick", "strip", conf_path],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write stripped config to a temp file
|
||||||
|
temp_path = f"/tmp/wgstrip_{interface_name}.conf"
|
||||||
|
with open(temp_path, "w") as f:
|
||||||
|
f.write(strip_proc.stdout)
|
||||||
|
|
||||||
|
# Apply syncconf
|
||||||
|
sync_proc = subprocess.run(
|
||||||
|
["wg", "syncconf", interface_name, temp_path],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
os.remove(temp_path)
|
||||||
|
|
||||||
|
if sync_proc.returncode != 0:
|
||||||
|
return False, sync_proc.stderr.strip()
|
||||||
|
|
||||||
|
return True, f"{interface_name} reloaded successfully"
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
return False, e.stderr.strip() if e.stderr else str(e)
|
||||||
|
except Exception as e:
|
||||||
|
return False, str(e)
|
||||||
@@ -102,7 +102,7 @@ def export_wireguard_configuration(instance_only: WireGuardInstance = None):
|
|||||||
instance_to_execute_firewall, force_export_all_instances = set_instance_to_include_firewall()
|
instance_to_execute_firewall, force_export_all_instances = set_instance_to_include_firewall()
|
||||||
|
|
||||||
if instance_only and not force_export_all_instances:
|
if instance_only and not force_export_all_instances:
|
||||||
instances = WireGuardInstance.objects.filter(id=instance_only.id)
|
instances = WireGuardInstance.objects.filter(uuid=instance_only.uuid)
|
||||||
cleanup_orphaned = False
|
cleanup_orphaned = False
|
||||||
else:
|
else:
|
||||||
instances = WireGuardInstance.objects.all()
|
instances = WireGuardInstance.objects.all()
|
||||||
@@ -230,8 +230,8 @@ def view_export_wireguard_configs(request):
|
|||||||
if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=30).exists():
|
if not UserAcl.objects.filter(user=request.user).filter(user_level__gte=30).exists():
|
||||||
return render(request, 'access_denied.html', {'page_title': 'Access Denied'})
|
return render(request, 'access_denied.html', {'page_title': 'Access Denied'})
|
||||||
|
|
||||||
export_firewall_configuration()
|
|
||||||
export_wireguard_configuration()
|
export_wireguard_configuration()
|
||||||
|
export_firewall_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/."))
|
||||||
|
|||||||
Reference in New Issue
Block a user