15 December 2009

Scenario

I think my setup is rather common.  There is one Linux computer that has two network cards, one connected to the internet and the other to a LAN switch.  Most of the computers in the LAN run Windows.  These Windows computers have the gateway and the DNS server entries set to the Linux box's IP.  None of them runs a firewall.  Because server versions of Windows cannot use free antivirus programs, there are computers on the LAN that do not run any antivirus program.

The Linux box runs Apache (web server), Pdnsd (caching DNS server), NcFTP (FTP server), Postfix (mail server), Samba (Windows file and printer sharing), Dnews (news server) and a custom iptables firewall.

In order for the Linux server to provide internet access to LAN machines, iptables' nat uses SNAT in the POSTROUTING chain and ip_forward is set.

Installation of software

The Linux computer runs Slackware, and the SlackBuilds for squid and Dans Guardian (often referred to herein as DG) were obtained from slackbuilds.org.

The latest stable version of squid was obtained from squid-cache.org and the squid.SlackBuild was set for the downloaded version and format.  With these files in a temporary directory, the SlackBuild was made executable and then was run as the root user.  The resulting package was installed, also by root.

Because it was desired to have a unique user and group to run Dans Guardian, the group squid was created, then the user squid was created with a home directory of /no/where and a shell of /no/shell.  The SlackBuilds want to run both squid and DG as user:group nobody:nobody, a fact that I failed to grasp until after the packages were installed, so it was necesary to run chown -R squid:squid in several directories in order to get the programs to run.

squid

Make sure the ports you intend to use are available.  For squid, run netstat -tulnp | grep 3128  No result means that port 3128 is not presently in use.

Lines beginning with - were changed to the oorresponding line that begins with +, and lines with neither - nor + are for context.

Here are my changes to /etc/squid/squid.conf.

- acl all src all
+#acl all src all

 acl manager proto cache_object
 acl localhost src 127.0.0.1/32

-acl to_localhost dst 127.0.0.0/8 0.0.0.0/32
+acl to_localhost dst 127.0.0.0/8

-acl localnet src 10.0.0.0/8	# RFC1918 possible internal network
+#acl localnet src 10.0.0.0/8	# RFC1918 possible internal network

-acl localnet src 172.16.0.0/12	# RFC1918 possible internal network
+#acl localnet src 172.16.0.0/12	# RFC1918 possible internal network

-acl localnet src 192.168.0.0/16	# RFC1918 possible internal network
+#acl localnet src 192.168.0.0/16	# RFC1918 possible internal network
+acl localnet src 192.168.5.0/24

 # INSERT YOUR OWN RULE(S) HERE TO ALLOW ACCESS FROM YOUR CLIENTS
+http_access allow localnet
+http_access allow localhost
+http_access deny all
 
 # Squid normally listens to port 3128
-http_port 3128
+http_port 127.0.0.1:3128 transparent
 
-# cache_dir ufs /var/log/squid/cache 100 16 256
+cache_dir ufs /var/cache/squid/ 100 16 256
 
-access_log /var/log/squid/logs/access.log squid
+access_log /var/log/squid/access.log squid
 
-# cache_log /var/log/squid/logs/cache.log
+#cache_log /var/log/squid/cache.log
+cache_log none
 
-# cache_store_log /var/log/squid/logs/store.log
+#cache_store_log /var/log/squid/store.log
+cache_store_log none
 
-# pid_filename /var/log/squid/logs/squid.pid
+pid_filename /var/run/squid/squid.pid

 # cache_mgr webmaster
+cache_mgr root

-# cache_effective_user nobody
+cache_effective_user squid
 
 #  TAG: cache_effective_group
-# none
+cache_effective_group squid
 
 #	Example: dns_nameservers 10.0.0.1 192.172.0.4
 #Default:
 # none
+dns_nameservers 127.0.0.1
 
-# forwarded_for on
+forwarded_for off
 
-coredump_dir /var/log/squid/cache
+coredump_dir /var/log/squid
Download the script that starts squid.

dansguardian

DG was obtained from dansguardian.org U.S. mirror and the dansguardian.SlackBuild was set for the downloaded version and format.  With these files in a temporary directory, the SlackBuild was made executable and then was run as the root user.  The resulting package was installed by root.

Make sure the port you intend to use is available.  For DG, run netstat -tulnp | grep 8080  No result means that port 8080 is not presently in use.

These are my changes to /etc/dansguardian/dansguardian.conf.

 # Network Settings
-filterip =
+filterip = 127.0.0.1
+filterip = 192.168.5.1
 
 # sets the minimum number of processes to spawn to handle the incoming connections.
 # On large sites you might want to try 32.
-minchildren = 8
+minchildren = 4
 
 # sets the minimum number of processes to be kept ready to handle connections.
 # On large sites you might want to try 8.
-minsparechildren = 4
+minsparechildren = 2
 
 # Temp files created during virus scanning are given owner and group read
 # permissions; to use content scanners based on external processes, such as
 # clamdscan, the two processes must run with either the same group or user ID.
-#daemonuser = 'squid'
+daemonuser = 'squid'

-#daemongroup = 'squid'
+daemongroup = 'squid'

