SSL on apache + nignix not working #13259

Open
manicko opened this Issue Jan 22, 2017 · 9 comments

Projects

None yet

5 participants

@manicko
manicko commented Jan 22, 2017 edited

Summary

Hi, just faced the problem that my hosting uses the chain of two servers, thus the SSL is installed on the front end server only and it does not return the $_SERVER['HTTPS'] variable and the $_SERVER['SERVER_PORT'] is set to 80.
Thus all checks in the core config file are missing and site returns the http protocol for the base_url/site_url.

Instead hosting is returning _SERVER['HTTP_FRONT_END_HTTPS'] === 'on'. Serfing the web I found that other hostings are using $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' which could be used as a reference too.

Step to reproduce

The easies way is to set $_SERVER['HTTPS'] to nothing and the $_SERVER['SERVER_PORT'] to 80.
The hard way is to use shared hosting with chain of servers apache + nignix,

Observed behavior

Thus all checks in the core config file are missing and site returns the http protocol for the base_url/site_url.

Expected behavior

Should return the correct https

Environment

MODX version 2.5.4, apache+nginx

I suggest to add more robust function to config checking the ssl:

if(!function_exists('is_https')){
function is_https($https_port=443)
 {
   if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) === 'on')
   {
     return TRUE;
   }
   elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
   {
       return TRUE;
   }
   elseif (isset($_SERVER['HTTP_FRONT_END_HTTPS']) && $_SERVER['HTTP_FRONT_END_HTTPS'] === 'on')
   {
     return TRUE;
   }
   elseif (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] === $https_port)
   {
     return TRUE;
   }
   return FALSE;
 }
}

And chage the $isSecureRequest as follows:

if(defined('PHP_SAPI') && (PHP_SAPI == "cli" || PHP_SAPI == "embed")) {
    $isSecureRequest = false;
} else {
    $isSecureRequest = is_https($https_port);
}
@manicko
manicko commented Jan 22, 2017

And the htaccess

    RewriteEngine On
    RewriteCond %{SERVER_PORT} !^443 [OR]
    RewriteCond %{HTTPS} !=on [OR]
    RewriteCond %{HTTP:X-Forwarded-Proto} !https [NC] [OR]
    RewriteCond %{HTTP:Front-End-Https} !on 
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
@OptimusCrime
Contributor

The two request fields you are relying on here are non-standard: https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Common_non-standard_request_fields

I am not sure if this is a good idea. I also find it very weird that your host does not state that https is turned on like almost every single piece of software would expect.

@Mark-H
Collaborator
Mark-H commented Jan 22, 2017

I don't think it's that uncommon @OptimusCrime - reverse proxies or CDNs/platforms like cloudflare have their own connection with the server which isn't always over HTTPS. To the origin server the request looks like HTTP, unless you check for additional headers that indicate the upstream request was HTTPS - HTTP_X_FORWARDED_PROTO is pretty common in my experience.

@manicko Have you tried setting the link_tag_scheme system setting to https to force MODX to generate HTTPS urls? That, plus your https tweak, should be sufficient to get things to work without core patches.

@manicko
manicko commented Jan 22, 2017 edited

Hi Mark, actually, setting link_tag_scheme to https was the first thing I've tried. It didn't help, and that is why I've finished modifing core config.

The reason is simple the url is generated in the cor config basing on the $isSecureRequest variable I've tweaked in the above code.
here is the original code

$https_port=443;
if(defined('PHP_SAPI') && (PHP_SAPI == "cli" || PHP_SAPI == "embed")) {
    $isSecureRequest = false;
} else {
    $isSecureRequest = ((isset ($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') || $_SERVER['SERVER_PORT'] == $https_port);
}
if (!defined('MODX_URL_SCHEME')) {
    $url_scheme=  $isSecureRequest ? 'https://' : 'http://';
    define('MODX_URL_SCHEME', $url_scheme);
}

Thus if $_SERVER['HTTPS']) = null and $_SERVER['SERVER_PORT'] is 80 the check fails.

@OptimusCrime
Contributor

There is a system setting where you can chose between http and https. Does that have any effect?

@manicko
manicko commented Jan 22, 2017

There is a system setting where you can chose between http and https. Does that have any effect?

server_protocol? I put it server_protocol=https

I do not know what it does but it had not had any effect in my case

@meshkov
meshkov commented Jan 24, 2017

My method of solving this problem:
In the file core/config/config.inc.php change the site url from http to https and in the system settings setting change the server_protocol to https and clear the cache.
In core/config/config.inc.php line:
if (!defined('MODX_URL_SCHEME')) {
$url_scheme= $isSecureRequest ? 'https://' : 'http://';
define('MODX_URL_SCHEME', $url_scheme);
}
change to:
if (!defined('MODX_URL_SCHEME')) {
$url_scheme= $isSecureRequest ? 'http://' : 'https://';
define('MODX_URL_SCHEME', $url_scheme);
}

@zaigham
Contributor
zaigham commented Jan 31, 2017

@meshkov You can just add url_scheme to system settings and valid values for it are: https://, http://, //

@manicko
manicko commented Jan 31, 2017

This will not help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment