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 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 RELEASE = packageJson.release.version; |
|||
|
|||
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