SSL+リバースプロキシの環境で、WordPressの管理画面にログインする方法です。
普通にログイン出来るのではと思いますが、ある事をしないと下記GIFアニメーション画像のようにログイン画面に戻され、特にエラー等も表示されずログインできません。
SSL+リバースプロキシの環境でWordPressを使用することはあまりないかと思います。
知っていれば簡単ですが、知らないとハマるかもしれないので参考になれば幸いです。
SSL+リバースプロキシの環境を再現
自PCのローカル環境で、Docker Composeとsteveltn/https-portalのイメージを使用してSSL+リバースプロキシの環境を再現してみます。
■Docker Composeとは
複数のコンテナを定義し実行するDockerアプリケーションのツールです。
■steveltn/https-portalとは
Nginx、Let’s Encrypt、Dockerを搭載した完全に自動化されたHTTPSサーバーです。
これを使用することで、HTTPSを介して既存のWebアプリケーションを実行できます。
Docker Compose用のファイル・ディレクトリ構成
Docker Compose用のファイル・ディレクトリ構成は下記で用意してみました。
画像だと見づらいかもしれないので、テキストで表すと下記の構成です。
1 2 3 4 5 6 7 8 9 10 11 | directory/ ├── services/ │ ├── apache/ │ │ ├── conf/ │ │ │ ├── httpd-vhosts.conf │ │ │ └── httpd.conf │ │ └── data/ │ └── php7.4/ │ └── build/ │ └── Dockerfile └── docker-compose.yml |
各ファイルに関して、ファイルごとの内容を下記に記載します。
各ファイルの説明
■docker-compose.yml
Docker ComposeのYAMLファイルです。
取り敢えず環境再現ということで、シンプルな内容にしています。
なおdocker-composeについて詳しい説明は割愛します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | version: '3' services: db: image: mysql:5.7 restart: always ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: password123 TZ: Asia/Tokyo phpmyadmin: image: phpmyadmin/phpmyadmin:latest restart: always ports: - 8888:80 environment: UPLOAD_LIMIT: 2048M depends_on: - db php: build: ./services/php7.4/build volumes: - ./services/apache/data:/usr/local/apache2/htdocs restart: always depends_on: - db web: image: httpd:latest volumes: - ./services/apache/conf/httpd.conf:/usr/local/apache2/conf/httpd.conf - ./services/apache/conf/httpd-vhosts.conf:/usr/local/apache2/conf/extra/httpd-vhosts.conf - ./services/apache/data:/usr/local/apache2/htdocs restart: always ports: - 8080:80 depends_on: - php https-portal: image: steveltn/https-portal:1 restart: always ports: - 80:80 - 443:443 environment: STAGE: local DOMAINS: 'localhost -> http://web:80' depends_on: - web |
重要なのはhttps-portalがリバースプロキシとして動作している点です。
https-portalでポート80と443を使用し、localhostからhttp://web:80にリダイレクトしています。
web:80はサービス名がwebのコンテナですので、Apacheがポート80で待ち受けていますね。
https-portalのenvironmentのSTAGEには、local/staging/productionの3種類の値が指定できます。
それぞれ下記の証明書の利用になりますが、今回はローカル環境のためlocalの
自己署名証明書(オレオレ証明書)を使用します。
- local:自己署名証明書(オレオレ証明書)
- staging:ステージング環境用のLet’s Encryptの証明書
- production:Let’s Encryptの証明書
■services/apache/conf/httpd.conf
Apacheのconfファイルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | ServerRoot "/usr/local/apache2" Listen 80 LoadModule mpm_event_module modules/mod_mpm_event.so LoadModule authn_file_module modules/mod_authn_file.so LoadModule authn_core_module modules/mod_authn_core.so LoadModule authz_host_module modules/mod_authz_host.so LoadModule authz_groupfile_module modules/mod_authz_groupfile.so LoadModule authz_user_module modules/mod_authz_user.so LoadModule authz_core_module modules/mod_authz_core.so LoadModule access_compat_module modules/mod_access_compat.so LoadModule auth_basic_module modules/mod_auth_basic.so LoadModule reqtimeout_module modules/mod_reqtimeout.so LoadModule filter_module modules/mod_filter.so LoadModule deflate_module modules/mod_deflate.so LoadModule mime_module modules/mod_mime.so LoadModule log_config_module modules/mod_log_config.so LoadModule env_module modules/mod_env.so LoadModule headers_module modules/mod_headers.so LoadModule setenvif_module modules/mod_setenvif.so LoadModule version_module modules/mod_version.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so LoadModule unixd_module modules/mod_unixd.so LoadModule status_module modules/mod_status.so LoadModule autoindex_module modules/mod_autoindex.so LoadModule dir_module modules/mod_dir.so LoadModule alias_module modules/mod_alias.so <IfModule unixd_module> User daemon Group daemon </IfModule> ServerAdmin you@example.com <Directory /> AllowOverride none Require all denied </Directory> DocumentRoot "/usr/local/apache2/htdocs" <Directory "/usr/local/apache2/htdocs"> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory> <IfModule dir_module> DirectoryIndex index.html index.php </IfModule> <Files ".ht*"> Require all denied </Files> ErrorLog /proc/self/fd/2 LogLevel warn <IfModule log_config_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined LogFormat "%h %l %u %t \"%r\" %>s %b" common <IfModule logio_module> LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio </IfModule> CustomLog /proc/self/fd/1 common </IfModule> <IfModule alias_module> ScriptAlias /cgi-bin/ "/usr/local/apache2/cgi-bin/" </IfModule> <Directory "/usr/local/apache2/cgi-bin"> AllowOverride None Options None Require all granted </Directory> <IfModule headers_module> RequestHeader unset Proxy early </IfModule> <IfModule mime_module> TypesConfig conf/mime.types AddType application/x-compress .Z AddType application/x-gzip .gz .tgz </IfModule> Include conf/extra/httpd-vhosts.conf <IfModule proxy_html_module> Include conf/extra/proxy-html.conf </IfModule> <IfModule ssl_module> SSLRandomSeed startup builtin SSLRandomSeed connect builtin </IfModule> <FilesMatch \.php$> SetHandler "proxy:fcgi://php:9000" </FilesMatch> |
重要なのはファイルの最下部にて、ファイル名が.phpで終わる場合(=PHPファイルの場合)、php:9000で起動しているFastCGI(=PHP-FPM)に処理を任せている点です。
つまりApacheでPHPが動作するようにしています。
php:9000のphpの部分は、docker-compose.ymlに記載のサービス名がphpのコンテナのことです。
■services/apache/conf/httpd-vhosts.conf
Apacheのバーチャル環境用のconfファイルです。
今回はlocalhostのみの為バーチャル環境である必要はありませんが、分かりやすいようにconfファイルを分けています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <VirtualHost *:80> DocumentRoot /usr/local/apache2/htdocs ErrorLog /usr/local/apache2/logs/error.log CustomLog /usr/local/apache2/logs/access.log common <Directory /usr/local/apache2/htdocs> Options Includes ExecCGI FollowSymLinks AllowOverride All Require all granted </Directory> SetEnv APP_ENV local </VirtualHost> |
SetEnv APP_ENV local は、今回特に深い理由はありません。
■services/php7.4/build/Dockerfile
PHPのコンテナ作成時に使用するDockerfileです。
PHPからMySQLに接続したり等、必要なエクステンションをインストールしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | FROM php:7.4-fpm # タイムゾーン設定 ENV TZ=Asia/Tokyo # apt-get update RUN apt-get update # mysql extension RUN docker-php-ext-install mysqli pdo_mysql # zip extension RUN apt-get -y install libzip-dev RUN docker-php-ext-install zip |
Docker Composeを起動
docker-compose.ymlファイルがあるディレクトリで、Dockerが起動している状態でターミナルより下記コマンドを実行します。
1 | $ docker-compose up -d --build |
前述のDocker Composeのディレクトリ構成やファイル内容に問題がない場合は、正常に起動します。
ブラウザからアクセス
ブラウザからhttps://localhost/にアクセスすると、services/apache/data/の中身は空のため403エラーとなりますが、下記の画面が表示されていればSSL+リバースプロキシの環境が再現されています。
※steveltn/https-portalは、起動後の証明書作成に数分など時間がかかる場合があるため直ぐにブラウザアクセスしても表示されません。
その場合は数分ほど待ってからアクセスしてみてください。
WordPressの設置
データベース作成
前述のDocker Composeが起動していることが前提ですが、http://localhost:8888/にアクセスするとphpMyAdminにアクセスできます。
WordPressで使用するデータベースを作成しましょう。(phpMyAdminの使い方等は割愛します)
ユーザー名はroot、パスワードはdocker-compose.ymlに記載のpassword123でログインできます。
WordPressの設置
公式サイトからWordPressをダウンロードして、services/apache/data/に設置します。
設置後は、https://localhost/にアクセスしてWordPressの初期セットアップを完了させましょう。
WordPress側のリバースプロキシの対応
ここが本ブログの目的ですが、SSL+リバースプロキシの環境でWordPressの管理画面にログインできるようにするには、wp-config.phpの27〜31行目付近などに下記を追記します。
1 2 3 4 | define('FORCE_SSL_ADMIN', true); if ( ! empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ) { $_SERVER['HTTPS']='on'; } |
上記で追記したものは、WordPress公式のドキュメントでも説明されているものです。
管理画面での SSL 通信 | リバースプロキシの使用 | WordPress.org 日本語
https://ja.wordpress.org/support/article/administration-over-ssl/#%e3%83%aa%e3%83%90%e3%83%bc%e3%82%b9%e3%83%97%e3%83%ad%e3%82%ad%e3%82%b7%e3%81%ae%e4%bd%bf%e7%94%a8
SSL を提供するリバースプロキシにより WordPress がホストされ、自身は SSL なしでホストされる場合、このオプションを設定すると当初すべてのリクエストが無限リダイレクトループに陥ります。これを避けるには HTTP_X_FORWARDED_PROTO ヘッダーを認識するように WordPress を構成してください。ここでリバースプロキシは適切に構成されており、ヘッダーを設定するものとします。
ブラウザでWordPressのログイン画面を開いている場合は、上記追記後に画面をリロードしてログインを試みると、正常にログインできるはずです。
ブラウザでlocalhostにアクセスできない場合
Google Chromeでは、localhostにアクセスすると警告が表示されてアクセス出来ません。
アクセスできるようにするには、Chromeブラウザのアドレスバーに
chrome://flags/#allow-insecure-localhost
を入力及びアクセスして「Allow invalid certificates for resources loaded from localhost」をEnableにするとlocalhostにアクセスできるようになります。
但し、2021年1月19〜20日にGoogle Chrome 88がリリースされましたが、バージョン87までは上記で回避できましたがバージョン88では回避できないようになっています。
どうやら不具合のようで、下記にチケットが切られています。
1159077 – Flag expired : allow-insecure-localhost – chromium
https://bugs.chromium.org/p/chromium/issues/detail?id=1159077
不具合が解消されるまではバージョン88は避けるか、またはFirefoxなど別のブラウザでlocalhostにアクセスしましょう。
(Firefox 84 for Macではlocalhostにアクセスできること確認できています)
2021年2月3日追記
2021年2月2日リリースのGoogle Chromeブラウザのバージョン88.0.4324.146で、「Allow invalid certificates for resources loaded from localhost」が表示されない不具合が解消されました。
不具合があったバージョンは88.0.4324.96でした。
chrome://flags/#allow-insecure-localhost
にアクセスすると「Allow invalid certificates for resources loaded from localhost」が表示されるようになっています。
不具合が解消されたバージョン88.0.4324.146にて、localhostでアクセスできることも確認できました。
最後に
知っていれば簡単なことですが、知らなかったとしてもSSL+リバースプロキシ環境で、WordPressログイン画面で冒頭のGIFアニメーションの動作が確認出来ればピンと来る方も多いと思います。
今回はApacheでの再現でしたが、Nginxの場合でも行うことは全く同じです。
(Dockerでの環境再現は蛇足部分ではありましたが、Dockerの記事を書いたことなかったので少し書きたくなり書きました)
【動確環境】
Mac:macOS Big Sur 11.1
Docker:20.10.2, build 2291f61
Docker Compose:1.27.4, build 40524192
WordPress:5.6(日本語版)
その他:docker-compose.yml参照
コメントを残す