From e0e50ec631b0cf26d5fbe6cbf6e5dd43a6fc59fe Mon Sep 17 00:00:00 2001 From: Jack Myers Date: Sun, 14 Jun 2026 16:53:30 +0800 Subject: [PATCH] feat: add an ENV var to configure trusting additional proxy IPs/subnets --- README.md | 8 ++++++++ index.js | 11 +++++++++-- tests.sh | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dfcbbd5..a62686a 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ This image is executed as non root by default and is fully compliant with Kubern - [Basic Usage](#basic-usage) - [Choose your ports](#choose-your-ports) - [Use your own certificates](#use-your-own-certificates) +- [Trust additional proxy IPs](#trust-additional-proxy-ips) - [Decode JWT header](#decode-jwt-header) - [Disable ExpressJS log lines](#disable-expressjs-log-lines) - [Do not log specific path](#do-not-log-specific-path) @@ -96,6 +97,13 @@ You can use volume mounting to substitute the certificate and private key with y You can use the environment variables `HTTPS_CERT_FILE` and `HTTPS_KEY_FILE` to define the location of existing certificate and private key inside container. +## Trust additional proxy IPs + +By default, Express is configured to trust forwarded proxy headers from loopback, link-local, and private IP ranges. To also trust additional proxy IPs or subnets, set `ADDITIONAL_TRUSTED_PROXIES` to a single value or a comma-separated list. + + docker run -e ADDITIONAL_TRUSTED_PROXIES="2001:db8::/32,203.0.113.10" -p 8080:8080 -p 8443:8443 --rm -t mendhak/http-https-echo:40 + + ## Decode JWT header If you specify the header that contains the JWT, the echo output will contain the decoded JWT. Use the `JWT_HEADER` environment variable for this. diff --git a/index.js b/index.js index a7b92c6..006d49e 100644 --- a/index.js +++ b/index.js @@ -17,11 +17,18 @@ const { PROMETHEUS_WITH_METHOD = 'true', PROMETHEUS_WITH_STATUS = 'true', PROMETHEUS_METRIC_TYPE = 'summary', - MAX_HEADER_SIZE = 1048576 + MAX_HEADER_SIZE = 1048576, + ADDITIONAL_TRUSTED_PROXIES } = process.env const maxHeaderSize = parseInt(MAX_HEADER_SIZE, 10) || 1048576; +const trustProxy = [ + 'loopback', + 'linklocal', + 'uniquelocal', + ...(ADDITIONAL_TRUSTED_PROXIES || '').split(',').map(proxy => proxy.trim()).filter(Boolean) +]; const sleep = promisify(setTimeout); const metricsMiddleware = promBundle({ @@ -34,7 +41,7 @@ const metricsMiddleware = promBundle({ const app = express() app.set('json spaces', 2); -app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']); +app.set('trust proxy', trustProxy); if(PROMETHEUS_ENABLED === 'true') { app.use(metricsMiddleware); diff --git a/tests.sh b/tests.sh index c6fa41d..0bee232 100755 --- a/tests.sh +++ b/tests.sh @@ -237,6 +237,22 @@ fi message " Stop containers " stop_and_remove +message " Start container with additional trusted proxies " +docker run -d --rm -e ADDITIONAL_TRUSTED_PROXIES="2001:db8::/32,198.51.100.0/24" --name http-echo-tests -p 8080:8080 -p 8443:8443 -t mendhak/http-https-echo:testing +wait_for_ready + +REQUEST=$(curl -s -H "X-Forwarded-For: 203.0.113.10, 198.51.100.1, 2001:db8::1" http://localhost:8080/) +if [[ "$(echo "$REQUEST" | jq -r '.ip')" == '203.0.113.10' ]]; then + passed "Additional trusted proxies passed." +else + failed "Additional trusted proxies failed." + echo "$REQUEST" | jq + exit 1 +fi + +message " Stop containers " +stop_and_remove + message " Start container with different internal ports " docker run -d --rm -e HTTP_PORT=8888 -e HTTPS_PORT=9999 --name http-echo-tests -p 8080:8888 -p 8443:9999 -t mendhak/http-https-echo:testing wait_for_ready