Give me back my broken night,
My mirrored room, my secret life.
It’s lonely here, there’s no one left to torture.
Give me absolute control over every living soul
And lie beside me, baby – that’s an order!

This is an unashamedly technical post. I’ve been playing with internet filtering for a few days and thought that it might be useful to others. If you’re not interested in deep-level home network and server configuration, you probably don’t want to read this; I’ve mostly written this down so I don’t forget it.

The UK government have recently started to pressure ISPs to filter their content by default, so that little Johnny might not see any naked ladies and be upset by it, or somesuch. Of course the filters that have been installed are laughably easy to get around at best (SSL, proxies, VPN, etc, etc). No doubt there will come a time when I’d like to restrict the internet access given to certain members of my own family. I thought I’d have a go at seeing how easy it might be to do. And it turns out it’s really not all that difficult.

I’m using a Linksys E4200 router running Toastman’s custom firmware, including the VLAN support, along with a home server running a Linux installation (currently KnoppMyth, but if I were doing this again it’d be either CentOS or an Ubuntu LSB release).

I want to maintain an unfiltered connection for the grown-ups in the house, too. So the first thing to do is to create a separate network allocation, under the Basic / Network section of the router:

10.0.0.0/24 is the unfiltered area; 192.168.0.0.24 is for filtered / guest traffic only.

We then need to associate this new network (br1) with a new VLAN (VLAN1) under the Advanced settings page:

Once this is done, we can add a new virtual network (with a new SSID) for the filtered network, on wl0.1 and wl1.1 (ie, both B and G wireless):


Make sure to go into the network settings for the existing SSID and set the broadcast flag to be off. This will prevent the network showing up when anyone searches for open networks. There’s one last thing to do, which is to allow the hosts on the filtered network to reach the proxy, under Advanced / LAN access:

Now, install Squid and Dansguardian on the server. There should be some OS packages available in your usual repositories. We want to look at what’s inside the SSL connections too so we’ll need to generate an SSL certificate for squid to present:

Generate key:

openssl genrsa -des3 -out server.key 1024 
openssl req -new -key server.key  -out server.csr 
openssl rsa -in server.key -out server.key # strip passphrase from key 
openssl x509 -req -days 3650 -in server.csr -sign server.key -out server.crt 
openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt

Leave the CN for the certificate blank. Fill in the rest of the details with whatever seems reasonable.

We need to configure squid (in /etc/squid/squid.conf) to listen on both HTTP and HTTPS ports, and to use the certificate we just generated as its SSL certificate, so add two lines:

http_port 3129
https_port 3130 cert=/etc/squid/dentrassi.crt key=/etc/squid/dentrassi.key accel

The https_port runs in “accel” mode because we want squid to behave as if it is these websites, with the exception that it can’t talk QUIC and SPDY (experimental protocols used by Facebook and Google among others), so we remove any references to switching protocols. So we need to add an additional configuration line too:

# Remove QUIC / SPDY header:
reply_header_access Alternate-Protocol deny all

I also don’t want details of my internal network to leak out. So I delete the X-Forwarded-For header:

forwarded_for delete

Configuring Dansguardian to talk to squid is straightforward enough:

# the port that DansGuardian listens to.  
filterport = 3128 
# the ip of the proxy (default is the loopback - i.e. this server)  
proxyip = 127.0.0.1 
# the port DansGuardian connects to proxy on  
proxyport = 3129

I have left configuration of Dansguardian, Squidguard, ClamAV, etc. is left as an exercise for the reader. Everyone’s requirements are different.

Finally, we need to redirect traffic coming out of the untrusted network. Back on the router, go to Administration / Scripts / Firewall. Add the following lines:

iptables -t nat -A PREROUTING -s 192.168.0.0/24 -p tcp --dport 80 -j DNAT --to 10.0.0.10:3128
iptables -t nat -A PREROUTING -s 192.168.0.0/24 -p tcp --dport 443 -j DNAT --to 10.0.0.10:3130
iptables -t nat -A PREROUTING -s 192.168.0.0/24  -p udp --dport 53 -j ACCEPT
iptables -t nat -A PREROUTING -s 192.168.0.0/24  -p tcp --dport 53 -j ACCEPT
iptables -t nat -A PREROUTING -s 192.168.0.0/24  -j DROP

All outbound HTTP and HTTPS connections are redirected to the proxy. DNS connections are allowed so that lookups succeed. Anything at all else coming from the untrusted network is dropped. Of course, for HTTPS connections a certificate error will be displayed. That’s OK; for any computers I control I can add the certificate to the trust store. For others, it’s probably a good thing anyway.

Things to do: There’s a vector of attack here along DNS, which is the only outbound connection I’m allowing. I’ll probably spin up a DNS server that gives the same response for all queries. So long as the response is outside 192.168.0.0/24, the request will get bounced to the proxy anyway. Then there’s adding IPv6 support too.