最終更新日: 2014年1月13日
Squid Home / FAQトップ

17. 透過プロキシ/キャッシュ
(Interception Caching/Proxying)


どのようにすれば、ユーザに設定させる事無くブラウジングの際に私のプロキシキャッシュを使わせることができますか?

最初に、まずはsquid.confのコメントを読んでください。 それがもっとも信頼すべき情報です。 しかし以下に示す方法は1999/7現在では正しい筈です。

透過プロキシ/キャッシュを構成するには以下の4つの手順を踏む必要があります:

  1. 他のアドレスであっても受け付けるバージョンのSquidをコンパイルして実行してください。
    幾つかのオペレーティングシステムでは、接続をハイジャックして宛先アドレスを見分けるようにシステムを構成する必要があります。 Linuxではこれは自動的に行われます。 *BSDベースのシステムではおそらく --enable-ipf-transparent オプションをつけて Squid を構成する必要があります。 (以前に Squid をこ構成しているなら make clean で構成をきれいにしてから実行してください)
  2. Squid の設定で接続を受け入れるようにします。
    あなたはSquidの設定を変更して接続をハイジャックして宛先アドレスを見分けるようにしなくてはいけません。 squid.conf での重要な設定項目は:
    http_port 8080
    httpd_accel_host virtual
    httpd_accel_port 80
    httpd_accel_with_proxy on
    httpd_accel_uses_host_header on
  3. あなたのキャッシュサーバでパケットを受けられるようにしてください。 
    あなたのキャッシュホストはどんな宛先であってもポート80のパケットを受け入れるように構成しなくてはなりません。 もしかするとIPフィルタリングがカーネルに組み込まれていて、これを使ってすべてのポート80のパケットを受け入れるようできるかも知れません。 Linuxではこれはiptables(カーネル2.4)、ipchains(2.2)またはipfwadm(2.0)、FreeBSDではipfwyaと呼ばれています。 他のBSDベースのシステムでは ip filter や ipnat と云われているかもしれません。
    (FreeBSD3.xからはipfwでなく ip filter や ipnat がサポートされています)
  4. キャッシュサーバにパケットを送ってください。
    これには幾つかの方法があります。 第1に、もしあなたのプロキシマシン常にパケットが通る位置(パケットパス)にある(例えばプロキシマシンがインターネットへのルータとして機能している)ならあなたは何もしなくて構いません。
    もし、プロキシがパケットパス上にないなら、ルータやスイッチをつかってパケットをプロキシへ集める必要があります。 あなたがCISCOのルータを使っているなら、IOSの"route maps"機能で実現できるかも知れません。 また、あなたは Alteon ACE-director や Foundry Networks 社等の Layer-4 と呼ばれるスイッチを使うことで集めることもできます。 最後として、スタンドアロンのルータやロードバランサ製品やルーティング機能を持ったクセスサーバなどを使うこともできるでしょう。

注意:

17.1 Solaris, SunOS, BSDシステムによる透過プロキシ/キャッシュ

メモ: FreeBSD3.x以前ではip filterではなく代わりに内蔵の ipfw 機能を使ってください。 後述のFreeBSD節を参照してください。FreeBSD3.0以上では、以下のように設定できます。

■ IPフィルターのインストール

もし既に、 IP Filter パッケージ がインストールされていないならこれを入手してインストールしてください。(FreeBSDを普通にインストールするとipフィルターはインストールされています)

■ ip-filter の設定

ip-filterを設定して、プロキシマシンでポート80のパケットを受け取れるように設定してください。 以下ではテストの為、すべてのパケットを受け入れるルールを設定します。

/etc/ipf.rules に対する設定

#
pass in all
pass out all

なお実際のフィルタルールは使う環境に合わせて安全な設定を行ってください。

ip-filterがシステム起動時に設定されるように起動スクリプトを設定してください。
FreeBSD3.x以降では、/etc/rc.conf ファイで以下のように記述します。

ipfilter_enable="YES"
ipfilter_rules="/etc/ipf.rules"
ipfilter_flags=""

■ ipnatの設定

/etc/ipnat.rules に対する設定:

# Redirect direct web traffic to local web server.
rdr de0 192.168.1.2/32 port 80 -> 192.168.1.2 port 80 tcp
# Redirect everything else to squid on port 8080
rdr de0 0.0.0.0/0 port 80 -> 192.168.1.2 port 8080 tcp

ここで、de0 はLANインターフェース名なのでifconfigコマンドで、インターフェース名は確認してください。 

この例では、自分宛のhttpパケット(80)はそのまま自分自身のWebサーバに渡して以外のパケットを8080へ渡すように設定しています。 それ以外のアドレス宛の80ポートへのパケットは8080へリダイレクトします。
(もしかしたら、apacheなどの受付ポートを81とかにして、最初のルールを

rdr de0 192.168.1.2/32 port 80 -> 192.168.1.2 port 81 tcp

とかにする方がより良いかも知れません。)

スタートアップスクリプトを編集してipnatを有効にします。 例えばFreeBSDでは/etc/rc.conf で次のように指定します:

ipnat_enable="YES"
ipnat_program="/sbin/ipnat -CF -f" file
ipnat_rules="/etc/ipnat.rules"
ipnat_flags=""
ip-filterとipnatの設定が終わった一度リブートして設定を有効にしてください。 設定ができているかは、
# ipfstat -i
# ipfstat -o
# ipnat -l

で確認できます。

■ Squidの設定

Squid-2の場合:

Squid-2(beta25以降)ではIPフィルターをサポートします。 この為には configure を次のように実行します。

./configure --enable-ipf-transparent

そして squid.conf で次のように指定します。

http_port 8080
httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_with_proxy on
httpd_accel_uses_host_header on

Note: ポートは8080でなくても構いませんが、必ず /etc/ipnat.rules での指定を合わせてください。

Squid-1.1の場合:

Quinton Dolan's Squid page.によるパッチを適用することでSquid-1.Xも利用できます。 squid.conf では次のように指定します。

http_port 8080
httpd_accel virtual 80
httpd_accel_with_proxy on
httpd_accel_uses_host_header on
Quinton Dolan.、ありがとう。

17.2 Linux 2.0 と ipfwadm での透過プロキシ/キャッシュ

Rodney van den Oever による

注意: 透過プロキシ/キャッシュはLinux 2.0.30では動かない。 Linux 2.0.29で十分に動作する。もしあなたが最近の 2.2.xのカーネルを使うなら ipchains で構成すべきです。 これについては後述します。

警告: このテクニックにはいくつかの欠陥があります。

  1. メソッドとしてHTTPプロトコルしかサポートしません。 FTP や gopher はサポートしません。
    firewallingとリダイレクションをサポートする為のカーネルコンパイルオプションがあります。 これらの重要なパラメータは/usr/src/linux/.configの中で、
    #
    # Code maturity level options
    #
    CONFIG_EXPERIMENTAL=y
    #
    # Networking options
    #
    CONFIG_FIREWALL=y
    # CONFIG_NET_ALIAS is not set
    CONFIG_INET=y
    CONFIG_IP_FORWARD=y
    # CONFIG_IP_MULTICAST is not set
    CONFIG_IP_FIREWALL=y
    # CONFIG_IP_FIREWALL_VERBOSE is not set
    CONFIG_IP_MASQUERADE=y
    CONFIG_IP_TRANSPARENT_PROXY=y
    CONFIG_IP_ALWAYS_DEFRAG=y
    # CONFIG_IP_ACCT is not set
    CONFIG_IP_ROUTER=y
    とします。 また、IPフォワードを有効にする為に、スタートアップスクリプトで次のように指定してください。
    echo 1 > /proc/sys/net/ipv4/ip_forward
  2. Linux IP Firewall and Accounting ページに行って、ipfwadmのソースを入手してインストールしてください。ipfwadmはバージョン2.3.0よりも小さいバージョンでないと働かないかもしれません。 あなたは、ipfwadmを使ってリダイレクションを設定します。 私はブート時にインターフェースを整える/etc/rc.d/rc.inet1(Slackware)から走るスクリプトにこの規則を加えました。
    /etc/rc.d/rc.firewall
    #!/bin/sh
    # rc.firewall   Linux kernel firewalling rules
    FW=/sbin/ipfwadm
    
    # Flush rules, for testing purposes
    for i in I O F # A      # If we enabled accounting too
    do
            ${FW} -$i -f
    done
    
    # Default policies:
    ${FW} -I -p rej         # Incoming policy: reject (quick error)
    ${FW} -O -p acc         # Output policy: accept
    ${FW} -F -p den         # Forwarding policy: deny
    
    # Input Rules:
    
    # Loopback-interface (local access, eg, to local nameserver):
    ${FW} -I -a acc -S localhost/32 -D localhost/32
    
    # Local Ethernet-interface:
    
    # Redirect to Squid proxy server:
    ${FW} -I -a acc -P tcp -D default/0 80 -r 8080
    
    # Accept packets from local network:
    ${FW} -I -a acc -P all -S localnet/8 -D default/0 -W eth0
    
    # Only required for other types of traffic (FTP, Telnet):
    
    # Forward localnet with masquerading (udp and tcp, no icmp!):
    ${FW} -F -a m -P tcp -S localnet/8 -D default/0
    ${FW} -F -a m -P udp -S localnet/8 -D default/0
    

    これでLANからのどんな宛先のポート80へのパケットはローカルホスト(自分自身)のポート8080に転送されます。 規則を表示させると次のように見えます。:
    IP firewall input rules, default policy: reject
    type prot source destination ports
    acc all 127.0.0.1 127.0.0.1 n/a
    acc/r tcp 10.0.0.0/8 0.0.0.0/0 * -> 80 => 8080
    acc all 10.0.0.0/8 0.0.0.0/0 n/a
    acc tcp 0.0.0.0/0 0.0.0.0/0 * -> *

    あるとき、LANからのアクセスでWebサーバとしてプロキシを指定した時に、ループに入ってしまいました。これはクライアントからの要求を拒否することで避けられるかもしれません。

    ${FW} -I -a rej -P tcp -S localnet/8 -D hostname/32 80M

    IP firewall input rules, default policy: reject
    type prot source destination ports
    acc all 127.0.0.1 127.0.0.1 n/a
    rej tcp 10.0.0.0/8 10.0.0.1 * -> 80
    acc/r tcp 10.0.0.0/8 0.0.0.0/0 * -> 80 => 8080
    acc all 10.0.0.0/8 0.0.0.0/0 n/a
    acc tcp 0.0.0.0/0 0.0.0.0/0 * -> *

