2026-02-10 16:41:02 -03:00
|
|
|
import ipaddress
|
|
|
|
|
import subprocess
|
2026-02-10 18:26:49 -03:00
|
|
|
from typing import Any, Dict, Optional, Tuple
|
2026-02-10 16:41:02 -03:00
|
|
|
|
|
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
|
|
|
|
from routing_templates.models import RoutingTemplate
|
|
|
|
|
from wireguard.models import Peer, PeerAllowedIP, WireGuardInstance
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_peer_default(wireguard_instance):
|
|
|
|
|
private_key = subprocess.check_output('wg genkey', shell=True).decode('utf-8').strip()
|
|
|
|
|
public_key = subprocess.check_output(f'echo {private_key} | wg pubkey', shell=True).decode('utf-8').strip()
|
|
|
|
|
pre_shared_key = subprocess.check_output('wg genpsk', shell=True).decode('utf-8').strip()
|
|
|
|
|
|
|
|
|
|
address = wireguard_instance.address
|
|
|
|
|
netmask = wireguard_instance.netmask
|
|
|
|
|
cidr_network = f"{address}/{netmask}"
|
|
|
|
|
network = ipaddress.ip_network(cidr_network, strict=False)
|
|
|
|
|
|
|
|
|
|
# the code below can be an issue for larger networks, for now it's fine, but it should be optimized in the future
|
|
|
|
|
used_ips = set(WireGuardInstance.objects.all().values_list('address', flat=True)) | \
|
|
|
|
|
set(PeerAllowedIP.objects.filter(config_file='server', priority=0).values_list('allowed_ip', flat=True))
|
|
|
|
|
|
|
|
|
|
free_ip_address = None
|
|
|
|
|
for ip in network.hosts():
|
|
|
|
|
if str(ip) not in used_ips:
|
|
|
|
|
free_ip_address = str(ip)
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
default_routing_template = RoutingTemplate.objects.filter(wireguard_instance=wireguard_instance, default_template=True).first()
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
'name': '',
|
|
|
|
|
'public_key': public_key,
|
|
|
|
|
'pre_shared_key': pre_shared_key,
|
|
|
|
|
'persistent_keepalive': 25,
|
|
|
|
|
'private_key': private_key,
|
|
|
|
|
'wireguard_instance': wireguard_instance,
|
|
|
|
|
'allowed_ip': free_ip_address,
|
|
|
|
|
'default_routing_template': default_routing_template,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2026-02-10 18:26:49 -03:00
|
|
|
def func_create_new_peer(
|
|
|
|
|
wireguard_instance: WireGuardInstance,
|
|
|
|
|
overrides: Optional[Dict[str, Any]] = None,
|
|
|
|
|
) -> Tuple[Optional[Peer], str]:
|
|
|
|
|
"""
|
|
|
|
|
Creates a new Peer using generate_peer_default(), allowing optional overrides.
|
|
|
|
|
|
|
|
|
|
Supported override keys:
|
|
|
|
|
- name
|
|
|
|
|
- public_key
|
|
|
|
|
- pre_shared_key
|
|
|
|
|
- persistent_keepalive
|
|
|
|
|
- private_key
|
|
|
|
|
- allowed_ip
|
|
|
|
|
- default_routing_template
|
|
|
|
|
- allowed_ip_netmask (defaults to 32)
|
|
|
|
|
"""
|
2026-02-10 16:41:02 -03:00
|
|
|
new_peer_data = generate_peer_default(wireguard_instance)
|
|
|
|
|
|
2026-02-10 18:26:49 -03:00
|
|
|
overrides = overrides or {}
|
|
|
|
|
|
|
|
|
|
# avoid accidental mismatch / footguns
|
|
|
|
|
forbidden_keys = {'wireguard_instance'}
|
|
|
|
|
for k in forbidden_keys:
|
|
|
|
|
if k in overrides:
|
|
|
|
|
raise ValueError(f'Override not allowed: {k}')
|
|
|
|
|
|
|
|
|
|
# apply overrides last
|
|
|
|
|
new_peer_data.update(overrides)
|
|
|
|
|
|
|
|
|
|
allowed_ip_netmask = int(new_peer_data.get('allowed_ip_netmask', 32) or 32)
|
|
|
|
|
|
|
|
|
|
if new_peer_data.get('allowed_ip'):
|
2026-02-10 16:41:02 -03:00
|
|
|
new_peer = Peer.objects.create(
|
2026-02-10 18:26:49 -03:00
|
|
|
name=new_peer_data.get('name', ''),
|
2026-02-10 16:41:02 -03:00
|
|
|
public_key=new_peer_data['public_key'],
|
|
|
|
|
pre_shared_key=new_peer_data['pre_shared_key'],
|
2026-02-10 18:26:49 -03:00
|
|
|
persistent_keepalive=new_peer_data.get('persistent_keepalive', 25),
|
|
|
|
|
private_key=new_peer_data.get('private_key'),
|
2026-02-10 16:41:02 -03:00
|
|
|
wireguard_instance=wireguard_instance,
|
2026-02-10 18:26:49 -03:00
|
|
|
routing_template=new_peer_data.get('default_routing_template'),
|
2026-02-10 16:41:02 -03:00
|
|
|
)
|
2026-02-10 18:26:49 -03:00
|
|
|
|
2026-02-10 16:41:02 -03:00
|
|
|
PeerAllowedIP.objects.create(
|
|
|
|
|
config_file='server',
|
|
|
|
|
peer=new_peer,
|
|
|
|
|
allowed_ip=new_peer_data['allowed_ip'],
|
|
|
|
|
priority=0,
|
2026-02-10 18:26:49 -03:00
|
|
|
netmask=allowed_ip_netmask,
|
2026-02-10 16:41:02 -03:00
|
|
|
)
|
2026-02-10 18:26:49 -03:00
|
|
|
|
|
|
|
|
message = str(_('Peer created|Peer created successfully.'))
|
2026-02-10 16:41:02 -03:00
|
|
|
return new_peer, message
|
2026-02-10 18:26:49 -03:00
|
|
|
|
|
|
|
|
message = str(_('Error creating peer|No available IP address found for peer creation.'))
|
|
|
|
|
return None, message
|