Browse Source

start supporting ipv6

pull/1354/head
Bernd Storath 2 years ago
parent
commit
ea490f9882
  1. 2
      Dockerfile
  2. 2
      Dockerfile.dev
  3. 3
      docker-compose.yml
  4. 3
      src/package.json
  5. 82
      src/pnpm-lock.yaml
  6. 3
      src/server/api/release.get.ts
  7. 2
      src/server/api/session.post.ts
  8. 20
      src/server/utils/WireGuard.ts
  9. 3
      src/server/utils/config.ts
  10. 17
      src/services/database/migrations/1.ts
  11. 4
      src/services/database/repositories/system.ts

2
Dockerfile

@ -27,11 +27,13 @@ RUN apk add --no-cache \
dpkg \
dumb-init \
iptables \
ip6tables \
iptables-legacy \
wireguard-tools
# Use iptables-legacy
RUN update-alternatives --install /sbin/iptables iptables /sbin/iptables-legacy 10 --slave /sbin/iptables-restore iptables-restore /sbin/iptables-legacy-restore --slave /sbin/iptables-save iptables-save /sbin/iptables-legacy-save
RUN update-alternatives --install /sbin/ip6tables ip6tables /sbin/ip6tables-legacy 10 --slave /sbin/ip6tables-restore ip6tables-restore /sbin/ip6tables-legacy-restore --slave /sbin/ip6tables-save ip6tables-save /sbin/ip6tables-legacy-save
# Set Environment
ENV DEBUG=Server,WireGuard,LowDB

2
Dockerfile.dev

@ -17,11 +17,13 @@ RUN apk add --no-cache \
dpkg \
dumb-init \
iptables \
ip6tables \
iptables-legacy \
wireguard-tools
# Use iptables-legacy
RUN update-alternatives --install /sbin/iptables iptables /sbin/iptables-legacy 10 --slave /sbin/iptables-restore iptables-restore /sbin/iptables-legacy-restore --slave /sbin/iptables-save iptables-save /sbin/iptables-legacy-save
RUN update-alternatives --install /sbin/ip6tables ip6tables /sbin/ip6tables-legacy 10 --slave /sbin/ip6tables-restore ip6tables-restore /sbin/ip6tables-legacy-restore --slave /sbin/ip6tables-save ip6tables-save /sbin/ip6tables-legacy-save
# Set Environment
ENV DEBUG=Server,WireGuard,LowDB

3
docker-compose.yml

@ -24,3 +24,6 @@ services:
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
- net.ipv6.conf.all.disable_ipv6=0
- net.ipv6.conf.all.forwarding=1
- net.ipv6.conf.default.forwarding=1

3
src/package.json

@ -27,9 +27,12 @@
"apexcharts": "^3.53.0",
"basic-auth": "^2.0.1",
"bcryptjs": "^2.4.3",
"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",
"lowdb": "^7.0.1",
"nuxt": "^3.13.0",

82
src/pnpm-lock.yaml

