#!/bin/sh

# This is the location of the iptables command
IPTABLES="/sbin/iptables"
TC="/sbin/tc"

EXTIF="eth0"
INTIF="eth1"


case "$1" in
   stop)
      echo "Shutting down firewall..."
      $IPTABLES -F
      $IPTABLES -F -t mangle
      $IPTABLES -F -t nat
      $IPTABLES -X
      $IPTABLES -X -t mangle
      $IPTABLES -X -t nat

      $IPTABLES -P INPUT ACCEPT
      $IPTABLES -P OUTPUT ACCEPT
      $IPTABLES -P FORWARD ACCEPT

     $TC qdisc del dev $INTIF root handle 10:0 cbq bandwidth 10Mbit avpkt 1000 

      echo "...done"
      ;;
   status)
      echo $"Table: filter"
      iptables --list
      echo $"Table: nat"
      iptables -t nat --list
      echo $"Table: mangle"
      iptables -t mangle --list
      ;;
   qos)
      echo "Starting the qos ..."

      add_class() {
       # $1=parent class $2=classid $3=hiband $4=lowband $5=handle $6=style
       $TC class add dev $INTIF  parent $1 classid $2 cbq bandwidth 10Mbit rate $3 allot 1514 weight $4 prio 5  maxburst 20 avpkt 1000 $6
       $TC qdisc add dev $INTIF parent $2 sfq quantum 1514b perturb 15
       $TC filter add dev $INTIF protocol ip prio 3 handle $5 fw classid $2
      }

       $TC qdisc add dev $INTIF root handle 10: cbq bandwidth 10Mbit avpkt 1000
       $TC class add dev $INTIF parent 10:0 classid 10:1 cbq bandwidth 10Mbit rate 64kbit allot 1514 weight 6.4kbit prio 8 maxburst 20 avpkt 1000 bounded

      #first type of traffic ICMP, TCP-SYN, DNS will be marked '1' by the firewall code
      #we will give it a bounded bandwidth of 5% of our total incoming bandwidth (64*0.05=3.2)
       add_class 10:1 10:100 3.2kbit 0.32kbit 1 bounded
 
      #second type of traffic SMTP,POP3 will be marked '2' by the firewalling code
      #we will give it a bounded bandwidth of 5% of our total incoming bandwidth (64*0.05=3.2)
      add_class 10:1 10:300 3.2kbit 0.32kbit 2 

      #third type of traffic nntp,ssh,ftp will be marked '3' by the firewalling code
      #we will give it a bounded bandwidth of 20% of our total incoming bandwidth (64*0.20=12.8)
      add_class 10:1 10:200 12.8kbit 1.28kbit 3 

      #last type of traffic is interactive traffic. It will be marked '4' by the firewalling code
      #we will give it a bounded bandwidth of 70% of our total incoming bandwidth (64*0.70=44.8)
      add_class 10:1 10:400 44.8kbit 4.48kbit 4 
      ;;

    restart|reload)
      sh $0 stop
      sh $0 start
      sh $0 qos
      ;;

   start)
    echo "Starting Firewall..."
   
    echo ""


##--------------------------Begin Firewall---------------------------------##


#----Flood Variables-----#
# Overall Limit for TCP-SYN-Flood detection
TCPSYNLIMIT="1/s"
# Burst Limit for TCP-SYN-Flood detection
TCPSYNLIMITBURST="5"

# Overall Limit for Ping-Flood-Detection
PINGLIMIT="1/s"
# Burst Limit for Ping-Flood-Detection
PINGLIMITBURST="5"

#----Clear/Reset all chains-----#

#Clear all IPTABLES-chains
#Flush everything, start from scratch
$IPTABLES -F
$IPTABLES -F -t mangle
$IPTABLES -F -t nat
$IPTABLES -X
$IPTABLES -X -t mangle
$IPTABLES -X -t nat

#Set default policies to DROP
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP


#Reduce DoS'ing ability by reducing timeouts
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
echo 2400 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 0 > /proc/sys/net/ipv4/tcp_window_scaling
echo 0 > /proc/sys/net/ipv4/tcp_sack

# Allow the kernel to forward packets and prevent ipspoof
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 1 > /proc/sys/net/ipv4/ip_dynaddr
for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 1 > $f; done

# Create chains to protect from pingofdeath,Syn-flood,Furtive-port
$IPTABLES -N mylimit
$IPTABLES -A mylimit -m limit --limit 1/s --limit-burst 5 -j ACCEPT
$IPTABLES -A mylimit -j DROP

# set up a new chain to accept the good connections
# block incoming connectios from eth0  on ports other than desired

# Create user chain
echo "Creating user-chains"
$IPTABLES -N myaccept
# Ping flood / Syn-flood protection / Furtive port scanner
$IPTABLES -A myaccept -p icmp --icmp-type echo-request -j mylimit
$IPTABLES -A myaccept -p tcp --syn -j mylimit
$IPTABLES -A myaccept -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j mylimit
#$IPTABLES -A myaccept -p tcp --tcp-flags SYN SYN -j mylimit

