News:

Bored?  Looking to kill some time?  Want to chat with other SMF users?  Join us in IRC chat or Discord

Main Menu

SMF doesn't recognize HTTPS URL in nginx

Started by De Kus, March 23, 2015, 11:49:36 AM

Previous topic - Next topic

De Kus

We are in the progress of moving our SMF installation from an old server to a new one. The old server runs Apache 2 + PHP 5.3  and the new runs nginx 1.2.1 + PHP 5.4.39-0+deb7u1. The only related topic I could find was http://www.simplemachines.org/community/index.php?topic=355237.0 , but that one refers to pretty old versions. I have checked my $_SERVER[]-Vars and $_SERVER["HTTPS"] and _SERVER["SERVER_NAME"] are definitely present. The only thing that's empty seems to be _SERVER["PHP_SELF"].

Actually it even removes the "www." in the domain. When I access http://www.domain.de/forum/ everything is fine, all links are appended to http://www.domain.de/forum/. However when I visit the forum on https://www.domain.de/forum/ which I obviously do to protect my cookies and the content of the private forums, it appends everything to http://domain.de/forum/. The removed www. would not be an issue, but a browsers default behaviour is to embed styles and stuff from a non-SSL-domain while browsing an SSL domain.

Any idea what I could be doing wrong?

Board on the old server is: https://www.baeckerprogramm.de/forum/
I test the new server redirecting www.baeckerprogramm.de and baeckerprogramm.de in my C:\Windows\System32\drivers\etc\hosts.
De Kus

Love hurts, love strengthens...

Kindred

It sounds like you have either misconfigured your forum or your htaccess...
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

De Kus

#2
The same configuration is running fine on the old server. Actually while inspecting the settings table I have found some more old static absolute paths that I could correct (like avatars and smilies). While it's not totally impossible there slipped something through, seeing the difference in behaviour from SSL and non-SSL I tend to claim it's not that simple.

The only technical difference is that the new server is configured to make use of SNI to send the correct SSL certificate, but if that part would fail, I'd see a warning in the browser about that (and failing to see the forum at all, because I'd get serviced a totally diffrent vhost).

