feat: add a trust proxy env to control whether to trust incoming x-forwarded-for headers
This commit is contained in:
parent
8fdf858dcb
commit
4f735f122f
4 changed files with 21 additions and 1 deletions
|
|
@ -5,4 +5,5 @@ ZEROBYTE_REPOSITORIES_DIR=./data/repositories
|
||||||
ZEROBYTE_VOLUMES_DIR=./data/volumes
|
ZEROBYTE_VOLUMES_DIR=./data/volumes
|
||||||
APP_SECRET=<openssl rand -hex 32>
|
APP_SECRET=<openssl rand -hex 32>
|
||||||
BASE_URL=http://localhost:300
|
BASE_URL=http://localhost:300
|
||||||
|
TRUST_PROXY=false
|
||||||
PORT=3000
|
PORT=3000
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ Zerobyte can be customized using environment variables. Below are the available
|
||||||
| `PORT` | The port the web interface and API will listen on. | `4096` |
|
| `PORT` | The port the web interface and API will listen on. | `4096` |
|
||||||
| `RESTIC_HOSTNAME` | The hostname used by Restic when creating snapshots. Automatically detected if a custom hostname is set in Docker. | `zerobyte` |
|
| `RESTIC_HOSTNAME` | The hostname used by Restic when creating snapshots. Automatically detected if a custom hostname is set in Docker. | `zerobyte` |
|
||||||
| `TZ` | Timezone for the container (e.g., `Europe/Zurich`). **Crucial for accurate backup scheduling.** | `UTC` |
|
| `TZ` | Timezone for the container (e.g., `Europe/Zurich`). **Crucial for accurate backup scheduling.** | `UTC` |
|
||||||
|
| `TRUST_PROXY` | When `true`, trust an existing `X-Forwarded-For` header from your reverse proxy. Leave `false` for direct deployments. | `false` |
|
||||||
| `TRUSTED_ORIGINS` | Comma-separated list of extra trusted origins for CORS (e.g., `http://localhost:3000,http://example.com`). | (none) |
|
| `TRUSTED_ORIGINS` | Comma-separated list of extra trusted origins for CORS (e.g., `http://localhost:3000,http://example.com`). | (none) |
|
||||||
| `LOG_LEVEL` | Logging verbosity. Options: `debug`, `info`, `warn`, `error`. | `info` |
|
| `LOG_LEVEL` | Logging verbosity. Options: `debug`, `info`, `warn`, `error`. | `info` |
|
||||||
| `SERVER_IDLE_TIMEOUT` | Idle timeout for the server in seconds. | `60` |
|
| `SERVER_IDLE_TIMEOUT` | Idle timeout for the server in seconds. | `60` |
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { config } from "~/server/core/config";
|
||||||
const app = createApp();
|
const app = createApp();
|
||||||
|
|
||||||
type NodeRuntimeRequest = Request & {
|
type NodeRuntimeRequest = Request & {
|
||||||
|
ip?: string;
|
||||||
runtime?: {
|
runtime?: {
|
||||||
node?: {
|
node?: {
|
||||||
res?: { setTimeout: (timeoutMs: number) => void };
|
res?: { setTimeout: (timeoutMs: number) => void };
|
||||||
|
|
@ -16,7 +17,22 @@ export const prepareApiRequest = (request: Request, timeoutMs: number) => {
|
||||||
const nodeRequest = request as NodeRuntimeRequest;
|
const nodeRequest = request as NodeRuntimeRequest;
|
||||||
nodeRequest.runtime?.node?.res?.setTimeout(timeoutMs);
|
nodeRequest.runtime?.node?.res?.setTimeout(timeoutMs);
|
||||||
|
|
||||||
return request.clone();
|
if (config.trustProxy && request.headers.has("x-forwarded-for")) {
|
||||||
|
return request.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
const remoteAddress = nodeRequest.ip;
|
||||||
|
if (remoteAddress) {
|
||||||
|
const headers = new Headers(request.headers);
|
||||||
|
headers.set("x-forwarded-for", remoteAddress);
|
||||||
|
|
||||||
|
return new Request(request, { headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = new Headers(request.headers);
|
||||||
|
headers.delete("x-forwarded-for");
|
||||||
|
|
||||||
|
return new Request(request, { headers });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handle = ({ request }: { request: Request }) =>
|
const handle = ({ request }: { request: Request }) =>
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ const envSchema = z
|
||||||
MIGRATIONS_PATH: z.string().optional(),
|
MIGRATIONS_PATH: z.string().optional(),
|
||||||
APP_VERSION: z.string().default("dev"),
|
APP_VERSION: z.string().default("dev"),
|
||||||
TRUSTED_ORIGINS: z.string().optional(),
|
TRUSTED_ORIGINS: z.string().optional(),
|
||||||
|
TRUST_PROXY: z.string().default("false"),
|
||||||
DISABLE_RATE_LIMITING: z.string().default("false"),
|
DISABLE_RATE_LIMITING: z.string().default("false"),
|
||||||
APP_SECRET: z.string().min(32).max(256),
|
APP_SECRET: z.string().min(32).max(256),
|
||||||
BASE_URL: z.string(),
|
BASE_URL: z.string(),
|
||||||
|
|
@ -53,6 +54,7 @@ const envSchema = z
|
||||||
.map((origin) => origin.trim())
|
.map((origin) => origin.trim())
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.concat(s.BASE_URL) ?? [s.BASE_URL],
|
.concat(s.BASE_URL) ?? [s.BASE_URL],
|
||||||
|
trustProxy: s.TRUST_PROXY === "true",
|
||||||
disableRateLimiting: s.DISABLE_RATE_LIMITING === "true",
|
disableRateLimiting: s.DISABLE_RATE_LIMITING === "true",
|
||||||
appSecret: s.APP_SECRET,
|
appSecret: s.APP_SECRET,
|
||||||
baseUrl: s.BASE_URL,
|
baseUrl: s.BASE_URL,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue