21

I am using nginx as a reverse proxy and when I login in my web interface I am redirected to the proxied URL. I would like to avoid it and always keep the "server_name" as the URL. Is it possible?

This is my /etc/nginx/conf.d/my_app.conf:

server { 
    listen 443 ssl; 
    server_name my-app.net; 
    ssl_certificate /etc/pki/tls/certs/my-app.cer; 
    ssl_certificate_key /etc/pki/tls/private/my-app.key; 
    ssl_protocols TLSv1.1 TLSv1.2; 
    access_log /var/log/nginx/my-app.access.log main; 

    location / { 
        proxy_pass http://ip_of_the_app:7180/; 
        proxy_redirect off; 
    } 
} 

I connect on http://my-app.net, enter login information, I am then redirected to http://ip_of_the_app:7180 at the same login page, and I have to login again. Can this double login be avoided?

grochmal
  • 8,489
  • 4
  • 30
  • 60
tonio94
  • 321
  • 1
  • 5
  • 8
  • tonio94, has your problem been addressed? if yes, please accept the answer. if no, please clarify what's missing. – cnst Jul 03 '16 at 22:56
  • 2
    I just tested it yesterday, it works, proxy_redirect need to be removed. Thanks for the help. – tonio94 Jul 05 '16 at 02:26

1 Answers1

36

Do not set proxy_redirect to off, that is not doing what you think it is doing. proxy_redirect performs something similar to URL rewriting, for example:

location /sales/ { 
    proxy_pass http://ip_of_the_app:7180/; 
    proxy_redirect http://ip_of_the_app:7180/ http://$host/sales/; 
}

This allows you to host the /sales/ path somewhere else. But even then, the default parameters for proxy_redirect do exactly that for you for free. The default is to redirect the location into whatever is present in proxy_pass (and the default parameters are used when you do not set proxy_redirect at all, or use proxy_redirect default;).

You do not need to set proxy_redirect.


What you're missing are headers that need to be sent to the app. The most important of them is HOST. This shall perform the proxying as desired and shall keep the correct URL in the browser.

location / { 
    proxy_pass http://ip_of_the_app:7180/; 
    proxy_set_header HOST $host;
}

Note that the app at http://ip_of_the_app:7180/ will now receive the request with the Host: my-app.net header.


You should also consider using a couple more headers:

proxy_set_header Referer $http_referer;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;

This will allow for better logging inside the app at http://ip_of_the_app:7180/. X-Forwarded-For giving the IP of the actual client (as opposed to nginxs IP) and X-Forwarded-Proto to check whether the client connected to the nginx through HTTP or HTTPS.

grochmal
  • 8,489
  • 4
  • 30
  • 60
  • Thanks for your help. proxy_redirect is not needed but proxy_set_header Referer http://ip_of_the_app:7180/ must be set in order to work properly. – tonio94 Jul 11 '16 at 15:53
  • @tonio94 - Thanks, I updated the answer. Note that the normal usage of the `Referer` is simply `$http_referer` which copies it from the request. That does not work if the request does not have a Referer header, therefore hardcoding it is a solution in some cases. – grochmal Jul 11 '16 at 16:16
  • @JonathanKomar - Thank you for that, you are correct, now edited. Sorry it took me a while to notice your comment. – grochmal Sep 04 '19 at 16:18
  • @grochmal Thanks, you basically saved my life with this info about: proxy_set_header HOST $host; – Obay Abd-Algader Mar 29 '20 at 23:09
  • 1
    @grochmal I think it should be `X-Forwarded-For $proxy_add_x_forwarded_for` this will append the `$remote_addr` IP to a list of possibly multiple forwarding hoops instead of replacing it. `X-Real-IP $remote_addr` is where the previous hoop is supposed to go if I understand this right - see also https://docs.oracle.com/en-us/iaas/Content/Balance/Reference/httpheaders.htm – Felix B. May 01 '21 at 17:09
  • @FelixB. I do not disagree, it would be better to use both X-Real-IP and then place the list in X-Forwarded-For . Unfortunately, few people/webservers use it that way (at least from my experience), and since the X- headers are just a convention there's no way to enforce anything. Moreover, if I'm not mistake to pass the full list through to X-Forwarded-For you would need nginx's realip and `real_ip_recursive on;`, which is another can of worms to worry about. I'd stick to the slightly incorrect but easy to make work solution for now. – grochmal May 14 '21 at 18:43