Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to handle nginx reverse proxy https to http scheme redirect

I have set up nginx as a reverse proxy on an ubuntu instance that is hosting jenkins, and a few other applications. I'm using nginx to route to the various applications based on a relative path. All traffic from the client to nginx is over https. Behind the firewall, nginx routes everything over http to the configured path and port numbers. It looks something like this:

              firewall
                |
                |
--->https--->nginx---http--->jenkins
                |
                |

The relevant part of the nginx config file is this:

server {

    listen 443 ssl;

    ssl_certificate cert.crt;
    ssl_certificate_key cert.key;
    ssl_session_cache builtin:1000 shared:SSL:10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;


    location /jenkins {

            proxy_set_header Host $http_host;
            proxy_set_header X-NginX-Proxy true;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

            proxy_pass http://127.0.0.1:6969;
    }

}

The problem is that jenkins uses a simple authentication, and upon a successful login, it sends a 302 redirect. Nginx correctly proxies the url and port, but not the scheme. So the client follows the redirect over http, instead of https. In the browser I then get a 400 error:

400 Bad Request The plain HTTP request was sent to HTTPS port

I know that there is a scheme variable: $scheme. But I don't know how to tell nginx to map the http redirect from jenkins to https. All the examples I've looked at on stackoverflow seem to address slightly different situations.

like image 898
Ted Avatar asked Jan 07 '16 13:01

Ted


People also ask

How do I redirect traffic from HTTP to HTTPS in Nginx?

Redirect HTTP to HTTPS version for Specified domain in Nginx Server_name domain-name.com www.domain-name.com – it specifies the domain names. So, replace it with your website domain name that you want to redirect. Return 301 https://domain-name.com$request_uri – it moves the traffic to the HTTPS version of the site.

How do I use Nginx as an HTTPS forward proxy?

The following steps briefly outlines the process. 1) The client sends an HTTP CONNECT request to the proxy server. 2) The proxy server uses the host and port information in the HTTP CONNECT request to establish a TCP connection with the target server. 3) The proxy server returns an HTTP 200 response to the client.

Is Nginx reverse proxy or forward proxy?

Nginx is often used as a load balancer, a reverse proxy, and an HTTP Cache, among other uses. In this tutorial, we are focusing on learning how to use it as a forward proxy for any requested location.

Can Nginx be used as reverse proxy?

Nginx is an open source web server that can also serve as a reverse proxy. Apart from being used to host websites, it's also one of the most widely used reverse proxy and load balancing solutions.


2 Answers

You probably need to rewrite the 302 redirect from upstream. Assuming everything else is correct, try:

proxy_redirect http:// https://;

See this document for details.

like image 150
Richard Smith Avatar answered Oct 22 '22 07:10

Richard Smith


Ok, I was having the same problem and after some more research and couple of trial and error attempts I figured it out.

Try adding the header X-Forwarded-Proto as in the following example:

server {

    server_name example.com;
    proxy_set_header Host $host;

    # You need this line
    proxy_set_header X-Forwarded-Proto $scheme;

    location ^~ /jenkins {
        proxy_pass http://localhost:8080/;
    }

    listen 443 ssl;
    ssl_certificate cert.crt;
    ssl_certificate_key cert.key;
    ssl_session_cache builtin:1000 shared:SSL:10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;

}

The $scheme will handle https in the front end and then you can call http in the backend using the location.

like image 44
Isaac Villanueva Avatar answered Oct 22 '22 07:10

Isaac Villanueva