Configuring DG

My purpose in installing DG was to block malicious software ("malware"), not to prevent children from accessing inappropriate material.  In addition, all computers on the LAN are allowed audio and video, to download executable files, and access any web site they desire.

Although DG includess malware control, an additional list of blocked sites was obtained from www.malware.com.br.
Here is the shell script that updates the list:

#! /bin/bash
wget -O - http://www.malware.com.br/cgi/submit?action=list_dguard >/etc/dansguardian/lists/blacklists/mbl/urls

# If dansguardian is running, reload
PIDr=`pgrep -o dansguardian`
PIDf=`cat /var/run/dansguardian.pid`	>/dev/null	2>&1
if [ ! "$PIDr" = "" ] && [ "$PIDr" = "$PIDf" ]; then
  dansguardian -r		# Reload, killing existing connections
fi
# Done.
and here is the crontabs entry that updates it:
13 6 * * mon	/etc/dansguardian/lists/blacklists/mbl/malware.sh	&>/dev/null
In order to employ this additional list, the directory mbl was created.
mkdir -p /etc/dansguardian/lists/blacklists/mbl With the file urls in that directory, /etc/dansguardian/lists/bannedurllist was edited so it looks like this:
#List other URLs to block:
members.home.net/uporn

# The squidGuard advert domain/URL lists are now included by default.
# To work with advanced ad blocking & the logadblocks option, advert
# phrase/site/URL lists should have the string "ADs" in their listcategory.
# .Include</etc/dansguardian/lists/blacklists/ads/urls>
.Include</etc/dansguardian/lists/blacklists/mbl/urls>
Note that the above shows the only lines left uncommented in bannedurllist.

The following files, located in /etc/dansguardian/lists, contain .Include<...> entries that control the operation of DG:  In our setup, only 5 entries remain uncommented.

It would be wonderful if DG could be entirely configured using only .Include statements.  Unfortunately, that is not the case.  I had to edit bannedextensionlist, bannedmimetypelist and bannedregexpurllist - remarking out most or all of the entries in those files - in order to get DG to behave as I desire.  Since there are 28 of these files, I am not yet certain that all necessary edits have been made.
Download the script that starts DG.


Transparent proxy

Since the computer running DG is also the gateway to the internet for all LAN machines, iptables rules were added to the firewall to force all HTTP activity to proxy through DG.  The following should also take care of the case where the same computer that runs DG is used to surf the web (but I have not tested this scenario) - so long as user root is not running the browser.  As you can see, root's --uid-owner entry bypasses DG.  Run TransparentProxy.sh up  to force all users to use ("Transparent proxy") DG as their HTTP proxy.
#! /bin/bash
# /user/sbin/TransparentProxy.sh

# Tear down
iptables -t nat -D PREROUTING -p tcp -s 192.168.5.1 --dport 80 -m limit --limit 12/h --limit-burst 1 -j LOG --log-prefix "EXCPT " >/dev/null 2>&1
iptables -t nat -D PREROUTING -p tcp -s 192.168.5.1 --dport 80 -j ACCEPT >/dev/null 2>&1
iptables -t nat -D PREROUTING -p tcp -s 192.168.5.0/24 --dport 80 -m limit --limit 12/h --limit-burst 1 -j LOG --log-prefix "REDIR " >/dev/null 2>&1
iptables -t nat -D PREROUTING -p tcp -s 192.168.5.0/24 --dport 80 -j DNAT --to 192.168.5.1:8080 >/dev/null 2>&1
iptables -t nat -D OUTPUT -p tcp -m owner --uid-owner root --dport 80 -j ACCEPT >/dev/null 2>&1
iptables -t nat -D OUTPUT -p tcp -m owner ! --uid-owner squid --dport 80 -j REDIRECT --to-port 8080 >/dev/null 2>&1
iptables -D OUTPUT -o eth1 -p tcp -s 127.0.0.1 -d 127.0.0.1 --dport 8080 -j ACCEPT >/dev/null 2>&1

# Set up
if [ "$1" = "up" ]; then
# iptables -t nat -A PREROUTING -p tcp -s 192.168.5.1 --dport 80 -m limit --limit 12/h --limit-burst 1 -j LOG --log-prefix "EXCPT "
iptables -t nat -A PREROUTING -p tcp -s 192.168.5.1 --dport 80 -j ACCEPT
# iptables -t nat -A PREROUTING -p tcp -s 192.168.5.0/24 --dport 80 -m limit --limit 12/h --limit-burst 1 -j LOG --log-prefix "REDIR "
iptables -t nat -A PREROUTING -p tcp -s 192.168.5.0/24 --dport 80 -j DNAT --to 192.168.5.1:8080
iptables -t nat -A OUTPUT -p tcp -m owner --uid-owner root --dport 80 -j ACCEPT
iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner squid --dport 80 -j REDIRECT --to-port 8080
iptables -I OUTPUT -o eth1 -p tcp -s 127.0.0.1 -d 127.0.0.1 --dport 8080 -j ACCEPT
fi
# Done.

Direct questions, comments and corrections to gypsy at iswest dot com
Please make sure the Subject line contains dansguardian.