WordPress hinter einem Reverse-Proxy

WordPress ist eine PHP-Applikation, die auf einem Webserver läuft. Normalerweise terminiert dieser Webserver auch die SSL/TLS Verbindungen vom Browser.

In einer Container-Umgebung, beispielsweise mit Docker, wird für ein Routing der Anfragen eines Browsers ein Reverse-Proxy davor geschaltet. Dadurch muss der Webserver-Container seine Ports (zumeist 80/TCP für HTTP) nicht publizieren und es können mehrere Container auf dem Port abgehandelt werden.

Hierbei wird innerhalb der Container-Umgebung auf dem Host ohne SSL/TLS Verschlüsselung gearbeitet, aber nach Außen mit dem Reverse-Proxy diese Funktionalität dennoch zur Verfügung gestellt.

Dadurch besteht aber dann das Problem, dass WordPress nicht auf Anhieb erkennt, das die eigentliche Browser-Verbindung über einen verschlüsselten HTTPS-Kanal läuft. Dies liegt daran, dass WordPress hierzu auf eine Server-Variable zurück greift, die direkt durch den verwendeten Webserver entsprechend dem wie er angesprochen gesetzt wird – es handelt sich dabei im PHP um: $_SERVER['HTTPS']

Voraussetzung ist, dass der Reverse-Proxy die Forwarded-Header zum Webserver hin mit gibt – dies ist zumeist standardmäßig eingeschaltet, muss aber ggf. im verwendeten Reverse-Proxy entsprechend eingestellt werden. (Dieses Thema will ich hier nicht behandeln, da es doch in seinen Variationen und Konstellationen zu umfangreich ist.)

Die wohl geschickte Möglichkeit ist bei WordPress selbst im Artikel Administration Over SSL dokumentiert. Dabei wird in der Datei wp-config.php folgende Ergänzung mit eingesetzt:

    <?php
     
    define('FORCE_SSL_ADMIN', true);
    /**
     * in some setups HTTP_X_FORWARDED_PROTO might contain 
     * a comma-separated list e.g. http,https
     * so check for https existence
     */
    if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false) $_SERVER['HTTPS']='on';
     
    if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
        $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
    }
     
    /**
     * The base configuration for WordPress
     *
    ....Code-Sprache: PHP (php)

Hierdurch wird die Server-Variable $_SERVER['HTTP_X_FORWARDED_PROTO'] ausgewertet um dann $_SERVER['HTTPS']='on' zu setzen.

Wenn eine WordPress-Site neu aufgesetzt wird, so kann man die Vorlage wp-config-sample.php für die wp-config.php umkopieren, setzt dort den oben aufgezeigten Code-Block am Anfang ein und passt seinen Bedürfnissen nach die Konstanten zu der verwendeten Datenbank an. Danach kann man dann mit dem Browser das Setup durchgehen um die Installation abzuschließen.

WordPress in einem Container

Wer sich beispielsweise mit Docker für den Betrieb in einem Container entscheidet, der hat weitere Möglichkeiten die Anpassung vorzunehmen.

Zunächst kann man bereits beim Initialisieren des Containers mit dem offiziellen WordPress Docker-Image Angaben zur Datenbank und auch zum HTTPS-Status mitgeben.
Hier ein skizzenhaftes Beispiel für Docker Compose:

version: "3.9"

networks:
  wpnet:
    external: true
  wpback:
    external: false

services:
  frontrt:
    image: haproxy:alpine
    container_name: frontrt
    restart: always
    volumes:
      - ./haproxy:/usr/local/etc/haproxy
    ports:
      - 80:80
      - 443:443
    depends_on:
      - wpsite
    networks:
      - wpnet
  wpsite:
    image: wordpress
    container_name: wpsite
    restart: always
    volumes:
      - ./wordpress:/var/www/html
      - ./secrets:/secrets
    environment:
      WORDPRESS_DB_HOST: database
      WORDPRESS_DB_USER_FILE: /secrets/username_secret
      WORDPRESS_DB_NAME: wpdb
      WORDPRESS_DB_PASSWORD_FILE: /secrets/password_secret
      WORDPRESS_TABLE_PREFIX: wp_
      VIRTUAL_HOST: "${OWN_DOMAIN},www.${OWN_DOMAIN}"
      WORDPRESS_CONFIG_EXTRA: |
        define('WP_HOME', 'https://${OWN_DOMAIN}');
        define('WP_SITEURL', 'https://${OWN_DOMAIN}');
        $_SERVER['HTTPS'] = 'on';
    depends_on:
      - database
    networks:
      - wpnet
      - wpback
  database:
    image: mariadb:10
    container_name: database
    restart: always
    volumes:
      - ./wpdbdata:/var/lib/mysql
      - ./secrets:/secrets
    environment:
      MARIADB_DATABASE: wpdb
      MARIADB_USER_FILE: /secrets/username_secret
      MARIADB_PASSWORD_FILE: /secrets/password_secret
      MARIADB_RANDOM_ROOT_PASSWORD: 1
      MARIADB_AUTO_UPGRADE: 1
    networks:
      - wpback

Code-Sprache: PHP (php)

In diesem Beispiel ist ein HA-Proxy als Reverse-Proxy und ein Datenbank-Container mit enthalten. Auf die Konfigurationen dieser beiden Komponenten wird hier aber nicht genauer eingegangen.

Beschreibung im Groben:
– Als erstes wird ein Netzwerk für die Verbindung zwischen Reverse-Proxy und dem WordPress-Container erstellt (Zeile 4 und 5). Dieses mit dem Parameter external: true damit im WordPress-Container später auch weitere Plugins installiert werden können (der Container würde sonst nicht ins Internet kommen).
– Als nächstes wird ein Netzwerk für die Verbindung vom WordPress-Container zur Datenbank erstellt (Zeile 6 und 7). In diesem Fall mit external: false damit diese keine Verbindung zum Internet hat.
– Nun kommen die eigentlichen Services – beginnend mit dem Reverse-Proxy (Zeile 10 bis 22). Dieser publiziert seine Ports nach Außen (Zeile 16 bis 18) um dann auch vom Internet her erreichbar zu sein. Aber zugleich wird dieser Container mit dem Netzwerk verbunden, in dem als nächstes auch der WordPress-Container eingebunden seien wird.
– Mit dem festgeschriebenen Container-Namen ‚wpsite‘ wird der WordPress-Container eingestellt (Zeile 23 bis 45). Dieser Name kann dann so in der Konfiguration für den Revere-Proxy verwendet werden um den Webserver des WordPress-Containers ansprechen zu können. Auf ein Publizieren der Ports mit ports wird hier verzichtet, da dieser Container nicht direkt vom Internet her angesprochen werden soll. Dennoch wird wegen einem EXPOSE 80 im Image der Port 80 innerhalb der Docker-Netzwerke geöffnet.
– Als letztes kommt dann noch ein Container für eine Datenbank (Zeile 46 bis 60). Dieser ist nun mit dem geschlossenen und rein internen Netzwerk mit dem WordPress-Container verbunden und ebenfalls durch ein EXPOSE im Image mit seinem Standard-Port in diesem Netzwerk zu erreichen. Auch hier wurde ein eindeutiger Container-Name vergeben, der dann für die WordPress-Konfiguration verwendet werden kann.

Der in dem Docker-Compose File markierte Bereich (Zeile 30 bis 40) soll verdeutlichen, wie ein Docker-Container von WordPress mit der Möglichkeit zum Festlegen des HTTPS-Betriebs eingestellt werden kann. Der wichtigste Punkt ist dabei der Eintrag von Zeile 37 bis 40.

Schreibe einen Kommentar