28

I'm chainging my setup from

nginx > apache/php

to

haproxy > nginx > apache/php

(using haproxy 1.5-dev18 with ssl support compiled in)

Both nginx and haproxy are setup correctly to set the HTTP_X_FORWARDED_PROTO header. However, when nginx gets the ssl traffic from haproxy, it sees the connection as http and sets the header as so.

How can I set nginx to forward the HTTP_X_FORWARDED_PROTO header if it exists, but otherwise continue setting it based on the connection?

3 Answers 3

43

I figured out how to solve this. The problem was that nginx was overwriting the header set by haproxy on this line of my config:

proxy_set_header X-Forwarded-Proto $scheme;

I fixed it by adding in this:

map $http_x_forwarded_proto $thescheme {
     default $scheme;
     https https;
 }   

and changing the proxy_set_header line to use the new scheme:

proxy_set_header X-Forwarded-Proto $thescheme;
5
  • Unless I'm missing something, your before and after proxy_set_header lines are the same. Sep 26, 2013 at 17:39
  • 2
    $scheme vs $thescheme. Jul 2, 2015 at 13:30
  • 1
    Isn't this in some rare cases insecure? If a web browser sends a HTTP request to haproxy, and haproxy then sends a HTTPS request to Nginx — then the default $scheme case will happen, setting $thescheme to HTTPS although in fact the request (to haproxy) is insecure HTTP. — To avoid that, what about: default $http_x_forwarded_proto; '' $scheme;, so if haproxy says HTTP it'll be respected.
    – KajMagnus
    May 8, 2018 at 14:28
  • That is suggested here: stackoverflow.com/a/21911864/694469 (i.e. default $http_x_forwarded_proto;).
    – KajMagnus
    May 8, 2018 at 14:41
  • look like are you forcefully sending the secure request Mar 22 at 9:42
16

I had the same need with AWS ELB

Here is my solving line:

proxy_set_header        X-Forwarded-Proto $http_x_forwarded_proto;
7
  • Should I bet setting $http_x_forwarded_proto somewhere? What is that?
    – Jonathan
    May 23, 2018 at 23:55
  • developer.mozilla.org/en-US/docs/Web/HTTP/Headers/… $http_x_forwarded_proto is the NGINX implementation
    – jobwat
    Jun 11, 2018 at 20:46
  • 2
    You answer just solved an issue I've been hammering at for 3 days! Every other post on the subject of aws load balancers with https advocate proxy_set_header X-Forwarded-Proto $scheme;, which doesn't work Jan 23, 2019 at 7:42
  • $http_x_forwarded_proto is the way nginx exposes the X-Forwarded-Proto header. See the docs for "$http_name" in nginx.org/en/docs/http/ngx_http_core_module.html#variables
    – RobSiklos
    Dec 17, 2020 at 21:53
  • Doesn't this just copy the header value from the upstream request? Shouldn't nginx do this automatically?
    – Migwell
    Jan 4, 2021 at 4:10
1

I can't just comment so I post this as an answer : Could you give us part or all of your nginx configuration so we can see what's wrong with it ? Possibly your HAProxy config too ?

The first problem I can think of is that your HAProxy is doing ssl termination. To sum it up, to offload your backend servers, a load balancer can be configured to do all the ssl thing, and then communicate with your backend servers in HTTP. Like the scheme here : http://blog.exceliance.fr/2012/09/10/how-to-get-ssl-with-haproxy-getting-rid-of-stunnel-stud-nginx-or-pound/

To give you a good answer to your question, could you check you don't have any loopback problem in your http<>https config ? Maybe then you could redirect http to http, https to https, and then force http to be redirected to https.

Could you check too that you have enabled ssl passthrough in your HAProxy config ?

2
  • Did you resolve your problem ?
    – Yannovitch
    Jun 15, 2013 at 12:53
  • 1
    I figured it out. Your answer didn't help directly, but that second link helped me figure out a way to solve it. Thanks. Jun 17, 2013 at 15:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.