From f452e9af898168afc7196c788b6d86913cdce91e Mon Sep 17 00:00:00 2001 From: Arad Alvand Date: Tue, 13 Jun 2023 14:29:47 +0330 Subject: [PATCH 1/2] Improve docs about `X-Forwarded-*` headers and move it to nginx.md --- docs/configuration/ssl.md | 33 +---------------------------- docs/networking/proxies/nginx.md | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/docs/configuration/ssl.md b/docs/configuration/ssl.md index 5402154cf..653b24fc2 100644 --- a/docs/configuration/ssl.md +++ b/docs/configuration/ssl.md @@ -132,37 +132,6 @@ See the [NGINX HSTS documentation](/docs/networking/proxies/nginx.md#hsts-header Certain versions of nginx have bugs that prevent [HTTP/2](https://nginx.org/en/docs/http/ngx_http_v2_module.html) from properly responding to all clients, thus causing applications to be unavailable. For HTTP/2 to be enabled in your applications' nginx configs, you need to have installed nginx 1.11.5 or higher. See [issue 2435](https://github.com/dokku/dokku/issues/2435) for more details. -## Running behind a load balancer - -Your application has access to the HTTP headers `X-Forwarded-Proto`, `X-Forwarded-Port` and `X-Forwarded-For`. These headers indicate the protocol of the original request (HTTP or HTTPS), the port number, and the IP address of the client making the request, respectively. The default configuration is for Nginx to set these headers. - -If your server runs behind an HTTP(S) load balancer, then Nginx will see all requests as coming from the load balancer. If your load balancer sets the `X-Forwarded-` headers, you can tell Nginx to pass these headers from load balancer to your application via `nginx:set`: - -```shell -dokku nginx:set node-js-app x-forwarded-for-value "\$http_x_forwarded_for" -dokku nginx:set node-js-app x-forwarded-port-value "\$http_x_forwarded_port" -dokku nginx:set node-js-app x-forwarded-proto-value "\$http_x_forwarded_proto" -``` - -Only use this option if: -1. All requests are terminated at the load balancer, and forwarded to Nginx -2. The load balancer is configured to send the `X-Forwarded-` headers (this may be off by default) - -If it's possible to make HTTP(S) requests directly to Nginx, bypassing the load balancer, or if the load balancer is not configured to set these headers, then it becomes possible for a client to set these headers to arbitrary values. - -The `x-forwarded-ssl` property may also be set for application frameworks that require this value. Note that this is a non-standard version of setting `x-forwarded-proto` to `https`, and should only be done as a last resort. - -```shell -# force-setting value to `on` -dokku nginx:set node-js-app x-forwarded-ssl on - -# force-setting value to `off` -dokku nginx:set node-js-app x-forwarded-ssl on - -# removing the value from nginx.conf (default) -dokku nginx:set node-js-app x-forwarded-ssl -``` - ### SSL Port Exposure -When your app is served from port `80` then the `/home/dokku/APP/nginx.conf` file will automatically be updated to instruct nginx to respond to ssl on port 443 as a new cert is added. If your app uses a non-standard port (perhaps you have a dockerfile deploy exposing port `99999`) you may need to manually expose an ssl port via `dokku proxy:ports-add https:443:99999`. +When your app is served from port `80` then the `/home/dokku/APP/nginx.conf` file will automatically be updated to instruct nginx to respond to ssl on port 443 as a new cert is added. If your app uses a non-standard port (perhaps you have a dockerfile deploy exposing port `99999`) you may need to manually expose an ssl port via `dokku proxy:ports-add https:443:99999`. diff --git a/docs/networking/proxies/nginx.md b/docs/networking/proxies/nginx.md index 4c22a1ec3..a4f349e16 100644 --- a/docs/networking/proxies/nginx.md +++ b/docs/networking/proxies/nginx.md @@ -107,6 +107,42 @@ Once the HSTS setting is disabled globally, it can be re-enabled on a per-app ba dokku nginx:set node-js-app hsts true ``` +## Running behind another proxy — configuring `X-Forwarded-*` headers: + +Dokku's default Nginx configuration passes the de-facto standard HTTP headers [`X-Forwarded-For`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For), [`X-Forwarded-Proto`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto), and `X-Forwarded-Port` to your application. +These headers indicate the IP address of the original client making the request, the protocol of the original request (HTTP or HTTPS), and the port number of the original request, respectively. + +If you have another HTTP proxy sitting in between the end user and your server (for example, a load balancer, or a CDN), then the values of these headers will contain information about (e.g. the IP address of) the the closest proxy, and not the end user. + +To fix this, assuming that the other proxy also passes `X-Forwarded-*` headers, which in turn contain information about the end user, you can tell Nginx include those values in the `X-Forwarded-*` headers that it sends to your application. You can do this via `nginx:set`, like so: + +```shell +dokku nginx:set node-js-app x-forwarded-for-value '$http_x_forwarded_for' +dokku nginx:set node-js-app x-forwarded-port-value '$http_x_forwarded_port' +dokku nginx:set node-js-app x-forwarded-proto-value '$http_x_forwarded_proto' +``` + +However, note that you should only do this if: + +1. Requests to your website always go through a trusted proxy. +2. That proxy is configured to send the aforementioned `X-Forwarded-*` headers. + +Otherwise, if it's possible for clients to make HTTP requests directly against your server, bypassing the other proxy, or if the other proxy is not configured to set these headers, then a client can basically pass any arbitrary values for these headers (which your app then presumably reads) and thereby fake an IP address, for example. + +There's also the `X-Forwarded-Ssl` header which a less common alternative to `X-Forwarded-Proto` — and because of that, isn't included in Dokku's default Nginx configuration. +But you can tell Nginx to send this header as well, if necessary. + +```shell +# force-setting value to `on` +dokku nginx:set node-js-app x-forwarded-ssl on + +# force-setting value to `off` +dokku nginx:set node-js-app x-forwarded-ssl on + +# removing the value from nginx.conf (default) +dokku nginx:set node-js-app x-forwarded-ssl +``` + ### Checking access logs > Note: Changing this value globally or on a per-app basis will require rebuilding the nginx config via the `proxy:build-config` command. From 76674ec9419d1afbcc925b5c94b2b06de6405b74 Mon Sep 17 00:00:00 2001 From: Arad Alvand Date: Wed, 14 Jun 2023 07:50:55 +0330 Subject: [PATCH 2/2] Add link to `X-Forwarded-*` docs in ssl.md --- docs/configuration/ssl.md | 6 ++++++ docs/networking/proxies/nginx.md | 6 +----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/configuration/ssl.md b/docs/configuration/ssl.md index 653b24fc2..42664a749 100644 --- a/docs/configuration/ssl.md +++ b/docs/configuration/ssl.md @@ -135,3 +135,9 @@ Certain versions of nginx have bugs that prevent [HTTP/2](https://nginx.org/en/d ### SSL Port Exposure When your app is served from port `80` then the `/home/dokku/APP/nginx.conf` file will automatically be updated to instruct nginx to respond to ssl on port 443 as a new cert is added. If your app uses a non-standard port (perhaps you have a dockerfile deploy exposing port `99999`) you may need to manually expose an ssl port via `dokku proxy:ports-add https:443:99999`. + +## Other + +### Running behind a proxy (`X-Forwarded-Ssl`, etc.) + +See the [running behind another proxy documentation](/docs/networking/proxies/nginx.md#running-behind-another-proxy--configuring-x-forwarded--headers) for more information on how to configure your Nginx config when your server is running behind a proxy (e.g. load balancer, etc.). diff --git a/docs/networking/proxies/nginx.md b/docs/networking/proxies/nginx.md index a4f349e16..1470736e6 100644 --- a/docs/networking/proxies/nginx.md +++ b/docs/networking/proxies/nginx.md @@ -107,7 +107,7 @@ Once the HSTS setting is disabled globally, it can be re-enabled on a per-app ba dokku nginx:set node-js-app hsts true ``` -## Running behind another proxy — configuring `X-Forwarded-*` headers: +### Running behind another proxy — configuring `X-Forwarded-*` headers: Dokku's default Nginx configuration passes the de-facto standard HTTP headers [`X-Forwarded-For`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For), [`X-Forwarded-Proto`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto), and `X-Forwarded-Port` to your application. These headers indicate the IP address of the original client making the request, the protocol of the original request (HTTP or HTTPS), and the port number of the original request, respectively. @@ -493,10 +493,6 @@ See the [customizing hostnames documentation](/docs/configuration/domains.md#cus See the [disabling vhosts documentation](/docs/configuration/domains.md#disabling-vhosts) for more information on how to disable domain usage for your app. -### Running behind a load balancer - -See the [load balancer documentation](/docs/configuration/ssl.md#running-behind-a-load-balancer) for more information on how to configure your nginx config for running behind a network load balancer. - ### SSL Configuration See the [ssl documentation](/docs/configuration/ssl.md) for more information on how to configure SSL certificates for your application.