mod_rewriteで特定のアクセスを拒否する＋mod_rewriteの再整理

#mod_rewriteで特定のアクセスを拒否する
AWSからシステムを使ったクロールが多いので拒否することとなった。
個人的には過負荷になっているわけではないし、攻撃的なパラメータでもないのでほっといてもいいと思うが、是非拒否してほしいとの事。

下記を設定し、403エラーを返すようにした。
条件：

0. *.amazonaws.comからのアクセス
0. リファラがない
0. Accept-Languageがen-us.*
（個人的にはAccept-Languageとか入れたくなかったが、入れて欲しいとのこと。多言語サイトでないからまぁいいのかな。）

```lang:具体例
RewriteCond %{REMOTE_HOST} "^.*\.amazonaws\.com" [NC]
RewriteCond %{HTTP_REFERER} ^$
RewriteCond %{HTTP:Accept-Language} "^en-us" [NC]
RewriteRule ^.*$ - [F,L]
```

##RewriteCondディレクティブ
書き換えの条件を指定する。この条件に一致した場合だけ書き換えが行われる。

```lang:書式
RewriteCond テスト文字列 条件パターン オプション
```

```lang:例）ファイルが存在する場合、後に続くパターンで書き換えを行う
RewriteCond %{REQUEST_FILENAME} !-f
```

###後方参照について
RewriteCondの条件パターンで「()（カッコ）」を使って一致した値は、変数を使って再利用できます。これを後方参照と言います。
RewriteCondで指定したパターンを参照する場合は「%（パーセント）」を使います。「()（カッコ）」が複数ある場合は左から%1、%2といった具合に利用することができます。
同じように、後に解説するRewriteRuleディレクティブでも後方参照を利用できます。こちらは通常の正規表現の後方参照と同じように「$（ドル）」で利用できます。

```lang:例）http://hogehoge.hoge/ex/hoge/index.htmlのリクエストがあった場合
RewriteCond %{REQUEST_FILENAME} ^(.*)/(.*)/index.html$
RewriteRule ^/ex/(.*)/(.*)$ /$1/%1/$2
```
以上のルールが実行されると、「/hoge/ex/index.html」となります。


###注意
直下のrewriteruleにしか適用されない。適用したい場合は都度かくか[C]フラグでチェインする必要あります。

RewriteCond a
RewriteCond b
RewriteRule c
RewriteRule d

上記のような場合、a && b のときcのルールが適用される。
dはaとbのcondが効かずに常に適用される。

###RewriteCondに利用できる環境変数変数表
|グループ|変数名|備考|
|:--|:--|:-------|
|HTTP ヘッダ|HTTP_USER_AGENT|ユーザーエージェント|
||HTTP_REFERER|参照元URL|
||HTTP_COOKIE|クッキー情報|
||HTTP_FORWARDED|プロキシ情報|
||HTTP_HOST|サーバーのホスト名|
||HTTP_PROXY_CONNECTION|プロキシを経由しているか否か|
||HTTP_ACCEPT|ブラウザの言語タイプ|
|コネクション & リクエスト|REMOTE_ADDR|リモートアドレス|
||REMOTE_HOST|リモートホスト名|
||REMOTE_USER|リモートユーザー名 (基本認証利用時)|
||REMOTE_IDENT|リモートユーザーのID|
||REQUEST_METHOD|リクエストメソッド|
||SCRIPT_FILENAME|スクリプトファイル名|
||PATH_INFO|パス情報|
||QUERY_STRING|クエリ文字列|
||AUTH_TYPE|認証タイプ|
|サーバ内部変数|DOCUMENT_ROOT|ドキュメントルートのパス|
||SERVER_ADMIN|サーバー管理者情報|
||SERVER_NAME|サーバー名|
||SERVER_ADDR|サーバーのアドレス|
||SERVER_PORT|サーバーのポート番号|
||SERVER_PROTOCOL|プロトコルバージョン|
||SERVER_SOFTWARE|サーバーソフトウェア|
|システム関連|TIME_YEAR|年|
||TIME_MON|月|
||TIME_DAY|日|
||TIME_HOUR|時|
||TIME_MIN|分|
||TIME_SEC|秒|
||TIME_WDAY|曜日 (0:日 ～ 6:土)|
||TIME|年月日時分秒 (例:20130123123456)|
|その他|API_VERSION|APIバージョン|
||THE_REQUEST|リクエスト文字列|
||REQUEST_URI|リクエストURI|
||REQUEST_FILENAME|リクエストされたファイル名|
||IS_SUBREQ|サブリクエストか否か|
||HTTPS|HTTPSでのアクセスか否か|

Accept-Languageは下記のような書き方を何故かするみたいです。
```HTTP:Accept-Language```

