Skip to content

Force SSL's redirection was activated when forwarding requests from another npm instance which already handled ssl staffs #5216

@jerry-yuan

Description

@jerry-yuan

Is your feature request related to a problem? Please describe.
I have a relatively complex reverse proxy topology that involves multiple Nginx Proxy Manager instances. As shown in the diagram, I have two servers—one located on the internal network and the other on the public internet—each hosting several Docker services and using Nginx Proxy Manager for reverse proxying. I have established a tunnel between the two servers to traverse the firewall. To allow public internet access to the internal services, I added the internal Nginx Proxy Manager as an upstream backend server in the public server’s NPM configuration.

Image

However, as illustrated in the diagram below, when I enable Force SSL on both servers, a problem occurs. The public server’s Nginx Proxy Manager uses HTTP to communicate with the internal upstream (since the tunnel is already encrypted, I prefer not to add another layer of SSL encryption). This causes the internal server’s Nginx Proxy Manager, upon receiving the HTTP request, to apply its Force SSL rule and return a 301 redirect to an HTTPS address. Consequently, even though the public client is already accessing the site via HTTPS, it gets redirected to the same HTTPS URL again, triggering a browser ERR_TOO_MANY_REDIRECTS error.

Image

Describe the solution you'd like

I developed a program capable of returning the request headers in response body, and used Nginx Proxy Manager to reverse proxy it. As shown in the screenshot below, I discovered that Nginx Proxy Manager adds the X-Forwarded-Scheme and X-Forwarded-Proto request headers. Furthermore, when a client correctly accesses a virtual host with Force SSL enabled via HTTPS, these headers already indicate that the original request was made over HTTPS.

Image

I modified the newly introduced conf.d/include/force-ssl.conf file, which is applied when Force SSL is enabled. I added a condition to prevent the 301 redirect from being triggered when the upstream X-Forwarded-Proto header is https. The modifications are as follows:

set $test "";
if ($scheme = "http") {
	set $test "H";
}
if ($request_uri = /.well-known/acme-challenge/test-challenge) {
	set $test "${test}T";
}
# Added code begin
if ($http_x_forwarded_proto = "https") {
    set $test "${test}S";
}
# Added code end

if ($test = H) {
	return 301 https://$host$request_uri;
}

After reload nginx, this problem has been resolved.

Describe alternatives you've considered

Under my solution, the two-layer Nginx Proxy Manager proxy configuration works, but it may not be suitable for more layers. This is because I found that the X-Forwarded-Proto header received by deeper layers may be overwritten as http by the preceding Nginx Proxy Manager instance. I believe that if support for multiple Nginx Proxy Manager instances in a forwarding chain is desired, additional handling of the X-Forwarded-Proto and X-Forwarded-Scheme headers may be necessary to ensure that the original protocol used by the client is not lost during multiple forwarding hops.

In addition, I have considered the security implications. Such modifications could potentially cause the Force SSL feature to fail if clients spoof the X-Forwarded-* headers. Therefore, a more thorough design may be necessary.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions