Previous Next Table of Contents

17. Transparent Caching/Proxying

How can I make my users' browsers use my cache without configuring the browsers for proxying?

You can do transparent caching on Linux, Solaris, and BSD derivations. The trick is to get the operating system to forward certain IP packets to the application. This document currently contains only instruction for configuring transparent caching on Linux and Solaris.

Here are the important settings in squid.conf:

        http_port               3128
        icp_port                3130
        httpd_accel             virtual 3128
        httpd_accel_with_proxy  on

Note, virtual is the magic word here! You don't necessarily need to use port 80, but the examples below assume that you will.

17.1 Transparent proxying for Solaris, SunOS, and BSD systems

See the IP Filter package pages.

17.2 Transparent proxying for Linux

by Rodney van den Oever

Note: Transparent proxying does NOT work with Linux 2.0.30! Linux 2.0.29 is known to work well.

Warning: this technique has several significant shortcomings!

  1. The access.log will not show hostnames in the URLs.
  2. Instead it prints raw IP addresses. This is because the destination address is determined with the getsockname(2) system call. This means the use of a parent or sibling doesn't work correctly anymore. The parent or sibling itself logs the URL by name not by IP address. These URLs are different so no cache HIT occurs. This means that you lose the benefit of reducing traffic in a caching hierarchy if you do transparent caching.
  3. This method only supports the HTTP protocol, not gopher or FTP
  4. Since the browser wasn't set up to use a proxy server, it uses the FTP protocol (with destination port 21) and not the required HTTP protocol. You can't setup a redirection-rule to the proxy server since the browser is speaking the wrong protocol. A similar problem occurs with gopher. Normally all proxy requests are translated by the client into the HTTP protocol, but since the client isn't aware of the redirection, this never happens.

If you can live with the side-effects, go ahead and compile your kernel with firewalling and redirection support. Here are the important parameters from /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

Go to the Linux IP Firewall and Accounting page, obtain the source distribution to ipfwadm and install it. Older versions of ipfwadm may not work. You might need at least version 2.3.0. You'll use ipfwadm to setup the redirection rules. I added this rule to the script that runs from /etc/rc.d/rc.inet1/ (Slackware) which sets up the interfaces at boot-time. The redirection should be done before any other Input-accept rule. To really make sure it worked I disabled the forwarding (masquerading) I normally do.

/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 accouting 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 80

        # 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

Here all traffic from the local LAN with any destination gets redirected to the local port 80. Rules can be viewed like this:

        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 => 80
        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            * -> *

I did some testing on Windows 95 with both Microsoft Internet Explorer 3.01 and Netscape Communicator pre-release and it worked with both browsers with the proxy-settings disabled.

At one time squid seemed to get in a loop when I pointed the browser to the local port 80. But this could be avoided by adding a reject rule for client to this address:

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

        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 => 80
        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            * -> *

NOTE on resolving names: Instead of just passing the URLs to the proxy server, the browser itself has to resolve the URLs. Make sure the workstations are setup to query a local nameserver, to minimize outgoing traffic.

If you're already running a nameserver at the firewall or proxy server (which is a good idea anyway IMHO) let the workstations use this nameserver.

Additional notes from Richard Ayres

I'm using such a setup. The only issues so far have been that:

  1. It's fairly useless to use my service providers parent caches (cache-?.www.demon.net) because by proxying squid only sees IP addresses, not host names and demon aren't generally asked for IP addresses by other users;
  2. Linux kernel 2.0.30 is a no-no as transparent proxying is broken (I use 2.0.29);
  3. Client browsers must do host name lookups themselves, as they don't know they're using a proxy;
  4. The Microsoft Network won't authorize its users through a proxy, so I have to specifically *not* redirect those packets (my company is a MSN content provider).

Aside from this, I get a 30-40% hit rate on a 50MB cache for 30-40 users and am quite pleased with the results.

17.3 Transparent proxying with Cisco

by John Saunders

This works with at least IOS 11.1 and later I guess. Possibly earlier, as I'm no CISCO expert I can't say for sure. If your router is doing anything more complicated that shuffling packets between an ethernet interface and either a serial port or BRI port, then you should work through if this will work for you.

First define a route map with a name of proxy-redirect (name doesn't matter) and specify the next hop to be the machine Squid runs on.

        !
        route-map proxy-redirect permit 10
         match ip address 110
         set ip next-hop 203.24.133.2
        !
Define an access list to trap HTTP requests. The first line allows the Squid host direct access so an routing loop is not formed.
        !
        access-list 110 deny   tcp host 203.24.133.2 any eq www
        access-list 110 permit tcp any any eq www
        !
Apply the route map to the ethernet interface.
        !
        interface Ethernet0
         ip policy route-map proxy-redirect
        !

17.4 Transparent proxying with LINUX 2.0.29 and CISCO IOS 11.1

Just for kicks, here's an email message posted to squid-users on how to make transparent proxying work with a Cisco router and Squid running on Linux.

by Brian Feeny

Here is how I have Transparent proxying working for me, in an enviroment where my router is a Cisco 2501 running IOS 11.1, and Squid machine is running Linux 2.0.33.

Many thanks to the following individules and the squid-users list for helping me get redirection and transparent proxying working on my Cisco/Linux box.

First, here is what I added to my Cisco, which is running IOS 11.1. In IOS 11.1 the route-map command is "process switched" as opposed to the faster "fast-switched" route-map which is found in IOS 11.2 and later. You may wish to be running IOS 11.2. I am running 11.1, and have had no problems with my current load of about 150 simultaneous connections to squid.:

        !
        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

So basically from above you can see I added the "route-map" declaration, and an access-list, and then turned the route-map on under int e0 "ip policy route-map proxy-redir"

ok, so the Cisco is taken care of at this point. The host above: 208.206.76.44, is the ip number of my squid host.

My squid box runs Linux, so I had to do the following on it:

my kernel (2.0.33) config looks like this:

        #
        # 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

You will need Firewalling and Transparent Proxy turned on at a minimum.

Then some ipfwadm stuff:

        # 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 destinated to port 80 to Squid on port 3128
        ipfwadm -I -a accept -P tcp -D 0/0 80 -r 3128

it accepts packets on port 80 (redirected from the Cisco), and redirects them to 3128 which is the port my squid process is sitting on. I put all this in /etc/rc.d/rc.local

I am using v1.1.20 of Squid with Henrik's patch installed. You will want to install this patch if using a setup similar to mine.

17.5 The cache is trying to connect to itself...

by Henrik Nordstrom

I think almost everyone who have tried to build a transparent proxy setup have been bitten by this one.

Measures you can take:


Previous Next Table of Contents