You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

146 lines
4.3 KiB

import ipaddress
import itertools
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from starlette.responses import PlainTextResponse
import const
import models
import schemas
import middleware
import db.wireguard
import script.wireguard
router = APIRouter()
def generate_ip_address(server: schemas.WGServer, v6):
if v6:
address_space = set(
itertools.islice(ipaddress.ip_network("fd42:42:42::1/64", strict=False).hosts(), 1, 1024)
)
else:
address_space = set(ipaddress.ip_network(f"{server.address}/{server.subnet}", strict=False).hosts())
occupied_space = set()
# Try add server IP to list.
try:
occupied_space.add(ipaddress.ip_address(server.v6_address if v6 else server.address))
except ValueError:
pass
for p in server.peers:
# Try add peer ip to list.
try:
occupied_space.add(ipaddress.ip_address(p.v6_address if v6 else p.address))
except ValueError as e:
pass # Ignore invalid addresses. These are out of address_space
address_space -= occupied_space
# Select first available address
return str(list(sorted(address_space)).pop(0))
@router.post("/add", response_model=schemas.WGPeer)
def add_peer(
peer_add: schemas.WGPeerConfigAdd,
sess: Session = Depends(middleware.get_db)
):
server = schemas.WGServer(interface=peer_add.server_interface).from_db(sess)
if server is None:
raise HTTPException(500, detail="The server-interface '%s' does not exist!" % peer_add.server_interface)
peer = schemas.WGPeer(server_id=server.id)
if server.v6_address:
peer.v6_address = generate_ip_address(server, v6=True)
peer.address = generate_ip_address(server, v6=False)
# Private public key generation
keys = script.wireguard.generate_keys()
peer.private_key = keys["private_key"]
peer.public_key = keys["public_key"]
# Set 0.0.0.0/0, ::/0 as default allowed ips
peer.allowed_ips = ', '.join(const.PEER_DEFAULT_ALLOWED_IPS)
# Set unnamed
peer.name = "Unnamed" if not peer_add.name else peer_add.name
peer.dns = server.dns
peer.configuration = script.wireguard.generate_config(dict(
peer=peer,
server=server
))
db_peer = models.WGPeer(**peer.dict())
sess.add(db_peer)
sess.commit()
# If server is running. Add peer
if script.wireguard.is_running(server):
script.wireguard.add_peer(server, peer)
# Update server configuration
db.wireguard.server_update_configuration(sess, db_peer.server_id)
return schemas.WGPeer.from_orm(db_peer)
@router.post("/configuration/get_or_add")
def get_or_add_peer_return_config(peer_get: schemas.WGPeerConfigGetByName,
sess: Session = Depends(middleware.get_db)
):
server = sess.query(models.WGServer).filter_by(interface=peer_get.server_interface).one()
peer = sess.query(models.WGPeer).filter_by(name=peer_get.name, server_id=server.id).all()
if not peer:
return add_peer_get_config(schemas.WGPeerConfigAdd(
name=peer_get.name,
server_interface=peer_get.server_interface
), sess=sess)
peer = peer[0]
return PlainTextResponse(peer.configuration)
@router.post("/configuration/add")
def add_peer_get_config(peer_add: schemas.WGPeerConfigAdd,
sess: Session = Depends(middleware.get_db)
):
wg_peer: schemas.WGPeer = add_peer(peer_add, sess)
return PlainTextResponse(wg_peer.configuration)
@router.post("/delete", response_model=schemas.WGPeer)
def delete_peer(
peer: schemas.WGPeer,
sess: Session = Depends(middleware.get_db)
):
server = sess.query(models.WGServer).filter_by(id=peer.server_id).one()
if not db.wireguard.peer_remove(sess, peer):
raise HTTPException(400, detail="Were not able to delete peer %s (%s)" % (peer.name, peer.public_key))
if script.wireguard.is_running(schemas.WGServer(interface=server.interface)):
script.wireguard.remove_peer(server, peer)
return peer
@router.post("/edit")
def edit_peer(
peer: schemas.WGPeer,
sess: Session = Depends(middleware.get_db)
):
peer = db.wireguard.peer_edit(sess, peer)
return peer