What will nginx reverse-proxy do with ‘proxy_redirect’ to https when a backend has invalid https certificate


I have a strange situation with my nginx acting as reverse proxy. When my backend website is responding to a user (user's browser) request through nginx reverse-proxy, the user will obtain http protocol in 302 FOUND redirects instead of https protocol.

I came to situation where two things on the nginx reverse-proxy will help me solve this situation with wrong protocol in the redirects:

add_header Content-Security-Policy "upgrade-insecure-requests";


proxy_redirect http:// https://;

However the approach is very different with these commands.

I would prefer to use the first CSP option because it seems to be the best way how to solve this. However I am not totally sure what happens when using the second 'proxy_redirect' option.

To be more specific my backend is listening on HTTP (80) and also on HTTPS (443). However the HTTPS (TLS) certificate on my backend is expired. In the nginx reverse proxy config, I am using HTTP protocol for the 'proxy_pass' to backend.

When I use 'proxy_redirect' in this situation it seems like the nginx reverse-proxy fails to create TLS handshake. However instead of terminating the 'proxy_pass' connection it continues to communicate on HTTP protocol. At least that is what I see in the backend's web server logs. From the user perspective the 302 FOUND redirects are now set to HTTPS which seems to be fine. The website seems to be working without any issue. There are no errors in the nginx reverse-proxy nor console.

So is this behavior in the nginx reverse-proxy normal? Which option should I implement when I don't want to use valid HTTPS connection to the backend? Will nginx reverse-proxy behave the same way with the 'proxy_redirect' option when HTTPS certificate is totally missing from the backend?

Best Answer

So I checked the nginx documentation: https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect

The statement of the "proxy_redirect" directive is clear:

Sets the text that should be changed in the “Location” and “Refresh” header fields of a proxied server response.

From my understanding the proxied server response in this case is the response from backend webserver. This means that "proxy_pass" directive on protocol HTTP on port 80 has no direct relation with "proxy_redirect" directive and vice versa.

This means that in this case I can freely use "proxy_redirect" directive as the solution to my problem. The first CSP approach is also available but the job of overwriting "Location" header from http to https relies on the users' browsers in this case. I think the better solution is to set this responsibility to nginx with the "proxy_redirect" directive. If something will go wrong I think it's better to rely on proper nginx settings than on multiple different browsers.

Related Question