サーバ管理 - Apache
作業メモ。マニュアルのオレ用補足とも言う。
ErrorDocumentのカスタマイズ
404 File Not Foundなどのエラーメッセージをカスタマイズする。書式はErrorDocument status-code path
となる。以下凡例。
ErrorDocument 401 /error/401.html ErrorDocument 403 /error/403.html ErrorDocument 404 /error/404.html ErrorDocument 500 /error/500.html
このへんは常識だね!
401のErrorDocumentを設定する際の注意点
401は扱いがちょっと特殊で、ほとんどのエラーメッセージは外部URIを指定可能なのだが、401に指定できる引数はローカルホスト限定となっており、リモートURLを指定するとcannot use a full URL in a 401 ErrorDocument
というエラーが返される。その理由だが、ErrorDocumentに外部のURLを指定したときの挙動はRedirect扱いとなる。そのためユーザーエージェントは401を受け取らずに301/302などのRedirectのステータスコードを受け取る事になる。
当然ユーザーエージェントはリダイレクト先にリクエストを要求し直すため、ユーザにパスワードを要求すること───つまり認証画面を表示することができなくなってしまう。ゆえにローカル以外を指定すると無視する仕様になっているらしい。
普通はエラーメッセージなんてローカルホストで処理するだろ?と思うだろうが、以前携わってた動画配信サイトではコンテンツ表示ページのホストと動画ファイル設置ホストを別にしており、認証は動画ホスト側に仕込んでいた。ゆえに401を動画ホスト側が返しても表示ページ側のホストには反映されない、という事態になってとっても困ったのだ。結局そんときは401だけ動画ホストで処理(エラー表示)し、リファ拾ってもとの表示ページに戻す流れにして解決した。
その他のステータスコードについては200/okを参照。
リダイレクトによる明示的な移転通知
ドメインやディレクトリ構造を変更したからってリンクやブックマーク、サーチエンジンからの訪問者に404 Not Foundを晒すのはどうなのかと(まあ拾い切れないよね。
Redirectについて
リクエストに対しページが移転したことを返す。移転先はレスポンスヘッダのLocationフィールドに格納され、クライアントはシームレスに移転先にアクセスできる。書式はRedirect [status] リダイレクト元パス リダイレクト先URI
となる。
statusはpermanent 、temp、seeother、goneから選ぶ。省略時はtemp。
凡例。
Redirect parmanent /B http://xxxworks.net/B
- リダイレクトでは該当部分を置き換えたURLをエージェントが再取得することになるため、ディレクトリ構造を維持した状態で移転するのが好ましい。
Redirect
permanentとRedirectPermanent
は同じ。Redirect
tempとRedirectTemp
も同じ。- permanentはリダイレクトと同時にクライアントに対してステータス301(Moved Permanently)を返す。サーチエンジンに対して明示的に移転を通知できるため、SEOの観点からも有効な手段らしい。
- tempはリダイレクトと同時にクライアントに対してステータス302(Found)を返す。家の建て替え中につき仮住まいにお通しします、というような場合に使う。
- 302はもともとMoved Temporarilyだったのだけど、想定された使い方をなかなかしてもらえないためRFC2616でFoundに変更になったようだ。
- seeotherはリダイレクトと同時にクライアントに対してステータス303(See Other)を返す。タグの解説ページを作っていたけど、書き換え中でお見せしたくないので該当するRFCにでも飛ばしとけ、というような場合はこちらを使う。
- goneはリダイレクトと同時にクライアントに対してステータス410(Gone)を返す。恒久的に削除されたことを意味するため引数のURIは不要。
- 404を晒すくらいなら401を使って明示的に「もう更新しません」と宣言すべきと思うのだが、多くの場合そんなヒマもなく突然死を迎えてしまうのだろう。
- マニュアルには“複数の Alias や Redirect が同じコンテキスト中に現れた場合は決まった順番で処理されます”とあり、この場合Redirectや後述のRedirectMatchはAliasよりも前に処理されるため、Aliasに対してRedirectは適用されないらしい。トラブったときにこれを疑ってみる。
- リダイレクト先はhttp://から始まる絶対パスである必要があるため、リダイレクト先が同一ドメインであったとしても省略してはいけない。
- 同一ドメイン内でのリダイレクトでは、引数どうしが重複して無限ループにならないよう注意する必要がある。
statusにHTTPのレスポンスコードを直接指定することも可能だが、300番台の場合は引数が必須となり、それ以外の場合は引数があってはいけない。というかいらない。
Redirect 410 /B/
B地区閉鎖の際に使う予定。
RedirectMatch
条件付のリダイレクトを行う。構文はRedirectと同じで引数が正規表現になるだけ。
凡例
RedirectMatch (.*)\.html$ http://b-area.org$1.php
拡張子htmlに対するリクエストが拡張子phpにリダイレクトされる。なお、同一サーバでアクセスURLの見た目を変更したい場合はリダイレクトさせるのではなくAliasMatchを使うほうがよいだろう。
mod_rewriteによるアクセスURLの書き換え
CGIやPHPなどによくある引数付きのURLは見た目が美しくないばかりかSEOの観点からもよろしくないらしい。アクセスURLの正規表現を使った置き換えを可能にするのがmod_rewriteで、モジュールが読み込まれているならRewriteEngineをOnにするだけで利用できる。構文はRewriteRule 検索パターン 置換文字列 [フラグ1,フラグ2・・・]
となる。なお、書き換え後のURLが実際のファイルへのパスである。そんなことは当たり前なのだが、最初どっちがどっちなのか混乱した奴もいる(誰。また正規表現慣れしていないと、最適化には時間がかかるかもしれない。
次の2つは同じリダイレクトを行う。
RedirectMatch /B/(.*)\.php$ http://b-area.org/G/$1.html RewriteRule /B/(.*)\.php$ /G/$1.html [R=301,L]
[フラグ]のうちRはリダイレクトのステータスコードを指定(引数なしで301)、Gha410 Gone。LはLastの意で、これが処理の最終行の指定となり、後にまだRewrite構文が続いても処理をさせない。リダイレクトを指定しない場合はクライアント側のアクセスURLの見た目は変化しないが、リダイレクト先をFQDNで指定した場合は変化する。
面白い利用方法
午前0時から3時までのアクセスをメンテナンス表示にする。
RewriteEngine on RewriteBase / RewriteCond %{TIME_HOUR}%{TIME_MIN} >0000 RewriteCond %{TIME_HOUR}%{TIME_MIN} <0300 RewriteRule ^.*$ /maintenance.html [L]
この項書きかけ。
基本的なアクセス制御
招かれざる者、来るべからず。概ね網を張るレイヤーが下がるほど強固なブロックが可能で、レイヤーが上がるほどターゲットの絞り込みが可能になる。んまあ、レイヤー2以下(MACアドレスベース?)でやる意味があるのかどうかは知らん。レイヤー1でやるとしたら物理的孤立なのだろうな(それでもソーシャルハックする奴はいるはずだ!
mod_access関連
アクセス制御を行うモジュール。ベーシック認証/ダイジェスト認証に関しては別途mod_authで。
ディレクティブはOrder、Allow、Denyの3つの組み合わせでIPやドメイン、環境変数をもとにしたアクセス制御が可能になる。
- Deny from donain.name
- 引数に指定したドメイン名に完全一致したホスト名を拒否。
- Deny from IP address
- 引数に指定したIPアドレスに一致したホスト名を拒否。
IPアドレスの場合いろんな指定ができる。一部のアドレス(cf.61.213.64)を指定すると上位アドレスからの一致。さらにサブネットマスク(cf.61.213.64.0/255.255.192.0)による指定やCIDR(cf.61.213.64.0/18)による広範囲な指定も可能。
Order Allow,Deny Allow from all Deny from asahi-net.or.jp Deny from 61.213.64.0/18
asahi-net.or.jpに一致するホスト名はすべて拒否。念のためASAHIネットのネットワークブロックである61.213.64.0/18(61.213.64.0~61.213.127.255)も拒否。
続いて環境変数で指定する場合。
SetEnvIf User-Agent "Mozilla" GoodBrowser Order Deny,Allow Deny from all Allow from env=GoodBrowser
Mozilla系(IEやネスケ、Safariあたり)のメジャーブラウザのみ許可。User-Agentなんていくらでも書き換え可能だけど、初心者のダウンロード支援ソフトはじきには使えるかもしれない。ちゃんとはじくならmod_limitipconnのような同時接続数制限モジュールを入れるべき(世が世だけにこんなの標準の組み込みモジュールで対応すべきことだ)。