SSL nutzen mit Reverse-Proxies und nginx

So funktioniert TYPO3 mit SSL hinter Reverse-Proxies wie beispielsweise Varnish

Software wie TYPO3 kann hinter einem Proxy meist nicht feststellen, dass interne Verlinkungen mit https:// erfolgen müssen, wenn das SSL Zertifikat schon durch einen anderen Dienst terminiert wurde. Die SSL-Verschlüsselte Verbindung geht ja dann nur bis zum Proxy und danach ist die Verbindung unverschlüsselt. Auf meinem Server wird "Hitch" (hitch-tls.org/) zur Terminierung eingesetzt. Dieser Proxy leitet dann die Daten zum Reverse-Proxy Varnish (varnish-cache.org/) weiter, der dann entscheidet, ob die von TYPO3 generierten Webseiten gecacht werden dürfen oder direkt vom Webserver nginx geholt werden müssen.

Auch wenn man mit Hitch und Varnish 5 inzwischen in der Lage ist, die Server-Variablen HTTP_SCHEME und HTTP_X_FORWARDED_PROTO auf https zu setzen, reicht dies nicht immer aus. Da die REMOTE_ADDR beim Einsatz von Varnish inzwischen nicht mehr die IP vom Proxy, sondern vom Besucher der Webseite beinhaltet, greift die if-Abfrage in der TYPO3 Core Datei typo3/sysext/core/Classes/Utility/GeneralUtility.php Zeile 6 nicht mehr. Schaut man sich den Code weiter an, dann sieht man die fehlende Environment-Variable HTTPS, die auf 'on' oder 1 gesetzt sein muss. Im Gegensatz zum Apache Webserver wird die Variable von nginx nicht automatisch zum PHP-FPM Daemon weitergegeben, aber sie kann einfach hinzugefügt werden.

typo3/sysext/core/Classes/Utility/GeneralUtility.php

case 'TYPO3_SSL':
                $proxySSL = trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxySSL']);
                if ($proxySSL === '*') {
                    $proxySSL = $GLOBALS['TYPO3_CONF_VARS']['SYS']['reverseProxyIP'];
                }
                if (self::cmpIP($_SERVER['REMOTE_ADDR'], $proxySSL)) {
                    $retVal = true;
                } else {
                    $retVal = $_SERVER['SSL_SESSION_ID'] || strtolower($_SERVER['HTTPS']) === 'on' || (string)$_SERVER['HTTPS'] === '1';
                }
                break;

Damit jetzt im PHP die Environment-Variable HTTPS auf 'on' gesetzt werden kann, muss der passende Abschnitt in den nginx-Konfigurationen geändert werden:

Include Snippet für php

location ~ \.php$ {
        include snippets/fastcgi-php.conf;

        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;

        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

        fastcgi_buffers 8 16k;
        fastcgi_buffer_size 32k;
        fastcgi_connect_timeout 300;
        fastcgi_send_timeout 300;
        fastcgi_read_timeout 300;

        include fastcgi_params;

        fastcgi_param TYPO3_CONTEXT Production;
        fastcgi_param TYPO3_DISABLE_CORE_UPDATER 1;
        fastcgi_param HTTPS 'on';
}

In diesem Beispiel sind auch noch zwei weitere Environment-Variablen gesetzt, die dafür sorgen, dass TYPO3 im Production Context läuft und dass TYPO3 Updates nicht im Install-Tool gemacht werden können.