Jump to content

[SOLVED]Enabling SSL on NGINX reverse proxy towards non-SSL apache


alberto

Recommended Posts

Hi, 

This is my first post here so i apologize for future possible errors in this post.

My Setup is as follow.

I have a NGINX web server (docker container) that accepts connections on port 80/443.

This is the main server which forwards encrypted requests to internal UNENCRYPTED servers running APACHE (also docker containers).

So the setup is:

INTERNET --(SSL)--> NGINX ---(NON-SSL)--->INTERNAL SERVERS (apache)

Prestashop 1.7.3.3 is installed in an internal server with APACHE.

My PROBLEM is that i cannot enable SSL on Prestashop directly on the internal Apache webserver which hosts it because it use port 80 and would get redirection loops towards the proxy server.

How would i do it?

I want encrypted https connections for every request but without enabling SSL on prestashop, it doesnt rewrite URLs to the correct https scheme.

SSL is enabled correctly on NGINX, i set up a rewrite rule to forwards http requests to https web server but the hosts just get 301/302 redirection response and then, mixed content.

Here are my nginx conf:

 

server {
        listen      80 reuseport;
        server_name  localhost <domain>;
        
        
        modsecurity off;
        modsecurity_rules_file /etc/nginx/modsecurity.d/include.conf;
        server_tokens off;

#       add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
#       return 301 https://<domain>$request_uri;

        rewrite ^ https://<domain>$request_uri? permanent;

    }

    server {
        listen       443 ssl default_server http2;
        server_name  <domain>;

        ssl_certificate      certs/cert.pem;
        ssl_certificate_key  certs/privkey.pem;

        ssl_session_cache    shared:SSL:10m;
        ssl_session_timeout  15m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_ecdh_curve secp384r1;

        ssl_stapling on;
        ssl_stapling_verify on;

#       add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        add_header X-Frame-Options SAMEORIGIN;
        add_header X-Content-Type-Options nosniff;
        add_header Referrer-Policy "strict-origin" always;
        add_header X-XSS-Protection "1; mode=block";
#        add_header Content-Security-Policy "upgrade-insecure-requests;  ... ;


        location / {
            resolver 127.0.0.11 valid=30s;

            proxy_pass   http://APACHE_PRIVATE_IP;
            proxy_http_version 1.1;           

            #proxy_set_header Host APACHE_PRIVATE_IP;
            proxy_set_header Host  <domain>;
            index index.html index.php;

            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;            
            
            root APACHE_ROOT_DIR/htdocs/erboristeria2;
            proxy_bind  MODSEC_INT_IP;
            proxy_pass_request_headers      on;
        }
    }


}

should the only solution be to manually rewrite EVERY resource link in the prestashop folder?

I am struggling with this for days... How can i make prestashop rewrite all urls to https?

Edited by alberto (see edit history)
Link to comment
Share on other sites

Okay. I got your point.

I think you can achieve the same by adding host entry in the server where NGINX is hosted.

In linux, Edit the /etc/hosts file & make the entry of the Apache private server with the domain name.

xx.xx.xx.xx www.abc.com

(Where xx.xx.xx.xx is the IP of the apache server)

Now enable the HTTPS on the PS Apache & In the nginx config file, Change the following line.

proxy_pass   http://APACHE_PRIVATE_IP;

to

proxy_pass   https://www.abc.com;

 

So basically, NGINX will forward the request to internally to Apache (due to host entry) instead of the sending request again to NGINX (via internet). So I think there will not be redirect loop.

Hope it will help :)


 

Link to comment
Share on other sites

Hi! thanks for the response but i think you didn't get the point exactly.

I use NGINX as a load balancer and SSL concentrator, so every INTERNAL connection to INTERNAL servers such as the PS apache one are UNENCRYPTED.

The way you suggest force me to enable ps apache server to use https, which i don't want to.

 

On NGINX using 

rewrite ^ https://<DOMAIN>$request_uri? permanent;
 

seems to work now but not for the administrative panel.

EDIT: SOLVED

It seems i have now found a solution.

 

First:  I need prestashop to create https links instead of http link though the function BaseLink so i changed "http" to "https" in the last row:

File: classes/Link.php

 

public function getBaseLink($idShop = null, $ssl = null, $relativeProtocol = false)
    {
        static $force_ssl = true;  /*CHANGED null to true */

        if ($ssl === null) {
            if ($force_ssl === null) {
                $force_ssl = (Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE'));
            }
            $ssl = $force_ssl;
        }

        if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && $idShop !== null) {
            $shop = new Shop($idShop);
        } else {
            $shop = Context::getContext()->shop;
        }

        if ($relativeProtocol) {
            $base = '//'.($ssl && $this->ssl_enable ? $shop->domain_ssl : $shop->domain);
        } else {
            $base = (($ssl && $this->ssl_enable) ? 'https://'.$shop->domain_ssl : 'https://'.$shop->domain); /*CHANGED second http to https */
        }

        return $base.$shop->getBaseURI();

i just forced PS to use https whether it is activated or not.

 

Now the backoffice works flawlessly but the front end get loop redirection because apache sees HTTP requests instead of HTTPS ones and so send a Location header to the HTTPS site.

 

Now you just need to make apache believe those are HTTPS requests even if those are actually HTTP so add these lines in NGINX reverse proxy nginx.conf:

proxy_set_header X-Scheme https;
proxy_set_header X-Forwarded-Proto https;
   

and everything works!

  • Thanks 1
Link to comment
Share on other sites

  • 1 month later...
On 8/27/2018 at 2:22 PM, alberto said:

Hi! thanks for the response but i think you didn't get the point exactly.

I use NGINX as a load balancer and SSL concentrator, so every INTERNAL connection to INTERNAL servers such as the PS apache one are UNENCRYPTED.

The way you suggest force me to enable ps apache server to use https, which i don't want to.

 

On NGINX using 


rewrite ^ https://<DOMAIN>$request_uri? permanent;


 

seems to work now but not for the administrative panel.

EDIT: SOLVED

It seems i have now found a solution.

 

First:  I need prestashop to create https links instead of http link though the function BaseLink so i changed "http" to "https" in the last row:

File: classes/Link.php

 


public function getBaseLink($idShop = null, $ssl = null, $relativeProtocol = false)
    {
        static $force_ssl = true;  /*CHANGED null to true */

        if ($ssl === null) {
            if ($force_ssl === null) {
                $force_ssl = (Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE'));
            }
            $ssl = $force_ssl;
        }

        if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && $idShop !== null) {
            $shop = new Shop($idShop);
        } else {
            $shop = Context::getContext()->shop;
        }

        if ($relativeProtocol) {
            $base = '//'.($ssl && $this->ssl_enable ? $shop->domain_ssl : $shop->domain);
        } else {
            $base = (($ssl && $this->ssl_enable) ? 'https://'.$shop->domain_ssl : 'https://'.$shop->domain); /*CHANGED second http to https */
        }

        return $base.$shop->getBaseURI();

i just forced PS to use https whether it is activated or not.

 

Now the backoffice works flawlessly but the front end get loop redirection because apache sees HTTP requests instead of HTTPS ones and so send a Location header to the HTTPS site.

 

Now you just need to make apache believe those are HTTPS requests even if those are actually HTTP so add these lines in NGINX reverse proxy nginx.conf:


proxy_set_header X-Scheme https;
proxy_set_header X-Forwarded-Proto https;
   

and everything works!

Hi boss,

this absolutely helped me to resolve the issue, i.e. run Prestoshop using the official image behind a Reverse Proxy.

I am now overwriting that classes/Link.php in my Dockerfile

# Solve reverse-proxy shortcoming
COPY Link.php /var/www/html/classes/Link.php
  • Like 1
Link to comment
Share on other sites

  • 3 years later...

This works, but be careful, some modules check if PS_SSL_ENABLED is "1". 
For example, paypal will stop work if the flag is 0 in database, so if you want to use the "fake" https workaround you have to edit the paypal code too where it checks for PS_SSL_ENABLED.

 

2022-03-11 09_16_02.png

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...