Apache のコンテンツフィルタリング

公開日:
更新日:
0.htaccess

コンテンツフィルタリングとは

Apache にはモジュールの入出力データに変更を加えることができる、"フィルタリングモジュール" が用意されています。フィルタリングモジュールには、Apache 2.0 から実装された "シンプルフィルタ" と Apache 2.2 から実装された "スマートフィルタ" の 2 種類があります。


以降は Apache 2.2 の説明になります。Apache 2.4 以降では、後述するスマートフィルタの FilterProvider ディレクティブの指定方法が変更になっているため注意して下さい。

シンプルフィルタとは

Apache は、"リクエストを処理する""入力 (受信) データを処理する""出力 (送信) データを処理する" の 3 つの内部プロセスを持ち、どのプロセスでモジュールを動作させるか指定できます。シンプルフィルタは、出力 (送信) データを処理するプロセスでコンテンツを加工することができます。Apache 2.0 で実装されたフィルタリングモジュールとしては、以下のものがあります。

  • mod_include : SSI (Server Side Include) を可能にする。
  • mod_ssl : SSL 暗号化通信を可能にする。
  • mod_deflate : コンテンツをクライアントに送信する前に圧縮することを可能にする。
  • mod_ext_filter : 外部プログラムをフィルタとして指定することを可能にする。
シンプルフィルタの概念図
シンプルフィルタの概念図

スマートフィルタとは

Apache 2.1 以降では、フィルタ機能が強化され、条件が指定可能なスマートフィルタが実装されました。シンプルフィルタでは、フィルタリングを実施するかは各モジュールが判断します。そのため、処理が不要なコンテンツに対してもモジュールにデータを渡しています。しかし、スマートフィルタでは、モジュールにデータを渡す条件を指定できるため、効率的で高度なフィルタリングが可能になりました。モジュールにデータを渡すかは "mod_filter" が制御しています。条件には、"HTTP リクエストの各ヘッダ"、"HTTP レスポンスの各ヘッダ"、"環境変数" などが利用できます。


スマートフィルタの概念図
スマートフィルタの概念図

フィルタの使い分けと対応ディレクティブ

シンプルフィルタとスマートフィルタは互換性がありません。組み合わせて使うことは可能ですが、不具合が発生したり、期待する動作をしない場合があります。どちらか一方のみを使用することを推奨します。


シンプルフィルタの関連するディレクティブは、以下の通りです。

  • AddInputFilter (mod_mime)
  • AddOutputFilter (mod_mime)
  • RemoveInputFilter (mod_mime)
  • RemoveOutputFilter (mod_mime)
  • SetInputFilter (Core)
  • SetOutputFilter (Core)

スマートフィルタの関連するディレクティブは、 以下の通りです。

  • FilterChain (mod_filter)
  • FilterDeclare (mod_filter)
  • FilterProtocol (mod_filter)
  • FilterProvider (mod_filter)

それぞれのディレクティブの詳細は、.htaccessの書き方を参照して下さい。また、それぞれのフィルタの説明は、mod_deflate を例に次章で説明します。

モジュールが組み込まれているかの確認方法

フィルタの利用例として取り上げている mod_deflate を使用する場合、"deflate_module" が組み込まれている必要があります。また、スマートフィルタは "mod_filter" (filter_module) で実装されているため、実際の処理を行うフィルタに加えて、mod_filter が組み込まれている必要があります。Apache にモジュールが組み込まれているか確認するためには httpd コマンドを使用するのが一般的です。ただし、レンタルサーバーなどを利用しているユーザは、httpd コマンドを使用できない場合があります。


# httpd コマンドで filter_module モジュールを確認する例 (他のモジュールは省略)
[root@ ~]# /etc/init.d/httpd -M
deflate_module (shared)
filter_module (shared)

[root@ ~]# 
 httpd コマンドで filter_module モジュールを確認する例

組み込まれていない場合でも "mod_deflate.so" や "mod_filter.so" が所定のディレクトリにあれば、httpd.conf に以下の設定を追加するだけで動きます。OS によっては指定するパスが異なるため、注意して下さい。


