Apache の rotatelogs コマンドを使ってみる

いつも Apache のログは logrotate でローテーションさせてるんですが PostgreSQL のように単体?でできないかなと思っていたら ちゃんとそういうコマンドがあるようです。

[参考]
Apache のログ管理 | バシャログ。

さっそく設定してみます。 Ubuntu10.04 では rotatelogs は /usr/sbin に入っていました。

$ which rotatelogs
/usr/sbin/rotatelogs

自分でコンパイルした場合は prefix の指定配下の bin に入ります。 私は Apache2.4.2 を /usr/local/apache242 に入れたので rotatelogs は /usr/local/apache242/bin になります。

$ vi /usr/local/apache242/conf/httpd.conf

CustomLog の設定を参考サイトに合わせて変更します。

【変更前】
CustomLog "logs/access_log" common

 ↓

【変更後】
CustomLog "|/usr/local/apache242/bin/rotatelogs logs/access_log.%Y%m%d 86400 540" common

Apache を再起動。

$ sudo /usr/local/apache242/bin/apachectl restart

アクセスするとログが出力されます。

$ ls -1 /usr/local/apache242/logs
access_log
access_log.20120428
error_log
httpd.pid

これで Apache だけでログのローテーションが設定できるようになりました。

Apache2.4 の新機能 mod_sed を試してみる

Apache2.4.2 が出たので、インストールついでに mod_sed を試してみたいと思います。

ダウンロードしたソースをコンパイルするわけですが APR を入れていないと configure でエラーになります。

$ ./configure --prefix=/usr/local/apache242
checking for chosen layout... Apache
checking for working mkdir -p... yes
checking for grep that handles long lines and -e... /bin/grep
checking for egrep... /bin/grep -E
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu

Configuring Apache Portable Runtime library ...

checking for APR... no
configure: error: APR not found.  Please read the documentation.

下記のページを参考に apr を入れてコンパイルします。

[参考]
Apache 2.4 で mod_lua を使ってみる

/usr/local/apache242 に入れます。

$ ./configure --prefix=/usr/local/apache242 \
  --with-apr=/usr/local/apr-httpd/ \
  --with-apr-util=/usr/local/apr-util-httpd/
$ make
$ sudo make install

最後に mod_sed のモジュールを有効にします。

$ vi /usr/local/apache242/conf/httpd.conf

コメントを外します。

#LoadModule sed_module modules/mod_sed.so

これでインストールは終了です。

次に実際の動作のための mod_sed の設定をします。 mod_sed は、入力と出力の内容に対して sed コマンドを使うように置換することができます。

入力と出力は使うディレクティブが違うだけなので 簡単に試せる出力で使ってみます。

次のように設定します。 AddOutputFilter で、拡張子 html に対して Sed フィルタを指定しています。

<IfModule sed_module>
    <Directory "/usr/local/apache242/htdocs/sed">
        AddOutputFilter Sed html
        OutputSed "s/monday/MON/g"
        OutputSed "s/sunday/SUN/g"
    </Directory>
</IfModule>

/usr/local/apache242/htdocs/sed にある .html のファイルは "monday","sunday" を出力すると "MON","SUN" に置換されます。

試してみます。次のファイルを用意。

$ cat /usr/local/apache242/htdocs/sed/test.html

<body>
sunday monday tuesday wednesday thursday friday saturday
</body>

アクセスします。

$ wget -q --no-proxy -O - http://localhost/sed/test.html

<body>
SUN MON tuesday wednesday thursday friday saturday
</body>

sunday monday が SUN MON に変わりました。

lua に触れてみる

[参考]
Apache HTTP Server 2.4.1 がリリースされました - Apache JP (2012/02/21)

ということなのですが、内容に「スクリプト言語 Lua を組み込むモジュール (mod_lua)」というのがあり、 巷で話題?の lua に触れてみました。

まずインストール。
Ubuntu 10.04 には lua50 というパッケージがあります。

