Gateway and Proxy Server with squid, squint, iptables in Ubuntu/Debian

Posted/Updated by rkarim1981@gmail.com June 2009

What I have done in this howto ...

I have googled and took several references from several how-to/tutorials and adopted/tested them to my system/server and make a Easy step-by-step howto. I hope this will help some other people who use/will use Linux as Gateway + Proxy Server.
I will revise this how-to time to time; you may give your valuable advise to me ...

STEP-01: Install Ubuntu Server Edition 8.04/8.10/9.04

Install Ubuntu Server Edition 8.04/8.10/9.04 On a particular server/pc which will be your gateway+proxy server.

Installation Requirements...
   >> Internet Connection; and

While you install Ubuntu Server; Select the following pkgs...
   >> OpenSSH Server
   >> LAMP (Optional; if you want to use squid graphical log analyzer like squint)

Also determine that; you have two ethernet interfaces...
    interface eth0 is connected to Internet
  interface eth1 is connected to Local Network


Suppose,
    eth0 have IP: 123.49.42.180
  eth1 have IP: 192.168.100.1


STEP: 02- Put IP Address on LAN Interface and DNS Address

# vi /etc/network/interfaces
# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
   address 123.49.42.180
   netmask 255.255.255.224
   network 123.49.42.160
   broadcast 123.49.42.191
   gateway 123.49.42.161

# The secondary network interface
auto eth1
iface eth1 inet static
   address 192.168.100.1
   netmask 255.255.255.0
   network 192.168.100.0
   broadcast 192.168.100.255
Save + Exit

# /etc/init.d/networking restart

Put dns server address...

# vi /etc/resolv.conf
nameserver 4.2.2.1
nameserver 4.2.2.2
Save + Exit

Now you should get the Internet


STEP: 03- Install some basic packages

# apt-get update
# apt-get -q -y install build-essential rcconf vim-nox iftop

STEP: 04- NAT and basic firewall with iptables

Make a nat/firewall script as /usr/bin/nat_firewall.sh "directory"

# vim /usr/bin/nat_firewall.sh

Add or copy/past the following lines (Use your own values of ips/ethernet) ...
#!/bin/bash

echo -e "\n>>> LOADING NAT FIREWALL ...\n"

echo -e ">>> RESETING IMPORTANT PARAMETERS ...\n"

#Reduce DoS'ing ability by reducing timeouts ...

echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/tcp_syncookies
echo 0 > /proc/sys/net/ipv4/conf/all/accept_redirects
echo 0 > /proc/sys/net/ipv4/conf/all/accept_source_route
echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 1 > /proc/sys/net/ipv4/conf/lo/rp_filter
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all
echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 1 > /proc/sys/net/ipv4/tcp_window_scaling
echo 0 > /proc/sys/net/ipv4/tcp_sack
echo 1280 > /proc/sys/net/ipv4/tcp_max_syn_backlog

echo -e ">>> RESETING FIREALL ...\n"

iptables -F INPUT
iptables -F OUTPUT
iptables -F FORWARD
iptables -F -t mangle
iptables -F -t nat
iptables -F
iptables -X
iptables -Z
iptables -t nat -F
iptables -t nat -X
iptables -t nat -Z
iptables --table nat -F
iptables --delete-chain
iptables --table nat --delete-chain
iptables -t mangle --delete-chain

echo -e ">>> LOADING MODULES ...\n"

/sbin/modprobe ip_tables
/sbin/modprobe ip_queue
/sbin/modprobe iptable_filter
/sbin/modprobe iptable_mangle
/sbin/modprobe iptable_nat
/sbin/modprobe ipt_limit
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_MASQUERADE
/sbin/modprobe ipt_multiport
/sbin/modprobe ipt_REDIRECT
/sbin/modprobe ipt_REJECT
/sbin/modprobe ipt_state
/sbin/modprobe ip_nat_ftp
/sbin/modprobe ip_conntrack
/sbin/modprobe ip_conntrack_ftp

echo -e ">>> SETING VARIABLES ...\n"

WAN="eth0"
LAN="eth1"


IPT="/sbin/iptables"
LAN_IP="192.168.100.0/24" # IP addresses on the LAN side
WAN_IP="123.49.42.180"    # IP from ISP Connected to Internet


echo -e ">>> SETING POLIECY ...\n"

$IPT -F INPUT
$IPT -P INPUT DROP
$IPT -F OUTPUT
$IPT -P OUTPUT ACCEPT
$IPT -F FORWARD
$IPT -P FORWARD ACCEPT

echo -e ">>> SETING CUSTOM RULES ...\n"

$IPT -A INPUT -i lo -j ACCEPT
$IPT -A INPUT -i $LAN -j ACCEPT
$IPT -A INPUT -i $WAN -m state --state ESTABLISHED,RELATED -j ACCEPT