# 動的読み込みにより mod_filter を読み込む例
LoadModule deflate_module /usr/lib/httpd/modules/mod_deflate.so
LoadModule filter_module /usr/lib/httpd/modules/mod_filter.so
 動的読み込みにより mod_filter を読み込む例

バイナリパッケージで Apache をインストールした場合、モジュールの格納先は以下のパスになります。


Fedora, Red Hat, Cent OS : /usr/lib/httpd/modules/
openSUSE                 : /usr/lib/apache2/
Debian, Ubuntu           : /usr/lib/apache2/modules/

シンプルフィルタの使い方

シンプルフィルタで mod_deflate を設定する例を以下に示します。SetOutputFilter ディレクティブと、DEFLATE フィルタを使用することで、クライアントに出力 (送信) するコンテンツを圧縮しています。


# シンプルフィルタの実装例
SetOutputFilter DEFLATE
 シンプルフィルタの実装例

上記の例では、すべてのコンテンツが圧縮されるため、<FilesMatch> ディレクティブなどでテキストファイル (HTML, CSS, Javascript など) を指定するのが一般的です。圧縮済みのコンテンツ (画像、音楽、動画、PDFなど) を更に圧縮すると、逆にファイルサイズが増える場合もあり、圧縮に時間もかかるためサーバリソースの無駄遣いになります。また httpd.conf の編集権限のあるユーザは、圧縮レベルの設定 (DeflateCompressLevel ディレクティブ) や、圧縮対象のディレクトリ指定 (<Location> ディレクティブ) などの設定が可能です。


DEFLATE フィルタが有効になっているか確認するためには、レスポンスヘッダの "Content-Encoding" を確認します。Content-Encoding が "gzip" となっていれば圧縮されています。例えば、コンソール上から cURL コマンドで確認する例は以下の通りです。


# DEFLATE フィルタの確認例
% curl -I https://murashun.jp

HTTP/1.1 200 OK
Content-Encoding: gzip
・・・ (中略) ・・・
 DEFLATE フィルタの確認例

スマートフィルタの使い方

スマートフィルタはまず "FilterDeclare" ディレクティブでフィルタ名を定義します。次に "FilterProvider" ディレクティブでフィルタの動作する条件を指定します。最後に "FilterChain" ディレクティブで定義したフィルタを有効にします。


# フィルタ名 "Compress" を定義
FilterDeclare Compress CONTENT_SET

# フィルタの動作する条件を指定
FilterProvider Compress DEFLATE resp=Content-Type $text/html
FilterProvider Compress DEFLATE resp=Content-Type $text/css

# "Compress" フィルタを有効にする
FilterChain Compress
 スマートフィルタの設定例

FilterDeclare ディレクティブで定義したフィルタ名は、FilterProviderディレクティブと、FilterChainディレクティブで指定できます。フィルタ名の後続に続く文字列には、"RESOURCE""CONTENT_SET""PROTOCOL""TRANSCODE""CONNECTION""NETWORK" のいずれかを指定します。指定しない場合は、"RESOURCE" がデフォルト値となります。


FilterProvider ディレクトリは、FilterDeclare ディレクティブで定義したフィルタを登録します。登録したフィルタは、条件の文字列と一致したときに呼ばれます。条件は、req= (リクエスト) 、resp= (レスポンス) 、env= (環境変数) を意味するプレフィックスを設定できます。プレフィックスを省略した場合は、デフォルトでレスポンスとなります。また、条件に一致するパターンとして、完全一致、部分一致、正規表現、整数、無条件一致のいずれかを設定できます。


FilterChain ディレクトリは、FilterProvider ディレクトリ登録したフィルタを有効にします。また、単純に登録するだけではなく先頭に登録したり、末尾に登録したり、フィルタを削除することもできます。フィルタの登録や削除を表すプレフィックスとして +=-@! を付けることができます。


各ディレクティブの詳細は、.htaccessの書き方を参照して下さい。

まとめ

コンテンツフィルタリングを使用することで、コンテンツをサーバサイドで柔軟に処理することができます。ただし、フィルタの使用に関しては少し難しいところがあるため、多用することは推奨しません。また、独自のフィルタシステムを組むこともできますが、実績のあるレシピを流用した方が無難です。組み上げたコンテンツフィルタは、十分な動作確認を行って下さい。