# established and related connetctions are acceptable
$IPTABLES -A myaccept -m state --state ESTABLISHED,RELATED -j ACCEPT
# new connections not from the outside are acceptable
$IPTABLES -A myaccept -i ! eth0 -m state --state NEW -j ACCEPT

# icmp connections that passed the pingflood test are accepted
#$IPTABLES -A myaccept -i eth0 -p icmp -m state --state NEW -j ACCEPT

# the good ports www and ssh are accepted
#$IPTABLES -A myaccept -i eth0 -p tcp -m multiport --dport www,ssh -m state --state NEW -j ACCEPT

# I'm not sure if this is a good Idea, but I like the idea of rejecting evan if it gives the attacker the info
# there is a host there.  Personal preference I guess.  I'd like to have a reject with icmp-port-nananana-booo-booo.
#/sbin/iptables -A myaccept -i eth0 -m state --state NEW -j REJECT --reject-with icmp-port-unreachable

# A problem was occuring where certain sites were unaccessible, this next line fixes it
$IPTABLES -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
$IPTABLES -A OUTPUT -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

##### RATE LIMITING GOES HERE ###########
# Append User chains
$IPTABLES -A INPUT -s 128.198.60.195 -p tcp -j myaccept
$IPTABLES -A INPUT -s 128.198.60.195 -p icmp -j myaccept
$IPTABLES -A INPUT -s 128.198.60.195 -p udp -j myaccept


######## END OF RATE LIMITING ############

########### QOS GOES HERE #################

# allow simple dns traffic
$IPTABLES -A INPUT -p udp -s 0/0 --dport  53 -j ACCEPT 
$IPTABLES -A OUTPUT -p udp -d 0/0 --dport 53 -j ACCEPT

# allow icmp traffic mark it with value 1
$IPTABLES -A INPUT -p icmp -i $EXTIF -j ACCEPT -m mark --mark 1
$IPTABLES -A INPUT -p tcp --syn -i $EXTIF -j ACCEPT -m mark --mark 1 

#mark incoming mail traffic with mark value 2
$IPTABLES -A INPUT -p tcp ! --syn -i $EXTIF -s 0/0 --dport smtp -d 0/0 -j ACCEPT -m mark --mark 2
$IPTABLES -A INPUT -p tcp ! --syn -i $EXTIF -s 0/0 --dport pop3 -d 0/0 -j ACCEPT -m mark --mark 2

#mark incoming  and News traffic with mark value 3
$IPTABLES -A INPUT -p tcp ! --syn -i $EXTIF -s 0/0 --dport 21 -d 0/0 -j ACCEPT -m mark --mark 3
$IPTABLES -A INPUT -p tcp ! --syn -i $EXTIF -s 0/0 --dport 22 -d 0/0 -j ACCEPT -m mark --mark 3
$IPTABLES -A INPUT -p tcp ! --syn -i $EXTIF -s 0/0 --dport 23 -d 0/0 -j ACCEPT -m mark --mark 3
$IPTABLES -A INPUT -p tcp ! --syn -i $EXTIF -s 0/0 --dport nntp -d 0/0 -j ACCEPT -m mark --mark 3

#mark incoming www and Real Server traffic with mark value 4
$IPTABLES -A INPUT -p tcp -i $EXTIF -s 0/0 --dport 80 -d 0/0 -j ACCEPT -m mark --mark 4
$IPTABLES -A INPUT -p tcp -i $EXTIF -s 0/0 --dport 443 -d 0/0 -j ACCEPT -m mark --mark 4
$IPTABLES -A INPUT -p tcp -i $EXTIF -s 0/0 --dport 7070 -d 0/0 -j ACCEPT -m mark --mark 4
$IPTABLES -A INPUT -p tcp -i $EXTIF -s 0/0 --dport 554 -d 0/0 -j ACCEPT -m mark --mark 4
$IPTABLES -A INPUT -p tcp -i $EXTIF -s 0/0 --dport 8080 -d 0/0 -j ACCEPT -m mark --mark 4
$IPTABLES -A INPUT -p tcp -i $EXTIF -s 0/0 --dport 2687 -d 0/0 -j ACCEPT -m mark --mark 4

#$IPTABLES -A OUTPUT -i $EXTIF -j ACCEPT
#$IPTABLES -A INPUT  -i $EXTIF -j ACCEPT

# DNAT
# translate incoming ssh and www traffic to my internal hosts
#iptables -t nat -A PREROUTING -p tcp --dport 22 -i ppp0 -j DNAT --to 192.168.0.3:22
#iptables -t nat -A PREROUTING -p tcp --dport 80 -i ppp0 -j DNAT --to 192.168.0.1:80

$IPTABLES -A INPUT -j ACCEPT
$IPTABLES -A FORWARD -j ACCEPT
$IPTABLES -A OUTPUT -j ACCEPT

#------End Ruleset------#

echo "...done"
echo ""

echo "--> IPTABLES firewall loaded/activated <--"


##--------------------------------End Firewall---------------------------------##

  sh $0  qos
   ;;
   *)
      echo "Usage: firewall (start|stop|restart|status) EXTIF INTIF"
      exit 1
esac

exit 0

