[vpn] make a vpn creat-able!

[15:40] line:~% http -a nicoschottelius:$(pass ungleich.ch/nico.schottelius@ungleich.ch)  http://localhost:8000/net/vpn/ network_size=48  wireguard_public_key=$(wg genkey | wg pubkey)
HTTP/1.1 201 Created
Allow: GET, POST, HEAD, OPTIONS
Content-Length: 206
Content-Type: application/json
Date: Sun, 12 Apr 2020 13:40:26 GMT
Server: WSGIServer/0.2 CPython/3.7.3
Vary: Accept
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "extra_data": null,
    "network": "2a0a:e5c1:203::",
    "order": null,
    "owner": 30,
    "status": "PENDING",
    "uuid": "8f977a8f-e06a-4346-94ae-8f525df58b7b",
    "wireguard_public_key": "JvCuUTZHm9unasJkGsLKN0Bf/hu6ZSIv7dnIGPyJ6xA="
}
This commit is contained in:
Nico Schottelius 2020-04-12 15:40:39 +02:00
commit 85b4d70592
4 changed files with 100 additions and 50 deletions

View file

@ -47,11 +47,15 @@ class VPNPool(UncloudModel):
maximum_networks = 2^(24-8)
"""
return 2**(subnetwork_size - network_size)
return 2**(self.subnetwork_size - self.network_size)
@property
def used_networks(self):
return self.vpnnetworkreservation_set.objects.filter(vpnpool=self, status='used')
return self.vpnnetworkreservation_set.filter(vpnpool=self, status='used')
@property
def free_networks(self):
return self.vpnnetworkreservation_set.filter(vpnpool=self, status='free')
@property
def num_used_networks(self):
@ -59,27 +63,18 @@ class VPNPool(UncloudModel):
@property
def num_free_networks(self):
return self.num_maximum_networks - self.num_used_networks
return self.num_maximum_networks - self.num_used_networks + len(self.free_networks)
@property
def next_free_network(self):
free_net = self.vpnnetworkreservation_set.objects.filter(vpnpool=self,
status='free')
used_net = self.vpnnetworkreservation_set.objects.filter(vpnpool=self,
status='used')
this_net = ipaddress.ip_network("{}/{}".format(
self.network, self.network_size))
if num_free_networks == 0:
if self.num_free_networks == 0:
# FIXME: use right exception
raise Exception("No free networks")
if len(free_net) > 0:
return free_net[0].address
if len(self.free_networks) > 0:
return self.free_networks[0].address
if len(used_net) > 0:
if len(self.used_networks) > 0:
"""
sample:
@ -89,7 +84,7 @@ class VPNPool(UncloudModel):
next:
"""
last_net = ipaddress.ip_network(self.used_networks.last())
last_net = ipaddress.ip_network(self.used_networks.last().address)
last_net_ip = last_net[0]
if last_net_ip.version == 6:
@ -99,7 +94,52 @@ class VPNPool(UncloudModel):
next_net_ip = last_net_ip + offset_to_next
return next_net_ip
return str(next_net_ip)
else:
# first network to be created
return self.network
@property
def wireguard_config_filename(self):
return '/etc/wireguard/{}.conf'.format(self.network)
@property
def wireguard_config(self):
wireguard_config = [
"""
[Interface]
ListenPort = 51820
PrivateKey = {privatekey}
""".format(privatekey=self.wireguard_private_key) ]
peers = []
for vpnnetwork in self.vpnnetworkreservation_set:
public_key = vpnnetwork.wireguard_public_key
peer_network = "{}/{}".format(vpnnetwork.address, self.subnetwork_size)
peers.append("""
[Peer]
PublicKey = {public_key}
AllowedIPs = {peer_network}
""")
wireguard_config.extend(peers)
return "\n".join(wireguard_config)
def configure_wireguard_vpnserver(self):
"""
This method is designed to run as a celery task and should
not be called directly from the web
"""
# subprocess, ssh
pass
@ -109,6 +149,7 @@ class VPNNetworkReservation(UncloudModel):
"""
vpnpool = models.ForeignKey(VPNPool,
on_delete=models.CASCADE)
address = models.GenericIPAddressField(primary_key=True)
status = models.CharField(max_length=256,