Transparent Caching Proxy with Squid and Just One Ethernet Port

Tags: ARM, Efika, Linux, Network, Squid

Some time ago we had a project which needed a simple transparent caching proxy for use in classrooms in Latin America. The classroom desktops consisted of ten of our Efika's, and we thought why not use an extra one of those to act as the proxy. This is not the kind of high bandwidth environment of a typical installation, so the performance limitations were not really an obstacle. The goal was rather to use the limited internet connection available as efficiently as possible. The configuration of the system using Squid is detailed below.

Efika NetTop

The goals:

  • Install and configure DHCP server on the system for the clients
  • Install and configure Squid as a transparent caching proxy with one Ethernet port
  • Setup of the network interface and iptables rules to route packages appropriately

The Network consists of: 

  • Internet gateway only visible by the Squid server (IP = 192.168.253)
  • The Squid server (IP = 192.169.2.253)
  • Several clients with IP addresses serviced by the same Squid server (Range 10.0.0.10/10.0.0.100)

The first step is to make sure the system (assuming a headless Debian or Ubuntu installation) is up to date (aptitude update followed by aptitude safe-upgrade). It would probably be a good idea to have OpenSSH running so the configuration can be done remotely.

We need the required Squid and DHCP server software installed:

aptitude install squid3 dhcp3-server

Note: there is also a package called squid (without the '3'). We opt to use Squid3 since it is easier to configure and subjectively runs better.

Now, we have to configure the network interface. Since we have only one, we are going to multi-host this interface to serve two networks: the 192.168.2.x and 10.0.0.x ones. Edit /etc/network/interfaces file so it looks like this:

auto lo
iface lo inet loopback
	
auto eth0
iface eth0 inet static
	address 192.168.2.253
	netmask 255.255.255.0
	network 192.168.2.0
	broadcast 192.168.2.255 
	gateway 192.168.2.254

auto eth0:0
iface eth0:0 inet static
	name Ethernet alias LAN card
	address 10.0.0.1
	netmask 255.255.255.0	
	network 10.0.0.0

Both eth0 and eth0:0 are configured static, with eth0 the part that will talk to the internet gateway, and eth0:0 the part that will talk to our local network. After we have configured the network interface, let's continue with the DHCP server so we can serve our clients with IP addresses. Edit /etc/dhcp3/dhcpd.conf and add a subnet as follows:

subnet 10.0.0.0 netmask 255.255.255.0 {
	range 10.0.0.10 10.0.0.100;
	option routers 10.0.0.1;
}

This will provision our clients with IP addresses in the range of 10.0.0.1o to 10.0.0.100, more than enough for this application. Make sure that in the same configuration file you also configure the correct domain name servers for your internet. This should be done in the following directives:

option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;

Next comes the configuration of Squid itself. The config file is quite big, but we only need to make some small changes to make it work. Open /etc/squid3/squid.conf in an editor and locate the section that deals with access control lists (acl). There should already be a minimum section like this:

acl manager proto cache_object
acl localhost src 127.0.0.1/32 ::1
acl to_localhost dst 127.0.0.0/8 0.0.0.0/32 ::1

To this section, add the following acl:

acl our_networks src 10.0.0.0/24

Next, locate the section that sets the http_port variable. It should look like this:

# Squid normally listens to port 3128 http_port 3128

change the value of the http_port variable so that it reads:

# Squid normally listens to port 3128 http_port 10.0.0.1:3128 transparent

The reason for this is twofold: it enables transparent mode so we don't have to configure proxy settings on each client, and it makes sure we only listen on the internal network. Next, we have to configure to allow the clients access to the Squid server. Search for a section that configures http_access rules (or search for "INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS"). There, add the following line:

http_access allow our_networks

Finally, turn on the disk cache mechanism. Search for "Uncomment and adjust the following to add a disk cache directory" and change the line that reads:

#cache_dir ufs /var/spool/squid3 100 16 256

into:

cache_dir ufs /var/spool/squid3 2000 16 256

That's all for Squid. To tie this all together, we have to instruct Linux that it is ok to route packets, and how they have to be routed. For that, a script was written with inline comments explaining the directives which looks like this:

#!/bin/sh

# Squid server IP
SQUID_SERVER="10.0.0.1"

# Interface connected to Internet
INTERNET="eth0"

# Address connected to LAN
LOCAL="10.0.0.0/24"

# Squid port
SQUID_PORT="3128"

# Clean old firewall
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X

# Enable Forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

# Setting default filter policy
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT

# Unlimited access to loop back
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Allow UDP, DNS and Passive FTP
iptables -A INPUT -i $INTERNET -m state --state ESTABLISHED,RELATED -j ACCEPT

# set this system as a router for Rest of LAN
iptables -t nat -A POSTROUTING -o $INTERNET -j MASQUERADE
iptables -A FORWARD -s $LOCAL -j ACCEPT

# unlimited access to LAN
iptables -A INPUT -s $LOCAL -j ACCEPT
iptables -A OUTPUT -s $LOCAL -j ACCEPT

# DNAT port 80 request comming from LAN systems to squid 3128 ($SQUID_PORT) aka transparent proxy
iptables -t nat -A PREROUTING -s $LOCAL -p tcp --dport 80 -j DNAT --to $SQUID_SERVER:$SQUID_PORT

# if it is same system
iptables -t nat -A PREROUTING -i $INTERNET -p tcp --dport 80 -j REDIRECT --to-port $SQUID_PORT

#open everything
iptables -A INPUT -i $INTERNET -j ACCEPT
iptables -A OUTPUT -o $INTERNET  -j ACCEPT

# DROP everything and Log it
iptables -A INPUT -j LOG
iptables -A INPUT -j DROP

Make this script executable and run it at startup, for example within /etc/rc.local. That's it! Make sure you restart all the services and double check the clients get the correct IP address, gateway and name servers. The full configuration files and script are attached. Remove the .txt extension from 'interfaces.txt' and 'firewall.sh.txt'

Attachments

Comments

Hi Johan, Nice setup. I'm

Hi Johan,

Nice setup. I'm curious - given that this is an small embedded system, how much throughput were you getting with this setup? Did you run any benchmarks comparing bandwidth before and after the proxy was placed inbetween?

Best regards,

John

Hi John, No, I did not run

Hi John,

No, I did not run any benchmarks since the bottle neck for the set-up was the main internet connection to begin with, and the proxy itself was fast enough to make that experience orders of magnitude better. I imagine that the device won't be the best choice for a corporate environment of course, but for small amounts of users with basic internet needs it works great. 

 

Johan.

Https sites not blocking

how to block https sites

Blocking https

Hi,

You can block https with iptables, e.g.:

iptables -t nat -I PREROUTING -m tcp -p tcp --dport 443 -j DROP

Keep in mind that in the set-up discussed in the post I did not make provisions for https in the first place. In order to use squid as a transparent proxy for https as well, complement my post with this one here: http://ajayadas.com/e110body-anchor/

Johan.