pinterface Posted December 7, 2013 Share Posted December 7, 2013 I'm experimenting with prestashop (1.5.6.0, according to _PS_VERSION_) and have a fairly typical setup of apache behind an SSL proxy. This works, in as much as I can visit an https page, however, Prestashop fails to detect that an SSL proxy is in use and thinks everything is on HTTP, and links everything to http URLs (why it isn't simply using relative URLs is beyond me, but that's beside the point), which of course means SSL never really sticks around. E.g., I can't enable it inside the admin interface, and even if I could it wouldn't recognize users were using SSL either, and would constantly be sending them back to non-SSL pages. So the question is how do I get it to detect SSL with a proxy in front? I'm hesitant to just modify Tools::usingSecureMode() (and possibly other functions which may need it) since it's been my experience that modifying central files tends to break upgrades when the upgrade overwrites the file and then dies halfway through because it no longer detects the thing it was looking for, so I was hoping there's some way I'm missing. Some relevant data from $_SERVER: Array ( [HTTP_X_FORWARDED_FOR] => 10.122.69.49 [HTTP_X_FORWARDED_PROTO] => https [PATH] => /usr/local/bin:/usr/bin:/bin [sERVER_SOFTWARE] => Apache/2.2.22 (Debian) [sERVER_ADDR] => 127.0.0.1 [sERVER_PORT] => 80 [sERVER_PROTOCOL] => HTTP/1.0 [REQUEST_METHOD] => GET ) Thanks! Link to comment Share on other sites More sharing options...
Bill Dalton Posted December 7, 2013 Share Posted December 7, 2013 This guy give a clear set of instructions of setting up Apache as a proxy with SSL. It is not for Prestashop but it may give you a guide. It mentions all of the modules that need to be installed and gives great examples. http://dev.mensfeld.pl/2013/06/jenkins-behind-apache-with-https-proxy-pass-with-ssl/ <VirtualHost *:443> ServerName jenkins.my.domain ServerAlias www.jenkins.my.domain SSLEngine On SSLCertificateFile /etc/apache2/ssl/crt/jenkins.my.domain.crt SSLCertificateKeyFile /etc/apache2/ssl/key/jenkins.my.domain.key ProxyRequests Off ProxyPass / http://localhost:8080/ ProxyPassReverse / http://localhost:8080/ ProxyPassReverse / http://my.jenkins.host/ <Proxy http://localhost:8080/*> Order allow,deny Allow from all </Proxy> ProxyPreserveHost on </VirtualHost> To create a SSL Proxy pass we need to install some Apache mods (still as a root): a2enmod proxya2enmod proxy_httpa2enmod rewritea2enmod ssl Link to comment Share on other sites More sharing options...
pinterface Posted December 7, 2013 Author Share Posted December 7, 2013 Thanks Bill, but I already /have/ an SSL proxy set up. My problem is that Prestashop doesn't seem to attempt to detect this case (e.g., by checking X-Forwarded-Proto), and I'm not sure how to explicitly override its incorrect detection in a way that will survive upgrades, etc. Link to comment Share on other sites More sharing options...
Bill Dalton Posted December 7, 2013 Share Posted December 7, 2013 So you have your SSL domain name and you have put that domain in Preferences > SEO & URLs SSL Domain You then go to Preferences > General Enable SSL You click on "Please click here to use HTTPS protocol before enabling SSL." What happens at that point? Can you put a plain html page in your PS folder and load that page VIA your SSL domain? Link to comment Share on other sites More sharing options...
pinterface Posted December 8, 2013 Author Share Posted December 8, 2013 You then go to Preferences > General Enable SSL You click on "Please click here to use HTTPS protocol before enabling SSL." What happens at that point? At that point, I get taken to the same page, but via SSL, and it continues to say "Please click here to use HTTPS protocol before enabling SSL.". Can you put a plain html page in your PS folder and load that page VIA your SSL domain? Yes. The proxy works fine, I'm just not seeing anything in Prestashop's code which attempts to detect an SSL proxy in use, and I'm not sure where a safe, upgrade-surviving place to put a snippet like the following to fake it out would be: if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { $_SERVER['HTTPS'] = 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ? 'on' : 'off'; } Link to comment Share on other sites More sharing options...
Bill Dalton Posted December 8, 2013 Share Posted December 8, 2013 Sorry for the preliminary questions. I would say you have it correctly setup and that for whatever reason PS can't pickup on that. This is the same with some setups for the rewrite modules. I suggest you bypass the current code that is incorrectly looking for your SSL, and edit your PS database directly. In the ps_configuration table change id_configuration #31 Name ps_SSL_Enabled from "0" to "1" Let me know if that works for you. Link to comment Share on other sites More sharing options...
pinterface Posted December 8, 2013 Author Share Posted December 8, 2013 No worries on the prelim questions. I appreciate the help. Forcing SSL on without having a way for it to detect SSL is in use just results in infinite redirects on pages which are forced to SSL (e.g., /en/order-history), presumably because without detecting the SSL proxy it mistakenly thinks the end user is not using SSL, and so redirects to HTTPS, where it doesn't detect SSL and ... well, you get the idea. If I add in my little snippet to munge $_SERVER['HTTPS'] it appears to function correctly, but that's not really a permanent solution without some place I can put it that'll survive upgrades. Link to comment Share on other sites More sharing options...
Bill Dalton Posted December 8, 2013 Share Posted December 8, 2013 (edited) Found a patch for Classes/Tools.php After you apply it, to make it work, you can simply add this to config.inc.php /* Proxy settings */ define('PS_PROXY_SERVER', 'http://proxy.example.com'); define('PS_PROXY_PORT', '3128'); define('PS_PROXY_USER', 'presta'); define('PS_PROXY_PASS', 'shop'); Download the patch here, http://forge.prestashop.com/browse/PSCFV-9498 Hope this helps. Edited December 8, 2013 by Bill Dalton (see edit history) Link to comment Share on other sites More sharing options...
pinterface Posted December 8, 2013 Author Share Posted December 8, 2013 Well that does involve proxying, yes, but unfortunately that's for an entirely different thing (Prestashop talking to other servers, not browsers talking to Prestashop). My problem is a "reverse proxy" scenario. Apologies for any confusion caused by my loose terminology earlier. Basically, the user's browser connects to a server (nginx, lighttpd, whatever) which handles the SSL, then forwards the request on to apache as a regular (non-SSL) HTTP request with some additional headers such as X-Forwarded-Proto and X-Forwarded-For, so one can distinguish betwixt client requests. Thus, $_SERVER['HTTPS'] is never "on" because apache never deals with the SSL, and Prestashop never checks the de-facto standard header added by the reverse proxy to tell it what protocol is being used for the client connection, so it never detects SSL is in use for the client connection. Since Prestashop doesn't appear to have native support for this mode of operation, I can fake it with a bit of smoke and mirrors, but I'm not familiar enough with the software yet to know what file (if any) is both going to be used on every request and would be safe to splice in a fix without worrying about being overwritten on upgrades. (E.g., is config/settings.inc.php safe, or is that a candidate for being rewritten on upgrades?) Link to comment Share on other sites More sharing options...
Bill Dalton Posted December 8, 2013 Share Posted December 8, 2013 (edited) I looked at the code in the patch. I feel certain that it will solve all problems related to proxy servers and Prestashop, at least in how I understand what is needed. You seem to have a unique problem that I just don't understand. I hope someone else can post or if you ever find a fix I hope you will share. I'll post the patch here for anyone else that may need it. diff --git a/classes/Tools.php b/classes/Tools.phpindex 7617dde..ab43fb7 100644--- a/classes/Tools.php+++ b/classes/Tools.php[spam-filter] -1281,9 +1281,7 [spam-filter] class ToolsCore { if ($stream_context == null && preg_match('/^https?:\/\//', $url)) $stream_context = @stream_context_create(array('http' => array('timeout' => $curl_timeout)));- if (in_array(ini_get('allow_url_fopen'), array('On', 'on', '1')) || !preg_match('/^https?:\/\//', $url))- return @file_get_contents($url, $use_include_path, $stream_context);- elseif (function_exists('curl_init'))+ if (function_exists('curl_init')) { $curl = curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);[spam-filter] -1301,10 +1299,18 [spam-filter] class ToolsCore curl_setopt($curl, CURLOPT_POSTFIELDS, $datas); } }+ if ((defined('_PS_PROXY_SERVER_')) && (defined('_PS_PROXY_PORT_'))) {+ curl_setopt( $curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP );+ curl_setopt( $curl, CURLOPT_PROXY, _PS_PROXY_SERVER_ );+ curl_setopt( $curl, CURLOPT_PROXYPORT, _PS_PROXY_PORT_ );+ curl_setopt( $curl, CURLOPT_USERPWD, _PS_PROXY_USER_.':'._PS_PROXY_PASS_ );+ } $content = curl_exec($curl); curl_close($curl); return $content; }+ elseif (in_array(ini_get('allow_url_fopen'), array('On', 'on', '1')) || !preg_match('/^https?:\/\//', $url))+ return @file_get_contents($url, $use_include_path, $stream_context); else return false; } Edited December 8, 2013 by Bill Dalton (see edit history) Link to comment Share on other sites More sharing options...
pinterface Posted December 10, 2013 Author Share Posted December 10, 2013 I looked at the code in the patch. I feel certain that it will solve all problems related to proxy servers and Prestashop, at least in how I understand what is needed. Alas, I am apparently incapable of explaining the problem in a way which puts us at an even understanding. But certainly modifying Tools::file_get_contents() is not going to help Tools::usingSecureMode() return the correct value. I appreciate the effort, though. You seem to have a unique problem that I just don't understand. I hope someone else can post or if you ever find a fix I hope you will share. Maybe not entirely unique (this post was almost certainly the same issue, for instance), but yeah, it's not something you're going to run into on generic el-cheapo webhost 37. And I did post a workaround , though I still don't know if where I put it (settings.inc.php) is upgrade-safe. Link to comment Share on other sites More sharing options...
shoobiz Posted December 10, 2013 Share Posted December 10, 2013 Hello ! I'm facing the same kind of problem and I just would like to be clear about your workaround. Actually, you can /resolve/ this by put the line "$_SERVER['HTTPS']" in "settings.inc.php" for exemple ? Thank you. Link to comment Share on other sites More sharing options...
pinterface Posted December 11, 2013 Author Share Posted December 11, 2013 ... I just would like to be clear about your workaround. Actually, you can /resolve/ this by put the line "$_SERVER['HTTPS']" in "settings.inc.php" for exemple ? The three lines I posted (and have duplicated below) appear to work for me, in my environment, yes. But as I've mentioned, I don't know if settings.inc.php is modified during the upgrade process, so I'd be hesitant to consider it a permanent fix. if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) { $_SERVER['HTTPS'] = 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ? 'on' : 'off'; } 1 Link to comment Share on other sites More sharing options...
shoobiz Posted December 11, 2013 Share Posted December 11, 2013 Thank you, I haven't read carefully this post. Sorry for that. Link to comment Share on other sites More sharing options...
Recommended Posts