Pejman Moghadam / Scripts

Firewall script 2009 - iptables recent module - flood control - ssh port-knocking - broute force control

Public domain


#!/bin/bash
####################################################################################################
# Configuration ####################################################################################
####################################################################################################
INTIF=eth1
EXTIF=$(route -n | egrep '^0.0.0.0' | sed -e 's,.* ,,')
ICMPHIT="10"
TCPHIT="50"
UDPHIT="70"
DEBUG="YES"

# Totaly Close IPs
CLOSE="$CLOSE 83.170.42.34"
CLOSE="$CLOSE 83.170.42.35"

# Totaly Close Ports
CLOSE_DPORT="$CLOSE_DPORT 135 139 445 "
CLOSE_SPORT="$CLOSE_SPORT 135 139 445 "

# Totaly Open IPs
OPEN="$OPEN 83.170.42.50"
OPEN="$OPEN 83.170.42.51"

# Trusted External IPs
TRUST="$TRUST 178.34.32.78"
TRUST="$TRUST 153.27.71.39"

# Local Servers
LANSERVER="$LANSERVER 83.170.42.9"
LANSERVER="$LANSERVER 83.170.42.10

# Local Networks
LOCALNET="$LOCALNET 83.170.42.0/24" 
LOCALNET="$LOCALNET 80.85.71.0/24" 

# Static Routes
route add -net 80.85.14.16/28     gw 80.85.14.11
route add -net 80.85.14.32/27     gw 80.85.14.11

####################################################################################################
# NAT ##############################################################################################
####################################################################################################
# NAT table flush
iptables -F -t nat
iptables -t nat -A POSTROUTING -o eth0 -s 10.20.231.198 -j SNAT --to 83.170.42.9 

####################################################################################################
# Functions ########################################################################################
####################################################################################################

load_modules() {
  /sbin/rmmod ipt_recent > /dev/null 2>&1
  /sbin/modprobe ipt_recent ip_list_tot=2048 ip_pkt_list_tot=255 ip_list_hash_size=0
  NAT_MODULES=$(
                  find /lib/modules/$(uname -r)/kernel -name '*nat*' |\
                  grep 'netfilter' |\
                  sed -e 's,.*/,,' -e 's,\..*,,'
               )
  CON_MODULES=$(
                  find /lib/modules/$(uname -r)/kernel -name '*conntrack*' |\
                  grep 'netfilter' |\
                  sed -e 's,.*/,,' -e 's,\..*,,'
               )
  for MODULE in $NAT_MODULES $CON_MODULES; do
    /sbin/modprobe $MODULE > /dev/null 2>&1
  done
}

find_ext_ip() {
  IFCS=$(ifconfig | grep $EXTIF | awk '{print $1}')
  for IF in $IFCS; do
    IP=$(ifconfig $IF | grep "inet addr" | awk '{print $2}' | sed -e 's,.*:,,')
    LOCALNET="$LOCALNET $IP"
  done
}

