備忘録

【.htaccess】設定をサブドメインに継承させない方法

Apacheでは、<Directory>ディレクティブを用いて適用範囲を特定のディレクトリ下に限定することができます。

例えば、このような記述でhogeディレクトリへのアクセスを禁止することができます。

<Directory /hoge>
  deny from all
</Directory>

しかし<Directory>ディレクティブの使用が認められているのは、httpd.confの中だけです。

.htaccessには記述できません。

この記事は、httpd.confを弄れる環境に無い場合に.htaccessでなんとかしたメモです。

※なお上記の例であれば、該当ディレクトリに.htaccessファイルを作成しても解決できます。

解決法:Ifでドメインの一致を調べる

<If "%{HTTP_HOST} == 'example.com'">
  #example.comの場合のみ適用したいものを記述
</If>

前提

httpd.confでは全体を制御することができます。

このファイルを弄れる場合、恒久的な設定はこちらに記述したほうが良いと思われます。

しかし共有サーバーなどでhttpd.confを弄れる環境に無い場合、.htaccessファイルで個別に設定を行うことになります。

重要なことなのですが、.htaccessファイルは置いたディレクトリ以下全てに影響します。

正確には、あるファイルにアクセスすると、初めに同じディレクトリ内に.htaccessが無いか探した後、ドキュメントルートまで遡りながら、角ディレクトリで.htaccessファイルを探します。

つまりドキュメントルートに書いた設定は、ドメイン全体で有効になります。

なお重複する設定は、より近い(下層)の設定が優先されます。

Overrideのイメージです。

今回の問題

このサイトは、サブドメインでWordPressで運用しています。

そしてサブじゃないメインのドメインでは、WordPress非導入のサイトを作成しています。

このメインのドメイン下においてCSPでinlineのスクリプトを拒否する記述を.htaccessに行ったところ、WordPressの入っているサブドメインの方でinlineスクリプトの実行を拒否したとエラーが出てしまいました。

この原因は、ディレクトリ構成が以下のようになっていたからです。

public_html (←document root [example.com])
├index.html
├.htaccess
└sub (←WordPress [sub.example.com])
 └index.php

ご覧の通りですが、WordPressサイト(sub.example.com/index.php)へのアクセスは、実際の構成としては/public_html/sub/index.phpへのアクセスとなっているため、1つ上の階層のメインドメイン用の.htaccessファイルを参照することになってしまいます。

WordPressからinlineの記述を全て取り除いたり、subディレクトリ内に打ち消しの.htaccessファイルを置いたりしても解消はできますが、あまり良い方法ではありません。

もう1つの問題

検索が下手だったのでしょうか?

「htaccess 継承 防ぐ」や「htaccess サブドメイン 適用しない」など、それっぽいワードをいくつか入れてみても、解決策が見つかりませんでした。

特定ディレクトリ下でのみリダイレクトする方法の記事などが上位に来てしまい、目的の記事がヒットしません。

珍しく苦労しました。

その後英語で検索して<If>ディレクティブで解決できそうだということが分かったので、再度検索を続けたところ、最終的にこちらの記事に行きつきました。

参考:Apache 2.4 で使える If 文

解決

上の記事を参考に、例えばこのような形で<If>ディレクティブの中に記述を行うとメインのドメインのみにHeader setを適用することができました。

<If "%{HTTP_HOST} == 'example.com'">
  Header set Content-Security-Policy "script-src 'self';"
</If>

条件には=~で正規表現を使用することも可能です。

色々応用もできそうですね。