.htaccess の設定レシピ集

公開日:
更新日:
0.htaccess

代表的なレシピ

.htaccess は RewriteRule や RewriteCond を利用することで柔軟性の高い設定が可能です。しかし、柔軟性が高い反面、複雑化しやすいためにスイス製のアーミーナイフや、黒魔術などと呼ばれています。.htaccess の書き方をすべてマスターするには膨大な知識が必要となります。そのため、このページでは一般的に設定されている .htaccess の代表的なレシピを紹介します。


.htaccess 自体の説明は、.htaccessの書き方を参照して下さい。

リダイレクト関連のレシピ集

Apache はリクエストを受信すると指定されたドキュメントを提供しますが、別の場所にあるドキュメントを提供したい場合もあります。リダイレクトは、ドキュメントを新しい場所に移動しなくても、今ある場所に置いたまま提供できます。リダイレクト関連のレシピ集は、URL の正規化や、Web サイトが移転した場合、メンテナンスページの表示方法などを紹介します。

URL の正規化 - www の省略

URLは、以下の構造となっています。URLのホスト名の部分は、サーバによっては省略が可能です。さくらインターネットでは、www を省略しても同一の Web サイトが表示される仕様になっています。ただし、Google では同一ドメインでも www のあり・なしによって異なる Web サイトと認識します。そのため、両方の URL で同一コンテンツにアクセス可能な場合は URL の正規化を行って下さい。


http://www.murashun.jp/contents/index.html
--A--  -B- -----C----- ---D---- ----E-----

A : スキーム
B : ホスト名
C : ドメイン名
D : ディレクトリ名
E : ファイル名

www を省略するには以下のように記述します。以下の例では、環境変数の "HTTP_HOST" が www を含む URL の場合、www を省略した URL に書き換えてリダイレクトしています。$1 は、リクエストされたページの URL を後方参照で正規化済みの URL の末尾に加えています。


RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.murashun\.jp
RewriteRule ^(.*)$ https://murashun.jp/$1 [R=301,L]
 URL の www を省略する

URL の正規化 - http から https にリダイレクト

SSL 暗号化通信対応後、http から https にリダイレクトする設定例です。


RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
 http から https にリダイレクトする例

プロキシサーバを経由している場合は、特殊な環境変数 "X-Forwarded-Proto" を確認します。


RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
 http から https にリダイレクトする例

ただし、さくらインターネットの SNI SSL では、上記の設定でリダイレクトループが発生します。 これは、さくらインターネットの HTTPS (SNI SSL) は、リバースプロキシとして動作しており、RewriteCond ディレクティブによる HTTPS 判定ができないためです。そのため、ユーザが HTTPS でアクセスしても、実行ファイルからは HTTP でアクセスしたものと見なされます。リダイレクトループを回避するには、以下の設定を試して下さい。


RewriteEngine On
RewriteCond %{HTTP:X-SAKURA-FORWARDED-FOR} ^$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
 http から https にリダイレクトする例 (さくらインターネットの場合)

上記の設定でもリダイレクトループが発生する場合は、HSTS (HTTP Strict Transport Security) を設定して下さい。この設定は、Web サーバがブラウザに対して、次回以降の接続は HTTP の代わりに HTTPS を使うように通知するセキュリティ機構です。


Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
 HSTSにより次回以降 HTTPS を通知する例

上記の設定は max-age で証明書の有効期間を 1 年間 (60 × 60 × 24 × 365 = 31536000) 設定しています。max-age 以降はオプションとなり省略可能です。また、オプションを設定する場合は ; で区切って設定します。


includeSubDomains は、すべてのサブドメインにも設定を適用するという意味です。サブドメインを持たない場合は、省略しても問題ありません。


preload は、HSTS の特性上 "初回は HTTP 接続になる" 脆弱性を回避するオプションです。具体的には HSTS の一覧に Web サイトのドメインを登録しておき、初回接続時から HTTPS 接続にするようにします。HSTS の一覧への登録は、以下の URL から受け付けています。ただし、登録が受理されても処理されるまでに数週間かかります。


HSTS Preload Submission

Web サイト全体をリダイレクトする

Web サイトが新しいドメインに移転する場合は、Web サイト全体をリダイレクトします。例えば、以下の設定では oldsite.com/sample.html を newsite.com/sample.html にリダイレクトします。


# Web サイト全体をリダイレクトする設定例
Redirect 301 / http://newsite.com/
 Web サイト全体をリダイレクトする設定例

上記の設定が書かれた .htaccess は oldsite.com のトップディレクトリに配置して下さい。

URL から拡張子を消す (clean URL)

一般的に URL にはファイルの拡張子が含まれますが、拡張子を消すことでクリーンな URL であるように見せることができます。下記の設定では、ファイル名の拡張子が .php の場合に省略する設定例です。


# .php を省略する設定例
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^([^.]+)$ $1.php [NC,L]
 .php を省略する設定例

  http://example.com/page.php?id=123
  http://example.com/page?id=123

 .php が省略された例

メンテナンスページにリダイレクトする

Web サイトを更新中は、どのページを閲覧してもメンテナンスページを表示するサイトがあります。例えば Apple はメンテナンス中には "We'll be back." と表示することが恒例になっています。


ただし、単純にメンテナンスページを用意して、そのページにリダイレクトするだけでは十分ではありません。メンテナンス中に検索エンジンのクローラーが訪れた場合、メンテナンスページにリダイレクトされますが、HTTP ステータスコードが 200 となるため、コンテンツとしてキャッシュしてしまいます。また、HTTP 404 (Not Found:未検出) を設定すると、クローラーはサイトが無くなったものと判断し、インデックスから削除される場合があります。そのため、HTTP ステータスコードは 503 (Service Unavailable:サービス利用不可) を返すのが正しい方法です。


# HTTP ステータスコード 503 を返す場合に表示するページ
ErrorDocument 503 /maintenance.html

RewriteEngine On
RewriteCond %{REQUEST_URI} !=/maintenance.html
RewriteRule ^.*$ - [R=503,L]

# メンテナンス終了時間を設定する
Header set Retry-After "Fri, 1 Jun 2016 6:00:00 GMT"
 メンテナンスページにリダイレクトする例

セキュリティ関連のレシピ集

.htaccess のセキュリティとは、ユーザに適切なドキュメントを公開し、秘密のドキュメントは非公開にすることを指します。セキュリティ関連のレシピでは、ファイル一覧の非表示、ファイルへのアクセス制限、画像コンテンツなどの無断使用をブロック、指定したドメインのアクセスをブロックするなどのレシピを紹介します。

ディレクトリやファイルの一覧を非表示にする

ディレクトリの中に index.html などのデフォルトで表示されるファイルがない場合、ディレクトリやファイルの一覧が表示されます。ディレクトリの中に非公開としておきたいファイルが含まれている場合、一覧で表示されてしまうため、セキュリティ上のリスクとなります。


ディレクトリとファイルの一覧
ディレクトリとファイルの一覧


ディレクトリやファイルの一覧を非表示にするには、"Options" や "DirectoryIndex" を指定します。非表示の設定となっている場合は、デフォルトで表示するファイルが必要になります。もしも、デフォルトで表示するファイルが存在しない場合は、HTTP 403(Forbidden:閲覧禁止)エラーになります。さくらインターネットでは、Options の指定ができないため、DirectoryIndex を指定してデフォルトで表示するファイルを配置しましょう。


# ディレクトリやファイルの一覧を非表示にする
Options -Indexes

# ディレクトリにアクセスした場合 index.html をデフォルトで表示する
DirectoryIndex index.html
 ディレクトリやファイルの一覧を非表示にしてデフォルトで index.html を表示する

