40

I want to set up Nginx as a reverse proxy for a https service, because we have a special usecase where we need to "un-https" a connection:

http://nginx_server:8080/myserver ==> https://mysecureservice

But what happens is that the actual https service isn't proxied. Nginx does redirect me to the actual service, so the URL in the browser changes. I want to interact with Nginx as it was the actual service, just without https.

This is what I have:

server {
    listen 0.0.0.0:8080 default_server;
    location /myserver {
        proxy_pass https://myserver/;
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
    }
}
Ahmad
  • 69,608
  • 17
  • 111
  • 137
mitchkman
  • 6,201
  • 8
  • 39
  • 67

4 Answers4

15

You have to use the proxy_redirect to handle the redirection.

 Sets the text that should be changed in the “Location” and “Refresh” header fields of a 
 proxied server response. Suppose a proxied server returned the header field 
 “Location:https://myserver/uri/”. The directive
 will rewrite this string to “Location: http://nginx_server:8080/uri/”. 

Example:

 proxy_redirect https://myserver/ http://nginx_server:8080/;

Source: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_redirect

Tan Hong Tat
  • 6,671
  • 2
  • 27
  • 25
  • 1
    Hi, thank you for your response. It does not work even for non-redirection URLs. I always get redirected, not matter if the actual https server does send a Location header or not: ```proxy_redirect https://mysecureservice/ http://$host:$server_port/myserver/;``` – mitchkman Jul 02 '14 at 03:43
  • Where does the redirection come from? If it's from the https server html, you have to `subs_filter` it. If there is a cookie, you may have to rewrite it. – Tan Hong Tat Jul 02 '14 at 03:50
  • The redirection definitely comes from Nginx. I'm not using HTML, I'm using JSON. If I do ```curl https://mysecureserver/api/v3/user -I``` (call the actual server directly), I get a 200 OK. If I do the same with Nginx: ```curl http://nginx_server:8080/myserver/api/v3/user -I```, I get a 301 Moved Permanently – mitchkman Jul 02 '14 at 03:55
  • 1
    Is the HTTP host in `proxy_set_header Host $host;` correct? It has to be mysecureserver. – Tan Hong Tat Jul 02 '14 at 05:07
  • 24
    With all the upvotes I must simply not understand what's wanted. I understood that mitchkman wants to proxy NOT redirect because a redirect is what's already happening. This answer says how to redirect, which is the opposite of what's asked for. – Altimus Prime Apr 25 '21 at 16:03
  • 3
    @Altimus Prime: I am with you. Spend one of my rep points to downvote. Just asking me, why this is accepted as a correct answer too. – benni Feb 22 '22 at 13:59
  • @Altimus Prime, and others who don't understand, because you misunderstood the `proxy_redirect`. Don't be confused with its name. Although it has "redirect" literally in its name, it has nothing to do with "redirect". Go read the doc. All it does is to modify the "Location" or "Refresh" field in the response header. The request is `proxy_pass`'ed by the nginx to `myserver`, and the response comes back from `myserver` to the nginx proxy, and with `proxy_redirect`, some of the fields in the response header are modified before sent back to the client. Isn't it a proxy? – Bruce Apr 16 '22 at 01:27
  • 2
    @Bruce We understand what `proxy_redirect` does. The OP specically asked "Nginx does redirect, not proxy" indicating that they wanted to proxy, but this answer redirects. Again, that isn't what was asked for and this answer is served by Google to people looking to reverse proxy, which is really annoying and unhelpful. – Altimus Prime Apr 24 '22 at 01:43
  • @AltimusPrime, Doesn't sound like you understand. The OP wanted to proxy, this answer does proxy. – Bruce Apr 24 '22 at 05:09
  • @AltimusPrime after I try, it does proxy. But sometimes the **source page** return 301 with `Location` header which then passed to **proxy server** and served to client browser. `proxy_redirect` rewrites this header so the browser redirects to **proxy server** address instead of the source page directly. I was looking for the way nginx follow redirects internally and serve the final page to browser but stumbled upon here, which is not the answer I'm looking for – Anggara Jun 20 '22 at 04:35
  • First I downvoted because it doesn't answer why is nginx redirecting instead of proxying, but, the truth is that this answer solved my problem. I will undo my downvote and upvote. – tesla-rules Aug 31 '22 at 02:03
13

You can setup nginx like this if you do not want the server to do redirects:

server
{
    listen 80;
    server_name YOUR.OWN.DOMAIN.URL;
    location / {
        proxy_pass http://THE.SITE.URL.YOU.WANT.TO.DELEGAGE/;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}
warch
  • 2,387
  • 2
  • 26
  • 43
4

For me, this config was sufficient:

events {
}

http {
    server {
        location / {
            resolver 8.8.8.8;
            proxy_pass https://www.example.com$request_uri;
        }
    }
}

(Note that the resolver directive has nothing to do with the problem in the OP, I just needed it to be able to proxy an external domain such as example.com)

The problem for me was just that I was missing the www. in www.example.com. In the Firefox developer's console, I could see the GET request to localhost coming back with a 301, and so I thought that NGINX was issuing 301s instead of just mirroring example.com. Not so: in fact the problem was that example.com was returning 301s to redirect to www.example.com, NGINX was dutifully mirroring those 301s, and then Firefox "changed the URL" (followed the redirect) straight from localhost to www.example.com.

Jack M
  • 4,769
  • 6
  • 43
  • 67
1

I was having a similar issue. In my case, I was able to resolve the issue by added a trailing slash to the proxy_pass URL:

before

server {
  location / {
    proxy_pass http://example.com/path/to/some/folder;
  }
}

after

server {
  location / {
    # added trailing slash
    proxy_pass http://example.com/path/to/some/folder/;
  }
}