Pound が Header Buffer を 2KByte しか確保しない不都合
本業の Web サーバの構成について以前書いた記憶もあるのですが、Lighttpd や Apache2 の mod_proxy が流行る前に構築したこともあって、ちょっとだけ Pound が流行った?時によくある構成で組んでます。ザックリ図にしてみると
な感じになっています。で、前から薄々気がついてはいたのですが、この構成、致命的な欠陥があるんです。
その欠陥とは、pound の HTTP リクエストのヘッダ処理の実装にあります。pound のソースは適当にしか読んでいないので、間違ってる可能性もありますが、図にするとヘッダーのサイズ最大値の処理がこんな感じになっています。
ヘッダーの中でサイズが大きいと言えば、Cookie しかないですね。その Cookie に関しては RFC 2109 (set-cookieについて)と RFC 2965 (set-cookie2について)で定められています。恥ずかしながら set-cookie2 何てのは初めて知ったわけですが、ここでは一般的な set-cookie の仕様から実装仕様に関して RFC 2109 から抜粋しますと、
実用的なユーザエージェント実装はそれらが保存できるクッキーのサイズや数に制限を持つ。一般的に、ユーザエージェントのクッキーサポートは固定した制限を持つべきではない。それらは可能な限り頻繁に使用されるクッキーを保存するよう努めるべきである。さらに、一般使用のユーザエージェントは個々に以下の最小容量を用意すべきであるが、すべて必要と言うわけではない。
* 最低 300 個のクッキー
* 一つのクッキーあたり最低 4096 バイト (Set-Cookie ヘッダの構文記述での非末期クッキーを構成する文字列のサイズによる評価)
* 個々のホストもしくはドメイン名ごとに最低 20 個のクッキー
特定の目的もしくは制限された容量のデバイスに対して造り出されたユーザエージェントはユーザがセッションベースのオリジンサーバと相互に作用する事を保証するため、最低 4096 バイトの 20 クッキーを用意すべきである。
Set-Cookie レスポンスヘッダの情報はその完全体を保持しなければならない。もしクッキーを保存するために不十分な空間であるというような理由があれば、それは先頭を断ち切らずに破棄されなければならない。
アプリケーションは可能な限り少なく、小さなクッキーを使用すべきであり、クッキーの損失に潔くうまく対処すべきである。
と定められています。
これに照らし合わせると、Pound の実装は cookie の最大サイズ値 4KByte ってのが無視された実装になっています。早い話、2KByte 以上の Cookie 等の大きいヘッダーは途中でぶち切られるってことです。自分で 2K 以上の Cookie を発行していなくても(通常は発行してないでしょう・・・)複数のサービスが存在するポータル系みないな場合、同じドメイン内の Cookie を合計すると意外と 2K なんてのはオーバーしてしまうものです。
具体的にソースを見てみると、
悪さをしているのは pound.h(pound 1系もpound 2系も同じです)であることがわかります。
#define MAXBUF 2048 #define MAXHEADERS 128
解決方法 → MAXBUF を 4096 にして再コンパイルすれば何も問題は発生しません。
ちなみに、ココまで辿り着くのは結構時間がかかりまして、Apache のLimitRequestFieldSize ディレクティブの設定値がおかしいのか?それとも、Apache 1 系の mod_env.c とか mod_usertrack のソースでバッファの確保がおかしいのか?とか Apache や mod_perl 側の実装を疑ってソースを読んでたので気が付きませんでした。
以下、参考にしたページです。
- クッキーの最大サイズ制限について →(メモ)ブラウザ側の実装として、Cookie は4K〜5Kが上限
- RFC 2109 の和訳 →(メモ)Set-Cookie の仕様について
- RFC 2965 の和訳 →(メモ)Set-Cookie2 の仕様について
- Apache: LimitRequestFieldSizeディレクティブ →(メモ)HTTP リクエストのヘッダのサイズを制限
コメントやシェアをお願いします!
hnagoya
pound の情報調べていてこちらへやってきました。
Debian sarge でパッケージされている pound_1.8.2-1sarge1 では
MAXBUF 8192 という変更が入っていたのですが、こういう理由だったのですね。
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=293915
勉強になりました、どうもありがとうございます。