ディレクトリやファイルへのアクセス制限を行う

ディレクトリやファイルの一覧を非表示にしても、ファイル名を指定して直接アクセスされると簡単にアクセスできます。また、重要なファイルは推測しにくいユニークなファイル名になっていないため、"Password.txt" や "Access.log" など一般的なファイル名で何度も試行されるとHitする可能性があります。本来、重要なファイルはサーバに保管すべきではありませんが、特定のファイルへのアクセス制限を行うには、以下のように記述します。


# 特定のファイルや拡張子へのアクセスを制限する
<FilesMatch "^(\.htaccess|\.txt|\.xml)$">
  deny from all
</FilesMatch>
 特定のファイルや拡張子へのアクセスを制限する

また、特定のディレクトリへのアクセス制限を行うには "Deny from all" とだけ記述した .htaccess を指定のディレクトリに配置します。その際には、最終行に空行を含めることを忘れないように注意しましょう。アクセス制限となった場合は、HTTP 403(Forbidden:閲覧禁止)エラーを返します。


上記の例では、すべてのアクセスを拒否する簡単な設定ですが、細かくアクセスを制限することも可能です。アクセス制限の基本は "許可(allow)""拒否(deny)" の条件を指定することです。具体的な設定例は、以下のようになります。


# 特定のファイルや拡張子へのアクセスを制限する
<FilesMatch "^(\.htaccess|\.txt|\.xml)$">
  # 許可してから拒否
  Order allow,deny
  # すべてを許可
  allow from all
  # 以下のIPアドレス(192.168.*.*)を拒否
  deny from 192.168
  # 以下のホストを拒否
  deny from example.ne.jp
  # ブラウザのIEを拒否
  SetEnvIf User-Agent "MSIE" MSIE
  deny from env=MSIE
  # ・・・他に拒否する条件は漏れてないかな?(・ω・;
</FilesMatch>
 特定のファイルや拡張子へのアクセスを条件を満たした場合に拒否する

"Order" では許可と拒否の順番を指定しています。上記の例では、すべてのアクセスを許可しますが条件を満たす場合は拒否するという意味になります。"許可してから拒否する"設定は、拒否条件が漏れていた場合にセキュリティホールとなるため、やや甘い設定になります。そのため、以下のように"拒否してから許可する"設定が推奨されます。


# 特定のファイルや拡張子へのアクセスを制限する
<FilesMatch "^(\.htaccess|\.txt|\.xml)$">
  # 拒否してから許可
  Order deny,allow
  # すべてを拒否
  deny from all
  # 以下のIPアドレス(192.168.100.*)を許可
  allow from 192.168.100
</FilesMatch>
 特定のファイルや拡張子へのアクセスを条件を満たした場合に許可する

画像コンテンツなどの無断使用をブロックする

画像などのファイルの無断リンクを制御します。もしも HTTP リファラーが murashun.jp のドメイン以外の場合は、 HTTP ステータスコード 403 (Forbidden:閲覧禁止) を返します。


# 画像コンテンツなどの無断使用をブロックする
RewriteEngine On

RewriteCond %{HTTP_REFERER} !^$  
RewriteCond %{HTTP_REFERER} !^https://murashun.jp/.*$ 
RewriteRule \.(jpe?g|png|gif)$ - [F]
 画像コンテンツなどの無断使用をブロックする

指定したドメインのアクセスをブロックする

Google アナリティクスや、ウェブマスターツールなどで不審なドメインからのアクセスがある場合、HTTP リファラーを使ってブロックすることができます。正確なサイトの解析のためにはリファラースパムを排除する必要があります。また、.htaccess ではブロックできなかったリファラースパムのアクセス数は、Google アナリティクスのフィルタの設定によって排除することが可能です。


# 指定したドメインのアクセスをブロックする
RewriteEngine on
RewriteCond %{HTTP_REFERER} spam-domain.com
RewriteRule .* - [F]
 指定したドメインのアクセスをブロックする

