Browse Source

update

pull/1345/head
Bernd Storath 11 months ago
parent
commit
ad24f54dfd
  1. 1
      src/app/app.vue
  2. 2
      src/app/pages/login.vue
  3. 8
      src/app/stores/global.ts
  4. 6
      src/app/utils/api.ts
  5. 5
      src/server/api/remember-me.get.ts
  6. 5
      src/server/api/session.post.ts
  7. 27
      src/server/utils/WireGuard.ts
  8. 51
      src/server/utils/config.ts
  9. 2
      src/services/database/lowdb.ts
  10. 60
      src/services/database/migrations/1.ts
  11. 4
      src/services/database/repositories/system.ts

1
src/app/app.vue

@ -14,7 +14,6 @@ globalStore.fetchRelease();
globalStore.fetchOneTimeLinks();
globalStore.fetchSortClients();
globalStore.fetchExpireTime();
globalStore.fetchRememberMe();
useHead({
bodyAttrs: {
class: 'bg-gray-50 dark:bg-neutral-800',

2
src/app/pages/login.vue

@ -37,7 +37,6 @@
/>
<label
v-if="globalStore.rememberMeEnabled"
class="inline-block mb-5 cursor-pointer whitespace-nowrap"
:title="$t('titleRememberMe')"
>
@ -89,7 +88,6 @@ const remember = ref(false);
const username = ref<null | string>(null);
const password = ref<null | string>(null);
const authStore = useAuthStore();
const globalStore = useGlobalStore();
async function login(e: Event) {
e.preventDefault();

8
src/app/stores/global.ts

@ -8,7 +8,6 @@ export const useGlobalStore = defineStore('Global', () => {
null
);
const uiTrafficStats = ref(false);
const rememberMeEnabled = ref(false);
const enableExpireTime = ref(false);
const enableOneTimeLinks = ref(false);
const enableSortClient = ref(false);
@ -65,11 +64,6 @@ export const useGlobalStore = defineStore('Global', () => {
enableExpireTime.value = expireTime.value ?? false;
}
async function fetchRememberMe() {
const { data: rememberMe } = await api.getRememberMeEnabled();
rememberMeEnabled.value = rememberMe.value ?? false;
}
const updateCharts = computed(() => {
return uiChartType.value > 0 && uiShowCharts.value;
});
@ -79,7 +73,6 @@ export const useGlobalStore = defineStore('Global', () => {
uiShowCharts,
uiTrafficStats,
updateCharts,
rememberMeEnabled,
enableSortClient,
sortClient,
enableExpireTime,
@ -90,6 +83,5 @@ export const useGlobalStore = defineStore('Global', () => {
fetchOneTimeLinks,
fetchSortClients,
fetchExpireTime,
fetchRememberMe,
};
});

6
src/app/utils/api.ts

@ -11,12 +11,6 @@ class API {
});
}
async getRememberMeEnabled() {
return useFetch('/api/remember-me', {
method: 'get',
});
}
async getTrafficStats() {
return useFetch('/api/ui-traffic-stats', {
method: 'get',

5
src/server/api/remember-me.get.ts

@ -1,5 +0,0 @@
export default defineEventHandler(async (event) => {
setHeader(event, 'Content-Type', 'application/json');
// TODO: enable by default
return MAX_AGE > 0;
});

5
src/server/api/session.post.ts

@ -30,10 +30,11 @@ export default defineEventHandler(async (event) => {
});
const conf: SessionConfig = system.sessionConfig;
if (MAX_AGE && remember) {
if (remember) {
conf.cookie = {
...(system.sessionConfig.cookie ?? {}),
maxAge: MAX_AGE,
maxAge: system.cookieMaxAge * 60,
};
}

27
src/server/utils/WireGuard.ts

@ -1,6 +1,6 @@
import fs from 'node:fs/promises';
import path from 'path';
import debug from 'DEBUG';
import debug from 'debug';
import crypto from 'node:crypto';
import QRCode from 'qrcode';
import CRC32 from 'crc-32';
@ -47,7 +47,7 @@ ${
}
DEBUG('Config saving...');
await fs.writeFile(path.join(WG_PATH, 'wg0.conf'), result, {
await fs.writeFile(path.join('/etc/wireguard', 'wg0.conf'), result, {
mode: 0o600,
});
DEBUG('Config saved.');
@ -136,16 +136,15 @@ ${
[Interface]
PrivateKey = ${client.privateKey ? `${client.privateKey}` : 'REPLACE_ME'}
Address = ${client.address}/24
${WG_DEFAULT_DNS ? `DNS = ${WG_DEFAULT_DNS}\n` : ''}\
${WG_MTU ? `MTU = ${WG_MTU}\n` : ''}\
DNS = ${system.userConfig.defaultDns.join(',')}
MTU = ${system.userConfig.mtu}
[Peer]
PublicKey = ${system.interface.publicKey}
${
client.preSharedKey ? `PresharedKey = ${client.preSharedKey}\n` : ''
}AllowedIPs = ${client.allowedIPs}
PresharedKey = ${client.preSharedKey}
AllowedIPs = ${client.allowedIPs}
PersistentKeepalive = ${client.persistentKeepalive}
Endpoint = ${WG_HOST}:${WG_CONFIG_PORT}`;
Endpoint = ${system.wgHost}:${system.wgConfigPort}`;
}
async getClientQRCodeSVG({ clientId }: { clientId: string }) {
@ -167,6 +166,7 @@ Endpoint = ${WG_HOST}:${WG_CONFIG_PORT}`;
throw new Error('Missing: Name');
}
const system = await Database.getSystem();
const clients = await Database.getClients();
const privateKey = await exec('wg genkey');
@ -180,11 +180,14 @@ Endpoint = ${WG_HOST}:${WG_CONFIG_PORT}`;
let address;
for (let i = 2; i < 255; i++) {
const client = Object.values(clients).find((client) => {
return client.address === WG_DEFAULT_ADDRESS.replace('x', i.toString());
return (
client.address ===
system.userConfig.addressRange.replace('x', i.toString())
);
});
if (!client) {
address = WG_DEFAULT_ADDRESS.replace('x', i.toString());
address = system.userConfig.addressRange.replace('x', i.toString());
break;
}
}
@ -207,8 +210,8 @@ Endpoint = ${WG_HOST}:${WG_CONFIG_PORT}`;
oneTimeLink: null,
expiresAt: null,
enabled: true,
allowedIPs: WG_ALLOWED_IPS.split(', '),
persistentKeepalive: Number(WG_PERSISTENT_KEEPALIVE),
allowedIPs: system.userConfig.allowedIps,
persistentKeepalive: system.userConfig.persistentKeepalive,
};
if (expireDate) {

51
src/server/utils/config.ts

@ -1,50 +1,5 @@
import type { SessionConfig } from 'h3';
import debug from 'debug';
export const MAX_AGE = process.env.MAX_AGE
? parseInt(process.env.MAX_AGE, 10) * 60
: 0;
export const WG_PATH = process.env.WG_PATH || '/etc/wireguard/';
export const WG_DEVICE = process.env.WG_DEVICE || 'eth0';
export const WG_HOST = process.env.WG_HOST;
export const WG_PORT = process.env.WG_PORT || '51820';
export const WG_CONFIG_PORT =
process.env.WG_CONFIG_PORT || process.env.WG_PORT || '51820';
export const WG_MTU = process.env.WG_MTU || null;
export const WG_PERSISTENT_KEEPALIVE =
process.env.WG_PERSISTENT_KEEPALIVE || '0';
export const WG_DEFAULT_ADDRESS = process.env.WG_DEFAULT_ADDRESS || '10.8.0.x';
export const WG_DEFAULT_DNS =
typeof process.env.WG_DEFAULT_DNS === 'string'
? process.env.WG_DEFAULT_DNS
: '1.1.1.1';
export const WG_ALLOWED_IPS = process.env.WG_ALLOWED_IPS || '0.0.0.0/0, ::/0';
export const WG_PRE_UP = process.env.WG_PRE_UP || '';
export const WG_POST_UP =
process.env.WG_POST_UP ||
`
iptables -t nat -A POSTROUTING -s ${WG_DEFAULT_ADDRESS.replace('x', '0')}/24 -o ${WG_DEVICE} -j MASQUERADE;
iptables -A INPUT -p udp -m udp --dport ${WG_PORT} -j ACCEPT;
iptables -A FORWARD -i wg0 -j ACCEPT;
iptables -A FORWARD -o wg0 -j ACCEPT;
`
.split('\n')
.join(' ');
export const WG_PRE_DOWN = process.env.WG_PRE_DOWN || '';
export const WG_POST_DOWN =
process.env.WG_POST_DOWN ||
`
iptables -t nat -D POSTROUTING -s ${WG_DEFAULT_ADDRESS.replace('x', '0')}/24 -o ${WG_DEVICE} -j MASQUERADE;
iptables -D INPUT -p udp -m udp --dport ${WG_PORT} -j ACCEPT;
iptables -D FORWARD -i wg0 -j ACCEPT;
iptables -D FORWARD -o wg0 -j ACCEPT;
`
.split('\n')
.join(' ');
export const LANG = process.env.LANG || 'en';
export const UI_TRAFFIC_STATS = process.env.UI_TRAFFIC_STATS || 'false';
export const UI_CHART_TYPE = process.env.UI_CHART_TYPE || '0';
export const WG_ENABLE_ONE_TIME_LINKS =
@ -60,10 +15,4 @@ export const PROMETHEUS_METRICS_PASSWORD =
export const REQUIRES_PROMETHEUS_PASSWORD = !!PROMETHEUS_METRICS_PASSWORD;
export const SESSION_CONFIG = {
password: getRandomHex(256),
name: 'wg-easy',
cookie: undefined,
} satisfies SessionConfig;
export const SERVER_DEBUG = debug('Server');

2
src/services/database/lowdb.ts

@ -23,7 +23,7 @@ export default class LowDB extends DatabaseProvider {
// is this really needed?
private async __init() {
// TODO: assume path to db file
const dbFilePath = join(WG_PATH, 'db.json');
const dbFilePath = join('/etc/wireguard', 'db.json');
this.#db = await JSONFilePreset(dbFilePath, DEFAULT_DATABASE);
}

60
src/services/database/migrations/1.ts

@ -3,32 +3,12 @@ import type { Database } from '../repositories/database';
import packageJson from '@@/package.json';
import { ChartType } from '../repositories/system';
// TODO: use variables inside up/down script
const DEFAULT_ADDRESS = '10.8.0.x';
const DEFAULT_DEVICE = 'eth0';
const DEFAULT_WG_PORT = 51820;
const DEFAULT_POST_UP = `
iptables -t nat -A POSTROUTING -s ${DEFAULT_ADDRESS.replace('x', '0')}/24 -o ${DEFAULT_DEVICE} -j MASQUERADE;
iptables -A INPUT -p udp -m udp --dport ${DEFAULT_WG_PORT} -j ACCEPT;
iptables -A FORWARD -i wg0 -j ACCEPT;
iptables -A FORWARD -o wg0 -j ACCEPT;
`
.split('\n')
.join(' ');
const DEFAULT_POST_DOWN = `
iptables -t nat -D POSTROUTING -s ${DEFAULT_ADDRESS.replace('x', '0')}/24 -o ${DEFAULT_DEVICE} -j MASQUERADE;
iptables -D INPUT -p udp -m udp --dport ${DEFAULT_WG_PORT} -j ACCEPT;
iptables -D FORWARD -i wg0 -j ACCEPT;
iptables -D FORWARD -o wg0 -j ACCEPT;
`
.split('\n')
.join(' ');
export async function run1(db: Low<Database>) {
const privateKey = await exec('wg genkey');
const publicKey = await exec(`echo ${privateKey} | wg pubkey`, {
log: 'echo ***hidden*** | wg pubkey',
});
const addressRange = '10.8.0.x';
const database: Database = {
migrations: [],
system: {
@ -36,7 +16,7 @@ export async function run1(db: Low<Database>) {
interface: {
privateKey: privateKey,
publicKey: publicKey,
address: DEFAULT_ADDRESS.replace('x', '1'),
address: addressRange.replace('x', '1'),
},
sessionTimeout: 3600, // 1 hour
lang: 'en',
@ -44,20 +24,21 @@ export async function run1(db: Low<Database>) {
mtu: 1420,
persistentKeepalive: 0,
// TODO: assume handle CIDR to compute next ip in WireGuard
rangeAddress: '10.8.0.0/24',
//addressRange: '10.8.0.0/24',
addressRange: addressRange,
defaultDns: ['1.1.1.1'],
allowedIps: ['0.0.0.0/0', '::/0'],
},
wgPath: WG_PATH,
wgDevice: DEFAULT_DEVICE,
wgHost: WG_HOST || '',
wgPort: DEFAULT_WG_PORT,
wgDevice: 'wg0',
// TODO: wgHost has to be configured when onboarding
wgHost: '',
wgPort: 51820,
wgConfigPort: 51820,
iptables: {
PreUp: '',
PostUp: DEFAULT_POST_UP,
PostUp: '',
PreDown: '',
PostDown: DEFAULT_POST_DOWN,
PostDown: '',
},
trafficStats: {
enabled: false,
@ -79,13 +60,32 @@ export async function run1(db: Low<Database>) {
sessionConfig: {
password: getRandomHex(256),
name: 'wg-easy',
cookie: undefined,
cookie: {},
},
cookieMaxAge: 24 * 60,
},
users: [],
clients: {},
};
// TODO: use variables inside up/down script
database.system.iptables.PostUp = `
iptables -t nat -A POSTROUTING -s ${database.system.userConfig.addressRange.replace('x', '0')}/24 -o ${database.system.wgDevice} -j MASQUERADE;
iptables -A INPUT -p udp -m udp --dport ${database.system.wgPort} -j ACCEPT;
iptables -A FORWARD -i wg0 -j ACCEPT;
iptables -A FORWARD -o wg0 -j ACCEPT;
`
.split('\n')
.join(' ');
database.system.iptables.PostDown = `
iptables -t nat -D POSTROUTING -s ${database.system.userConfig.addressRange.replace('x', '0')}/24 -o ${database.system.wgDevice} -j MASQUERADE;
iptables -D INPUT -p udp -m udp --dport ${database.system.wgPort} -j ACCEPT;
iptables -D FORWARD -i wg0 -j ACCEPT;
iptables -D FORWARD -o wg0 -j ACCEPT;
`
.split('\n')
.join(' ');
db.data = database;
db.write();
}

4
src/services/database/repositories/system.ts

@ -18,7 +18,7 @@ export type WGInterface = {
export type WGConfig = {
mtu: number;
persistentKeepalive: number;
rangeAddress: string;
addressRange: string;
defaultDns: string[];
allowedIps: string[];
};
@ -57,7 +57,6 @@ export type System = {
userConfig: WGConfig;
wgPath: string;
wgDevice: string;
wgHost: string;
wgPort: number;
@ -72,6 +71,7 @@ export type System = {
prometheus: Prometheus;
sessionConfig: SessionConfig;
cookieMaxAge: number;
};
/**

Loading…
Cancel
Save