[Apache] .git, .gitignore等をWebからアクセスできないようにする

gitで管理しているwebサイトでうっかり.gitや.gitignoreなどの Git 関連ファイルが漏れてしまわないようにするには、httpd.conf で以下のように設定します。

# .git から始まるファイルへのアクセスを禁止
<Files ~ "^\.git">
Order allow,deny
Deny from all
Satisfy All
</Files>
# .git/ フォルダ以下のファイル・ディレクトリへのアクセスを禁止
<Directorymatch "^/.*/\.git/">
Order deny,allow
Deny from all
</Directorymatch>

.git は外してアップしているよ、という方も、保険として入れておくと万一の時に .git や .gitignore などが
公開ディレクトリに混ざってしまってもアクセスできないようになるので安全ですね。

RewriteEngine のURL書き換えを親ディレクトリ優先にする

他の.htaccessオプション同様、複数の .htaccess で mod_rewrite でURL書き換えを行うとサブディレクトリ優先になります。
メンテナンス状態にしたい時など、ドキュメントルートの.htaccessを差し替えるだけでサイト内の全てのコンテンツを不可視にしたい場合はこれでは困るので、調べてみたところ、RewriteOptions という設定がありました。
 
サブディレクトリでURL書き換えを行う .htaccess に以下のように
RewriteOptions inherit を追加すると、親ディレクトリ優先になりました。

RewriteEngine on
RewriteOptions inherit
RewriteRule .* http://www.ecoop.net/ [L]

 
RewriteOptions のマニュアルを日本語訳してみたので、ご参考下さい。

The RewriteOptions directive sets some special options for the current per-server or per-directory configuration. The Option string can currently only be one of the following:

inherit
This forces the current configuration to inherit the configuration of the parent. In per-virtual-server context, this means that the maps, conditions and rules of the main server are inherited. In per-directory context this means that conditions and rules of the parent directory’s .htaccess configuration are inherited.

Rules inherited from the parent scope are applied after rules specified in the child scope.

 (訳:
RewriteOptions ディレクティブは、記述箇所によって個別のサーバやディレクトリごとの設定を行うための特別なオプションです。オプション文字列は今のところ下記のひとつしかありません。
 
inherit
このオプションは現在の設定について強制的に親の設定を受け継ぐようにします。バーチャルサーバごとのコンテキストなら、これはメインサーバーのマッピングや条件、ルールを継承するという意味になります。ディレクトリごとのコンテキストなら親ディレクトリの条件やルールを継承します。
 
親のスコープから継承したルールは子のスコープで指定したルールの後に適用されます。
)

 
参考:
mod_rewrite
URLを書き換えろ!Apache Rewrite 機能の応用

httpd でリクエストにかかった時間をログ出力する

Apache モジュール mod_log_config

カスタムログ書式(抜粋):
%D リクエストを処理するのにかかった時間、マイクロ秒単位
%X 応答が完了したときの接続ステータス:
        X = 応答が完了する前に接続が異常終了
        + = 応答が送られた後に接続を持続することが可能
        – = 応答が送られた後に接続が切られる

自前でプロセスの所要時間を計算してログ出力したりしていました。
httpd 1.3 から 秒単位出力(%T オプション)は存在したのですね…。
灯台下暗しとはまさにこのこと。

.htaccess で PHP の表示言語を切り替える

php_value, php_flag を使って自動文字コード変換をする tips です。
  
.htaccess:

# ソースの文字コード(SJIS, EUC-JP, UTF-8 など mb_convert_encoding()で指定する書式)
php_value mbstring.internal_encoding UTF-8
# ヘッダで表明する出力文字コード(Shift_JIS, EUC-JP, UTF-8 など Content-Type で指定する書式)
php_value default_charset Shift_JIS
# 変換に使う出力文字コード(mb_convert_encoding()で指定する書式)
php_value mbstring.http_output SJIS
# 変換文字コードが属する言語
php_value mbstring.language Japanese
# フォームなどの入力文字コードは自動判別させる
php_value mbstring.http_input auto
# 入力の自動変換を有効化(Off で無効化)
php_flag mbstring.encoding_translation On
# 出力の自動変換を有効化(空値で無効化)
php_value output_handler mb_output_handler

なお、動作には

1.CGI モードではなく PHP-CLIモードで動いていること
2. httpd.conf で AllowOverride Options または AllowOverride All など Options の変更ができるように設定されていること。

が必要です。