# ENABLE SOME SERVICES ....
for i in 22 78 25 53 80 8080 443 110 143
do
$IPT -A INPUT -i $WAN -p tcp --dport $i -j ACCEPT
done

# ALLOW DNS(udp)/icmp
$IPT -A INPUT -i $WAN -p udp --dport 53 -j ACCEPT

$IPT -A INPUT -p icmp --icmp-type 8 -s 0/0 -d $WAN_IP -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 0 -s 0/0 -d $WAN_IP -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPT -A INPUT -p icmp --icmp-type 8 -s 0/0 -d $LAN_IP -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPT -A INPUT -p icmp --icmp-type 0 -s 0/0 -d $LAN_IP -m state --state ESTABLISHED,RELATED -j ACCEPT

#Limiting the incoming icmp ping request:
$IPT -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j ACCEPT
$IPT -A INPUT -p icmp -m limit --limit 1/s --limit-burst 1 -j LOG --log-prefix PING-DROP:
$IPT -A INPUT -p icmp -j DROP

#### SOME PORT BLOCK
badport="135,136,137,138,139,445"

$IPT -A INPUT -p tcp -m multiport --dport $badport -j DROP
$IPT -A INPUT -p udp -m multiport --dport $badport -j DROP

$IPT -A INPUT -p tcp -m multiport --sport $badport -j DROP
$IPT -A INPUT -p udp -m multiport --sport $badport -j DROP
# SNAT/NAT
$IPT -t nat -A POSTROUTING -s $LAN_IP -d 0/0 -j SNAT --to-source $WAN_IP

# TPROXY (Uncomment 'remove hash #' this line after you configure squid proxy)
# $IPT -t nat -A PREROUTING -p tcp -s $LAN_IP --dport 80 -j REDIRECT --to-port 8080

#
echo -e ">>> FIRWALL LOADED [DONE] \n"
Save + Exit

# chmod 755 /usr/bin/nat_firewall.sh
# vim /etc/rc.local

Add the following line in /etc/rc.local before the line 'exit 0'...
/usr/bin/nat_firewall.sh
Save + Exit

Now run the nat_firewall.sh script; See the output bellow;.
# /usr/bin/nat_firewall.sh

Output
>>> LOADING NAT FIREWALL ...

>>> RESETING IMPORTANT PARAMETERS ...

>>> RESETING FIREALL ...

>>> LOADING MODULES ...

>>> SETING VARIABLES ...

>>> SETING POLIECY ...

>>> SETING CUSTOM RULES ...

>>> FIRWALL LOADED [DONE]
Now go to a client PC and put the local ip address (from 192.168.100.0/24) and verify that you are getting internet via your linux-gateway.

STEP: 05- Install and Configure Squid

Download the latest version of squid from http://www.squid-cache.org/Versions/v3/3.0/

# cd /opt/
# wget http://www.squid-cache.org/Versions/v3/3.0/squid-3.0.STABLE15.tar.gz

Unpack and Install Squid...
# tar zxvf squid-3.0.STABLE15.tar.gz
# cd squid-3.0.STABLE15

# ./configure --prefix=/usr --includedir=/usr/include --datadir=/usr/share --bindir=/usr/sbin --libexecdir=/usr/lib/squid --localstatedir=/var --sysconfdir=/etc/squid --enable-removal-policies=heap,lru --enable-storeio=diskd,aufs,ufs --enable-time-hack --enable-snmp --with-large-files --enable-linux-netfilter --enable-large-cache-files --disable-ident-lookups --enable-cache-digests --enable-underscores --enable-kill-parent-hack --enable-follow-x-forwarded-for

# make all
# make install

Configure Squid...
# useradd squid
# vim /etc/passwd

Change " squid:x:.....:/home/squid:/bin/bash " to " squid:x:......:/home/squid:/bin/false"
Save + Exit

# cd /etc/squid/
# cp squid.conf squid.conf.orig
# echo "" > squid.conf
# vim squid.conf

Now Insert (you may copy/past) the following configuration,

############## Start of squid.conf ###########

cache_effective_user squid
cache_effective_group squid

# put your own/appropriate dns address on tag 'dns_nameservers'
dns_nameservers 4.2.2.1 4.2.2.2
icp_query_timeout 1000

# tag 'high_memory_warning' should be 1/4 of your total ram ...
high_memory_warning 512 MB

# visible_hostname should be your servers/systems/pcs hostname found in /etc/hostname file ...
visible_hostname gw-proxy

# tag 'cache_mem' should be 1/4 of your total ram ...
cache_mem 512 MB
cache_replacement_policy heap LFUDA
memory_replacement_policy heap LFUDA
cache_swap_low 90
cache_swap_high 95

# Object siez in cahce ...
maximum_object_size 8192 KB
maximum_object_size_in_memory 64 KB

# cache storage scehme ...
# cache can be in a directory or individual hdd partition and size should not be equal to your total hdd ...
# here size is about 55GB out of a individual hdd partition labeled as 'cache' of 60GB...
# create a directory named 'cache' in '/' (later mentioned) if you don't have individual partition..

cache_dir diskd /cache 55000 16 256 Q1=72 Q2=64

# Log files ...
cache_store_log none
cache_access_log /var/log/squid/access.log
cache_log /var/log/squid/cache.log

cache_mgr sysadmin@yourdomain.com

refresh_pattern ^ftp:        1440   20%   10080
refresh_pattern ^gopher:     1440   0%    1440
refresh_pattern (cgi-bin|\?) 0      0%    0
refresh_pattern .            0      20%   4320

# Squid to run transparently ...
http_port 8080 transparent

# Acess Controll list ...

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

#
acl SSL_ports port 443
acl Safe_ports port 80  # http
acl Safe_ports port 21  # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70  # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT

http_access allow manager localhost
http_access deny manager
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports

# your ip blocks ...
acl mynetwork src 192.168.100.0/24

# block some common viruses ...
acl badurl urlpath_regex -i cmd.exe
acl virus urlpath_regex winnt/system32/cmd.exe?
acl codered url_regex \/default\.ida$
acl dangurl urlpath_regex -i \.id[aq]\?.{100,}
acl dangurl urlpath_regex -i /readme\.(eml|nws|exe)

http_access deny badurl
http_access deny virus
http_access deny codered
http_access deny dangurl

#
http_access allow mynetwork

#
acl PURGE method PURGE
http_access allow PURGE localhost
http_access deny PURGE

#
deny_info TCP_RESET all
http_access deny all

#put your WAN IP (Connected to internet, here eth0)
tcp_outgoing_address 123.49.42.180 mynetwork

#
icp_access allow mynetwork
icp_access deny all

#
htcp_access allow mynetwork
htcp_access deny all

ie_refresh on

######## End of squid.conf ###############

Save + Exit

Create necessary files to run squid ...
# mkdir /var/log/squid
# touch /var/log/squid/access.log
# touch /var/log/squid/cache.log

# mkdir /cache

# chown -R squid:squid /cache
# chown -R squid:squid /var/log/squid
# chown -R squid:squid /var/log/squid/

Creating cache sub-directories...
# squid -z
# chown -R squid:squid /cache

Now run the squid service ...
# squid -D

Check that squid sevice is running (you will see the process ids)...
# pgrep squid
# vim /etc/rc.local

Add the following line in /etc/rc.local before the line 'exit 0'...
squid -D
Save + Exit

Activate the transparent proxy line in /usr/bin/nat_firewall.sh ...
# vim /usr/bin/nat_firewall.sh