17.3 Linux 2.2 と ipchainsでの透過プロキシ/キャッシュ

Martin Lyonsによる、

あなたは ipchains が機能するようにカーネルを構築する必要があります。カーネルの構築に関してはこのFAQの範疇を越えていますので詳しい情報は Linux JFLinux HQ The Linux Kernel Archives とかを参考にすると良いでしょう。カーネルの再構成の一般的な手順は:

# cd /usr/src/linux
# make menuconfig

を実行して以下のよう機能を組み込むことが必要です。

[*] Network firewalls
[ ] Socket Filtering
[*] Unix domain sockets
[*] TCP/IP networking
[ ] IP: multicasting
[ ] IP: advanced router
[ ] IP: kernel level autoconfiguration
[*] IP: firewalling
[ ] IP: firewall packet netlink device
[*] IP: always defragment (required for masquerading)
[*] IP: transparent proxy support

あなたは、 IP: always defragment (required for masquerading) を組み込む必要があります。さもないとリダイレクトの機能が使えません。

以下は、ipchainsを構成する為のスクリプト(rc.firewall)の例です。

#!/bin/sh
# rc.firewall Linux kernel firewalling rules
# Leon Brooks (leon at brooks dot fdns dot net)
FW=/sbin/ipchains
ADD="$FW -A"

# Flush rules, for testing purposes
for i in I O F # A # If we enabled accounting too
do
${FW} -F $i
done

# Default policies:
${FW} -P input REJECT # Incoming policy: reject (quick error)
${FW} -P output ACCEPT # Output policy: accept
${FW} -P forward DENY # Forwarding policy: deny

# Input Rules:

# Loopback-interface (local access, eg, to local nameserver):
${ADD} input -j ACCEPT -s localhost/32 -d localhost/32

# Local Ethernet-interface:

# Redirect to Squid proxy server:
${ADD} input -p tcp -d 0/0 80 -j REDIRECT 8080

# Accept packets from local network:
${ADD} input -j ACCEPT -s localnet/8 -d 0/0 -i eth0

# Only required for other types of traffic (FTP, Telnet):

# Forward localnet with masquerading (udp and tcp, no icmp!):
${ADD} forward -j MASQ -p tcp -s localnet/8 -d 0/0
${ADD} forward -j MASQ -P udp -s localnet/8 -d 0/0
カーネル2.0では不要でしたが、カーネル2.1、2.2では、ipフォワーディングを有効にするために次のコマンドが必要です。
echo 1 > /proc/sys/net/ipv4/ip_forward

17.4 Linux 2.4 と netfilterでの透過プロキシ/キャッシュ

注:この情報は Daniel Kiracofe's の Transparent Proxy with Squid mini-HOWTO. によります。

Linux2.4上で--enable-linux-netfilter をつけて構成されたSquidはnetfilter transparent interceptionをサポートします。
netfilterをサポートする為にカーネルを再構築する場合には次のオプションが有効になっている事を確認してください。

また、

"Fast switching"にはNoを指定しなくてはいけません。 カーネルの再構築が終わってインストールできたなら再起動してください。

パケットフォワードも(起動スクリプトなどで)有効にする必要があります。そのためには、

echo 1 > /proc/sys/net/ipv4/ip_forward

を実行します。
iptablesコマンドを使ってあなたのカーネルにHTTPコネクションを捕まえさせて、Squidにそれらを送ってください。

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080

17.5 CISCOルータによる透過プロキシ/キャッシュへのルート

