diff --git a/src/package.json b/src/package.json index bf4c80bd..88429b25 100644 --- a/src/package.json +++ b/src/package.json @@ -30,7 +30,6 @@ "cidr-tools": "^11.0.2", "crc-32": "^1.2.2", "debug": "^4.3.6", - "ip": "^2.0.1", "ip-bigint": "^8.2.0", "is-ip": "^5.0.1", "js-sha256": "^0.11.0", @@ -48,7 +47,6 @@ "@nuxt/eslint-config": "^0.5.5", "@types/bcryptjs": "^2.4.6", "@types/debug": "^4.1.12", - "@types/ip": "^1.1.3", "@types/qrcode": "^1.5.5", "eslint": "^9.9.1", "eslint-config-prettier": "^9.1.0", diff --git a/src/pnpm-lock.yaml b/src/pnpm-lock.yaml index c9f052f1..861faced 100644 --- a/src/pnpm-lock.yaml +++ b/src/pnpm-lock.yaml @@ -41,9 +41,6 @@ importers: debug: specifier: ^4.3.6 version: 4.3.6 - ip: - specifier: ^2.0.1 - version: 2.0.1 ip-bigint: specifier: ^8.2.0 version: 8.2.0 @@ -90,9 +87,6 @@ importers: '@types/debug': specifier: ^4.1.12 version: 4.1.12 - '@types/ip': - specifier: ^1.1.3 - version: 1.1.3 '@types/qrcode': specifier: ^1.5.5 version: 1.5.5 @@ -1232,9 +1226,6 @@ packages: '@types/http-proxy@1.17.15': resolution: {integrity: sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==} - '@types/ip@1.1.3': - resolution: {integrity: sha512-64waoJgkXFTYnCYDUWgSATJ/dXEBanVkaP5d4Sbk7P6U7cTTMhxVyROTckc6JKdwCrgnAjZMn0k3177aQxtDEA==} - '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -2588,9 +2579,6 @@ packages: resolution: {integrity: sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - ip@2.0.1: - resolution: {integrity: sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==} - iron-webcrypto@1.2.1: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} @@ -5683,10 +5671,6 @@ snapshots: dependencies: '@types/node': 22.5.2 - '@types/ip@1.1.3': - dependencies: - '@types/node': 22.5.2 - '@types/json-schema@7.0.15': {} '@types/ms@0.7.34': {} @@ -7255,8 +7239,6 @@ snapshots: ip-regex@5.0.0: {} - ip@2.0.1: {} - iron-webcrypto@1.2.1: {} is-arrayish@0.2.1: {} diff --git a/src/server/utils/WireGuard.ts b/src/server/utils/WireGuard.ts index e2636bd8..fb83b5f1 100644 --- a/src/server/utils/WireGuard.ts +++ b/src/server/utils/WireGuard.ts @@ -22,6 +22,7 @@ class WireGuard { const system = await Database.getSystem(); const clients = await Database.getClients(); const cidrBlock = parseCidr(system.userConfig.addressRange).prefix; + const cidr6Block = parseCidr(system.userConfig.addressRange6).prefix; let result = ` # Note: Do not edit this file directly. # Your changes will be overwritten! @@ -29,7 +30,7 @@ class WireGuard { # Server [Interface] PrivateKey = ${system.interface.privateKey} -Address = ${system.interface.address}/${cidrBlock} +Address = ${system.interface.address}/${cidrBlock}, ${system.interface.address6}/${cidr6Block} ListenPort = ${system.wgPort} PreUp = ${system.iptables.PreUp} PostUp = ${system.iptables.PostUp} @@ -46,7 +47,7 @@ PostDown = ${system.iptables.PostDown} [Peer] PublicKey = ${client.publicKey} PresharedKey = ${client.preSharedKey} -AllowedIPs = ${client.address}/32`; +AllowedIPs = ${client.address}/32, ${client.address6}/128`; } DEBUG('Config saving...'); @@ -69,6 +70,7 @@ AllowedIPs = ${client.address}/32`; name: client.name, enabled: client.enabled, address: client.address, + address6: client.address6, publicKey: client.publicKey, createdAt: new Date(client.createdAt), updatedAt: new Date(client.updatedAt), @@ -139,13 +141,13 @@ AllowedIPs = ${client.address}/32`; [Interface] PrivateKey = ${client.privateKey} Address = ${client.address} -DNS = ${system.userConfig.defaultDns.join(',')} +DNS = ${system.userConfig.defaultDns.join(', ')} MTU = ${system.userConfig.mtu} [Peer] PublicKey = ${system.interface.publicKey} PresharedKey = ${client.preSharedKey} -AllowedIPs = ${client.allowedIPs} +AllowedIPs = ${client.allowedIPs.join(', ')} PersistentKeepalive = ${client.persistentKeepalive} Endpoint = ${system.wgHost}:${system.wgConfigPort}`; } @@ -181,7 +183,7 @@ Endpoint = ${system.wgHost}:${system.wgConfigPort}`; // Calculate next IP const cidr = parseCidr(system.userConfig.addressRange); let address; - for (let i = cidr.start + 2n; i <= cidr.end - 2n; i++) { + for (let i = cidr.start + 2n; i <= cidr.end - 1n; i++) { const currentIp = stringifyIp({ number: i, version: 4 }); const client = Object.values(clients).find((client) => { return client.address === currentIp; @@ -197,6 +199,24 @@ Endpoint = ${system.wgHost}:${system.wgConfigPort}`; throw new Error('Maximum number of clients reached.'); } + const cidr6 = parseCidr(system.userConfig.addressRange6); + let address6; + for (let i = cidr6.start + 2n; i <= cidr.end - 1n; i++) { + const currentIp6 = stringifyIp({ number: i, version: 6 }); + const client = Object.values(clients).find((client) => { + return client.address6 === currentIp6; + }); + + if (!client) { + address6 = currentIp6; + break; + } + } + + if (!address6) { + throw new Error('Maximum number of clients reached.'); + } + // Create Client const id = crypto.randomUUID(); @@ -204,6 +224,7 @@ Endpoint = ${system.wgHost}:${system.wgConfigPort}`; id, name, address, + address6, privateKey, publicKey, preSharedKey, diff --git a/src/services/database/migrations/1.ts b/src/services/database/migrations/1.ts index 281d9b09..ed944bf0 100644 --- a/src/services/database/migrations/1.ts +++ b/src/services/database/migrations/1.ts @@ -19,8 +19,8 @@ export async function run1(db: Low) { interface: { privateKey: privateKey, publicKey: publicKey, - address: stringifyIp({ number: cidr.start, version: 4 }), - address6: stringifyIp({ number: cidr6.start, version: 6 }), + address: stringifyIp({ number: cidr.start + 1n, version: 4 }), + address6: stringifyIp({ number: cidr6.start + 1n, version: 6 }), }, sessionTimeout: 3600, // 1 hour lang: 'en', @@ -71,19 +71,29 @@ export async function run1(db: Low) { }; // TODO: use variables inside up/down script + // TODO: properly check if ipv6 support database.system.iptables.PostUp = ` iptables -t nat -A POSTROUTING -s ${database.system.userConfig.addressRange} -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; +ip6tables -t nat -A POSTROUTING -s ${database.system.userConfig.addressRange6} -o ${database.system.wgDevice} -j MASQUERADE; +ip6tables -A INPUT -p udp -m udp --dport ${database.system.wgPort} -j ACCEPT; +ip6tables -A FORWARD -i wg0 -j ACCEPT; +ip6tables -A FORWARD -o wg0 -j ACCEPT; ` .split('\n') .join(' '); + database.system.iptables.PostDown = ` iptables -t nat -D POSTROUTING -s ${database.system.userConfig.addressRange} -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; +ip6tables -t nat -D POSTROUTING -s ${database.system.userConfig.addressRange6} -o ${database.system.wgDevice} -j MASQUERADE; +ip6tables -D INPUT -p udp -m udp --dport ${database.system.wgPort} -j ACCEPT; +ip6tables -D FORWARD -i wg0 -j ACCEPT; +ip6tables -D FORWARD -o wg0 -j ACCEPT; ` .split('\n') .join(' '); diff --git a/src/services/database/repositories/client.ts b/src/services/database/repositories/client.ts index 8666f300..eb25eacf 100644 --- a/src/services/database/repositories/client.ts +++ b/src/services/database/repositories/client.ts @@ -8,6 +8,7 @@ export type Client = { id: string; name: string; address: string; + address6: string; privateKey: string; publicKey: string; preSharedKey: string;