@ -32,6 +32,9 @@ importers:
bcryptjs:
specifier: ^2.4.3
version: 2.4.3
cidr-tools:
specifier: ^11.0.2
version: 11.0.2
crc-32:
specifier: ^1.2.2
version: 1.2.2
@ -41,6 +44,12 @@ importers:
ip:
specifier: ^2.0.1
version: 2.0.1
ip-bigint:
specifier: ^8.2.0
version: 8.2.0
is-ip:
specifier: ^5.0.1
version: 5.0.1
js-sha256:
specifier: ^0.11.0
version: 0.11.0
@ -1678,6 +1687,10 @@ packages:
resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==}
engines: {node: '>=8'}
[email protected]:
resolution: {integrity: sha512-OLeM9EOXybbhMsGGBNRLCMjn8e+wFOXARIShF/sZwmJLsxWywqfE0By4BMftT6BFWpbcETWpW7TfM2KGCtrZDg==}
engines: {node: '>=18'}
[email protected]:
resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
@ -1699,6 +1712,10 @@ packages:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
[email protected]:
resolution: {integrity: sha512-ujdnoq2Kxb8s3ItNBtnYeXdm07FcU0u8ARAT1lQ2YdMwQC+cdiXX8KoqMVuglztILivceTtp4ivqGSmEmhBUJw==}
engines: {node: '>=12'}
[email protected]:
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
engines: {node: '>=0.10.0'}
@ -1784,6 +1801,10 @@ packages:
resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
engines: {node: '>= 0.6'}
[email protected]:
resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==}
engines: {node: '>=12'}
[email protected]:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
@ -2338,6 +2359,10 @@ packages:
[email protected]:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
[email protected]:
resolution: {integrity: sha512-0NVVC0TaP7dSTvn1yMiy6d6Q8gifzbvQafO46RtLG/kHJUBNd+pVRGOBoK44wNBvtSPUJRfdVvkFdD3p0xvyZg==}
engines: {node: '>=14.16'}
[email protected]:
resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
engines: {node: '>=10'}
@ -2555,6 +2580,14 @@ packages:
resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==}
engines: {node: '>=12.22.0'}
[email protected]:
resolution: {integrity: sha512-46EAEKzGNxojH5JaGEeCix49tL4h1W8ia5mhogZ68HroVAfyLj1E+SFFid4GuyK0mdIKjwcAITLqwg1wlkx2iQ==}
engines: {node: '>=18'}
[email protected]:
resolution: {integrity: sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
[email protected]:
resolution: {integrity: sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==}
@ -2614,6 +2647,10 @@ packages:
resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==}
engines: {node: '>=18'}
[email protected]:
resolution: {integrity: sha512-FCsGHdlrOnZQcp0+XT5a+pYowf33itBalCl+7ovNXC/7o5BhIpG14M3OrpPPdBSIQJCm+0M5+9mO7S9VVTTCFw==}
engines: {node: '>=14.16'}
[email protected]:
resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
@ -2632,6 +2669,10 @@ packages:
[email protected]:
resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
[email protected]:
resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==}
engines: {node: '>=12'}
[email protected]:
resolution: {integrity: sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==}
@ -3843,6 +3884,10 @@ packages:
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
[email protected]:
resolution: {integrity: sha512-WZzIx3rC1CvbMDloLsVw0lkZVKJWbrkJ0k1ghKFmcnPrW1+jWbgTkTEWVtD9lMdmI4jZEz40+naBxl1dCUhXXw==}
engines: {node: '>=14.16'}
[email protected]:
resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==}
engines: {node: '>=16'}
@ -3951,6 +3996,10 @@ packages:
[email protected]:
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
[email protected]:
resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==}
engines: {node: '>=12'}
[email protected]:
resolution: {integrity: sha512-a7wPxPdVlQL7lqvitHGGRsofhdwtkoSXPGATFuSOA2i1ZNQEPLrGnj68vOp2sOJTCFAQVXPeNMX/GctBaO9L2w==}
@ -6214,6 +6263,10 @@ snapshots:
[email protected]: {}
[email protected]:
dependencies:
ip-bigint: 8.2.0
[email protected]:
dependencies:
consola: 3.2.3
@ -6242,6 +6295,10 @@ snapshots:
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
[email protected]:
dependencies:
is-regexp: 3.1.0
[email protected]: {}
[email protected]: {}
@ -6302,6 +6359,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {}
@ -6951,6 +7010,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
aproba: 2.0.0
@ -7190,6 +7251,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {}
@ -7235,6 +7300,11 @@ snapshots:
global-directory: 4.0.1
is-path-inside: 4.0.0
[email protected]:
dependencies:
ip-regex: 5.0.0
super-regex: 0.2.0
[email protected]: {}
[email protected]: {}
@ -7247,6 +7317,8 @@ snapshots:
dependencies:
'@types/estree': 1.0.5
[email protected]: {}
[email protected]:
dependencies:
protocols: 2.0.1
@ -8598,6 +8670,12 @@ snapshots:
pirates: 4.0.6
ts-interface-checker: 0.1.13
[email protected]:
dependencies:
clone-regexp: 3.0.0
function-timeout: 0.1.1
time-span: 5.1.0
[email protected]:
dependencies:
copy-anything: 3.0.5
@ -8743,6 +8821,10 @@ snapshots:
dependencies:
any-promise: 1.3.0
[email protected]:
dependencies:
convert-hrtime: 5.0.0
[email protected]: {}
[email protected]: {}

3
src/server/api/release.get.ts

@ -1,8 +1,7 @@
export default defineEventHandler(async () => {
const system = await Database.getSystem();
const latestRelease = await fetchLatestRelease();
return {
currentRelease: system.release,
currentRelease: RELEASE,
latestRelease: latestRelease,
};
});

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

