mirror of
https://github.com/wireadmin/wireadmin
synced 2025-02-26 05:48:44 +00:00
better code quality and fixes minor-known issues
This commit is contained in:
parent
75013113b0
commit
42bc3dc971
@ -1,8 +1,8 @@
|
|||||||
import { promises } from 'fs';
|
import { accessSync, promises } from 'fs';
|
||||||
|
|
||||||
export async function fsAccess(path: string): Promise<boolean> {
|
export function fsAccess(path: string): boolean {
|
||||||
try {
|
try {
|
||||||
await promises.access(path);
|
accessSync(path);
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -5,7 +5,7 @@ import { resolve } from 'node:path';
|
|||||||
import { fsAccess, fsTouch } from '$lib/fs-extra';
|
import { fsAccess, fsTouch } from '$lib/fs-extra';
|
||||||
|
|
||||||
const LOG_LEVEL = process.env.LOG_LEVEL || 'trace';
|
const LOG_LEVEL = process.env.LOG_LEVEL || 'trace';
|
||||||
const LOG_FILE_PATH = process.env.LOG_FILE_PATH || '/var/vlogs/web.log';
|
const LOG_FILE_PATH = process.env.LOG_FILE_PATH || '/var/vlogs/web';
|
||||||
const LOG_COLORS = process.env.LOG_COLORS || 'true';
|
const LOG_COLORS = process.env.LOG_COLORS || 'true';
|
||||||
|
|
||||||
const prettyStream = pretty({
|
const prettyStream = pretty({
|
||||||
@ -24,6 +24,7 @@ fsTouch(LOG_FILE_PATH)
|
|||||||
.then((ok) => {
|
.then((ok) => {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
logger.warn('Log file is not accessible');
|
logger.warn('Log file is not accessible');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
logger = pino(
|
logger = pino(
|
||||||
{
|
{
|
||||||
@ -37,8 +38,6 @@ fsTouch(LOG_FILE_PATH)
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(console.error);
|
||||||
logger.error(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default logger;
|
export default logger;
|
||||||
|
@ -23,7 +23,7 @@ export default class Shell {
|
|||||||
)}`;
|
)}`;
|
||||||
|
|
||||||
if (safe) {
|
if (safe) {
|
||||||
logger.warn(message);
|
logger.debug(message);
|
||||||
return resolve(stderr);
|
return resolve(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import deepmerge from 'deepmerge';
|
import deepmerge from 'deepmerge';
|
||||||
import SHA256 from 'crypto-js/sha256';
|
|
||||||
import Hex from 'crypto-js/enc-hex';
|
|
||||||
import type { Peer, WgKey, WgServer } from '$lib/typings';
|
import type { Peer, WgKey, WgServer } from '$lib/typings';
|
||||||
import Network from '$lib/network';
|
import Network from '$lib/network';
|
||||||
import Shell from '$lib/shell';
|
import Shell from '$lib/shell';
|
||||||
@ -10,34 +8,62 @@ import { WG_PATH } from '$lib/constants';
|
|||||||
import { client, WG_SEVER_PATH } from '$lib/redis';
|
import { client, WG_SEVER_PATH } from '$lib/redis';
|
||||||
import { dynaJoin, isJson } from '$lib/utils';
|
import { dynaJoin, isJson } from '$lib/utils';
|
||||||
import { getPeerConf } from '$lib/wireguard/utils';
|
import { getPeerConf } from '$lib/wireguard/utils';
|
||||||
|
import logger from '$lib/logger';
|
||||||
|
import { sha256 } from '$lib/hash';
|
||||||
|
import { fsAccess } from '$lib/fs-extra';
|
||||||
|
|
||||||
export class WGServer {
|
export class WGServer {
|
||||||
static async stop(id: string): Promise<boolean> {
|
readonly id: string;
|
||||||
const server = await findServer(id);
|
readonly peers: WGPeers;
|
||||||
if (!server) {
|
|
||||||
console.error('server could not be updated (reason: not exists)');
|
constructor(serverId: string) {
|
||||||
return false;
|
if (!serverId) throw new Error('serverId is required');
|
||||||
|
|
||||||
|
if (!WGServer.exists(serverId)) throw new Error('server does not exists');
|
||||||
|
|
||||||
|
this.id = serverId;
|
||||||
|
this.peers = new WGPeers(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async exists(id: string): Promise<boolean> {
|
||||||
|
const servers = await getServers();
|
||||||
|
return servers.some((s) => s.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
async get(): Promise<WgServer> {
|
||||||
|
if (!fsAccess(WG_PATH)) {
|
||||||
|
fs.mkdirSync(WG_PATH, { recursive: true, mode: 0o600 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const server = await findServer(this.id);
|
||||||
|
if (!server) {
|
||||||
|
throw new Error('server not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fsAccess(resolveConfigPath(server.confId))) {
|
||||||
|
await this.writeConfigFile(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
async stop(): Promise<boolean> {
|
||||||
|
const server = await this.get();
|
||||||
|
|
||||||
if (await Network.checkInterfaceExists(`wg${server.confId}`)) {
|
if (await Network.checkInterfaceExists(`wg${server.confId}`)) {
|
||||||
await Shell.exec(`wg-quick down wg${server.confId}`, true);
|
await Shell.exec(`wg-quick down wg${server.confId}`, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.update(id, { status: 'down' });
|
await this.update({ status: 'down' });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async start(id: string): Promise<boolean> {
|
async start(): Promise<boolean> {
|
||||||
const server = await findServer(id);
|
const server = await this.get();
|
||||||
if (!server) {
|
|
||||||
console.error('server could not be updated (reason: not exists)');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const HASH = getConfigHash(server.confId);
|
const HASH = getConfigHash(server.confId);
|
||||||
if (!HASH || server.confHash !== HASH) {
|
if (!HASH || server.confHash !== HASH) {
|
||||||
await writeConfigFile(server);
|
await this.writeConfigFile(server);
|
||||||
await WGServer.update(id, { confHash: getConfigHash(server.confId) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await Network.checkInterfaceExists(`wg${server.confId}`)) {
|
if (await Network.checkInterfaceExists(`wg${server.confId}`)) {
|
||||||
@ -46,31 +72,27 @@ export class WGServer {
|
|||||||
|
|
||||||
await Shell.exec(`wg-quick up wg${server.confId}`);
|
await Shell.exec(`wg-quick up wg${server.confId}`);
|
||||||
|
|
||||||
await this.update(id, { status: 'up' });
|
await this.update({ status: 'up' });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async remove(id: string): Promise<boolean> {
|
async remove(): Promise<boolean> {
|
||||||
const server = await findServer(id);
|
const server = await this.get();
|
||||||
if (!server) {
|
|
||||||
console.error('server could not be updated (reason: not exists)');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.stop(id);
|
await this.stop();
|
||||||
if (wgConfExists(server.confId)) {
|
if (wgConfExists(server.confId)) {
|
||||||
fs.unlinkSync(path.join(WG_PATH, `wg${server.confId}.conf`));
|
fs.unlinkSync(resolveConfigPath(server.confId));
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = await findServerIndex(id);
|
const index = await findServerIndex(this.id);
|
||||||
if (typeof index !== 'number') {
|
if (typeof index !== 'number') {
|
||||||
console.warn('findServerIndex: index not found');
|
logger.warn('findServerIndex: index not found');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const element = await client.lindex(WG_SEVER_PATH, index);
|
const element = await client.lindex(WG_SEVER_PATH, index);
|
||||||
if (!element) {
|
if (!element) {
|
||||||
console.warn('remove: element not found');
|
logger.warn('remove: element not found');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,17 +101,15 @@ export class WGServer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async update(id: string, update: Partial<WgServer>): Promise<boolean> {
|
async update(update: Partial<WgServer>): Promise<boolean> {
|
||||||
const server = await findServer(id);
|
const server = await this.get();
|
||||||
if (!server) {
|
|
||||||
console.error('server could not be updated (reason: not exists)');
|
const index = await findServerIndex(this.id);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const index = await findServerIndex(id);
|
|
||||||
if (typeof index !== 'number') {
|
if (typeof index !== 'number') {
|
||||||
console.warn('findServerIndex: index not found');
|
logger.warn('findServerIndex: index not found');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await client.lset(
|
const res = await client.lset(
|
||||||
WG_SEVER_PATH,
|
WG_SEVER_PATH,
|
||||||
index,
|
index,
|
||||||
@ -99,22 +119,50 @@ export class WGServer {
|
|||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return res === 'OK';
|
return res === 'OK';
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findAttachedUuid(confId: number): Promise<string | undefined> {
|
async writeConfigFile(wg: WgServer): Promise<void> {
|
||||||
const server = await getServers();
|
const CONFIG_PATH = resolveConfigPath(wg.confId);
|
||||||
return server.find((s) => s.confId === confId)?.id;
|
fs.writeFileSync(CONFIG_PATH, await genServerConf(wg), { mode: 0o600 });
|
||||||
|
await this.update({ confHash: getConfigHash(wg.confId) });
|
||||||
}
|
}
|
||||||
|
|
||||||
static async addPeer(id: string, peer: WgServer['peers'][0]): Promise<boolean> {
|
static async getFreePeerIp(serverId: string): Promise<string | undefined> {
|
||||||
const server = await findServer(id);
|
const server = await findServer(serverId);
|
||||||
if (!server) {
|
if (!server) {
|
||||||
console.error('server could not be updated (reason: not exists)');
|
logger.error('GetFreePeerIP: no server found');
|
||||||
return false;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const confPath = path.join(WG_PATH, `wg${server.confId}.conf`);
|
const reservedIps = server.peers.map((p) => p.allowedIps);
|
||||||
|
const ips = reservedIps.map((ip) => ip.split('/')[0]);
|
||||||
|
const net = server.address.split('/')[0].split('.');
|
||||||
|
|
||||||
|
for (let i = 1; i < 255; i++) {
|
||||||
|
const ip = `${net[0]}.${net[1]}.${net[2]}.${i}`;
|
||||||
|
if (!ips.includes(ip) && ip !== server.address.split('/')[0]) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.error('GetFreePeerIP: no free ip found');
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WGPeers {
|
||||||
|
private readonly server: WGServer;
|
||||||
|
|
||||||
|
constructor(server: WGServer) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
async add(peer: WgServer['peers'][0]): Promise<boolean> {
|
||||||
|
const server = await this.server.get();
|
||||||
|
|
||||||
|
const confPath = resolveConfigPath(server.confId);
|
||||||
const conf = fs.readFileSync(confPath, 'utf-8');
|
const conf = fs.readFileSync(confPath, 'utf-8');
|
||||||
const lines = conf.split('\n');
|
const lines = conf.split('\n');
|
||||||
|
|
||||||
@ -128,13 +176,14 @@ export class WGServer {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
fs.writeFileSync(confPath, lines.join('\n'), { mode: 0o600 });
|
fs.writeFileSync(confPath, lines.join('\n'), { mode: 0o600 });
|
||||||
await WGServer.update(id, { confHash: getConfigHash(server.confId) });
|
await this.server.update({ confHash: getConfigHash(server.confId) });
|
||||||
|
|
||||||
const index = await findServerIndex(id);
|
const index = await findServerIndex(this.server.id);
|
||||||
if (typeof index !== 'number') {
|
if (typeof index !== 'number') {
|
||||||
console.warn('findServerIndex: index not found');
|
logger.warn('findServerIndex: index not found');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.lset(
|
await client.lset(
|
||||||
WG_SEVER_PATH,
|
WG_SEVER_PATH,
|
||||||
index,
|
index,
|
||||||
@ -145,24 +194,20 @@ export class WGServer {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (server.status === 'up') {
|
if (server.status === 'up') {
|
||||||
await this.stop(server.id);
|
await this.server.stop();
|
||||||
await this.start(server.id);
|
await this.server.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async removePeer(serverId: string, publicKey: string): Promise<boolean> {
|
async remove(publicKey: string): Promise<boolean> {
|
||||||
const server = await findServer(serverId);
|
const server = await this.server.get();
|
||||||
if (!server) {
|
|
||||||
console.error('server could not be updated (reason: not exists)');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const peers = await wgPeersStr(server.confId);
|
const peers = await wgPeersStr(server.confId);
|
||||||
|
|
||||||
const index = await findServerIndex(serverId);
|
const index = await findServerIndex(this.server.id);
|
||||||
if (typeof index !== 'number') {
|
if (typeof index !== 'number') {
|
||||||
console.warn('findServerIndex: index not found');
|
logger.warn('findServerIndex: index not found');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
await client.lset(
|
await client.lset(
|
||||||
@ -176,35 +221,31 @@ export class WGServer {
|
|||||||
|
|
||||||
const peerIndex = peers.findIndex((p) => p.includes(`PublicKey = ${publicKey}`));
|
const peerIndex = peers.findIndex((p) => p.includes(`PublicKey = ${publicKey}`));
|
||||||
if (peerIndex === -1) {
|
if (peerIndex === -1) {
|
||||||
console.warn('removePeer: no peer found');
|
logger.warn('removePeer: no peer found');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const confPath = path.join(WG_PATH, `wg${server.confId}.conf`);
|
const confPath = resolveConfigPath(server.confId);
|
||||||
const conf = fs.readFileSync(confPath, 'utf-8');
|
const conf = fs.readFileSync(confPath, 'utf-8');
|
||||||
const serverConfStr = conf.includes('[Peer]') ? conf.split('[Peer]')[0] : conf;
|
const serverConfStr = conf.includes('[Peer]') ? conf.split('[Peer]')[0] : conf;
|
||||||
const peersStr = peers.filter((_, i) => i !== peerIndex).join('\n');
|
const peersStr = peers.filter((_, i) => i !== peerIndex).join('\n');
|
||||||
fs.writeFileSync(confPath, `${serverConfStr}\n${peersStr}`, { mode: 0o600 });
|
fs.writeFileSync(confPath, `${serverConfStr}\n${peersStr}`, { mode: 0o600 });
|
||||||
await WGServer.update(server.id, { confHash: getConfigHash(server.confId) });
|
await this.server.update({ confHash: getConfigHash(server.confId) });
|
||||||
|
|
||||||
if (server.status === 'up') {
|
if (server.status === 'up') {
|
||||||
await this.stop(server.id);
|
await this.server.stop();
|
||||||
await this.start(server.id);
|
await this.server.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async updatePeer(serverId: string, publicKey: string, update: Partial<Peer>): Promise<boolean> {
|
async update(publicKey: string, update: Partial<Peer>): Promise<boolean> {
|
||||||
const server = await findServer(serverId);
|
const server = await this.server.get();
|
||||||
if (!server) {
|
|
||||||
console.error('WGServer:UpdatePeer: server could not be updated (Reason: not exists)');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const index = await findServerIndex(serverId);
|
const index = await findServerIndex(this.server.id);
|
||||||
if (typeof index !== 'number') {
|
if (typeof index !== 'number') {
|
||||||
console.warn('findServerIndex: index not found');
|
logger.warn('findServerIndex: index not found');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,73 +255,30 @@ export class WGServer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await client.lset(WG_SEVER_PATH, index, JSON.stringify({ ...server, peers: updatedPeers }));
|
await client.lset(WG_SEVER_PATH, index, JSON.stringify({ ...server, peers: updatedPeers }));
|
||||||
await this.storePeers({ id: server.id, confId: server.confId }, publicKey, updatedPeers);
|
await this.storePeers(publicKey, updatedPeers);
|
||||||
|
|
||||||
if (server.status === 'up') {
|
if (server.status === 'up') {
|
||||||
await this.stop(serverId);
|
await this.server.stop();
|
||||||
await this.start(serverId);
|
await this.server.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async getPeerIndex(id: string, publicKey: string): Promise<number | undefined> {
|
async getIndex(publicKey: string): Promise<number | undefined> {
|
||||||
const server = await findServer(id);
|
const server = await this.server.get();
|
||||||
if (!server) {
|
|
||||||
console.error('server could not be updated (reason: not exists)');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return server.peers.findIndex((p) => p.publicKey === publicKey);
|
return server.peers.findIndex((p) => p.publicKey === publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async storePeers(
|
async generateConfig(peerId: string): Promise<string | undefined> {
|
||||||
sd: Pick<WgServer, 'id' | 'confId'>,
|
const server = await findServer(this.server.id);
|
||||||
publicKey: string,
|
|
||||||
peers: Peer[],
|
|
||||||
): Promise<void> {
|
|
||||||
const peerIndex = await this.getPeerIndex(sd.id, publicKey);
|
|
||||||
if (peerIndex === -1) {
|
|
||||||
console.warn('WGServer:StorePeers: no peer found');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const confPath = path.join(WG_PATH, `wg${sd.confId}.conf`);
|
|
||||||
const conf = fs.readFileSync(confPath, 'utf-8');
|
|
||||||
const serverConfStr = conf.includes('[Peer]') ? conf.split('[Peer]')[0] : conf;
|
|
||||||
|
|
||||||
const peersStr = peers.filter((_, i) => i !== peerIndex).join('\n');
|
|
||||||
fs.writeFileSync(confPath, `${serverConfStr}\n${peersStr}`, { mode: 0o600 });
|
|
||||||
await WGServer.update(sd.id, { confHash: getConfigHash(sd.confId) });
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getFreePeerIp(id: string): Promise<string | undefined> {
|
|
||||||
const server = await findServer(id);
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
console.error('getFreePeerIp: server not found');
|
logger.error('generatePeerConfig: server not found');
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const reservedIps = server.peers.map((p) => p.allowedIps);
|
|
||||||
const ips = reservedIps.map((ip) => ip.split('/')[0]);
|
|
||||||
const net = server.address.split('/')[0].split('.');
|
|
||||||
for (let i = 1; i < 255; i++) {
|
|
||||||
const ip = `${net[0]}.${net[1]}.${net[2]}.${i}`;
|
|
||||||
if (!ips.includes(ip) && ip !== server.address.split('/')[0]) {
|
|
||||||
return ip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.error('getFreePeerIp: no free ip found');
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async generatePeerConfig(id: string, peerId: string): Promise<string | undefined> {
|
|
||||||
const server = await findServer(id);
|
|
||||||
if (!server) {
|
|
||||||
console.error('generatePeerConfig: server not found');
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
const peer = server.peers.find((p) => p.id === peerId);
|
const peer = server.peers.find((p) => p.id === peerId);
|
||||||
if (!peer) {
|
if (!peer) {
|
||||||
console.error('generatePeerConfig: peer not found');
|
logger.error('generatePeerConfig: peer not found');
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return await getPeerConf({
|
return await getPeerConf({
|
||||||
@ -290,6 +288,28 @@ export class WGServer {
|
|||||||
dns: server.dns,
|
dns: server.dns,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async storePeers(publicKey: string, peers: Peer[]): Promise<void> {
|
||||||
|
const { confId } = await this.server.get();
|
||||||
|
|
||||||
|
const peerIndex = await this.getIndex(publicKey);
|
||||||
|
if (peerIndex === -1) {
|
||||||
|
logger.warn('WGServer:StorePeers: no peer found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const confPath = resolveConfigPath(confId);
|
||||||
|
const conf = fs.readFileSync(confPath, 'utf-8');
|
||||||
|
const serverConfStr = conf.includes('[Peer]') ? conf.split('[Peer]')[0] : conf;
|
||||||
|
|
||||||
|
const peersStr = peers.filter((_, i) => i !== peerIndex).join('\n');
|
||||||
|
fs.writeFileSync(confPath, `${serverConfStr}\n${peersStr}`, { mode: 0o600 });
|
||||||
|
await this.server.update({ confHash: getConfigHash(confId) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveConfigPath(confId: number): string {
|
||||||
|
return path.resolve(path.join(WG_PATH, `wg${confId}.conf`));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -301,7 +321,7 @@ async function wgCheckout(configId: number): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function readWgConf(configId: number): Promise<WgServer> {
|
export async function readWgConf(configId: number): Promise<WgServer> {
|
||||||
const confPath = path.join(WG_PATH, `wg${configId}.conf`);
|
const confPath = resolveConfigPath(configId);
|
||||||
const conf = fs.readFileSync(confPath, 'utf-8');
|
const conf = fs.readFileSync(confPath, 'utf-8');
|
||||||
const lines = conf.split('\n');
|
const lines = conf.split('\n');
|
||||||
const server: WgServer = {
|
const server: WgServer = {
|
||||||
@ -392,13 +412,8 @@ export async function readWgConf(configId: number): Promise<WgServer> {
|
|||||||
* @param configId
|
* @param configId
|
||||||
*/
|
*/
|
||||||
function wgConfExists(configId: number): boolean {
|
function wgConfExists(configId: number): boolean {
|
||||||
const confPath = path.join(WG_PATH, `wg${configId}.conf`);
|
const confPath = resolveConfigPath(configId);
|
||||||
try {
|
return fsAccess(confPath);
|
||||||
fs.accessSync(confPath);
|
|
||||||
return true;
|
|
||||||
} catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -421,7 +436,7 @@ async function syncServers(): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function wgPeersStr(configId: number): string[] {
|
function wgPeersStr(configId: number): string[] {
|
||||||
const confPath = path.join(WG_PATH, `wg${configId}.conf`);
|
const confPath = path.resolve(WG_PATH, `wg${configId}.conf`);
|
||||||
const conf = fs.readFileSync(confPath, 'utf-8');
|
const conf = fs.readFileSync(confPath, 'utf-8');
|
||||||
const rawPeers = conf.split('[Peer]');
|
const rawPeers = conf.split('[Peer]');
|
||||||
return rawPeers.slice(1).map((p) => `[Peer]\n${p}`);
|
return rawPeers.slice(1).map((p) => `[Peer]\n${p}`);
|
||||||
@ -491,13 +506,14 @@ export async function generateWgServer(config: GenerateWgServerParams): Promise<
|
|||||||
await client.lpush(WG_SEVER_PATH, JSON.stringify(server));
|
await client.lpush(WG_SEVER_PATH, JSON.stringify(server));
|
||||||
}
|
}
|
||||||
|
|
||||||
const CONFIG_PATH = path.join(WG_PATH, `wg${confId}.conf`);
|
const CONFIG_PATH = resolveConfigPath(confId);
|
||||||
|
|
||||||
// save server config to disk
|
// save server config to disk
|
||||||
fs.writeFileSync(CONFIG_PATH, await genServerConf(server), { mode: 0o600 });
|
fs.writeFileSync(CONFIG_PATH, await genServerConf(server), { mode: 0o600 });
|
||||||
|
|
||||||
// updating hash of the config
|
// updating hash of the config
|
||||||
await WGServer.update(uuid, { confHash: getConfigHash(confId) });
|
const wg = new WGServer(uuid);
|
||||||
|
await wg.update({ confHash: getConfigHash(confId) });
|
||||||
|
|
||||||
// to ensure interface does not exists
|
// to ensure interface does not exists
|
||||||
await Shell.exec(`wg-quick down wg${confId}`, true);
|
await Shell.exec(`wg-quick down wg${confId}`, true);
|
||||||
@ -539,15 +555,9 @@ export function getConfigHash(confId: number): string | undefined {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const confPath = path.join(WG_PATH, `wg${confId}.conf`);
|
const confPath = resolveConfigPath(confId);
|
||||||
const conf = fs.readFileSync(confPath, 'utf-8');
|
const conf = fs.readFileSync(confPath, 'utf-8');
|
||||||
return Hex.stringify(SHA256(conf));
|
return sha256(conf);
|
||||||
}
|
|
||||||
|
|
||||||
export async function writeConfigFile(wg: WgServer): Promise<void> {
|
|
||||||
const CONFIG_PATH = path.join(WG_PATH, `wg${wg.confId}.conf`);
|
|
||||||
fs.writeFileSync(CONFIG_PATH, await genServerConf(wg), { mode: 0o600 });
|
|
||||||
await WGServer.update(wg.id, { confHash: getConfigHash(wg.confId) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function maxConfId(): number {
|
export function maxConfId(): number {
|
||||||
@ -589,8 +599,8 @@ export async function findServer(id: string | undefined, hash?: string): Promise
|
|||||||
return id
|
return id
|
||||||
? servers.find((s) => s.id === id)
|
? servers.find((s) => s.id === id)
|
||||||
: hash && isJson(hash)
|
: hash && isJson(hash)
|
||||||
? servers.find((s) => JSON.stringify(s) === hash)
|
? servers.find((s) => JSON.stringify(s) === hash)
|
||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function makeWgIptables(s: WgServer): Promise<{ up: string; down: string }> {
|
export async function makeWgIptables(s: WgServer): Promise<{ up: string; down: string }> {
|
||||||
|
@ -30,7 +30,8 @@ export const actions: Actions = {
|
|||||||
return error(400, 'Bad Request');
|
return error(400, 'Bad Request');
|
||||||
}
|
}
|
||||||
|
|
||||||
await WGServer.update(server.id, { name });
|
const wg = new WGServer(server.id);
|
||||||
|
await wg.update({ name });
|
||||||
|
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
},
|
},
|
||||||
|
@ -41,7 +41,8 @@ export const actions: Actions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await WGServer.updatePeer(server.id, peer.publicKey, { name });
|
const wg = new WGServer(server.id);
|
||||||
|
await wg.peers.update(peer.publicKey, { name });
|
||||||
|
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -63,7 +64,8 @@ export const actions: Actions = {
|
|||||||
const peerId = (form.get('id') ?? '').toString();
|
const peerId = (form.get('id') ?? '').toString();
|
||||||
const peer = server.peers.find((p) => p.id === peerId);
|
const peer = server.peers.find((p) => p.id === peerId);
|
||||||
if (peer) {
|
if (peer) {
|
||||||
await WGServer.removePeer(server.id, peer.publicKey);
|
const wg = new WGServer(server.id);
|
||||||
|
await wg.peers.remove(peer.publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
@ -78,7 +80,8 @@ export const actions: Actions = {
|
|||||||
try {
|
try {
|
||||||
const server = await findServer(serverId ?? '');
|
const server = await findServer(serverId ?? '');
|
||||||
if (server) {
|
if (server) {
|
||||||
await WGServer.remove(server.id);
|
const wg = new WGServer(server.id);
|
||||||
|
await wg.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ok: true };
|
return { ok: true };
|
||||||
@ -99,24 +102,26 @@ export const actions: Actions = {
|
|||||||
const form = await request.formData();
|
const form = await request.formData();
|
||||||
const status = (form.get('state') ?? '').toString();
|
const status = (form.get('state') ?? '').toString();
|
||||||
|
|
||||||
|
const wg = new WGServer(server.id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (server.status !== status) {
|
if (server.status !== status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 'start':
|
case 'start':
|
||||||
await WGServer.start(server.id);
|
await wg.start();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'stop':
|
case 'stop':
|
||||||
await WGServer.stop(server.id);
|
await wg.stop();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'remove':
|
case 'remove':
|
||||||
await WGServer.remove(server.id);
|
await wg.remove();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'restart':
|
case 'restart':
|
||||||
await WGServer.stop(server.id);
|
await wg.stop();
|
||||||
await WGServer.start(server.id);
|
await wg.start();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,7 +156,8 @@ export const actions: Actions = {
|
|||||||
|
|
||||||
const peerKeys = await generateWgKey();
|
const peerKeys = await generateWgKey();
|
||||||
|
|
||||||
const addedPeer = await WGServer.addPeer(server.id, {
|
const wg = new WGServer(server.id);
|
||||||
|
const addedPeer = await wg.peers.add({
|
||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
name,
|
name,
|
||||||
allowedIps: freeAddress,
|
allowedIps: freeAddress,
|
||||||
|
@ -7,15 +7,11 @@ export const GET: RequestHandler = async () => {
|
|||||||
const servers = await getServers();
|
const servers = await getServers();
|
||||||
|
|
||||||
for (const s of servers) {
|
for (const s of servers) {
|
||||||
const HASH = getConfigHash(s.confId);
|
const wg = new WGServer(s.id);
|
||||||
if (s.confId && HASH && s.confHash === HASH) {
|
|
||||||
// Skip, due to no changes on the config
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
if (s.status === 'up') {
|
if (s.status === 'up') {
|
||||||
await WGServer.start(s.id);
|
await wg.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -4,8 +4,8 @@ import type { PageServerLoad } from './$types';
|
|||||||
import { setError, superValidate } from 'sveltekit-superforms/server';
|
import { setError, superValidate } from 'sveltekit-superforms/server';
|
||||||
import { formSchema } from './schema';
|
import { formSchema } from './schema';
|
||||||
import { generateToken } from '$lib/auth';
|
import { generateToken } from '$lib/auth';
|
||||||
import 'dotenv/config';
|
|
||||||
import logger from '$lib/logger';
|
import logger from '$lib/logger';
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
export const load: PageServerLoad = () => {
|
export const load: PageServerLoad = () => {
|
||||||
return {
|
return {
|
||||||
@ -22,8 +22,10 @@ export const actions: Actions = {
|
|||||||
return fail(400, { ok: false, message: 'Bad Request', form });
|
return fail(400, { ok: false, message: 'Bad Request', form });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
const { HASHED_PASSWORD } = process.env;
|
const { HASHED_PASSWORD } = process.env;
|
||||||
if (HASHED_PASSWORD) {
|
if (HASHED_PASSWORD && HASHED_PASSWORD !== '') {
|
||||||
const { password } = form.data;
|
const { password } = form.data;
|
||||||
|
|
||||||
const hashed = HASHED_PASSWORD.toLowerCase();
|
const hashed = HASHED_PASSWORD.toLowerCase();
|
||||||
@ -34,7 +36,7 @@ export const actions: Actions = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HASHED_PASSWORD) {
|
if (!HASHED_PASSWORD || HASHED_PASSWORD === '') {
|
||||||
logger.warn('No password is set!');
|
logger.warn('No password is set!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user