John Saundersによる、

以下の説明はIOS11.1よりも新しい場合に機能します。 でもその前に、私はCISCOの専門家ではないので私のいう事は完全に信頼しないでください。 
最初にproxy-redirectという名前(名前はどんな名前でも良い)のルートマップを定義し、次のホップ先をSquidマシンとした指定を行います。

!
route-map proxy-redirect permit 10
match ip address 110
set ip next-hop 203.24.133.2
!
続いてアクセスリストを作成してHTTPリクエストをトラップします。 2番目の行ではルーティングループを避ける為にSquidマシンへの直接アクセスパケットを拒否するようにしています。 
!
access-list 110 deny tcp any any neq www
access-list 110 deny tcp host 203.24.133.2 any
access-list 110 permit tcp any any
!
そして、イーサネットインターフェースにルールを適用します。
!
interface Ethernet0
ip policy route-map proxy-redirect
!

起こりうるバグ:

ブルース・モーガンは、CiscoにおいてIPポリシールートマップを利用し透過プロシキをお行った場合に関連するバグを報告しています。それは、NFS並びに他のアプリケーションによて引き起こされます。

17.6 Linux2.0.29とCISCO IOS 11.1でのように透過プロキシを実現しますか

ドンピシャリ。いまここに、Squid-userメーリングリストにポストしたCiscoルータとLinux上のSquidを使った透過プロキシについてのメッセージがあります。

Brian Feeny による:

いま私の手元にIOS 11.1のCisco2501とLinux2.0.33上の環境で動作している透過プロキシがあります。 
以下の方に感謝します。Squid-usersメーリングリストで助けてくれたことで私のCisco/Linuxボックスでリダイレクションと透過プロキシが機能するようになりました。

最初に、私のCiscoはIOS11.1で動作しています。 IOS 11.1におけるroute-mapコマンドは"プロセス スイッチ"で、IOS 11.2以上での速度の速い"fast-switched"のroute-mapとは違うものです。 あなたは、IOS11.2 を使いたいかもしれませんが、私の11.1でもSquidに同時に150の接続を行っても全く問題は発生していません。
私のIOS11.1の設定は:

!
interface Ethernet0
description To Office Ethernet
ip address 208.206.76.1 255.255.255.0
no ip directed-broadcast
no ip mroute-cache
ip policy route-map proxy-redir
!
access-list 110 deny tcp host 208.206.76.44 any eq www
access-list 110 permit tcp any any eq www
route-map proxy-redir permit 10
match ip address 110
set ip next-hop 208.206.76.44

基本的には、上の設定では"route-map"での定義を行い、それをint e0での"ip policy route-map proxy-redir"で使うようにしています。
判りますか。 これがCiscoにおける設定のポイントです。
この設定においての、208.206.76.44はSquidの動いているホストのIPアドレスです。

私のSquidの動くLinuxでは次のような指定を行いました。
尚、私のカーネルは(2.0.33)です:

#Networking options
#
CONFIG_FIREWALL=y
# CONFIG_NET_ALIAS is not set
CONFIG_INET=y
CONFIG_IP_FORWARD=y
CONFIG_IP_MULTICAST=y
CONFIG_SYN_COOKIES=y
# CONFIG_RST_COOKIES is not set
CONFIG_IP_FIREWALL=y
# CONFIG_IP_FIREWALL_VERBOSE is not set
CONFIG_IP_MASQUERADE=y
# CONFIG_IP_MASQUERADE_IPAUTOFW is not set
CONFIG_IP_MASQUERADE_ICMP=y
CONFIG_IP_TRANSPARENT_PROXY=y
CONFIG_IP_ALWAYS_DEFRAG=y
# CONFIG_IP_ACCT is not set
CONFIG_IP_ROUTER=y

Firewalling と Transparent Proxy に対する指定は最低限必要です。そして、ipfwadmでの指定として以下のようなイーサネットインターフェースにルールを適用します。

# Accept all on loopback
ipfwadm -I -a accept -W lo
# Accept my own IP, to prevent loops (repeat for each interface/alias)
ipfwadm -I -a accept -P tcp -D 208.206.76.44 80
# Send all traffic destined to port 80 to Squid on port 3128
ipfwadm -I -a accept -P tcp -D 0/0 80 -r 3128

この設定によって、ポートは80で受け取った(これはCiscoからリダイレクトされてきます)パケットを、Squidプロセスで指定したポート3128へリダイレクトしています。 
上記の設定は/etc/rc.d/rc.localで行いました。

私はSquid V1.1.20に Henrik's patch のパッチをインストールして使いました。 あなたが同じようなものを使うならパッチを適用すると良いでしょう。

Squid Home / FAQトップ

参考: