This post continues from Part 6: Remote Access

This is another one of those things that isn't strictly necessary, but has some minor benefits and sets you up to do other cool things. A proxy is sort of like a relay. A client sends a request to the proxy, the proxy relays that request to the server hosting the content, and then the proxy sends the response back to the client. Since it sits in the middle of the client and the server the proxy can log and manipulate the traffic going through it. It's not even necessary for the client to know the traffic is going through a proxy, a setup known as transparent proxying. As long as you control the network traffic you can route the traffic to a transparent proxy.

One of the most widely used proxies out there is called Squid. Chances are every public network you've ever connected to, including your own ISP's, has a Squid box running on it somewhere. And there's good reason. Squid is what's known as a caching web proxy. This means it keeps a copy of the things that get proxied through it. If another request is made for the same content it can return the copy it already has stored. By avoiding making identical requests over and over the proxy can make requests faster and save a ton of bandwidth.

Squid is capable of proxying pretty much any type of network traffic, but it's most commonly used as an HTTP proxy. With the web moving to HTTPS, its effectiveness is declining but it still serves its purpose. It's not that it can't proxy HTTPS, but it would need to forge certificates which would cause scary security warnings to users and effectively break web security. Nevertheless, there's still a fair bit of HTTP traffic around so let's set up a Squid proxy to cache some of it.

Squid Installation and Configuration

First up, install Squid:

$> sudo apt-get install squid

Next you'll need to edit a few options in its configuration file. Be warned, the configuration file is a 5000+ line behemoth. You don't need to touch 99% of it. Just search over the file and find the lines you need to change.

Open up /etc/squid/squid.conf and set the port the proxy will run on using the http_port option:

http_port 3129
http_port 3128 intercept

This puts a regular HTTP proxy on port 3129 as well as enables a transparent (intercepting) proxy on port 3128. The next step is to configure which IP ranges are allowed to access the proxy. Create a network with an acl option:

acl lan src 192.168.0.0/24

And then grant access to that network:

http_access allow lan

Also make sure there is a deny rule to deny access from all other networks

http_access deny all

To allow outgoing proxy traffic to port 80 (HTTP) make sure port 80 is in the Safe_ports ACL with a line like:

acl Safe_ports port 80

And then disable traffic on all non-safe ports:

http_access deny !Safe_ports

Lastly, you'll should create a disk cache for Squid to use. By default it will cache to memory, but if you want better cache hit rates you'll need to start caching things to disk. Add a line like:

cache_dir ufs /var/spool/squid 1024 16 256

This creates a disk cache at /var/spool/squid with a maximum size of 1GB (1024 is the size of the cache in MB). You can adjust it to be larger or smaller to trade off hit rate for disk space.

Restart Squid for the new settings to take effect:

$> sudo systemctl restart squid

Routing Traffic to Squid

Squid should be ready to go now, but it's not actually receiving any traffic. We need to redirect normal web traffic to the proxy port for it to get run through Squid. This can be done with a iptables destination NAT rule:

$> sudo iptables -t nat -A PREROUTING -i enx0050b617c34f \
    -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.0.1:3128

This rule matches HTTP traffic (-p tcp -m tcp --dport 80) coming from the LAN interface (-i enx0050b617c34f) and applies a destination NAT (DNAT) rule. That rule modifies the destination IP address and port before sending the packet through the routing pipeline (since it's in the PREROUTING chain). In this case we're re-routing the packet to the Squid host and port.

Squid should now be automagically proxying and caching HTTP traffic from your LAN. You can test by making a request and looking for the HTTP headers Squid appends to the response:

$> curl -I http://neverssl.com
HTTP/1.1 200 OK
...
X-Cache: MISS from localhost.localdomain
X-Cache-Lookup: MISS from localhost.localdomain:3129
Via: 1.1 localhost.localdomain (squid/3.5.12)
...

If the request went through Squid you should see some X-Cache headers. In this particular example you can see the request was proxied but it could not be served from cache (it was a cache "miss"). Once you have traffic flowing through Squid there are a bunch more things you could try. You can mess with headers, modify content, and generally wreak havoc on your network's traffic. Have fun.

For the last post of this series we'll look at adding monitoring and visualization to your router. See you next week.

Other Posts in This Series