ちなみに余談ですが、同じことを .htaccess なしでやろうとした場合は次のようになります。

<?php
// 自動変換処理
mb_language(“Japanese”);
// ソース文字コード
mb_internal_encoding(“UTF-8”);
// 出力文字コード
mb_http_output(“SJIS”);
header(“Content-Type:text/html;charset=Shift_JIS”);
 
// mb_output_handler で出力をフィルタリング
ob_start(“mb_output_handler”);
register_shutdown_function(‘ob_end_flush’);
 
// 入力をフィルタリング
// (mb_convert_encoding($value, mb_internal_encoding(), “auto, UTF-8”);
// を使い、 $_REQUEST, $_GET, $_POST, $_COOKIE など入力変数を変換すればエミュレートできるが
// 長くなるので省略)
 
// —————————–
// あとは普通の処理
 
echo “はろーわーるど\n”;

参考:
AllowOverride ディレクティブ(Apache 2.2 リファレンス)
PHP 出力制御関数(php.net)

AllowOverride が効かない

<Directory ~ “^/path/to/(htdocs|secure)/”>
AllowOverride All
</Directory>

こういう設定で、 AllowOverride All してるのに .htaccess が無視されていておかしいなと首を傾げていたところ、マニュアルを見て納得。

AllowOverride ディレクティブ:
(中略)
<Directory> セクションでのみ使用可能
AllowOverride は正規表現無しの<Directory> セクションでのみ有効で、<Location> や <DirectoryMatch> や <Files> セクションでは無効です。

なーるほど…。
ただ複数書くのが面倒、っていう理由で正規表現形式にしていたので、<Directory> を複数に分けて解決。

ブラウザの通信の切断は CGI の処理中断につながるか?

HTTP でサーバサイドプログラムの実行中に通信が切断された場合、
サーバサイドのプログラムがどうなるか?という疑問から
PHP 4.4.X + Apache 2.0.X でちょっと実験してみました。

exp_timeout.php:
<?php
set_time_limit (0); // PHP の処理時間制限を無しに。
 
display(‘begin’);
for($i = 1; $i <= 100; $i++){ // 100 秒間処理をする。
  sleep(1);
display(($i*1).’%’);
}
 
display(‘end’);
 
// 表示&記録。
function display($mes){
   $line = date(‘Y-m-d H:i:s’).”: “.$mes.”<br>\n”;
   echo $line; // (*1)
   system(‘echo ‘.escapeshellarg($line).’>> result.html’);
   //flush(); ob_flush(); // (*2)
}
?>

この PHP スクリプトに Apache 経由でアクセスし、
レスポンスが返ってくるまでに HTTP クライアントのリクエストを中断させてみます。中断しても、result.html に結果が書かれるため、result.html にアクセスすることで処理がどこまで進んだか確認できます。
この検証を、(*1)、(*2)のコメントアウト, アンコメントアウトして行ってみました。
 
なお、PHP の設定についてはデフォルトで出力をバッファするものとします。
 
結果(コメントアウト状態を「なし」、コメントアウトを外した状態を「あり」と表記します):
– (*1)あり (*2)なし: 常に 100% まで完了。
– (*1)あり (*2)あり: 切断して数回出力した後に処理が中断。
– (*1)なし (*2)あり: 常に 100% まで完了。
– (*1)なし (*2)なし: 常に 100% まで完了。
 
 
考察:
HTTP 通信が切断された場合、HTTPレスポンス送信に規定回数失敗した時点で切断されたと認識され、スクリプトの処理が中断されるようです。
(*2), (*1)いずれかをコメントアウトした場合、処理完了まで一切出力を行わず、通信の切断を検知しないため、通常通り最後まで実行すると考えられます。
 
注:
この実験は、Apache 2.0 に限定したもので、仕様も一切あたらず行ったため、これ以外の HTTP サーバの場合に必ずしも同じ結果になるとは限りません。
 
捕捉:
処理時間を600秒など極端に長い時間にしてもタイムアウトすることなく動作を続けました。

.htaccess で php.ini の設定を上書きする

php_value (mod_php が提供するディレクティブ) を使う事で、 .htaccess で php.ini での設定を上書きすることが可能です。
これにより、Web サービス単位で php.ini でできる設定を使い分けるということが可能になります。

php_value output_handler mb_output_handler
php_value mbstring.language Japanese
php_value mbstring.internal_encoding SJIS
php_value mbstring.http_input auto
php_value mbstring.http_output SJIS
php_flag mbstring.encoding_translation On

