最近知ったGoogleマネージド証明書がなかなかいい感じだったので、じゃあ放置していた既存サイトもついでにhttps化しようかなーと長らくほったらかしだったサイトをいじっていたら色々問題にひっかかったので備忘録として。
ここに書いている以外にも多くの紆余曲折があったのですが、あとから振り返って「この手順でよかったものだと思われる」ということを書いています。もし同じ手順を踏んだのにうまくいかなかった、という場合にはすみません。
大事な情報の大半はほとんどリンク先にあり、この記事独自?と言える情報は手順2まわりくらいな気がしますが、WordPressについて、しかもGPC提供ではないオレオレ構成のComputeEngineでhttps対応、というまさに自分の状況にあたる情報が見つからなかったので、似たような状況で困っているかたがいらしたらご参考になればと思います。
前提
環境
- PHP7.0
- WordPress(いちおう作業直前に最新に更新する)
- Apache2
構成
- GCP提供のWordPressイメージは使用せず、OSだけ積んだCompute Engineに独自構築
- Compute Engineのインスタンスひとつだけを使用し、必要なものをすべて積んでいる。DBもWEBサーバ上で動かしている
- 公開用サイトはhttpのみでアクセスする前提で提供
- 管理ページのみはもとからhttpsでのみアクセスするようにしていた
- オレオレ証明書でssl化。アクセス時にブラウザから警告が出るが一般公開しているわけではないので無視して使う。
やりたかったこと
- 現在httpでのみ公開する前提のサイトを、httpとhttps両方でアクセスできるようにする
- 管理画面は引き続きhttpsのみでのアクセスとする
- SSL証明書はGoogleマネージド証明書を使用
- gcloudコマンド打つのかったるいので、必要な設定はすべてConsole画面でやりたい
やったこと
手順1、公式手順に従って設定ロードバランサを設定
公式ドキュメントの、このあたり
の手順に従い設定。(入力画面までたどり着けばあとは画面の内容に従えばOK!)
結果
いちおう表示がうまくいったが問題発生
発生した問題
- 問題1−1:httpsでアクセスした際に、サイトの表示が壊れる
- cssの読み込みがうまくいっていない様子
- httpではこれまで通り動く
- 問題1ー2:管理画面に、httpsで入れなくなった
- 「リダイレクトが多発」でアクセスできないというエラー。
問題の原因
前掲の公式ドキュメントに従いhttps対応を行なうと、サービス構成が以下のように変わる。
変更前:
サーバ - クライアント
変更後:
サーバ - ロードバランサ - クライアント
このとき、公式マニュアルの説明のまま設定した場合、ロードバランサ - クライアント間はhttpとhttpsのどちらでも動き サーバ - ロードバランサ
間は常にhttpで通信する、という構成になる。その結果、以下のような現象が発生し、上記の問題が発生する。
問題1ー1の原因詳細
WordPressが生成するページにおいて、cssのsrcなどのURLは、httpでのリクエストに対してはhttpのプロトコル(http://
)で、httpsでのリクエストに対してはhttpsプロトコル(https://
)で値を返す。
しかし、設定に従うと、サーバには常にhttpでリクエストが来るようになる(ロードバランサの設定がそうであるため)ので、結果、サーバは常にhttp向けのページを生成して返すことになる。
いっぽうクライアント、つまりWEBブラウザは、セキュアなhttpsでアクセスしているページに非セキュアなhttpでの読み込みが発生しているため、そのURL読み込みをブロックする。(セキュリティ的な観点からの仕様と思われる)
以上の結果から、クライアントからhttpでアクセスした際には問題なくcssを読み込めるが、httpsでアクセスしたした場合はcssの読み込みをブラウザがブロックするということが発生し、そのためhttpsでアクセスしたときだけ表示が崩れる。
問題1ー2の原因詳細
すでに述べたようにロードバランサからサーバへは常にhttpプロトコルでリクエストを行う。
管理画面にはhttpsによるアクセスしか許していないので、httpでのリクエストが来た場合リダイレクトを返す。しかし、ブラウザがhttpsへのリクエストを要求しても、間に立つロードバランサがサーバに対してはhttpでリクエストしてしまうので、結果、リダイレクトの無限ループが発生することになり、それを検知したブラウザによりアクセスが中断される。
手順2、ロードバランサ - サーバ間の通信をhttpからhttpsに変更
公式手順で以下のような「バックエンドサービスの設定」の説明において、「プロトコルHTTP」「ポート80」が指定されているところを「プロトコルHTTPS」「ポート443」と読み替えてバックエンドサービスを追加し、そちらを使用する。
結果
http, httpsで問題なくアクセスできるようになり、管理画面も動くようになったが、別の問題発生。
発生した問題
- 問題2:タイムアウトで画面にアクセスできなくなる現象が頻発
- しばらく時間を置いてからのアクセス時だとほぼ100%起こる
- 画面には以下のようなエラーメッセージが表示される。
Error: Server Error
The server encountered a temporary error and could not complete your request.
Please try again in 30 seconds.
問題の原因
次の手順の参考ページに詳しく書いてありますm(_ _)m
手順3、KeepAliveTimeoutとMaxKeepAliveRequestsを大きくすると解決するかも?
参考:
https://blog.teratail.com/entry/gcp-lb-and-apache-keepalive
結果
解決!!!(・∀・)
余談
先にも書きましたが、ここに残している以外にもいっぱい無駄なことをやり、たとえばPHPなどのバージョンをあげてみたり、WordPressやApache関連の無駄そうな設定やプラグインを削除してみたり、逆にhttps関連のプラグインを追加してみたり…など色々やったのですが、振り返ってみればまったく意味のない対応でした。
また、意味がないだけならよかったのですが、設定の過不足競合が起こるなど別の問題が起こりまくり、一時はサイトが動かなくなって、インスタンスの再起動を繰り返したり、DBの値を直接書き換えてようやく復旧、という事態にまで発展しました…。
いまさら当たり前の話ではありますが検証用の環境を用意してまずはそちらで手順を確認するべきでした。過疎化した放置サイトなので仮に落ちてもまあいいかといきなり本番でやったのですが、どんな限界集落サイトでも、本番に異常があるというのは精神衛生上よくないですね。
さらに余談ですが、3年ほど前のGCPでComputeEngineのバックアップを定期取得という記事で設定したのがまさにこのサイトでした。
最近ではバックアップにはGCP提供の機能をそのまま使っているので、当時はまさかこんなことをやっていたとは我ながら驚きです(笑) 放置しすぎてスナップショットをどうやってとっていたのかすら忘れてしまっていたのを、自分の書いたもの読んで思い出しました。
ドキュメントは人のためならず、ということで…。
ここまで読んでいただきありがとうございました m(_ _)m