Apache の環境変数

Apache HTTP サーバは環境変数と呼ばれる、名前のついた 変数に情報を記憶する仕組みを提供しています。この情報はログ収集や アクセス制御などのいろいろな操作を制御するために使うことができます。 これらの変数は CGI スクリプトなどの外部プログラムと通信するためにも 使われます。この文書はそれらの変数の操作方法と使用方法をいくつか 紹介します。

これらの変数は環境変数と呼ばれていますが、オペレーティング システムによって制御されている環境変数と同じではありません。 実際は、これらの変数は Apache の内部構造の中に記憶され、操作されています。 それらは、CGI や SSI スクリプトに渡されたときだけ、実際の オペレーティングシステムの環境変数になります。サーバ自身が 実行されているオペレーティングシステムの環境を操作したい場合は、 オペレーティングシステムのシェルが提供している標準の環境変数の 操作方法を使わなければなりません。

環境変数の設定 mod_env mod_rewrite mod_setenvif mod_unique_id BrowserMatch BrowserMatchNoCase PassEnv RewriteRule SetEnv SetEnvIf SetEnvIfNoCase UnsetEnv
基本的な環境の操作

Apache において環境変数を設定する一番基本的な方法は、 無条件に環境変数を設定する SetEnv ディレクティブを使用することです。 PassEnv ディレクティブにより、Apache が起動されたシェルの 環境変数を渡すこともできます。

リクエスト毎に条件に基づいて設定する

より柔軟性を高めるために、mod_setenvif で提供されているディレクティブを使用することで、リクエストの 特性に基づいて環境変数を設定することができます。例えば、特定のブラウザ (User-Agent) のリクエストや特定の Referer [意図的な綴りです] 正しい綴りは referrer ですが、HTTP の仕様では Referer となっていますヘッダが見つかったときのみ変数を設定することができます。 mod_rewrite の RewriteRule ディレクティブにおいて環境変数を設定する [E=...] オプションを使用することで、 より柔軟な設定を行なうことができます。

一意な識別子

mod_unique_id は、非常に限られた条件の下で 「すべて」のリクエストについて、一意であることが保証されている値を環境変数 UNIQUE_ID に設定します。

標準 CGI 変数

Apache の設定ファイルで設定された環境変数とシェルから渡される 環境変数に加えて、CGI スクリプトと SSI ページには CGI の仕様で要求されている、 リクエストのメタ情報を持った環境変数の組が提供されます。

いくつかの注意
  • 環境を操作するディレクティブを使って標準 CGI 変数を上書きしたり変更したりすることはできません。
  • CGI スクリプトを起動するために suexec が使用されている場合、CGI スクリプトが起動するために、環境変数は安全な環境変数の組に整理されます。 この安全な環境変数の集合は、コンパイル時に suexec.c で定義されます。
  • 移植性のために、環境変数の名前はアルファベット、 数字とアンダースコア '_' だけから成ります。 さらに、最初の文字は数字であってはいけません。 この制限に合わない文字は CGI スクリプトと SSI ページに渡されるときにアンダースコアに置換されます。
  • SetEnv はリクエスト処理の 段階の中でも遅くに実行されます。つまり SetEnvIfRewriteCond などからは、変数がそこで設定されていることがわかりません。
環境変数の使用 mod_authz_host mod_cgi mod_ext_filter mod_headers mod_include mod_log_config mod_rewrite Allow CustomLog Deny ExtFilterDefine Header LogFormat RewriteCond RewriteRule
CGI スクリプト

環境変数の主な利用法の一つは、CGI スクリプトに情報を伝えることです。 上で説明されているように、CGI スクリプトに渡される環境変数は Apache の設定により設定される変数に加えて、リクエストの標準のメタ情報を含んでいます。 詳細は CGI チュートリアル を参照してください。

SSI ページ

mod_include の INCLUDES フィルタで処理される server-parsed (SSI) ドキュメントでは、echo 要素を使用すると環境変数が出力されます。 また、ページのある部分がリクエストの性質に応じて変更されるように、 環境変数をフロー制御要素で使うことができます。詳細は SSI チュートリアル を参照してください。

アクセス制御

