From 0bbe91bec3ee8fe4fa0d8dfa60c4ae7d80402de5 Mon Sep 17 00:00:00 2001 From: Kai Waggeling Date: Sat, 6 Dec 2025 20:04:11 +0100 Subject: [PATCH] improved Database & Models --- .gitignore | 4 + docker/Dockerfile | 46 ++++ docker/nftables.conf | 28 +++ docker/start.sh | 35 +++ docker/supervisor.conf | 14 ++ docs/database.png | Bin 0 -> 87314 bytes lib/generator/wg_config.mjs | 15 ++ lib/models.mjs | 465 ++++++++++++++++++++++++++++++++++++ lib/nftables/config.mjs | 40 ++++ lib/wireguard/config.mjs | 34 +++ lib/wireguard/process.mjs | 45 ++++ master.mjs | 26 ++ package.json | 21 ++ routes/api/v1/routes.mjs | 54 +++++ templates/nftables.ejs | 60 +++++ templates/wg_client.ejs | 11 + templates/wg_server.ejs | 14 ++ webserver.mjs | 44 ++++ 18 files changed, 956 insertions(+) create mode 100644 .gitignore create mode 100644 docker/Dockerfile create mode 100644 docker/nftables.conf create mode 100644 docker/start.sh create mode 100644 docker/supervisor.conf create mode 100644 docs/database.png create mode 100644 lib/generator/wg_config.mjs create mode 100644 lib/models.mjs create mode 100644 lib/nftables/config.mjs create mode 100644 lib/wireguard/config.mjs create mode 100644 lib/wireguard/process.mjs create mode 100644 master.mjs create mode 100644 package.json create mode 100644 routes/api/v1/routes.mjs create mode 100644 templates/nftables.ejs create mode 100644 templates/wg_client.ejs create mode 100644 templates/wg_server.ejs create mode 100644 webserver.mjs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a6d9f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +data/* +*test*.mjs +package-lock.json \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..347707b --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,46 @@ +FROM alpine:latest + +# ---------------------------------------- +# Install required packages +# ---------------------------------------- +RUN apk update && apk add --no-cache \ + wireguard-tools \ + wireguard-virt \ + nftables \ + supervisor \ + nodejs \ + npm \ + curl \ + bash + +# ---------------------------------------- +# Setup nftables base config +# You will manage rules from Node.js or mounted config +# ---------------------------------------- +RUN mkdir -p /etc/nftables +COPY nftables.conf /etc/nftables/nftables.conf + +# ---------------------------------------- +# Application +# ---------------------------------------- +WORKDIR /app + +COPY ../package.json ./ +RUN npm install --production +COPY .. . + +# ---------------------------------------- +# Supervisor config +# ---------------------------------------- +COPY supervisor.conf /etc/ +COPY start.sh /usr/local/bin/start.sh +RUN chmod +x /usr/local/bin/start.sh + +# ---------------------------------------- +# Volumes +# ---------------------------------------- +VOLUME ["/etc/wireguard", "/etc/nftables", "/app/data"] + +EXPOSE 3000 + +CMD ["/usr/local/bin/start.sh"] \ No newline at end of file diff --git a/docker/nftables.conf b/docker/nftables.conf new file mode 100644 index 0000000..4cd76ff --- /dev/null +++ b/docker/nftables.conf @@ -0,0 +1,28 @@ +#!/usr/sbin/nft -f + +flush ruleset + +table inet filter { + chain input { + type filter hook input priority 0; + + # Accept localhost + iif lo accept + + # Accept WireGuard traffic + udp dport 51820 accept + + # Allow traffic from wg0 only if defined later (allowlist approach) + iif wg0 drop + } + + chain forward { + type filter hook forward priority 0; + # Default deny + drop + } + + chain output { + type filter hook output priority 0; + } +} \ No newline at end of file diff --git a/docker/start.sh b/docker/start.sh new file mode 100644 index 0000000..5ad2f7b --- /dev/null +++ b/docker/start.sh @@ -0,0 +1,35 @@ +#!/bin/sh +set -e + +# -------------------------------------------- +# Ensure /etc/wireguard exists +# -------------------------------------------- +if [ ! -d /etc/wireguard ]; then + echo "WARN: /etc/wireguard does not exist. Creating it..." + mkdir -p /etc/wireguard +fi + +# Default config für WireGuard +if [ ! -f /etc/wireguard/wg0.conf ]; then + echo "INFO: Installing default WireGuard config..." + cp /defaults/wg0.conf /etc/wireguard/wg0.conf +fi + +# -------------------------------------------- +# Ensure /etc/nftables exists +# -------------------------------------------- +if [ ! -d /etc/nftables ]; then + echo "WARN: /etc/nftables does not exist. Creating it..." + mkdir -p /etc/nftables +fi + +# default nftables.conf +if [ ! -f /etc/nftables/nftables.conf ]; then + echo "INFO: Installing default nftables.conf..." + cp /defaults/nftables.conf /etc/nftables/nftables.conf +fi + +# -------------------------------------------- +# Start Supervisor +# -------------------------------------------- +exec /usr/bin/supervisord -c /etc/supervisor.conf diff --git a/docker/supervisor.conf b/docker/supervisor.conf new file mode 100644 index 0000000..33078d7 --- /dev/null +++ b/docker/supervisor.conf @@ -0,0 +1,14 @@ +[program:nftables] +command=nft -f /etc/nftables/nftables.conf +priority=5 +autostart=true +autorestart=true +stdout_logfile=/dev/fd/1 +stderr_logfile=/dev/fd/2 + +[program:manager] +command=node /app/master.mjs +autostart=true +autorestart=true +stdout_logfile=/dev/fd/1 +stderr_logfile=/dev/fd/2 \ No newline at end of file diff --git a/docs/database.png b/docs/database.png new file mode 100644 index 0000000000000000000000000000000000000000..f48a78ceca1f0c09d4c64eeceb1d3309e76d7bdf GIT binary patch literal 87314 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
TAzeRvCjU~72 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

Y2|m`O!g%F!hE>JDtDhM`bUl--De%!N+`;7pYcD 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Ƃ=e9B zl!R1hYRFQx!+5!|=rkE5P-BV&*{J&V1y1?f@|wwlaE7{6Zegmfh=YC{4%-F# zEMV2>O<3uF~uwcw2fj=8eR7U-N);h<*=y#DA z7$&^y`Yu)R#B1RJgoz4WY1V+iDFI61p5BL#H+BBOOa-e3_-P{prJxw97(Ie|?7Aymg?|NG^cb!p z&y3OLKwb;@NdC~M5~dry(-JJX3w1UGP9UzXN-s7>XYavFw!!d8SLA)!QNYD;gmIy> z$=2~8qG~ZQV=;c&jQCY7=J@G~|4_)JLVgR4roU?S<8qc}fLsF6EsZ0L{P^v-0 literal 0 HcmV?d00001 diff --git a/lib/generator/wg_config.mjs b/lib/generator/wg_config.mjs new file mode 100644 index 0000000..7e19e68 --- /dev/null +++ b/lib/generator/wg_config.mjs @@ -0,0 +1,15 @@ +import { + instance, + peer, + address +} from "../models.mjs"; + + +export async function generateWireguardServerConfig(interfaceName) { + +} + + +export async function generateWireguardClientConfig(interfaceName) { + +} \ No newline at end of file diff --git a/lib/models.mjs b/lib/models.mjs new file mode 100644 index 0000000..98e4d92 --- /dev/null +++ b/lib/models.mjs @@ -0,0 +1,465 @@ +import { + object, + array, + string, + number, + enums, + boolean, + literal, + optional, + dynamic, + nullable, + defaulted, + union, + size, + create, + assert, + define, +} from "superstruct"; +import { Database } from "all.db"; +import crypto from "node:crypto"; +import { + ipv4, + ipv6 +} from "cidr-block"; +import path from "node:path"; +import { EventEmitter } from "node:events"; + + +class ObjectModel { + #modelName; + #modelStruct; + #modelStore; + #dynRef = {}; + #hooks = new EventEmitter(); + + constructor(settings) { + this.#modelName = settings.name; + this.#modelStruct = settings.model; + this.#modelStore = new Database({ + dataPath: path.join(process.cwd(), 'data/database', `${settings.name}.json`) + }); + + if (settings.hooks) { + Object.entries(settings.hooks).forEach(([eventName, eventFunction]) => { + this.on(eventName, eventFunction); + }) + } + + this.#dynRef.refOne = dynamic((objectId, context) => { + let permittedObjIds = Object.values(this.getAll()).map(item => item.id); + return enums(permittedObjIds); + }); + + this.#dynRef.refMany = dynamic((objectId, context) => { + let permittedObjIds = Object.values(this.getAll()).map(item => item.id); + return array( + enums(permittedObjIds) + ); + }); + + if (settings.dynRef instanceof Object) { + this.#dynRef = Object.assign(this.#dynRef, settings.dynRef) + } + } + + complete(data) { + try { + let result = create(data, this.#modelStruct); + return result; + } catch (error) { + throw new Error(`error completing ${this.#modelName}: ` + error.message); + } + } + validate(data) { + try { + assert(data, this.#modelStruct); + return data; + } catch (error) { + throw new Error(`error validating ${this.#modelName}: ` + error.message); + } + } + + getAll() { + return this.#modelStore.getAll(); + } + getById(objectId) { + return this.#modelStore.get(objectId); + } + create(objectData) { + // try { + const newData = this.validate( + this.complete(objectData) + ); + + if (this.#modelStore.exists(newData.id)) { + throw new Error(`failed create ${this.#modelName} with ID ${newData.id}. already existing in database.`); + } + + this.#hooks.emit('beforeCreate', null, newData); + this.#modelStore.set(newData.id, newData); + this.#hooks.emit('afterCreate', newData); + return newData; + // } catch (error) { + // throw error; + // } + } + update(objectData) { + // try { + const newData = this.validate( + this.complete(objectData) + ); + const oldData = this.getById(newData.id) + + if (!oldData) { + throw new Error(`failed update ${this.#modelName} with ID ${newData.id}. not existing in database.`); + } + + this.#hooks.emit('beforeUpdate', oldData, newData); + this.#modelStore.set(newData.id, newData); + this.#hooks.emit('afterUpdate', oldData, newData); + return newData; + // } catch (error) { + // throw error; + // } + } + delete(objectId) { + // try { + const oldData = this.getById(objectId); + + if (!oldData) { + throw new Error(`failed delete ${this.#modelName} with ID ${newData.id}. not existing in database.`); + } + this.#hooks.emit('beforeDelete', oldData, null); + this.#modelStore.delete(oldData.id); + this.#hooks.emit('afterDelete', oldData, null); + return oldData; + // } catch (error) { + // throw error; + // } + } + has(objectId) { + return this.#modelStore.has(objectId); + } + get dynRef() { + return this.#dynRef; + } + + on(eventName, eventFunction) { + this.#hooks.on(eventName, eventFunction); + } +} + + +// - --- --- --- --- --- --- --- --- --- --- --- --- +// +// Custom Checks +// +// - --- --- --- --- --- --- --- --- --- --- --- --- + +const ipv4Address = define('ipv4Address', (value) => { + return ipv4.isValidAddress(value); +}); + +const ipv4Cidr = define('ipv4Cidr', (value) => { + console.log(value); + console.log(ipv4.isValidCIDR(value)); + + return ipv4.isValidCIDR(value); +}); + + +// - --- --- --- --- --- --- --- --- --- --- --- --- +// +// Base Models +// +// - --- --- --- --- --- --- --- --- --- --- --- --- + +// Authorisation Provider Model +export const authProvider = new ObjectModel({ + name: 'authProvider', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + name: string(), + login_text: string(), + type: enums(["oauth2"]), + settings: dynamic((value, context) => { + switch (value.type) { + case "oauth2": + return object({ + client_id: string(), + client_secret: string(), + authorize_url: string(), + token_url: string(), + user_info_url: string(), + redirect_url: string(), + scope: array(string()) + }); + } + return object({}); + }) + }) +}); + +// User Model +export const user = new ObjectModel({ + name: 'user', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + external_id: string(), + provider: string(), + displayName: string(), + email: string() + }) +}); + +// User Group Model +export const userGroup = new ObjectModel({ + name: 'userGroup', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + name: string(), + comment: defaulted(string(), ''), + members: user.dynRef.refMany + }) +}); + + +// - --- --- --- --- --- --- --- --- --- --- --- --- +// +// Wireguard Models +// +// - --- --- --- --- --- --- --- --- --- --- --- --- + +// Wireguard Interface Model +export const wireguardInterface = new ObjectModel({ + name: 'wireguardInterface', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + name: size(string(), 1, 128), + comment: defaulted(size(string(), 0, 256), ''), + enabled: defaulted(boolean(), true), + privateKey: string(), + publicKey: string(), + ifName: string(), + ifAddress: ipv4Cidr, + listenPort: number(), + endpoint: string(), + dnsServer: nullable(ipv4Address) + }) +}); + +// Wireguard Peer Model +export const wireguardPeer = new ObjectModel({ + name: 'wireguardPeer', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + name: size(string(), 1, 128), + comment: defaulted(size(string(), 0, 256), ''), + interface: wireguardInterface.dynRef.refOne, + enabled: defaulted(boolean(), true), + + privateKey: string(), + publicKey: string(), + presharedKey: string(), + ifAddress: ipv4Cidr, + keepalive: size(defaulted(number(), 30), 1, 300), + }) +}); + +// - --- --- --- --- --- --- --- --- --- --- --- --- +// +// CMDB Models +// +// - --- --- --- --- --- --- --- --- --- --- --- --- + +// Address Object Model +export const addressObject = new ObjectModel({ + name: 'addressObject', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + name: size(string(), 1, 128), + comment: defaulted(size(string(), 0, 256), ''), + elements: array(union([ + object({ + type: literal('ipmask'), + ipmask: ipv4Address + }), + object({ + type: literal('fqdn'), + fqdn: string(), + result: nullable(defaulted(string(), null)) + }), + object({ + type: literal('peer'), + peer: wireguardPeer.dynRef.refOne + }) + ])), + members: dynamic((memberList, context) => { + // allow many values from list of Peer IDs + // - exclude objects that contain members (loop prevention) + // - exclude self (loop prevention) + let permittedAdressObjects = Object.values(addressObject.getAll()) + .filter(object => object.members.length == 0) + .filter(object => object.id != context.id) + .map(item => item.id); + + // return array from here to reduce Database reads + return array(enums(permittedAdressObjects)); + }), + }) +}); + +// Service Object Model +export const serviceObject = new ObjectModel({ + name: 'serviceObject', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + name: size(string(), 1, 128), + comment: defaulted(size(string(), 0, 256), ''), + elements: array(union([ + object({ + type: literal('tcp'), + port: number() + }), + object({ + type: literal('udp'), + port: number() + }), + object({ + type: literal('icmp'), + icmpType: enums([ + "echo-reply", + "destination-unreachable", + "source-quench", + "redirect", + "echo-request", + "time-exceeded", + "parameter-problem", + "timestamp-request", + "timestamp-reply", + "info-request", + "info-reply", + "address-mask-request", + "address-mask-reply", + "router-advertisement", + "router-solicitation" + ]) + }), + object({ + type: literal('esp'), + port: number() + }) + ])) + }) +}); + + +// - --- --- --- --- --- --- --- --- --- --- --- --- +// +// Firewall Policy Models +// +// - --- --- --- --- --- --- --- --- --- --- --- --- + +export const accessPolicy = new ObjectModel({ + name: 'accessPolicy', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + name: size(string(), 1, 128), + comment: defaulted(size(string(), 0, 256), ''), + enabled: defaulted(boolean(), true), + + srcAddr: addressObject.dynRef.refMany, + dstAddr: addressObject.dynRef.refMany, + services: serviceObject.dynRef.refMany, + }) +}); + +export const natPolicy = new ObjectModel({ + name: 'natPolicy', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + name: size(string(), 1, 128), + comment: defaulted(size(string(), 0, 256), ''), + enabled: defaulted(boolean(), true), + + natType: enums(['snat', 'dnat', ' masquerade']), + srcAddress: string(), + dstAddress: string(), + dnatPort: optional(number()), // Ziel Port für DNAT + }) +}); + + +// - --- --- --- --- --- --- --- --- --- --- --- --- +// +// Access Control Models +// +// - --- --- --- --- --- --- --- --- --- --- --- --- + +export const configToken = new ObjectModel({ + name: 'configToken', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + token: defaulted(string(), () => { + return crypto.randomBytes(32).toString('hex'); + }), + peer: string(), + name: string() + }) +}); + +export const apiToken = new ObjectModel({ + name: 'apiToken', + model: object({ + id: defaulted(string(), () => { + return crypto.randomUUID(); + }), + token: defaulted(string(), () => { + return crypto.randomBytes(32).toString('hex'); + }), + name: string() + }), + hooks: { + beforeCreate: (oldData, newData) => { + console.log("before API Token created"); + }, + afterCreate: (oldData, newData) => { + console.log("after API Token created"); + } + } +}); + + +export default { + wireguardInterface, + wireguardPeer, + addressObject, + authProvider, + user, + userGroup, + accessPolicy, + natPolicy, + configToken, + apiToken +} \ No newline at end of file diff --git a/lib/nftables/config.mjs b/lib/nftables/config.mjs new file mode 100644 index 0000000..9ee0b33 --- /dev/null +++ b/lib/nftables/config.mjs @@ -0,0 +1,40 @@ +import { + wireguardInterface, + wireguardPeer, + addressObject, + accessPolicy, + natPolicy +} from "../models.mjs"; + +import path from "node:path"; +import file from "node:fs"; +import ejs from "ejs"; + + +const configTemplatePath = path.join(process.cwd(), 'templates', 'nftables.ejs'); + + +export async function generateNftablesConfig(interfaceId) { + const ifData = Object.values(wireguardInterface.getAll()).find(fi => fi.id == interfaceId); + const addressObjects = addressObject.getAll(); + const accessPolicies = accessPolicy.getAll(); + const natPolicies = natPolicy.getAll(); + + const configData = { + interface: ifData, + peerList + }; + + const configContent = await ejs.renderFile( + configTemplatePath, + configData, + { + async: true + } + ); + + file.writeFileSync( + path.join(process.cwd(), 'data', 'nftables', `${ifData.ifName}.conf`), + configContent + ) +} \ No newline at end of file diff --git a/lib/wireguard/config.mjs b/lib/wireguard/config.mjs new file mode 100644 index 0000000..c2ab708 --- /dev/null +++ b/lib/wireguard/config.mjs @@ -0,0 +1,34 @@ +import { + wireguardInterface, + wireguardPeer +} from "../models.mjs"; + +import path from "node:path"; +import file from "node:fs"; +import ejs from "ejs"; + + +const serverTemplatePath = path.join(process.cwd(), 'templates', 'wg_server.ejs'); +const clientTemplatePath = path.join(process.cwd(), 'templates', 'wg_client.ejs'); + + +export async function generateInterfaceConfig(interfaceId) { + const ifData = Object.values(wireguardInterface.getAll()).find(fi => fi.id == interfaceId); + const peerList = Object.values(wireguardPeer.getAll()).filter(fi => fi.interface == interfaceId); + + let configData = await ejs.renderFile( + serverTemplatePath, + { + interface: ifData, + peerList + }, + { + async: true + } + ); + + file.writeFileSync( + path.join(process.cwd(), 'data', 'wireguard', `${ifData.ifName}.conf`), + configData + ) +} \ No newline at end of file diff --git a/lib/wireguard/process.mjs b/lib/wireguard/process.mjs new file mode 100644 index 0000000..8a44e25 --- /dev/null +++ b/lib/wireguard/process.mjs @@ -0,0 +1,45 @@ +import { + execSync as execCommand +} from "node:child_process"; + +import { + wireguardInterface +} from "../models.mjs"; + + + +export async function startWireguardInterface(interfaceid) { + try { + const ifData = wireguardInterface.getById(interfaceid); + const ifLink = getInterfaceLink(ifData.ifName); + + if (ifLink.operstate == 'UP') { + console.log(`Reloading interface ${ifData.ifName}`); + console.log(`» reloading interface ${ifData.ifName}`); + execCommand(`wg-quick up ${ifData.ifName}`, { stdio: 'inherit' }); + console.log(`✓ reloaded interface ${ifData.ifName}`); + } else { + console.log(`» starting interface ${ifData.ifName}`); + execCommand(`wg-quick up ${ifData.ifName}`, { stdio: 'inherit' }); + console.log(`✓ started interface ${ifData.ifName}`); + } + } catch (error) { + console.error(`✕ failed to start interface ${iface}:`, error.message); + } +} + + +export async function getInterfaceLink(ifName) { + try { + let result = JSON.parse( + execCommand(`ip -j link show`, { stdio: 'inherit' }) + ).find(linkResult => linkResult.ifname == ifName); + + if (!result) { return undefined; } + + return result; + } catch (error) { + console.error(`failed to get interface link for ${ifName}:`, error.message); + return undefined; + } +} \ No newline at end of file diff --git a/master.mjs b/master.mjs new file mode 100644 index 0000000..6c0fab0 --- /dev/null +++ b/master.mjs @@ -0,0 +1,26 @@ +import path from "path"; +import fs from "fs"; +import "./webserver.mjs"; +import { + apiToken, + wireguardInterface +} from "./lib/models.mjs"; + + +// create database directory if not exists +const databaseDir = path.join(process.cwd(), 'data', 'database'); +if (!fs.existsSync(databaseDir)) { + fs.mkdirSync(databaseDir, { recursive: true }); +} + +// create database directory if not exists +const wgConfigDir = path.join(process.cwd(), 'data', 'wireguard'); +if (!fs.existsSync(wgConfigDir)) { + fs.mkdirSync(wgConfigDir, { recursive: true }); +} + +// create database directory if not exists +const nftConfigDir = path.join(process.cwd(), 'data', 'nftables'); +if (!fs.existsSync(nftConfigDir)) { + fs.mkdirSync(nftConfigDir, { recursive: true }); +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..f2d5f0d --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "wireguard-manager", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@fastify/autoload": "^6.3.1", + "@fastify/view": "^11.1.1", + "all.db": "^0.3.2", + "cidr-block": "^2.1.1", + "ejs": "^3.1.10", + "fastify": "^5.6.2", + "superstruct": "^2.0.2" + } +} diff --git a/routes/api/v1/routes.mjs b/routes/api/v1/routes.mjs new file mode 100644 index 0000000..9af25de --- /dev/null +++ b/routes/api/v1/routes.mjs @@ -0,0 +1,54 @@ +import models from "../../../lib/models.mjs"; + + +export default async function (fastify, opts) { + fastify.register(async function secureApiContext(secureApiScope) { + // check API token + secureApiScope.addHook('onRequest', async (request, reply) => { + if (!request.headers.authorization) { + reply.code(401).send({ error: 'Unauthorized: missing Authorization header' }); + return; + } + + const token = Object.values(await models.apiToken.getAll()).find(t => t.token === request.headers.authorization.replace('Bearer ', '')); + + if (!token) { + reply.code(403).send({ error: 'Forbidden: invalid Token' }); + return; + } + }); + + // check requested Model Type + secureApiScope.addHook('onRequest', async (request, reply) => { + if (!request.params.modelType) { + reply.code(400).send({ error: 'Bad Request: missing Model Type' }); + } + if (!models[request.params.modelType]) { + reply.code(404).send({ error: 'Unavailable: requested Model is not available' }); + } + }); + + secureApiScope.get("/:modelType", async function (request, reply) { + const objects = await models[request.params.modelType].getAll(); + reply.send(objects); + }); + secureApiScope.post("/:modelType", async function (request, reply) { + try { + const newObject = await models[request.params.modelType].create(request.body); + reply.send(newObject); + } catch (error) { + reply.code(500).send({ error: error.message }); + } + }); + secureApiScope.get("/:modelType/:resourceId", async function (request, reply) { + const object = await models[request.params.modelType].getById(request.params.resourceId); + if (object) { + reply.send(object); + } else { + reply.code(404).send({ error: 'Unavailable: requested Object is not available' }); + } + }); + secureApiScope.patch("/:modelType/:resourceId", async function (request, reply) { }); + secureApiScope.delete("/:modelType/:resourceId", async function (request, reply) { }); + }); +} \ No newline at end of file diff --git a/templates/nftables.ejs b/templates/nftables.ejs new file mode 100644 index 0000000..fdb1968 --- /dev/null +++ b/templates/nftables.ejs @@ -0,0 +1,60 @@ +#!/usr/sbin/nft -f + +# Lösche alte Tabelle +flush ruleset + +table inet <%= interface.ifName %> { + + <% addressGroupList.forEach((addressGroup) => { %> + set addressGroup_<%= addressGroup.name %> { + type ipv4_addr + flags interval + elements = { <%= addressGroup.addressList.join(", ") %> } + } + <% }) %> + + <% addressGroupList.forEach((addressGroup) => { %> + set addressGroup_<%= addressGroup.name %> { + type ipv4_addr + flags interval + elements = { <%= addressGroup.addressList.join(", ") %> } + } + <% }) %> + + chain input_<%= interface.ifName %> { + type filter hook input priority 0; policy drop; + + # Traffic vom Interface akzeptieren + iif "<%= interface %>" tcp dport { 22, 53 } accept + iif "<%= interface %>" udp dport 53 accept + iif "<%= interface %>" icmp type echo-request accept + iif "<%= interface %>" ip saddr @allowed_sources_<%= instanceId %> counter accept + } + + chain forward_<%= interface.ifName %> { + type filter hook forward priority 0; policy drop; + + # Eingehende Pakete von erlaubten IPs weiterleiten + iif "<%= interface %>" ip saddr @allowed_sources_<%= instanceId %> ip daddr @allowed_destinations_<%= instanceId %> accept + + # Rückläufige Antworten zulassen (established connections) + oif "<%= interface %>" ip saddr @allowed_destinations_<%= instanceId %> ip daddr @allowed_sources_<%= instanceId %> ct state established accept + } + + chain output_<%= interface.ifName %> { + type filter hook output priority 0; policy accept; + + # Host -> WG Interface + oif "<%= interface %>" ip daddr @allowed_destinations_<%= instanceId %> accept + } + + chain postrouting_<%= interface.ifName %> { + type route hook output priority 100; policy accept; + ip saddr <%= localSubnet %> oif "<%= outboundInterface %>" masquerade + } + +} +<% accessRuleList.forEach((accessRule) => { %> + <%= accessRule.proto %> dport <%= accessRule.dstport %> ip saddr + # Description: <%= accessRule.description %> +<% }) %> diff --git a/templates/wg_client.ejs b/templates/wg_client.ejs new file mode 100644 index 0000000..04e575e --- /dev/null +++ b/templates/wg_client.ejs @@ -0,0 +1,11 @@ +[Interface] +PrivateKey = <%= client.PrivateKey %> +Address = <%= client.allowedIps %> +DNS = 1.1.1.1 + +[Peer] +PublicKey = <%= server.publicKey %> +PresharedKey = <%= client.presharedKey %> +Endpoint = <%= server.endpoint %>:<%= server.listenPort %> +AllowedIPs = 0.0.0.0/0 +PersistentKeepalive = <%= client.allowedIps %> \ No newline at end of file diff --git a/templates/wg_server.ejs b/templates/wg_server.ejs new file mode 100644 index 0000000..db59bd0 --- /dev/null +++ b/templates/wg_server.ejs @@ -0,0 +1,14 @@ +[Interface] +Address = <%= interface.ifAddress %> +<% if (interface.dnsServer) { %> +DNS = <%= interface.dnsServer %> +<% } %> +PrivateKey = <%= interface.privateKey %> +ListenPort = <%= interface.listenPort %> + +<% peerList.forEach((peer) => { %> +[Peer] +# <%= peer.name %> +PublicKey = <%= peer.publicKey %> + +<% }) %> diff --git a/webserver.mjs b/webserver.mjs new file mode 100644 index 0000000..4ce4afa --- /dev/null +++ b/webserver.mjs @@ -0,0 +1,44 @@ +import fastify from "fastify"; +import fastifyView from '@fastify/view'; +import autoLoad from "@fastify/autoload"; +import path from "node:path"; +import ejs from "ejs"; + + +const webServer = fastify({ logger: false }); + +// EJS-Renderer +webServer.register(fastifyView, { + root: path.join(process.cwd(), 'templates'), + engine: { + ejs + } +}); + +// file based route loader +webServer.register(autoLoad, { + dir: path.join(process.cwd(), "routes"), + dirNameRoutePrefix: true, + routeParams: true +}); + +// load plugins +// import registerSSOPlugin from './plugins/sso.mjs'; +// await registerSSOPlugin(webServer) + +// error handling +webServer.setErrorHandler((error, request, reply) => { + // gezielt Fehler anzeigen, aber nicht alles loggen + console.error("! Fehler in Route:", request.url); + console.error(error); + + reply.status(500).send({ error: "Internal Server Error" }); +}); + +// start server +webServer.listen({ port: 3000 }, (err) => { + if (err) { + console.error(err); + process.exit(1); + } +});