$ sudo apt-get install lua50

これで lua 5.0.x が入ります。

コマンドは次のような感じです。

$ lua
lua     lua50   luac    luac50 

lua コマンドが lua の実行で、luac がコンパイラのようです。
Java と似てますね。

対話形式もできるようですが、それはまた別の機会に。

とりあえず適当なソースを書いてみます。

$ vi test.lua
print(3)

実行してみます。

$ lua test.lua
3

コンパイルしてみます。

$ luac test.lua
$ ls
luac.out  test.lua 

"luac.out" というファイルができました。
実行してみます。

$ lua luac.out
3

コンパイルしたファイルの実行も "luac.out" 単体ではなく lua コマンドに食べさせるようです。

実行可能なスクリプトファイルにしてみます。

$ vi test2.lua
$ chmod 755 test2.lua
#!/usr/bin/lua

print(3)

実行してみます。

$ ./test2.lua
3

簡単ですね。

ちなみにコンパイルしたファイルを file すると コンパイルしたバージョンが表示されるようです。

$ file luac.out
luac.out: Lua bytecode, version 5.0

PHP のバージョンを出力しないようにする

PHP 5.3 のデフォルトでは expose_php という設定項目が On になっています。 この項目が On の場合、HTTP レスポンスヘッダに PHP のバージョンを出力します。

HTTP/1.1 200 OK
Date: Sat, 03 Sep 2011 04:24:15 GMT
Server: Apache/2.2.14 (Ubuntu)
X-Powered-By: PHP/5.3.2-1ubuntu4.9
Vary: Accept-Encoding
Content-Length: 1703
Connection: close
Content-Type: text/html

expose_php を Off にします。

HTTP/1.1 200 OK
Date: Sat, 03 Sep 2011 04:26:20 GMT
Server: Apache/2.2.14 (Ubuntu)
Vary: Accept-Encoding
Content-Length: 1703
Connection: close
Content-Type: text/html

X-Powered-By の行が消えました。

Apache の設定で ServerSignature も Off にします。

HTTP/1.1 200 OK
Date: Sat, 03 Sep 2011 04:28:18 GMT
Server: Apache
Vary: Accept-Encoding
Connection: close
Content-Type: text/html 

Apache のバージョンも消えました。
サーバを公開する場合、情報は少ないほうが良いですね。

Apache の設定ファイルに PHP の設定を記述する

PHP を Apache のモジュールとして実行していて 設定項目が PHP_INI_ALL か PHP_INI_PERDIR の場合 Apache の設定ファイル (httpd.conf, apache2.conf) や .htaccess に PHP の設定を記述できます。

詳しくは次の表を参照。

モード php.ini Apache
設定ファイル
.htaccess スクリプト内
ini_set()
PHP_INI_ALL
PHP_INI_SYSTEM
PHP_INI_PERDIR
PHP_INI_USER

.htaccess に記述する場合 php_value と php_flag の 2 つのディレクティブを使うことができます。 php_value は論理値以外の値用で php_flag は論理値に使用します。

php_value default_charset UTF-8
php_flag html_errors on

Apache の設定ファイルに記述する場合 さらに php_admin_value と php_admin_flag の 2 つのディレクティブを使うことができます。

こちらのディレクティブで設定した場合 .htaccess や ini_set() では変更できないようになります。 PHP の設定ファイルである php.ini に記述した設定では そのようなことができないので 個々のユーザに変更されたくない サーバ全体の固い設定を作るときに良いですね。

Apache の prefork と worker

最近の(というほど最近では無いですが) Apache には 子プロセスの 扱いに prefork と worker の 2 種類があります。

設定ファイルにも prefork と worker の設定が入っています。

下は Debian (Apache 2.2.3) の設定ファイルです。

<IfModule mpm_prefork_module>
    StartServers          5
    MinSpareServers       5
    MaxSpareServers      10
    MaxClients          150
    MaxRequestsPerChild   0
</IfModule>