上記のパターンは単一スパムのみブロックしていますが、リファラースパムと判明しているドメインはまとめてフィルタする例は以下になります。以下のリストは WordPress や Google のフォーラムで指摘されているリファラースパムの一覧です。


# 指定したドメインのアクセスをブロックする
SetEnvIfNoCase Referer baixar-musicas-gratis.com spammer=yes
SetEnvIfNoCase Referer descargar-musicas-gratis.com spammer=yes
SetEnvIfNoCase Referer evil-spam-domain.com spammer=yes
SetEnvIfNoCase Referer evil-spam-keyword spammer=yes
SetEnvIfNoCase Referer fbdownloader.com spammer=yes
SetEnvIfNoCase Referer hao123.com spammer=yes
SetEnvIfNoCase Referer kambasoft.com spammer=yes
SetEnvIfNoCase Referer poker spammer=yes
SetEnvIfNoCase Referer savetubevideo.com spammer=yes
SetEnvIfNoCase Referer semalt.com spammer=yes
SetEnvIfNoCase Referer srecorder.com spammer=yes
SetEnvIfNoCase Via evil-spam-proxy spammer=yes
SetEnvIfNoCase Via pinappleproxy spammer=yes

Order allow,deny
Allow from all
Deny from env=spammer
 指定したドメインのアクセスをブロックする

パフォーマンス関連のレシピ集

パフォーマンス関連のレシピは特別な事情がない限り設定することをお勧めします。ただし、パフォーマンスを向上させることは、何かとのトレードオフの関係 (例えば、サーバの CPU リソースなど) になります。そのため、レンタルサーバーなどを利用している場合は、管理会社側が禁止している設定もあるため、使えない場合があります。

コンテンツを gzip で圧縮する

gzip 圧縮とは、ファイルサイズを小さくする圧縮方法の1つです。gzip 圧縮を取り入れることで、ユーザと Web サーバ間でやりとりされている HTML ドキュメントのファイルサイズが小さくなり、転送速度が向上します。


# mod_deflate を有効にする
SetOutputFilter DEFLATE

# レガシーブラウザは gzip 圧縮を行わない
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

# 画像ファイルはgzip圧縮を行わない
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|ico)$ no-gzip dont-vary

# プロキシサーバ用の設定
Header append Vary User-Agent env=!dont-vary
 mod_deflate モジュールを有効にする(Apache 2.x)

ただし、さくらインターネットでは上記の記述方法では gzip 圧縮されません。 正攻法ではありませんが gzip 圧縮するためには、以下のように記述します。


# mod_deflate を有効にする
SetOutputFilter DEFLATE

# Accept-Encoding を無視して強制的に gzip を返す
SetEnv force-gzip
 さくらインターネットで mod_deflate モジュールを有効にする

コンテンツを gzip 圧縮する詳細は、gzip 圧縮によるサイトパフォーマンスを向上させる方法を参照して下さい。

FastCGI を使って CGI プログラムを高速化する

FastCGI とは、CGI プログラムの高速化、およびサーバの負荷を軽減するためのインターフェース仕様の 1 つです。サーバで CGI プログラムを実行した場合、"プロセスの起動"、"プロセスの実行"、"プロセスの終了" の処理が発生します。FastCGIでは、プロセスが起動して実行が完了しても、そのままプロセスの終了を行わず、一定時間サーバ内に保持します。そして、一定時間内に同じプログラムが起動された場合 "プロセスの起動" と "プロセス終了" を省略します。そうすることで、CGI プログラムの高速化や、サーバの CPU 負荷を軽減することが可能になります。


# FastCGI を有効にする
AddHandler fcgid-script .cgi
 FastCGI を有効にする設定例

ただし、さくらインターネットのレンタルサーバーでは FastCGI は利用できません。

mod_perl を使って Perl プログラムを高速化する

mod_perl とは、Apache の追加モジュールの 1 つで、Perl 言語で書かれたプログラムを高速に実行する機能です。mod_perl モジュールが Apache にインストール済みであれば、mod_cgi の代わりに mod_perl で Perl プログラムを高速に実行できます。通常、Perl プログラムは、呼び出される毎にコンピュータが実行できる形式 (オブジェクトコード) に変換しながら実行しています。しかし、mod_perl では変換が行われるのは最初の 1 回だけで、変換後のプログラムがキャッシュされるため、高速に動作します。mod_perl を .htaccess に記述する方法は "Registry" と "PerlRun" 2 種類のモードあり、どちらかを指定します。


# Registry を指定する方法
SetHandler perl-script
PerlHandler Apache::Registry
Options +ExecCGI

# PerlRun を指定する方法
SetHandler perl-script
PerlHandler Apache::PerlRun
Options +ExecCGI
 FastCGI を有効にする設定例

Registry モードでは、コンパイル後にプログラム自体がキャッシュされますが、PerlRunモードではキャッシュされません。Registry モードは PerlRun モードよりも高速ですが、コードの品質が求められます。具体的には、以下の 2 行をコードの先頭に追加してエラーメッセージが表示されずに動作すれば、Registryモードでも問題ありません。


use strict;
use warnings;

mod_perl の確認方法としては、$ENV{'MOD_PERL'} の環境変数の中身を確認する方法が一般的です。mod_perl が正しく入っていれば、バージョン情報を取得できます。


ただし、さくらインターネットのレンタルサーバーでは mod_perl は利用できません。

ブラウザのキャッシュを有効にする

ブラウザのキャッシュとは、Web ページを表示したときに取得したデータを一時的にローカルコンピュータに保存しておく仕組みのことです。次回以降、同じページにアクセスした場合、データを再度ダウンロードせず、ローカルコンピュータに保存されたデータを参照するためパフォーマンスが向上します。


ブラウザのキャッシュを有効にするには一般的に "Expires" または "Cache-Control" を使用します。両方記述した場合は、Cache-Control が優先されます。ブラウザのキャッシュについての詳細は、ブラウザのキャッシュよるサイトパフォーマンスを向上させる方法を参照して下さい。


# Expires を指定する方法
ExpiresActive On
ExpiresByType image/png         "access 1 year"
ExpiresByType image/x-icon      "access 1 year"
ExpiresByType text/css          "access 1 month"
ExpiresByType text/x-javascript "access 1 month"
ExpiresDefault                  "access 1 days"

# Cache-Control を指定する方法
<FilesMatch "\.(html|css|js|png|ico)$">
  Header set Cache-Control "private, must-revalidate"
</FilesMatch>
<FilesMatch "\.(png|ico)$">
  Header set Cache-Control "max-age=31536000"
</FilesMatch>
<FilesMatch "\.(css|js)$">
  Header set Cache-Control "max-age=2592000"
</FilesMatch>
 ブラウザのキャッシュを有効にする設定例

エラー処理関連のレシピ集

Web サイトを動かしていると、何らかの問題が発生することがあります。問題が発生した場合、ユーザが Web サイトから離脱しないようにすることが重要になります。エラー処理関連のレシピでは、エラーページをカスタマイズする方法などを紹介します。

文字化け対策を行う

文字化け対策を行うためには、.htaccess で設定を行う他にもいくつかの注意点があります。まずテキストエディタで HTML ファイルを作成しますが、ここで保存するときに文字エンコーディングを選択します。この保存時の文字エンコーディングがベースの文字コードとなります。一般的には、"UTF-8" (BOMなし) を選択します。


次に .htaccess で以下のようにデフォルトの文字コードを設定します。


# AddDefaultCharset の設定例
AddDefaultCharset utf-8
 AddDefaultCharset の設定例

