個人WordPressサイトをCloudflare経由で爆速にしてみた
概要
本記事は Cloudflare Advent Calendar 2024 19 日目の記事です。
WordPress のサイトを Cloudflare の CDN を使って高速に表示できるようにした事例を紹介します。
今回移行してみたサイトの 1 つはこちら。瞬間的に表示されると思います。
3行まとめ
- Cloudflare CDN を利用して、パフォーマンスが 15req/sec => 512req/sec。(約34倍改善) レスポンス速度が平均 611.64ms/req => 28.82ms/req。(約21倍改善)。
- WordPress に Cloudflare プラグインを導入して CDN 連携を自動化
- E2EE(end-to-end Encryption)を導入して経路の安全性を向上
背景
自宅サーバで WordPress を使ったサイトを 10 個ほど運用しています。
問題
WordPress は動的にページを生成するため、突発的なトラフィックや悪意のあるプログラムによる攻撃を受けたときにサーバの負荷が上がってしまう問題がありました。
WordPress で作られたユーザ向けのページはほとんどのトラフィックが Read なので、CDN(Contents Delivery Network)に載せられれば効率的に配信ができます。
しかし、記事を更新したり、コメントが追加された際には CDN 上のキャッシュの削除といった操作する必要があり、Origin が更新された際に CDN への通知が必要となります。
アプローチ
WordPress には Cloudflare の CDN を使った運用を効率的に行う プラグインが用意されているので、これを使えばWordPressの記事更新に応じたCDNの運用を行えます。
しかも Cloudflare の CDN は無料で利用できます。
Cloudflare CDNの主な特徴は以下の通りです:
- 世界中に 330 以上のデータセンターを展開し、Anycast ネットワークを活用
- インターネット人口の 95%から約 50 ミリ秒以内でアクセス可能
- DDoS 攻撃の緩和や WAF などのクラウドセキュリティ機能
- SSL/TLS 暗号化によるセキュアな通信
Cloudflare CDN には上記以外にも様々な機能があります。
概念的には以下のようになります:

CDN を完全にユーザ向けサービスのフロントエンドに配置します。
画像や動画の静的コンテンツだけでなく、ページ自体もほとんど更新が入らないので CDN に載せます。このように CDN、WAF、ロードバランサの機能を統合するアーキテクチャは昨今のスタンダードになってきていると思います。
Cloudflareでの設定
フェーズ1
Cloudflare を利用するためにはドメインが必要であり、DNSゾーンをCloudflareでホスティングする必要があります。
Cloudflare のゾーンホスティング機能は無料で利用できます。
新規構築ではなく、別の DNS ゾーンサービスを使っている場合は、まず Cloudflare に DNS ゾーンを管理させる設定をします。

「Cloudflare as CDN」と書かれている部分が普通の概念とは異なりますが、CDNとざっくり書いてしまいましたがこの部分がCloudflareの超重要な部分です。
Cloudflare の CDN はただの CDN ではなく、TLS terminationを行い、リバースプロキシとして動作しています。
それにより、外部からの攻撃、リクエスト内容の検証、オリジンへのトラフィックの制御を行えるようになっています。
次に、設定の手順の概略を記します。
DNSゾーンの登録
まず、Cloudflare を使うための第 1 ステップはドメインの ゾーンを登録するところからです。

ゾーンを登録したら、各レコードを追加していきます。
レコードを追加する際に普通とは違うのが、"Proxy status" というスイッチがあることです。このスイッチをオンにすると DNS ゾーンサーバのレスポンスは登録した IP アドレスなどではなく、Cloudflare のリバースプロキシサーバのアドレスに置き換わります。
DNS の設定なのに、DNS とは違うリバースプロキシの設定も混ざっているので分かりづらいですが、ここは一旦オフにして単純に DNS ゾーンの設定にフォーカスします。

リバースプロキシで受けられるようにWordPress側のWebサーバを設定
既存の WordPress はインターネット経由でエンドユーザからリクエストを受ける設定になっています。それに追加して、Cloudflare CDN のリバースプロキシからアクセスを受けられるように設定します。
運用中のサーバの場合は、並行運用できるように追加で設定します。
設定例: Configure Nginx Reverse Proxy behind Cloudflare
キャッシュルールの設定
リバースプロキシ自体が CDN 機能を持っているので、どのコンテンツをキャッシュするかを設定します。
Web から分かりやすい UI で設定できるので、自分のホスティングするサービスに応じてルールを書いていきます。
無料プランでは 10 個までしかルールセットを作れません。私はキャッシュの期間ごとにルールセットを作っています。
1 ヶ月キャッシュ、7 日キャッシュ、1 日キャッシュ、キャッシュ無しという分類です。

私の環境における「キャッシュ無し」の設定例を示します。
WordPress の管理画面、ヘルスチェック用エンドポイント、動的なスクリプト、RSS フィードなどを記載しています。

