Squid が付与する HTTP レスポンスヘッダの X-Cache や X-Squid-Error を消す方法。
squid.confg に以下を追加する。squid/2.5.STABLE13 ではこれで当該ヘッダの出力を抑制することができた。
Squid をリバースプロキシとして使用していて、内部のコンテンツサーバのホスト名などがクライアントに返ってしまうのを避けたい場合に使える。別に消す必要もないかなあと思ったが、サービスに直接影響のない情報は外部に出さないのが基本だし、とりあえず設定しておくことにした。でも、それでいて X-Powered-By: ASP.NET とか X-AspNet-Version: 2.0.50727 などといったヘッダは平気で出力してたりする。一貫性のない私。
squid.confg に以下を追加する。squid/2.5.STABLE13 ではこれで当該ヘッダの出力を抑制することができた。
header_access X-Cache deny all
header_access X-Squid-Error deny all
Squid をリバースプロキシとして使用していて、内部のコンテンツサーバのホスト名などがクライアントに返ってしまうのを避けたい場合に使える。別に消す必要もないかなあと思ったが、サービスに直接影響のない情報は外部に出さないのが基本だし、とりあえず設定しておくことにした。でも、それでいて X-Powered-By: ASP.NET とか X-AspNet-Version: 2.0.50727 などといったヘッダは平気で出力してたりする。一貫性のない私。
業務で SSL 対応のリバースプロキシを作ることになった。Squid とリダイレクタの Squirm を使って実現しようとしたが、Squirm 1.0betaB が POST メソッドに対応していないために別の構成をとることとなった。
第二候補は Apache 2.2 系 + mod_proxy だ。しかし、運用するマシンも OS も古いし、Apache を使ったリバースプロキシの運用ノウハウはあまりないため、Squid では役者不足の時だけお出まし願う予定。第三候補は Pound だが、これもノウハウがないので今回の案件ではまず使わないだろう。ちなみに運用マシンは Solaris 2.6。現在テスト中のマシンのスペックは以下の通り。
SSL の部分は透過的な SSL アクセラレータを別途利用する予定なので、Squid はとくに何もしない。
Squid は前の担当者がインストールしていた squid-2.5.STABLE12 を使う。安定版の最新は 2006年3月12日リリースの squid-2.5.STABLE13 だが、とくに問題がなければ squid-2.5.STABLE12 のまま運用に乗せる予定。
つまり、以下のように外向けの URL のパス部分を基準に中継先を決めるようにしたい。
example.jp/sonic64/ へのリクエストは sonic64.intranet.example.jp にリダイレクト。
example.jp/landscape/ へのリクエストは landscape.intranet.example.jp にリダイレクト。
この要件は Squid 単体では実現できないので、リダイレクタと呼ぶサブシステムと Squid を連携させて成し遂げる。今回はリダイレクタには Squirm (スクワーム) を使うことにした。採用の理由は解説しているウェブサイトがあったことと、ライセンスが GPL だから。Perl か C でリダイレクタを書いても良いんだけど、広く使われているものがあるならそっちの方がいい。
http://squirm.foote.com.au/
上記サイトから squirm-1.0betaB.tar をダウンロード。tar ball を展開した後は、サイトに書かれていた説明に従ってコンパイルとインストールを進める。
なんだか結構手間がかかるなあ。「configure script の動作について知って欲しいから」みたいなことが上記サイトに書かれてたけど、そういうことなのか。
正規表現ライブラリのコンパイルと make は終わった。しかし、いざ make install しようとしたらエラー。
install のオプションがおかしいの? 私は make はよく知らないんだけど、これはコマンドラインの指定の仕方がおかしいってエラーだよね。Squirm のサイトに書かれてる記述が変なのかな。それとも、私が使ってる make がおかしいのかな。そういえば、私の使っている make って GNU make じゃなくて Solaris の特別な make なの? 確認してみる。
以下の出力を見る限り、ごく普通の GNU make のようだ。
仕方がない。結局 make install がやってることって、ファイルのコピーとパーミッションの設定とかでしょう? というわけで、とりあえず手作業で /usr/local/squirm へファイルをコピーしてパーミッションを設定した。strip はやったんだっけ? まあとりあえずはどちらでもいいや。
squid.conf には以下のリダイレクタのための設定を追加。
Squid 起動。とりあえず何パターンかのリダイレクトを試してみたが、うまく動いているようだ。
しかし、ASP.NET + IIS 6.0 を動かしているサーバにリダイレクトしたときの挙動を確認しようとしたときに問題発生。どうも HTTP の POST メソッドによるリクエストがリダイレクトされていない模様。リダイレクタに処理が渡らず、Squid だけで処理しているように見える。これは Squid が悪いのか? Squirm が悪いのか?
squirm-1.0betaB の squirm.c の load_in_buff()
となると、Apache + mod_proxy を使うか、あとはリバース先のサーバ構成を変えるか、自分でリダイレクタを書くか。うーん。
いろいろ検討した結果、URL のパス部分を基準にした振り分けは要件として必須でないということになり、リダイレクタを使う必要はなくなった。つまり、Squid だけでよいということだ。
1.0BetaB から一気にバージョンが進んで 1.26 になってるわけだから、もしかして POST メソッドにも対応してるかもしれない。もう必要なくなったけど、一応 tar ball をダウンロードしてソースだけは見てみよう。
squirm 1.26 の squrim.c
上記を見る限り、Squirm 1.26 なら HTTP POST メソッドにも対応してるようだ。もしかしたら、対応しているように見せかけて、別のところでリダイレクトせずに素通ししてるかもしれないけど、さすがにそんなことはなさそう。POST 対応してるなら最初からこれ使えば良かったね。
- Squid を使って SSL リバースプロキシ
今回の案件で使うリバースプロキシソフトウェアの第一候補は Squid (スキッド) だ。他の担当者が作りかけていたということと、Squid なら組織内で利用している実績があって運用のノウハウ比較的もあるというのが理由。第二候補は Apache 2.2 系 + mod_proxy だ。しかし、運用するマシンも OS も古いし、Apache を使ったリバースプロキシの運用ノウハウはあまりないため、Squid では役者不足の時だけお出まし願う予定。第三候補は Pound だが、これもノウハウがないので今回の案件ではまず使わないだろう。ちなみに運用マシンは Solaris 2.6。現在テスト中のマシンのスペックは以下の通り。
$ uname -a
SunOS sonic64 5.6 Generic_105181-32 sun4u sparc SUNW,Ultra-1
$ dmesg
cpu0: SUNW,UltraSPARC (upaid 0 impl 0x10 ver 0x40 clock 200 MHz)
SunOS Release 5.6 Version Generic_105181-32 [UNIX(R) System V Release 4.0]
Copyright (c) 1983-1997, Sun Microsystems, Inc.
mem = 131072K (0x8000000)
avail mem = 125919232
SSL の部分は透過的な SSL アクセラレータを別途利用する予定なので、Squid はとくに何もしない。
Squid は前の担当者がインストールしていた squid-2.5.STABLE12 を使う。安定版の最新は 2006年3月12日リリースの squid-2.5.STABLE13 だが、とくに問題がなければ squid-2.5.STABLE12 のまま運用に乗せる予定。
- Squid + Squirm でリダイレクタ付きリバースプロキシ
いろいろな事情を検討した結果、外向けのドメインは一つにしておきたい。しかし、リバースプロキシは複数のドメインにリクエストを中継したい。つまり、以下のように外向けの URL のパス部分を基準に中継先を決めるようにしたい。
example.jp/sonic64/ へのリクエストは sonic64.intranet.example.jp にリダイレクト。
example.jp/landscape/ へのリクエストは landscape.intranet.example.jp にリダイレクト。
この要件は Squid 単体では実現できないので、リダイレクタと呼ぶサブシステムと Squid を連携させて成し遂げる。今回はリダイレクタには Squirm (スクワーム) を使うことにした。採用の理由は解説しているウェブサイトがあったことと、ライセンスが GPL だから。Perl か C でリダイレクタを書いても良いんだけど、広く使われているものがあるならそっちの方がいい。
- Squirm のコンパイルとインストール
Squirm - A redirector for Squidhttp://squirm.foote.com.au/
上記サイトから squirm-1.0betaB.tar をダウンロード。tar ball を展開した後は、サイトに書かれていた説明に従ってコンパイルとインストールを進める。
cd regex
./configure
make clean
make
cp -p regex.o regex.h ..
cd ..
make
なんだか結構手間がかかるなあ。「configure script の動作について知って欲しいから」みたいなことが上記サイトに書かれてたけど、そういうことなのか。
正規表現ライブラリのコンパイルと make は終わった。しかし、いざ make install しようとしたらエラー。
# make install
install -m 755 -o root -g root -d /usr/local/squirm \
/usr/local/squirm/bin
usage: install [options] file [dir1 ...]
make: *** [install] Error 2
install のオプションがおかしいの? 私は make はよく知らないんだけど、これはコマンドラインの指定の仕方がおかしいってエラーだよね。Squirm のサイトに書かれてる記述が変なのかな。それとも、私が使ってる make がおかしいのかな。そういえば、私の使っている make って GNU make じゃなくて Solaris の特別な make なの? 確認してみる。
以下の出力を見る限り、ごく普通の GNU make のようだ。
$ make -v
GNU Make version 3.78.1, by Richard Stallman and Roland McGrath.
Built for sparc-sun-solaris2.6
仕方がない。結局 make install がやってることって、ファイルのコピーとパーミッションの設定とかでしょう? というわけで、とりあえず手作業で /usr/local/squirm へファイルをコピーしてパーミッションを設定した。strip はやったんだっけ? まあとりあえずはどちらでもいいや。
- squirm.conf と squid.conf を設定して動作確認
squirm.conf に以下を設定。regex ^http://.*?/ivalice/(.*) http://ivalice.intranet.example.jp/\1
regex ^http://.*?/landscape/(.*) http://landscape.intranet.example.jp/\1
squid.conf には以下のリダイレクタのための設定を追加。
redirect_program /usr/local/squirm/bin/squirm
redirect_children 10
Squid 起動。とりあえず何パターンかのリダイレクトを試してみたが、うまく動いているようだ。
しかし、ASP.NET + IIS 6.0 を動かしているサーバにリダイレクトしたときの挙動を確認しようとしたときに問題発生。どうも HTTP の POST メソッドによるリクエストがリダイレクトされていない模様。リダイレクタに処理が渡らず、Squid だけで処理しているように見える。これは Squid が悪いのか? Squirm が悪いのか?
- Squirm は POST をリダイレクトしない
Squirm のソースを確認してみた。あー、なるほど。対応しているのは GET メソッドだけで、POST メソッドによるリクエストは受け付けないようになってる。Squid というより Squirm の仕様なのか。squirm-1.0betaB の squirm.c の load_in_buff()
/* all methods must be GET */
if((strcmp(in_buff->method, "") == 0) ||
(strcmp(in_buff->method, "GET"))) {
#ifdef DEBUG
log(LOG_DEBUG, "in_buff.method not \"GET\"\n",
in_buff->src_address);
#endif
return 1;
}
となると、Apache + mod_proxy を使うか、あとはリバース先のサーバ構成を変えるか、自分でリダイレクタを書くか。うーん。
いろいろ検討した結果、URL のパス部分を基準にした振り分けは要件として必須でないということになり、リダイレクタを使う必要はなくなった。つまり、Squid だけでよいということだ。
- Squirm は バージョン 1.26 が最新
今ふと Squirm のサイトを見ると、なんだかページの上の方に「Squirm は 1.26 が最新だよ。でも、ドキュメント書く暇がないよ。」みたいなことが書いてある。気づかなかった。Note: This web page documents version 1.0-BetaB. There is, in fact, a newer version: squirm-1.26, but I haven't documented it yet. This new version has some new features:
new squirm.conf file allows different redirection lists based upon different sets of source network addresses in CIDR notation.
Automagic accelerator string generation.
It compiles with a simple 'make'
A few other minor features.
Use your systems regex library
1.0BetaB から一気にバージョンが進んで 1.26 になってるわけだから、もしかして POST メソッドにも対応してるかもしれない。もう必要なくなったけど、一応 tar ball をダウンロードしてソースだけは見てみよう。
squirm 1.26 の squrim.c
/* match_method() returns 1 on match, 0 for no-match */
int match_method(char *method, int accept) {
lower_case(method);
/* match all first */
if (accept == ALL) {
return 1;
}
/* and then the most common */
if (strcmp(method,"get") == 0) {
return ((GET & accept) != 0 ? 1 : 0);
}
if (strcmp(method,"put") == 0) {
return ((PUT & accept) != 0 ? 1 : 0);
}
if (strcmp(method,"post") == 0) {
return ((POST & accept) != 0 ? 1 : 0);
}
if (strcmp(method,"head") == 0) {
return ((HEAD & accept) != 0 ? 1 : 0);
}
return 0;
}
上記を見る限り、Squirm 1.26 なら HTTP POST メソッドにも対応してるようだ。もしかしたら、対応しているように見せかけて、別のところでリダイレクトせずに素通ししてるかもしれないけど、さすがにそんなことはなさそう。POST 対応してるなら最初からこれ使えば良かったね。
ブラウザが ftp://ftp.ring.gr.jp/pub/linux/ に Squid 経由でアクセスするとき、
以下のようなリクエストが投げられる。
当然、ID/Password を指定することも可能。
アップロードするときは、PUT メソッドを使えば可能。ただし、私が使っている HTTP プロキシ経由では試してない。Netscape を使って LAN 内の ftp サーバ に対し PUT することはできた。
Squid 経由だと、FTP アップロードするときに Netscape は以下のようなリクエストを投げているようだ。
上記リクエストで、アップロード先のパスは PUT リクエストに含まれているけど、ローカルファイルのパスはどこで指定してるんだろうか? カレントのファイルが対象になるんだろうか?
もちろん、anonymous だと ftp.ring.gr.jp にアップロードはできないのでエラーになった。ちなみに Squid から返ってきたエラーは以下の通り。PUT を STOR に変換してるのがわかる。
追記。
2004-05-11 に「lftp で FTP Over HTTP Proxy」という記事を書いた。
以下のようなリクエストが投げられる。
GET ftp://ftp.ring.gr.jp/pub/linux/ HTTP/1.1
Host: ftp.ring.gr.jp
当然、ID/Password を指定することも可能。
GET ftp://anonymous:saitou-hiroaki%40example.com@ftp.ring.gr.jp/pub/linux/ HTTP/1.1
アップロードするときは、PUT メソッドを使えば可能。ただし、私が使っている HTTP プロキシ経由では試してない。Netscape を使って LAN 内の ftp サーバ に対し PUT することはできた。
Squid 経由だと、FTP アップロードするときに Netscape は以下のようなリクエストを投げているようだ。
PUT ftp://anonymous:saitou-hiroaki%40example.com@ftp.ring.gr.jp/pub/linux/Zip7Search.dll HTTP/1.0以下、ファイルの中身のデータがバイナリで続く。
Proxy-Connection: Keep-Alive
User-Agent: Mozilla/4.78 [en] (Windows NT 5.0; U)
Pragma: no-cache
Host: ftp.ring.gr.jp
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Encoding: gzip
Accept-Language: ja,en
Accept-Charset: iso-8859-1,*,utf-8
Content-Length: 6144
上記リクエストで、アップロード先のパスは PUT リクエストに含まれているけど、ローカルファイルのパスはどこで指定してるんだろうか? カレントのファイルが対象になるんだろうか?
もちろん、anonymous だと ftp.ring.gr.jp にアップロードはできないのでエラーになった。ちなみに Squid から返ってきたエラーは以下の通り。PUT を STOR に変換してるのがわかる。
HTTP/1.0 500 Internal Server Error
Server: Squid/2.2.STABLE5
Mime-Version: 1.0
Date: Thu, 24 Apr 2003 09:55:52 GMT
Content-Type: text/html
Content-Length: 896
Expires: Thu, 24 Apr 2003 09:55:52 GMT
X-Squid-Error: ERR_FTP_PUT_ERROR 0
X-Cache: MISS from unknown
Age: 286
Via: HTTP/1.0 hostname (Traffic-Server/4.0.19 [cMs f ])
エラー
FTP アップロードは失敗しました
以下の URL を PUT しようとした際に:
ftp://anonymous@ftp.ring.gr.jp/pub/linux/Zip7Search.dll
Squid は以下の ftp コマンドを送りましたが:
STOR Zip7Search.dll
このような結果を受け取りました.
Zip7Search.dll: Permission denied on server. (Upload)
この意味は次の通りです:
パス,パーミッション,ディスクの空き容量を確認し,再度試してください.
Generated Thu, 24 Apr 2003 09:55:52 GMT by unknown
(Squid/2.2.STABLE5)
追記。
2004-05-11 に「lftp で FTP Over HTTP Proxy」という記事を書いた。