diff --git a/Dockerfile b/Dockerfile index 71a85257..236cb4eb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -54,6 +54,7 @@ ENV PORT=51821 ENV HOST=0.0.0.0 ENV INSECURE=false ENV INIT_ENABLED=false +ENV DISABLE_IPV6=false LABEL org.opencontainers.image.source=https://github.com/wg-easy/wg-easy diff --git a/Dockerfile.dev b/Dockerfile.dev index d130ad49..d0857ad8 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -28,6 +28,7 @@ ENV PORT=51821 ENV HOST=0.0.0.0 ENV INSECURE=true ENV INIT_ENABLED=false +ENV DISABLE_IPV6=false # Install Dependencies COPY src/package.json src/pnpm-lock.yaml ./ diff --git a/docs/content/advanced/config/optional-config.md b/docs/content/advanced/config/optional-config.md index 34d94db7..7598b9f3 100644 --- a/docs/content/advanced/config/optional-config.md +++ b/docs/content/advanced/config/optional-config.md @@ -4,8 +4,17 @@ title: Optional Configuration You can set these environment variables to configure the container. They are not required, but can be useful in some cases. -| Env | Default | Example | Description | -| ---------- | --------- | ----------- | ------------------------------ | -| `PORT` | `51821` | `6789` | TCP port for Web UI. | -| `HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. | -| `INSECURE` | `false` | `true` | If access over http is allowed | +| Env | Default | Example | Description | +| -------------- | --------- | ----------- | ---------------------------------- | +| `PORT` | `51821` | `6789` | TCP port for Web UI. | +| `HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. | +| `INSECURE` | `false` | `true` | If access over http is allowed | +| `DISABLE_IPV6` | `false` | `true` | If IPv6 support should be disabled | + +/// note | IPv6 Caveats + +Disabling IPv6 will only disable the creation of the default IPv6 firewall rules. The clients will still get an IPv6 address assigned. + +This option can be removed in the future, as more devices support IPv6. + +/// diff --git a/src/server/database/sqlite.ts b/src/server/database/sqlite.ts index dbfade9b..c09523c7 100644 --- a/src/server/database/sqlite.ts +++ b/src/server/database/sqlite.ts @@ -2,6 +2,7 @@ import { drizzle } from 'drizzle-orm/libsql'; import { migrate as drizzleMigrate } from 'drizzle-orm/libsql/migrator'; import { createClient } from '@libsql/client'; import debug from 'debug'; +import { eq } from 'drizzle-orm'; import * as schema from './schema'; import { ClientService } from './repositories/client/service'; @@ -25,6 +26,11 @@ export async function connect() { await initialSetup(dbService); } + if (WG_ENV.DISABLE_IPV6) { + DB_DEBUG('Warning: Disabling IPv6...'); + await disableIpv6(db); + } + return dbService; } @@ -108,3 +114,48 @@ async function initialSetup(db: DBServiceType) { await db.general.setSetupStep(0); } } + +async function disableIpv6(db: DBType) { + // This should match the initial value migration + const postUpMatch = + ' ip6tables -t nat -A POSTROUTING -s {{ipv6Cidr}} -o {{device}} -j MASQUERADE; ip6tables -A INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT;'; + const postDownMatch = + ' ip6tables -t nat -D POSTROUTING -s {{ipv6Cidr}} -o {{device}} -j MASQUERADE; ip6tables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT;'; + + await db.transaction(async (tx) => { + const hooks = await tx.query.hooks.findFirst({ + where: eq(schema.hooks.id, 'wg0'), + }); + + if (!hooks) { + throw new Error('Hooks not found'); + } + + if (hooks.postUp.includes(postUpMatch)) { + DB_DEBUG('Disabling IPv6 in Post Up hooks...'); + await tx + .update(schema.hooks) + .set({ + postUp: hooks.postUp.replace(postUpMatch, ''), + postDown: hooks.postDown.replace(postDownMatch, ''), + }) + .where(eq(schema.hooks.id, 'wg0')) + .execute(); + } else { + DB_DEBUG('IPv6 Post Up hooks already disabled, skipping...'); + } + if (hooks.postDown.includes(postDownMatch)) { + DB_DEBUG('Disabling IPv6 in Post Down hooks...'); + await tx + .update(schema.hooks) + .set({ + postUp: hooks.postUp.replace(postUpMatch, ''), + postDown: hooks.postDown.replace(postDownMatch, ''), + }) + .where(eq(schema.hooks.id, 'wg0')) + .execute(); + } else { + DB_DEBUG('IPv6 Post Down hooks already disabled, skipping...'); + } + }); +} diff --git a/src/server/utils/config.ts b/src/server/utils/config.ts index f6e89242..886c0a28 100644 --- a/src/server/utils/config.ts +++ b/src/server/utils/config.ts @@ -17,6 +17,8 @@ export const WG_ENV = { INSECURE: process.env.INSECURE === 'true', /** Port the UI is listening on */ PORT: assertEnv('PORT'), + /** If IPv6 should be disabled */ + DISABLE_IPV6: process.env.DISABLE_IPV6 === 'true', }; export const WG_INITIAL_ENV = {