###RewriteCondに利用できる条件パターンの一覧
|パターン|意味|
|:--|:--|
|!|否定|
|<|テスト文字列より上の場合true|
|>|テスト文字列より下の場合true|
|=|テスト文字列と等しい場合true|
|<=|テスト文字列以上の場合true|
|>=|テスト文字列以下の場合true|
|-d|(is directory)ディレクトリが存在すればtrue|
|-f|(is regular file)ファイルが存在すればtrue|
|-eq|(is numerically equal to)いわゆる「=」|
|-ge|(is numerically greater than or equal to)いわゆる「<=」|
|-gt|(is numerically greater than)いわゆる「<」|
|-le|(is numerically less than or equal to)いわゆる「>=」|
|-lt|(is numerically less than)いわゆる「>」|
|-F|(is existing file, via subrequest)アクセス可能な有効なパスを指している場合にtrue (内部サブリクエストを用いてcheckされる)|
|-l|(is symbolic link)シンボルリンク（-H、-Lも同じ意味。ちなみに小文字エルです）|
|-s|(is regular file, with size)ファイルが存在し、サイズが0でなければtrue|
|-U|(is existing URL, via subrequest)アクセス可能な有効なURLとなっている場合にtrue|
|-x|(has executable permissions)実行権限がある場合にtrue|

###RewriteCondに利用できるオプションの一覧
下記のように[]でオプションを指定できます。複数指定時はカンマ区切り
`RewriteCond %{HTTP:Accept-Language} "^en-us" [NC]`

|オプション|意味|
|:--|:--|
|OR|連続した複数の条件の内、どちらかに一致した場合に実行する。指定しない場合はANDとなり、連続した全ての条件が一致した場合にだけ実行する。|
|NC|大文字小文字を区別しない。|

##RewriteRuleディレクティブ
書き換えのルールを決めるディレティブ。パターンで一致した値を置換文字列で書き換えます。
条件パターンはPerl互換の正規表現で指定する。

```lang:書式
RewriteRule 条件パターン 置換文字列 [フラグ]
```

###RewriteRuleのフラグ
一般的にはこの省略形で記載します。

|フラグ|省略形|意味|
|:--|:--|:--|
|B|英数字のエスケープ。いわゆるURLエンコード（&を%26など）。|
|chain|C|チェーン。次の処理を連続して行う場合に指定する。|
|cookie|CO=NAME:VAL|Cookieをセットすることができる。書式：CO=NAME:VAL:domain[:lifetime[:path[:secure[:httponly]]]]|
|discardpath|DPI|PATH_INFOの削除。PATH_INFOとは実際のスクリプトファイル名とクエリ文字列の間にある、クライアントが提供するパス名情報。|
|env|E=[!]VAR[:VAL]|環境変数をセットできます。セットするときは[E=VAR:VAL]、削除するときは[E=!VAR]とする。例）hogeという閑居言う変数にhugaを入れる。[E=hoge:huga]|
|forbidden|F|クライアントに403 Forbiddenステータスコードを返す。|
|gone|G|クライアントに410 Goneステータスコードを返す。|
|Handler|H=Content-handler|実行するアプリケーションを指定するハンドラを強制的に付ける。application/x-httpd-phpなど。設定ファイルでAddType application/x-httpd-php .phpとしておけば同じハンドラの場合はPHPプログラムとして実行されてる。|
|last|L|Lフラグが付くとそこでルールセットが停止する。直後に続くルールを実行しない。|
|next|N|書き換えを行ったら、ルールセットの最初からやり直す。|
|nocase|NC|no case。大文字小文字を区別しない。|
|noescape|NE|noescape。エスケープをしなくなる。通常は&や%はURLエスケープされるが、このフラグを使うとエスケープせずにそのままの文字になる。|
|nosubreq|NS|現在のリクエストがサブリクエストの場合はルールをスキップ。|
|proxy|P|ルールに一致したリクエストをプロキシを介して処理する。以降の処理はプロキシに渡るのでLフラグと同じようにルールの進行は停止する。|
|passthrough|PT|uri フィールドに filename フィールドの値をセットする。直後にmod_aliasでディレクトリ構造の書き換えを行う際などに利用する。|
|qsappend|QSA|クエリ文字列部分に書き換えではなく、文字を追加したい場合に指定する。通常「?」後のクエリ文字列は削除されるため利用する。|
|qsdiscard|QSD|クエリ文字列がある場合削除される。これはデフォルトの動作。|
|redirect|R[=code]|クライアントに外部へのリダイレクトとレスポンスコードを返す。何も指定しないと302で返す。[R=301]等とすればレスポンスコードを変更できる。|
|skip|S=num|指定した数のルールをスキップする。[s=2]とすれば、一致した場合、以降のルールを2つ飛ばす。if-then-elseを実現できる。|
|type|T=MIME-type|一致した項目にMIME-typeを付加する。AddTypeと同じ挙動。|