個人使用(しかもクライアント 1(汗))において Proxy サーバをたてるメリットなんて無いんじゃないの? 否、Inernet Explorer のオフライン機能、大変便利です。でもいちいちオフラインモードに切り替えるのも面倒です。 IE5 Power Tweaks Web Accessory を利用すればツールバーのトグルアイコンで一発ですが、「切り替える」と言うことを常に意識するためこれもある意味面倒です。 それにダイアルアップなので IE で見たページを回線切ってから NN でも見れるじゃないですか。(←メリットなのか?)
そういうわけでネットワークトラフィック軽減に貢献するために Squid を導入してみました。
squid 2.3STABLE4 と全く同様にインストール。2.4 STABLE1 用の自作パッチを作らねば...
squid は ftp プロトコルも処理できますが、何故かアイコン群が not_found 状態になっています。(→図1) どうやらこれは既知のバグで、既に 対応パッチ が出ています。 patch を当てた squid で 図1 をリロードしたものが 図2 です。きちんとアイコンが表示されていますね。
→ | ||
図1 | 図2 |
---|
cache_peer で ISP のプロキシサーバを親に設定しているにもかかわらず 診断くん で調べてみると、HTTP_VIA に自分で立てた squid のバージョンしか表示されない。 どうやら今まで大丈夫だと信じ込んでいた設定が全く役に立っていないみたい。トホホ。 これでは REMOTE_HOST でホスト名がばれてしまうのできちんと設定を見直す。
never_direct allow all
結局、always_direct の記述や never_direct 直前に重複して記入していた acl も全て削って、
単に never_direct allow all を記述することにより目的達成。でも HTTP_X_FORWARDED_FOR だと IP バレバレ。
全てのクライアントは直接(自分のsquidで)取りに行かない -> 親 squid を必ず通す、と言うことでしょうか。
configure オプションに enable-err-language=Japanese を付けてコンパイルするとエラー画面がジャパナイズされるそうです。 このためだけにリコンパイルするのもヤなので、
# cp -f /usr/local/src/squid-2.3.STABLE4/errors/Japanese/* /usr/local/squid/etc/errors/
としたら OK でした。次回コンパイルする際は付け忘れないようにしよう。
squid-2.3.STABLE4-src.tar.gz をインストール。手順は一緒。
squid-2.3.STABLE2-src.tar.gz を拾ってきて何も考えず適当なディレクトリに展開して configure → make → make install。 tar ball からだとデフォルトのインストール先は /usr/local/squid 以下になるようだ。 このままだと旧バージョン(/usr/sbin/squid)が動いてしまうのでとりあえず旧バージョンを適当なところに隠して /usr/local/squid/bin をパスに追加。 squid.conf も /etc/squid/squid.conf から /usr/local/squid/etc/squid.conf へ移動。
どうやらデフォルトではログやキャッシュなど全て /usr/local/squid 以下で行うようになっているみたいなので、 なんとなくコレでは今まで作ったディレクトリが無駄そうなので squid.conf のパス関係を変更。
cache_access_log /var/log/squid/access.log cache_log /var/log/squid/cache.log cache_store_log /var/log/squid.store.log pid_filename /var/run/squid.pid
2.2.x では何も考えずに /usr/sbin/squid を起動すれば squid と共に squid.conf に指定された数(デフォルト 5)だけ DNS を引くプロセス unlinkd が起動されていましたが、2.3.STABLE2 では /usr/local/squid/bin/RunCache スクリプトによって起動するようです。
直接 squid を起動せずに RunCache を起動する理由は、なんらかの原因で squid が死んでしまっても、 RunCache がそれをチェックして再び起動し直してくれるからだそうです。便利。
# rpm -Uvh squid-2.2.STABLE4-0.5.2.rpm でインストール。
squid-2.3.STABLE4 には FTP ディレクトリアイコンの非表示バグなどに対する いくつかのパッチ が出ていますので、それらを当ててからコンパイルします。 先のページから取得した squid-2.3.stable4-*.patch を /usr/local/src/squid-2.3.STABLE4/ 以下にコピーします。 そしてパッチを当ててコンパイル、インストールします。
なお、匿名化 に記述した squid.conf による HTTP_HEADER の隠蔽方法では隠しきれない HTTP_VIA や HTTP_X_FORWARDED_FOR, Cache-Control 等を塞ぐため、http.c の該当部分をコメントアウトしたパッチ を作ったのでそれも当てています。
# pwd /usr/local/src/squid-2.3.STABLE4/ # for file in *.patch > do > patch -p0 < $file > done patching file `src/client_side.c' patching file `src/carp.c' patching file `src/store.c' patching file `src/http.c' patching file `lib/html_quote.c' patching file `lib/Makefile.in' patching file `include/util.h' patching file `src/errorpage.c' patching file `src/ftp.c' patching file `src/gopher.c' patching file `src/dns_internal.c' patching file `src/acl.c' patching file `configure' patching file `configure.in' # ./configure --enable-err-language=Japanese ... # make all; make install
configure のオプション (--enable-err-language=Japanese) はその名の通りですが、エラーファイルを日本語にするという意味です。
squid が利用するスプールディレクトリを作成し、初期化します。
# mkdir /var/spool/squid # squid -z /var/spool/squid
ユーザー「squid」を作成し、スプールディレクトリの所有者を squid に変更します。
# adduser squid # chown -R squid.squid /var/spool/squid
以下、/usr/local/squid/etc/squid.conf についての最低限の設定を行います。
キャッシュの設定を行います。私の場合はディスクキャッシュを /var/spool/squid 以下に 1GB、メモリキャッシュを 128MB にします。
cache_dir /var/spool/squid 1000 16 256 cache_mem 128 MB
コメント部分を読めば分かりますが cache_dir のエントリは、
となっています。ディレクトリとサイズ以外はいじることはないでしょう。cache_mem の値、数値と単位(MB)の間にスペースを忘れずに。(ハマりました)
cache_mem で指定するメモリは squid 本体が動作するメモリの総計ではなく、キャッシュに対して割り当てるメモリ容量です。
cache_peer 202.26.1.156 parent 10082 13130
ウチの ISP の proxy(squid) は ICP ポートを公開 しているので ISP の proxy を親 proxy として利用させてもらいます。 DNS を参照することを考えるとホスト名ではなく IP アドレスの方が良さそうなので nslookup で ISP の proxy サーバーの IP アドレスを割り出してそれを指定しています。
次の設定では必ず親プロキシを通してアクセスするように設定します。ここでの all はアクセス制御での acl 名(全てのアドレス)です。
never_direct allow all
踏み台にされないようにアクセス制限を設けます。まず始めにアクセスリストを定義します。 ここでは localnet という名前で LAN を定義します。
acl all src 0.0.0.0/0.0.0.0
acl manager proto cash_object
acl localhost src 127.0.0.1/255.255.255.255
acl localnet src 192.168.1.0/255.255.255.0 ←追加
続いてこの定義した名前でアクセス制限をします。deny all の前に記述しないとダメみたいです。
# # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS # http_access allow localhost ←追加 http_access allow localnet ←追加 http_access deny all
squid を起動するには直接 squid を起動するのではなく、RunCache というシェルスクリプトを介して起動します。 こうするとにより、設定ファイルを再読込させるために squid を殺した場合や、 何らかの原因で squid が死んでしまったりした場合に、 常駐している RunCache がそれを検知して再び squid を起動してくれます。
# RunCache & [1] 4668 # Running: squid -sY >> /usr/local/squid/squid.out 2>&1
設定ファイルにエラーがあると squid の起動に失敗し、RunCache は 5 回ほど起動を試みたのちに諦めます。
squid に含まれる client プログラムを使って動作を確認します。
# /usr/local/squid/bin/client http://localhost/index.html ←任意の有効な URL を指定 HTTP/1.0 200 OK Date: Fri, 03 Nov 2000 11:11:38 GMT Server: Apache/1.3.14 (Unix) PHP/3.0.18-i18n-ja Content-Location: index.html Vary: negotiate,accept-language,accept-charset TCN: choice Last-Modified: Sat, 14 Oct 2000 14:12:15 GMT (以降省略)
エラーが出て上手くいかない場合は acl の再確認と、ログファイル(/usr/local/squid/logs/*.log)をよく見ましょう。
そして外部からの接続を拒否出来ているかどうか、Proxy Checker でチェックしてみましょう。
1 リクエストにつき 1 行吐き出す squid のログは気が付くと莫大なサイズになってしまいます。 squid に USR1 シグナルを送るとログを rotate するそうですので以下のように cron に設定します。
23 4 * * 0 /bin/kill -USR1 `cat /var/run/squid.pid`
なお、# squid -k rotate でも rotate 出来るそうです。コッチの方がスマートでしょうか。
squid のログは 10 のフィールドを持ち、HTTP, ICP の問い合わせ毎に 1 つのエントリがあり、 クライアントのソケットが閉じられる毎に記録されるようです。
Timestamp | TCP 接続の閉じられた時間。ミリ秒まで含まれる、1970/1/1 から始まる ``UNIX 時間''。 |
---|---|
Elapsed_Time | ミリ秒単位での要求の経過時間。TCP 接続の、accept() から close() までの時間。 |
Client_Address | 接続されたクライアントの IP アドレス。 |
Log_Tag | ローカルで要求がどう処理されたかどうか(HIT, MISS, etc.)。 |
HTTP_Code | HTTP 応答ヘッダの最初の行から得られるコード。ICP 要求には 0000 が返される。 |
Size | クライアントに書き出されたバイト数。 |
Request_Method | HTTP 要求手段。GET もしくは POST。ICP 要求の場合は ICP_QUERY。 |
URL | 要求された URL。 |
Ident | 設定ファイルの ident-lookup が on の場合、接続されたクライアントで要求を行ったユーザー名。 |
Hierarchy_Data/Hostname | どのように、何処から要求されたオブジェクトを持ってきたのか。 |
Content_Type | お馴染み、HTTP 応答中の Content-Type。 |
access_log 中の Log_Tag 情報です。
TCP_HIT | 要求されたオブジェクトの有効なコピーがキャッシュに存在。 |
---|---|
TCP_MISS | 要求されたオブジェクトの有効なコピーがキャッシュに無かった。 |
TCP_REFRESH_HIT | オブジェクトはキャッシュにあったが、新鮮ではなく、If-Modified-Since 要求がなされ、"304 Not-Modifide" 応答を得た。 |
TCP_REFRESH_MISS | オブジェクトはキャッシュにあったが、新鮮ではなく、If-Modified-Since 要求がなされ、応答に新たなコンテンツが含まれていた。 |
TCP_REF_FAIL_HIT | オブジェクトのキャッシュにあったが、新鮮ではなく、オブジェクトの有効性の要求に失敗したため、古い(新鮮ではない)オブジェクトが返された。 |
TCP_CLIENT_REFRESH | クライアントが "no-cache" を付けて要求を送ってきた。 |
TCP_IMS_HIT | クライアントは If_Modified-Since 要求を送ってきて、オブジェクトがキャッシュ内にあり、かつ、まだ新鮮だった。 |
TCP_IMS_MISS | クライアントは If_Modified-Since 要求を送ってきたが、オブジェクトは新鮮ではなかった。 |
TCP_SWAPFAIL | オブジェクトはキャッシュ内にあるはずであったが、アクセスできなかった。 |
TCP_DENIED | この要求に対するアクセスは拒否された。 |
UDP_HIT | 要求されたオブジェキュとの有効なコピーはキャッシュに存在。 |
UDP_HIT_OBJ | UDP_HIT と同じだが、オブジェクトデータが UDP 応答パケットで送れるほど十分に小さく、これに続く TCP 接続要求を省く。 |
UDP_MISS | 要求されたオブジェクトはキャッシュに無かった。 |
UDP_DENIED | この要求に対するアクセスは否定された。 |
UDP_INVALID | 正しくない要求を受信した。 |
UDP_RELOADING | キャッシュがそのメタデータの再転送をするには忙しいので、ICP 要求が否定された。 |
親 proxy への問い合わせステータス?
DIREDT | オブジェクトをオリジナルサーバーに直接要求した。 |
---|---|
FIREWALL_IP_DIRECT | 発信元のホスト IP アドレスがファイアーウォール内部にあるため、オブジェクトオリジナルサーバーに直接要求した。 |
FIRST_PARENT_MISS | オブジェクトを、往復時間がもっとも短くなるよう、重みを付けられた親キャッシュに要求した。 |
FIRST_UP_PARENT | オブジェクトをリストの中の最初の有効な親キャッシュに要求した。 |
LOCAL_IP_DIRECT | サーバホスト IP アドレスが local_ip リストと一致したため、オブジェクトをオリジナルサーバに要求した。 |
SIBLING_HIT | オブジェクトをその URL に割り当てられた親キャッシュに要求した。 |
NO_DIRECT_FALL | ファイアーウォールの制限と親キャッシュが有効でないため、オブジェクトを要求しなかった。 |
SOURCE_FASTTEST | source_ping 応答が最初に到着したため、オブジェクトをオリジナルサーバに要求した。 |
PARENT_UDP_HIT_OBJ | オブジェクトは親キャッシュからの UDP_HIT_OBJ 要求から得られた。 |
SIBLING_UDP_HIT_OBJ | オブジェクトは兄弟キャッシュからの UDP_HIT_OBJ 要求から得られた。 |
PASSTHROUGH_PARENT | 設定オプション passthrough_proxy に定義された近隣サーバまたはプロキシサーバかが使用された。 |
SSL_PARENT_MISS | 設定オプション ssl_proxy に定義された近隣サーバまたはプロキシサーバが使用された。 |
DEFAULT_PARENT | ICP 問い合わせが親キャッシュに送られず、設定ファイルで default となっていたため、この親が選択された。 |
ROUNDROBIN_PARENT | 親キャッシュからの ICP 問い合わせを受信せず、設定ファイルで default となっていて、もっとも低いラウンドロビンカウントであったため、この親が選択された。 |
CLOSENT_PARENT_MISS | オリジナルサーバへのもっとも低い RTT 測定値を持っていたため、この親が選択され、設定ファイル中で query_icmp がセットされた時のみに現れる。 |
CLOSENT_DIRECT | このキャッシュが他の親オブジェクトより RTT が小さかったため、オブジェクトはオリジナルサーバから直接取ってきた。 |
ちなみに ISP を親キャッシュにして Yahoo JAPAN にアクセスしたときのログはこのようになっています。
973996261.818 1759 192.168.1.9 TCP_CLIENT_REFRESH_MISS/304 181 GET http://img.yahoo.co.jp/images/main6.gif - FIRST_UP_PARENT/202.26.1.156 - 973996262.988 2740 192.168.1.9 TCP_MISS/200 3225 GET http://img.yahoo.co.jp/adv/artmaster/20001106/pseat330-a.gif - FIRST_UP_PARENT/202.26.1.156 image/gif 973996263.018 2753 192.168.1.9 TCP_CLIENT_REFRESH_MISS/304 181 GET http://img.yahoo.co.jp/images/new2.gif - FIRST_UP_PARENT/202.26.1.156 - 973996263.038 1220 192.168.1.9 TCP_CLIENT_REFRESH_MISS/304 181 GET http://img.yahoo.co.jp/images/clear.gif - FIRST_UP_PARENT/202.26.1.156 - 973996263.328 4621 192.168.1.9 TCP_MISS/200 21476 GET http://www.yahoo.co.jp/ - FIRST_UP_PARENT/202.26.1.156 text/html
特定のサイトにはプロキシを使わない設定など、ブラウザ毎に毎回毎回設定しますが、 自動起動スクリプトを使用することによりサーバで一元管理する事が出来ます。
まずはこの自動設定スクリプトを提供する Web サーバ(ここでは Apache)を用意しなければなりません。 そして Apache の mime.types に自動スクリプトの定義(Proxy Auto Config)を加えます。
# echo "application/x-ns-proxy-autoconfig pac" >> /usr/local/apache/conf/mime.types
次に自動起動スクリプトの作成。
function FindProxyForURL(url, host) { if (isPlainHostName(host)) { return "DIRECT"; } if (dnsDomainIs(host, "192.168.1.")) { return "DIRECT"; } return "PROXY 192.168.1.1:3128; DIRECT"; }
これは LAN (192.168.1.0/24)は直接見に行って、それ以外は proxy(192.168.1.1) に取ってきて貰うという設定です。 スクリプトの詳細は Navigator Proxy Auto-Config File Format でどうぞ。 このファイルを適当な場所、私の場合は Apache のドキュメントルートに proxy.pac として保存します。
クライアント側では自動起動スクリプトへの URL を記述します。
私の環境では proxy サーバが動作している端末のポート 80 を外部公開用 Apache へ fowarding している関係で proxy.pac 提供用の Apache をポート 10080 で動かしています。
きちんと自動設定スクリプトで proxy が利用できているか 診断くん でチェック。
あなたの環境変数をちょっとだけ表示してみます。
どうですか、表示されたくない情報がありますか?
私は proxy に繋いでいるクライアントの IP アドレス(HTTP_X_FORWARDERD_FOR)はあまり表示して欲しくありません。
# と言ってもこの Linux のページでバレバレですが(^^;
環境変数 | 値 | コメント |
---|---|---|
REMOTE_HOST | ページリクエスト元ホスト名。 | |
REMOTE_ADDR | ページリクエスト元 IP アドレス。 | |
HTTP_USER_AGENT | クライアントユーザーエージェント文字列 | |
HTTP_REFERER | ページ参照元 URL | |
HTTP_X_FORWARDED_FOR | proxy 経由時のクライアント IP アドレス。 | |
HTTP_VIA | proxy 経由時の proxy サーバ情報。 |
proxy というと匿名性(よく言えば透過性?)を求める要望があるでしょうから、ここでは squid で簡単にできる設定を紹介します。 各セクション近辺のコメントを見れば分かりますが、HTTP_* な環境変数はほぼ全て squid.conf で潰すことが可能なようです。
それにしても私のページのアクセスログにあった Nutscrape/1.0 (CP/M; 8-bit) って何だろう?と気にしていたけど、 squid.conf に書かれていたのね(^^;
表示したくない環境変数 | 対応セクション | コメント |
---|---|---|
HTTP_VIA | visible_hoastname unknown | プロキシサーバーのホスト名。空だと squid 起動不可。 |
HTTP_X_FORWARDED_FOR | forwarded_for off | クライアントの IP アドレスの表示設定。off で非表示 |
HTTP_REFERER | anonymize_headers deny From Referer Server | 参照元 URL の非表示。 |
HTTP_USER_AGENT | anonymize_headers deny User-Agent | クライアントのユーザーエージェント文字列の非表示。 |
任意の HTTP_USER_AGENT | fake_user_agent | ここで設定する文字列が HTTP_USER_AGENT になる。 |
squid.conf の設定で HTTP_X_FORWARDED_FOR も潰せると思ったのですが、「unknown」という文字列が出てしまい結局漏れてしまっているみたいです。 他にも Cache-Control の値も proxy サーバとして見なされる変数の一部らしいのですがこれも潰す手だてが見つかりません。
しかし考えてみたら設定ファイルで潰せないならソースで出力しないようにすればいいわけですよね。 調べてみると、どうやら http.c というファイルが HTTP ヘッダを出力しているそうなのでじっくりと眺めてみました。 すると httpHeaderPutStr() でいろいろと HTTP ヘッダに出力してるのが伺えます。 目的は HTTP_VIA, X_FORWARDED_FOR, Cache-Control の隠蔽なので、それらを出力している部分をコメントアウトしました。 そして幾度となく来るであろう再インストールに備え、 差分をパッチとして作成 しました。
しかし、ISP の親 proxy を利用しているので結局バレバレ。 って、本来の目的はオブジェクトのキャッシュによる体感速度の向上、 これが満たせている(と思う)ので OK。
いくつかの環境変数を隠蔽するためのパッチを作成しました。物好きな方はご利用下さい。当然ノークレーム。フィードバック大歓迎。
対応バージョン | patch | コメント |
---|---|---|
squid 2.4STABLE1 | squid-2.4.stable1-hide_proxy_info.patch | 2.3STABLE4 用の patch と同じ部分をコメントアウト。 |
squid 2.3STABLE4 | squid-2.3.stable4-hide_proxy_info.patch | HTTP_VIA, X_FORWARDED_FOR, Cache-Control の出力をコメントアウト。 | squid-2.3.stable4-error_page_signature_hack.patch | 単なる自己満足。エラー画面のホスト名を隠蔽。(でもツールチップで分かる) |
エラー画面の出力時刻がローカルタイムに出来ないかなぁ...+9 すりゃいんだけど、C わからん(^_^;
proxy.pac で記述した proxy を通さないドメインの設定が上手くいかない。
さらに、これはローカルで立ち上げている DNS の問題だと思うが、ブラウザのプロキシ設定で IP アドレス直打ちでないと適用されない。
ローカル DNS できちんと正/逆引きが確認できるホスト名を指定しているにも関わらず...
Squid Web Proxy Cache
squid のソースはここから取得。パッチも忘れずに。
SQUID Frequently Asked Questions (Japanese)
Squid FAQ の日本語版。つまずく前に一読を。
Squid 情報@ksakai さん
Squid に関する様々な情報や統計ツールへのリンクがあります。
Squidメモ(2.3対応)@Que さん
Squid の導入、transparent proxy の設定まで、幅広い情報が得られます。
Squid@奥村晴彦さん
Squid の設定、acl、transparent proxy、Squid ログ解析ツールなどがあります。
squid.confの日本語訳
Squid 2.x の細かなチューニングがしたいけど英語は...という方は是非。
環境変数のお話
環境変数について詳しく説明されています。匿名化をするにあたり大変参考になりました。
ヤリイカ3分クッキング
ネーミングがスキです(笑)