start() {
  echo 'Starting Firewall...'
  load_modules
  iptables -F
  iptables -X
  iptables -Z
  iptables -P INPUT DROP
  iptables -P OUTPUT DROP
  iptables -P FORWARD DROP

  # Totally close
  for NET in $CLOSE; do
    iptables -A FORWARD -i $INTIF -s $NET -j DROP
    iptables -A FORWARD -i $EXTIF -d $NET -j DROP
  done

  # Totally close destination ports
  for PORT in $CLOSE_DPORT; do
    iptables -A FORWARD -i $INTIF -p tcp --dport $PORT -j DROP
    iptables -A FORWARD -i $INTIF -p udp --dport $PORT -j DROP
    iptables -A FORWARD -i $EXTIF -p tcp --dport $PORT -j DROP
    iptables -A FORWARD -i $EXTIF -p udp --dport $PORT -j DROP
  done

  # Totally close source ports
  for PORT in $CLOSE_SPORT; do
    iptables -A FORWARD -i $INTIF -p tcp --sport $PORT -j DROP
    iptables -A FORWARD -i $INTIF -p udp --sport $PORT -j DROP
    iptables -A FORWARD -i $EXTIF -p tcp --sport $PORT -j DROP
    iptables -A FORWARD -i $EXTIF -p udp --sport $PORT -j DROP
  done

  # Totally open
  for NET in $OPEN; do
    iptables -A FORWARD -s $NET -j ACCEPT
    iptables -A FORWARD -d $NET -j ACCEPT
  done

  # Trusted networks
  for NET in $TRUST; do
    iptables -A INPUT  -i $EXTIF -s $NET -j ACCEPT
    iptables -A OUTPUT -o $EXTIF -d $NET -j ACCEPT
    iptables -A FORWARD -i $EXTIF -s $NET -j ACCEPT
    iptables -A FORWARD -o $EXTIF -d $NET -j ACCEPT
  done

  # Local Servers
  for SERVER in $LANSERVER; do
    iptables -A FORWARD -o $EXTIF -s $SERVER -m state --state NEW,ESTABLISHED -j ACCEPT
    iptables -A FORWARD -i $EXTIF -d $SERVER -m state --state ESTABLISHED,RELATED -j ACCEPT
    iptables -A FORWARD -i $INTIF -d $SERVER -j ACCEPT
    iptables -A FORWARD -i $INTIF -s $SERVER -j ACCEPT
  done

  # Source Check
  iptables -N SRC-CHK
  for NET in $LOCALNET; do
    iptables -A SRC-CHK -s $NET -j RETURN
  done
  if [ "$DEBUG" == "YES" ]; then 
    iptables -A SRC-CHK -j LOG --log-prefix "SRC:CHK:"
  fi
  iptables -A SRC-CHK -j DROP

  # Destination Check
  iptables -N DST-CHK
  for NET in $LOCALNET; do
    iptables -A DST-CHK -d $NET -j RETURN
  done
  if [ "$DEBUG" == "YES" ]; then
    iptables -A DST-CHK -j LOG --log-prefix "DST:CHK:"
  fi
  iptables -A DST-CHK -j DROP

  ################
  # INPUT/OUTPUT #
  ################

  # Loopback access
  iptables -A INPUT  -i lo -j ACCEPT
  iptables -A OUTPUT -o lo -j ACCEPT

  # ICMP access to firewall from internet
  if [ "$DEBUG" == "YES" ]; then
    iptables -A INPUT -i $EXTIF -p icmp --icmp-type echo-request \
      -m recent --rcheck --rttl --hitcount 2 --seconds 1 --name ICMP-RECENT-OUTSIDE -j LOG --log-prefix "ICMP:ATK:"
  fi
  iptables -A INPUT -i $EXTIF -p icmp --icmp-type echo-request \
    -m recent --rcheck --rttl --hitcount 2 --seconds 1 --name ICMP-RECENT-OUTSIDE -j DROP
  iptables -A INPUT -i $EXTIF -p icmp --icmp-type echo-request \
    -m recent --set --name ICMP-RECENT-OUTSIDE -j ACCEPT

  # SSH access to firewall from internet with port knocking
  # SSH brute-force prevention from both sides
  iptables -N KNOCK1
  iptables -N KNOCK2
  iptables -N KNOCK3
  iptables -N BRUTE

  iptables -A KNOCK1 -m recent --set --name SEENFIRST
  iptables -A KNOCK1 -m recent --remove --name KNOCKED
  iptables -A KNOCK1 -j DROP

  iptables -A KNOCK2 -m recent --rcheck --name SEENFIRST --seconds 5 -j KNOCK3
  iptables -A KNOCK2 -m recent --remove --name SEENFIRST
  iptables -A KNOCK2 -j DROP

  iptables -A KNOCK3 -m recent --set --name KNOCKED
  iptables -A KNOCK3 -j DROP

  if [ "$DEBUG" == "YES" ]; then
    iptables -A BRUTE -p tcp --dport 22 -m state --state NEW \
      -m recent --rcheck --seconds 60 --hitcount 2 --rttl --name SSH-OUTSIDE -j LOG --log-prefix "SSH:OUTSIDE:"
  fi
  iptables -A BRUTE -p tcp --dport 22 -m state --state NEW \
    -m recent --rcheck --seconds 60 --hitcount 2 --rttl --name SSH-OUTSIDE -j DROP
  iptables -A BRUTE -p tcp --dport 22 -m state --state NEW \
    -m recent --set --name SSH-OUTSIDE -j ACCEPT

  iptables -A INPUT -i $EXTIF -p tcp --dport 7006 -j KNOCK1
  iptables -A INPUT -i $EXTIF -p tcp --dport 5003 -j KNOCK2
  iptables -A INPUT -i $EXTIF -p tcp --dport 22 -m state --state NEW -m recent --seconds 10 --rcheck --name KNOCKED -j BRUTE
  iptables -A INPUT -i $EXTIF -p tcp --dport 22 -m state --state NEW -j DROP

  # SSH access to firewall for clients with brute-force prevention
  iptables -A INPUT -i $INTIF -p tcp --dport 22 -m state --state NEW -j BRUTE

  # Clients Access To Firewall
  iptables -A INPUT  -i $INTIF -m state --state NEW,ESTABLISHED -j ACCEPT
  iptables -A OUTPUT -o $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT

  # Firewall Access To Internet
  iptables -A OUTPUT -o $EXTIF -m state --state NEW,ESTABLISHED -j ACCEPT
  iptables -A INPUT  -i $EXTIF -m state --state ESTABLISHED,RELATED -j ACCEPT

  # Firewall Access To Clients
  iptables -A OUTPUT -o $INTIF -m state --state NEW,ESTABLISHED -j ACCEPT
  iptables -A INPUT  -i $INTIF -m state --state ESTABLISHED,RELATED -j ACCEPT

  ###########
  # FORWARD #
  ###########

  # Local access
  iptables -A FORWARD -i $EXTIF -j DST-CHK
  # packthayey ke betarafe cache server e local route mishavand
  # destination e internet darand na local
  # va pasokh haye in packet ha ba source e internet rooye lan
  # route mishavand
  #iptables -A FORWARD -o $INTIF -j DST-CHK
  #iptables -A FORWARD -i $INTIF -j SRC-CHK
  iptables -A FORWARD -i $INTIF -o $INTIF -j ACCEPT

  # ICMP flood control
  if [ "$DEBUG" == "YES" ]; then
    iptables -A FORWARD -i $INTIF -p icmp --icmp-type echo-request \
      -m recent --rcheck --rttl --hitcount $ICMPHIT --seconds 1 --name ICMP-RECENT-FORWARD -j LOG --log-prefix "ICMP:FLOOD:"
  fi
  iptables -A FORWARD -i $INTIF -p icmp --icmp-type echo-request \
    -m recent --rcheck --rttl --hitcount $ICMPHIT --seconds 1 --name ICMP-RECENT-FORWARD -j DROP
  iptables -A FORWARD -i $INTIF -p icmp --icmp-type echo-request \
    -m recent --set --name ICMP-RECENT-FORWARD -j ACCEPT

  # TCP flood control
  if [ "$DEBUG" == "YES" ]; then
    iptables -A FORWARD -i $INTIF -p tcp -m state --state NEW \
      -m recent --rcheck --rttl --hitcount $TCPHIT --seconds 1 --name TCP-RECENT-FORWARD -j LOG --log-prefix "TCP:FLOOD:"
  fi
  iptables -A FORWARD -i $INTIF -p tcp -m state --state NEW \
    -m recent --rcheck --rttl --hitcount $TCPHIT --seconds 1 --name TCP-RECENT-FORWARD -j DROP
  iptables -A FORWARD -i $INTIF -p tcp -m state --state NEW \
    -m recent --set --name TCP-RECENT-FORWARD -j ACCEPT

  # UDP flood control
  if [ "$DEBUG" == "YES" ]; then
    iptables -A FORWARD -i $INTIF -p udp -m state --state NEW \
      -m recent --rcheck --rttl --hitcount $UDPHIT --seconds 1 --name UDP-RECENT-FORWARD -j LOG --log-prefix "UDP:FLOOD:"
  fi
  iptables -A FORWARD -i $INTIF -p udp -m state --state NEW \
    -m recent --rcheck --rttl --hitcount $UDPHIT --seconds 1 --name UDP-RECENT-FORWARD -j DROP
  iptables -A FORWARD -i $INTIF -p udp -m state --state NEW \
    -m recent --set --name UDP-RECENT-FORWARD -j ACCEPT

  # Clients access to internet
  iptables -A FORWARD -i $INTIF -m state --state NEW,ESTABLISHED -j ACCEPT
  iptables -A FORWARD -i $EXTIF -m state --state ESTABLISHED,RELATED -j ACCEPT

  # Chiz
  iptables -A FORWARD -p gre -j ACCEPT

}

stop() {
  echo 'Stoping Firewall...'
  iptables -F
  iptables -X
  iptables -Z
  iptables -P INPUT ACCEPT
  iptables -P OUTPUT ACCEPT
  iptables -P FORWARD ACCEPT
  rmmod ipt_recent > /dev/null 2>&1
}

####################################################################################################
# Main #############################################################################################
####################################################################################################

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart | reload)
        stop
        start
        ;;
  *)
        echo "Usage: $0 {start|stop|restart}"
esac

BY: Pejman Moghadam
TAG: firewall, iptables, bash-script, bash, port-knocking, recent
DATE: 2009-06-07 20:24:27


Pejman Moghadam / Scripts [ TXT ]