# See www.andybev.com for full details of this script

#!/bin/bash

IPTABLES=/sbin/iptables

# Enable FTP connection tracking
modprobe nf_conntrack_ftp

# Enable Internet connection sharing
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr

# clear out existing setting
$IPTABLES -P INPUT ACCEPT
$IPTABLES -F INPUT 
$IPTABLES -P OUTPUT ACCEPT
$IPTABLES -F OUTPUT 
$IPTABLES -P FORWARD DROP
$IPTABLES -F FORWARD 
$IPTABLES -t nat -F
$IPTABLES -t mangle -F
$IPTABLES -t filter -F


# Create and flush internet chain
# This is used to authenitcate users who have already signed up
$IPTABLES -N internet -t nat 2>/dev/null
$IPTABLES -F internet -t nat

# Create ipset for storing ip addresses of p2p users
# Set timeout to 60 seconds meaning their address will
# be cleared after 60 seconds of inactivity of p2p
#
# The current IP addresses in the IP Set can be monitored
# with the 'ipset -L' comand from the bash prompt
#
ipset -X p2p
ipset -N p2p iptree --timeout 60

# Accept all local traffic
$IPTABLES -t nat -A PREROUTING -i eth0 --destination 10.0.0.0/16 -j ACCEPT

# Send all traffic via internet chain
# At the prerouting NAT stage this will DNAT them to the local
# webserver for them to signup if they aren't authorised
# Packets for unauthorised users are marked for dropping later
$IPTABLES -t nat -A PREROUTING -j internet

# Drop invalid packets
$IPTABLES -t mangle -A PREROUTING -p tcp -i eth0 -m conntrack --ctstate INVALID -j DROP  # drop invalid connections

# Accept ping and ssh incoming FROM Internet networks
$IPTABLES -t filter -A INPUT -p icmp -i ppp0 --icmp-type 8 -j ACCEPT
$IPTABLES -t filter -A INPUT -p ICMP -i ppp0 --icmp-type 11 -j ACCEPT
$IPTABLES -t filter -A INPUT -i ppp0 -p tcp --dport 22 -j ACCEPT
$IPTABLES -t filter -A INPUT -i ppp0 -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -t filter -A INPUT -i ppp0 -j DROP

# accept NTP time requess
# we allow these for any PC regardless of whether they are logged
# on to the network because the Internet Suite PCs use NTP to set
# their clocks BEFORE they are authorised to use the Internet
$IPTABLES -t filter -A FORWARD -p UDP --dport 123 -j ACCEPT

# Stop DoS attacks on DNS-BL
$IPTABLES -t filter -A FORWARD -i eth0 --destination 216.168.28.50 -j DROP

# Do not allow outgoing internet SMTP connections
# This is essential to stop the many viruses that sit on
# people's computers and attempt to send spam (using bandwidth up)
# This can be changed on a per user basis if required as per the example
$IPTABLES -t filter -A FORWARD -p tcp -i eth0 --dport 25 -m mac --mac-source 00:19:D1:02:1B:02 -j ACCEPT
$IPTABLES -t filter -A FORWARD -p tcp -i eth0 --dport 25 -j DROP


# Mark traffic for shaping later
# The lower the MARK the higher the priority
# Default mark is marked at prerouting to catch both
# internal and forwarded traffic destined for other machines
$IPTABLES -t mangle -A PREROUTING -i ppp0 -j MARK --set-mark 40
# Accept any packets marked 99 here; they will be dropped later
# If they are re-marked then they will be allowed through
$IPTABLES -t mangle -A FORWARD -m mark --mark 99 -j ACCEPT
# http / https
$IPTABLES -t mangle -A FORWARD -p tcp --sport 80 -i ppp0 -j MARK --set-mark 30
$IPTABLES -t mangle -A FORWARD -p tcp --dport 80 -o ppp0 -j MARK --set-mark 30
$IPTABLES -t mangle -A FORWARD -p tcp --sport 443 -i ppp0 -j MARK --set-mark 30
$IPTABLES -t mangle -A FORWARD -p tcp --dport 443 -i eth0 -j MARK --set-mark 30
# SSH
$IPTABLES -t mangle -A FORWARD -p tcp --sport 22 -i ppp0 -j MARK --set-mark 10
$IPTABLES -t mangle -A FORWARD -p tcp --dport 22 -o ppp0 -j MARK --set-mark 10
# local traffic
$IPTABLES -t mangle -A POSTROUTING --source 10.0.0.1 -j MARK --set-mark 1
$IPTABLES -t mangle -A POSTROUTING --destination 10.0.0.1 -j MARK --set-mark 1
# http via squid
$IPTABLES -t mangle -A POSTROUTING -p tcp --sport 3128 --source 10.0.0.1 -j MARK --set-mark 30
# DNS requests
$IPTABLES -t mangle -A OUTPUT -m udp -p udp --dport 53 -j MARK --set-mark 10
$IPTABLES -t mangle -A OUTPUT -m tcp -p tcp --dport 53 -j MARK --set-mark 10
$IPTABLES -t mangle -A INPUT -m udp -p udp --sport 53 -j MARK --set-mark 10
$IPTABLES -t mangle -A INPUT -m tcp -p tcp --sport 53 -j MARK --set-mark 10
# mark large downloads from squid
$IPTABLES -t mangle -A POSTROUTING -p tcp --sport 3128 --source 10.0.0.1 -m connbytes --connbytes 504857: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 40
# IMAP
$IPTABLES -t mangle -A FORWARD -p tcp --sport 993 -i ppp0 -j MARK --set-mark 30  # imap
$IPTABLES -t mangle -A FORWARD -p tcp --dport 993 -o ppp0 -j MARK --set-mark 30  # imap
# Mark large downloads (> 500kb)
$IPTABLES -t mangle -A FORWARD -m connbytes --connbytes 504857: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 40
# To speed up downloads while an upload is going on, put short ACK
# packets in the interactive class:
$IPTABLES -t mangle -A FORWARD -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK ACK -m length --length :64 -j MARK --set-mark 10

