Local transparent HTTP proxy
This article was originally written in March 2008.
Setting up Squid as a transparent HTTP proxy has been discussed plenty of times. All of these examples and blogs I’ve read on the subject assume that you run Squid on your network gateway. While this is a very common and sensible set up, it doesn’t suit my need. I need to lock down one single computer and perform filtering using Squid’s ACL mechanism, regardless of the network it’s plugged into.
Difference with Squid on gateway
The technique of running a local transparent HTTP proxy is basically the same as the usual proxying on the gateway. However, there is one more hurdle. If we indiscriminately redirect all outgoing HTTP requests via Squid, we create an infinite loop. After all, Squid itself has to perform HTTP requests too, which should not be looped through itself.
Unlooping the loop
The trick to prevent this infinite loop is to filter on user ID. We’ll tell IPTables that it should accept all HTTP requests coming from our Squid user, and redirect all others. Of course, this assumes that Squid runs as a user specifically reserved for this purpose.
Here is my IPTables configuration that takes care of this.
# Shortcuts filter="ipttables -t filter" nat="iptables -t nat" # Proxy HTTP access through Squid $nat -A OUTPUT -m owner --uid-owner 13 -j ACCEPT $nat -A OUTPUT -p tcp --dport 80 -j REDIRECT -p tcp --to-port 3128 # Reject HTTPS $filter -A OUTPUT -m owner --uid-owner 13 -j ACCEPT $filter -A OUTPUT -p tcp --dport 443 -j REJECT
This set up assumes that Squid runs as the “proxy” user with uid 13. This is the default in Ubuntu and probably other distributions, but please check to ensure it matches your system.
$nat rules tell IPTables to accept all HTTP connections coming from Squid,
and to redirect all other HTTP connections to Squid.
$filter rules are there to block HTTPS traffic. If I understand SSL
connections well (and I believe I do) there is no way to transparently proxy
those without breaking security. Since I want to prevent all HTTP access that
doesn’t get routed through Squid, I simply block it. The user of the computer
can set up her browser to use Squid for HTTPS connections.
The Squid part is no different than any other transparent proxying
configuration. Just know that the redirected HTTP traffic will appear come from
the same network interface as it was originally sent on. So if - without
transparent proxy set up - your HTTP request would go through
eth0, Squid will
see a connection coming from the IP address of
eth0. Use this knowledge to
configure your ACLs.
Here is my configuration, just so you can take a look at how I configured things. This is for Squid 2.6, earlier versions used slightly different configuration for transparent proxying.
hierarchy_stoplist cgi-bin ? acl QUERY urlpath_regex cgi-bin \? no_cache deny QUERY hosts_file /etc/hosts acl all src 0.0.0.0/0.0.0.0 acl manager proto cache_object acl localhost src 127.0.0.1/255.255.255.255 acl localhost src 172.27.0.4/255.255.255.255 acl to_localhost dst 127.0.0.0/8 acl SSL_ports port 443 563 acl SSL_ports port 873 acl lan src 172.27.0.0/24 acl Safe_ports port 80 acl Safe_ports port 21 acl Safe_ports port 443 563 acl Safe_ports port 70 acl Safe_ports port 210 acl Safe_ports port 1025-65535 acl Safe_ports port 280 acl Safe_ports port 488 acl Safe_ports port 591 acl Safe_ports port 777 acl Safe_ports port 631 acl Safe_ports port 873 acl Safe_ports port 901 acl purge method PURGE acl CONNECT method CONNECT http_access allow manager localhost http_access deny manager http_access allow purge localhost http_access deny purge http_access deny !Safe_ports http_access deny CONNECT !SSL_ports http_access deny to_localhost http_access allow localhost http_access deny all http_reply_access allow all # Transparent redirection options always_direct allow all http_port 0.0.0.0:3128 transparent # Effective user/group cache_effective_user proxy cache_effective_group proxy access_log /var/log/squid/access.log squid icp_access allow all cache_mgr firstname.lastname@example.org forwarded_for off coredump_dir /var/spool/squid
Most of this file is the bog-standard Squid configuration with all comments removed.
Hopefully this article explains how to secure and manage HTTP and HTTPS access on a single machine. It only handles connections to port 80, so HTTP servers listening on another port won’t be connected. Expand on the examples if you want, because the mechanism will be exactly the same for different ports.
If anything is unclear, don’t hesitate to contact me and ask for clarification.