設定 - .htaccess
概要
Filesディレクティブ
Apache2のセキュリティを向上させる重要なツールの1つである。
Filesディレクティブは、特定のファイルやファイルタイプに対してアクセス制御を行うために使用する。
特定のファイルやファイルタイプへのアクセスを制御することにより、機密情報の保護や不正アクセスの防止に役立つ。
- 特定のファイルへのアクセス制御
- 特定のファイル名やファイルパターンに対して、アクセス権限を設定できる。
- セキュリティ強化
- 重要なファイルや設定ファイルへの不正アクセスを防ぐ。
- 柔軟な設定
- ワイルドカードを使用して、複数のファイルに一度に適用することができる。
<Files "filename">
# ここにディレクティブを記述
</Files>
# 例 1: .htaccessファイル自体へのアクセスを拒否する場合
<Files ".htaccess">
Require all denied
</Files>
# または
<Files ~ "^.*\.([Hh][Tt][Aa][Cc][Cc][Es][Ss][Ss])$">
Order allow,deny
Deny from all
</Files>
# 例 2: 複数のファイルタイプに対して設定を適用する場合
<Files ~ "\.(php|ini)$">
Require all denied
</Files>
FilesMatchディレクティブ
FilesMatchディレクティブは、Filesディレクティブの拡張版と考えることができる。
正規表現を使用することにより、複雑なルールを簡潔に記述でき、Apache2のセキュリティと柔軟性を向上させることができる。
特に、より精密なファイルアクセス制御が必要な場合に有用である。
- 正規表現によるマッチング
- FilesMatchは正規表現を使用してファイル名やパターンにマッチするため、より柔軟で強力なマッチングが可能である。
- 複雑なパターンの指定
- 複数の条件や複雑なファイル名パターンに対して設定を適用できる。
- 効率的な設定
- 1つのディレクティブで多様なファイルタイプやパターンを指定できるため、設定がより簡潔になる。
<FilesMatch "<正規表現>">
# ここにディレクティブを記述
</FilesMatch>
# 例 1: 特定の拡張子を持つファイルへのアクセスを拒否する場合
# 指定された拡張子 (.htaccess、.htpasswd、.ini等) を持つファイルへのアクセスを拒否している
<FilesMatch "\.(htaccess|htpasswd|ini|phps|fla|psd|log|sh)$">
Require all denied
</FilesMatch>
# 例 2: 特定のパターンを含むファイル名へのアクセスを許可する場合
# "index"、"main"、"home"で始まり、".php"または".html"で終わるファイルへのアクセスを許可している
<FilesMatch "^(index|main|home)\.(php|html)$">
Require all granted
</FilesMatch>
# 例 3: 特定の文字で始まるファイルへのアクセスを制限する場合
# 数字で始まる全てのファイルへのアクセスを拒否している
<FilesMatch "^[0-9]">
Require all denied
</FilesMatch>
# 例 4: .htaccessファイルと同階層にあるhogeディレクトリ内にある全てのXMLファイルへのアクセスを拒否する場合
# サイトマップは全て閲覧可能にする
<FilesMatch "^hoge/.*\.xml$">
Require all denied
</FilesMatch>
Directoryディレクティブ
Directoryディレクティブは、Apache2の設定を細かく制御するための重要なツールである。
Directoryディレクティブは、特定のディレクトリやそのサブディレクトリに対して設定を適用するために使用する。
サイトの構造に合わせて適切に使用することにより、セキュリティ、パフォーマンス、機能性を向上させることができる。
- ディレクトリ単位の設定
- 特定のディレクトリとそのサブディレクトリに対して、一括で設定を適用できる。
- 階層的な設定
- Webサイトの構造に合わせて、異なるディレクトリに異なる設定を適用できる。
- 柔軟なアクセス制御
- 特定のディレクトリに対するアクセス権限、実行可能なスクリプト、インデックスオプション等を制御できる。
<Directory "/path/to/directory">
# ここにディレクティブを記述
</Directory>
# 例 1: 特定のディレクトリへのアクセスを制限する場合
# /var/www/html/adminディレクトリへのアクセスにおいて、特定のIPアドレス範囲とホストからのみ許可している
<Directory "/var/www/html/admin">
Require ip 192.168.1.0/24
Require host example.com
</Directory>
# 例 2: .htaccessファイルと同階層にあるhogeディレクトリおよび直下のファイル群へのアクセスを拒否する場合
# "hoge"は、.htaccessファイルからの相対パス
# "/hoge"は、ドキュメントルートからの相対パス
<Directory "hoge">
Require all denied
</Directory>
# 例 3: ディレクトリ内のPHPファイルの実行を禁止する場合
# /var/www/html/uploadsディレクトリ内のPHPファイルの実行を禁止している
<Directory "/var/www/html/uploads">
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
</Directory>
# 例 4: ディレクトリインデックスを設定する場合
# /var/www/html/publicディレクトリでディレクトリリスティング (インデックス) を有効にして、見栄えの良い表示オプションを設定している
<Directory "/var/www/html/public">
Options +Indexes
IndexOptions FancyIndexing
</Directory>
# 例 5: 特定のディレクトリでのリライトルールの適用する場合
# /var/www/html/blogディレクトリ内で特定のURLパターンをPHPスクリプトにリダイレクトしている
<Directory "/var/www/html/blog">
RewriteEngine On
RewriteRule ^article-([0-9]+)\.html$ article.php?id=$1 [L]
</Directory>
mod_rewriteモジュール
mod_rewriteモジュールとは
mod_rewriteモジュールは、Apache2の非常に強力で柔軟な機能の1つである。
このモジュールを使用することにより、URLの書き換えやリダイレクトを動的に行うことができる。
mod_rewriteモジュールは正規表現を使用して柔軟なルール設定が可能であるが、複雑な設定になりがちであり、間違った設定によるパフォーマンスへの影響も考慮する必要がある。
- URL書き換え
- 複雑なURLを簡潔で覚えやすいものに変更できる。
- リダイレクト
- ユーザを別のURLに転送することができる。
- 条件分岐
- 様々な条件 (ブラウザタイプ、IPアドレス等) に基づいて異なる動作を設定できる。
- セキュリティ強化
- 特定のリソースへのアクセスを制限、または、悪意のあるリクエストをブロックすることができる。
- SEO最適化
- 検索エンジンフレンドリーなURLを作成できる。
- レガシーURLの維持
- サイト構造を変更しても古いURLを機能させ続けることができる。
RewriteEngine
mod_rewriteモジュールの機能を有効または無効にするための命令である。
以下の例では、mod_rewriteモジュールおよびRewriteRule
を有効にしている。
RewriteEngine On
RewriteCond
RewriteRule
が適用される条件を指定する。
複数のRewriteCondを指定することができる。
RewriteCond <設定の種類> <パターン> [<フラグ>]
# 例: HTTPホストが"www.example.com"の場合に条件が真になる
RewriteCond %{HTTP_HOST} ^www\.example\.com$
複数のRewriteCond
ディレクティブが連続して記述されている場合、それらは暗黙的にAND条件として扱われる。
# 例: リモートホストに".example.com"で終わる文字列が含まれており、かつ、".osk[0-9]."という文字列が含まれていない場合はアクセスを許可
RewriteCond %{REMOTE_HOST} \.example\.com$ [NC]
RewriteCond %{REMOTE_HOST} !\.osk[0-9]\. [NC]
RewriteRule ^ - [L]
もし、OR条件にしたい場合は、[OR]
フラグを使用して明示的に指定する必要がある。
# 例: リモートホストに".example.com"で終わる文字列が含まれている場合、または、".osk[0-9]."という文字列が含まれていない場合はアクセスを許可
RewriteCond %{REMOTE_HOST} \.example\.com$ [NC,OR]
RewriteCond %{REMOTE_HOST} !\.osk[0-9]\. [NC]
RewriteRule ^ - [L]
また、OR条件の場合のみ、複数のRewriteCond
ディレクティブを1つにまとめることが可能である。
以下の例では、|
(パイプ) を使用して、OR条件を使用している。
これにより、リクエストURIに"osaka"または"osk"が含まれている場合にマッチする。
※注意
複数の条件を1行にまとめる場合は、OR条件 (|
) のみが可能である。
AND条件は、複数のRewriteCond
ディレクティブを別々の行に記述することにより表現する。
RewriteCond %{REQUEST_URI} osaka|osk
# 3つの条件のいずれかに該当する場合にリダイレクトを行う
RewriteCond %{REQUEST_URI} Qt|QML [NC,OR]
RewriteCond %{THE_REQUEST} \s(Qt|QML) [NC,OR]
RewriteCond %{QUERY_STRING} Qt|QML [NC]
RewriteRule ^(.*)$ </path/to/redirect> [L,R=301]
1つにまとめる場合、以下に示すようなメリットがある。
ただし、パフォーマンスに大きな影響を与えるものではないため、可読性を重視する場合は別々に記述しても構わない。
- コードがより簡潔になる。
- パフォーマンスが若干向上する可能性がある。 (1回の条件チェックで済むため)
RewriteRuleディレクティブ
RewriteCond
の設定を適用する。
RewriteRule <パターン> <Substitution> [<フラグ>]
RewriteRule ^ - [L]
- この規則は、現在のURLを変更せずにそのまま処理を続行することを表す。
- [L]フラグはLastを意味しており、この規則によりRewriteエンジンの処理を停止する。
- つまり、この規則以降の他の
RewriteRule
は適用されない。
RewriteRule ^ - [F,L]
- この規則も現在のURLを変更しないが、[F]フラグによりアクセスを拒否する。
- [F]フラグはForbiddenを意味しており、403 Forbiddenステータスコードを返す。
- [L]フラグも含まれているため、この規則により処理が停止する。
# 例 1: mineo回線のアクセスを許可する場合
RewriteCond %{REMOTE_HOST} ^[\w.-]*\.mineo\.jp$ [NC]
RewriteRule ^ - [L]
# 例 2: リモートホストに".osaka."という文字列が含まれている場合は、アクセスを拒否する場合
RewriteCond %{REMOTE_HOST} ^[\w.-]*\.osaka\.[\w.-]*$ [NC]
RewriteRule ^ - [F,L]
# 例 3: "old-page.html"へのリクエストを"/new-page.html"にリダイレクトする
RewriteRule ^old-page\.html$ /new-page.html [R=301,L]
以下に示す2つの設定は、全てのリクエストに対して403 Forbiddenエラーを返す。
したがって、Webサイト全体へのアクセスを禁止する設定である。
- RewriteRule .* - [F,L]
- RewriteRule ^(.*)$ - [F,L]
後者のルールの方がより厳密である。
正規表現である^
および$
を使用することにより、URLの先頭から末尾までを完全にマッチさせる。
一方、前者のルールは理論的にはURLの一部分にもマッチする可能性がある。
以下に示す設定は、全てのリクエストに対して403 Forbiddenエラーを返す。
R=403とは、403 Forbiddenステータスコードでリダイレクトを行う設定である。
- RewriteRule ^ /hoge.html [L,R=403]
RewriteBaseディレクティブ
RewriteBaseディレクティブは、mod_rewriteモジュールで使用されており、その後に続くRewriteRule
で使用される相対URLのベースパスを設定する。
RewriteBaseディレクティブが設定されていない場合は、RewriteBase
はドキュメントルートからの相対パスとなる。
RewriteBaseを適切に設定することにより、より柔軟でメンテナンスしやすいURL書き換えルールを作成することができる。
サブディレクトリでのRewriteRule
使用時において、特に重要である。
.htaccessファイルを異なる階層で再利用する場合に便利である。
- 機能
- 相対パスの解決
RewriteRule
で相対パスを使用する際の起点を定義する。
- URLの一貫性
- 異なるディレクトリ階層でも同じ
RewriteRule
を使用可能にする。
- 異なるディレクトリ階層でも同じ
- 相対パスの解決
# 例 1: "/blog/post/123"へのリクエストは、"/blog/view.php?id=123"に内部的にリダイレクトする
RewriteBase /blog/
RewriteRule ^post/(.*)$ view.php?id=$1
# 例 2: Webサイトのルートディレクトリ (例: http://example.com/) にアクセスした場合、サーバは内部的に"index.php"にリクエストを転送する
# WebブラウザにはURLの変更は表示されない (内部リダイレクト)
# "RewriteBase /"は、以降のRewriteRuleで使用される相対パスの基準点をサーバのドキュメントルート (/) に設定する
# つまり、全ての相対パスはサーバのルートディレクトリを起点として解釈される
# "RewriteRule ^$ index.php [L]"は、書き換えルールを定義している
# "^$": この正規表現は、空の文字列 (ディレクトリのルート) にマッチする
# "index.php": マッチした場合にリダイレクトされる先のファイル
# "[L]": "Last"の略であり、このルールが適用された場合、以降のルールは処理されない
RewriteBase /
RewriteRule ^$ index.php [L]
例 1 : 全てのWebサイトからのリンク経由のアクセスを許可
ただし、HTTPリファラーはWebブラウザによっては送信されない場合があり、また、ユーザによって改竄される可能性があることに注意する。
# "RewriteCond %{HTTP_REFERER} ."は、HTTP_REFERERヘッダが存在して、かつ、空でない場合にマッチする (ドットは任意の1文字にマッチ)
# マッチした場合、"RewriteRule ^ - [L]"が適用されて、リクエストは変更されずに処理が終了する
# したがって、リファラーが存在する全てのリクエスト (他のWebサイトからのリンク経由のアクセス全て) が許可される
RewriteCond %{HTTP_REFERER} .
RewriteRule ^ - [L]
例 2 : 特定のWebサイト以外からのリンク経由のアクセスを許可
# "RewriteCond %{HTTP_REFERER} !^$"は、HTTP_REFERERが空でない場合にマッチする
# "RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example\.com [NC]"は、リファラーが指定されたドメイン (example.com) ではない場合にマッチする
# 両方の条件がマッチした場合、"RewriteRule ^ - [L]"が適用されて、リクエストは変更されずに処理が終了する
# したがって、リファラーが存在して、かつ、指定されたドメイン以外からのアクセスが全て許可される
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example\.com [NC]
RewriteRule ^ - [L]
直接アクセスを拒否
以下の例では、WebブラウザのURL入力やブックマークからの直接アクセスを拒否している。
# リファラーが存在しない(直接アクセスの)場合にアクセスを拒否
RewriteCond %{HTTP_REFERER} ^$
RewriteRule ^ - [F,L]
例 3 : 特定のリモートホストのアクセスを拒否
以下の例では、リモートホストに".osaka."という文字列が含まれている場合、特定のユーザエージェント以外はアクセスを拒否している。
SetEnvIfNoCase User-Agent "Linux x86_64" linux_user_agent=1
SetEnvIfNoCase User-Agent "Linux i686" linux_user_agent=1
SetEnvIfNoCase User-Agent "Linux i686 on x86_64" linux_user_agent=1
SetEnvIfNoCase User-Agent "Linux arm" linux_user_agent=1
SetEnvIfNoCase User-Agent "Linux aarch64" linux_user_agent=1
SetEnvIfNoCase User-Agent "CrOS" linux_user_agent=1
RewriteCond %{REMOTE_HOST} ^[\w.-]*\.osaka\.[\w.-]*$ [NC]
RewriteCond %{ENV:linux_user_agent} =1 [OR]
RewriteRule ^ - [L]
RewriteCond %{REMOTE_HOST} ^[\w.-]*\.osaka\.[\w.-]*$ [NC]
RewriteRule ^ - [F,L]
例 4 : 特定のリモートアドレスのアクセスを許可
以下の例では、指定されたIPアドレスの範囲からのアクセスを許可している。
RewriteCond %{REMOTE_ADDR} ^91\.219\.239\. [OR]
RewriteCond %{REMOTE_ADDR} ^85\.203\.39\. [OR]
RewriteCond %{REMOTE_ADDR} ^45\.250\.255\.
RewriteRule ^ - [L]
wgetコマンドからのアクセスを拒否
wgetコマンドでダウンロードする場合、ユーザエージェントにWgetという文字列が含まれている。
RewriteRule
と組み合わせて使用することにより、wgetコマンドからのアクセスを拒否することができる。
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} ^Wget [NC]
RewriteRule .* - [F,L]
</IfModule>
リダイレクト
# 例 1: リモートホストに"vpn"という文字列が含まれている場合、アクセスを拒否してhoge.htmlへリダイレクト
RewriteCond %{REMOTE_HOST} vpn [NC]
RewriteRule ^ /hoge.html [L,R=403]
# 例 2: リモートホストに"softbank"という文字列が含まれている場合、アクセスを拒否してpiyo.htmlへリダイレクト
RewriteCond %{REMOTE_HOST} softbank [NC]
RewriteRule ^ /piyo.html [L,R=403]
また、HTMLファイルやPHPファイル等の後に?
を追記することにより、元のリクエストのクエリ文字列を無視して、新しいURLにクエリ文字列が付加されない。
# 例 1: リモートホストに"au-net"という文字列が含まれている場合、huga.htmlへリダイレクト
RewriteCond %{REMOTE_HOST} au-net [NC]
RewriteRule ^ /huga.html? [R=302,L]
必要に応じて、301 (恒久的リダイレクト) や 302 (一時的リダイレクト) に変更することもできる。
全角文字の取り扱い
.htaccessファイルでは、以下に示す理由から、全角文字の使用は非推奨である。
- エンコーディングの問題
- .htaccessファイルは通常ASCII文字セットで保存される。
- 全角文字を使用する場合、ファイルのエンコーディングがUTF-8等になり、サーバによっては正しく解釈されない可能性がある。
- 可読性と保守性
- 全角文字を使用する場合、他の開発者やサーバ管理者が.htaccessファイルを読み解くのが難しくなる可能性がある。
- 互換性の問題
- 異なるサーバ環境や設定間での互換性の問題が発生する可能性がある。
- URLエンコーディング
- URLには通常ASCII文字のみが使用されるため、全角文字はURLエンコードされる必要がある。
そのため、以下に示すようにURLエンコードされた文字列を使用する必要がある。
# "ほげ"をURLエンコードした"%E3%81%BB%E3%81%92"を使用
RewriteCond %{REQUEST_URI} "%E3%81%BB%E3%81%92" [OR]
RewriteCond %{THE_REQUEST} \s"%E3%81%BB%E3%81%92" [OR]
RewriteCond %{QUERY_STRING} "%E3%81%BB%E3%81%92"
これにより、エンコーディングの問題を回避して、より安全で互換性のある設定が可能になる。
もし全角文字の使用が絶対に必要な場合は、Apacheの設定でUTF-8エンコーディングが正しく処理されることを確認する。
ただし、上記の理由から、可能な限りURLエンコードされた文字列を使用することを強く推奨する。
Options -Indexes
Options -Indexes
は、ディレクトリリスティング (インデックス表示) を無効にする設定である。
特定のディレクトリにアクセスされた時、index.html等のデフォルトページが存在しない場合はディレクトリの内容一覧を表示せずに、"403 Forbidden"エラーが表示される。
この設定は、Webサイトのセキュリティを向上させるための基本的な方策の1つとして広く推奨されている。
ディレクトリの内容を意図せず公開してしまうリスクを軽減することができる。
Options -Indexesが設定されていない場合は、
デフォルトのインデックスファイル (例:index.html, index.php等) が存在しないディレクトリにアクセスすると、ディレクトリの内容一覧が表示される。
- セキュリティ面での利点
- Webサーバ上のファイル構造や存在するファイルの一覧が公開されるのを防ぐ。
- 潜在的な脆弱性や機密情報の露出リスクを低減する。
Options -Indexes