4923 文字
25 分

個人開発のWebサービスをCloudflareに載せてみた【無料でここまでできる】

概要#

私は個人でWebサイトやWebサービスを色々公開しております。

この度、個人開発でWebサービスを運用するときにCloudflareを利用すると様々なリスクを無料でヘッジできるので事例を紹介します。

しかも無料です。

個人開発サービスの問題#

費用をかけられない#

お金をかければWAFや計算処理の高いサーバやコンテナなどの環境を使えますが、テストで開発したサービスや収益化するかどうかわからないサービスをたくさん運用することになるので固定費は可能な限り抑える必要があります。

いかに安く安定的にサービスを提供できるかは腕の見せどころでもあります。

複数サービスがダウンする可能性#

固定費を抑えるために1ホストにいろいろなサービスを動かすことが多いと思います。

よって、1つのサービスに対してDoS攻撃や突発的にWeb上でバズって大量のトラフィックが来ると捌ききれなくなってあるホストで運用しているサービスがすべてダウンしてしまうリスクがあります。

自宅サーバの場合はポートを解放しないといけない#

費用を抑えるために自宅サーバを運用して居る場合もあると思いますが、自宅サーバを公開するためにはポートを開放する必要があります。また、ホストレベルでクラックされた場合には自宅LANに第三者が入れる状態になってしまうリスクがあります。

Cloudflareとは#

主なサービスは、コンテンツ配信ネットワーク(CDN)、DDoS攻撃防御、Webアプリケーションファイアウォール(WAF)などのセキュリティ機能、およびインターネット最適化を提供します。Cloudflareの主な機能は以下になります。

  1. コンテンツ配信ネットワーク (CDN)
  2. DDoS保護
  3. Webアプリケーションファイアウォール (WAF)
  4. SSL/TLS暗号化
  5. DNSサービス
  6. Zero Trustセキュリティ
  7. エッジコンピューティング

これ以外にもたくさんのWebサービスを運用する上で便利な機能があります。

概念的には以下のようなイメージです。主にレイヤー7のアプリケーション層においてのリスクをCloudflareで全部受け止めてくれるような使い方ができます。

Cloudflareのダッシュボードをチラ見せしますとこんな感じになります。左のメニューを見てもらうとわかると思うのですが、Webサービスを運用する上で便利な機能が用意されています。

変更前インフラ#

おそらく、個人開発しているサービスや小規模サービスは以下のようなインフラ構成になっていると思います。

AWSでいえば、アプリケーションサーバはEC2やAWS Lightsail、自宅サーバで動かして、CDNに乗せられるようなコンテンツはCloud Frontを使うと言ったような感じです。

個人開発サービス・インフラデプロイ図

上記の構成であれば、無料枠で収まるかなと思います。

上記の構成を少し先に進めるために、WAFを入れたり、TLS証明書の自動更新を入れたりすると毎月数万円の金額がかかってきます。

Cloudflareでの設定#

フェーズ1#

Cloudflareを利用するためにはドメインが切られている必要があり、zoneサーバをCloudflareでホスティングする必要があります。

CloudflareのDNSだけを使うだけでも無料で運用できるのでそれだけでも価値はあったりしますが、まずはCloudflareの恩恵を受けるためには以下のような構成を作るのが1歩目です。

「Cloudflare as CDN」と書かれている部分が普通の概念とは異なるのですが、CDNとざっくり書いてしまいましがこの部分がCloudflareの超重要な部分です。そして説明しづらいところなのであんまりCloudflareが認知されていない理由にもなっているのかなと思います。

分かりやすく説明するために、1つのメインの機能としては、TLS terminationReverse Proxyが動作しています。それにより、外部からの攻撃、リクエスト内容の検証、originへのトラフィックの制御を行えるようになっています。

次に、設定の手順の概略を書いておきます。

DNS zoneの登録#

なにはともあれ、Cloudflareを使うための第1ステップはドメインのzoneを登録するところからです。

例えば、CloudflareのCDN(無料)だけを使いたかったとしてもDNS zoneをCloudflare上でホスティングする必要があります。Cloudflareの恩恵は受けられませんが、CloudflareのDNS zoneホスティングだけを使うと言ったことも無料で可能です。

(スクショは英語ですが、すべて日本語の表示もできます)

zoneを登録したら、各レコードを追加していきます。

レコードを追加する際に普通とは違うのが、“Proxy status” というスイッチがあることです。このスイッチをonにするとDNS zoneサーバのレスポンスは登録したIPアドレスなどではなく、CloudflareのReverse proxyサーバのアドレスに置き換わります。

では、”Proxy status”をonにしたら左の項目に登録したIPアドレスはどう扱われるのかといいますと、Reverse Proxyのoriginのホストとして扱われます。

独特な概念ではあって最初からつまずきやすいですが、一度理解してしまえば大丈夫ですし、段階的に切り替えられます。まずはReverse proxyをoffにした状態でDNS zoneを移行するのが良いです。

このblog.teraren.comのサイト自体もCloudflareを使っているのでDNSを引くとReverse proxyのアドレスが返ってきます。

Reverse proxyで受けられるようにoriginを設定#

既存のはorigin側のwebサーバの設定では、グローバルからリクエストを受ける設定になっているのでreverse proxyからアクセスを受けられるように設定します。

今までは、ユーザに見せるホスト名でのTLS terminationなどを行ったいた設定をreverse proxyからのアクセスを前提とした設定にします。

設定例: Configure Nginx Reverse Proxy behind Cloudflare

キャッシュルールの設定#

Reverse Proxy自体がCDN機能を持っているので、どのコンテンツをキャッシュするかどうかを設定します。

WebからわかりやすいUIで設定できるので自分のホスティングするサービスに応じてルールを書いていきます。

無料だと10個までしかルールセットを作れません。私はキャッシュの期間ごとにルールセットを作っています。

1ヶ月キャッシュ、7日キャッシュ、1日キャッシュ、キャッシュ無しという分類です。

(2つ目と3つ目は同義です。もともとは別の期間を設定していた名残です。)

私の環境における「キャッシュ無し」のスクショを書いておきます。

WordPressの管理画面、ヘルスチェック用エンドポイント、動的なスクリプト、RSSフィードなどを記載してあります。

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

CDN周りだけでも以下のような設定が簡単に行えます。

  • Query Stringごとにキャッシュするかどうか
  • ブラウザキャッシュのヘッダを付加するか
  • Originが落ちたときにキャッシュをサーブするか
  • CDNの一時的に一括無効化

CloudflareのCDNのすごいところはinvalidationが数秒で終わることです。Amazonだと数分とかかかったりしちゃいますが。

統計情報#

Reverse ProxyとCDNを使いだすと以下のような統計情報が表示されてきます。眺めているだけでも楽しいです。

右にあるメニューに注目してほしいのですが、もしサービスが攻撃を受けていたら一時的に「Javascriptによる人間かどうかのチャレンジを挟む」というスイッチがあるのでONにすればoriginのサービスを過負荷から守れます。

トラフィックの統計も細かく表示されます。

Webサイトへの攻撃に関する統計情報

プロトコルやどれだけ待機を節約できたかの情報も表示されます。

30日で見てみると、300GBのトラフィックを節約できたみたいです。(無駄なトラフィックを節約することでCO2削減にも貢献!)

WordPressの設定#

WordPress用にCloudflareのプラグインが用意されています。

インストールしなくても使えることは使えるのですが、記事を更新すると自動でCDNの関連ページをpurgeしてくれます。あと、CDNでWordPressを運用するにあたってWordPressの挙動を勝手に裏で変更しているようです。

Cloudflare CDN を使う場合はこのプラグインは必須と言っていいです。物理的にはインストールしなくても動きますが、様々な運用上のユースケースに対応する機能が入っているので、入れておかないと予想外のコンテンツがキャッシュされてしまうリスクがあります。

内部でどんなことをやっているのか軽く紹介します。

管理者ログイン時のキャッシュバイパス#

WordPressは動的にページを生成しているので、管理者が記事を閲覧したときと一般ユーザが閲覧したときではコンテンツの内容が異なります(管理バーの表示など)。このプラグインは管理者がログインしている場合は 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');
}
}

is_user_logged_in() で判定して、ログイン中は cf-edge-cache: no-cache ヘッダを送信することで CDN にキャッシュさせない仕組みです。

記事・コメント更新時の自動キャッシュパージ#

記事やコメントが更新されたら CDN の関連するページを自動で削除してくれます。Cloudflare の CDN は削除命令を出してから数秒で反映されるのでほぼリアルタイムです。

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;
}
}

記事のステータスが publish に変わったとき、またはコメントのステータスが approved に変わったときに関連URLのキャッシュをパージしています。この仕組みがあるおかげで、記事を更新したのにキャッシュが古いままという問題を気にしなくて済みます。

まとめ#

IPv6対応、HTTP3/QUICK対応、DDoS対策、TLS証明書更新自動化、HSTS設定、CDN利用、DNSSECが行えてます。今までは自分で頑張って設定していたことがもうすでに用意されている感じです。

Cloudfalreは昨今の面倒なWebサイト運用における設定をWebサービスの1レイヤー上で面倒を見てくれるようなサービスです。

しかも無料。。。申し訳なくなってきます。

フェーズ2#

フェーズ1からより安全にする方法です。

これにより、E2EEが実現でき、origin側のポート開放が不要になってよりセキュアにサービス運用を行えます。

tunnelのセットアップ#

origin側にCloudflareのdaemonを動かして、tunnelを設定できます。cloudflareとoriginの間のトラフィックをこのtunnelを通すことによってoriginサーバ側でポート開放をする必要が無くなります

tunnelを使うためにはCloudflare上のZero Trustの管理画面で設定します。

1ホストに対して1本のトンネルを作ってある設定例です。

daemonのインストールも非常に楽で管理画面上に表示されている例にあるコマンドを叩くだけです。

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

tunnel経由でoriginへアクセス#

1つ前のトンネルの設定をする際に、Cloudflareとoriginの通信を安全にしておくことをおすすめします。ブラウザとCloudflare間の設定はグローバルなのでLet’s encryptといった枠組みでTLS証明書の発行と運用簡単に設定できますが、originへのアクセスはprivateネットワークなのでそう簡単にはできません。

そこで、Cloudflareが発行する証明書をoriginサーバにインストールすることでCloudflareから発行された証明書がインストールされたoriginサーバということを担保する証明書を利用します。

その設定が完了すれば、上記のようにCloudflareを挟んでも安全にoriginの信頼性を保証できることになります。

Cloudflare上ではこのことをE2EEと呼んでますが、TLS terminationをCloudflare上で行っているのでE2Eでの秘匿性と、完全制は保証できないですね。紛らわしいです。

また、ここでは触れませんがsshなどのサービスもzero trustのサービスによってtunnel経由でアクセスできるように設定できるのでsshのポートすら空けないですみます。

BICはOFFにしたほうが良さそう#

Security > Settingメニューに有るBrowser Integrity Checkはオフにしたほうが良さそうです。プログラムからアクセスされるAPIサービスを運用していると、このルールによってblockされているリクエストが存在します。

24時間以内に10件くらいがブロックされてしまっていました。

Cloudflareの有料機能#

これまでの設定はすべて無料で行える範囲です。トラフィックがどんなに増えても無料です。

課金すれば、もっと良いサービスを利用できるので将来使いそうなサービスをいくつか紹介しておきます。

  1. Waiting page
    急にサイトに大量のトラフィックが来たときに、Cloudflareでの待機ルームを表示してoriginが空くまでユーザを待たせる機能。チケット予約サイトとかはこれを使えば一発解決します。
  2. Image compression
    pngやjpgなどの画像を次世代圧縮形式であるwebpに変換してブラウザにサーブしてくれる機能です。サーバサイドで色々設定しなくても済みます。
  3. Advanced WAF
    怪しいアクセスをHTTPリクエストの内容を見て判断してくれます。

考察#

Cloudflareを導入してみて大きく変わったことを書いておきます。

レスポンスタイムが超速い#

CDNにキャッシュされると表示が一瞬で終わります。

Terminal window
$ ab -c 5 -n 20 https://blog.teraren.com | grep 'Time per request'
Time per request: 30.551 [ms] (mean)

今見ているこのページをリロードしてみると、ブラウザキャッシュが読み込んだかのような速さで表示されると思います。

wrk を使ってもう少し詳しくベンチマークしてみました。まずは CDN 経由のリクエスト。

❯ 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

512.91req/sec、平均レイテンシ 28.82ms です。

参考までに 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、平均レイテンシ 611.64ms でした。

つまり、CDN を挟むことでスループットが 約34倍、レスポンス速度が 約21倍 改善しています。ここまで差が出ると CDN を使わない理由がありません。

WordPressで運用しているサイトはそのままで運用しているとキャパが少ないので普通はWP Super Cacheを入れて運用すると思いますが、Cloudflare CDN を使えばページキャッシュは CDN 側でやってくれるので、cache関連のプラグインもこの際にすべて削除しました。

Webサーバ側の設定が激減#

WordPressのサイトでは1サイトあたり約100行削減できました。

HTTPのリダイレクト、HSTS、text compressionの設定などなどを削減できてメンテナンス性が上がります。

Terminal window
# git diff --stat a9d832ed7f1493ea0ce8e75664e7a1b70f95760e matsu.teraren.com.conf
nginx/conf.d/matsu.teraren.com.conf | 178 ++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------
1 file changed, 40 insertions(+), 138 deletions(-)

TLS証明書更新から開放#

以前はcertbotで自動で更新を書けていても、知らない間に動かなくなっていたりとか設定ファイルが変わっていたりして結局は手での運用が発生してしまっていました。

Let’s encryptからの更新のお知らせのメールも一切期にしなくて良くなるので運用の手間からかなり開放されました。

TLS証明書に関連しては、HTTPからHTTPSのリダイレクト設定がスイッチ1つで行えたり、HSTSのヘッダ送信がUI上から行えるので非常に楽です。

HSTSの設定項目。

自宅サーバ用の固定IPまたはDynamic DNSが不要#

tunnelをCloudflareに張るだけなのでローカルで動いているサービスをインターネット上に公開できるので自宅の回線に固定IPアドレスやDynamic DNSが不要になりました。

自宅ネットワークにDMZを作ったりVLANを切っている場合は、設定を無くせる場合もあります。(セキュリティ要件に応じてですが)

ポート開放が無くなった#

外部から自宅のネットワークのポート開放を一切無くせました。Web系、SSHなどのリモートアクセス、場合によってはVPN関係のサービスを無くせます。

Terminal window
$ 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

自宅のIPアドレスを晒さなくても良くなったので安心感があります。

Webページのパフォーマンススコアが向上

Webサイトのベストプラクティスを自動的に、または簡単に導入できるためGT metrixのスコアが上がります。

まとめ#

最初はCloudflareのCDNが無料なので調査していたら、CloudflareはCDN以外の機能もかなり充実していてしかも無料で使えるサービスが沢山あるので今回は無料で使えるサービスをフルに活用して安全で安定的なサービス提供をできるように設定をしました。

最初の設定が大変ですし、知識が必要になりますがその後は安心して高速で安全なWebサービスの提供を行えるようになります。

個人開発のWebサービスをCloudflareに載せてみた【無料でここまでできる】
https://blog.teraren.com/posts/web-service-on-cloudflare/
作者
Yuki Matsukura
公開日
2023-04-23
ライセンス
CC BY-NC-SA 4.0
この記事が役に立ったら
GitHub Sponsorsで応援できます

コメント