逆に 1 ヶ月の長期間を設定している設定はこちらです。主に画像などの静的アセットが対象です。昨今は CDN を考慮したアセットの構築が行われているので、内容が変われば URL も変わるという前提のためです。

CDN 周りだけでも以下のような設定が簡単に行えます:
- クエリ文字列ごとにキャッシュするかどうか
- ブラウザキャッシュのヘッダを付加するか
- オリジンが落ちたときにキャッシュをサーブするか
- CDN の一時的な一括無効化

WordPressの設定
WordPress 用に Cloudflare のプラグインが用意されています。
インストールしなくても使えますが、記事を更新すると自動で CDN の関連ページをパージしてくれます。
また、CDN で WordPress を運用するにあたって WordPress の挙動を裏で自動的に変更しているようです。

例えば、WordPress は動的にページを生成しているので、管理者が記事を閲覧したときと、そうでないときはコンテンツの内容が違います。
その点を考慮して管理者が閲覧したときの内容はキャッシュされないような仕組みを提供しています(おそらく)
Cloudflare CDN を使う場合は Cloudflare プラグインは必須です。物理的にはインストールしなくても運用できますが、様々な運用する際のユースケースに対応する機能が入っているので、入れておかないと予想外のコンテンツがキャッシュされてしまうリスクがあります。
CloudflareのDNS設定でリバースプロキシを有効にする
最後に、DNS の設定を書き換えて Cloudflare のリバースプロキシ経由でアクセスできるように設定を変更します。
こうすることで CDN によって WordPress サイトを配信できます。
フェーズ2
フェーズ 1 だけの設定では問題ないのですが、オリジナルの WordPress サイトはグローバルに公開された状態なので攻撃の危険性があります。
フェーズ 2 では、オリジナルの WordPress をインターネット上に公開しない設定をし、オリジン側のポート開放が不要になってよりセキュアにサービス運用を行えます。
目指すトポロジは以下です:

トンネルのセットアップ
オリジン側に Cloudflare のデーモンを動かして、トンネルを設定できます。Cloudflare とオリジンとのトラフィックをこのトンネルを通すことによってオリジンサーバ側でポート開放をする必要がなくなります。
トンネルを使うためには Cloudflare 上の Zero Trust の管理画面で設定します。
1 ホストに対して 1 本のトンネルを作ってある設定例です。

デーモンのインストールも非常に簡単で、管理画面上に表示されている例にあるコマンドを実行するだけです。

以下のようにパブリックのホスト名と、オリジンのサービス名を登録していきます。ここで登録すると Cloudflare の DNS の設定にレコードが追加されていきます。既存のレコードと重複する場合はエラーが出ます。

トンネル経由でオリジンへアクセス
トンネルの設定をする際に、Cloudflare とオリジンの通信を安全にしておくことをおすすめします。ブラウザと Cloudflare 間の設定はグローバルなので Let's Encrypt といった枠組みで TLS 証明書の発行と運用が簡単に設定できますが、オリジンへのアクセスはプライベートネットワークなのでそう簡単にはできません。
そこで、Cloudflare が発行する証明書をオリジンサーバにインストールすることで、Cloudflare から発行された証明書がインストールされたオリジンサーバということを担保する証明書を利用します。

その設定が完了すれば、上記のように Cloudflare を挟んでも安全にオリジンの信頼性を保証できることになります。
Cloudflare 上ではこのことを E2EE と呼んでいますが、TLS termination を Cloudflare 上で行っているので end-to-end での秘匿性と完全性は保証できません。紛らわしい表現ですね。
また、ここでは触れませんが SSH などのサービスも Zero Trust のサービスによってトンネル経由でアクセスできるように設定できるので、SSH のポートすら開ける必要がありません。
Cloudflareの有料機能
無料プランでも多くの機能が利用可能ですが、有料プランではさらに高度な機能が提供されています:
- Waiting page: トラフィック急増時にユーザーを待機させる機能
- Image compression: 画像を webp に自動変換
- Advanced WAF: HTTP リクエストの内容を分析し、不審なアクセスを検知
考察
Cloudflare を導入してみて大きく変わったことを書いておきます。
レスポンスタイムが超速い
CDN にキャッシュされると表示が一瞬で終わります。
このページをリロードしてみると、ブラウザキャッシュが読み込んだかのような速さで表示されると思います。
軽くベンチマークをしてみると、 512.91req/sec でました。
❯ wrk 'https://blog.teraren.com/'
Running 10s test @ https://blog.teraren.com/
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 28.82ms 90.99ms 1.40s 98.65%
Req/Sec 257.79 43.32 353.00 73.50%
5147 requests in 10.03s, 2.06GB read
Requests/sec: 512.91
Transfer/sec: 210.53MB
参考までにWordPressの動的ページをベンチマークしてみます。
❯ wrk -H 'Host: blog.teraren.com' http://localhost:8080/
Running 10s test @ http://localhost:8080/
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 611.64ms 94.75ms 948.43ms 74.05%
Req/Sec 9.68 5.43 30.00 72.22%
158 requests in 10.02s, 64.64MB read
Requests/sec: 15.77
Transfer/sec: 6.45MB
15.77req/secでした。
WordPressで運用しているサイトはそのままで運用しているとキャパが少ないので普通はWP Super Cacheを入れて運用すると思いますが、これを機にページをキャッシュするプラグインをこの際にすべて削除しました。
Webサーバ側の設定が激減
WordPressのサイトでは1サイトあたり約100行削減できました。
HTTPのリダイレクト、HSTS、text compressionの設定などなどを削減できてメンテナンス性が上がります。
# git diff --stat a9d832ed7f1493ea0ce8e75664e7a1b70f95760e blog.teraren.com.conf
nginx/conf.d/blog.teraren.com.conf | 178 ++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------
1 file changed, 40 insertions(+), 138 deletions(\-)
TLS証明書更新から開放
以前はcertbotを利用して自動で証明書の更新をしていましたが、使うべきではない言葉なので修正してください間に動かなくなっていたりとか設定ファイルが変わっていたりして結局は手での運用が発生してしまっていました。
Let’s encryptからの更新のお知らせのメールも気にしなくて良くなるので運用の手間から開放されました。
Cloudflare上で行うTLS証明書の設定関連では、HTTPからHTTPSのリダイレクト設定がスイッチ1つで行えたり、HSTSのヘッダ送信がUI上から行えます。
HSTSの設定項目。
自宅サーバ用の固定IPまたはDynamic DNSが不要
tunnelをCloudflareに張るだけなのでローカルで動いているサービスをインターネット上に公開できるので自宅の回線に固定IPアドレスやDynamic DNSが不要になりました。
自宅ネットワークにDMZを作ったりVLANを切っている場合は、設定を無くせる場合もあります(セキュリティ要件に応じてですが)
ポート開放が不要になった
外部から自宅のネットワークのポート開放(静的NAT)を消せました。Web系、SSHなどのリモートアクセス、リモートアクセスVPN関係のサービスを無くせます。
$ nmap <my home address>
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-22 11:40 JST
Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn
Nmap done: 1 IP address (0 hosts up) scanned in 3.04 seconds
Webページのパフォーマンススコアが向上
Webサイトのベストプラクティスを自動的に、または簡単に導入できるためGT metrixのスコアが上がります。

Cloudflare WordPress Pluginの機能
内部でどんなことをやっているのか軽く紹介します。
まず1つ目に、管理者がログインしていたらCDNのキャッシュを使わないようにしてくれています。
該当コード。
public function initAutomaticPlatformOptimization()
{
// it could be too late to set the headers,
// return early without triggering a warning in logs
if (headers_sent()) {
return;
}
// add header unconditionally so we can detect plugin is activated
$cache = apply_filters('cloudflare_use_cache', !is_user_logged_in());
if ($cache) {
header('cf-edge-cache: cache,platform=wordpress');
} else {
header('cf-edge-cache: no-cache');
}
}
記事やコメントが更新されたらCDNの関連するページを削除してくれます。CloudflareのCDNは削除命令を出してから数秒で消えますが
AWS CloudFrontは数秒で消えてくれます。
該当コード。
public function purgeCacheOnPostStatusChange($new_status, $old_status, $post)
{
if ('publish' === $new_status || 'publish' === $old_status) {
$this->purgeCacheByRelevantURLs($post->ID);
}
}
public function purgeCacheOnCommentStatusChange($new_status, $old_status, $comment)
{
if (!isset($comment->comment_post_ID) || empty($comment->comment_post_ID)) {
return; // nothing to do
}
// in case the comment status changed, and either old or new status is "approved", we need to purge cache for the corresponding post
if (($old_status != $new_status) && (($old_status === 'approved') || ($new_status === 'approved'))) {
$this->purgeCacheByRelevantURLs($comment->comment_post_ID);
return;
}
}
Cloudflareの統計情報
リバースプロキシと CDN を使いだすと以下のような統計情報が表示されてきます。眺めているだけでも楽しいです。
右にあるメニューに注目してほしいのですが、もしサービスが攻撃を受けていたら一時的に「JavaScript による人間かどうかのチャレンジを挟む」というスイッチがあるので ON にすれば origin のサービスを過負荷から守れます。
トラフィックの統計も細かく表示されます。
Web サイトへの攻撃に関する統計情報
使われたプロトコルの種別や、節約できた帯域の情報が表示されます。
30日で見てみると、300GBのトラフィックを節約できたみたいです。(無駄なトラフィックを節約することで CO2 削減にも貢献!)
まとめ
最初は Cloudflare の CDN が無料なので調査していましたが、実際は CDN 以外の機能も充実していることがわかりました。
しかも無料で使えるサービスが沢山あるので今回は無料で使えるサービスをフルに活用して安全で安定的なサービス提供をできるように設定をしました。
Cloudflare を使いだす最初の設定が大変ですし、知識が必要になりますがその後は安心して高速で安全な Web サービスの提供を行えるようになります。






Discussion