allow from env= ディレクティブと deny from env= ディレクティブを使用して、サーバへのアクセスを環境変数の値で制御することができます。 SetEnvIf ディレクティブと組み合わせることで、クライアントの特性に基づいて サーバへのアクセス制御を柔軟に行なうことができるようになります。 たとえば、これらのディレクティブを使用して、特定のブラウザ (User-Agent) からのアクセスを拒否することができます。

条件付きログ記録

LogFormat ディレクティブのオプション %e を使用することで、環境変数をアクセスログに記録することができます。さらに、 CustomLog ディレクティブの条件分岐式を使用することで、 環境変数の値によってリクエストをログに記録するかどうかを決めることができます。 SetEnvIf ディレクティブと組み合わせることで、 どのリクエストをログに記録するかを柔軟に制御することが可能になります。たとえば、 gif で終わるファイル名へのリクエストはログに記録しない、 違うサブネットのクライアントからのリクエストだけをログに記録する、 という選択が可能です。

条件付き応答ヘッダ

Header ディレクティブは環境変数の存在や不在によってクライアントへの応答に特定の HTTP ヘッダを付けるかどうかを決めることができます。 これにより、たとえば、クライアントからのリクエスト にあるヘッダがある場合にのみ特定の応答ヘッダを送る、というようなことが できます。

外部フィルタの適用

ExtFilterDefine ディレクティブを使用して mod_ext_filter で設定される外部フィルタは、 disableenv=enableenv= オプションを使って、環境変数による条件付き適用ができます。

URL の書き換え

RewriteCond ディレクティブで評価文字列として %{ENV:...} 式を指定することで、mod_rewrite の書き換えエンジンが環境変数に基いて条件分岐を行なうことができます。 mod_rewrite が使用可能な変数で ENV: が前についていない変数は、 実際は環境変数ではないということに注意してください。 それらは他のモジュールからは使用できない mod_rewrite 用の特別な変数です。

特別な目的の環境変数

互換性の問題を解決するために、特定のクライアントと通信しているときは Apache の動作を変更できる機構が導入されました。できるだけ柔軟にするために、 これらの機構は環境変数を定義することで呼び出されます。普通は、 BrowserMatch ディレクティブを使いますが、たとえば SetEnv ディレクティブや PassEnv ディレクティブも使用することができます。

downgrade-1.0

これを指定することで、リクエストが HTTP/1.0 より新しいプロトコルの場合でも、HTTP/1.0 として扱われます。

force-gzip

DEFLATE フィルタが使用するように設定されているときに、 この環境変数はブラウザの accept-encoding の設定を無視して常に 圧縮された出力を送るようにします。

force-no-vary

応答ヘッダがクライアントに送られる前に Vary フィールドを取り除きます。 クライアントの中にはこのフィールドを正しく解釈しないものがあります。 この変数を設定することでその問題を回避することができます。 この変数を設定すると、force-response-1.0 が設定されたことになります。

force-response-1.0

これが設定されていると、HTTP/1.0 リクエストを発行するクライアントに対しては 常に HTTP/1.0 で応答するようになります。この機能は、 元々は AOL のプロキシの問題のために実装されました。HTTP/1.0 クライアントの中には、 HTTP/1.1 の応答を返されると正しく動作しないものがあるかもしれません。 この機能を使用することで、そのようなクライアントとの間の互換性問題を解決できます。

gzip-only-text/html

これが 1 に設定されると、この変数は text/html 以外のコンテントタイプに対する、mod_deflate 提供の DEFLATE 出力フィルタを無効にします。 また、静的に、既に圧縮されたファイルを使用したい場合、 (gzip だけでなく、"identity" と異なる全てのエンコードに対して) mod_negotiation も変数を評価します。

no-gzip

セットされると、mod_deflateDEFLATE フィルタがオフになります。 そして mod_negotiation はエンコードされたリソースを送らないようにします。

nokeepalive

これが設定されている場合は、KeepAlive を使用しないようにします。

prefer-language

mod_negotiation の挙動に影響を与えます。 (en, ja, x-klingonといった) 言語タグが格納されていれば、その言語の variant を送信しようとします。 そのような variant がない場合は、 通常のネゴシエーション処理が 適用されます。

redirect-carefully

