Need SSL state to be visible behind a double nginx proxy
Rob Schultz
rschultz7 at gmail.com
Thu Oct 30 03:26:29 MSK 2008
Hi Nick,
Why don't you simplify your setup. You can have your Rails App running
on your big server without needing nginx on it at all. All you do is open up
the rails instances to allow access from your nginx frontends and then proxy
the requests to it. Instead of having to proxy to nginx and then proxying
again.
Or the other option you can do is on your nginx server that proxy's to
your rails app. Have 2 server directives that listen on two different ports.
Then when non-ssl traffic comes into your frontend server and redirect it to
server 1, which has your standard proxy_pass. Then on your frontends have
your ssl portion of the server redirect to the 2nd server port on the
backend that sets the X_FORWARDED_PROTO to https manually.
Rob
On Wed, Oct 29, 2008 at 3:14 PM, Nick Pearson <nick.pearson at gmail.com>wrote:
> Hi,
>
> I have what I think is an obscure problem to which I cannot find a
> solution in the nginx docs. Here's a summary of the problem:
>
> I have a content management system that I wrote (using Rails), and it
> hosts several sites. Each site has SSL, and due to a policy limit by
> my hosting provider, each virtual server ("slice") can only have five
> external IP addresses. This creates a problem in that the CMS that
> was built to host lots of sites is limited to hosting only five. My
> solution was to set up smaller slices in front of the main server, and
> the small slices would run nothing but nginx. As such, the
> "front-end" nginx instances would proxy requests to the "back-end"
> nginx, and the "back-end" nginx would proxy requests through to the
> Rails app server instances.
>
> I saw a recent post on SSL pass-through, but this is not what I'm
> looking for. As the slices are on the same network at my hosting
> provider, I don't care that the slice-to-slice communications are
> encrypted. This is not an issue.
>
> What is an issue is that the application (and thus the Rails app
> server instances) need to be able to determine whether a request came
> in using SSL or not. Because requests are proxied through two
> instances of nginx running on separate slices, the back-end nginx
> cannot see whether a request came in over http or https -- because
> either way, the request arrived at the back-end nginx over http (not
> https). Here is a simple depiction of two requests -- one over http
> and one over https:
>
> client ---http---> nginx ---http---> nginx ---> rails
> client ---https--> nginx ---http---> nginx ---> rails
>
> As you can see, it is the second (back-end) nginx instance in the
> chain that tells the Rails app server instances whether the request
> made to nginx was over http or https. And since all requests to the
> second nginx instance are made over http, it passes this on to the
> Rails app, which thinks all requests are made over http even if the
> communication between the client and the first (front-end) nginx is
> over https.
>
> Also worth noting is that there are no SSL errors. If the request is
> made over http, it works. And if the request is made over https, it
> works. The app server just doesn't know whether a request was made
> over http or https.
>
> I attempted to set the following on the back-end nginx:
>
> proxy_set_header X_FORWARDED_PROTO $scheme;
>
> but not surprisingly, it doesn't work. ($scheme is either "http" or
> "https", taken directly from the request.) I may have a solution to
> the problem, but it will require some extra plumbing work in Rails to
> make it functional. What I am able to do is to set a custom header
> and then read the value of that header in the Rails code. Here is
> what I've tried:
>
> proxy_set_header HTTPS on;
>
> Then, in the Rails code, I can look for the HTTP_HTTPS environment
> variable. (nginx apparently prepends anything sent to
> proxy_set_header with "HTTP_".) While this solution will probably
> work, I would prefer to have nginx pass the request scheme to the app
> servers without having to change the internals of Rails (by rewriting
> the request.ssl? method).
>
> This could be accomplished if nginx would let me conditionally set a
> header based on the value of another header. I just can't figure out
> how to read a header. Here's what I would like to do -- keep the
> "proxy_set_header HTTPS on;" (above) on the front-end nginx and use
> the header on the back-end nginx -- like this:
>
> if ($HTTP_HTTPS = on) {
> proxy_set_header X_FORWARDED_PROTO https;
> }
>
> I realize that this means that anyone could arbitrarily add this
> header to a request and trick the Rails server into thinking the
> request was secure when it was not, but I would solve this by setting
> "ignore_invalid_headers on;" or similar on the front-end nginx.
>
> Can anyone tell me whether it is possible to read custom headers and
> to act on them as in my example above? If not, I think this would be
> a great addition.
>
> Thanks in advance.
>
> Nick Pearson
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://nginx.org/pipermail/nginx/attachments/20081029/77f0647a/attachment.html>
More information about the nginx
mailing list