The forum doesn't use an .htaccess file, neither on the old server nor on the new one. Well there is one on the old server, but I don't see a single rule that should apply for it. 2 are for the mediawiki (and can't apply since the all have ^-regexes that cannot trigger using a /forum prefixed request.

Editi:
I just had another stupid idea... but the /cache was already empty. :D

I also don't see any permission issues, both the SSL and non-SSL vhost use the same user for PHP5-FPM (obviously the only efficient way to call PHP in nginx) and all files have been properly mirrored using lftp and have proper ownership.

There also no errors logged in the error log table.

I also just confirmed that at least the "www." does no longer vanish, but the HTTPS is still dropped.
De Kus

Love hurts, love strengthens...

Kindred

when you moved servers, did you use repair_settings.php? or did you attempt to correct the paths and urls manually?
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

De Kus

#4
Haha, actually I did edit everything manually. I just loaded up that file, but I can't find any mistakes. The only thing that pops to my attention is that repair_settings wants to remove the /forum part of all URLs... but that would obviously not work, outside of /forum there is no simple machines (but a wordpress in / and a mediawiki in /w (with aliases for /wiki) and some other services in /db which gets redirected out of the webspace).

I just also checked the temp paths with nothing obvious wrong, the path is owned by the suexec user and there are all the session files obviously.

For completeness I tinkered together the global vars that seemed not to carry too much private informations from a request "https://www.baeckerprogramm.de/forum/phpinfo.php?test=test"
_REQUEST["test"] test
_GET["test"] test
_SERVER["TEMP"] /var/customers/tmp/Systemarena/
_SERVER["TMPDIR"] /var/customers/tmp/Systemarena/
_SERVER["TMP"] /var/customers/tmp/Systemarena/
_SERVER["USER"] Systemarena
_SERVER["HOME"] /var/customers/webs/Systemarena
_SERVER["FCGI_ROLE"] RESPONDER
_SERVER["QUERY_STRING"] test=test
_SERVER["REQUEST_METHOD"] GET
_SERVER["CONTENT_TYPE"] no value
_SERVER["CONTENT_LENGTH"] no value
_SERVER["SCRIPT_FILENAME"] /var/customers/webs/Systemarena/baeckerprogramm.de/forum/phpinfo.php
_SERVER["SCRIPT_NAME"] /forum/phpinfo.php
_SERVER["REQUEST_URI"] /forum/phpinfo.php?test=test
_SERVER["DOCUMENT_URI"] /forum/phpinfo.php
_SERVER["DOCUMENT_ROOT"] /var/customers/webs/Systemarena/baeckerprogramm.de
_SERVER["SERVER_PROTOCOL"] HTTP/1.1
_SERVER["GATEWAY_INTERFACE"] CGI/1.1
_SERVER["SERVER_SOFTWARE"] nginx/1.2.1
_SERVER["SERVER_ADDR"] 5.45.109.191
_SERVER["SERVER_PORT"] 443
_SERVER["SERVER_NAME"] baeckerprogramm.de
_SERVER["HTTPS"] on
_SERVER["REDIRECT_STATUS"] 200
_SERVER["PATH_INFO"] no value
_SERVER["HTTP_HOST"] www.baeckerprogramm.de
_SERVER["HTTP_ACCEPT"] text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
_SERVER["HTTP_ACCEPT_LANGUAGE"] de-DE,de;q=0.7,en;q=0.3
_SERVER["HTTP_ACCEPT_ENCODING"] gzip, deflate
_SERVER["HTTP_DNT"] 1
_SERVER["HTTP_CONNECTION"] keep-alive
_SERVER["PHP_SELF"] no value
_SERVER["REQUEST_TIME_FLOAT"] 1427195085.9718
_SERVER["REQUEST_TIME"] 1427195085


The status.php doesn't give any valueable information, the only hint it gave me was that it couldn't query any host informations with openbasedir restriction in effect, but I disabled it temporarily to see if anything changes... and nothing changes (besides for the fact it could load the basic informations).

PS: I also just verified that the value passed as "HTTPS" can be properly interpreted as boolean:
php -r "echo '' ? 'yes' : 'no';"
no
php -r "echo 'on' ? 'yes' : 'no';"
yes


Quote from: De Kus on March 23, 2015, 11:49:36 AM... but a browsers default behaviour is to not embed styles and stuff from a non-SSL-domain while browsing an SSL domain.
I just notice a crucial "not" was missing, time for correcting myself is up...
De Kus

Love hurts, love strengthens...

LiroyvH

Are you absolutely sure the URL of forums and themes are set to www.domain.com rather than domain.com?
Because the described behavior would usually only occur when you set the forum to use "domain.com" rather than "www.domain.com".
((U + C + I)x(10 − S)) / 20xAx1 / (1 − sin(F / 10))
President/CEO of Simple Machines - Server Manager
Please do not PM for support - anything else is usually OK.

De Kus

I am very sure. I give you a screenshot of the repair_settings.php as "proof". I indicated all relevant occurance of "http://" and marked the mentioned wrong recommned value parts where the "/forum" is missing.
De Kus

Love hurts, love strengthens...

De Kus

#7
I started to debug Load.php and found the issue...

My debug output was:
QuoteAfter HTTPS:string(8) "https://"
Complete detected:string(30) "https://www.baeckerprogramm.de"
Original:string(35) "http://www.baeckerprogramm.de/forum"

And the corrosponding debugging lines in Sources/Load.php:
        if (isset($_SERVER['HTTP_HOST']) || isset($_SERVER['SERVER_NAME']))
        {
                $detected_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on' ? 'https://' : 'http://';
                echo 'After HTTPS:'; var_dump($detected_url); echo '<br />';
                $detected_url .= empty($_SERVER['HTTP_HOST']) ? $_SERVER['SERVER_NAME'] . (empty($_SERVER['SERVER_PORT']) || $_SERVER['SERVER_PORT'] == '80' ? '' : ':' . $_SERVER['SERVER_PORT']) : $_$
                $temp = preg_replace('~/' . basename($scripturl) . '(/.+)?$~', '', strtr(dirname($_SERVER['PHP_SELF']), '\\', '/'));
                if ($temp != '/')
                        $detected_url .= $temp;
        }
        echo 'Complete detected:'; var_dump($detected_url); echo '<br />';
        if (isset($detected_url) && $detected_url != $boardurl)
        {
                // Try #1 - check if it's in a list of alias addresses.
                if (!empty($modSettings['forum_alias_urls']))
                {
                        $aliases = explode(',', $modSettings['forum_alias_urls']);

                        foreach ($aliases as $alias)
                        {
                                // Rip off all the boring parts, spaces, etc.
                                if ($detected_url == trim($alias) || strtr($detected_url, array('http://' => '', 'https://' => '')) == trim($alias))
                                        $do_fix = true;
                        }
                }

                // Hmm... check #2 - is it just different by a www?  Send them to the correct place!!
...

                // #3 is just a check for SSL...
                echo 'Original:'; var_dump($oldurl); echo '<br />';

                if (strtr($detected_url, array('https://' => 'http://')) == $boardurl)
                        $do_fix = true;

                // Okay, #4 - perhaps it's an IP address?  We're gonna want to use that one, then. (assuming it's the IP or something...)
                if (!empty($do_fix) || preg_match('~^http[s]?://(?:[\d\.:]+|\[[\d:]+\](?::\d+)?)(?:$|/)~', $detected_url) == 1)

Since the non-/forum-URL (detected) is compared against the real board URL, $do_fix won't be set and of course won't replace the boardurl...

Since the script path in detected_url is missing, the issue indeed is the missing PHP_SELF servervar. (I even mentioned that it was the only suspicious empty var I found) But I am unsure what PHP_SELF is actually supposed to be... why is not SCRIPT_NAME used... at least as fallback?!

Replacing:
$temp = preg_replace('~/' . basename($scripturl) . '(/.+)?$~', '', strtr(dirname($_SERVER['PHP_SELF']), '\\', '/'));

With:
$temp = preg_replace('~/' . basename($scripturl) . '(/.+)?$~', '', strtr(!empty($_SERVER['PHP_SELF']) ? dirname($_SERVER['PHP_SELF']) : dirname($_SERVER['SCRIPT_NAME']), '\\', '/'));

did the trick for me. PHP_SELF is definitely not set by /etc/nginx/fastcgi_params provided by Debian. Is it even supposed to be set there? I suppose the same misbehaviour applies to repair_settings.php, it seems it doesn't rely on Sources/Load.php there... evil copy&paste, huh?

PS: Seems that issue is pretty old:
https://bugs.php.net/bug.php?id=55208
I can't even set PATH_INFO (giving me an access denied error) or PHP_SELF (just ignored, still empty).
De Kus

Love hurts, love strengthens...

LiroyvH

Setting the domain with a https:// rather than http:// prefix may also have done it for you if nginx was set to redirect http to https.
((U + C + I)x(10 − S)) / 20xAx1 / (1 − sin(F / 10))
President/CEO of Simple Machines - Server Manager
Please do not PM for support - anything else is usually OK.

De Kus

Nope, there was no redirection. HTTP and is (domain is now transferred and running smooth on Nginx :)) was accessible perfectly fine. We encourage the use of HTTPS, but don't enforce it for the forum.
De Kus

Love hurts, love strengthens...

De Kus

While fiddling with the SEO URLs on the new servers I found an interesting issue. For people not having an Admin Panel that prevents changing the PATH_INFO (refer: http://forum.froxlor.org/index.php/topic/12029-nginx-php5-fpm-path-info/#entry29421 ) it might be also a solution to set "fastcgi_param  PATH_INFO          $fastcgi_path_info;". My "hack" fails at the moment SEO URLs come on the stage, since with an URL like "https://www.baeckerprogramm.de/forum/index.php/topic,1.0.html" the PATH_INFO and PHP_SELF suddenly contain "/topic,1.0.html" breaking the fallback with an empty PHP_SELF...
De Kus

Love hurts, love strengthens...

Kindred

We really need to get rid of that idiotic sef url thing. It has not been useful or valid for years now.

In other words. .. don't use ir.
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

De Kus

#12
Just an update... the original problem was this "feature" in Nginx: http://trac.nginx.org/nginx/ticket/321

Best workaround I found for us: Enable cgi.fix_pathinfo, since doing the above workaround would have required to totally overthrow the structure of the Froxlor job script to generate the Nginx vhost files which I obviously hesitated to do.

A test of the server vars resulted in the following result:
_SERVER["SCRIPT_NAME"] /forum/index.php
_SERVER["REQUEST_URI"] /forum/index.php/topic,450.0.html
_SERVER["PATH_INFO"] /topic,450.0.html
_SERVER["PHP_SELF"] /forum/index.php/topic,450.0.html
De Kus

Love hurts, love strengthens...

Advertisement: