CDN導入の注意点
a-blog cms で構築されたサイトの前段に CDN を配置することは可能です。ただし、CDN を挟むことで a-blog cms 側にいくつかの設定対応が必要になります。
CDN サービス固有の設定手順は各サービスのドキュメントを参照してください。本ドキュメントは a-blog cms 側で必要な設定と注意点をまとめたものです。
1. 接続元 IP アドレスの取得設定
CDN を経由すると、そのままでは接続元 IP がすべて CDN のものになります。正しい IP が取得できないと、以下の機能が期待通りに動作しません。
ログイン制限・不正ログイン対策
IP アクセス制限
各種ログ記録(監査ログなど)
設定方法
/config.server.php で以下の定数を設定します。
// プロキシでIPアドレスを追加するヘッダーを指定します。
// RFC 7239 の Forwarded ヘッダーを使う場合は HTTP_FORWARDED を指定すると for= に加えて
// proto=・host= も読みます。X-Forwarded-Proto・X-Forwarded-Server を併送する構成もそのまま動作します。
define('PROXY_IP_HEADER', 'HTTP_TRUE_CLIENT_IP');
// プロキシが入っている場合、X-Forwarded-ForヘッダーからクライアントIPアドレスを特定するため、
// 信頼できるプロキシのIPを設定します。 例: define('TRUSTED_PROXY_LIST', 'xxx.xxx.xxx.xxx,yyy.yyy.yyy.yyy');
// CIDRも使えます。例: define('TRUSTED_PROXY_LIST', '10.0.0.0/8');
// プロキシは X-Forwarded-For にクライアントの値を追記する構成である必要があります。
// 接続元がここに一致しないリクエストでは、ヘッダーを無視して接続元のIPアドレスを使います。
// プロキシのIPアドレスが動的に変わる場合は '*' を指定すると接続元だけを信頼します。
// '*' はサーバーへプロキシ経由以外で到達できる構成では使えません(IPアドレスを偽装されます)。
// IPアドレスの範囲が公開されているCDNでは '*' ではなくその範囲をCIDRで指定してください。
// この設定は X-Forwarded-Proto(HTTPS判定)と X-Forwarded-Server(SERVER_NAME)を信頼するか
// どうかの境界も兼ねます。接続元がここに一致せず、プライベート/ループバック/リンクローカル
// アドレスでもない場合、これらのヘッダーは無視されHTTP扱いになります。
// TLSを終端するCDNやロードバランサーが公開IPからオリジンに接続する構成では、この設定が空の
// ままだと常時SSL有効時にhttpsへの301リダイレクトが無限ループします。301はブラウザにキャッシュ
// されるため、設定を直した後もキャッシュの削除が必要です。
define('TRUSTED_PROXY_LIST', '192.0.2.10,198.51.100.20');PROXY_IP_HEADER のデフォルト値は HTTP_X_FORWARDED_FOR です。CDN が実 IP を渡すヘッダー名に合わせて変更してください。
プロキシが RFC 7239 の Forwarded ヘッダーしか送出できない構成の場合、PROXY_IP_HEADER に HTTP_FORWARDED を指定できます。for= パラメータからクライアントIPアドレスを読み取ります(proto=・host= も同時に読み取られ、次項のHTTPS判定・SERVER_NAME判定にも使われます)。
TRUSTED_PROXY_LIST に CDN のオリジン接続元 IP を登録すると、X-Forwarded-For ヘッダーのチェーンから信頼できるプロキシ IP を除外して実クライアント IP を特定します。CDN サービスによっては、オリジンへの接続元 IP を固定・公開している場合があります。その IP を TRUSTED_PROXY_LIST に登録することで、実 IP の特定に加え、CDN を経由しないオリジンへの直接アクセスをサーバー側で制限することも安全に行えます。
ロードバランサーのIPアドレスが動的に変わり事前に列挙できない場合は、*を指定できます。*は「すべてのIPアドレスを信頼する」ではなく「接続してきた相手だけを信頼する」という意味で、CIDRと併記も可能です(例: *,10.0.0.0/8)。* は「サーバーへプロキシ経由以外で到達できない」構成でのみ使用してください。直接到達できる構成で使うと、ヘッダーを1つ付けるだけで任意のIPアドレスを偽装できます。IPアドレス範囲が公開されているCDN(Cloudflare等)では、* ではなくその範囲をCIDRで列挙することを推奨します。
2. キャッシュ制御(情報漏えい防止)
管理画面・ログイン中の会員ページ・プレビュー・フォーム送信などをキャッシュしてしまうと、会員向けコンテンツや個人情報が別のユーザーに配信される危険があります。
ログイン判定用 Cookie の活用
a-blog cms には、ログイン中のユーザーにのみ発行される専用 Cookie が用意されています(CDN でのキャッシュ出し分けを想定した機能です)。
/private/config.system.yaml で有効化します。
extra_logged_in_cookie: on
extra_logged_in_cookie_name: acms-logged-in # 任意で変更可能この Cookie の有無を条件にキャッシュをバイパスするよう CDN 側を設定してください。
セッション Cookie(config.server.php の SESSION_NAME で変更可能)は未ログインの訪問者にも付与される場合があるため、これをキャッシュバイパス条件にすると公開ページもキャッシュされなくなり、CDN の効果が薄れます。ログイン判定には上記の専用 Cookie を使用してください。
POST リクエストのバイパス
フォーム送信などの POST リクエストは必ずキャッシュをバイパスする設定にしてください。
3. HTTPS・プロトコル判定(CDN でSSL を終端する場合)
CDN のエッジで SSL を終端し、オリジン(a-blog cms)へ HTTP で接続する構成では、a-blog cms が正しく HTTPS と判定できるよう対応が必要です。
a-blog cms は以下の順序でプロトコルを判定します。
1. $_SERVER['HTTPS'] が存在する
2. $_SERVER['SERVER_PORT'] が 443 である
3. $_SERVER['HTTP_X_FORWARDED_PROTO'] が https である
X-Forwarded-Proto・X-Forwarded-Server を信頼するかどうかは、上記の TRUSTED_PROXY_LIST と同じ設定で制御されます。接続元IPアドレスが TRUSTED_PROXY_LIST に一致する場合のみ、これらのヘッダーが信頼され、HTTPS判定・SERVER_NAME(ホスト名)の解決に使われます。一致しない場合はヘッダーが無視されHTTP扱い・接続元のホスト名扱いになります。
そのため、CDN・ロードバランサーでSSLを終端する構成では、接続元IPアドレスの取得設定(前項の TRUSTED_PROXY_LIST)を行わないと、HTTPS判定も正しく機能しません。Secure Cookieなど「HTTPS接続であること」を前提にした機能を使う場合は、前項の設定を先に済ませてください。
CDN 側で X-Forwarded-Proto: https ヘッダーをオリジンへ転送するよう設定することで、a-blog cms が HTTPS として動作します。この設定が漏れると、管理画面やログインページで HTTP へリダイレクトされるなどの問題が発生することがあります。
4. キャッシュのパージ運用
コンテンツを公開・更新したときに、CDN に古いキャッシュが残ったままにならないよう、パージ(キャッシュ消去)の運用を設計してください。
5. WAF によるリクエストブロック
CDN の WAF(Web Application Firewall)を有効にしている場合、a-blog cms の正常な操作がブロックされることがあります。
以下はブロックされやすい操作の例です。
管理画面での HTML を含むコンテンツ編集
ファイル・画像のアップロード
リッチエディタやブロックエディタからの POST
フォーム送信
対処としては、管理画面の URL パス(例: /bid/admin/ など)を WAF ルールの除外対象に設定することが一般的です。WAF のルールチューニングは CDN サービス側での対応となります。
設定項目の一覧
設定ファイル | 項目 | デフォルト値 |
|---|---|---|
config.server.php | PROXY_IP_HEADER | HTTP_X_FORWARDED_FOR |
config.server.php | TRUSTED_PROXY_LIST | (空) |
private/config.system.yaml | extra_logged_in_cookie | off |
private/config.system.yaml | extra_logged_in_cookie_name | acms-logged-in |