mirror of https://github.com/wg-easy/wg-easy
committed by
Bernd Storath
3 changed files with 121 additions and 45 deletions
@ -1,8 +1,80 @@ |
|||||
import debug from 'debug'; |
import debug from 'debug'; |
||||
import packageJson from '@@/package.json'; |
import packageJson from '@@/package.json'; |
||||
|
import { z } from 'zod'; |
||||
|
import type { Database } from '~~/services/database/repositories/database'; |
||||
|
import { parseCidr } from 'cidr-tools'; |
||||
|
import { stringifyIp } from 'ip-bigint'; |
||||
|
|
||||
export const WG_PATH = process.env.WG_PATH || '/etc/wireguard/'; |
export const WG_PATH = process.env.WG_PATH || '/etc/wireguard/'; |
||||
|
|
||||
export const RELEASE = packageJson.release.version; |
export const RELEASE = packageJson.release.version; |
||||
|
|
||||
export const SERVER_DEBUG = debug('Server'); |
export const SERVER_DEBUG = debug('Server'); |
||||
|
|
||||
|
export async function migrateConfig(input: unknown) { |
||||
|
const schema = z.object({ |
||||
|
server: z.object({ |
||||
|
privateKey: z.string(), |
||||
|
publicKey: z.string(), |
||||
|
address: z.string(), |
||||
|
}), |
||||
|
clients: z.record( |
||||
|
z.string(), |
||||
|
z.object({ |
||||
|
name: z.string(), |
||||
|
address: z.string(), |
||||
|
privateKey: z.string(), |
||||
|
publicKey: z.string(), |
||||
|
preSharedKey: z.string(), |
||||
|
createdAt: z.string(), |
||||
|
updatedAt: z.string(), |
||||
|
enabled: z.boolean(), |
||||
|
}) |
||||
|
), |
||||
|
}); |
||||
|
const res = await schema.safeParseAsync(input); |
||||
|
if (!res.success) { |
||||
|
throw new Error('Invalid Config'); |
||||
|
} |
||||
|
const system = await Database.getSystem(); |
||||
|
const oldConfig = res.data; |
||||
|
const oldCidr = parseCidr(oldConfig.server.address + '/24'); |
||||
|
const db = { |
||||
|
system: { |
||||
|
...system, |
||||
|
interface: { |
||||
|
...system.interface, |
||||
|
address4: oldConfig.server.address, |
||||
|
privateKey: oldConfig.server.privateKey, |
||||
|
publicKey: oldConfig.server.publicKey, |
||||
|
}, |
||||
|
userConfig: { |
||||
|
...system.userConfig, |
||||
|
address4Range: |
||||
|
stringifyIp({ number: oldCidr.start, version: 4 }) + '/24', |
||||
|
}, |
||||
|
} satisfies Partial<Database['system']>, |
||||
|
clients: {} as Database['clients'], |
||||
|
}; |
||||
|
for (const [oldId, oldClient] of Object.entries(oldConfig.clients)) { |
||||
|
const address6 = nextIPv6(db.system, db.clients); |
||||
|
db.clients[oldId] = { |
||||
|
id: oldId, |
||||
|
address4: oldClient.address, |
||||
|
createdAt: oldClient.createdAt, |
||||
|
enabled: oldClient.enabled, |
||||
|
name: oldClient.name, |
||||
|
preSharedKey: oldClient.preSharedKey, |
||||
|
privateKey: oldClient.privateKey, |
||||
|
publicKey: oldClient.publicKey, |
||||
|
updatedAt: oldClient.updatedAt, |
||||
|
endpoint: null, |
||||
|
expiresAt: null, |
||||
|
oneTimeLink: null, |
||||
|
allowedIPs: db.system.userConfig.allowedIps, |
||||
|
serverAllowedIPs: [], |
||||
|
persistentKeepalive: 0, |
||||
|
address6: address6, |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
@ -0,0 +1,47 @@ |
|||||
|
import { parseCidr } from 'cidr-tools'; |
||||
|
import { stringifyIp } from 'ip-bigint'; |
||||
|
import type { Database } from '~~/services/database/repositories/database'; |
||||
|
|
||||
|
export function nextIPv4( |
||||
|
system: Database['system'], |
||||
|
clients: Database['clients'] |
||||
|
) { |
||||
|
return nextIP(4, system, clients); |
||||
|
} |
||||
|
|
||||
|
export function nextIPv6( |
||||
|
system: Database['system'], |
||||
|
clients: Database['clients'] |
||||
|
) { |
||||
|
return nextIP(6, system, clients); |
||||
|
} |
||||
|
|
||||
|
function nextIP( |
||||
|
version: 4 | 6, |
||||
|
system: Database['system'], |
||||
|
clients: Database['clients'] |
||||
|
) { |
||||
|
const cidr = parseCidr(system.userConfig[`address${version}Range`]); |
||||
|
let address; |
||||
|
for (let i = cidr.start + 2n; i <= cidr.end - 1n; i++) { |
||||
|
const currentIp = stringifyIp({ number: i, version: version }); |
||||
|
const client = Object.values(clients).find((client) => { |
||||
|
return client[`address${version}`] === currentIp; |
||||
|
}); |
||||
|
|
||||
|
if (!client) { |
||||
|
address = currentIp; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!address) { |
||||
|
throw createError({ |
||||
|
statusCode: 409, |
||||
|
statusMessage: 'Maximum number of clients reached.', |
||||
|
data: { cause: `IPv${version} Address Pool exhausted` }, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return address; |
||||
|
} |
Loading…
Reference in new issue