change: trust proxy option

This commit is contained in:
Julian Krauser 2025-02-08 11:04:46 +01:00
parent 1006a2b1c1
commit 80b083f1aa
5 changed files with 54 additions and 6 deletions

View file

@ -42,4 +42,6 @@ SECURITY_STRICT_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 15
SECURITY_STRICT_LIMIT_REQUEST_COUNT = strict_request_count # default ist 15 SECURITY_STRICT_LIMIT_REQUEST_COUNT = strict_request_count # default ist 15
USE_SECURITY_LIMIT = (true|false) # default ist true USE_SECURITY_LIMIT = (true|false) # default ist true
SECURITY_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 1m SECURITY_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 1m
SECURITY_LIMIT_REQUEST_COUNT = request_count # default ist 500 SECURITY_LIMIT_REQUEST_COUNT = request_count # default ist 500
TRUST_PROXY = <boolean|number|ip|ip1,ip2,...> # wenn leer, wird dieser Wert nicht angewendet.

18
package-lock.json generated
View file

@ -17,6 +17,7 @@
"handlebars": "^4.7.8", "handlebars": "^4.7.8",
"helmet": "^8.0.0", "helmet": "^8.0.0",
"ics": "^3.8.1", "ics": "^3.8.1",
"ip": "^2.0.1",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"lodash.uniqby": "^4.7.0", "lodash.uniqby": "^4.7.0",
"moment": "^2.30.1", "moment": "^2.30.1",
@ -41,6 +42,7 @@
"devDependencies": { "devDependencies": {
"@types/cors": "^2.8.14", "@types/cors": "^2.8.14",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/ip": "^1.1.3",
"@types/jsonwebtoken": "^9.0.6", "@types/jsonwebtoken": "^9.0.6",
"@types/lodash.uniqby": "^4.7.9", "@types/lodash.uniqby": "^4.7.9",
"@types/morgan": "^1.9.9", "@types/morgan": "^1.9.9",
@ -535,6 +537,16 @@
"integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
"dev": true "dev": true
}, },
"node_modules/@types/ip": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@types/ip/-/ip-1.1.3.tgz",
"integrity": "sha512-64waoJgkXFTYnCYDUWgSATJ/dXEBanVkaP5d4Sbk7P6U7cTTMhxVyROTckc6JKdwCrgnAjZMn0k3177aQxtDEA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/jsonwebtoken": { "node_modules/@types/jsonwebtoken": {
"version": "9.0.6", "version": "9.0.6",
"resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz",
@ -2681,6 +2693,12 @@
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
}, },
"node_modules/ip": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
"integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==",
"license": "MIT"
},
"node_modules/ip-address": { "node_modules/ip-address": {
"version": "9.0.5", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",

View file

@ -32,6 +32,7 @@
"handlebars": "^4.7.8", "handlebars": "^4.7.8",
"helmet": "^8.0.0", "helmet": "^8.0.0",
"ics": "^3.8.1", "ics": "^3.8.1",
"ip": "^2.0.1",
"jsonwebtoken": "^9.0.2", "jsonwebtoken": "^9.0.2",
"lodash.uniqby": "^4.7.0", "lodash.uniqby": "^4.7.0",
"moment": "^2.30.1", "moment": "^2.30.1",
@ -56,6 +57,7 @@
"devDependencies": { "devDependencies": {
"@types/cors": "^2.8.14", "@types/cors": "^2.8.14",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
"@types/ip": "^1.1.3",
"@types/jsonwebtoken": "^9.0.6", "@types/jsonwebtoken": "^9.0.6",
"@types/lodash.uniqby": "^4.7.9", "@types/lodash.uniqby": "^4.7.9",
"@types/morgan": "^1.9.9", "@types/morgan": "^1.9.9",

View file

@ -1,5 +1,6 @@
import "dotenv/config"; import "dotenv/config";
import ms from "ms"; import ms from "ms";
import ip from "ip";
export const DB_TYPE = process.env.DB_TYPE ?? "mysql"; export const DB_TYPE = process.env.DB_TYPE ?? "mysql";
export const DB_HOST = process.env.DB_HOST ?? ""; export const DB_HOST = process.env.DB_HOST ?? "";
@ -35,6 +36,24 @@ export const USE_SECURITY_LIMIT = process.env.USE_SECURITY_LIMIT ?? "true";
export const SECURITY_LIMIT_WINDOW = process.env.SECURITY_LIMIT_WINDOW ?? "1m"; export const SECURITY_LIMIT_WINDOW = process.env.SECURITY_LIMIT_WINDOW ?? "1m";
export const SECURITY_LIMIT_REQUEST_COUNT = Number(process.env.SECURITY_LIMIT_REQUEST_COUNT ?? "500"); export const SECURITY_LIMIT_REQUEST_COUNT = Number(process.env.SECURITY_LIMIT_REQUEST_COUNT ?? "500");
export const TRUST_PROXY = ((): Array<string> | string | boolean | number | null => {
const proxyVal = process.env.TRUST_PROXY;
if (!proxyVal) return null;
if (proxyVal == "true" || proxyVal == "false") {
return proxyVal == "true";
}
if (!isNaN(Number(proxyVal))) {
return Number(proxyVal);
}
if (proxyVal.includes(",") && proxyVal.split(",").every((pv) => ip.isV4Format(pv) || ip.isV6Format(pv))) {
return proxyVal.split(",");
}
if (ip.isV4Format(proxyVal) || ip.isV6Format(proxyVal)) {
return proxyVal;
}
return null;
})();
export function configCheck() { export function configCheck() {
if (DB_TYPE != "mysql" && DB_TYPE != "sqlite" && DB_TYPE != "postgres") if (DB_TYPE != "mysql" && DB_TYPE != "sqlite" && DB_TYPE != "postgres")
throw new Error("set valid value to DB_TYPE (mysql|sqlite|postgres)"); throw new Error("set valid value to DB_TYPE (mysql|sqlite|postgres)");
@ -46,7 +65,7 @@ export function configCheck() {
if ((DB_PASSWORD == "" || typeof DB_PASSWORD != "string") && DB_TYPE != "sqlite") if ((DB_PASSWORD == "" || typeof DB_PASSWORD != "string") && DB_TYPE != "sqlite")
throw new Error("set valid value to DB_PASSWORD"); throw new Error("set valid value to DB_PASSWORD");
if (typeof SERVER_PORT != "number") throw new Error("set valid numeric value to SERVER_PORT"); if (isNaN(SERVER_PORT)) throw new Error("set valid numeric value to SERVER_PORT");
if (JWT_SECRET == "" || typeof JWT_SECRET != "string") throw new Error("set valid value to JWT_SECRET"); if (JWT_SECRET == "" || typeof JWT_SECRET != "string") throw new Error("set valid value to JWT_SECRET");
checkMS(JWT_EXPIRATION, "JWT_EXPIRATION"); checkMS(JWT_EXPIRATION, "JWT_EXPIRATION");
@ -56,7 +75,7 @@ export function configCheck() {
if (MAIL_USERNAME == "" || typeof MAIL_USERNAME != "string") throw new Error("set valid value to MAIL_USERNAME"); if (MAIL_USERNAME == "" || typeof MAIL_USERNAME != "string") throw new Error("set valid value to MAIL_USERNAME");
if (MAIL_PASSWORD == "" || typeof MAIL_PASSWORD != "string") throw new Error("set valid value to MAIL_PASSWORD"); if (MAIL_PASSWORD == "" || typeof MAIL_PASSWORD != "string") throw new Error("set valid value to MAIL_PASSWORD");
if (MAIL_HOST == "" || typeof MAIL_HOST != "string") throw new Error("set valid value to MAIL_HOST"); if (MAIL_HOST == "" || typeof MAIL_HOST != "string") throw new Error("set valid value to MAIL_HOST");
if (typeof MAIL_PORT != "number") throw new Error("set valid numeric value to MAIL_PORT"); if (isNaN(MAIL_PORT)) throw new Error("set valid numeric value to MAIL_PORT");
if (MAIL_SECURE != "true" && MAIL_SECURE != "false") throw new Error("set 'true' or 'false' to MAIL_SECURE"); if (MAIL_SECURE != "true" && MAIL_SECURE != "false") throw new Error("set 'true' or 'false' to MAIL_SECURE");
if ( if (
@ -73,13 +92,16 @@ export function configCheck() {
if (USE_SECURITY_STRICT_LIMIT != "true" && USE_SECURITY_STRICT_LIMIT != "false") if (USE_SECURITY_STRICT_LIMIT != "true" && USE_SECURITY_STRICT_LIMIT != "false")
throw new Error("set 'true' or 'false' to USE_SECURITY_STRICT_LIMIT"); throw new Error("set 'true' or 'false' to USE_SECURITY_STRICT_LIMIT");
checkMS(SECURITY_STRICT_LIMIT_WINDOW, "SECURITY_STRICT_LIMIT_WINDOW"); checkMS(SECURITY_STRICT_LIMIT_WINDOW, "SECURITY_STRICT_LIMIT_WINDOW");
if (typeof SECURITY_STRICT_LIMIT_REQUEST_COUNT != "number") if (isNaN(SECURITY_STRICT_LIMIT_REQUEST_COUNT))
throw new Error("set valid numeric value to SECURITY_STRICT_LIMIT_REQUEST_COUNT"); throw new Error("set valid numeric value to SECURITY_STRICT_LIMIT_REQUEST_COUNT");
if (USE_SECURITY_LIMIT != "true" && USE_SECURITY_LIMIT != "false") if (USE_SECURITY_LIMIT != "true" && USE_SECURITY_LIMIT != "false")
throw new Error("set 'true' or 'false' to USE_SECURITY_LIMIT"); throw new Error("set 'true' or 'false' to USE_SECURITY_LIMIT");
checkMS(SECURITY_LIMIT_WINDOW, "SECURITY_LIMIT_WINDOW"); checkMS(SECURITY_LIMIT_WINDOW, "SECURITY_LIMIT_WINDOW");
if (typeof SECURITY_LIMIT_REQUEST_COUNT != "number") if (isNaN(SECURITY_LIMIT_REQUEST_COUNT)) throw new Error("set valid numeric value to SECURITY_LIMIT_REQUEST_COUNT");
throw new Error("set valid numeric value to SECURITY_LIMIT_REQUEST_COUNT");
if (!TRUST_PROXY && process.env.TRUST_PROXY) {
throw new Error("set valid boolean, number, ip or ips value to TRUST_PROXY");
}
} }
function checkMS(input: string, origin: string) { function checkMS(input: string, origin: string) {

View file

@ -28,6 +28,7 @@ import {
SECURITY_LIMIT_WINDOW, SECURITY_LIMIT_WINDOW,
SECURITY_STRICT_LIMIT_REQUEST_COUNT, SECURITY_STRICT_LIMIT_REQUEST_COUNT,
SECURITY_STRICT_LIMIT_WINDOW, SECURITY_STRICT_LIMIT_WINDOW,
TRUST_PROXY,
USE_SECURITY_LIMIT, USE_SECURITY_LIMIT,
USE_SECURITY_STRICT_LIMIT, USE_SECURITY_STRICT_LIMIT,
} from "../env.defaults"; } from "../env.defaults";
@ -62,6 +63,9 @@ function excludePaths(middleware: RequestHandler, excludedPaths: Array<string>)
} }
export default (app: Express) => { export default (app: Express) => {
if (TRUST_PROXY) {
app.set("trust proxy", TRUST_PROXY);
}
app.set("query parser", "extended"); app.set("query parser", "extended");
app.use(cors()); app.use(cors());
app.options("*", cors()); app.options("*", cors());