設定 - .htaccess

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要



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