First published on 2012-01-10.
Setting up a proxy server in a local network allows you to:
speed up Internet access by locally caching and subsequently distributing frequently requested resources (pages, images, CSS) from the cache;
configure ad blocking (or other unwanted content) in one place for all local network users simultaneously.
A transparent HTTP proxy is called so because all clients accessing external web servers from the internal network pass through it automatically, without making any changes to their own settings (without explicitly specifying the proxy in all programs used, some of which may not even support proxies).
Let's consider how to ensure this very convenient transparency for both IPv4 and IPv6.
The following examples assume:
you are using a router based on GNU/Linux;
Squid 3.1+ proxy server is installed on it (installation and configuration of Squid is beyond the scope of this article);
the OS uses Linux kernel version 2.6.37+ and iptables package 1.4.10+;
the internal interface of the router is named eth0.
IPv4
IPv4 connections are redirected to the proxy using the NAT mechanism. It looks quite simple:
iptables
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8084
Add this line to your existing iptables script.
Squid
On the Squid side, you need to add to /etc/squid3/squid.conf:
http_port 8084 transparent
You can use any other port of your choice, as long as it is not occupied by anything else and is the same in both the iptables rule and the Squid configuration.
IPv6
Since NAT is absent in ip6tables, a transparent proxy for IPv6 is implemented in a slightly different way. The configuration looks a bit more complex, but thanks to the absence of the need for NAT, an important advantage is achieved: although connections pass through the proxy, the remote web server sees the IPv6 address of the end machine as the client address, not the proxy's address.
iproute & ip6tables
#!/bin/sh
# === Removing previous settings (if any) ===========
ip -6 route flush table 64
ip -6 rule del from all fwmark 0x6
ip6tables -t mangle -F
ip6tables -t mangle -X DIVERT
# === Applying new configuration =====================
ip -6 route add local default dev lo table 64
ip -6 rule add from all fwmark 0x6 lookup 64
ip6tables -t mangle -N DIVERT
ip6tables -t mangle -A DIVERT -j MARK --set-mark 6
ip6tables -t mangle -A DIVERT -j ACCEPT
ip6tables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
ip6tables -t mangle -A PREROUTING -p tcp -i eth0 --dport 80 -j TPROXY --tproxy-mark 0x6 --on-port 8086
The values table 64 and fwmark 0x6 are chosen arbitrarily here; if you already use multiple routing tables and firewall rules using marks in your system (for example, to support multiple WAN connections), make sure this script does not conflict with your existing settings.
Squid
In /etc/squid3/squid.conf you need to add:
http_port 8086 tproxy
As in the above-described IPv4 configuration process, you can choose any other port.
Applying settings
To apply the changes made in squid.conf, it is sufficient to instruct Squid to reload this file; for example, in Debian-based distributions, you can do this by running /etc/init.d/squid3 reload.
The ip/iptables/ip6tables settings take effect immediately after executing the corresponding commands. To ensure they are applied on every system boot, add them to your firewall script (in the arno-iptables-firewall I use, custom additions can be specified in /etc/arno-iptables-firewall/custom-rules), or simply add them to /etc/rc.local.
Verification
From any machine on the local network (but not from the server itself), run:
curl -I4 http://version6.ru/
curl -I6 http://version6.ru/
In both cases, the curl output should include the following lines:
X-Cache: MISS from yourproxy
X-Cache-Lookup: MISS from yourproxy:port
If these lines are missing, or if the connection cannot be established, something is configured incorrectly. If you are unable to configure it properly, join our IRC channel; someone may be able to help.
