old-www/HOWTO/TransparentProxy-6.html

127 lines
6.8 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<HTML>
<HEAD>
<META NAME="GENERATOR" CONTENT="SGML-Tools 1.0.9">
<TITLE>Transparent Proxy with Linux and Squid mini-HOWTO: Transparent Proxy to a Remote Box </TITLE>
<LINK HREF="TransparentProxy-7.html" REL=next>
<LINK HREF="TransparentProxy-5.html" REL=previous>
<LINK HREF="TransparentProxy.html#toc6" REL=contents>
</HEAD>
<BODY>
<A HREF="TransparentProxy-7.html">Next</A>
<A HREF="TransparentProxy-5.html">Previous</A>
<A HREF="TransparentProxy.html#toc6">Contents</A>
<HR>
<H2><A NAME="twoboxes"></A> <A NAME="s6">6. Transparent Proxy to a Remote Box </A></H2>
<P>Now, the question naturally arises, if we can do all this nifty stuff
redirecting HTTP connections to local ports, could we do the same thing
but to a remote box (e.g., the machine with squid running is not the same
machine as iptables is running on). The answer is yes, but it takes a little different magic words. If you only want to redirect to the local box
(the normal case), skip this section.
<P>For the purposes of example commands, let's assume we have two boxes called squid-box and iptables-box, and that they are on the network local-network. In the commands below, replace these strings with the actual IP addresses or
name of your machines and network.
<P>I will present two different approaches here.
<H2><A NAME="ss6.1">6.1 First method (simpler, but does not work for some esoteric cases)</A>
</H2>
<P>
<P>First, we need to machine that squid will be running on, squid-box.
You do not need iptables
or any special kernel options on this machine, just squid. You *will*,
however, need the 'http_accel' options as described above. (Previous version
of this HOWTO suggested that you did not need those options. That was a
mistake. Sorry to have confused people...)
<P>Now, the machine that iptables will be running on, iptables-box You will need to configure the kernel as described in section 3 above, except that you don't need the REDIRECT target support). Now, for the iptables commands. You need three:
<P>
<UL>
<LI>iptables -t nat -A PREROUTING -i eth0 -s ! <B>squid-box</B> -p tcp --dport 80 -j DNAT --to <B>squid-box</B>:3128</LI>
<LI>iptables -t nat -A POSTROUTING -o eth0 -s <B>local-network</B> -d <B>squid-box</B> -j SNAT --to <B>iptables-box</B></LI>
<LI>iptables -A FORWARD -s <B>local-network</B> -d <B>squid-box</B> -i eth0 -o eth0 -p tcp --dport 3128 -j ACCEPT</LI>
</UL>
<P> The first one sends the packets to squid-box from iptables-box. The second
makes sure that the reply gets sent back through iptables-box, instead of
directly to the client (this is very important!). The last one makes sure
the iptables-box will forward the appropriate packets to squid-box. It may
not be needed. YMMV. Note that we specified '-i eth0' and then '-o eth0',
which stands for input interface eth0 and output interface eth0. If your
packets are
entering and leaving on different interfaces, you will need to adjust the
commands accordingly.
<P>Add these commands to your appropriate startup scripts under /etc/rc.d/
<P>(Thanks to Giles Coochey for help writing this section).
<H2><A NAME="ss6.2">6.2 Second method (more complicated, but more general)</A>
</H2>
<P>Our first shot at this works good, but there is a minor drawback in that
HTTP/1.0 connections without the Host header do not get handled properly.
Connections that are fully or partially HTTP/1.1 compliant work fine. As
most modern web browsers send the Host header, this is not a problem for
most people. However, some small programs or embedded devices may send
only very simple HTTP/1.0 requests. If you want to support these, we'll
need to do a little more work.
Namely, on iptables-box we'll need the following options enabled in the kernel
in addition to what was specified above:
<P>
<UL>
<LI>IP: advanced router </LI>
<LI>IP: policy routing </LI>
<LI>IP: use netfilter MARK value as routing key </LI>
<LI>IP: Netfilter Configuration -> Packet mangling</LI>
<LI>IP: Netfilter Configuration -> MARK target support </LI>
</UL>
<P>You'll also need the iproute2 tools. Your distribution probably already
has them installed, but if not, look at ftp://ftp.inr.ac.ru/ip-routing/
<P>You'll want to use the following set of commands on iptables-box:
<UL>
<LI>iptables -t mangle -A PREROUTING -j ACCEPT -p tcp --dport 80 -s <B>squid-box</B></LI>
<LI>iptables -t mangle -A PREROUTING -j MARK --set-mark 3 -p tcp --dport 80</LI>
<LI>ip rule add fwmark 3 table 2</LI>
<LI>ip route add default via <B>squid-box</B> dev eth1 table 2</LI>
</UL>
Note that the choice of firewall mark (3) and routing table (2) was fairly
arbitrary. If you are already using policy routing or firewall marking for
some other purpose, make sure you choose unique numbers here. Otherwise,
don't worry about it.
<P>
<P>Next, squid-box. Use this command, which should look remarkably similar to a
command we've seen previously.
<UL>
<LI>iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128</LI>
</UL>
As before, add all of these commands to the appropriate startup scripts.
<P>Here is a brief explanation of how this works: in method one, we used Network
Address Translation to get the packets to the other box. The result of this
is that the packet gets altered. This alteration is what causes some kinds
of clients mentioned above to fail. In method two,
we use a magic thing called policy routing. The first thing we do is to
select the packets we want. Thus, all packets on port 80, except those
coming from squid-box itself, are MARKed. Then, when the kernel goes to
make a routing decision, the MARKed packets aren't routing using the normal
routing table that you access with the ``route'' command but with a special
table. This special table has only one entry, a default gateway to squid-box.
Thus, the packet is sent merrily on it's way without every having been altered.
So, even HTTP/1.0 connections can be handled perfectly.
(Thanks to Michal Svoboda for suggesting and helping to write this section)
<P>
<P>
<H2><A NAME="ss6.3">6.3 Method One: What if iptables-box is on a dynamic IP?</A>
</H2>
<P>If the iptables-box is on a dynamic IP address (e.g. a dialup PPP connection, or a DHCP assigned IP address from a cable modem, etc.), then you will want to
make a slight change to the above commands. Replace the second command with this one:
<P>
<UL>
<LI>iptables -t nat -A POSTROUTING -o eth0 -s <B>local-network</B> -d <B>squid-box</B> -j MASQUERADE</LI>
</UL>
<P>This change avoids having to specify the IP address of iptables-box in the command. Since it will change often, you'd have to change your commands to
reflect it. This will save you a lot of hassle.
<HR>
<A HREF="TransparentProxy-7.html">Next</A>
<A HREF="TransparentProxy-5.html">Previous</A>
<A HREF="TransparentProxy.html#toc6">Contents</A>
</BODY>
</HTML>