9.4 Operating System Tweaks

You must enable certain networking features in your operating system to make interception caching work. First, you need to enable IP packet forwarding. This allows the operating system to receive packets with foreign destination addresses. Second, you must enable and configure optional code in the kernel that redirects the foreign packets to Squid.

9.4.1 Linux

The instructions in this section should work for the 2.4 series of Linux kernels. I used RedHat Linux 7.2 (kernel 2.4.7-10). If you are using an older or newer version, these may not work. I recommend searching the Squid FAQ and other places for updated or historical information.

In my tests with iptables, it wasn't necessary to enable IP forwarding. However, you may want to enable it initially and see if you can disable it after everything else is working. The best way to enable packet forwarding is to add this line to /etc/sysctl.conf:

net.ipv4.ip_forward = 1

Most likely you'll need to make a new kernel before HTTP interception will work. See O'Reilly's Running Linux by Matt Welsh, Matthias Kalle Dalheimer, and Lar Kaufman, if you don't know how to configure and create a Linux kernel. When you configure the kernel, make sure these options are enabled:

o  General setup

     Networking support (CONFIG_NET=y)

     Sysctl support (CONFIG_SYSCTL=y)

o  Networking options

     Network packet filtering (CONFIG_NETFILTER=y)

     TCP/IP networking (CONFIG_INET=y)

     Netfilter Configuration

       Connection tracking (CONFIG_IP_NF_CONNTRACK=y)

       IP tables support (CONFIG_IP_NF_IPTABLES=y)

       Full NAT (CONFIG_IP_NF_NAT=y)

       REDIRECT target support (CONFIG_IP_NF_TARGET_REDIRECT=y)

o  File systems

     /proc filesystem support (CONFIG_PROC_FS=y)

Additionally, make sure this option isn't enabled:

o Networking options

    Fast switching (CONFIG_NET_FASTROUTE=n)

The code that redirects foreign packets to Squid is part of the Netfilter software. Here is a rule that sends the intercepted HTTP connections to Squid:

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

The Linux kernel maintains a number of different tables. The -t nat option indicates that we are modifying the Network Address Translation (NAT) table. In essence, we're using iptables to translate origin server TCP/IP addresses to Squid's local TCP/IP address.

Each iptables table has a number of chains. The -A PREROUTING option indicates that we are appending a rule to the built-in chain named PREROUTING. The PREROUTING chain applies only to packets entering the system from the outside network.

The next three options determine which packets match this rule. The -i eth0 option restricts the rule to packets received on the eth0 interface. The -p tcp option specifies TCP packets, and dport 80 specifies packets with destination port equal to 80. If all three conditions are true, the packet matches the rule.

The -j REDIRECT option indicates the target, or action to take, for packets that match the rule. REDIRECT is a built-in target name that causes iptables to change the packet's destination address to 127.0.0.1. The to-port 3128 option instructs iptables also to change the destination TCP port number to 3128.

If you are also running an HTTP server (such as Apache) on the Squid host, you must add another iptables rule. The additional rule is necessary to allow connections to your HTTP server. Otherwise, the REDIRECT rule causes iptables to send those connections to Squid on port 3128. You can use the -I option to insert a new rule at the top of the list:

iptables -t nat -I PREROUTING -i eth0 -p tcp -d 172.16.102.66 --dport 80 -j ACCEPT

Once you have all your iptables rules working correctly, be sure to save them with this command:

/sbin/service iptables save

This saves the current rules to /etc/sysconfig/iptables so they get automatically loaded when you reboot.

9.4.1.1 Linux and WCCP

Version 2.4 of the Linux kernel comes with a GRE pseudo-interface. However, it doesn't work for decoding GRE-encapsulated packets from a WCCP session. The problem seems to be that the router sets the Protocol Type field to 0x883E for WCCP/GRE packets. Linux's GRE driver doesn't know what to do with these packets because it doesn't know about protocol type 0x883E.

You can try patching Linux's GRE module so that it works with WCCP. The Squid FAQ contains a link to such a patch. However, you'll probably find it easier to use the WCCP-specific module for Linux. You can find it at http://www.squid-cache.org/WCCP-support/Linux/ip_wccp.c.

You need to compile the ip_wccp.c file as a loadable kernel module. This can be a little tricky because the specific compiler options may change depending on your kernel version. One thing you can do is go to your kernel source directory, type make modules and watch the compiler commands scroll by. Then copy one of those commands and change the last argument to ip_wccp.c. Here are the commands that I used with the 2.4.7-10 Linux kernel:

% gcc -Wall -D_ _KERNEL_ _ -I/usr/src/linux-2.4.7-10/include  \

  -DMODULE -DMODVERSIONS -DEXPORT_SYMBAB \

  -include /usr/src/linux-2.4.7-10/include/linux/modversions.h \

  -O2 -c ip_wccp.c

The gcc command should leave you with an ip_wccp.o file in the current directory. The next step is to load that file into the kernel with the insmod command:

# insmod ip_wccp.o

Note that the ip_wccp module accepts GRE/WCCP packets from any source address. In other words, a malicious person might be able to send traffic to your Squid cache. If you use this module, you should also install an iptables rule to deny foreign GRE packets. For example:

# iptables -A INPUT -p gre -s 172.16.102.65 -j ACCEPT

# iptables -A INPUT -p gre -j DROP

Again, don't forget to save your working rules with the /sbin/service iptables save command.

9.4.2 FreeBSD

The examples in this section are based on FreeBSD-4.8 and should work for any later version of FreeBSD-4 and FreeBSD-5.

To enable IP packet forwarding, add this line to /etc/sysctl.conf:

net.inet.ip.forwarding=1

You'll need a kernel with two special options enabled. If you don't know how to make a kernel, refer to Section 9 of the FreeBSD Handbook (http://www.freebsd.org/handbook/index.html). Edit your kernel config file and make sure these lines are present:

options          IPFIREWALL

options          IPFIREWALL_FORWARD

If the Squid box is in an unattended machine room, I also recommend using the IPFIREWALL_DEFAULT_TO_ACCEPT option. In case you mess up the firewall rules, you'll still be able to log in.

These ipfw commands tell the kernel to redirect intercepted connections to Squid:

/sbin/ipfw add allow tcp from 172.16.102.66 to any out

/sbin/ipfw add allow tcp from any 80 to any out

/sbin/ipfw add fwd 127.0.0.1,3128 tcp from any to any 80 in

/sbin/ipfw add allow tcp from any 80 to 172.16.102.66 in

The first rule matches packets originating from the Squid host. It ensures that outgoing TCP connections won't be redirected back to Squid.[3] The second rule matches TCP packets sent from Squid back to the clients. I've added it here in case you have additional ipfw rules later that would deny these packets. The third rule is the one that actually redirects incoming connections to Squid. The fourth rule matches packets coming back from origin servers to Squid. Again, this is in case you have subsequent deny rules.

[3] Although a misconfiguration on the switch/router may still reintercept these packets.

If you're also running an HTTP server on the Squid host, you must add another rule that passes, rather than redirects, TCP packets destined for the origin server. The following rule goes before the fwd rule:

/sbin/ipfw add allow tcp from any to 172.16.102.66 80 in

FreeBSD typically stores ipfw rules in /etc/rc.firewall. Once you get your rule set working properly, be sure to save them. Add this line to /etc/rc.conf to make FreeBSD automatically run the /etc/rc.firewall script when it boots:

firewall_enable="YES"
9.4.2.1 FreeBSD and WCCP

FreeBSD Version 4.8 and later have built-in support for GRE and WCCP. Earlier versions require patches, which you can still find at http://www.squid-cache.org/WCCP-support/FreeBSD/. The built-in implementation is much better, however, as it is written by real kernel gurus. You'll probably need to make a new kernel that supports GRE. Add this line to your kernel configuration:

pseudo-device   gre

For FreeBSD-5, use device instead of pseudo-device. Of course, you also need the FIREWALL options mentioned in the preceding section.

After installing and booting from the new kernel, you must configure a GRE tunnel to accept GRE packets from the router. For example:

# ifconfig gre0 create

# ifconfig gre0 172.16.102.66 172.16.102.65 netmask 255.255.255.255 up

# ifconfig gre0 tunnel 172.16.102.66 172.16.102.65

# route delete 172.16.102.65

The ifconfig command adds a routing table entry for the router (172.16.102.65) over the gre0 interface. I found it necessary to delete that route so that Squid can talk to the router.

You may want or need to add an ipfw rule for the GRE packets coming from the router:

/sbin/ipfw add allow gre from 172.16.102.65 to 172.16.102.66

9.4.3 OpenBSD

The examples in this section are based on OpenBSD 3.3.

To enable packet forwarding, uncomment or add this line in /etc/sysctl.conf:

net.inet.ip.forwarding=1

Now, configure the packet filter rules for interception by adding lines like these to /etc/pf.conf:

rdr inet proto tcp from any to any port = www -> 127.0.0.1 port 3128

pass out proto tcp from 172.16.102.66 to any

pass out proto tcp from any port = 80 to any

pass in proto tcp from any port = 80 to 172.16.102.66

If you aren't already using OpenBSD's packet filter, you need to enable it with this line in /etc/rc.conf.local:

pf=YES
9.4.3.1 OpenBSD and WCCP

First, tell the system to accept and process GRE and WCCP packets by adding these lines to /etc/sysctl.conf:

net.inet.gre.allow=1

net.inet.gre.wccp=1

Then, configure a GRE interface with commands like these:

# ifconfig gre0 172.16.102.66 172.16.102.65 netmask 255.255.255.255 up

# ifconfig gre0 tunnel 172.16.102.66 172.16.102.65

# route delete 172.16.102.65

As with FreeBSD, I found it necessary to delete the route that is automatically added by ifconfig. Finally, depending on your packet filter configuration, you may need to add a rule that allows the GRE packets:

pass in proto gre from 172.16.102.65 to 172.16.102.66

9.4.4 IPFilter on NetBSD and Others

The examples in this section are based on NetBSD 1.6.1. They might also work on Solaris, HP-UX, IRIX, and Tru64 since IPFilter runs on those systems as well.

To enable packet forwarding (on NetBSD), add this line to /etc/sysctl.conf:

net.inet.ip.forwarding=1

Then, insert a line like this into the NAT (network address translation) configuration file, /etc/ipnat.conf:

rdr fxp0 0/0 port 80 -> 172.16.102.66 port 3128 tcp

Your interface name may be different from fxp0 in this example.

9.4.4.1 NetBSD and WCCP

I was not able to make WCCP work with NetBSD, even after patching the GRE code to accept WCCP packets. The problem seems to arise because the IPFilter rdr rule is bound to a specific interface. Packets coming from the router go through NetBSD's gre0 interface (where they are unencapsulated). However, packets going the other way, back to the router, aren't encapsulated and don't go through the same network interface. Therefore, the IPFilter code doesn't translate Squid's local IP address back to the origin server's address.



    Appendix A. Config File Reference