Enable the follwoing line (remove hash #) ...
# TPROXY (Uncomment 'remove hash #' this line after you configure squid proxy)
$IPT -A PREROUTING -t nat -s $LAN_IP -p tcp --dport 80 -j REDIRECT --to-port 8080
Save + Exit

Re-run /usr/bin/nat_firewall.sh ...
# /usr/bin/nat_firewall.sh

Now goto your local client pc and browse and see the log file in linux-gw/proxy server as ...
# tail -f /var/log/squid/access.log

STEP: 06- Install squid log analyzer Squint

Among several squid (proxy) log analyzer, I found squint is cool and I still use it; though it is not updated since 2004, but still it works in latest version of Ubuntu Server Edtion 9.04 and Debian 5 Lenny without any funcitonal problem.

I hope you already have installed LAMP while you installed the Linux, otherwise you have to install apache2 and php5 by apt-get and have to start the apache2 service.

Download the last version of squint from my site link http://www.linux-bd.com/app/squint.tar.gz and install it.

# cd /opt/
# wget http://www.linux-bd.com/app/squint.tar.gz
# tar zxvf squint.tar.gz
# cd squint-0.3.18/
# cp squint.pl squint.cron.sh /usr/local/bin
# squint.cron.sh init
# squint.cron.sh all

After you apply the command # squint.cron.sh all you might see the output like bellow, but don't worry, it is ok. Also you might have to wait some time after applying the command, this depneds on the amount of access.log file you have.

OUTPUT SAMPLE ...
Generating report to /var/www/squint/all/daily from 20090622 to 20090623
Parentheses missing around "my" list at /usr/local/bin/squint.pl line 404.
Useless use of a variable in void context at /usr/local/bin/squint.pl line 404.
Useless use of a variable in void context at /usr/local/bin/squint.pl line 404.
main::writeusersitereports() called too early to check prototype at /usr/local/bin/squint.pl line 247.
main::writeusersitereports() called too early to check prototype at /usr/local/bin/squint.pl line 341.
Name "main::messagelog" used only once: possible typo at /usr/local/bin/squint.pl line 351.
Name "main::listlimit" used only once: possible typo at /usr/local/bin/squint.pl line 168.
Name "main::peak" used only once: possible typo at /usr/local/bin/squint.pl line 709.
Name "main::nametofilenamebasehref" used only once: possible typo at /usr/local/bin/squint.pl line 568.
Name "main::basedom" used only once: possible typo at /usr/local/bin/squint.pl line 351.
Name "main::basename" used only once: possible typo at /usr/local/bin/squint.pl line 351.

rm: cannot remove `/var/www/squint/all/weekly6': No such file or directory
Generating report to /var/www/squint/all/weekly0 from 20090616 to 20090623
Parentheses missing around "my" list at /usr/local/bin/squint.pl line 404.
Useless use of a variable in void context at /usr/local/bin/squint.pl line 404.
Useless use of a variable in void context at /usr/local/bin/squint.pl line 404.
main::writeusersitereports() called too early to check prototype at /usr/local/bin/squint.pl line 247.
main::writeusersitereports() called too early to check prototype at /usr/local/bin/squint.pl line 341.
Name "main::messagelog" used only once: possible typo at /usr/local/bin/squint.pl line 351.
Name "main::listlimit" used only once: possible typo at /usr/local/bin/squint.pl line 168.
Name "main::peak" used only once: possible typo at /usr/local/bin/squint.pl line 709.
Name "main::nametofilenamebasehref" used only once: possible typo at /usr/local/bin/squint.pl line 568.
Name "main::basedom" used only once: possible typo at /usr/local/bin/squint.pl line 351.
Name "main::basename" used only once: possible typo at /usr/local/bin/squint.pl line 351.

rm: cannot remove `/var/www/squint/all/monthly6': No such file or directory
Generating report to /var/www/squint/all/monthly0 from 20090501 to 20090601
Parentheses missing around "my" list at /usr/local/bin/squint.pl line 404.
Useless use of a variable in void context at /usr/local/bin/squint.pl line 404.
Useless use of a variable in void context at /usr/local/bin/squint.pl line 404.
main::writeusersitereports() called too early to check prototype at /usr/local/bin/squint.pl line 247.
main::writeusersitereports() called too early to check prototype at /usr/local/bin/squint.pl line 341.
Name "main::messagelog" used only once: possible typo at /usr/local/bin/squint.pl line 351.
Name "main::listlimit" used only once: possible typo at /usr/local/bin/squint.pl line 168.
Name "main::peak" used only once: possible typo at /usr/local/bin/squint.pl line 709.
Name "main::nametofilenamebasehref" used only once: possible typo at /usr/local/bin/squint.pl line 568.
Name "main::basedom" used only once: possible typo at /usr/local/bin/squint.pl line 351.
Name "main::basename" used only once: possible typo at /usr/local/bin/squint.pl line 351.

~#

Now there is a bug in crontab format of squint in /etc/crontab to work the squint properly we have to fix that. Open the crontab file and see what exits for squint section.
# vim /etc/crontab

You will see the following section
# squint squid reports
# Weekly, on Mondays
00    01    *    *    Monday    root   /usr/local/bin/squint.cron.sh weekly
# Monthly, on the first day of the month
00    02    1    *    *    root   /usr/local/bin/squint.cron.sh monthly
# Daily at 3am
00    03    *    *    *    root   /usr/local/bin/squint.cron.sh daily

You have to replace the Monday with numaric 1 which also means it is Monday (first working day of a week) but in numaric vlaue. Otherwise crontab daemon will not run properly.

So, Finally the crontab section for squint will be as follows
# squint squid reports
# Weekly, on Mondays
00    01    *    *    1    root   /usr/local/bin/squint.cron.sh weekly
# Monthly, on the first day of the month
00    02    1    *    *    root   /usr/local/bin/squint.cron.sh monthly
# Daily at 3am
00    03    *    *    *    root   /usr/local/bin/squint.cron.sh daily
Save + Exit

You will also see a directory name squint created in /var/www located as /var/www/squint that is your squint log storage directory, this is also the apache documentroot for accessing squint by web browser.

Browse the location http://123.49.42.180/squint by your firefox/ie/opera web-browser and you should see the squid log files.

So, I am done for now for linux as internet gateway, you may use this howto as a guideline and make changes as your requirements, also you may drop your asking to helpdesk@linux-bd.com


...I believe that "There is no shortcut on the way of success"