通常は、上記までの設定でも問題ありませんが、AddType ディレクティブの設定で、extension (拡張子) に指定された MIME-type (MIME タイプ(Content-Type)) の関連付けを行うことができます。


# AddType の設定例
AddType "text/html; charset=UTF-8" .html
 AddType の設定例

Web サイトで使う文字コードは統一した上で、上記の設定を行うと文字化けを回避することができます。テキストエディタによっては、通常の文字コードが Shift_JIS で保存するものもあるため、気付かずに文字コードが異なる場合があります。その場合は、.htaccess の設定とあわせて、ファイルの文字コードも確認してみて下さい。

存在しないページを表示させない

Apache サーバの仕様では実際には存在しない URL でもページが表示される場合があります。例えば、ファイルを保存しているディレクトリ名がネストしている場合や、ディレクトリに 1 ファイルしか存在しない場合に発生します。


具体的には https://murashun.jp/top/example.html というファイルパスがあった場合、以下の存在しない URL でもページが表示されます。


  • https://murashun.jp/top/top/top/example.html
  • https://murashun.jp/top/top/top/
  • https://murashun.jp/top/example/
  • https://murashun.jp/top/example

上記のような存在しない URL に対して HTTP ステータス 404 エラー (Not Found) エラーを返すには、明示的に AcceptPathInfo ディレクティブで Off または Default を設定します。


# AcceptPathInfo の設定例
AcceptPathInfo Default
 AcceptPathInfo の設定例

存在しないページがブラウザに表示されます|さくらインターネット公式サポートサイト

エラーページをカスタマイズする

ファイルが見つからない場合など、WebサーバはHTTP 404(Not Found:未検出)エラーを返しますが、中身は無機質なテキストのページです。本来、エラーページは表示すべきものではありませんが、見えないところにもこだわるのがデザインです。"ErrorDocument" を利用すれば、HTTPステータスコードに応じたページを返すことができます。すべてのエラーに対応する必要はありませんが、代表的なエラーページは作成しましょう。


# エラーに対応する html を返す
ErrorDocument 403 /403.html
ErrorDocument 404 /404.html
ErrorDocument 500 /500.html
ErrorDocument 503 /503.html
 エラーに対応する html を返す

"ErrorDocument" + "HTTP ステータスコード" + "絶対パス or 相対パス" の形で記述します。未定義のHTTP ステータスコードが発生した場合は、デフォルトのページが表示されます。

その他

その他のレシピでは、上記のカテゴリに属さないレシピを紹介します。

タイムゾーンを設定する

タイムゾーンを日本時間に設定します。設定方法は、日本標準時か、地域のどちらかで設定します。


# JST (日本標準時) で設定
SetEnv TZ JST-9

# 地域で設定
SetEnv TZ Asia/Tokyo
 タイムゾーンの設定例

文字コードを設定する

不要な文字化けを回避するためにデフォルトの文字コードを設定します。拡張子ごとに文字コードを設定することもできます。


# デフォルトの文字コードを utf-8 に設定する
AddDefaultCharset utf-8

# 拡張子ごとに文字コードを設定する
AddDefaultCharset utf-8 .css .js
 デフォルトの文字コードを utf-8 に設定する

言語コードを設定する

デフォルトの言語コードを日本語に設定します。この設定により、コンテンツが何語で書かれているのかをブラウザに通知することができます。DefaultLanguage ディレクティブで設定できる言語は 1 つだけであることに注意して下さい。


# デフォルトの言語コードを ja に設定する
DefaultLanguage ja
 デフォルトの言語コードを ja に設定する

まとめ

.htaccess は非常に柔軟であるため、数々のレシピがあります。独自のレシピを組み上げるよりかは、既に使われていて実績のあるレシピを流用した方が無難です。このページでは、それらのレシピの中でも特に重要の高いと思われるリダイレクト、セキュリティ、パフォーマンス、エラー処理に関連したレシピを紹介しました。