https,nginx,リバースプロキシ,CloudFlare使用でWordPressがリダイレクトループにハマった時

      2016/03/01

やっとクリアした…何回目のアタックだっただろう。昨日夕方にリトライして3時間…。意味を理解。

そもそもなんでこんなことになるのかというと、nginxのconfファイルの設定の意味を詳細に理解していないという所にあるのだけど。同様にハマる人もいると思うのでシェア。情報が意外と少なくて困った。

ハマる条件

  • WordPressをまるごとSSL化する
  • nginxをつかっている
  • リバースプロキシ
  • CloudFlareを使っている

発生する事象

  • サイト及び管理画面におけるリダイレクトループの発生

実行したいこと

  • httpでアクセスがあったらhttpsにリダイレクトする
  • 問題なくWordpressが稼働する

解決方法

  1. サーバーブロックはhttpとhttpsで分ける
  2. httpsのサーバーブロックにヘッダ情報を追加

サーバーブロックはhttpとhttpsで分ける

httpのアクセスをhttpsにリダイレクトする為にそうする。海外のフォーラムなんかを見ていても、これは色んな所に書いてあった。具体的には以下の様にする。

[code]
server {
listen 80;
server_name 設定したいドメイン(例:yourdomain.com);
return 301 https://yourdomain.com$request_uri;
}

server {
listen 443 ssl;

以下https設定

[/code]

httpsのサーバーブロックにヘッダ情報を追加

ここでドハマりした。

そもそものnginxの設定はUKlabさんのを使ってる。

さくらのVPSでWordPressを動かそう – nginx設定編 - - UKLab開発者ブログ


WordPress用に細かな設定がされていて良いのだけど、それ故にハマった。
やらなくてはいけないことはここにかいてある。

WordPressをhttps化してnginx reverse proxy配下で使うには | 家鯖構築日記


nginxのconfファイルを書き換えることと、Wordpressのwp-config.phpに追記をするという二点。まずはnginxの方から。
httpsのサーバーブロックに以下を追記する。
重要なのはここだ

[code]
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
    
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass          http://backend.hogehoge.site/;
}
[/code]

これ。全部必要。
httpsのサーバーブロック全体はこんな感じ。

[code]
server {
listen 443 ssl;

# example.com、example.com/wordpress、wp.example.comなどを指定する。
server_name yourdomain.com;
# ドキュメントルートの設定
root /var/www/html/yourdomain.com;
index index.html index.htm;
charset utf-8;

# 秘密鍵 (cert. key)
ssl_certificate_key /etc/nginx/ssl/秘密鍵.key;
# 合体証明書
ssl_certificate /etc/nginx/ssl/合体証明書.crt;

ssl_protocols TLSv1 TLSv1.1 TLSV1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

access_log /var/log/nginx/$host.access.log main;
error_log /var/log/nginx/$host.error.log;

# アクセスログ、Not Foundログを無効にするための設定を読み込みます
include /etc/nginx/conf.d/common/drop.conf;

rewrite /wp-admin$ $scheme://$host$uri/ permanent;

# 変数の初期化
set $mobile '';
# 携帯やスマートフォンを別々にキャッシュしたい場合は先頭の#を外す
#include /etc/nginx/conf.d/common/mobile-cache.conf;

location ~* ^/wp-(content|admin|includes) {
index index.php index.html index.htm;
if ($request_filename ~ .*\.php) {
break;
proxy_pass http://backend;
}
# expiresヘッダー用の設定を読み込みます。
include /etc/nginx/conf.d/common/expires.conf;
}

location / {
# PHPファイルへのアクセスの場合バックエンドに処理が投げられる。
if ($request_filename ~ .*\.php) {
break;
proxy_pass http://backend;
}
# expiresヘッダー用の設定を読み込みます。
include /etc/nginx/conf.d/common/expires.conf;

# デフォルトではキャッシュするように変数に0をセットする。
set $do_not_cache 0;
# WordPressにログインしている場合はキャッシュしないように変数に1をセットする。
if ($http_cookie ~* "comment_author_|wordpress_(?!test_cookie)|wp-postpass_" ) {
set $do_not_cache 1;
}
# POSTアクセスの場合もキャッシュしないように変数に1をセットする。
if ($request_method = POST) {
set $do_not_cache 1;
}
proxy_no_cache $do_not_cache;
proxy_cache_bypass $do_not_cache;

proxy_redirect off;
proxy_cache czone;
proxy_cache_key "$scheme://$host$request_uri$mobile";
proxy_cache_valid 200 0m;

# do_not_cacheの値が1の場合バックエンドに処理が投げられる。
proxy_pass http://backend;
}

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# phpMyAdmin用設定を読み込む(このドメインで使用する場合のみ先頭の#を外して下さい。)
#include /etc/nginx/conf.d/common/phpmyadmin.conf;

# postfixadmin用設定を読み込む(このドメインで使用する場合のみ先頭の#を外して下さい。)
#include /etc/nginx/conf.d/common/postfixadmin.conf;

# 50x系のページ設定/usr/share/nginx/htmlにあるファイルが使用される
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
[/code]

17〜20行目と76〜79行目が追記した部分。

次にwp-config.phpについて。
これは以下の通り

[code]
<?php

if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
&& $_SERVER['HTTP_X_FORWARDED_PROTO'] === "https") {
$_SERVER['HTTPS'] = 'on';
}

define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

〜ここから下は元々書かれている部分〜
[/code]

CloudFlareを使っている場合

恐らくここまでやってもリダイレクトループにハマります。
冒頭に書いたconfの設定をこんな感じに変えます。
[code]
server {
listen 80;
server_name 設定したいドメイン(例:yourdomain.com);
location / {
if ($http_x_forwarded_proto = "http") {
return 301 https://yourdomain.com$request_uri;
}
}
}

server {
listen 443 ssl;

以下https設定
[/code]

そして、CloudFlareのSSL設定をFullにしてください。それでOK。

参考:NginxでSSLの設定でredirect loopが起きる

おすすめ記事一覧

 - Tips, Wordpress