ただし、mb_output_handler を利用する場合は、php.ini で指定してしまうと、.htaccess での設定を中途半端に反映するため文字化けする可能性があるため、php.ini の output_handler はデフォルト値のままにしておくほうがいいでしょう(この説明について間違っていれば指摘お願いします)。

output_handler =

 
参考:
【 ほでなすPHP 】 PHPのインストール -> 「.htaccess」ファイルでの設定
Re: .htaccessにてphp_value が設定できないパラメータがある(PHP-Users)
設定の際の注意。E_* (E_ALL など)を利用する際は定数ではなく対応する定数の値(2047など)で指定しましょう。

HTTPS でクライアント認証に証明書を使う

電子申請や決済サイトでの管理など、各所で利用されてきているので導入してみました。
以下は自分が承認した証明書のみを受け付ける時の設定手順です。

1. CA 構築のための鍵のペアを生成する
2. Apache の設定で、クライアント証明書が承認を要求して CA を参照するように設定する
2. クライアント用の鍵のペアを生成する
3. クライアント用の鍵から証明書を作成する
4. 証明書を .p12 形式に変換する
5. 4 で作った証明書をクライアントのブラウザにインポートしてもらう

という手順を踏めば見られるようになります。証明書がないと閲覧不可になります。
参考:
SSL 入門
OpenSSL を使った CA の構築

現在のプロセス数、TCP 接続本数を調べる

ad-hoc なコードですが。
パフォーマンスの分析を簡易的にしたい場合(ab 実行対象の状態調査など)に、現在何プロセス、何本のコネクションか調べる、というコード。今回の対象は Linux2.6 + sh + Apache. BSD で動作させるには ps の引数を ax から -ax にするといいです。

apache_monitor.sh:
#!/bin/sh
export _APACHE_BIN=httpd
while true; do
    echo -n `date +’%Y-%m-%d %H:%M:%S’`.;
    _proc=`ps ax | grep ht[t]pd | wc -l`; echo -n .;
    _con=`(netstat -an 2>/dev/null)| sed -e ‘/ESTABLISHED/p’ \
         -ed -e ‘/:80/p’ -ed|wc -l` ;
    echo p:$_proc c:$_con;
    sleep 5;
done

実行結果はこのようになります。

# p がプロセス数, c が接続本数
$ apache_monitor.sh
2006-03-13 04:40:57..p:223 c:2
2006-03-13 04:41:03..p:226 c:40
2006-03-13 04:41:10..p:253 c:103
2006-03-13 04:41:17..p:397 c:128
2006-03-13 04:41:25..p:398 c:138
2006-03-13 04:41:34..p:398 c:207

sleep タイミングで Ctrl-C を押せば終了します。

Apache パフォーマンスチューニング

パフォーマンスのために必要なモジュールを削る、とか、DSO をやめる、というのは各所で書かれていますが、あんまり例がなかったので書いておきます。

/configure –prefix=/usr/local/apache \
    –disable-module=all \
    –enable-module=access \
    –enable-module=log_config \
    –enable-module=dir \
    –enable-module=mime \
    –enable-module=auth \
    –enable-module=status

もう一件、Apach 1.x における MaxClients の限界ですが、

src/include/httpd.h:
#ifndef HARD_SERVER_LIMIT
#ifdef WIN32
#define HARD_SERVER_LIMIT 1024
#elif defined(NETWARE)
#define HARD_SERVER_LIMIT 2048
#else
#define HARD_SERVER_LIMIT 256
#endif
#endif

という部分で、HARD_SERVER_LIMIT が MaxClients に設定する値以上になるように編集してやればいいです。
参考:
Apacheパフォーマンス・チューニングの実践(@IT)
ステップバイステップでApacheをセキュアに(愛の死体安置所)
セキュリティの話ですが、必要なモジュールを削る際に参考になります。
Apache1.3.33+PHP4.3.10 (cubic9.com)
外部モジュール(サイトにあるのは PHP4)を静的に組み込む例。
configure –help にある、

 –add-module=FILE on-the-fly copy & activate a 3rd-party Module
–activate-module=FILE on-the-fly activate existing 3rd-party Module

という設定ですね。

 –activate-module=src/modules/php4/libphp4.a

みたく、リンクライブラリを指定するとそれを一緒にビルドしてくれます。
追記 (2006-02-22):
PHP4 + Apache1.3 チューニング
Apache設定ファイルをチューニング