これはクライアントへのリダイレクトの送信をサーバがより注意深く 行なうようにします。 これは通常、リダイレクトに際してクライアントに 問題があることが分かっている場合に使われます。この機能は元々は マイクロソフトのウェブフォルダのソフトが DAV メソッドによるディレクトリのリソースへのリダイレクトの扱いに 問題がり、それを回避するために実装されました。

suppress-error-charset

Apache 2.2 以降で利用可能

クライアントのリクエストに対する応答としてリダイレクトを送信する際、 レスポンスにはリダイレクトが自動的に行なえない (行なわれない) 場合に表示するテキストが含まれます。 通常、このテキストに合致したキャラクタセット、ISO-8859-1 でラベル付けをします。

しかし、リダイレクト先が別の文字セットを使っている場合、 ある問題のあるブラウザのバージョンでは、 リダイレクト先の実際の文字セットの代わりに、 リダイレクト元の文字セットを使ってしまうことがあります。 その結果、例えば変な描画が行なわれたりして、読めなくなったりします。

この環境変数を設定することで、リダイレクションテキストに対する キャラクタセットの指定を除去しますので、それら問題のあるブラウザでも リダイレクト先の文字セットを正しく使うようにできます。

セキュリティ

文字セットを指定せずにエラーページを送信すると、 クロスサイトスクリプティング XSS 攻撃の危険性がでてきます。 HTTP/1.1 仕様に準拠していなくて、コンテンツの中身から文字セットを "推測" しようとするブラウザ (MSIE) が実際にあるからです。 そのようなブラウザは UTF-7 文字セットを使って簡単に騙すことができます。 クロスサイトスクリプティング攻撃を防ぐために実装されている 通常のエスケープ機構が、入力データ中にある UTF-7 で エンコードされたコンテンツ (リクエスト URI など) には うまく動作しないからです。

force-proxy-request-1.0, proxy-nokeepalive, proxy-sendchunked, proxy-sendcl

これらの指示子は mod_proxy の挙動を変更します。 詳細は mod_proxy のドキュメントをご参照ください。

おかしな挙動をするクライアントに対してプロトコルの動作を変更する

クライアントに関する既知の問題に対処するために、以下の行を httpd.conf に入れることを推奨しています。

古いバージョンの Apache では、クライアントの問題に対応するために httpd.conf に次の行を加えるよう推奨されていましたが、 今となっては、問題としていたクライアントは実際には見かけることは なくなってきたので、この設定はもはや必要ないかもしれません。

#
# The following directives modify normal HTTP response behavior.
# The first directive disables keepalive for Netscape 2.x and browsers that
# spoof it. There are known problems with these browser implementations.
# The second directive is for Microsoft Internet Explorer 4.0b2
# which has a broken HTTP/1.1 implementation and does not properly
# support keepalive when it is used on 301 or 302 (redirect) responses.
#
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0

#
# The following directive disables HTTP/1.1 responses to browsers which
# are in violation of the HTTP/1.0 spec by not being able to grok a
# basic 1.1 response.
#
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0
画像へのリクエストをアクセスログに記録しない

この例では、画像へのリクエストがアクセスログに現れないようにします。 これを変更することで、特定のディレクトリのログ収集をやめたり、 特定のホストからのリクエストのログ収集をやめたりすることが簡単にできます。

SetEnvIf Request_URI \.gif image-request
SetEnvIf Request_URI \.jpg image-request
SetEnvIf Request_URI \.png image-request
CustomLog logs/access_log common env=!image-request
「画像の盗用」を防ぐ

この例は、別のサーバにいる人が、あなたのサーバにある画像を inline 画像として使用することを防ぎます。 これは推奨されている設定ではありませんが、ある限定された状況では有効です。 ここでは、すべての画像は /web/images というディレクトリにあると仮定します。

SetEnvIf Referer "^http://www\.example\.com/" local_referal
# Allow browsers that do not send Referer info
SetEnvIf Referer "^$" local_referal
<Directory /web/images>
   Order Deny,Allow
   Deny from all
   Allow from env=local_referal
</Directory>

この手法に関する詳しい情報は ServerWatch にあるチュートリアル 「Keeping Your Images from Adorning Other Sites 」を参照してください。