Nginx reverse proxy redirection

107,824

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.

Share:
107,824

Related videos on Youtube

tonio94
Author by

tonio94

Updated on September 18, 2022

Comments

  • tonio94
    tonio94 over 1 year

    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?

    • cnst
      cnst almost 8 years
      tonio94, has your problem been addressed? if yes, please accept the answer. if no, please clarify what's missing.
    • tonio94
      tonio94 almost 8 years
      I just tested it yesterday, it works, proxy_redirect need to be removed. Thanks for the help.
  • tonio94
    tonio94 almost 8 years
    Thanks for your help. proxy_redirect is not needed but proxy_set_header Referer ip_of_the_app:7180 must be set in order to work properly.
  • grochmal
    grochmal almost 8 years
    @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
    grochmal over 4 years
    @JonathanKomar - Thank you for that, you are correct, now edited. Sorry it took me a while to notice your comment.
  • Obay Abd-Algader
    Obay Abd-Algader about 4 years
    @grochmal Thanks, you basically saved my life with this info about: proxy_set_header HOST $host;
  • Felix B.
    Felix B. about 3 years
    @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 docs.oracle.com/en-us/iaas/Content/Balance/Reference/…
  • grochmal
    grochmal about 3 years
    @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.