#!/bin/sh
# script written by Gargi 2009 http://www.gargi.org

### BEGIN INIT INFO
# Provides:          firewall
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       Enable service provided by daemon.
### END INIT INFO

#needed modules
#modprobe ip_conntrack_ftp

BLACKLIST=/usr/local/etc/blacklist.txt

#trigger for your ports
#IN_ALLOWED_TCP="21 22 25 53 80 443 465 993 995 2812 10024 10025 64738"
#IN_ALLOWED_TCP="22 25 53 80 443 587 993 1024:65535"
IN_ALLOWED_TCP="22 25 53 80 443 587 993 27960"
OUT_ALLOWED_TCP="22 25 53 80 443 587 873 993 2703 1024:65535"
IN_ALLOWED_UDP="53 27960 64738"
OUT_ALLOWED_UDP="53 11335"
IN_ALLOWED_ICMP=" "
OUT_ALLOWED_IMCP=" "

case "$1" in
  start)

  # Stopping IP trap
  /etc/init.d/fail2ban stop
  echo "Stopping fail2ban IP trap ..."

  # Clear iptables
  iptables -F

  #Defaults
  iptables -P INPUT DROP
  iptables -P OUTPUT DROP
  iptables -P FORWARD DROP

  # loopback communication
  iptables -A INPUT -i lo -j ACCEPT
  iptables -A OUTPUT -o lo -j ACCEPT

  # persist on connections
  iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
  iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

  # allow outgoing icmp
  iptables -A INPUT -p icmp --icmp-type 8 -d 0/0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
  iptables -A OUTPUT -p icmp --icmp-type 0 -s 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT

  ### 1: Drop invalid packets ###
  iptables -t mangle -A PREROUTING -m conntrack --ctstate INVALID -j DROP

  ### 2: Drop TCP packets that are new and are not SYN ###
  iptables -t mangle -A PREROUTING -p tcp ! --syn -m conntrack --ctstate NEW -j DROP

  ### 3: Drop SYN packets with suspicious MSS value ###
  iptables -t mangle -A PREROUTING -p tcp -m conntrack --ctstate NEW -m tcpmss ! --mss 536:65535 -j DROP

  ### 4: Block packets with bogus TCP flags ###
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags FIN,ACK FIN -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,URG URG -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,FIN FIN -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags ACK,PSH PSH -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL ALL -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL NONE -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL FIN,PSH,URG -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,FIN,PSH,URG -j DROP
  iptables -t mangle -A PREROUTING -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP

  ### SSH brute-force protection ###
  iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --set
  iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -m recent --update --seconds 60 --hitcount 10 -j DROP

  ### Protection against port scanning ###
  iptables -N port-scanning
  iptables -A port-scanning -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s --limit-burst 2 -j RETURN
  iptables -A port-scanning -j DROP




  # set connection limits
  iptables -I INPUT 3 -p tcp --syn --dport 22 -m connlimit --connlimit-above 3 -j REJECT
  iptables -I INPUT 4 -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j DROP
  iptables -I INPUT 5 -p tcp --syn --dport 443 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j DROP
  #iptables -I INPUT 5 -p tcp --syn --dport 8448 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j DROP
  #iptables -A INPUT -p tcp --dport 80 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
  #iptables -A INPUT -p tcp --dport 443 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT

  # block outside to reach node.js exposed port
  iptables -I INPUT 6 -p tcp -s localhost --dport 3000 -j ACCEPT
  iptables -I INPUT 7 -p tcp --dport 3000 -j DROP

  # limit connections
  #iptables -I INPUT 6 -p tcp --syn --dport 8448 -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset
  iptables -I OUTPUT 4 -p tcp --syn --dport 443 -m connlimit --connlimit-above 40 -j REJECT --reject-with tcp-reset
  #iptables -I OUTPUT 5 -p tcp --syn --dport 8448 -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset

  # SYN Flood stuff
  #iptables -A INPUT -p tcp -m state --state NEW -m limit --limit 2/second --limit-burst 2 -j ACCEPT
  #iptables -A INPUT –p tcp –m state --state NEW –j DROP

  # Ban blacklisted IPs
  for x in `grep -v ^# $BLACKLIST | awk '{print $1}'`; do
    echo "Blocking $x..."
    iptables -I INPUT 3 -t filter -s $x -j LOGGING
  done

  # TCP rules in
  for port in $IN_ALLOWED_TCP; do
    echo "Accepting TCP port $port"
    iptables -A INPUT -t filter -p tcp --dport $port -j ACCEPT
  done

  # TCP rules out
  for port in $OUT_ALLOWED_TCP; do
    echo "Allowing sending over TCP port $port"
    iptables -A OUTPUT -t filter -p tcp --dport $port -j ACCEPT
  done

  # UDP rules in
  for port in $IN_ALLOWED_UDP; do
    echo "Accepting UDP  port $port"
    iptables -A INPUT -t filter -p udp --dport $port -j ACCEPT
  done

  # UDP  rules out
  for port in $OUT_ALLOWED_UDP; do
    echo "Allowing sending over UDP port $port"
    iptables -A OUTPUT -t filter -p udp --dport $port -j ACCEPT
  done

  # Dropping startup requests
  iptables -A INPUT -t filter -p tcp --syn -j DROP

  # enable LOGGING
  iptables -N LOGGING
  iptables -A INPUT -j LOGGING
  iptables -A OUTPUT -j LOGGING
  iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "iptables: " --log-level 7
  iptables -A LOGGING -j DROP

  # Restarting IP trap
  /etc/init.d/fail2ban start
  echo "Fire up IP trap again ..."
  ;;

stop)
  /etc/init.d/fail2ban stop
  iptables -F
  iptables -P INPUT ACCEPT
  iptables -P OUTPUT ACCEPT
  echo "Warning! Firewall is stopped, server is unprotected now!"
  ;;

restart)
  $0 stop
  sleep 1
  $0 start
  ;;

*)
  echo "Usage $0 {start|stop|restart}"
  ;;

esac
