diff options
| author | Hazelnoot <acomputerdog@gmail.com> | 2025-05-11 23:22:41 -0400 |
|---|---|---|
| committer | Hazelnoot <acomputerdog@gmail.com> | 2025-05-12 21:44:45 -0400 |
| commit | fb63167d854f277ffeb82da720580b3e99f9cc8c (patch) | |
| tree | c060ff042e9f1b815206dedee64acd2dc60eec72 /packages/backend/src/config.ts | |
| parent | merge: Add "is from local bubble instance" role condition (!1011) (diff) | |
| download | sharkey-fb63167d854f277ffeb82da720580b3e99f9cc8c.tar.gz sharkey-fb63167d854f277ffeb82da720580b3e99f9cc8c.tar.bz2 sharkey-fb63167d854f277ffeb82da720580b3e99f9cc8c.zip | |
allow private IP ranges to specify allowed ports
Diffstat (limited to 'packages/backend/src/config.ts')
| -rw-r--r-- | packages/backend/src/config.ts | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 92fc2b8a13..2a3184f9b4 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -8,9 +8,11 @@ import { fileURLToPath } from 'node:url'; import { dirname, resolve } from 'node:path'; import * as yaml from 'js-yaml'; import { globSync } from 'glob'; +import ipaddr from 'ipaddr.js'; import type * as Sentry from '@sentry/node'; import type * as SentryVue from '@sentry/vue'; import type { RedisOptions } from 'ioredis'; +import type { IPv4, IPv6 } from 'ipaddr.js'; type RedisOptionsSource = Partial<RedisOptions> & { host?: string; @@ -152,6 +154,33 @@ type Source = { } }; +export type PrivateNetwork = { + /** + * CIDR IP/netmask definition of the IP range to match. + */ + cidr: [ip: IPv4 | IPv6, mask: number]; + + /** + * List of ports to match. + * If undefined, then all ports match. + * If empty, then NO ports match. + */ + ports?: number[]; +}; + +export function parsePrivateNetworks(patterns: string[]): PrivateNetwork[]; +export function parsePrivateNetworks(patterns: undefined): undefined; +export function parsePrivateNetworks(patterns: string[] | undefined): PrivateNetwork[] | undefined; +export function parsePrivateNetworks(patterns: string[] | undefined): PrivateNetwork[] | undefined { + return patterns?.map(e => { + const [ip, ports] = e.split('#') as [string, ...(string | undefined)[]]; + return { + cidr: ipaddr.parseCIDR(ip), + ports: ports?.split(',').map(p => parseInt(p)), + }; + }); +} + export type Config = { url: string; port: number; @@ -190,7 +219,7 @@ export type Config = { proxy: string | undefined; proxySmtp: string | undefined; proxyBypassHosts: string[] | undefined; - allowedPrivateNetworks: string[] | undefined; + allowedPrivateNetworks: PrivateNetwork[] | undefined; disallowExternalApRedirect: boolean; maxFileSize: number; maxNoteLength: number; @@ -382,7 +411,7 @@ export function loadConfig(): Config { proxy: config.proxy, proxySmtp: config.proxySmtp, proxyBypassHosts: config.proxyBypassHosts, - allowedPrivateNetworks: config.allowedPrivateNetworks, + allowedPrivateNetworks: parsePrivateNetworks(config.allowedPrivateNetworks), disallowExternalApRedirect: config.disallowExternalApRedirect ?? false, maxFileSize: config.maxFileSize ?? 262144000, maxNoteLength: config.maxNoteLength ?? 3000, |