Browse Source

- Add AmneziaWG 2.0 support;

- buildAmneziaQrPack is async (zlib deflate);
- ClientQrSchema now has 'wireguard' as fallback
pull/2423/head
ne0x 6 months ago
parent
commit
44b3412179
  1. 7
      src/server/database/repositories/client/types.ts
  2. 9
      src/server/utils/WireGuard.ts
  3. 26
      src/server/utils/wgHelper.ts

7
src/server/database/repositories/client/types.ts

@ -104,11 +104,10 @@ export type ClientCreateFromExistingType = Pick<
| 'enabled'
>;
const qrType = z.preprocess(
(val) => (val === 'amnezia-vpn' ? val : undefined),
z.enum(['amnezia-vpn']).optional()
);
const qrType = z.enum(['amnezia-vpn', 'wireguard']).catch('wireguard');
export const ClientQrSchema = z.object({
type: qrType,
});
export type QrType = z.infer<typeof qrType>;

9
src/server/utils/WireGuard.ts

@ -2,6 +2,7 @@ import fs from 'node:fs/promises';
import debug from 'debug';
import { encodeQR } from 'qr';
import type { InterfaceType } from '#db/repositories/interface/types';
import type { QrType } from '#db/repositories/client/types';
const WG_DEBUG = debug('WireGuard');
@ -149,7 +150,7 @@ class WireGuard {
return clients;
}
async getClientConfiguration({ clientId, type }: { clientId: ID, type?: 'amnezia-vpn' }) {
async getClientConfiguration({ clientId, type }: { clientId: ID, type?: QrType }) {
const wgInterface = await Database.interfaces.get();
const userConfig = await Database.userConfigs.get();
@ -167,13 +168,15 @@ class WireGuard {
const amneziaVPNClientConfig = wg.generateAmneziaVPNClientConfig(wgInterface, userConfig, client, configText, {
enableIpv6: !WG_ENV.DISABLE_IPV6,
});
return wg.buildAmneziaQrPack(JSON.stringify(amneziaVPNClientConfig));
const qrConfigPack = await wg.buildAmneziaQrPack(JSON.stringify(amneziaVPNClientConfig));
return qrConfigPack;
}
return configText;
}
async getClientQRCodeSVG({ clientId, type }: { clientId: ID, type?: 'amnezia-vpn' }) {
async getClientQRCodeSVG({ clientId, type }: { clientId: ID, type?: QrType }) {
const config = await this.getClientConfiguration({ clientId, type });
const ECMode = ['high', 'quartile', 'medium', 'low'] as const;
for (const ecc of ECMode) {

26
src/server/utils/wgHelper.ts

@ -1,4 +1,5 @@
import { deflateSync as zlibDeflateSync } from 'node:zlib';
import { deflate } from 'node:zlib';
import { promisify } from 'node:util';
import { parseCidr } from 'cidr-tools';
import { stringifyIp } from 'ip-bigint';
import type { ClientType } from '#db/repositories/client/types';
@ -6,6 +7,8 @@ import type { InterfaceType } from '#db/repositories/interface/types';
import type { UserConfigType } from '#db/repositories/userConfig/types';
import type { HooksType } from '#db/repositories/hooks/types';
const zlibDeflate = promisify(deflate);
type Options = {
enableIpv6?: boolean;
};
@ -188,20 +191,14 @@ Endpoint = ${userConfig.host}:${userConfig.port}`;
if (wgExecutable === 'awg') {
containerType = 'awg';
// S3, S4, i1, i2, i3, i4, i5 are not supported by AmneziaVPN app for now
const awgParams = {
Jc: client.jC,
Jmin: client.jMin,
Jmax: client.jMax,
S1: wgInterface.s1,
S2: wgInterface.s2,
// S3: wgInterface.s3,
// S4: wgInterface.s4,
// i1: client.i1,
// i2: client.i2,
// i3: client.i3,
// i4: client.i4,
// i5: client.i5,
S3: wgInterface.s3,
S4: wgInterface.s4,
H1: wgInterface.h1,
H2: wgInterface.h2,
H3: wgInterface.h3,
@ -217,6 +214,12 @@ Endpoint = ${userConfig.host}:${userConfig.port}`;
);
}
const protocolInfo: { protocol_version?: string } = {};
if (awgExtras.hasOwnProperty('S3') && awgExtras.hasOwnProperty('S4')) {
protocolInfo.protocol_version = '2';
}
const lastConfigObj = {
...awgExtras,
allowed_ips: client.allowedIps ?? userConfig.defaultAllowedIps ?? [],
@ -238,6 +241,7 @@ Endpoint = ${userConfig.host}:${userConfig.port}`;
isThirdPartyConfig: true,
last_config: JSON.stringify(lastConfigObj),
port: `${userConfig.port}`,
...protocolInfo,
transport_proto: 'udp',
},
container: `amnezia-${containerType}`,
@ -251,14 +255,14 @@ Endpoint = ${userConfig.host}:${userConfig.port}`;
};
},
buildAmneziaQrPack: (amneziaConfigJSON: string) => {
buildAmneziaQrPack: async (amneziaConfigJSON: string) => {
// Observed working QR wrapper:
// [0..3] magic/version (0x07C00100)
// [4..7] zlib_len + 4
// [8..11] uncompressed_len
// [12..] zlib(deflate) bytes (starts with 78 DA typically)
const plain = Buffer.from(amneziaConfigJSON, 'utf8');
const z = zlibDeflateSync(plain);
const z = await zlibDeflate(plain);
const MAGIC = 0x07c00100;
const header = Buffer.allocUnsafe(12);

Loading…
Cancel
Save