UseCanonicalNameにご注意

UseCanonicalNameはOffにしておくほうが良いだろうという話です。

動作について

例えば以下のようなURLがあります。

http://xxx.xxx.xxx.xxx/directory


http://xxx.xxx.xxx.xxx/directory」がディレクトリであった場合、
Apacheが最後の"/"を補完しようとします。このときにリダイレクト(HTTPステータスコード301)が発生します。

http://xxx.xxx.xxx.xxx/directory (301)
        ↓
http://xxx.xxx.xxx.xxx/directory/ (200)


普段あまり意識することはないと思いますが、「UseCanonicalName」というディレクティブがあります。
このUseCanonicalNameが意外に曲者です。この設定次第で自己参照URLの結果が変わります。
環境によっては影響が出ることも。


ここから先はApacheに以下の設定がされているものとして話を進めます。


以下は「xxx.xxx.xxx.xxx:1080」でアクセスしたと想定します。

  • UseCanonicalNameがOnの場合の自己参照URL


「UseCanonicalName」がOnの場合、
httpd.conf に設定した「ServerName」「Port」を使ってURLを自己参照URLを生成します。


この場合の自己参照URLは以下になります。

www.example.com:1080


この条件でApache同梱のprintenvスクリプトを実行すると以下のようになります。
(今回関連する部分だけ抜粋)

 HTTP_HOST="xxx.xxx.xxx.10:1080"
 SERVER_NAME="www.example.com"
 SERVER_PORT="1080"
  • UseCanonicalNameがOffの場合の自己参照URL


「UseCanonicalName」がOffの場合、
クライアントがホスト名とポートを指定した場合、クライアントが提示した値を使って
自己参照URLを生成します。具体的にはHTTPのHostヘッダを利用するようです。
※Hostヘッダが指定されていない場合は、「UseCanonicalName On」と同じ動作をします。


この場合の自己参照URLは以下になります。

xxx.xxx.xxx.xxx:1080


こちらも同様にApache同梱のprintenvスクリプトを実行すると以下のようになります。

HTTP_HOST="xxx.xxx.xxx.10:1080"
SERVER_NAME="xxx.xxx.xxx.10"
SERVER_PORT="1080"
ロードバランサー配下における挙動を考える


上の結果を踏まえて、このサーバーがロードバランサー配下に設置されているケースを考えてみます。
「www.example.com」というホスト名がロードバランサーの仮想IPアドレスに登録されているケースです。

今度は「www.example.com」というホスト名でアクセスしたとします。

  • UseCanonicalNameがOnの場合の自己参照URL


この場合の自己参照URLは以下になります。

www.example.com:1080


先ほど同様にApache同梱のprintenvスクリプトを実行すると以下のようになります。

 HTTP_HOST="www.example.com"
 SERVER_NAME="www.example.com"
 SERVER_PORT="1080"
  • UseCanonicalNameがOffの場合の自己参照URL


こちらはクライアントから提示された値を使うため、
自己参照URLは以下になります。

www.example.com:80


こちらも同様にApache同梱のprintenvスクリプトを実行すると以下のようになります。

 HTTP_HOST="www.example.com"
 SERVER_NAME="www.example.com"
 SERVER_PORT="80"


例えば、ロードバランサーを使って負荷分散を行っている場合、待ち受けポートを変えることもあります。
そうした場合、注意が必要です。


具体的にはApacheが"/"を補完するためのリダイレクトを行った場合に問題が起きるケースがあります。
最初に示したように"/"をつけないでディレクトリにアクセスした場合、"/"を補完するために、リダイレクトが発生します。


リダイレクト先のURLは自己参照URLに基づき生成されるため、「UseCanonicalName On」の場合、
http://www.example.com:1080/directory/」となります。


リダイレクト先のリソースを再度取得しようとするものの、
このケースでは結果的にロードバランサーの仮想IPアドレスに対して1080番ポートでアクセスすることになります。
ロードバランサーの仮想IPアドレスで1080番でアクセスした際にも処理が出来るようになっていない限りは、
クライアントに対してリダイレクト後のリクエストを処理することができないケースが考えられます。


対外的に公開しているURLを全て"/"で終わるようにすればいいのかもしれませんが、
利用者の"/"付け忘れのケースもあると思いますので。


参考:


今日はこんなところで。