From a3799b30539fd0aae8f17b56224aa9ff88bca8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2?= Date: Fri, 26 Jul 2024 16:23:58 +0200 Subject: [PATCH] feat(server): add IP trust list for reverse proxy (#11286) * feat(server): add IP trust list for reverse proxy Signed-off-by: hitech95 * feat(docs): add documentation of `IMMICH_TRUSTED_PROXIES` env Signed-off-by: hitech95 --------- Signed-off-by: hitech95 --- docs/docs/install/environment-variables.md | 1 + server/src/config.ts | 16 +++++++++++++++- server/src/workers/api.ts | 11 ++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/docs/install/environment-variables.md b/docs/docs/install/environment-variables.md index 4f09818d8f..5cbef2cbf1 100644 --- a/docs/docs/install/environment-variables.md +++ b/docs/docs/install/environment-variables.md @@ -50,6 +50,7 @@ Regardless of filesystem, it is not recommended to use a network share for your | `IMMICH_API_METRICS_PORT` | Port for the OTEL metrics | `8081` | server | api | | `IMMICH_MICROSERVICES_METRICS_PORT` | Port for the OTEL metrics | `8082` | server | microservices | | `IMMICH_PROCESS_INVALID_IMAGES` | When `true`, generate thumbnails for invalid images | | server | microservices | +| `IMMICH_TRUSTED_PROXIES` | List of comma separated IPs set as trusted proxies | | server | api | \*1: With the default `WORKDIR` of `/usr/src/app`, this path will resolve to `/usr/src/app/upload`. It only need to be set if the Immich deployment method is changing. diff --git a/server/src/config.ts b/server/src/config.ts index c7d16826bf..96ce63cf45 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -4,7 +4,7 @@ import { CronExpression } from '@nestjs/schedule'; import { QueueOptions } from 'bullmq'; import { Request, Response } from 'express'; import { RedisOptions } from 'ioredis'; -import Joi from 'joi'; +import Joi, { Root } from 'joi'; import { CLS_ID, ClsModuleOptions } from 'nestjs-cls'; import { ImmichHeader } from 'src/dtos/auth.dto'; import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface'; @@ -388,6 +388,20 @@ export const immichAppConfig: ConfigModuleOptions = { IMMICH_API_METRICS_PORT: Joi.number().optional(), IMMICH_MICROSERVICES_METRICS_PORT: Joi.number().optional(), + IMMICH_TRUSTED_PROXIES: Joi.extend((joi: Root) => ({ + type: 'stringArray', + base: joi.array(), + coerce: (value) => (value.split ? value.split(',') : value), + })) + .stringArray() + .single() + .items( + Joi.string().ip({ + version: ['ipv4', 'ipv6'], + cidr: 'optional', + }), + ), + IMMICH_METRICS: Joi.boolean().optional().default(false), IMMICH_HOST_METRICS: Joi.boolean().optional().default(false), IMMICH_API_METRICS: Joi.boolean().optional().default(false), diff --git a/server/src/workers/api.ts b/server/src/workers/api.ts index 8166665515..5857f587a0 100644 --- a/server/src/workers/api.ts +++ b/server/src/workers/api.ts @@ -14,9 +14,18 @@ import { useSwagger } from 'src/utils/misc'; const host = process.env.HOST; +function parseTrustedProxy(input?: string) { + if (!input) { + return []; + } + // Split on ',' char to allow multiple IPs + return input.split(','); +} + async function bootstrap() { process.title = 'immich-api'; const otelPort = Number.parseInt(process.env.IMMICH_API_METRICS_PORT ?? '8081'); + const trustedProxies = parseTrustedProxy(process.env.IMMICH_TRUSTED_PROXIES ?? ''); otelStart(otelPort); @@ -27,7 +36,7 @@ async function bootstrap() { logger.setAppName('Api'); logger.setContext('Bootstrap'); app.useLogger(logger); - app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']); + app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal', ...trustedProxies]); app.set('etag', 'strong'); app.use(cookieParser()); app.use(json({ limit: '10mb' }));