<IfModule mpm_worker_module>
    StartServers          2
    MaxClients          150
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadsPerChild      25
    MaxRequestsPerChild   0
</IfModule>

mpm は Multi Processing Module の略です。

自分の apache がどちらで動いているか 調べるためには 次のように モジュールを確認します。

$ /usr/sbin/apache2 -l

Compiled in modules:
  core.c
  mod_log_config.c
  mod_logio.c
  prefork.c
  http_core.c
  mod_so.c

prefork.c なら prefork 、worker なら worker.c です。

"-V" オプションで確認する方法もあります。

$ /usr/sbin/apache2 -V | grep MPM

Server MPM:     Prefork
 -D APACHE_MPM_DIR="server/mpm/prefork"

IE で Office2007 形式をダウンロードすると zip になる

Vista 環境の IE 7 で Office2007 形式のファイル (.docs, .xlsx, .pptx) を ダウンロードすると zip ファイルとしてダウンロードされてしまう、という現象が発生しました。

WRITE_0238_01

Web サーバに Office2007 形式用の MIME タイプを設定しないと IE が勝手に中身を見て判断してしまうようです。

追加する MIME タイプは以下のようになります。

Word .docx application/vnd.openxmlformats-officedocument.wordprocessingml.document
Excel .xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
PowerPoint .pptx application/vnd.openxmlformats-officedocument.presentationml.presentation

【参考サイト】
Microsoft - サード パーティのサーバー上のファイル拡張子を登録します。

設定すると Office のドキュメントとして認識されるようになります。

WRITE_0238_02

Apache が提供する情報を制限する ServerSignature 編

前回、ServerTokens ディレクティブについて説明しましたが 今回は ServerSignature ディレクティブです。

ServerSignature ディレクティブは CentOS の場合、デフォルトでは On になっています。

ServerSignature On

これが On になっていると Web サーバにアクセスして エラーになった場合に 次のように サーバの情報が表示されます。

WRITE_0216_01

ここで表示される内容は ServerTokens ディレクティブの設定で変化します。 (上の例では "ProductOnly" を設定しています)

ServerSignature ディレクティブを Off に設定してみます。

ServerSignature Off

ServerSignature ディレクティブを Off に設定すると 次のように サーバの情報が表示されなくなります。

WRITE_0216_02

ちょっとしたことですが 情報の提示に対して 気を使ってる雰囲気を出すことも大事だと思います。

Apache が提供する情報を制限する ServerTokens 編

サーバの防衛の基本として、「攻撃者に多くの情報を提供しない」というものがあります。

現実に当てはめれば『独り暮らし』『平日の午前中は留守が多い』『セコムしてません』などの情報は 極力知られない方が良い、というのと同じですね。

今回は Web サーバ Apache の情報制限です。

CentOS などでは、 Apache をインストールすると デフォルトでは ServerTokens ディレクティブは次のように "OS" が設定されています。 (設定ファイルは /etc/httpd/conf/httpd.conf です)

ServerTokens OS

この場合、Webサーバにアクセスすると次のような値が戻ります。

HTTP/1.1 403 Forbidden
Date: Tue, 02 Feb 2010 05:36:28 GMT
Server: Apache/2.2.3 (CentOS)
Accept-Ranges: bytes
Content-Length: 5043
Connection: close
Content-Type: text/html; charset=UTF-8

Server: を見ると "Apache/2.2.3 (CentOS)" のように バージョン番号から OS まで 出力してしまっています。

これでは、仮に 2.2.3 に重大なセキュリティホールがあった場合、狙ってくださいと 言ってるようなものですよね。

というわけで、これを表示させないように変更します。

ServerTokens ProductOnly

このように設定すると、表示が "Apache" だけになります。

HTTP/1.1 403 Forbidden
Date: Tue, 02 Feb 2010 05:38:45 GMT
Server: Apache
Accept-Ranges: bytes
Content-Length: 5043
Connection: close
Content-Type: text/html; charset=UTF-8

ServerTokens ディレクティブの デフォルト値は "Full" で、 これ以上は隠せないようです。

ちなみにこの設定は ServerSignature の表示内容にも影響します。 ServerSignature については、また次回。

Digest: generating secret for digest authentication

httpd で error_log に次のようなメッセージが出ることがあります。

[notice] Digest: generating secret for digest authentication ...
[notice] Digest: done 

これは Digest 認証用のモジュール mod_auth_digest.so が ロードされているためのようです。

notice なので問題はないですが、 Digest 認証用を使用していないのであれば mod_auth_digest.so をロードしないように コメントアウトすれば出なくなります。

エラードキュメントの設定

blog っぽくなるように ちょこちょこと手を加えているのですが エラードキュメントも設定しました。

ページが見つからない場合
http://www.odin.hyork.net/xxxx.html

参照する権限がない場合
http://www.odin.hyork.net/img/

Apache の場合 .htaccess などに 次のように記述します。

ErrorDocument 403 /error/403.html
ErrorDocument 404 /error/404.html

他にも次のような書き方があります。

ErrorDocument 500 http://foo.example.com/cgi-bin/tester
ErrorDocument 404 /cgi-bin/bad_urls.pl
ErrorDocument 401 /subscription_info.html
ErrorDocument 403 "Sorry can't allow you access today"

4 番目は、ブラウザに送る文字のみを指定しています。

ただ、ErrorDocument の使用には 注意点が 2 つあります。 1 つ目は、1 番目の例のように URL を指定した場合 ブラウザには、エラーコードが返らずに 指定した URL のリダイレクトが送られてしまいます。 2 つ目は、これらのエラーを送っても 結局表示する内容を決めるのはブラウザであるということです。

サイトの引越しと、Apacheのリダイレクト

サーバを借りることにしたので サイトの引越しをしました。

Googleにも引越しを伝える必要があるのですが 301のコードでリダイレクトすれば勝手に認識してくれるそうです。

リダイレクトは、こんな感じで書けます。

RewriteEngine on
RewriteRule (.*) http://www.odin.hyork.net/$1 [R=301,L]

元のサーバのApacheには、mod_rewriteを 入れていなかったので、下の方法で対応しました。

Redirect 301 / http://www.odin.hyork.net/

Digest認証を使ってみる

Webの認証の1つにDigest認証というものがあります。

Basic認証の上位版といった感じのもので、 ユーザIDとパスワードを平文で送るBasic認証と違い 暗号化したユーザIDとパスワードを Webサーバに送るため、盗聴や改竄に対して強くなっています。

最近では、ほとんどのWebブラウザが対応しているそうで IEでもFireFoxでも使うことができましたえ。

Digest認証は以下のコマンドでパスワードファイルを作成します。 コマンド実行後にパスワードの入力を求められます。

# htdigest -c /etc/apache2/.htdigest "digest auth" testuser

Apacheの設定は以下のようになります。

Alias /site/ /var/www/digest/
<Directory "/var/www/digest">
    AuthUserFile /etc/apache2/.htdigest
    AuthName "digest auth"
    AuthType Digest
    Require valid-user
</Directory>

ほとんどBasic認証と同じです。

Basic認証と違う点は、パスワードファイルの作成時に 認証領域(この場合は"digest auth")を設定することと この値がApacheのAuthNameと一致している必要があります。

Apacheが2.2未満の場合は、AuthUserFileではなく AuthDigestFileディレクティブを使わないとエラーになります。

ホントは、これだけでOKのはずなのですが、 IEはCGIなどで?が付くURLだと正しく認証情報を作れないそうです。 (IE7からは対応されているらしいです)

IEがずっと対応しないので、 Apache側で専用に対応策を作ってくれたそうです。 下の定義をApacheの設定ファイルに追加します。

BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On

あとはauth_digestモジュールを有効にして、再起動します。

# a2enmod auth_digest
# apache2ctl graceful

これで終わりです。