# The next few lines pick out P2P packets
# These are characterised by lots of connections to high port numbers
# First look for the packets and log to IPSET p2p
# Detects traffic from users using >8 ports above 1024
# and adds the source address to the P2P list.
$IPTABLES -t mangle -A FORWARD -o ppp0 -p tcp --dport 1024: \
	-m connlimit --connlimit-above 8 -j SET --add-set p2p src 
# Detects traffic from users using >4 UDP ports above 1024
# and adds the source address to the P2P list.
$IPTABLES -t mangle -A FORWARD -o ppp0 -p udp --dport 1024: \
	-m connlimit --connlimit-above 4 -j SET --add-set p2p src 
# Detects traffic to users using >8 ports above 1024
# and adds the dst address (ie the user) to the P2P list.
$IPTABLES -t mangle -A FORWARD -i ppp0 -p tcp --sport 1024: \
	-m connlimit --connlimit-above 8 -j SET --add-set p2p dst
# Detects traffic to users using >4 UDP ports above 1024
# and adds the dst address (ie the user) to the P2P list.
$IPTABLES -t mangle -A FORWARD -i ppp0 -p udp --sport 1024: \
	-m connlimit --connlimit-above 4 -j SET --add-set p2p dst
# Once a user is in the p2p IPSET, these rules mark their packets
# Any packets above 1024 are marked as the lowest priority
$IPTABLES -t mangle -A FORWARD -o ppp0 -p tcp --dport 1024: \
	-m set --set p2p src -j MARK --set-mark 60
$IPTABLES -t mangle -A FORWARD -i ppp0 -p tcp --sport 1024: \
	-m set --set p2p dst -j MARK --set-mark 60
$IPTABLES -t mangle -A FORWARD -o ppp0 -p udp --dport 1024: \
	-m set --set p2p src -j MARK --set-mark 60
$IPTABLES -t mangle -A FORWARD -i ppp0 -p udp --sport 1024: \
	-m set --set p2p dst -j MARK --set-mark 60

# Now that we've got to the forward filter, drop all packets
# marked 99 - these are unknown users. We can't drop them earlier
# as there's no filter table
$IPTABLES -t filter -A FORWARD -m mark --mark 99 -j DROP
# Do the same for the INPUT chain so that they also can't get to squid
# but allow them to the webserver to signup
$IPTABLES -t filter -A INPUT -p tcp --dport 80 -j ACCEPT
$IPTABLES -t filter -A INPUT -m mark --mark 99 -j DROP

###### INTERNET CHAIN ##########
# Allow authorised hosts in, redirect all others to login webserver
# Add known users to the NAT table to stop their dest being rewritten
# Ignore MAC address with a * - these users are blocked
awk 'BEGIN { FS="\t"; } { if ($5 !~ /\*/) { system("'$IPTABLES' -t nat -A internet -m mac --mac-source "$5" -j RETURN"); } }' /var/lib/users
# MAC address not found. Mark the packet 99
$IPTABLES -t nat -A internet -j MARK --set-mark 99
# Redirects web requests from Unauthorised users to logon Web Page
$IPTABLES -t nat -A internet -m mark --mark 99 -p tcp --dport 80 -j DNAT --to-destination 10.0.0.1
################################

# Force all traffic via web proxy to speed up some traffic
$IPTABLES -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3128

# Bocks outgoing traffic from local host on unused ports.
# Allow known ports out
$IPTABLES -t mangle -A OUTPUT -p tcp --dport 80 -o ppp0 -j ACCEPT  # Accept web proxy traffic
$IPTABLES -t mangle -A OUTPUT -p tcp --dport 25 -o ppp0 -j ACCEPT # Accept outgoing mail 
$IPTABLES -t mangle -A OUTPUT -p tcp --dport 21 -o ppp0 -j ACCEPT # Accept outgoing ftp
$IPTABLES -t mangle -A OUTPUT -p tcp --dport 22 -o ppp0 -j ACCEPT # Accept outgoing ssh
$IPTABLES -t mangle -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -t mangle -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -t mangle -A OUTPUT -p icmp -o ppp0 --icmp-type 8 -j ACCEPT #Accept ping commamnds
$IPTABLES -t mangle -A OUTPUT -p ICMP -o ppp0 --icmp-type 11 -j ACCEPT #Accept ping commands
$IPTABLES -t mangle -A OUTPUT -m udp -p udp --dport 53 -j ACCEPT   # DNS
$IPTABLES -t mangle -A OUTPUT -o ppp0 -j DROP # Drops all other outputs from the local machine


# Enable Internet connection sharing
$IPTABLES -A FORWARD -i ppp0 -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A FORWARD -i eth0 -o ppp0 -j ACCEPT
$IPTABLES -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