@ -29,7 +29,7 @@ export default defineEventHandler(async (event) => {
if (remember) {
conf.cookie = {
...(system.sessionConfig.cookie ?? {}),
maxAge: system.cookieMaxAge * 60,
maxAge: system.sessionTimeout,
};
}

20
src/server/utils/WireGuard.ts

@ -6,7 +6,9 @@ import QRCode from 'qrcode';
import CRC32 from 'crc-32';
import type { NewClient } from '~~/services/database/repositories/client';
import ip from 'ip';
import { parseCidr } from 'cidr-tools';
import { stringifyIp } from 'ip-bigint';
import { isIPv4 } from 'is-ip';
const DEBUG = debug('WireGuard');
@ -19,9 +21,7 @@ class WireGuard {
async #saveWireguardConfig() {
const system = await Database.getSystem();
const clients = await Database.getClients();
const cidrBlock = ip.cidrSubnet(
system.userConfig.addressRange
).subnetMaskLength;
const cidrBlock = parseCidr(system.userConfig.addressRange).prefix;
let result = `
# Note: Do not edit this file directly.
# Your changes will be overwritten!
@ -179,14 +179,10 @@ Endpoint = ${system.wgHost}:${system.wgConfigPort}`;
const preSharedKey = await exec('wg genpsk');
// Calculate next IP
const cidr = ip.cidrSubnet(system.userConfig.addressRange);
const cidr = parseCidr(system.userConfig.addressRange);
let address;
for (
let i = ip.toLong(cidr.firstAddress) + 1;
i <= ip.toLong(cidr.lastAddress) - 1;
i++
) {
const currentIp = ip.fromLong(i);
for (let i = cidr.start + 2n; i <= cidr.end - 2n; i++) {
const currentIp = stringifyIp({ number: i, version: 4 });
const client = Object.values(clients).find((client) => {
return client.address === currentIp;
});
@ -286,7 +282,7 @@ Endpoint = ${system.wgHost}:${system.wgConfigPort}`;
clientId: string;
address: string;
}) {
if (!ip.isV4Format(address)) {
if (!isIPv4(address)) {
throw createError({
statusCode: 400,
statusMessage: `Invalid Address: ${address}`,

3
src/server/utils/config.ts

@ -1,5 +1,8 @@
import debug from 'debug';
import packageJson from '@@/package.json';
export const WG_PATH = process.env.WG_PATH || '/etc/wireguard/';
export const RELEASE = packageJson.release.version;
export const SERVER_DEBUG = debug('Server');

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

@ -1,8 +1,8 @@
import type { Low } from 'lowdb';
import type { Database } from '../repositories/database';
import packageJson from '@@/package.json';
import { ChartType } from '../repositories/system';
import ip from 'ip';
import { parseCidr } from 'cidr-tools';
import { stringifyIp } from 'ip-bigint';
export async function run1(db: Low<Database>) {
const privateKey = await exec('wg genkey');
@ -10,16 +10,17 @@ export async function run1(db: Low<Database>) {
log: 'echo ***hidden*** | wg pubkey',
});
const addressRange = '10.8.0.0/24';
const cidr = ip.cidrSubnet(addressRange);
const addressRange6 = 'fdcc:ad94:bacf:61a4::cafe:0/112';
const cidr = parseCidr(addressRange);
const cidr6 = parseCidr(addressRange6);
const database: Database = {
migrations: [],
system: {
// TODO: move to var, no need for database
release: packageJson.release.version,
interface: {
privateKey: privateKey,
publicKey: publicKey,
address: cidr.firstAddress,
address: stringifyIp({ number: cidr.start, version: 4 }),
address6: stringifyIp({ number: cidr6.start, version: 6 }),
},
sessionTimeout: 3600, // 1 hour
lang: 'en',
@ -27,7 +28,8 @@ export async function run1(db: Low<Database>) {
mtu: 1420,
persistentKeepalive: 0,
addressRange: addressRange,
defaultDns: ['1.1.1.1'],
addressRange6: addressRange6,
defaultDns: ['1.1.1.1', '2606:4700:4700::1111'],
allowedIps: ['0.0.0.0/0', '::/0'],
},
wgDevice: 'eth0',
@ -63,7 +65,6 @@ export async function run1(db: Low<Database>) {
name: 'wg-easy',
cookie: {},
},
cookieMaxAge: 24 * 60,
},
users: [],
clients: {},

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

@ -13,12 +13,14 @@ export type WGInterface = {
privateKey: string;
publicKey: string;
address: string;
address6: string;
};
export type WGConfig = {
mtu: number;
persistentKeepalive: number;
addressRange: string;
addressRange6: string;
defaultDns: string[];
allowedIps: string[];
};
@ -50,7 +52,6 @@ export type Feature = {
export type System = {
interface: WGInterface;
release: string;
// maxAge
sessionTimeout: number;
lang: Lang;
@ -71,7 +72,6 @@ export type System = {
prometheus: Prometheus;
sessionConfig: SessionConfig;
cookieMaxAge: number;
};
/**

Loading…
Cancel
Save